aboutsummaryrefslogtreecommitdiff
path: root/drivers/mfd/glamo/glamo-fb.c
diff options
context:
space:
mode:
authorNicolas Dufresne <nicolas.dufresne@gmail.com>2009-04-04 14:15:48 -0400
committerNelson Castillo <n@fugue.noexisteestedominiotanlargo.biz>2009-04-05 09:54:49 -0500
commitbd4b7e8e84ab43a13a4620b001d52d373c2122b3 (patch)
tree1a2b5dc890489f80b694a61ddbe21629a2c23147 /drivers/mfd/glamo/glamo-fb.c
parent9c4451ff31b937a478f3d3eabef30b71cbe12b12 (diff)
Fixed the LCM driver state transition delay and pixel clock issue
Space transition between sleep-in and sleep-out of at least 120 ms as mentionned in the spec. Also, made sure the LCM is moved into sleep state before the pixel clock is turned off. To do so, I've modified glamo-fb to send FB_BLANK_POWERDOWN before turning off the pixel clock. Also fixed various violation of coding style. This patch should reduce the risk of white screen. Signed-off-by: Nicolas Dufresne <nicolas.dufresne@gmail.com>
Diffstat (limited to 'drivers/mfd/glamo/glamo-fb.c')
-rw-r--r--drivers/mfd/glamo/glamo-fb.c127
1 files changed, 74 insertions, 53 deletions
diff --git a/drivers/mfd/glamo/glamo-fb.c b/drivers/mfd/glamo/glamo-fb.c
index 4eb81a508e5..5491dadbf8a 100644
--- a/drivers/mfd/glamo/glamo-fb.c
+++ b/drivers/mfd/glamo/glamo-fb.c
@@ -37,9 +37,9 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
#include <asm/div64.h>
#ifdef CONFIG_PM
@@ -76,6 +76,7 @@ struct glamofb_handle {
u_int32_t pseudo_pal[16];
spinlock_t lock_cmd;
int angle; /* Current rotation angle */
+ int blank_mode;
};
/* 'sibling' spi device for lcm init */
@@ -89,7 +90,7 @@ static int reg_read(struct glamofb_handle *glamo,
{
int i = 0;
- for (i = 0; i != 2; i ++)
+ for (i = 0; i != 2; i++)
nop();
return readw(glamo->base + reg);
@@ -100,7 +101,7 @@ static void reg_write(struct glamofb_handle *glamo,
{
int i = 0;
- for (i = 0; i != 2; i ++)
+ for (i = 0; i != 2; i++)
nop();
writew(val, glamo->base + reg);
@@ -141,7 +142,8 @@ static int glamofb_run_script(struct glamofb_handle *glamo,
int i;
if (glamo->mach_info->glamo->suspending) {
- dev_err(&glamo->mach_info->glamo->pdev->dev, "IGNORING glamofb_run_script while "
+ dev_err(&glamo->mach_info->glamo->pdev->dev,
+ "IGNORING glamofb_run_script while "
"suspended\n");
return -EBUSY;
}
@@ -166,7 +168,8 @@ static int glamofb_check_var(struct fb_var_screeninfo *var,
struct glamofb_handle *glamo = info->par;
if (glamo->mach_info->glamo->suspending) {
- dev_err(&glamo->mach_info->glamo->pdev->dev, "IGNORING glamofb_check_var while "
+ dev_err(&glamo->mach_info->glamo->pdev->dev,
+ "IGNORING glamofb_check_var while "
"suspended\n");
return -EBUSY;
}
@@ -263,32 +266,33 @@ static void __rotate_lcd(struct glamofb_handle *glamo, __u32 rotation)
int glamo_rot;
if (glamo->mach_info->glamo->suspending) {
- dev_err(&glamo->mach_info->glamo->pdev->dev, "IGNORING rotate_lcd while "
+ dev_err(&glamo->mach_info->glamo->pdev->dev,
+ "IGNORING rotate_lcd while "
"suspended\n");
return;
}
switch (rotation) {
- case FB_ROTATE_UR:
- glamo_rot = GLAMO_LCD_ROT_MODE_0;
- glamo->angle = 0;
- break;
- case FB_ROTATE_CW:
- glamo_rot = GLAMO_LCD_ROT_MODE_90;
- glamo->angle = 90;
- break;
- case FB_ROTATE_UD:
- glamo_rot = GLAMO_LCD_ROT_MODE_180;
- glamo->angle = 180;
- break;
- case FB_ROTATE_CCW:
- glamo_rot = GLAMO_LCD_ROT_MODE_270;
- glamo->angle = 270;
- break;
- default:
- glamo->angle = 0;
- glamo_rot = GLAMO_LCD_ROT_MODE_0;
- break;
+ case FB_ROTATE_UR:
+ glamo_rot = GLAMO_LCD_ROT_MODE_0;
+ glamo->angle = 0;
+ break;
+ case FB_ROTATE_CW:
+ glamo_rot = GLAMO_LCD_ROT_MODE_90;
+ glamo->angle = 90;
+ break;
+ case FB_ROTATE_UD:
+ glamo_rot = GLAMO_LCD_ROT_MODE_180;
+ glamo->angle = 180;
+ break;
+ case FB_ROTATE_CCW:
+ glamo_rot = GLAMO_LCD_ROT_MODE_270;
+ glamo->angle = 270;
+ break;
+ default:
+ glamo->angle = 0;
+ glamo_rot = GLAMO_LCD_ROT_MODE_0;
+ break;
}
reg_set_bit_mask(glamo,
@@ -298,7 +302,7 @@ static void __rotate_lcd(struct glamofb_handle *glamo, __u32 rotation)
reg_set_bit_mask(glamo,
GLAMO_REG_LCD_MODE1,
GLAMO_LCD_MODE1_ROTATE_EN,
- (glamo_rot != GLAMO_LCD_ROT_MODE_0)?
+ (glamo_rot != GLAMO_LCD_ROT_MODE_0) ?
GLAMO_LCD_MODE1_ROTATE_EN : 0);
}
@@ -313,7 +317,8 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
return;
if (glamo->mach_info->glamo->suspending) {
- dev_err(&glamo->mach_info->glamo->pdev->dev, "IGNORING glamofb_update_lcd_controller while "
+ dev_err(&glamo->mach_info->glamo->pdev->dev,
+ "IGNORING glamofb_update_lcd_controller while "
"suspended\n");
return;
}
@@ -331,10 +336,10 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
var->pixclock);
if (glamo->angle == 90 || glamo->angle == 270) {
- /*
+ /*
* But if we are going back to portrait mode from here,
- * we get inverted values from Xglamo
- */
+ * we get inverted values from Xglamo
+ */
if (!(var->rotate == FB_ROTATE_UR ||
var->rotate == FB_ROTATE_UD)) {
width = var->yres;
@@ -354,7 +359,8 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
/* We don't need to set xres and yres in this particular case
* because Xglamo does it for us */
if (!(glamo->angle == 90 || glamo->angle == 270)) {
- var->xres = width;var->yres = height;
+ var->xres = width;
+ var->yres = height;
}
var->xres_virtual = width;
@@ -427,7 +433,8 @@ out_unlock:
spin_unlock_irqrestore(&glamo->lock_cmd, flags);
}
-static int glamofb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+static int glamofb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
{
struct glamofb_handle *glamo = info->par;
u_int16_t page = var->yoffset / glamo->mach_info->yres.defval;
@@ -442,7 +449,8 @@ static int glamofb_set_par(struct fb_info *info)
struct fb_var_screeninfo *var = &info->var;
if (glamo->mach_info->glamo->suspending) {
- dev_err(&glamo->mach_info->glamo->pdev->dev, "IGNORING glamofb_set_par while "
+ dev_err(&glamo->mach_info->glamo->pdev->dev,
+ "IGNORING glamofb_set_par while "
"suspended\n");
return -EBUSY;
}
@@ -488,17 +496,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->blank_mode != 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->blank_mode = blank_mode;
break;
case FB_BLANK_UNBLANK:
case FB_BLANK_NORMAL:
- /* enable the pixel clock */
- glamo_engine_clkreg_set(gcore, GLAMO_ENGINE_LCD,
+ /* enable the pixel clock if off */
+ if (gfb->blank_mode == FB_BLANK_POWERDOWN)
+ glamo_engine_clkreg_set(gcore,
+ GLAMO_ENGINE_LCD,
GLAMO_CLOCK_LCD_EN_DCLK,
GLAMO_CLOCK_LCD_EN_DCLK);
+
notify_blank(info, blank_mode);
+ gfb->blank_mode = blank_mode;
break;
}
@@ -524,7 +544,8 @@ static int glamofb_setcolreg(unsigned regno,
unsigned int val;
if (glamo->mach_info->glamo->suspending) {
- dev_err(&glamo->mach_info->glamo->pdev->dev, "IGNORING glamofb_set_par while "
+ dev_err(&glamo->mach_info->glamo->pdev->dev,
+ "IGNORING glamofb_set_par while "
"suspended\n");
return -EBUSY;
}
@@ -692,7 +713,8 @@ int glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
int timeout = 2000000;
if (gfb->mach_info->glamo->suspending) {
- dev_err(&gfb->mach_info->glamo->pdev->dev, "IGNORING glamofb_cmd_mode while "
+ dev_err(&gfb->mach_info->glamo->pdev->dev,
+ "IGNORING glamofb_cmd_mode while "
"suspended\n");
return -EBUSY;
}
@@ -700,7 +722,7 @@ int glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
dev_dbg(gfb->dev, "glamofb_cmd_mode(gfb=%p, on=%d)\n", gfb, on);
if (on) {
dev_dbg(gfb->dev, "%s: waiting for cmdq empty: ",
- __FUNCTION__);
+ __func__);
while ((!glamofb_cmdq_empty(gfb)) && (timeout--))
/* yield() */;
if (timeout < 0) {
@@ -755,12 +777,13 @@ int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val)
int timeout = 200000;
if (gfb->mach_info->glamo->suspending) {
- dev_err(&gfb->mach_info->glamo->pdev->dev, "IGNORING glamofb_cmd_write while "
+ dev_err(&gfb->mach_info->glamo->pdev->dev,
+ "IGNORING glamofb_cmd_write while "
"suspended\n");
return -EBUSY;
}
- dev_dbg(gfb->dev, "%s: waiting for cmdq empty\n", __FUNCTION__);
+ dev_dbg(gfb->dev, "%s: waiting for cmdq empty\n", __func__);
while ((!glamofb_cmdq_empty(gfb)) && (timeout--))
yield();
if (timeout < 0) {
@@ -822,6 +845,7 @@ static int __init glamofb_probe(struct platform_device *pdev)
glamofb->dev = &pdev->dev;
glamofb->angle = 0;
+ glamofb->blank_mode = FB_BLANK_POWERDOWN;
strcpy(fbinfo->fix.id, "SMedia Glamo");
@@ -976,38 +1000,35 @@ 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
* are suspended or we lock on nWAIT
*/
-// iounmap(gfb->fb->screen_base);
+ /* iounmap(gfb->fb->screen_base); */
return 0;
}
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 */
-// gfb->fb->screen_base = ioremap(gfb->fb_res->start,
-// RESSIZE(gfb->fb_res));
+ /* gfb->fb->screen_base = ioremap(gfb->fb_res->start,
+ RESSIZE(gfb->fb_res)); */
glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD);
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;
}