The attached patch allow entering sleep state in the JBT LCM before the pixel clock is turned off. This was found to be required according to the partial spec provided by Joerg in bug 1841.
While this patch fixes some white screen issue, it's not very elegant. I think we should rework the display interface (this was introduce by OM) to have a more granular way to create interaction between frame buffer and the LCM. Also, it would be nice if we could hook direct actions on the backlight to prevent white flash from kernel side wihtout having to trade on power drain. Nicolas
commit 59307617837714ce4d937fb276d8fa57694e7fe5 Author: Nicolas Dufresne <[email protected]> Date: Sat Apr 4 10:36:32 2009 -0400 Altered frame buffer event order to allow the jbt LCM to enter sleep state before the pixel clock is turned off. Note that for long term, this may need a custom event mechanic between the glamo frame buffer and the LCM. Signed-off-by: Nicolas Dufresne <[email protected]> diff --git a/drivers/mfd/glamo/glamo-fb.c b/drivers/mfd/glamo/glamo-fb.c index 4eb81a5..6457e9d 100644 --- a/drivers/mfd/glamo/glamo-fb.c +++ b/drivers/mfd/glamo/glamo-fb.c @@ -76,6 +76,7 @@ struct glamofb_handle { u_int32_t pseudo_pal[16]; spinlock_t lock_cmd; int angle; /* Current rotation angle */ + int fb_blank; }; /* 'sibling' spi device for lcm init */ @@ -479,7 +480,7 @@ static int glamofb_blank(int blank_mode, struct fb_info *info) struct glamofb_handle *gfb = info->par; struct glamo_core *gcore = gfb->mach_info->glamo; - dev_dbg(gfb->dev, "glamofb_blank(%u)\n", blank_mode); + dev_info(gfb->dev, "glamofb_blank(%u)\n", blank_mode); switch (blank_mode) { case FB_BLANK_VSYNC_SUSPEND: @@ -488,17 +489,29 @@ static int glamofb_blank(int blank_mode, struct fb_info *info) * we should already switch off pixel clock here */ break; case FB_BLANK_POWERDOWN: + /* Simulating FB_BLANK_NORMAL allow turning off backlight */ + if (gfb->fb_blank != FB_BLANK_NORMAL) + notify_blank(info, FB_BLANK_NORMAL); + + /* LCM need notification before pixel clock is stopped */ + notify_blank(info, blank_mode); + /* disable the pixel clock */ glamo_engine_clkreg_set(gcore, GLAMO_ENGINE_LCD, GLAMO_CLOCK_LCD_EN_DCLK, 0); + gfb->fb_blank = blank_mode; break; case FB_BLANK_UNBLANK: case FB_BLANK_NORMAL: - /* enable the pixel clock */ - glamo_engine_clkreg_set(gcore, GLAMO_ENGINE_LCD, - GLAMO_CLOCK_LCD_EN_DCLK, - GLAMO_CLOCK_LCD_EN_DCLK); + if (gfb->fb_blank == FB_BLANK_POWERDOWN) + { + /* enable the pixel clock */ + glamo_engine_clkreg_set(gcore, GLAMO_ENGINE_LCD, + GLAMO_CLOCK_LCD_EN_DCLK, + GLAMO_CLOCK_LCD_EN_DCLK); + } notify_blank(info, blank_mode); + gfb->fb_blank = blank_mode; break; } @@ -822,6 +835,7 @@ static int __init glamofb_probe(struct platform_device *pdev) glamofb->dev = &pdev->dev; glamofb->angle = 0; + glamofb->fb_blank = FB_BLANK_POWERDOWN; strcpy(fbinfo->fix.id, "SMedia Glamo"); @@ -976,7 +990,6 @@ static int glamofb_suspend(struct platform_device *pdev, pm_message_t state) struct glamofb_handle *gfb = platform_get_drvdata(pdev); /* we need to stop anything touching our framebuffer */ -// fb_blank(gfb->fb, FB_BLANK_NORMAL); fb_set_suspend(gfb->fb, 1); /* seriously -- nobody is allowed to touch glamo memory when we @@ -989,7 +1002,7 @@ static int glamofb_suspend(struct platform_device *pdev, pm_message_t state) static int glamofb_resume(struct platform_device *pdev) { - struct glamofb_handle *glamofb = platform_get_drvdata(pdev); + struct glamofb_handle *gfb = platform_get_drvdata(pdev); struct glamofb_platform_data *mach_info = pdev->dev.platform_data; /* OK let's allow framebuffer ops again */ @@ -999,15 +1012,13 @@ static int glamofb_resume(struct platform_device *pdev) glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD); printk(KERN_ERR"spin_lock_init\n"); - spin_lock_init(&glamofb->lock_cmd); - glamofb_init_regs(glamofb); + spin_lock_init(&gfb->lock_cmd); + glamofb_init_regs(gfb); #ifdef CONFIG_MFD_GLAMO_HWACCEL - glamofb_cursor_onoff(glamofb, 1); + glamofb_cursor_onoff(gfb, 1); #endif - - fb_set_suspend(glamofb->fb, 0); -// fb_blank(gfb->fb, FB_BLANK_UNBLANK); + fb_set_suspend(gfb->fb, 0); return 0; } diff --git a/drivers/video/display/jbt6k74.c b/drivers/video/display/jbt6k74.c index 16add20..52050cb 100644 --- a/drivers/video/display/jbt6k74.c +++ b/drivers/video/display/jbt6k74.c @@ -591,32 +591,29 @@ static int fb_notifier_callback(struct notifier_block *self, struct jbt_info *jbt; struct fb_event *evdata = data; int fb_blank; + + jbt = container_of(self, struct jbt_info, fb_notif); + + dev_info(&jbt->spi_dev->dev, "jbt6k74 event=%lu\n", event); if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK) return 0; fb_blank = *(int *)evdata->data; - jbt = container_of(self, struct jbt_info, fb_notif); - switch (fb_blank) { case FB_BLANK_UNBLANK: - dev_info(&jbt->spi_dev->dev, "**** jbt6k74 unblank\n"); + dev_info(&jbt->spi_dev->dev, "unblank\n"); jbt6k74_enter_state(jbt, jbt->normal_state); break; case FB_BLANK_NORMAL: - dev_info(&jbt->spi_dev->dev, "**** jbt6k74 normal\n"); + dev_info(&jbt->spi_dev->dev, "blank\n"); break; case FB_BLANK_VSYNC_SUSPEND: - dev_info(&jbt->spi_dev->dev, "**** jbt6k74 vsync suspend\n"); - break; case FB_BLANK_HSYNC_SUSPEND: - dev_info(&jbt->spi_dev->dev, "**** jbt6k74 hsync suspend\n"); + dev_dbg(&jbt->spi_dev->dev, "hsync suspend\n"); break; case FB_BLANK_POWERDOWN: - dev_info(&jbt->spi_dev->dev, "**** jbt6k74 powerdown\n"); - /* FIXME DEEP STANDBY wihtout suspend causes WSOD at cold - * temperature on certain devices. */ - /*jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);*/ + dev_info(&jbt->spi_dev->dev, "powerdown\n"); jbt6k74_enter_state(jbt, JBT_STATE_SLEEP); break; }
