aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/s3c24xx/patches-2.6.26/0109-fix-glamofb-cmd-mode-locking.patch.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/s3c24xx/patches-2.6.26/0109-fix-glamofb-cmd-mode-locking.patch.patch')
-rwxr-xr-xtarget/linux/s3c24xx/patches-2.6.26/0109-fix-glamofb-cmd-mode-locking.patch.patch320
1 files changed, 320 insertions, 0 deletions
diff --git a/target/linux/s3c24xx/patches-2.6.26/0109-fix-glamofb-cmd-mode-locking.patch.patch b/target/linux/s3c24xx/patches-2.6.26/0109-fix-glamofb-cmd-mode-locking.patch.patch
new file mode 100755
index 0000000000..851eab0221
--- /dev/null
+++ b/target/linux/s3c24xx/patches-2.6.26/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
+
3'>643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705