From 863d980d4392041b36edd53b248ae7709609325d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 25 Jul 2008 23:06:04 +0100 Subject: [PATCH] fix-glamofb-cmd-mode-locking.patch Glamo "cmd mode" is modal, but nothing took care about locking. Also cmd mode was entered recursively in rotate_lcd(). Signed-off-by: Andy Green --- drivers/mfd/glamo/glamo-core.c | 2 +- drivers/mfd/glamo/glamo-fb.c | 106 +++++++++++++++++++++++++-------------- include/linux/glamofb.h | 2 +- 3 files changed, 70 insertions(+), 40 deletions(-) diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c index accd933..19ca363 100644 --- a/drivers/mfd/glamo/glamo-core.c +++ b/drivers/mfd/glamo/glamo-core.c @@ -588,7 +588,7 @@ int glamo_engine_reclock(struct glamo_core *glamo, if (val) { val--; reg_set_bit_mask(glamo, reg, mask, val); - msleep(5); /* wait some time to stabilize */ + mdelay(5); /* wait some time to stabilize */ return 0; } else { diff --git a/drivers/mfd/glamo/glamo-fb.c b/drivers/mfd/glamo/glamo-fb.c index 87c7420..8633e44 100644 --- a/drivers/mfd/glamo/glamo-fb.c +++ b/drivers/mfd/glamo/glamo-fb.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -50,7 +51,7 @@ #include "glamo-regs.h" #include "glamo-core.h" -#ifdef DEBUG +#ifndef DEBUG #define GLAMO_LOG(...) #else #define GLAMO_LOG(...) \ @@ -72,6 +73,7 @@ struct glamofb_handle { struct glamofb_platform_data *mach_info; char __iomem *cursor_addr; u_int32_t pseudo_pal[16]; + spinlock_t lock_cmd; }; /* 'sibling' spi device for lcm init */ @@ -237,6 +239,7 @@ static void rotate_lcd(struct glamofb_handle *glamo, __u32 rotation) { int glamo_rot; + unsigned long flags; switch (rotation) { case FB_ROTATE_UR: @@ -255,7 +258,15 @@ static void rotate_lcd(struct glamofb_handle *glamo, glamo_rot = GLAMO_LCD_ROT_MODE_0; break; } - glamofb_cmd_mode(glamo, 1); + + /* + * ha ha we are only called when we are in cmd mode already + * printk(KERN_ERR"rotate_lcd spin_lock_irqsave\n"); + * spin_lock_irqsave(&glamo->lock_cmd, flags); + * + * if (glamofb_cmd_mode(glamo, 1)) + * goto out_unlock; + */ reg_set_bit_mask(glamo, GLAMO_REG_LCD_WIDTH, GLAMO_LCD_ROT_MODE_MASK, @@ -265,17 +276,19 @@ static void rotate_lcd(struct glamofb_handle *glamo, GLAMO_LCD_MODE1_ROTATE_EN, (glamo_rot != GLAMO_LCD_ROT_MODE_0)? GLAMO_LCD_MODE1_ROTATE_EN : 0); - glamofb_cmd_mode(glamo, 0); +/* glamofb_cmd_mode(glamo, 0); + +out_unlock: + printk(KERN_ERR"rotate_lcd spin_unlock_irqrestore\n"); + spin_unlock_irqrestore(&glamo->lock_cmd, flags); +*/ } static enum orientation get_orientation(struct fb_var_screeninfo *var) { - GLAMO_LOG("mark\n") - if (var->xres <= var->yres) { - GLAMO_LOG("portrait\n") + if (var->xres <= var->yres) return ORIENTATION_PORTRAIT; - } - GLAMO_LOG("landscape\n") + return ORIENTATION_LANDSCAPE; } @@ -299,12 +312,18 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo, struct fb_var_screeninfo *var) { int sync, bp, disp, fp, total, xres, yres, pitch, orientation_changing; + unsigned long flags; - GLAMO_LOG("enter: glamo:%#x, var:%#x\n", (unsigned)glamo, (unsigned)var); +/* GLAMO_LOG("enter: glamo:%#x, var:%#x\n", (unsigned)glamo, (unsigned)var); +*/ if (!glamo || !var) return; - glamofb_cmd_mode(glamo, 1); + printk(KERN_ERR"glamofb_update_lcd_controller spin_lock_irqsave\n"); + spin_lock_irqsave(&glamo->lock_cmd, flags); + + if (glamofb_cmd_mode(glamo, 1)) + goto out_unlock; if (var->pixclock) glamo_engine_reclock(glamo->mach_info->glamo, @@ -313,14 +332,14 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo, xres = var->xres; yres = var->yres; - GLAMO_LOG("xres:%d, yres:%d, rotate:%d\n", xres, yres, var->rotate); - +/* GLAMO_LOG("xres:%d, yres:%d, rotate:%d\n", xres, yres, var->rotate); +*/ /* * figure out if orientation is going to change */ orientation_changing = will_orientation_change(var); - GLAMO_LOG("orientation_changing:%d\n", orientation_changing); - +/* GLAMO_LOG("orientation_changing:%d\n", orientation_changing); +*/ /* * adjust the pitch according to new orientation to come */ @@ -329,8 +348,8 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo, } else { pitch = var->xres * var->bits_per_pixel / 8; } - GLAMO_LOG("pitch:%d\n", pitch); - +/* GLAMO_LOG("pitch:%d\n", pitch); +*/ /* * set the awaiten LCD geometry */ @@ -347,7 +366,7 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo, GLAMO_LCD_PITCH_MASK, pitch); - GLAMO_LOG("mark:\n"); +/* GLAMO_LOG("mark:\n");*/ /* * honour the rotation request */ @@ -365,7 +384,8 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo, var->yres_virtual = var->yres = yres; } - GLAMO_LOG("reported res:(%d,%d)\n", var->xres, var->yres); +/* GLAMO_LOG("reported res:(%d,%d)\n", var->xres, var->yres); +*/ /* * update scannout timings */ @@ -386,8 +406,8 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo, reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_DISP_END, GLAMO_LCD_HV_RETR_DISP_END_MASK, fp); - GLAMO_LOG("mark:\n"); - +/* GLAMO_LOG("mark:\n"); +*/ sync = 0; bp = sync + var->vsync_len; disp = bp + var->upper_margin; @@ -405,10 +425,13 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo, reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_DISP_END, GLAMO_LCD_HV_RETR_DISP_END_MASK, fp); - GLAMO_LOG("mark:\n"); +/* GLAMO_LOG("mark:\n"); */ glamofb_cmd_mode(glamo, 0); - GLAMO_LOG("leave:\n"); +/* GLAMO_LOG("leave:\n"); */ +out_unlock: + printk(KERN_ERR"glamofb_update_lcd_controller spin_unlock_irqrestore\n"); + spin_unlock_irqrestore(&glamo->lock_cmd, flags); } static int glamofb_set_par(struct fb_info *info) @@ -552,23 +575,25 @@ static inline int glamofb_cmdq_empty(struct glamofb_handle *gfb) return reg_read(gfb, GLAMO_REG_LCD_STATUS1) & (1 << 15); } -void glamofb_cmd_mode(struct glamofb_handle *gfb, int on) +/* call holding gfb->lock_cmd when locking, until you unlock */ + +int glamofb_cmd_mode(struct glamofb_handle *gfb, int on) { - int timeout = 20000; + int timeout = 200000; - dev_dbg(gfb->dev, "glamofb_cmd_mode(gfb=%p, on=%d)\n", gfb, 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__); +/* dev_dbg(gfb->dev, "%s: waiting for cmdq empty: ", + __FUNCTION__); */ while ((!glamofb_cmdq_empty(gfb)) && (timeout--)) yield(); if (timeout < 0) { printk(KERN_ERR"*************" "glamofb cmd_queue never got empty" "*************\n"); - return; + return -EIO; } - dev_dbg(gfb->dev, "empty!\n"); +/* dev_dbg(gfb->dev, "empty!\n"); */ /* display the entire frame then switch to command */ reg_write(gfb, GLAMO_REG_LCD_COMMAND1, @@ -576,8 +601,8 @@ void glamofb_cmd_mode(struct glamofb_handle *gfb, int on) GLAMO_LCD_CMD_DATA_FIRE_VSYNC); /* wait until LCD is idle */ - dev_dbg(gfb->dev, "waiting for LCD idle: "); - timeout = 2000; +/* dev_dbg(gfb->dev, "waiting for LCD idle: "); */ + timeout = 200000; while ((!reg_read(gfb, GLAMO_REG_LCD_STATUS2) & (1 << 12)) && (timeout--)) yield(); @@ -585,11 +610,11 @@ void glamofb_cmd_mode(struct glamofb_handle *gfb, int on) printk(KERN_ERR"*************" "glamofb lcd never idle" "*************\n"); - return; + return -EIO; } - dev_dbg(gfb->dev, "idle!\n"); +/* dev_dbg(gfb->dev, "idle!\n"); */ - msleep(90); + mdelay(100); } else { /* RGB interface needs vsync/hsync */ if (reg_read(gfb, GLAMO_REG_LCD_MODE3) & GLAMO_LCD_MODE3_RGB) @@ -601,15 +626,17 @@ void glamofb_cmd_mode(struct glamofb_handle *gfb, int on) GLAMO_LCD_CMD_TYPE_DISP | GLAMO_LCD_CMD_DATA_DISP_FIRE); } + + return 0; } EXPORT_SYMBOL_GPL(glamofb_cmd_mode); int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val) { - int timeout = 20000; + int timeout = 200000; - dev_dbg(gfb->dev, "%s: waiting for cmdq empty\n", - __FUNCTION__); +/* dev_dbg(gfb->dev, "%s: waiting for cmdq empty\n", + __FUNCTION__); */ while ((!glamofb_cmdq_empty(gfb)) && (timeout--)) yield(); if (timeout < 0) { @@ -618,7 +645,7 @@ int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val) "*************\n"); return 1; } - dev_dbg(gfb->dev, "idle, writing 0x%04x\n", val); +/* dev_dbg(gfb->dev, "idle, writing 0x%04x\n", val); */ reg_write(gfb, GLAMO_REG_LCD_COMMAND1, val); @@ -758,6 +785,9 @@ static int __init glamofb_probe(struct platform_device *pdev) 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); rc = register_framebuffer(fbinfo); diff --git a/include/linux/glamofb.h b/include/linux/glamofb.h index 75eefef..51bf593 100644 --- a/include/linux/glamofb.h +++ b/include/linux/glamofb.h @@ -33,7 +33,7 @@ struct glamofb_platform_data { int (*glamo_irq_is_wired)(void); }; -void glamofb_cmd_mode(struct glamofb_handle *gfb, int on); +int glamofb_cmd_mode(struct glamofb_handle *gfb, int on); int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val); void glamo_lcm_reset(int level); -- 1.5.6.3