diff options
Diffstat (limited to 'target/linux/s3c24xx/patches/0109-fix-glamofb-cmd-mode-locking.patch.patch')
-rwxr-xr-x | target/linux/s3c24xx/patches/0109-fix-glamofb-cmd-mode-locking.patch.patch | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/target/linux/s3c24xx/patches/0109-fix-glamofb-cmd-mode-locking.patch.patch b/target/linux/s3c24xx/patches/0109-fix-glamofb-cmd-mode-locking.patch.patch new file mode 100755 index 0000000000..851eab0221 --- /dev/null +++ b/target/linux/s3c24xx/patches/0109-fix-glamofb-cmd-mode-locking.patch.patch @@ -0,0 +1,320 @@ +From 863d980d4392041b36edd53b248ae7709609325d Mon Sep 17 00:00:00 2001 +From: Andy Green <andy@openmoko.com> +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 <andy@openmoko.com> +--- + 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 <linux/wait.h> + #include <linux/platform_device.h> + #include <linux/clk.h> ++#include <linux/spinlock.h> + + #include <asm/io.h> + #include <asm/uaccess.h> +@@ -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 + |