From aded2e51a7a2113dae6431c858df1d95fb312851 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 13 Feb 2008 19:34:08 +0300 Subject: [PATCH] modeswitching Signed-off-by: Dmitry Baryshkov --- arch/arm/mach-pxa/tosa.c | 33 +++++++++++++++++++++++++++++++- drivers/mfd/tc6393xb.c | 2 +- drivers/video/backlight/tosa_bl.c | 38 +++++++++++++++++++++++++++++++++--- drivers/video/tmiofb.c | 8 +++--- include/asm-arm/arch-pxa/tosa.h | 2 + include/linux/mfd/tc6393xb.h | 2 +- include/linux/mfd/tmio.h | 2 +- 7 files changed, 75 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 94c9915..6631de2 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -455,9 +455,40 @@ static struct fb_videomode tosa_tc6393xb_lcd_mode[] = { } }; +static DEFINE_SPINLOCK(tosa_lcd_mode_lock); + +static const struct fb_videomode *tosa_lcd_mode = &tosa_tc6393xb_lcd_mode[0]; + +static int tosa_lcd_set_mode(struct platform_device *fb_dev, + const struct fb_videomode *mode) +{ + int rc; + unsigned long flags; + + spin_lock_irqsave(&tosa_lcd_mode_lock, flags); + rc = tc6393xb_lcd_mode(fb_dev, mode); + if (!rc) + tosa_lcd_mode = mode; + spin_unlock_irqrestore(&tosa_lcd_mode_lock, flags); + + return rc; +} + +const struct fb_videomode *tosa_lcd_get_mode(void) +{ + unsigned long flags; + const struct fb_videomode *mode; + + spin_lock_irqsave(&tosa_lcd_mode_lock, flags); + mode = tosa_lcd_mode; + spin_unlock_irqrestore(&tosa_lcd_mode_lock, flags); + + return mode; +} + static struct tmio_fb_data tosa_tc6393xb_fb_config = { .lcd_set_power = tc6393xb_lcd_set_power, - .lcd_mode = tc6393xb_lcd_mode, + .lcd_mode = tosa_lcd_set_mode, .num_modes = ARRAY_SIZE(tosa_tc6393xb_lcd_mode), .modes = &tosa_tc6393xb_lcd_mode[0], }; diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index 9001687..21190f3 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c @@ -196,7 +196,7 @@ int tc6393xb_lcd_set_power(struct platform_device *fb, bool on) EXPORT_SYMBOL(tc6393xb_lcd_set_power); int tc6393xb_lcd_mode(struct platform_device *fb_dev, - struct fb_videomode *mode) { + const struct fb_videomode *mode) { struct tc6393xb *tc6393xb = platform_get_drvdata(to_platform_device(fb_dev->dev.parent)); struct tc6393xb_scr __iomem *scr = tc6393xb->scr; diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c index 9ef0bfb..45fc6ae 100644 --- a/drivers/video/backlight/tosa_bl.c +++ b/drivers/video/backlight/tosa_bl.c @@ -48,6 +48,9 @@ struct tosa_bl_data { struct ssp_dev nssp_dev; struct ssp_state nssp_state; + /* listen for mode changes */ + struct notifier_block fb_notif; + struct backlight_device *bl_dev; }; @@ -103,14 +106,19 @@ static void tosa_lcd_tg_init(struct tosa_bl_data *data) pxa_nssp_output(data, TG_GPOSR,0x02); /* GPOS0=powercontrol, GPOS1=GPIO, GPOS2=TCTL */ } -static void tosa_lcd_tg_on(struct tosa_bl_data *data/*, const struct fb_videomode *mode*/) +static void tosa_lcd_tg_on(struct tosa_bl_data *data) { - const int value = TG_REG0_COLOR | TG_REG0_UD | TG_REG0_LR; + const struct fb_videomode *mode = tosa_lcd_get_mode(); + + int value = TG_REG0_COLOR | TG_REG0_UD | TG_REG0_LR; + + if (mode->yres == 640) + value |= TG_REG0_VQV; tosa_lcd_tg_init(data); - dev_dbg(&data->bl_dev->dev, "tosa_lcd_on\n"); - pxa_nssp_output(data, TG_PNLCTL, value | (/*mode->yres == 320 ? 0 : */ TG_REG0_VQV)); + dev_dbg(&data->bl_dev->dev, "tosa_lcd_on: %04x (%d)\n", value, mode->yres); + pxa_nssp_output(data, TG_PNLCTL, value); /* TG LCD pannel power up */ pxa_nssp_output(data, TG_PINICTL,0x4); @@ -173,6 +181,20 @@ static struct backlight_ops tosa_bl_ops = { .update_status = tosa_bl_update_status, }; +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *_data) +{ + struct tosa_bl_data *bl_data = + container_of(self, struct tosa_bl_data, fb_notif); + + if (event != FB_EVENT_MODE_CHANGE && event != FB_EVENT_MODE_CHANGE_ALL) + return 0; + + tosa_bl_update_status(bl_data->bl_dev); + + return 0; +} + static int tosa_bl_detect_client(struct i2c_adapter *adapter, int address, int kind) { @@ -238,9 +260,15 @@ static int tosa_bl_detect_client(struct i2c_adapter *adapter, int address, data->bl_dev->props.power = FB_BLANK_UNBLANK; backlight_update_status(data->bl_dev); + data->fb_notif.notifier_call = fb_notifier_callback; + err = fb_register_client(&data->fb_notif); + if (err) + goto err_fb_register; return 0; +err_fb_register: + backlight_device_unregister(data->bl_dev); err_bl_register: tosa_set_backlight(data, 0); tosa_lcd_tg_off(data); @@ -265,6 +293,8 @@ static int tosa_bl_detach_client(struct i2c_client *client) int err = 0; struct tosa_bl_data *data = i2c_get_clientdata(client); + fb_unregister_client(&data->fb_notif); + backlight_device_unregister(data->bl_dev); tosa_set_backlight(data, 0); diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c index 958ee8a..cc75df9 100644 --- a/drivers/video/tmiofb.c +++ b/drivers/video/tmiofb.c @@ -618,17 +618,17 @@ static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) static int tmiofb_set_par(struct fb_info *info) { -/* struct fb_var_screeninfo *var = &info->var; + struct fb_var_screeninfo *var = &info->var; struct fb_videomode *mode; mode = tmiofb_find_mode(info, var); if (!mode) return -EINVAL; - if (info->mode == mode) - return 0; +/* if (info->mode == mode) + return 0;*/ - info->mode = mode; */ + info->mode = mode; info->fix.line_length = info->mode->xres * 2; tmiofb_hw_mode(to_platform_device(info->device)); diff --git a/include/asm-arm/arch-pxa/tosa.h b/include/asm-arm/arch-pxa/tosa.h index 410fa9a..624c636 100644 --- a/include/asm-arm/arch-pxa/tosa.h +++ b/include/asm-arm/arch-pxa/tosa.h @@ -230,4 +230,6 @@ extern struct platform_device tosascoop_device; #define TOSA_KEY_MAIL KEY_MAIL #endif +const struct fb_videomode *tosa_lcd_get_mode(void); + #endif /* _ASM_ARCH_TOSA_H_ */ diff --git a/include/linux/mfd/tc6393xb.h b/include/linux/mfd/tc6393xb.h index 97c4c7c..8ab9e91 100644 --- a/include/linux/mfd/tc6393xb.h +++ b/include/linux/mfd/tc6393xb.h @@ -53,7 +53,7 @@ struct tc6393xb_platform_data { extern int tc6393xb_lcd_set_power(struct platform_device *fb_dev, bool on); extern int tc6393xb_lcd_mode(struct platform_device *fb_dev, - struct fb_videomode *mode); + const struct fb_videomode *mode); /* * Relative to irq_base diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h index b6d4aac..fe7ff2d 100644 --- a/include/linux/mfd/tmio.h +++ b/include/linux/mfd/tmio.h @@ -19,7 +19,7 @@ struct tmio_fb_data { int (*lcd_set_power)(struct platform_device *fb_dev, bool on); int (*lcd_mode)(struct platform_device *fb_dev, - struct fb_videomode *mode); + const struct fb_videomode *mode); int num_modes; struct fb_videomode *modes; }; -- 1.5.4.1