summaryrefslogtreecommitdiff
path: root/target/linux/s3c24xx/patches-2.6.24/1122-fix-glamofb-cmd-mode-locking.patch.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/s3c24xx/patches-2.6.24/1122-fix-glamofb-cmd-mode-locking.patch.patch')
-rw-r--r--target/linux/s3c24xx/patches-2.6.24/1122-fix-glamofb-cmd-mode-locking.patch.patch320
1 files changed, 320 insertions, 0 deletions
diff --git a/target/linux/s3c24xx/patches-2.6.24/1122-fix-glamofb-cmd-mode-locking.patch.patch b/target/linux/s3c24xx/patches-2.6.24/1122-fix-glamofb-cmd-mode-locking.patch.patch
new file mode 100644
index 0000000000..58eecf3ac7
--- /dev/null
+++ b/target/linux/s3c24xx/patches-2.6.24/1122-fix-glamofb-cmd-mode-locking.patch.patch
@@ -0,0 +1,320 @@
+From f2cf4e5f204e981a02a0edaccab4ca39f868ac0f Mon Sep 17 00:00:00 2001
+From: Andy Green <andy@openmoko.com>
+Date: Sun, 13 Apr 2008 07:25:56 +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.5
+