linux-omap git: refresh DSS2 patches against upstream git
authorKoen Kooi <koen@openembedded.org>
Mon, 8 Dec 2008 19:03:10 +0000 (20:03 +0100)
committerKoen Kooi <koen@openembedded.org>
Mon, 8 Dec 2008 19:03:10 +0000 (20:03 +0100)
packages/linux/linux-omap/0003-DSS-Documentation-for-OMAP2-3-display-subsystem.patch
packages/linux/linux-omap/0004-DSS-New-display-subsystem-driver-for-OMAP2-3.patch
packages/linux/linux-omap/0005-DSS-OMAPFB-fb-driver-for-new-display-subsystem.patch
packages/linux/linux-omap/0006-DSS-Add-generic-DVI-panel.patch
packages/linux/linux-omap/0007-DSS-support-for-Beagle-Board.patch
packages/linux/linux-omap/0008-DSS-BEAGLE-Enable-DSS-in-beagle-defconfig.patch
packages/linux/linux-omap/0009-DSS-Sharp-LS037V7DW01-LCD-Panel-driver.patch
packages/linux/linux-omap/0009-DSS-support-for-OMAP3-SDP-board.patch
packages/linux/linux-omap/0011-DSS-Support-for-OMAP3-EVM-board.patch
packages/linux/linux-omap_git.bb

index 6cc8ce1..c3dba57 100644 (file)
@@ -1,4 +1,4 @@
-From e8cc995ace5ef4c8e920ccac6bacc1a0129ad2c4 Mon Sep 17 00:00:00 2001
+From 66fad2b53d3427962407b40af79e227635aed780 Mon Sep 17 00:00:00 2001
 From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
 Date: Tue, 4 Nov 2008 15:08:07 +0200
 Subject: [PATCH] DSS: Documentation for OMAP2/3 display subsystem
index e7beec7..8e64005 100644 (file)
@@ -1,6 +1,6 @@
-From 6bec28d7c3d7cf97d644c610beadfef354fa596e Mon Sep 17 00:00:00 2001
+From 0eceac2ba3548ae41200403a8dae9907ab788fd0 Mon Sep 17 00:00:00 2001
 From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
-Date: Thu, 13 Nov 2008 15:38:15 +0200
+Date: Mon, 8 Dec 2008 13:43:36 +0200
 Subject: [PATCH] DSS: New display subsystem driver for OMAP2/3
 
 Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
@@ -9,17 +9,17 @@ Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
  arch/arm/plat-omap/Makefile               |    2 +
  arch/arm/plat-omap/dss/Kconfig            |   66 +
  arch/arm/plat-omap/dss/Makefile           |    6 +
- arch/arm/plat-omap/dss/dispc.c            | 1722 ++++++++++++++++
- arch/arm/plat-omap/dss/display.c          |  775 ++++++++
- arch/arm/plat-omap/dss/dpi.c              |  323 +++
- arch/arm/plat-omap/dss/dsi.c              | 3020 +++++++++++++++++++++++++++++
- arch/arm/plat-omap/dss/dss.c              |  554 ++++++
- arch/arm/plat-omap/dss/dss.h              |  254 +++
- arch/arm/plat-omap/dss/rfbi.c             | 1234 ++++++++++++
- arch/arm/plat-omap/dss/sdi.c              |  157 ++
- arch/arm/plat-omap/dss/venc.c             |  515 +++++
- arch/arm/plat-omap/include/mach/display.h |  458 +++++
- 14 files changed, 9088 insertions(+), 0 deletions(-)
+ arch/arm/plat-omap/dss/dispc.c            | 2021 +++++++++++++++++++
+ arch/arm/plat-omap/dss/display.c          |  765 +++++++
+ arch/arm/plat-omap/dss/dpi.c              |  320 +++
+ arch/arm/plat-omap/dss/dsi.c              | 3135 +++++++++++++++++++++++++++++
+ arch/arm/plat-omap/dss/dss.c              |  784 +++++++
+ arch/arm/plat-omap/dss/dss.h              |  268 +++
+ arch/arm/plat-omap/dss/rfbi.c             | 1225 +++++++++++
+ arch/arm/plat-omap/dss/sdi.c              |  150 ++
+ arch/arm/plat-omap/dss/venc.c             |  501 +++++
+ arch/arm/plat-omap/include/mach/display.h |  463 +++++
+ 14 files changed, 9708 insertions(+), 0 deletions(-)
  create mode 100644 arch/arm/plat-omap/dss/Kconfig
  create mode 100644 arch/arm/plat-omap/dss/Makefile
  create mode 100644 arch/arm/plat-omap/dss/dispc.c
@@ -142,10 +142,10 @@ index 0000000..e98c6c1
 +omap-dss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
 diff --git a/arch/arm/plat-omap/dss/dispc.c b/arch/arm/plat-omap/dss/dispc.c
 new file mode 100644
-index 0000000..3738cf3
+index 0000000..33fbd0a
 --- /dev/null
 +++ b/arch/arm/plat-omap/dss/dispc.c
-@@ -0,0 +1,1722 @@
+@@ -0,0 +1,2021 @@
 +/*
 + * linux/arch/arm/plat-omap/dss/dispc.c
 + *
@@ -188,6 +188,8 @@ index 0000000..3738cf3
 +/* DISPC */
 +#define DISPC_BASE                    0x48050400
 +
++#define DISPC_SZ_REGS                 SZ_1K
++
 +struct dispc_reg { u16 idx; };
 +
 +#define DISPC_REG(idx)                        ((const struct dispc_reg) { idx })
@@ -211,13 +213,10 @@ index 0000000..3738cf3
 +#define DISPC_TIMING_V                        DISPC_REG(0x0068)
 +#define DISPC_POL_FREQ                        DISPC_REG(0x006C)
 +#define DISPC_DIVISOR                 DISPC_REG(0x0070)
++#define DISPC_GLOBAL_ALPHA            DISPC_REG(0x0074)
 +#define DISPC_SIZE_DIG                        DISPC_REG(0x0078)
 +#define DISPC_SIZE_LCD                        DISPC_REG(0x007C)
 +
-+#define DISPC_DATA_CYCLE1             DISPC_REG(0x01D4)
-+#define DISPC_DATA_CYCLE2             DISPC_REG(0x01D8)
-+#define DISPC_DATA_CYCLE3             DISPC_REG(0x01DC)
-+
 +/* DISPC GFX plane */
 +#define DISPC_GFX_BA0                 DISPC_REG(0x0080)
 +#define DISPC_GFX_BA1                 DISPC_REG(0x0084)
@@ -231,6 +230,16 @@ index 0000000..3738cf3
 +#define DISPC_GFX_WINDOW_SKIP         DISPC_REG(0x00B4)
 +#define DISPC_GFX_TABLE_BA            DISPC_REG(0x00B8)
 +
++#define DISPC_DATA_CYCLE1             DISPC_REG(0x01D4)
++#define DISPC_DATA_CYCLE2             DISPC_REG(0x01D8)
++#define DISPC_DATA_CYCLE3             DISPC_REG(0x01DC)
++
++#define DISPC_CPR_COEF_R              DISPC_REG(0x0220)
++#define DISPC_CPR_COEF_G              DISPC_REG(0x0224)
++#define DISPC_CPR_COEF_B              DISPC_REG(0x0228)
++
++#define DISPC_GFX_PRELOAD             DISPC_REG(0x022C)
++
 +/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */
 +#define DISPC_VID_REG(n, idx)         DISPC_REG(0x00BC + (n)*0x90 + idx)
 +
@@ -254,6 +263,11 @@ index 0000000..3738cf3
 +#define DISPC_VID_FIR_COEF_HV(n, i)   DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8)
 +/* coef index i = {0, 1, 2, 3, 4} */
 +#define DISPC_VID_CONV_COEF(n, i)     DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4)
++/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
++#define DISPC_VID_FIR_COEF_V(n, i)    DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4)
++
++#define DISPC_VID_PRELOAD(n)          DISPC_REG(0x230 + (n)*0x04)
++
 +
 +#define DISPC_IRQ_MASK_ERROR            (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
 +                                       DISPC_IRQ_OCP_ERR | \
@@ -283,24 +297,12 @@ index 0000000..3738cf3
 +static struct {
 +      void __iomem    *base;
 +
-+      struct clk      *dss_ick;
-+      struct clk      *dss1_fck;
-+      struct clk      *dss_54m_fck;
 +      struct clk      *dpll4_m4_ck;
-+} dispc;
 +
-+static spinlock_t dss_lock;
++      spinlock_t      irq_lock;
 +
-+static inline void enable_clocks(int enable)
-+{
-+      if (enable) {
-+              clk_enable(dispc.dss_ick);
-+              clk_enable(dispc.dss1_fck);
-+      } else {
-+              clk_disable(dispc.dss1_fck);
-+              clk_disable(dispc.dss_ick);
-+      }
-+}
++      u32             ctx[DISPC_SZ_REGS / sizeof(u32)];
++} dispc;
 +
 +static inline void dispc_write_reg(const struct dispc_reg idx, u32 val)
 +{
@@ -312,6 +314,303 @@ index 0000000..3738cf3
 +      return __raw_readl(dispc.base + idx.idx);
 +}
 +
++#define SR(reg) \
++      dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
++#define RR(reg) \
++      dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)])
++
++void dispc_save_context(void)
++{
++      SR(SYSCONFIG);
++      SR(IRQENABLE);
++      SR(CONTROL);
++      SR(CONFIG);
++      SR(DEFAULT_COLOR0);
++      SR(DEFAULT_COLOR1);
++      SR(TRANS_COLOR0);
++      SR(TRANS_COLOR1);
++      SR(LINE_NUMBER);
++      SR(TIMING_H);
++      SR(TIMING_V);
++      SR(POL_FREQ);
++      SR(DIVISOR);
++      SR(GLOBAL_ALPHA);
++      SR(SIZE_DIG);
++      SR(SIZE_LCD);
++
++      SR(GFX_BA0);
++      SR(GFX_BA1);
++      SR(GFX_POSITION);
++      SR(GFX_SIZE);
++      SR(GFX_ATTRIBUTES);
++      SR(GFX_FIFO_THRESHOLD);
++      SR(GFX_ROW_INC);
++      SR(GFX_PIXEL_INC);
++      SR(GFX_WINDOW_SKIP);
++      SR(GFX_TABLE_BA);
++
++      SR(DATA_CYCLE1);
++      SR(DATA_CYCLE2);
++      SR(DATA_CYCLE3);
++
++      SR(CPR_COEF_R);
++      SR(CPR_COEF_G);
++      SR(CPR_COEF_B);
++
++      SR(GFX_PRELOAD);
++
++      /* VID1 */
++      SR(VID_BA0(0));
++      SR(VID_BA1(0));
++      SR(VID_POSITION(0));
++      SR(VID_SIZE(0));
++      SR(VID_ATTRIBUTES(0));
++      SR(VID_FIFO_THRESHOLD(0));
++      SR(VID_ROW_INC(0));
++      SR(VID_PIXEL_INC(0));
++      SR(VID_FIR(0));
++      SR(VID_PICTURE_SIZE(0));
++      SR(VID_ACCU0(0));
++      SR(VID_ACCU1(0));
++
++      SR(VID_FIR_COEF_H(0, 0));
++      SR(VID_FIR_COEF_H(0, 1));
++      SR(VID_FIR_COEF_H(0, 2));
++      SR(VID_FIR_COEF_H(0, 3));
++      SR(VID_FIR_COEF_H(0, 4));
++      SR(VID_FIR_COEF_H(0, 5));
++      SR(VID_FIR_COEF_H(0, 6));
++      SR(VID_FIR_COEF_H(0, 7));
++
++      SR(VID_FIR_COEF_HV(0, 0));
++      SR(VID_FIR_COEF_HV(0, 1));
++      SR(VID_FIR_COEF_HV(0, 2));
++      SR(VID_FIR_COEF_HV(0, 3));
++      SR(VID_FIR_COEF_HV(0, 4));
++      SR(VID_FIR_COEF_HV(0, 5));
++      SR(VID_FIR_COEF_HV(0, 6));
++      SR(VID_FIR_COEF_HV(0, 7));
++
++      SR(VID_CONV_COEF(0, 0));
++      SR(VID_CONV_COEF(0, 1));
++      SR(VID_CONV_COEF(0, 2));
++      SR(VID_CONV_COEF(0, 3));
++      SR(VID_CONV_COEF(0, 4));
++
++      SR(VID_FIR_COEF_V(0, 0));
++      SR(VID_FIR_COEF_V(0, 1));
++      SR(VID_FIR_COEF_V(0, 2));
++      SR(VID_FIR_COEF_V(0, 3));
++      SR(VID_FIR_COEF_V(0, 4));
++      SR(VID_FIR_COEF_V(0, 5));
++      SR(VID_FIR_COEF_V(0, 6));
++      SR(VID_FIR_COEF_V(0, 7));
++
++      SR(VID_PRELOAD(0));
++
++      /* VID2 */
++      SR(VID_BA0(1));
++      SR(VID_BA1(1));
++      SR(VID_POSITION(1));
++      SR(VID_SIZE(1));
++      SR(VID_ATTRIBUTES(1));
++      SR(VID_FIFO_THRESHOLD(1));
++      SR(VID_ROW_INC(1));
++      SR(VID_PIXEL_INC(1));
++      SR(VID_FIR(1));
++      SR(VID_PICTURE_SIZE(1));
++      SR(VID_ACCU0(1));
++      SR(VID_ACCU1(1));
++
++      SR(VID_FIR_COEF_H(1, 0));
++      SR(VID_FIR_COEF_H(1, 1));
++      SR(VID_FIR_COEF_H(1, 2));
++      SR(VID_FIR_COEF_H(1, 3));
++      SR(VID_FIR_COEF_H(1, 4));
++      SR(VID_FIR_COEF_H(1, 5));
++      SR(VID_FIR_COEF_H(1, 6));
++      SR(VID_FIR_COEF_H(1, 7));
++
++      SR(VID_FIR_COEF_HV(1, 0));
++      SR(VID_FIR_COEF_HV(1, 1));
++      SR(VID_FIR_COEF_HV(1, 2));
++      SR(VID_FIR_COEF_HV(1, 3));
++      SR(VID_FIR_COEF_HV(1, 4));
++      SR(VID_FIR_COEF_HV(1, 5));
++      SR(VID_FIR_COEF_HV(1, 6));
++      SR(VID_FIR_COEF_HV(1, 7));
++
++      SR(VID_CONV_COEF(1, 0));
++      SR(VID_CONV_COEF(1, 1));
++      SR(VID_CONV_COEF(1, 2));
++      SR(VID_CONV_COEF(1, 3));
++      SR(VID_CONV_COEF(1, 4));
++
++      SR(VID_FIR_COEF_V(1, 0));
++      SR(VID_FIR_COEF_V(1, 1));
++      SR(VID_FIR_COEF_V(1, 2));
++      SR(VID_FIR_COEF_V(1, 3));
++      SR(VID_FIR_COEF_V(1, 4));
++      SR(VID_FIR_COEF_V(1, 5));
++      SR(VID_FIR_COEF_V(1, 6));
++      SR(VID_FIR_COEF_V(1, 7));
++
++      SR(VID_PRELOAD(1));
++}
++
++void dispc_restore_context(void)
++{
++      RR(SYSCONFIG);
++      RR(IRQENABLE);
++      //RR(CONTROL);
++      RR(CONFIG);
++      RR(DEFAULT_COLOR0);
++      RR(DEFAULT_COLOR1);
++      RR(TRANS_COLOR0);
++      RR(TRANS_COLOR1);
++      RR(LINE_NUMBER);
++      RR(TIMING_H);
++      RR(TIMING_V);
++      RR(POL_FREQ);
++      RR(DIVISOR);
++      RR(GLOBAL_ALPHA);
++      RR(SIZE_DIG);
++      RR(SIZE_LCD);
++
++      RR(GFX_BA0);
++      RR(GFX_BA1);
++      RR(GFX_POSITION);
++      RR(GFX_SIZE);
++      RR(GFX_ATTRIBUTES);
++      RR(GFX_FIFO_THRESHOLD);
++      RR(GFX_ROW_INC);
++      RR(GFX_PIXEL_INC);
++      RR(GFX_WINDOW_SKIP);
++      RR(GFX_TABLE_BA);
++
++      RR(DATA_CYCLE1);
++      RR(DATA_CYCLE2);
++      RR(DATA_CYCLE3);
++
++      RR(CPR_COEF_R);
++      RR(CPR_COEF_G);
++      RR(CPR_COEF_B);
++
++      RR(GFX_PRELOAD);
++
++      /* VID1 */
++      RR(VID_BA0(0));
++      RR(VID_BA1(0));
++      RR(VID_POSITION(0));
++      RR(VID_SIZE(0));
++      RR(VID_ATTRIBUTES(0));
++      RR(VID_FIFO_THRESHOLD(0));
++      RR(VID_ROW_INC(0));
++      RR(VID_PIXEL_INC(0));
++      RR(VID_FIR(0));
++      RR(VID_PICTURE_SIZE(0));
++      RR(VID_ACCU0(0));
++      RR(VID_ACCU1(0));
++
++      RR(VID_FIR_COEF_H(0, 0));
++      RR(VID_FIR_COEF_H(0, 1));
++      RR(VID_FIR_COEF_H(0, 2));
++      RR(VID_FIR_COEF_H(0, 3));
++      RR(VID_FIR_COEF_H(0, 4));
++      RR(VID_FIR_COEF_H(0, 5));
++      RR(VID_FIR_COEF_H(0, 6));
++      RR(VID_FIR_COEF_H(0, 7));
++
++      RR(VID_FIR_COEF_HV(0, 0));
++      RR(VID_FIR_COEF_HV(0, 1));
++      RR(VID_FIR_COEF_HV(0, 2));
++      RR(VID_FIR_COEF_HV(0, 3));
++      RR(VID_FIR_COEF_HV(0, 4));
++      RR(VID_FIR_COEF_HV(0, 5));
++      RR(VID_FIR_COEF_HV(0, 6));
++      RR(VID_FIR_COEF_HV(0, 7));
++
++      RR(VID_CONV_COEF(0, 0));
++      RR(VID_CONV_COEF(0, 1));
++      RR(VID_CONV_COEF(0, 2));
++      RR(VID_CONV_COEF(0, 3));
++      RR(VID_CONV_COEF(0, 4));
++
++      RR(VID_FIR_COEF_V(0, 0));
++      RR(VID_FIR_COEF_V(0, 1));
++      RR(VID_FIR_COEF_V(0, 2));
++      RR(VID_FIR_COEF_V(0, 3));
++      RR(VID_FIR_COEF_V(0, 4));
++      RR(VID_FIR_COEF_V(0, 5));
++      RR(VID_FIR_COEF_V(0, 6));
++      RR(VID_FIR_COEF_V(0, 7));
++
++      RR(VID_PRELOAD(0));
++
++      /* VID2 */
++      RR(VID_BA0(1));
++      RR(VID_BA1(1));
++      RR(VID_POSITION(1));
++      RR(VID_SIZE(1));
++      RR(VID_ATTRIBUTES(1));
++      RR(VID_FIFO_THRESHOLD(1));
++      RR(VID_ROW_INC(1));
++      RR(VID_PIXEL_INC(1));
++      RR(VID_FIR(1));
++      RR(VID_PICTURE_SIZE(1));
++      RR(VID_ACCU0(1));
++      RR(VID_ACCU1(1));
++
++      RR(VID_FIR_COEF_H(1, 0));
++      RR(VID_FIR_COEF_H(1, 1));
++      RR(VID_FIR_COEF_H(1, 2));
++      RR(VID_FIR_COEF_H(1, 3));
++      RR(VID_FIR_COEF_H(1, 4));
++      RR(VID_FIR_COEF_H(1, 5));
++      RR(VID_FIR_COEF_H(1, 6));
++      RR(VID_FIR_COEF_H(1, 7));
++
++      RR(VID_FIR_COEF_HV(1, 0));
++      RR(VID_FIR_COEF_HV(1, 1));
++      RR(VID_FIR_COEF_HV(1, 2));
++      RR(VID_FIR_COEF_HV(1, 3));
++      RR(VID_FIR_COEF_HV(1, 4));
++      RR(VID_FIR_COEF_HV(1, 5));
++      RR(VID_FIR_COEF_HV(1, 6));
++      RR(VID_FIR_COEF_HV(1, 7));
++
++      RR(VID_CONV_COEF(1, 0));
++      RR(VID_CONV_COEF(1, 1));
++      RR(VID_CONV_COEF(1, 2));
++      RR(VID_CONV_COEF(1, 3));
++      RR(VID_CONV_COEF(1, 4));
++
++      RR(VID_FIR_COEF_V(1, 0));
++      RR(VID_FIR_COEF_V(1, 1));
++      RR(VID_FIR_COEF_V(1, 2));
++      RR(VID_FIR_COEF_V(1, 3));
++      RR(VID_FIR_COEF_V(1, 4));
++      RR(VID_FIR_COEF_V(1, 5));
++      RR(VID_FIR_COEF_V(1, 6));
++      RR(VID_FIR_COEF_V(1, 7));
++
++      RR(VID_PRELOAD(1));
++
++      /* enable last, because LCD & DIGIT enable are here */
++      RR(CONTROL);
++}
++
++#undef SR
++#undef RR
++
++static inline void enable_clocks(int enable)
++{
++      if (enable)
++              dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++      else
++              dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++}
++
 +void dispc_go(enum omap_channel channel)
 +{
 +      int bit;
@@ -962,13 +1261,6 @@ index 0000000..3738cf3
 +}
 +
 +
-+static inline void get_dss_clocks(void)
-+{
-+      dispc.dss_ick = get_dss_ick();
-+      dispc.dss1_fck = get_dss1_fck();
-+      dispc.dss_54m_fck = get_tv_fck();
-+}
-+
 +void dispc_set_lcd_display_type(enum omap_lcd_display_type type)
 +{
 +      int mode;
@@ -1160,7 +1452,7 @@ index 0000000..3738cf3
 +      unsigned long r = 0;
 +
 +      if (dss_get_dispc_clk_source() == 0)
-+              r = clk_get_rate(dispc.dss1_fck);
++              r = dss_clk_get_rate(DSS_CLK_FCK1);
 +      else
 +#ifdef CONFIG_OMAP2_DSS_DSI
 +              r = dsi_get_dsi1_pll_rate();
@@ -1387,7 +1679,7 @@ index 0000000..3738cf3
 +      if (isr == NULL)
 +              return -EINVAL;
 +
-+      spin_lock_irqsave(&dss_lock, flags);
++      spin_lock_irqsave(&dispc.irq_lock, flags);
 +
 +      for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
 +              if (registered_isr[i].isr == isr) {
@@ -1412,7 +1704,7 @@ index 0000000..3738cf3
 +              break;
 +      }
 +
-+      spin_unlock_irqrestore(&dss_lock, flags);
++      spin_unlock_irqrestore(&dispc.irq_lock, flags);
 +
 +      return ret;
 +}
@@ -1425,7 +1717,7 @@ index 0000000..3738cf3
 +      u32 new_mask = DISPC_IRQ_MASK_ERROR;
 +      int ret = -EINVAL;
 +
-+      spin_lock_irqsave(&dss_lock, flags);
++      spin_lock_irqsave(&dispc.irq_lock, flags);
 +
 +      for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
 +              if (registered_isr[i].isr != isr)
@@ -1446,7 +1738,7 @@ index 0000000..3738cf3
 +              break;
 +      }
 +
-+      spin_unlock_irqrestore(&dss_lock, flags);
++      spin_unlock_irqrestore(&dispc.irq_lock, flags);
 +
 +      return ret;
 +}
@@ -1551,7 +1843,7 @@ index 0000000..3738cf3
 +      l = FLD_MOD(l, 2, 13, 12);      /* MIDLEMODE: smart standby */
 +      l = FLD_MOD(l, 2, 4, 3);        /* SIDLEMODE: smart idle */
 +      l = FLD_MOD(l, 1, 2, 2);        /* ENWAKEUP */
-+      l = FLD_MOD(l, 1, 1, 1);        /* AUTOIDLE */
++      l = FLD_MOD(l, 1, 0, 0);        /* AUTOIDLE */
 +      dispc_write_reg(DISPC_SYSCONFIG, l);
 +
 +      /* FUNCGATED */
@@ -1570,24 +1862,29 @@ index 0000000..3738cf3
 +
 +      /* Set logic clock to fck, pixel clock to fck/2 for now */
 +      dispc_set_lcd_divisor(1, 2);
++
++      dispc_setup_plane_fifo(OMAP_DSS_GFX, 0);
++      dispc_setup_plane_fifo(OMAP_DSS_VIDEO1, 0);
++      dispc_setup_plane_fifo(OMAP_DSS_VIDEO2, 0);
 +}
 +
 +int dispc_init(void)
 +{
 +      u32 rev;
 +
-+      spin_lock_init(&dss_lock);
++      spin_lock_init(&dispc.irq_lock);
 +
-+      dispc.base = ioremap(DISPC_BASE, SZ_1K);
++      dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS);
 +      if (!dispc.base) {
 +              DSSERR("can't ioremap DISPC\n");
 +              return -ENOMEM;
 +      }
 +
-+      get_dss_clocks();
 +      dispc.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
-+      if (IS_ERR(dispc.dpll4_m4_ck))
++      if (IS_ERR(dispc.dpll4_m4_ck)) {
 +              DSSERR("Failed to get dpll4_m4_ck\n");
++              return -ENODEV;
++      }
 +
 +      enable_clocks(1);
 +
@@ -1595,6 +1892,8 @@ index 0000000..3738cf3
 +
 +      _omap_dispc_initialize_irq();
 +
++      dispc_save_context();
++
 +      rev = dispc_read_reg(DISPC_REVISION);
 +      printk(KERN_INFO "OMAP DISPC rev %d.%d\n",
 +             FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
@@ -1870,10 +2169,10 @@ index 0000000..3738cf3
 +
 diff --git a/arch/arm/plat-omap/dss/display.c b/arch/arm/plat-omap/dss/display.c
 new file mode 100644
-index 0000000..4d7238f
+index 0000000..b7f7aff
 --- /dev/null
 +++ b/arch/arm/plat-omap/dss/display.c
-@@ -0,0 +1,775 @@
+@@ -0,0 +1,765 @@
 +/*
 + * linux/arch/arm/plat-omap/dss/display.c
 + *
@@ -1917,26 +2216,11 @@ index 0000000..4d7238f
 +static ssize_t show_clk(struct device *dev, struct device_attribute *attr,
 +              char *buf)
 +{
-+      struct clk *clocks[5];
-+      int i;
 +      ssize_t l, size = PAGE_SIZE;
 +
-+      clocks[0] = get_dss_ick();
-+      clocks[1] = get_dss1_fck();
-+      clocks[2] = get_dss2_fck();
-+      clocks[3] = get_tv_fck();
-+      clocks[4] = get_96m_fck();
-+
 +      l = 0;
 +
-+      l += snprintf(buf + l, size - l, "- dss -\n");
-+
-+      for (i = 0; i < 5; i++) {
-+              l += snprintf(buf + l, size - l, "%-15s\t%lu\t%d\n",
-+                              clocks[i]->name,
-+                              clk_get_rate(clocks[i]),
-+                              clk_get_usecount(clocks[i]));
-+      }
++      l += dss_print_clocks(buf + l, size - l);
 +
 +      l += dispc_print_clocks(buf + l, size - l);
 +#ifdef CONFIG_OMAP2_DSS_DSI
@@ -2218,7 +2502,7 @@ index 0000000..4d7238f
 +static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 +{
 +      int i;
-+      int r;
++      int r = 0;
 +
 +      DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
 +
@@ -2236,6 +2520,8 @@ index 0000000..4d7238f
 +                      return 0;
 +      }
 +
++      dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
 +      for (i = 0; i < mgr->num_overlays; i++) {
 +              int ilace = 0;
 +              int outw, outh;
@@ -2282,7 +2568,7 @@ index 0000000..4d7238f
 +
 +              if (r) {
 +                      DSSERR("dispc_setup_plane failed\n");
-+                      return r;
++                      goto exit;
 +              }
 +
 +              dispc_enable_plane(ovl->id, 1);
@@ -2290,7 +2576,10 @@ index 0000000..4d7238f
 +
 +      dispc_go(mgr->id);
 +
-+      return 0;
++exit:
++      dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++      return r;
 +}
 +
 +static struct omap_overlay dispc_overlays[] = {
@@ -2651,10 +2940,10 @@ index 0000000..4d7238f
 +EXPORT_SYMBOL(omap_dss_unregister_panel);
 diff --git a/arch/arm/plat-omap/dss/dpi.c b/arch/arm/plat-omap/dss/dpi.c
 new file mode 100644
-index 0000000..2261288
+index 0000000..e3ad44e
 --- /dev/null
 +++ b/arch/arm/plat-omap/dss/dpi.c
-@@ -0,0 +1,323 @@
+@@ -0,0 +1,320 @@
 +/*
 + * linux/arch/arm/plat-omap/dss/dpi.c
 + *
@@ -2688,8 +2977,6 @@ index 0000000..2261288
 +
 +
 +static struct {
-+      struct clk      *dss_ick;
-+      struct clk      *dss1_fck;
 +      int update_enabled;
 +} dpi;
 +
@@ -2790,11 +3077,13 @@ index 0000000..2261288
 +      if (r)
 +              return r;
 +
-+      clk_enable(dpi.dss_ick);
-+      clk_enable(dpi.dss1_fck);
++      dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
 +
 +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
-+      dsi_pll_init(0, 1);
++      dss_clk_enable(DSS_CLK_FCK2);
++      r = dsi_pll_init(0, 1);
++      if (r)
++              return r;
 +#endif
 +      is_tft = (display->panel->config & OMAP_DSS_LCD_TFT) != 0;
 +
@@ -2830,10 +3119,10 @@ index 0000000..2261288
 +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
 +      dss_select_clk_source(0, 0);
 +      dsi_pll_uninit();
++      dss_clk_disable(DSS_CLK_FCK2);
 +#endif
 +
-+      clk_disable(dpi.dss_ick);
-+      clk_disable(dpi.dss1_fck);
++      dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
 +
 +      display->state = OMAP_DSS_DISPLAY_DISABLED;
 +}
@@ -2848,8 +3137,7 @@ index 0000000..2261288
 +
 +      dispc_enable_lcd_out(0);
 +
-+      clk_disable(dpi.dss_ick);
-+      clk_disable(dpi.dss1_fck);
++      dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
 +
 +      display->state = OMAP_DSS_DISPLAY_SUSPENDED;
 +
@@ -2863,8 +3151,7 @@ index 0000000..2261288
 +
 +      dispc_enable_lcd_out(1);
 +
-+      clk_enable(dpi.dss_ick);
-+      clk_enable(dpi.dss1_fck);
++      dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
 +
 +      if (display->panel->resume)
 +              display->panel->resume(display);
@@ -2906,6 +3193,8 @@ index 0000000..2261288
 +              return -EINVAL;
 +      }
 +
++      if (timings->pixel_clock == 0)
++              return -EINVAL;
 +
 +      is_tft = (display->panel->config & OMAP_DSS_LCD_TFT) != 0;
 +
@@ -2968,9 +3257,6 @@ index 0000000..2261288
 +
 +int dpi_init(void)
 +{
-+      dpi.dss_ick = get_dss_ick();
-+      dpi.dss1_fck = get_dss1_fck();
-+
 +      return 0;
 +}
 +
@@ -2980,10 +3266,10 @@ index 0000000..2261288
 +
 diff --git a/arch/arm/plat-omap/dss/dsi.c b/arch/arm/plat-omap/dss/dsi.c
 new file mode 100644
-index 0000000..9f31ac3
+index 0000000..7f7db32
 --- /dev/null
 +++ b/arch/arm/plat-omap/dss/dsi.c
-@@ -0,0 +1,3020 @@
+@@ -0,0 +1,3135 @@
 +/*
 + * linux/arch/arm/plat-omap/dss/dsi.c
 + *
@@ -3017,6 +3303,7 @@ index 0000000..9f31ac3
 +
 +#include <mach/board.h>
 +#include <mach/display.h>
++#include <mach/clock.h>
 +
 +#include "dss.h"
 +
@@ -3030,6 +3317,7 @@ index 0000000..9f31ac3
 +
 +#define DSI_REG(idx)          ((const struct dsi_reg) { idx })
 +
++#define DSI_SZ_REGS           SZ_1K
 +/* DSI Protocol Engine */
 +
 +#define DSI_REVISION                  DSI_REG(0x0000)
@@ -3068,10 +3356,10 @@ index 0000000..9f31ac3
 +
 +/* DSIPHY_SCP */
 +
-+#define DSIPHY_CFG0                   DSI_REG(0x200 + 0x0000)
-+#define DSIPHY_CFG1                   DSI_REG(0x200 + 0x0004)
-+#define DSIPHY_CFG2                   DSI_REG(0x200 + 0x0008)
-+#define DSIPHY_CFG5                   DSI_REG(0x200 + 0x0014)
++#define DSI_DSIPHY_CFG0                       DSI_REG(0x200 + 0x0000)
++#define DSI_DSIPHY_CFG1                       DSI_REG(0x200 + 0x0004)
++#define DSI_DSIPHY_CFG2                       DSI_REG(0x200 + 0x0008)
++#define DSI_DSIPHY_CFG5                       DSI_REG(0x200 + 0x0014)
 +
 +/* DSI_PLL_CTRL_SCP */
 +
@@ -3178,15 +3466,13 @@ index 0000000..9f31ac3
 +{
 +      void __iomem    *base;
 +
-+      struct clk      *dss_ick;
-+      struct clk      *dss1_fck;
-+      struct clk      *dss2_fck;
-+
 +      unsigned long   dsi1_pll_fclk;  /* Hz */
 +      unsigned long   dsi2_pll_fclk;  /* Hz */
 +      unsigned long   dsiphy;         /* Hz */
 +      unsigned long   ddr_clk;        /* Hz */
 +
++      u32             ctx[DSI_SZ_REGS / sizeof(u32)];
++
 +      struct {
 +              enum fifo_size  fifo_size;
 +              int dest_per;   /* destination peripheral 0-3 */
@@ -3194,15 +3480,18 @@ index 0000000..9f31ac3
 +
 +      struct mutex lock;
 +
++      unsigned pll_locked;
++
 +      struct completion bta_completion;
 +
 +      spinlock_t update_lock;
 +      int update_ongoing;
 +      int update_syncers;
 +      struct completion update_completion;
-+      struct work_struct framedone_work;
++      struct delayed_work framedone_work;
 +
-+      enum omap_dss_update_mode update_mode;
++      enum omap_dss_update_mode user_update_mode;     /* what the user wants */
++      enum omap_dss_update_mode update_mode;          /* current mode */
 +      int use_te;
 +      int framedone_scheduled; /* helps to catch strange framedone bugs */
 +
@@ -3218,7 +3507,6 @@ index 0000000..9f31ac3
 +#endif
 +} dsi;
 +
-+
 +static inline void dsi_write_reg(const struct dsi_reg idx, u32 val)
 +{
 +      __raw_writel(val, dsi.base + idx.idx);
@@ -3229,10 +3517,113 @@ index 0000000..9f31ac3
 +      return __raw_readl(dsi.base + idx.idx);
 +}
 +
++
++#define SR(reg) \
++      dsi.ctx[(DSI_##reg).idx / sizeof(u32)] = dsi_read_reg(DSI_##reg)
++#define RR(reg) \
++      dsi_write_reg(DSI_##reg, dsi.ctx[(DSI_##reg).idx / sizeof(u32)])
++
++void dsi_save_context(void)
++{
++      SR(SYSCONFIG);
++      SR(IRQENABLE);
++      SR(CTRL);
++      SR(COMPLEXIO_CFG1);
++      SR(COMPLEXIO_IRQ_ENABLE);
++      SR(CLK_CTRL);
++      SR(TIMING1);
++      SR(TIMING2);
++      SR(VM_TIMING1);
++      SR(VM_TIMING2);
++      SR(VM_TIMING3);
++      SR(CLK_TIMING);
++      SR(TX_FIFO_VC_SIZE);
++      SR(RX_FIFO_VC_SIZE);
++      SR(COMPLEXIO_CFG2);
++      SR(VM_TIMING4);
++      SR(VM_TIMING5);
++      SR(VM_TIMING6);
++      SR(VM_TIMING7);
++      SR(STOPCLK_TIMING);
++
++      SR(VC_CTRL(0));
++      SR(VC_TE(0));
++      SR(VC_IRQENABLE(0));
++
++      SR(VC_CTRL(1));
++      SR(VC_TE(1));
++      SR(VC_IRQENABLE(1));
++
++      SR(VC_CTRL(2));
++      SR(VC_TE(2));
++      SR(VC_IRQENABLE(2));
++
++      SR(VC_CTRL(3));
++      SR(VC_TE(3));
++      SR(VC_IRQENABLE(3));
++
++      SR(DSIPHY_CFG0);
++      SR(DSIPHY_CFG1);
++      SR(DSIPHY_CFG2);
++      SR(DSIPHY_CFG5);
++
++      SR(PLL_CONTROL);
++      SR(PLL_CONFIGURATION1);
++      SR(PLL_CONFIGURATION2);
++}
++
++void dsi_restore_context(void)
++{
++      RR(SYSCONFIG);
++      RR(IRQENABLE);
++      RR(CTRL);
++      RR(COMPLEXIO_CFG1);
++      RR(COMPLEXIO_IRQ_ENABLE);
++      RR(CLK_CTRL);
++      RR(TIMING1);
++      RR(TIMING2);
++      RR(VM_TIMING1);
++      RR(VM_TIMING2);
++      RR(VM_TIMING3);
++      RR(CLK_TIMING);
++      RR(TX_FIFO_VC_SIZE);
++      RR(RX_FIFO_VC_SIZE);
++      RR(COMPLEXIO_CFG2);
++      RR(VM_TIMING4);
++      RR(VM_TIMING5);
++      RR(VM_TIMING6);
++      RR(VM_TIMING7);
++      RR(STOPCLK_TIMING);
++
++      RR(VC_CTRL(0));
++      RR(VC_IRQENABLE(0));
++
++      RR(VC_CTRL(1));
++      RR(VC_IRQENABLE(1));
++
++      RR(VC_CTRL(2));
++      RR(VC_IRQENABLE(2));
++
++      RR(VC_CTRL(3));
++      RR(VC_IRQENABLE(3));
++
++      RR(DSIPHY_CFG0);
++      RR(DSIPHY_CFG1);
++      RR(DSIPHY_CFG2);
++      RR(DSIPHY_CFG5);
++
++      RR(PLL_CONTROL);
++      RR(PLL_CONFIGURATION1);
++      RR(PLL_CONFIGURATION2);
++}
++
++#undef SR
++#undef RR
++
 +static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
 +              int value)
 +{
-+      int t = 1000;
++      int t = 100000;
 +
 +      while (REG_GET(idx, bitnum, bitnum) != value) {
 +              if (--t == 0)
@@ -3500,22 +3891,24 @@ index 0000000..9f31ac3
 +/* DSI func clock. this could also be DSI2_PLL_FCLK */
 +static inline void enable_clocks(int enable)
 +{
-+      if (enable) {
-+              clk_enable(dsi.dss_ick);
-+              clk_enable(dsi.dss1_fck);
-+      } else {
-+              clk_disable(dsi.dss1_fck);
-+              clk_disable(dsi.dss_ick);
-+      }
++      if (enable)
++              dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++      else
++              dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
 +}
 +
 +/* source clock for DSI PLL. this could also be PCLKFREE */
 +static inline void dsi_enable_pll_clock(int enable)
 +{
 +      if (enable)
-+              clk_enable(dsi.dss2_fck);
++              dss_clk_enable(DSS_CLK_FCK2);
 +      else
-+              clk_disable(dsi.dss2_fck);
++              dss_clk_disable(DSS_CLK_FCK2);
++
++      if (enable && dsi.pll_locked) {
++              if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1)
++                      DSSERR("cannot lock PLL when enabling clocks\n");
++      }
 +}
 +
 +#if 1
@@ -3528,7 +3921,7 @@ index 0000000..9f31ac3
 +      /* A dummy read using the SCP interface to any DSIPHY register is
 +       * required after DSIPHY reset to complete the reset of the DSI complex
 +       * I/O. */
-+      l = dsi_read_reg(DSIPHY_CFG5);
++      l = dsi_read_reg(DSI_DSIPHY_CFG5);
 +
 +      printk(KERN_DEBUG "DSI resets: ");
 +
@@ -3538,7 +3931,7 @@ index 0000000..9f31ac3
 +      l = dsi_read_reg(DSI_COMPLEXIO_CFG1);
 +      printk("CIO (%d) ", FLD_GET(l, 29, 29));
 +
-+      l = dsi_read_reg(DSIPHY_CFG5);
++      l = dsi_read_reg(DSI_DSIPHY_CFG5);
 +      printk("PHY (%x, %d, %d, %d)\n",
 +                      FLD_GET(l, 28, 26),
 +                      FLD_GET(l, 29, 29),
@@ -3564,7 +3957,7 @@ index 0000000..9f31ac3
 +      /* A dummy read using the SCP interface to any DSIPHY register is
 +       * required after DSIPHY reset to complete the reset of the DSI complex
 +       * I/O. */
-+      dsi_read_reg(DSIPHY_CFG5);
++      dsi_read_reg(DSI_DSIPHY_CFG5);
 +
 +      _dsi_print_reset_status();
 +
@@ -3593,7 +3986,7 @@ index 0000000..9f31ac3
 +
 +      if (dss_get_dsi_clk_source() == 0) {
 +              /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */
-+              r = clk_get_rate(dsi.dss1_fck);
++              r = dss_clk_get_rate(DSS_CLK_FCK1);
 +      } else {
 +              /* DSI FCLK source is DSI2_PLL_FCLK */
 +              r = dsi.dsi2_pll_fclk;
@@ -3619,7 +4012,7 @@ index 0000000..9f31ac3
 +      }
 +
 +      if (n == (1 << 13) - 1) {
-+              DSSERR("DSI: Failed to find LP_CLK_DIVISOR\n");
++              DSSERR("Failed to find LP_CLK_DIVISOR\n");
 +              return -EINVAL;
 +      }
 +
@@ -3650,7 +4043,7 @@ index 0000000..9f31ac3
 +      while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) {
 +              udelay(1);
 +              if (t++ > 1000) {
-+                      DSSERR("DSI: Failed to set DSI PLL power mode to %d\n",
++                      DSSERR("Failed to set DSI PLL power mode to %d\n",
 +                                      state);
 +                      return -ENODEV;
 +              }
@@ -3682,7 +4075,7 @@ index 0000000..9f31ac3
 +      memset(&best, 0, sizeof(best));
 +
 +      memset(&cur, 0, sizeof(cur));
-+      cur.clkin = clk_get_rate(dsi.dss2_fck);
++      cur.clkin = dss_clk_get_rate(DSS_CLK_FCK2);
 +      cur.use_dss2_fck = 1;
 +      cur.highfreq = 0;
 +
@@ -3789,7 +4182,7 @@ index 0000000..9f31ac3
 +      memset(&cur, 0, sizeof(cur));
 +      cur.use_dss2_fck = use_dss2_fck;
 +      if (use_dss2_fck) {
-+              cur.clkin = clk_get_rate(dsi.dss2_fck);
++              cur.clkin = dss_clk_get_rate(DSS_CLK_FCK2);
 +              cur.highfreq = 0;
 +      } else {
 +              cur.clkin = dispc_pclk_rate();
@@ -3861,6 +4254,7 @@ index 0000000..9f31ac3
 +      DSSDBG("dsi_pll_program\n");
 +
 +      enable_clocks(1);
++      dsi_enable_pll_clock(1);
 +
 +      dsi.dsiphy = cinfo->dsiphy;
 +      dsi.ddr_clk = dsi.dsiphy / 4;
@@ -3921,11 +4315,13 @@ index 0000000..9f31ac3
 +      }
 +
 +      if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) {
-+              DSSERR("DSI: cannot lock PLL\n");
++              DSSERR("cannot lock PLL\n");
 +              r = -EIO;
 +              goto err;
 +      }
 +
++      dsi.pll_locked = 1;
++
 +      l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
 +      l = FLD_MOD(l, 0, 0, 0);        /* DSI_PLL_IDLE */
 +      l = FLD_MOD(l, 0, 5, 5);        /* DSI_PLL_PLLLPMODE */
@@ -3946,6 +4342,7 @@ index 0000000..9f31ac3
 +      DSSDBG("PLL config done\n");
 +err:
 +      enable_clocks(0);
++      dsi_enable_pll_clock(0);
 +
 +      return r;
 +}
@@ -3967,14 +4364,16 @@ index 0000000..9f31ac3
 +              return r;
 +
 +      r = dispc_set_clock_div(&cinfo);
-+      if (r)
++      if (r) {
++              DSSERR("Failed to set basic clocks\n");
 +              return r;
++      }
 +
 +      /* PLL does not come out of reset without this... */
 +      dispc_pck_free_enable(1);
 +
 +      if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) {
-+              DSSERR("DSI: PLL not coming out of reset.\n");
++              DSSERR("PLL not coming out of reset.\n");
 +              r = -ENODEV;
 +              goto err;
 +      }
@@ -3998,6 +4397,7 @@ index 0000000..9f31ac3
 +              goto err;
 +
 +      enable_clocks(0);
++      dsi_enable_pll_clock(0);
 +
 +      DSSDBG("PLL init done\n");
 +
@@ -4010,8 +4410,8 @@ index 0000000..9f31ac3
 +
 +void dsi_pll_uninit(void)
 +{
++      dsi.pll_locked = 0;
 +      dsi_pll_power(DSI_PLL_POWER_OFF);
-+      dsi_enable_pll_clock(0);
 +      DSSDBG("PLL uninit done\n");
 +}
 +
@@ -4079,7 +4479,7 @@ index 0000000..9f31ac3
 +      while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) {
 +              udelay(1);
 +              if (t++ > 1000) {
-+                      DSSERR("DSI: failed to set complexio power state to "
++                      DSSERR("failed to set complexio power state to "
 +                                      "%d\n", state);
 +                      return -ENODEV;
 +              }
@@ -4181,22 +4581,22 @@ index 0000000..9f31ac3
 +
 +      /* program timings */
 +
-+      r = dsi_read_reg(DSIPHY_CFG0);
++      r = dsi_read_reg(DSI_DSIPHY_CFG0);
 +      r = FLD_MOD(r, ths_prepare, 31, 24);
 +      r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16);
 +      r = FLD_MOD(r, ths_trail, 15, 8);
 +      r = FLD_MOD(r, ths_exit, 7, 0);
-+      dsi_write_reg(DSIPHY_CFG0, r);
++      dsi_write_reg(DSI_DSIPHY_CFG0, r);
 +
-+      r = dsi_read_reg(DSIPHY_CFG1);
++      r = dsi_read_reg(DSI_DSIPHY_CFG1);
 +      r = FLD_MOD(r, tlpx_half, 22, 16);
 +      r = FLD_MOD(r, tclk_trail, 15, 8);
 +      r = FLD_MOD(r, tclk_zero, 7, 0);
-+      dsi_write_reg(DSIPHY_CFG1, r);
++      dsi_write_reg(DSI_DSIPHY_CFG1, r);
 +
-+      r = dsi_read_reg(DSIPHY_CFG2);
++      r = dsi_read_reg(DSI_DSIPHY_CFG2);
 +      r = FLD_MOD(r, tclk_prepare, 7, 0);
-+      dsi_write_reg(DSIPHY_CFG2, r);
++      dsi_write_reg(DSI_DSIPHY_CFG2, r);
 +}
 +
 +
@@ -4209,8 +4609,8 @@ index 0000000..9f31ac3
 +      /* CIO_CLK_ICG, enable L3 clk to CIO */
 +      REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
 +
-+      if (wait_for_bit_change(DSIPHY_CFG5, 30, 1) != 1) {
-+              DSSERR("DSI: ComplexIO PHY not coming out of reset.\n");
++      if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) {
++              DSSERR("ComplexIO PHY not coming out of reset.\n");
 +              r = -ENODEV;
 +              goto err;
 +      }
@@ -4223,13 +4623,13 @@ index 0000000..9f31ac3
 +              goto err;
 +
 +      if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
-+              DSSERR("DSI: ComplexIO not coming out of reset.\n");
++              DSSERR("ComplexIO not coming out of reset.\n");
 +              r = -ENODEV;
 +              goto err;
 +      }
 +
 +      if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
-+              DSSERR("DSI: ComplexIO LDO power down.\n");
++              DSSERR("ComplexIO LDO power down.\n");
 +              r = -ENODEV;
 +              goto err;
 +      }
@@ -4283,7 +4683,7 @@ index 0000000..9f31ac3
 +              int size = dsi.vc[i].fifo_size;
 +
 +              if (add + size > 4) {
-+                      DSSERR("DSI: Illegal FIFO configuration\n");
++                      DSSERR("Illegal FIFO configuration\n");
 +                      BUG();
 +              }
 +
@@ -4313,7 +4713,7 @@ index 0000000..9f31ac3
 +              int size = dsi.vc[i].fifo_size;
 +
 +              if (add + size > 4) {
-+                      DSSERR("DSI: Illegal FIFO configuration\n");
++                      DSSERR("Illegal FIFO configuration\n");
 +                      BUG();
 +              }
 +
@@ -4576,7 +4976,7 @@ index 0000000..9f31ac3
 +
 +      /* len + header */
 +      if (dsi.vc[channel].fifo_size * 32 * 4 < len + 4) {
-+              DSSERR("DSI: unable to send long packet: packet too long.\n");
++              DSSERR("unable to send long packet: packet too long.\n");
 +              return -EINVAL;
 +      }
 +
@@ -4991,16 +5391,16 @@ index 0000000..9f31ac3
 +      int ddr_clk_pre, ddr_clk_post;
 +      u32 r;
 +
-+      r = dsi_read_reg(DSIPHY_CFG1);
++      r = dsi_read_reg(DSI_DSIPHY_CFG1);
 +      tlpx_half = FLD_GET(r, 22, 16);
 +      tclk_trail = FLD_GET(r, 15, 8);
 +      tclk_zero = FLD_GET(r, 7, 0);
 +
-+      r = dsi_read_reg(DSIPHY_CFG2);
++      r = dsi_read_reg(DSI_DSIPHY_CFG2);
 +      tclk_prepare = FLD_GET(r, 7, 0);
 +
 +      /* min 8*UI */
-+      tclk_pre = 4;
++      tclk_pre = 20;
 +      /* min 60ns + 52*UI */
 +      tclk_post = ns2ddr(60) + 26;
 +
@@ -5070,6 +5470,7 @@ index 0000000..9f31ac3
 +              return -EINVAL;
 +
 +      enable_clocks(1);
++      dsi_enable_pll_clock(1);
 +
 +      scr_width = ovl->info.screen_width;
 +      data = ovl->info.vaddr;
@@ -5186,6 +5587,7 @@ index 0000000..9f31ac3
 +      end_measuring("L4");
 +
 +      enable_clocks(0);
++      dsi_enable_pll_clock(0);
 +
 +      return 0;
 +}
@@ -5284,7 +5686,7 @@ index 0000000..9f31ac3
 +}
 +#endif
 +
-+static int dsi_wait_for_framedone(void)
++static int dsi_wait_for_framedone(int stop_update)
 +{
 +      unsigned long flags;
 +
@@ -5292,6 +5694,8 @@ index 0000000..9f31ac3
 +      if (dsi.update_ongoing) {
 +              long wait = msecs_to_jiffies(1000);
 +              dsi.update_syncers++;
++              if (stop_update)
++                      dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
 +              spin_unlock_irqrestore(&dsi.update_lock, flags);
 +              wait = wait_for_completion_timeout(&dsi.update_completion,
 +                              wait);
@@ -5343,10 +5747,12 @@ index 0000000..9f31ac3
 +      w = dsi.update_region.w;
 +      h = dsi.update_region.h;
 +
-+      DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
-+                      x, y, w, h);
++      if (dsi.user_update_mode != OMAP_DSS_UPDATE_AUTO)
++              DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
++                              x, y, w, h);
 +
 +      enable_clocks(1);
++      dsi_enable_pll_clock(1);
 +
 +      /* TODO: one packet could be longer, I think? Max is the line buffer */
 +      line_packet_len = w * bytespp + 1;      /* 1 byte for DCS cmd */
@@ -5390,7 +5796,13 @@ index 0000000..9f31ac3
 +       * is sending the data. Thus we have to wait until we can do a new
 +       * transfer or turn the clocks off. We do that in a separate work
 +       * func. */
-+      schedule_work(&dsi.framedone_work);
++      /* XXX When using auto update and delay value 0, the kernel seems to be
++       * very relaxed about when to call our callback. It may take a second.
++       * Thus we use a delay of 1 */
++      if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
++              schedule_delayed_work(&dsi.framedone_work, 1);
++      else
++              schedule_delayed_work(&dsi.framedone_work, 0);
 +}
 +
 +static void framedone_worker(struct work_struct *work)
@@ -5432,7 +5844,8 @@ index 0000000..9f31ac3
 +
 +      end_measuring("DISPC");
 +
-+      DSSDBG("FRAMEDONE\n");
++      if (dsi.user_update_mode != OMAP_DSS_UPDATE_AUTO)
++              DSSDBG("FRAMEDONE\n");
 +
 +#if 0
 +      if (l)
@@ -5442,26 +5855,29 @@ index 0000000..9f31ac3
 +              DSSWARN("FRAMEDONE irq too early, %d bytes, %d loops\n", l, i);
 +#endif
 +
-+      spin_lock_irqsave(&dsi.update_lock, flags);
-+      dsi.update_ongoing = 0;
-+      while (dsi.update_syncers > 0) {
-+              complete(&dsi.update_completion);
-+              --dsi.update_syncers;
-+      }
-+      spin_unlock_irqrestore(&dsi.update_lock, flags);
-+
 +#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
 +      dispc_fake_vsync_irq();
 +#endif
 +      enable_clocks(0);
++      dsi_enable_pll_clock(0);
 +
 +      dsi.framedone_scheduled = 0;
 +
++      spin_lock_irqsave(&dsi.update_lock, flags);
++
++      if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
++              dsi.update_ongoing = 0;
++
++      while (dsi.update_syncers > 0) {
++              complete(&dsi.update_completion);
++              --dsi.update_syncers;
++      }
++
 +      if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
-+              spin_lock_irqsave(&dsi.update_lock, flags);
-+              dsi.update_ongoing = 1;
 +              spin_unlock_irqrestore(&dsi.update_lock, flags);
 +              dsi_update_screen_dispc(dsi.update_region.display);
++      } else {
++              spin_unlock_irqrestore(&dsi.update_lock, flags);
 +      }
 +}
 +
@@ -5480,6 +5896,7 @@ index 0000000..9f31ac3
 +      dsi.update_region.bytespp = bytespp;
 +
 +      enable_clocks(1);
++      dsi_enable_pll_clock(1);
 +
 +      dispc_set_lcd_size(display->x_res, display->y_res);
 +
@@ -5491,14 +5908,12 @@ index 0000000..9f31ac3
 +
 +static void dsi_stop_auto_update(void)
 +{
-+      dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
-+
 +      DSSDBG("waiting for display to finish.\n");
-+      dsi_wait_for_framedone();
++      dsi_wait_for_framedone(1);
 +      DSSDBG("done waiting\n");
-+      enable_clocks(0);
 +
-+      dsi.update_mode = OMAP_DSS_UPDATE_MANUAL;
++      enable_clocks(0);
++      dsi_enable_pll_clock(0);
 +}
 +
 +static int dsi_set_update_mode(struct omap_display *display,
@@ -5510,7 +5925,7 @@ index 0000000..9f31ac3
 +      if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
 +              dsi_stop_auto_update();
 +      else if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
-+              dsi_wait_for_framedone();
++              dsi_wait_for_framedone(0);
 +
 +      dsi.update_mode = mode;
 +
@@ -5538,6 +5953,7 @@ index 0000000..9f31ac3
 +      }
 +
 +      enable_clocks(1);
++      dsi_enable_pll_clock(1);
 +
 +      r = omap_dispc_register_isr(framedone_callback, NULL,
 +                      DISPC_IRQ_FRAMEDONE);
@@ -5631,10 +6047,10 @@ index 0000000..9f31ac3
 +
 +      display->state = OMAP_DSS_DISPLAY_ACTIVE;
 +
-+      if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
-+              dsi_start_auto_update(display);
++      dsi_set_update_mode(display, dsi.user_update_mode);
 +
 +      enable_clocks(0);
++      dsi_enable_pll_clock(0);
 +      mutex_unlock(&dsi.lock);
 +
 +      return 0;
@@ -5654,6 +6070,7 @@ index 0000000..9f31ac3
 +      omap_dispc_unregister_isr(framedone_callback);
 +err1:
 +      enable_clocks(0);
++      dsi_enable_pll_clock(0);
 +err0:
 +      mutex_unlock(&dsi.lock);
 +      DSSDBG("dsi_display_enable FAILED\n");
@@ -5670,11 +6087,9 @@ index 0000000..9f31ac3
 +              goto end;
 +
 +      enable_clocks(1);
++      dsi_enable_pll_clock(1);
 +
-+      if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
-+              dsi_stop_auto_update();
-+      else if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
-+              dsi_wait_for_framedone();
++      dsi_set_update_mode(display, OMAP_DSS_UPDATE_DISABLED);
 +
 +      display->state = OMAP_DSS_DISPLAY_DISABLED;
 +
@@ -5689,7 +6104,7 @@ index 0000000..9f31ac3
 +      dsi_pll_uninit();
 +
 +      enable_clocks(0);
-+
++      dsi_enable_pll_clock(0);
 +end:
 +      mutex_unlock(&dsi.lock);
 +}
@@ -5797,7 +6212,7 @@ index 0000000..9f31ac3
 +      if (dsi.update_mode != OMAP_DSS_UPDATE_MANUAL)
 +              goto end;
 +
-+      r = dsi_wait_for_framedone();
++      r = dsi_wait_for_framedone(0);
 +
 +end:
 +      mutex_unlock(&dsi.lock);
@@ -5814,6 +6229,7 @@ index 0000000..9f31ac3
 +      mutex_lock(&dsi.lock);
 +
 +      r = dsi_set_update_mode(display, mode);
++      dsi.user_update_mode = mode;
 +
 +      mutex_unlock(&dsi.lock);
 +
@@ -5823,26 +6239,19 @@ index 0000000..9f31ac3
 +static enum omap_dss_update_mode dsi_display_get_update_mode(
 +              struct omap_display *display)
 +{
-+      return dsi.update_mode;
++      return dsi.user_update_mode;
 +}
 +
 +static int dsi_display_enable_te(struct omap_display *display, int enable)
 +{
-+      enum omap_dss_update_mode mode;
-+
 +      DSSDBG("dsi_display_enable_te\n");
 +
 +      mutex_lock(&dsi.lock);
 +
 +      enable_clocks(1);
++      dsi_enable_pll_clock(1);
 +
-+      mode = dsi.update_mode;
-+
-+      /* XXX perhaps suspend or something would be better here */
-+      if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
-+              dsi_stop_auto_update();
-+      else if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
-+              dsi_wait_for_framedone();
++      dsi_set_update_mode(display, OMAP_DSS_UPDATE_DISABLED);
 +
 +      dsi.use_te = enable;
 +      display->ctrl->enable_te(display, enable);
@@ -5855,9 +6264,10 @@ index 0000000..9f31ac3
 +      }
 +
 +      /* restore the old update mode */
-+      dsi_set_update_mode(display, mode);
++      dsi_set_update_mode(display, dsi.user_update_mode);
 +
 +      enable_clocks(0);
++      dsi_enable_pll_clock(0);
 +
 +      mutex_unlock(&dsi.lock);
 +
@@ -5871,7 +6281,6 @@ index 0000000..9f31ac3
 +
 +static int dsi_display_run_test(struct omap_display *display, int test_num)
 +{
-+      enum omap_dss_update_mode mode;
 +      int r = 0;
 +
 +      DSSDBG("dsi_display_run_test %d\n", test_num);
@@ -5879,14 +6288,9 @@ index 0000000..9f31ac3
 +      mutex_lock(&dsi.lock);
 +
 +      enable_clocks(1);
++      dsi_enable_pll_clock(1);
 +
-+      mode = dsi.update_mode;
-+
-+      /* XXX perhaps suspend or something would be better here */
-+      if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
-+              dsi_stop_auto_update();
-+      else if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
-+              dsi_wait_for_framedone();
++      dsi_set_update_mode(display, OMAP_DSS_UPDATE_DISABLED);
 +
 +      /* run test first in low speed mode */
 +      dsi_vc_enable_hs(0, 0);
@@ -5919,9 +6323,10 @@ index 0000000..9f31ac3
 +      dsi_vc_enable_hs(0, 1);
 +
 +      /* restore the old update mode */
-+      dsi_set_update_mode(display, mode);
++      dsi_set_update_mode(display, dsi.user_update_mode);
 +
 +      enable_clocks(0);
++      dsi_enable_pll_clock(0);
 +
 +      mutex_unlock(&dsi.lock);
 +
@@ -5953,7 +6358,7 @@ index 0000000..9f31ac3
 +      u32 rev;
 +
 +      init_completion(&dsi.bta_completion);
-+      INIT_WORK(&dsi.framedone_work, framedone_worker);
++      INIT_DELAYED_WORK(&dsi.framedone_work, framedone_worker);
 +
 +      init_completion(&dsi.update_completion);
 +      spin_lock_init(&dsi.update_lock);
@@ -5962,16 +6367,12 @@ index 0000000..9f31ac3
 +
 +      mutex_init(&dsi.lock);
 +
-+      dsi.base = ioremap(DSI_BASE, SZ_1K);
++      dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS);
 +      if (!dsi.base) {
 +              DSSERR("can't ioremap DSI\n");
 +              return -ENOMEM;
 +      }
 +
-+      dsi.dss_ick = get_dss_ick();
-+      dsi.dss1_fck = get_dss1_fck();
-+      dsi.dss2_fck = get_dss2_fck();
-+
 +      enable_clocks(1);
 +
 +      /* Autoidle */
@@ -6006,10 +6407,10 @@ index 0000000..9f31ac3
 +
 diff --git a/arch/arm/plat-omap/dss/dss.c b/arch/arm/plat-omap/dss/dss.c
 new file mode 100644
-index 0000000..8450ddd
+index 0000000..e585fcd
 --- /dev/null
 +++ b/arch/arm/plat-omap/dss/dss.c
-@@ -0,0 +1,554 @@
+@@ -0,0 +1,784 @@
 +/*
 + * linux/arch/arm/plat-omap/dss/dss.c
 + *
@@ -6049,6 +6450,8 @@ index 0000000..8450ddd
 +
 +#define DSS_BASE                      0x48050000
 +
++#define DSS_SZ_REGS                   SZ_512
++
 +struct dss_reg {
 +      u16 idx;
 +};
@@ -6064,6 +6467,9 @@ index 0000000..8450ddd
 +#define DSS_PLL_CONTROL                       DSS_REG(0x0048)
 +#define DSS_SDI_STATUS                        DSS_REG(0x005C)
 +
++#define REG_GET(idx, start, end) \
++      FLD_GET(dss_read_reg(idx), start, end)
++
 +#define REG_FLD_MOD(idx, val, start, end) \
 +      dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
 +
@@ -6075,8 +6481,34 @@ index 0000000..8450ddd
 +      struct clk      *dss2_fck;
 +      struct clk      *dss_54m_fck;
 +      struct clk      *dss_96m_fck;
++
++      unsigned        num_clks_enabled;
++      struct platform_device *pdev;
++      unsigned        ctx_id;
++      u32             ctx[DSS_SZ_REGS / sizeof(u32)];
 +} dss;
 +
++/* PM TESTING */
++#if 1
++static unsigned last_tr_id;
++
++unsigned get_last_off_on_transaction_id(struct device *dev)
++{
++      return last_tr_id;
++}
++
++void inc_last_off_on_transaction_id(void)
++{
++      last_tr_id++;
++}
++#endif
++
++static void dss_clk_enable_all_no_ctx(void);
++static void dss_clk_disable_all_no_ctx(void);
++static void dss_clk_enable_no_ctx(enum dss_clock clks);
++static void dss_clk_disable_no_ctx(enum dss_clock clks);
++static int _omap_dss_wait_reset(void);
++
 +static inline void dss_write_reg(const struct dss_reg idx, u32 val)
 +{
 +      __raw_writel(val, dss.base + idx.idx);
@@ -6087,6 +6519,70 @@ index 0000000..8450ddd
 +      return __raw_readl(dss.base + idx.idx);
 +}
 +
++#define SR(reg) \
++      dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
++#define RR(reg) \
++      dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
++
++static void dss_save_context(void)
++{
++      SR(SYSCONFIG);
++      SR(CONTROL);
++      SR(SDI_CONTROL);
++      SR(PLL_CONTROL);
++}
++
++static void dss_restore_context(void)
++{
++      RR(SYSCONFIG);
++      RR(CONTROL);
++      RR(SDI_CONTROL);
++      RR(PLL_CONTROL);
++}
++
++#undef SR
++#undef RR
++
++unsigned get_last_off_on_transaction_id(struct device *dev);
++
++unsigned dss_get_id(void)
++{
++      return get_last_off_on_transaction_id(&dss.pdev->dev);
++}
++
++static void save_all_ctx(void)
++{
++      //printk("save context\n");
++
++      dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++      dss_save_context();
++      dispc_save_context();
++#ifdef CONFIG_OMAP2_DSS_DSI
++      dsi_save_context();
++#endif
++
++      dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
++}
++
++static void restore_all_ctx(void)
++{
++      //printk("restore context\n");
++
++      dss_clk_enable_all_no_ctx();
++
++      if (_omap_dss_wait_reset())
++              DSSERR("DSS not coming out of reset after sleep\n");
++
++      dss_restore_context();
++      dispc_restore_context();
++#ifdef CONFIG_OMAP2_DSS_DSI
++      dsi_restore_context();
++#endif
++
++      dss_clk_disable_all_no_ctx();
++}
++
 +void dss_sdi_init(int datapairs)
 +{
 +      u32 l;
@@ -6130,6 +6626,35 @@ index 0000000..8450ddd
 +              ;
 +}
 +
++ssize_t dss_print_clocks(char *buf, ssize_t size)
++{
++      ssize_t l = 0;
++      int i;
++      struct clk *clocks[5] = {
++              dss.dss_ick,
++              dss.dss1_fck,
++              dss.dss2_fck,
++              dss.dss_54m_fck,
++              dss.dss_96m_fck
++      };
++
++      l += snprintf(buf + l, size - l, "- dss -\n");
++
++      l += snprintf(buf + l, size - l, "internal clk count\t%u\n",
++                      dss.num_clks_enabled);
++
++      for (i = 0; i < 5; i++) {
++              if (!clocks[i])
++                      continue;
++              l += snprintf(buf + l, size - l, "%-15s\t%lu\t%d\n",
++                              clocks[i]->name,
++                              clk_get_rate(clocks[i]),
++                              clk_get_usecount(clocks[i]));
++      }
++
++      return l;
++}
++
 +static int get_dss_clocks(void)
 +{
 +      const struct {
@@ -6196,49 +6721,135 @@ index 0000000..8450ddd
 +      clk_put(dss.dss_ick);
 +}
 +
-+struct clk *get_dss_ick(void)
++unsigned long dss_clk_get_rate(enum dss_clock clk)
 +{
-+      return dss.dss_ick;
++      switch (clk) {
++      case DSS_CLK_ICK:
++              return clk_get_rate(dss.dss_ick);
++      case DSS_CLK_FCK1:
++              return clk_get_rate(dss.dss1_fck);
++      case DSS_CLK_FCK2:
++              return clk_get_rate(dss.dss2_fck);
++      case DSS_CLK_54M:
++              return clk_get_rate(dss.dss_54m_fck);
++      case DSS_CLK_96M:
++              return clk_get_rate(dss.dss_96m_fck);
++      }
++
++      BUG();
++      return 0;
 +}
 +
-+struct clk *get_dss1_fck(void)
++static unsigned count_clk_bits(enum dss_clock clks)
 +{
-+      return dss.dss1_fck;
++      unsigned num_clks = 0;
++
++      if (clks & DSS_CLK_ICK)
++              ++num_clks;
++      if (clks & DSS_CLK_FCK1)
++              ++num_clks;
++      if (clks & DSS_CLK_FCK2)
++              ++num_clks;
++      if (clks & DSS_CLK_54M)
++              ++num_clks;
++      if (clks & DSS_CLK_96M)
++              ++num_clks;
++
++      return num_clks;
 +}
 +
-+struct clk *get_dss2_fck(void)
++static void dss_clk_enable_no_ctx(enum dss_clock clks)
 +{
-+      return dss.dss2_fck;
++      unsigned num_clks = count_clk_bits(clks);
++
++      if (clks & DSS_CLK_ICK)
++              clk_enable(dss.dss_ick);
++      if (clks & DSS_CLK_FCK1)
++              clk_enable(dss.dss1_fck);
++      if (clks & DSS_CLK_FCK2)
++              clk_enable(dss.dss2_fck);
++      if (clks & DSS_CLK_54M)
++              clk_enable(dss.dss_54m_fck);
++      if (clks & DSS_CLK_96M)
++              clk_enable(dss.dss_96m_fck);
++
++      dss.num_clks_enabled += num_clks;
 +}
 +
-+struct clk *get_tv_fck(void)
++void dss_clk_enable(enum dss_clock clks)
 +{
-+      return dss.dss_54m_fck;
++      int id;
++
++      dss_clk_enable_no_ctx(clks);
++
++      id = dss_get_id();
++
++      if (id != dss.ctx_id) {
++              printk("old id %u, new id %u\n",
++                              dss.ctx_id, id);
++              restore_all_ctx();
++              dss.ctx_id = id;
++      }
 +}
 +
-+struct clk *get_96m_fck(void)
++static void dss_clk_disable_no_ctx(enum dss_clock clks)
 +{
-+      return dss.dss_96m_fck;
++      unsigned num_clks = count_clk_bits(clks);
++
++      if (clks & DSS_CLK_ICK)
++              clk_disable(dss.dss_ick);
++      if (clks & DSS_CLK_FCK1)
++              clk_disable(dss.dss1_fck);
++      if (clks & DSS_CLK_FCK2)
++              clk_disable(dss.dss2_fck);
++      if (clks & DSS_CLK_54M)
++              clk_disable(dss.dss_54m_fck);
++      if (clks & DSS_CLK_96M)
++              clk_disable(dss.dss_96m_fck);
++
++      dss.num_clks_enabled -= num_clks;
 +}
 +
-+static void enable_dss_clocks(void)
++void dss_clk_disable(enum dss_clock clks)
 +{
-+      clk_enable(dss.dss_ick);
-+      clk_enable(dss.dss1_fck);
-+      clk_enable(dss.dss2_fck);
-+      clk_enable(dss.dss_54m_fck);
-+      if (dss.dss_96m_fck)
-+              clk_enable(dss.dss_96m_fck);
++      unsigned num_clks = count_clk_bits(clks);
++
++      BUG_ON(dss.num_clks_enabled < num_clks);
++
++      if (dss.num_clks_enabled == num_clks)
++              save_all_ctx();
++
++      dss_clk_disable_no_ctx(clks);
 +}
 +
-+static void disable_dss_clocks(void)
++static void dss_clk_enable_all_no_ctx(void)
 +{
-+      clk_disable(dss.dss_ick);
-+      clk_disable(dss.dss1_fck);
-+      clk_disable(dss.dss2_fck);
-+      clk_disable(dss.dss_54m_fck);
-+      if (dss.dss_96m_fck)
-+              clk_disable(dss.dss_96m_fck);
++      enum dss_clock clks;
++
++      clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
++      if (cpu_is_omap34xx())
++              clks |= DSS_CLK_96M;
++      dss_clk_enable_no_ctx(clks);
++}
++
++static void dss_clk_disable_all_no_ctx(void)
++{
++      enum dss_clock clks;
++
++      clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
++      if (cpu_is_omap34xx())
++              clks |= DSS_CLK_96M;
++      dss_clk_disable_no_ctx(clks);
++}
++
++static void dss_clk_disable_all(void)
++{
++      enum dss_clock clks;
++
++      clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
++      if (cpu_is_omap34xx())
++              clks |= DSS_CLK_96M;
++      dss_clk_disable(clks);
 +}
 +
 +void dss_select_clk_source(int dsi, int dispc)
@@ -6260,13 +6871,25 @@ index 0000000..8450ddd
 +      return FLD_GET(dss_read_reg(DSS_CONTROL), 0, 0);
 +}
 +
-+static irqreturn_t dss_irq_handler(int irq, void *arg)
++static irqreturn_t dss_irq_handler_omap2(int irq, void *arg)
++{
++      //clk_enable(dss.dss_ick);
++      //clk_enable(dss.dss1_fck);
++
++      dispc_irq_handler();
++
++      //clk_disable(dss.dss1_fck);
++      //clk_disable(dss.dss_ick);
++
++      return IRQ_HANDLED;
++}
++
++static irqreturn_t dss_irq_handler_omap3(int irq, void *arg)
 +{
-+#ifdef CONFIG_ARCH_OMAP3
 +      u32 irqstatus;
 +
-+      clk_enable(dss.dss_ick);
-+      clk_enable(dss.dss1_fck);
++      //clk_enable(dss.dss_ick); // XXX are these needed...
++      //clk_enable(dss.dss1_fck);
 +
 +      irqstatus = dss_read_reg(DSS_IRQSTATUS);
 +
@@ -6276,34 +6899,33 @@ index 0000000..8450ddd
 +      if (irqstatus & (1<<1)) /* DSI_IRQ */
 +              dsi_irq_handler();
 +#endif
-+#else /* OMAP2 */
-+      dispc_irq_handler();
-+#endif
 +
-+      clk_disable(dss.dss1_fck);
-+      clk_disable(dss.dss_ick);
++      //clk_disable(dss.dss1_fck);
++      //clk_disable(dss.dss_ick);
 +
 +      return IRQ_HANDLED;
 +}
 +
-+
-+static int _omap_dss_reset(void)
++static int _omap_dss_wait_reset(void)
 +{
-+      int timeout = 10000;
-+      int r = 0;
-+
-+      /* Soft reset */
-+      REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
++      unsigned timeout = 1000;
 +
-+      while (!(dss_read_reg(DSS_SYSSTATUS) & 1)) {
++      while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
++              udelay(1);
 +              if (!--timeout) {
 +                      DSSERR("soft reset failed\n");
-+                      r = -ENODEV;
-+                      break;
++                      return -ENODEV;
 +              }
 +      }
 +
-+      return r;
++      return 0;
++}
++
++static int _omap_dss_reset(void)
++{
++      /* Soft reset */
++      REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
++      return _omap_dss_wait_reset();
 +}
 +
 +void dss_set_venc_output(enum omap_dss_venc_type type)
@@ -6331,25 +6953,19 @@ index 0000000..8450ddd
 +      int r;
 +      u32 rev;
 +
-+      dss.base = ioremap(DSS_BASE, SZ_512);
++      dss.base = ioremap(DSS_BASE, DSS_SZ_REGS);
 +      if (!dss.base) {
 +              DSSERR("can't ioremap DSS\n");
 +              r = -ENOMEM;
 +              goto fail0;
 +      }
 +
-+      r = get_dss_clocks();
-+      if (r)
-+              goto fail1;
-+
-+      enable_dss_clocks();
-+
 +      /* We need to wait here a bit, otherwise we sometimes start to get
 +       * synclost errors. I believe we could wait for one framedone or
 +       * perhaps vsync interrupt, but, because dispc is not initialized yet,
 +       * we don't have access to the irq register.
 +       */
-+      msleep(40);
++      msleep(400);
 +
 +      _omap_dss_reset();
 +
@@ -6365,24 +6981,25 @@ index 0000000..8450ddd
 +      REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);      /* venc clock mode = normal */
 +#endif
 +
-+      r = request_irq(INT_24XX_DSS_IRQ, dss_irq_handler,
++      r = request_irq(INT_24XX_DSS_IRQ,
++                      cpu_is_omap24xx()
++                      ? dss_irq_handler_omap2
++                      : dss_irq_handler_omap3,
 +                      0, "OMAP DSS", NULL);
 +
 +      if (r < 0) {
 +              DSSERR("omap2 dss: request_irq failed\n");
-+              goto fail2;
++              goto fail1;
 +      }
 +
++      dss_save_context();
++
 +      rev = dss_read_reg(DSS_REVISION);
 +      printk(KERN_INFO "OMAP DSS rev %d.%d\n",
 +                      FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
 +
-+      disable_dss_clocks();
 +      return 0;
 +
-+fail2:
-+      disable_dss_clocks();
-+      put_dss_clocks();
 +fail1:
 +      iounmap(dss.base);
 +fail0:
@@ -6447,6 +7064,17 @@ index 0000000..8450ddd
 +
 +      int r;
 +
++      dss.pdev = pdev;
++
++      r = get_dss_clocks();
++      if (r)
++              goto fail0;
++
++      dss_clk_enable_all_no_ctx();
++
++      dss.ctx_id = dss_get_id();
++      printk("initial id %u\n", dss.ctx_id);
++
 +      r = dss_init();
 +      if (r) {
 +              DSSERR("Failed to initialize DSS\n");
@@ -6504,8 +7132,11 @@ index 0000000..8450ddd
 +
 +      initialize_overlays();
 +
++      dss_clk_disable_all();
++
 +      return 0;
 +
++      /* XXX fail correctly */
 +fail0:
 +      return r;
 +}
@@ -6566,10 +7197,10 @@ index 0000000..8450ddd
 +
 diff --git a/arch/arm/plat-omap/dss/dss.h b/arch/arm/plat-omap/dss/dss.h
 new file mode 100644
-index 0000000..28929b9
+index 0000000..04abdc6
 --- /dev/null
 +++ b/arch/arm/plat-omap/dss/dss.h
-@@ -0,0 +1,254 @@
+@@ -0,0 +1,268 @@
 +/*
 + * linux/arch/arm/plat-omap/dss/dss.h
 + *
@@ -6661,6 +7292,14 @@ index 0000000..28929b9
 +      OMAP_DSS_PARALLELMODE_DSI,
 +};
 +
++enum dss_clock {
++      DSS_CLK_ICK     = 1 << 0,
++      DSS_CLK_FCK1    = 1 << 1,
++      DSS_CLK_FCK2    = 1 << 2,
++      DSS_CLK_54M     = 1 << 3,
++      DSS_CLK_96M     = 1 << 4,
++};
++
 +struct dispc_clock_info {
 +      /* rates that we get with dividers below */
 +      unsigned long fck;
@@ -6705,18 +7344,17 @@ index 0000000..28929b9
 +int dss_init(void);
 +void dss_exit(void);
 +
++void dss_clk_enable(enum dss_clock clks);
++void dss_clk_disable(enum dss_clock clks);
++
 +void dss_sdi_init(int datapairs);
 +void dss_select_clk_source(int dsi, int dispc);
 +int dss_get_dsi_clk_source(void);
 +int dss_get_dispc_clk_source(void);
 +void dss_set_venc_output(enum omap_dss_venc_type type);
 +void dss_set_dac_pwrdn_bgz(int enable);
-+
-+struct clk *get_dss_ick(void);
-+struct clk *get_dss1_fck(void);
-+struct clk *get_dss2_fck(void);
-+struct clk *get_tv_fck(void);
-+struct clk *get_96m_fck(void);
++unsigned long dss_clk_get_rate(enum dss_clock clk);
++ssize_t dss_print_clocks(char *buf, ssize_t size);
 +
 +/* SDI */
 +int sdi_init(void);
@@ -6727,6 +7365,10 @@ index 0000000..28929b9
 +/* DSI */
 +int dsi_init(void);
 +void dsi_exit(void);
++
++void dsi_save_context(void);
++void dsi_restore_context(void);
++
 +void dsi_init_display(struct omap_display *display);
 +void dsi_irq_handler(void);
 +unsigned long dsi_get_dsi1_pll_rate(void);
@@ -6749,6 +7391,9 @@ index 0000000..28929b9
 +void dispc_irq_handler(void);
 +void dispc_fake_vsync_irq(void);
 +
++void dispc_save_context(void);
++void dispc_restore_context(void);
++
 +void dispc_lcd_enable_signal_polarity(int act_high);
 +void dispc_lcd_enable_signal(int enable);
 +void dispc_pck_free_enable(int enable);
@@ -6826,10 +7471,10 @@ index 0000000..28929b9
 +#endif
 diff --git a/arch/arm/plat-omap/dss/rfbi.c b/arch/arm/plat-omap/dss/rfbi.c
 new file mode 100644
-index 0000000..31ddd24
+index 0000000..eaf6e2c
 --- /dev/null
 +++ b/arch/arm/plat-omap/dss/rfbi.c
-@@ -0,0 +1,1234 @@
+@@ -0,0 +1,1225 @@
 +/*
 + * linux/arch/arm/plat-omap/dss/rfbi.c
 + *
@@ -6938,9 +7583,6 @@ index 0000000..31ddd24
 +static struct {
 +      void __iomem    *base;
 +
-+      struct clk      *dss_ick;
-+      struct clk      *dss1_fck;
-+
 +      unsigned long   l4_khz;
 +
 +      enum omap_rfbi_datatype datatype;
@@ -6993,13 +7635,10 @@ index 0000000..31ddd24
 +
 +static void rfbi_enable_clocks(int enable)
 +{
-+      if (enable) {
-+              clk_enable(rfbi.dss_ick);
-+              clk_enable(rfbi.dss1_fck);
-+      } else {
-+              clk_disable(rfbi.dss1_fck);
-+              clk_disable(rfbi.dss_ick);
-+      }
++      if (enable)
++              dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++      else
++              dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
 +}
 +
 +void omap_rfbi_write_command(const void *buf, u32 len)
@@ -7363,7 +8002,7 @@ index 0000000..31ddd24
 +      };
 +
 +      l4_rate = rfbi.l4_khz / 1000;
-+      dss1_rate = clk_get_rate(rfbi.dss1_fck) / 1000000;
++      dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000;
 +
 +      for (i = 0; i < ARRAY_SIZE(ftab); i++) {
 +              /* Use a window instead of an exact match, to account
@@ -7929,14 +8568,11 @@ index 0000000..31ddd24
 +              return -ENOMEM;
 +      }
 +
-+      rfbi.dss_ick = get_dss_ick();
-+      rfbi.dss1_fck = get_dss1_fck();
-+
 +      rfbi_enable_clocks(1);
 +
 +      msleep(10);
 +
-+      rfbi.l4_khz = clk_get_rate(rfbi.dss_ick) / 1000;
++      rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
 +
 +      /* Enable autoidle and smart-idle */
 +      l = rfbi_read_reg(RFBI_SYSCONFIG);
@@ -8066,10 +8702,10 @@ index 0000000..31ddd24
 +}
 diff --git a/arch/arm/plat-omap/dss/sdi.c b/arch/arm/plat-omap/dss/sdi.c
 new file mode 100644
-index 0000000..de19d47
+index 0000000..8d5b16d
 --- /dev/null
 +++ b/arch/arm/plat-omap/dss/sdi.c
-@@ -0,0 +1,157 @@
+@@ -0,0 +1,150 @@
 +/*
 + * linux/arch/arm/plat-omap/dss/sdi.c
 + *
@@ -8102,8 +8738,6 @@ index 0000000..de19d47
 +
 +
 +static struct {
-+      struct clk      *dss_ick;
-+      struct clk      *dss1_fck;
 +      int update_enabled;
 +} sdi;
 +
@@ -8118,8 +8752,7 @@ index 0000000..de19d47
 +
 +      panel->enable(display);
 +
-+      clk_enable(sdi.dss_ick);
-+      clk_enable(sdi.dss1_fck);
++      dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
 +
 +      dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
 +      dispc_set_lcd_size(display->x_res, display->y_res);
@@ -8167,8 +8800,7 @@ index 0000000..de19d47
 +      display->panel->disable(display);
 +      dispc_enable_lcd_out(0);
 +
-+      clk_disable(sdi.dss_ick);
-+      clk_disable(sdi.dss1_fck);
++      dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
 +}
 +
 +static void sdi_display_set_mode(struct omap_display *display,
@@ -8218,9 +8850,6 @@ index 0000000..de19d47
 +
 +int sdi_init(void)
 +{
-+      sdi.dss_ick = get_dss_ick();
-+      sdi.dss1_fck = get_dss1_fck();
-+
 +      return 0;
 +}
 +
@@ -8229,10 +8858,10 @@ index 0000000..de19d47
 +}
 diff --git a/arch/arm/plat-omap/dss/venc.c b/arch/arm/plat-omap/dss/venc.c
 new file mode 100644
-index 0000000..2ed68b5
+index 0000000..7afb2c5
 --- /dev/null
 +++ b/arch/arm/plat-omap/dss/venc.c
-@@ -0,0 +1,515 @@
+@@ -0,0 +1,501 @@
 +/*
 + * linux/arch/arm/plat-omap/dss/venc.c
 + *
@@ -8505,10 +9134,6 @@ index 0000000..2ed68b5
 +
 +static struct {
 +      void __iomem *base;
-+      struct clk *dss_54m_fck;
-+      struct clk *dss_96m_fck;
-+      struct clk *dss_ick;
-+      struct clk *dss1_fck;
 +      const struct venc_config *config;
 +      struct mutex venc_lock;
 +} venc;
@@ -8601,17 +9226,12 @@ index 0000000..2ed68b5
 +
 +static void venc_enable_clocks(int enable)
 +{
-+      if (enable) {
-+              clk_enable(venc.dss_ick);
-+              clk_enable(venc.dss1_fck);
-+              clk_enable(venc.dss_54m_fck);
-+              clk_enable(venc.dss_96m_fck);
-+      } else {
-+              clk_disable(venc.dss_96m_fck);
-+              clk_disable(venc.dss_54m_fck);
-+              clk_disable(venc.dss1_fck);
-+              clk_disable(venc.dss_ick);
-+      }
++      if (enable)
++              dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
++                              DSS_CLK_96M);
++      else
++              dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
++                              DSS_CLK_96M);
 +}
 +
 +int venc_init(void)
@@ -8635,11 +9255,6 @@ index 0000000..2ed68b5
 +              return -ENOMEM;
 +      }
 +
-+      venc.dss_ick = get_dss_ick();
-+      venc.dss1_fck = get_dss1_fck();
-+      venc.dss_54m_fck = get_tv_fck();
-+      venc.dss_96m_fck = get_96m_fck();
-+
 +      /* enable clocks */
 +      venc_enable_clocks(1);
 +
@@ -8750,10 +9365,10 @@ index 0000000..2ed68b5
 +}
 diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
 new file mode 100644
-index 0000000..2e55fae
+index 0000000..95f5b3a
 --- /dev/null
 +++ b/arch/arm/plat-omap/include/mach/display.h
-@@ -0,0 +1,458 @@
+@@ -0,0 +1,463 @@
 +/*
 + * linux/include/asm-arm/arch-omap/display.h
 + *
@@ -8973,6 +9588,8 @@ index 0000000..2e55fae
 +      void (*panel_disable)(struct omap_display *display);
 +      int (*ctrl_enable)(struct omap_display *display);
 +      void (*ctrl_disable)(struct omap_display *display);
++      int (*set_backlight)(struct omap_display *display,
++                      int level);
 +};
 +
 +/* Board specific data */
@@ -8999,6 +9616,9 @@ index 0000000..2e55fae
 +
 +      int (*enable_te)(struct omap_display *display, int enable);
 +
++      int (*rotate)(struct omap_display *display, int rotate);
++      int (*mirror)(struct omap_display *display, int enable);
++
 +      int (*run_test)(struct omap_display *display, int test);
 +
 +      int bpp;
index b9a56af..b5cf7e8 100644 (file)
@@ -1,22 +1,25 @@
-From 36ac3fa1184b392dc54024de6d98e4355f2baba8 Mon Sep 17 00:00:00 2001
+From ecdfbac90a49f517c7d5132e44522b089123b413 Mon Sep 17 00:00:00 2001
 From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
 Date: Tue, 4 Nov 2008 15:12:21 +0200
 Subject: [PATCH] DSS: OMAPFB: fb driver for new display subsystem
 
 Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
 ---
- arch/arm/plat-omap/fb.c                  |    9 +-
- arch/arm/plat-omap/include/mach/omapfb.h |    7 +
+ arch/arm/plat-omap/Makefile              |    2 +-
+ arch/arm/plat-omap/fb-vram.c             |  498 +++++++++++
+ arch/arm/plat-omap/fb.c                  |   33 +-
+ arch/arm/plat-omap/include/mach/omapfb.h |   14 +
  drivers/video/Kconfig                    |    1 +
  drivers/video/Makefile                   |    1 +
  drivers/video/omap/Kconfig               |    5 +-
- drivers/video/omap2/Kconfig              |   29 +
+ drivers/video/omap2/Kconfig              |   38 +
  drivers/video/omap2/Makefile             |    2 +
- drivers/video/omap2/omapfb-ioctl.c       |  428 ++++++++++
- drivers/video/omap2/omapfb-main.c        | 1276 ++++++++++++++++++++++++++++++
- drivers/video/omap2/omapfb-sysfs.c       |  833 +++++++++++++++++++
- drivers/video/omap2/omapfb.h             |  104 +++
- 11 files changed, 2692 insertions(+), 3 deletions(-)
+ drivers/video/omap2/omapfb-ioctl.c       |  462 ++++++++++
+ drivers/video/omap2/omapfb-main.c        | 1382 ++++++++++++++++++++++++++++++
+ drivers/video/omap2/omapfb-sysfs.c       |  838 ++++++++++++++++++
+ drivers/video/omap2/omapfb.h             |  109 +++
+ 13 files changed, 3377 insertions(+), 8 deletions(-)
+ create mode 100644 arch/arm/plat-omap/fb-vram.c
  create mode 100644 drivers/video/omap2/Kconfig
  create mode 100644 drivers/video/omap2/Makefile
  create mode 100644 drivers/video/omap2/omapfb-ioctl.c
@@ -24,24 +27,588 @@ Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
  create mode 100644 drivers/video/omap2/omapfb-sysfs.c
  create mode 100644 drivers/video/omap2/omapfb.h
 
+diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
+index 2740497..7d602a6 100644
+--- a/arch/arm/plat-omap/Makefile
++++ b/arch/arm/plat-omap/Makefile
+@@ -4,7 +4,7 @@
+ # Common support
+ obj-y := common.o sram.o clock.o devices.o dma.o mux.o gpio.o \
+-       usb.o fb.o io.o
++       usb.o fb.o fb-vram.o io.o
+ obj-m :=
+ obj-n :=
+ obj-  :=
+diff --git a/arch/arm/plat-omap/fb-vram.c b/arch/arm/plat-omap/fb-vram.c
+new file mode 100644
+index 0000000..de24503
+--- /dev/null
++++ b/arch/arm/plat-omap/fb-vram.c
+@@ -0,0 +1,498 @@
++/*
++ * linux/arch/arm/plat-omap/fb-vram.c
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++//#define DEBUG
++
++#include <linux/vmalloc.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/list.h>
++#include <linux/dma-mapping.h>
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++
++#include <mach/omapfb.h>
++
++#ifdef DEBUG
++#define DBG(format, ...) printk(KERN_DEBUG "VRAM: " format, ## __VA_ARGS__)
++#else
++#define DBG(format, ...)
++#endif
++
++#define OMAP2_SRAM_START              0x40200000
++/* Maximum size, in reality this is smaller if SRAM is partially locked. */
++#define OMAP2_SRAM_SIZE                       0xa0000         /* 640k */
++
++#define REG_MAP_SIZE(_page_cnt)                                               \
++      ((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8)
++#define REG_MAP_PTR(_rg, _page_nr)                                    \
++      (((_rg)->map) + (_page_nr) / (sizeof(unsigned long) * 8))
++#define REG_MAP_MASK(_page_nr)                                                \
++      (1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1)))
++
++#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) \
++      || defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
++
++/* postponed regions are used to temporarily store region information at boot
++ * time when we cannot yet allocate the region list */
++#define MAX_POSTPONED_REGIONS 10
++
++static int postponed_cnt __initdata;
++static struct {
++      unsigned long paddr;
++      size_t size;
++} postponed_regions[MAX_POSTPONED_REGIONS] __initdata;
++
++struct vram_alloc {
++      struct list_head list;
++      unsigned long paddr;
++      unsigned pages;
++};
++
++struct vram_region {
++      struct list_head list;
++      struct list_head alloc_list;
++      unsigned long   paddr;
++      void            *vaddr;
++      unsigned        pages;
++      unsigned        dma_alloced:1;
++};
++
++static DEFINE_MUTEX(region_mutex);
++static LIST_HEAD(region_list);
++
++static inline int region_mem_type(unsigned long paddr)
++{
++      if (paddr >= OMAP2_SRAM_START &&
++          paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
++              return OMAPFB_MEMTYPE_SRAM;
++      else
++              return OMAPFB_MEMTYPE_SDRAM;
++}
++
++static struct vram_region *omap_vram_create_region(unsigned long paddr,
++              void *vaddr, unsigned pages)
++{
++      struct vram_region *rm;
++
++      rm = kzalloc(sizeof(*rm), GFP_KERNEL);
++
++      if (rm) {
++              INIT_LIST_HEAD(&rm->alloc_list);
++              rm->paddr = paddr;
++              rm->vaddr = vaddr;
++              rm->pages = pages;
++      }
++
++      return rm;
++}
++
++static void omap_vram_free_region(struct vram_region *vr)
++{
++      list_del(&vr->list);
++      kfree(vr);
++}
++
++static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr,
++              unsigned long paddr, unsigned pages)
++{
++      struct vram_alloc *va;
++      struct vram_alloc *new;
++
++      new = kzalloc(sizeof(*va), GFP_KERNEL);
++
++      if (!new)
++              return NULL;
++
++      new->paddr = paddr;
++      new->pages = pages;
++
++      list_for_each_entry(va, &vr->alloc_list, list) {
++              if (va->paddr > new->paddr)
++                      break;
++      }
++
++      list_add_tail(&new->list, &va->list);
++
++      return new;
++}
++
++static void omap_vram_free_allocation(struct vram_alloc *va)
++{
++      list_del(&va->list);
++      kfree(va);
++}
++
++__init int omap_vram_add_region_postponed(unsigned long paddr, size_t size)
++{
++      if (postponed_cnt == MAX_POSTPONED_REGIONS)
++              return -ENOMEM;
++
++      postponed_regions[postponed_cnt].paddr = paddr;
++      postponed_regions[postponed_cnt].size = size;
++
++      ++postponed_cnt;
++
++      return 0;
++}
++
++/* add/remove_region can be exported if there's need to add/remove regions
++ * runtime */
++static int omap_vram_add_region(unsigned long paddr, size_t size)
++{
++      struct vram_region *rm;
++      void *vaddr;
++      unsigned pages;
++
++      DBG("adding region paddr %08lx size %d\n",
++                      paddr, size);
++
++      size &= PAGE_MASK;
++      pages = size >> PAGE_SHIFT;
++
++      vaddr = ioremap_wc(paddr, size);
++      if (vaddr == NULL)
++              return -ENOMEM;
++
++      rm = omap_vram_create_region(paddr, vaddr, pages);
++      if (rm == NULL) {
++              iounmap(vaddr);
++              return -ENOMEM;
++      }
++
++      list_add(&rm->list, &region_list);
++
++      return 0;
++}
++
++#if 0
++int omap_vram_remove_region(unsigned long paddr)
++{
++      struct region *rm;
++      unsigned i;
++
++      DBG("remove region paddr %08lx\n", paddr);
++      list_for_each_entry(rm, &region_list, list)
++              if (rm->paddr != paddr)
++                      continue;
++
++      if (rm->paddr != paddr)
++              return -EINVAL;
++
++      for (i = 0; i < rm->page_cnt; i++)
++              if (region_page_reserved(rm, i))
++                      return -EBUSY;
++
++      iounmap(rm->vaddr);
++
++      list_del(&rm->list);
++
++      kfree(rm);
++
++      return 0;
++}
++#endif
++
++int omap_vram_free(unsigned long paddr, void *vaddr, size_t size)
++{
++      struct vram_region *rm;
++      struct vram_alloc *alloc;
++      unsigned start, end;
++
++      DBG("free mem paddr %08lx vaddr %p size %d\n",
++                      paddr, vaddr, size);
++
++      size = PAGE_ALIGN(size);
++
++      mutex_lock(&region_mutex);
++
++      list_for_each_entry(rm, &region_list, list) {
++              list_for_each_entry(alloc, &rm->alloc_list, list) {
++                      start = alloc->paddr;
++                      end = alloc->paddr + (alloc->pages >> PAGE_SHIFT);
++
++                      if (start >= paddr && end < paddr + size)
++                              goto found;
++              }
++      }
++
++      mutex_unlock(&region_mutex);
++      return -EINVAL;
++
++found:
++      if (rm->dma_alloced) {
++              DBG("freeing dma-alloced\n");
++              dma_free_writecombine(NULL, size, vaddr, paddr);
++              omap_vram_free_allocation(alloc);
++              omap_vram_free_region(rm);
++      } else {
++              omap_vram_free_allocation(alloc);
++      }
++
++      mutex_unlock(&region_mutex);
++      return 0;
++}
++EXPORT_SYMBOL(omap_vram_free);
++
++#if 0
++void *omap_vram_reserve(unsigned long paddr, size_t size)
++{
++
++      struct region *rm;
++      unsigned start_page;
++      unsigned end_page;
++      unsigned i;
++      void *vaddr;
++
++      size = PAGE_ALIGN(size);
++
++      rm = region_find_region(paddr, size);
++
++      DBG("reserve mem paddr %08lx size %d\n",
++                      paddr, size);
++
++      BUG_ON(rm == NULL);
++
++      start_page = (paddr - rm->paddr) >> PAGE_SHIFT;
++      end_page = start_page + (size >> PAGE_SHIFT);
++      for (i = start_page; i < end_page; i++)
++              region_reserve_page(rm, i);
++
++      vaddr = rm->vaddr + (start_page << PAGE_SHIFT);
++
++      return vaddr;
++}
++EXPORT_SYMBOL(omap_vram_reserve);
++#endif
++static void *_omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr)
++{
++      struct vram_region *rm;
++      struct vram_alloc *alloc;
++      void *vaddr;
++
++      list_for_each_entry(rm, &region_list, list) {
++              unsigned long start, end;
++
++              DBG("checking region %lx %d\n", rm->paddr, rm->pages);
++
++              if (region_mem_type(rm->paddr) != mtype)
++                      continue;
++
++              start = rm->paddr;
++
++              list_for_each_entry(alloc, &rm->alloc_list, list) {
++                      end = alloc->paddr;
++
++                      if (end - start >= pages << PAGE_SHIFT)
++                              goto found;
++
++                      start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
++              }
++
++              end = rm->paddr + (rm->pages << PAGE_SHIFT);
++found:
++              if (end - start < pages << PAGE_SHIFT)
++                      continue;
++
++              DBG("FOUND %lx, end %lx\n", start, end);
++
++              if (omap_vram_create_allocation(rm, start, pages) == NULL)
++                      return NULL;
++
++              *paddr = start;
++              vaddr = rm->vaddr + (start - rm->paddr);
++
++              return vaddr;
++      }
++
++      return NULL;
++}
++
++static void *_omap_vram_alloc_dma(unsigned pages, unsigned long *paddr)
++{
++      struct vram_region *rm;
++      void *vaddr;
++
++      vaddr = dma_alloc_writecombine(NULL, pages << PAGE_SHIFT,
++                      (dma_addr_t *)paddr, GFP_KERNEL);
++
++      if (vaddr == NULL)
++              return NULL;
++
++      rm = omap_vram_create_region(*paddr, vaddr, pages);
++      if (rm == NULL) {
++              dma_free_writecombine(NULL, pages << PAGE_SHIFT, vaddr,
++                              (dma_addr_t)*paddr);
++              return NULL;
++      }
++
++      rm->dma_alloced = 1;
++
++      if (omap_vram_create_allocation(rm, *paddr, pages) == NULL) {
++              dma_free_writecombine(NULL, pages << PAGE_SHIFT, vaddr,
++                              (dma_addr_t)*paddr);
++              kfree(rm);
++              return NULL;
++      }
++
++      list_add(&rm->list, &region_list);
++
++      return vaddr;
++}
++
++void *omap_vram_alloc(int mtype, size_t size, unsigned long *paddr)
++{
++      void *vaddr;
++      unsigned pages;
++
++      BUG_ON(mtype > OMAPFB_MEMTYPE_MAX || !size);
++
++      DBG("alloc mem type %d size %d\n", mtype, size);
++
++      size = PAGE_ALIGN(size);
++      pages = size >> PAGE_SHIFT;
++
++      mutex_lock(&region_mutex);
++
++      vaddr = _omap_vram_alloc(mtype, pages, paddr);
++
++      if (vaddr == NULL && mtype == OMAPFB_MEMTYPE_SDRAM) {
++              DBG("fallback to dma_alloc\n");
++
++              vaddr = _omap_vram_alloc_dma(pages, paddr);
++      }
++
++      mutex_unlock(&region_mutex);
++
++      return vaddr;
++}
++EXPORT_SYMBOL(omap_vram_alloc);
++
++#ifdef CONFIG_PROC_FS
++static void *r_next(struct seq_file *m, void *v, loff_t *pos)
++{
++      struct list_head *l = v;
++
++      (*pos)++;
++
++      if (list_is_last(l, &region_list))
++              return 0;
++
++      return l->next;
++}
++
++static void *r_start(struct seq_file *m, loff_t *pos)
++{
++      loff_t p = *pos;
++      struct list_head *l = &region_list;
++
++      mutex_lock(&region_mutex);
++
++      do {
++              l = l->next;
++              if (l == &region_list)
++                      return NULL;
++      } while (p--);
++
++      return l;
++}
++
++static void r_stop(struct seq_file *m, void *v)
++{
++      mutex_unlock(&region_mutex);
++}
++
++static int r_show(struct seq_file *m, void *v)
++{
++      struct vram_region *vr;
++      struct vram_alloc *va;
++      unsigned size;
++
++      vr = list_entry(v, struct vram_region, list);
++
++      size = vr->pages << PAGE_SHIFT;
++      seq_printf(m, "%08lx-%08lx v:%p-%p (%d bytes) %s\n",
++                      vr->paddr, vr->paddr + size,
++                      vr->vaddr, vr->vaddr + size,
++                      size,
++                      vr->dma_alloced ? "dma_alloc" : "");
++
++      list_for_each_entry(va, &vr->alloc_list, list) {
++              size = va->pages << PAGE_SHIFT;
++              seq_printf(m, "    %08lx-%08lx (%d bytes)\n",
++                              va->paddr, va->paddr + size,
++                              size);
++      }
++
++
++
++      return 0;
++}
++
++static const struct seq_operations resource_op = {
++      .start  = r_start,
++      .next   = r_next,
++      .stop   = r_stop,
++      .show   = r_show,
++};
++
++static int vram_open(struct inode *inode, struct file *file)
++{
++      return seq_open(file, &resource_op);
++}
++
++static const struct file_operations proc_vram_operations = {
++      .open           = vram_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = seq_release,
++};
++
++static int __init omap_vram_create_proc(void)
++{
++      proc_create("omap-vram", 0, NULL, &proc_vram_operations);
++
++      return 0;
++}
++#endif
++
++static __init int omap_vram_init(void)
++{
++      int i, r;
++
++      for (i = 0; i < postponed_cnt; i++)
++              omap_vram_add_region(postponed_regions[i].paddr,
++                              postponed_regions[i].size);
++
++#ifdef CONFIG_PROC_FS
++      r = omap_vram_create_proc();
++      if (r)
++              return -ENOMEM;
++#endif
++
++      return 0;
++}
++
++arch_initcall(omap_vram_init);
++
++#endif
++
 diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
-index 3746222..0ba1603 100644
+index 3746222..da528d0 100644
 --- a/arch/arm/plat-omap/fb.c
 +++ b/arch/arm/plat-omap/fb.c
-@@ -36,7 +36,8 @@
+@@ -36,7 +36,11 @@
  #include <mach/sram.h>
  #include <mach/omapfb.h>
  
 -#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
 +#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) \
 +      || defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
++
++static int omapfb_vram_count;
++static struct omap_fbmem_config *omapfb_vram_config;
  
  static struct omapfb_platform_data omapfb_config;
  static int config_invalid;
-@@ -298,14 +299,18 @@ unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+@@ -95,11 +99,11 @@ static int get_fbmem_region(int region_idx, struct omapfb_mem_region *rg)
+       const struct omap_fbmem_config  *conf;
+       u32                             paddr;
+-      conf = omap_get_nr_config(OMAP_TAG_FBMEM,
+-                                struct omap_fbmem_config, region_idx);
+-      if (conf == NULL)
++      if (region_idx >= omapfb_vram_count)
+               return -ENOENT;
++      conf = &omapfb_vram_config[region_idx];
++
+       paddr = conf->start;
+       /*
+        * Low bits encode the page allocation mode, if high bits
+@@ -209,6 +213,13 @@ void __init omapfb_reserve_sdram(void)
+               if (rg.paddr) {
+                       reserve_bootmem(rg.paddr, rg.size, BOOTMEM_DEFAULT);
+                       reserved += rg.size;
++                      omap_vram_add_region_postponed(rg.paddr, rg.size);
++              } else {
++                      void *vaddr;
++                      vaddr = alloc_bootmem(rg.size);
++                      rg.paddr = virt_to_phys(vaddr);
++                      reserved += rg.size;
++                      omap_vram_add_region_postponed(rg.paddr, rg.size);
+               }
+               omapfb_config.mem_desc.region[i] = rg;
+               configured_regions++;
+@@ -229,7 +240,7 @@ void __init omapfb_reserve_sdram(void)
+  * this point, since the driver built as a module would have problem with
+  * freeing / reallocating the regions.
+  */
+-unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
++unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
+                                 unsigned long sram_vstart,
+                                 unsigned long sram_size,
+                                 unsigned long pstart_avail,
+@@ -298,14 +309,24 @@ unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
        return reserved;
  }
  
++void __init omapfb_set_vram_config(struct omap_fbmem_config *config, int count)
++{
++      omapfb_vram_count = count;
++      omapfb_vram_config = config;
++}
++
 +#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
  void omapfb_set_ctrl_platform_data(void *data)
  {
@@ -57,7 +624,7 @@ index 3746222..0ba1603 100644
  
        if (config_invalid)
                return 0;
-@@ -313,6 +318,7 @@ static inline int omap_init_fb(void)
+@@ -313,6 +334,7 @@ static inline int omap_init_fb(void)
                printk(KERN_ERR "Invalid FB mem configuration entries\n");
                return 0;
        }
@@ -65,7 +632,7 @@ index 3746222..0ba1603 100644
        conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
        if (conf == NULL) {
                if (configured_regions)
-@@ -321,6 +327,7 @@ static inline int omap_init_fb(void)
+@@ -321,6 +343,7 @@ static inline int omap_init_fb(void)
                return 0;
        }
        omapfb_config.lcd = *conf;
@@ -74,7 +641,7 @@ index 3746222..0ba1603 100644
        return platform_device_register(&omap_fb_device);
  }
 diff --git a/arch/arm/plat-omap/include/mach/omapfb.h b/arch/arm/plat-omap/include/mach/omapfb.h
-index 90d63c5..1e34304 100644
+index 90d63c5..277e3cf 100644
 --- a/arch/arm/plat-omap/include/mach/omapfb.h
 +++ b/arch/arm/plat-omap/include/mach/omapfb.h
 @@ -90,6 +90,13 @@ enum omapfb_color_format {
@@ -91,6 +658,20 @@ index 90d63c5..1e34304 100644
  };
  
  struct omapfb_update_window {
+@@ -392,6 +399,13 @@ extern int  omapfb_update_window_async(struct fb_info *fbi,
+ /* in arch/arm/plat-omap/fb.c */
+ extern void omapfb_set_ctrl_platform_data(void *pdata);
++extern void omapfb_set_vram_config(struct omap_fbmem_config *config, int count);
++
++/* in arch/arm/plat-omap/fb-vram */
++__init int omap_vram_add_region_postponed(unsigned long paddr, size_t size);
++int omap_vram_free(unsigned long paddr, void *vaddr, size_t size);
++void *omap_vram_reserve(unsigned long paddr, size_t size);
++void *omap_vram_alloc(int mtype, size_t size, unsigned long *paddr);
+ #endif /* __KERNEL__ */
 diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
 index 3f3ce13..689a3b1 100644
 --- a/drivers/video/Kconfig
@@ -139,10 +720,10 @@ index c355b59..541fab3 100644
        help
 diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
 new file mode 100644
-index 0000000..4b72479
+index 0000000..bfa1617
 --- /dev/null
 +++ b/drivers/video/omap2/Kconfig
-@@ -0,0 +1,29 @@
+@@ -0,0 +1,38 @@
 +config FB_OMAP2
 +        tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)"
 +        depends on FB && OMAP2_DSS
@@ -166,6 +747,15 @@ index 0000000..4b72479
 +        displays that support manual update are started in manual
 +        update mode.
 +
++config FB_OMAP2_NUM_FBS
++      int "Number of framebuffers"
++      range 1 10
++      default 3
++      depends on FB_OMAP2
++      help
++        Select the number of framebuffers created. OMAP2/3 has 3 overlays
++        so normally this would be 3.
++
 +menu "OMAP2/3 Display Device Drivers"
 +        depends on OMAP2_DSS
 +
@@ -182,10 +772,10 @@ index 0000000..51c2e00
 +omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
 diff --git a/drivers/video/omap2/omapfb-ioctl.c b/drivers/video/omap2/omapfb-ioctl.c
 new file mode 100644
-index 0000000..1ceb6b9
+index 0000000..6bf750f
 --- /dev/null
 +++ b/drivers/video/omap2/omapfb-ioctl.c
-@@ -0,0 +1,428 @@
+@@ -0,0 +1,462 @@
 +/*
 + * linux/drivers/video/omap2/omapfb-ioctl.c
 + *
@@ -212,6 +802,7 @@ index 0000000..1ceb6b9
 +#include <linux/device.h>
 +#include <linux/uaccess.h>
 +#include <linux/platform_device.h>
++#include <linux/mm.h>
 +
 +#include <mach/display.h>
 +#include <mach/omapfb.h>
@@ -228,23 +819,16 @@ index 0000000..1ceb6b9
 +
 +      DBG("omapfb_setup_plane\n");
 +
++      omapfb_lock(fbdev);
++
 +      if (ofbi->num_overlays != 1) {
 +              r = -EINVAL;
 +              goto out;
 +      }
 +
++      /* XXX uses only the first overlay */
 +      ovl = ofbi->overlays[0];
 +
-+      omapfb_lock(fbdev);
-+
-+      if (display) {
-+              if (pi->pos_x + pi->out_width > display->x_res ||
-+                              pi->pos_y + pi->out_height > display->y_res) {
-+                      r = -EINVAL;
-+                      goto out;
-+              }
-+      }
-+
 +      if (pi->enabled && !ofbi->region.size) {
 +              /*
 +               * This plane's memory was freed, can't enable it
@@ -254,9 +838,11 @@ index 0000000..1ceb6b9
 +              goto out;
 +      }
 +
-+      if (!ovl) {
-+              r = -EINVAL;
-+              goto out;
++      if (pi->enabled) {
++              r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
++                              pi->out_width, pi->out_height);
++              if (r)
++                      goto out;
 +      }
 +
 +      r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
@@ -320,24 +906,62 @@ index 0000000..1ceb6b9
 +      struct omapfb_info *ofbi = FB2OFB(fbi);
 +      struct omapfb2_device *fbdev = ofbi->fbdev;
 +      struct omapfb_mem_region *rg;
-+      int ret = -EINVAL;
++      struct omap_display *display = fb2display(fbi);
++      int r, i;
++      size_t size;
++
++      if (mi->type > OMAPFB_MEMTYPE_MAX)
++              return -EINVAL;
++
++      size = PAGE_ALIGN(mi->size);
 +
 +      rg = &ofbi->region;
 +
 +      omapfb_lock(fbdev);
-+      if (mi->size > rg->size) {
-+              ret = -ENOMEM;
-+              goto out;
++
++      for (i = 0; i < ofbi->num_overlays; i++) {
++              if (ofbi->overlays[i]->info.enabled) {
++                      r = -EBUSY;
++                      goto out;
++              }
 +      }
 +
-+      if (mi->type != rg->type)
-+              goto out;
++      if (rg->size != size || rg->type != mi->type) {
++              struct fb_var_screeninfo new_var;
++              unsigned long old_size = rg->size;
 +
-+      ret = 0;
++              if (display->sync)
++                      display->sync(display);
++
++              r = omapfb_realloc_fbmem(fbdev, ofbi->id, size);
++              if (r)
++                      goto out;
++
++              if (old_size != size) {
++                      if (size) {
++                              memcpy(&new_var, &fbi->var, sizeof(new_var));
++                              r = check_fb_var(fbi, &new_var);
++                              if (r < 0)
++                                      goto out;
++                              memcpy(&fbi->var, &new_var, sizeof(fbi->var));
++                              set_fb_fix(fbi);
++                      } else {
++                              /*
++                               * Set these explicitly to indicate that the
++                               * plane memory is dealloce'd, the other
++                               * screen parameters in var / fix are invalid.
++                               */
++                              fbi->fix.smem_start = 0;
++                              fbi->fix.smem_len = 0;
++                      }
++              }
++      }
++
++      r = 0;
 +out:
 +      omapfb_unlock(fbdev);
 +
-+      return ret;
++      return r;
 +}
 +
 +static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
@@ -616,10 +1240,10 @@ index 0000000..1ceb6b9
 +
 diff --git a/drivers/video/omap2/omapfb-main.c b/drivers/video/omap2/omapfb-main.c
 new file mode 100644
-index 0000000..c0f1664
+index 0000000..89ad631
 --- /dev/null
 +++ b/drivers/video/omap2/omapfb-main.c
-@@ -0,0 +1,1276 @@
+@@ -0,0 +1,1382 @@
 +/*
 + * linux/drivers/video/omap2/omapfb-main.c
 + *
@@ -673,7 +1297,9 @@ index 0000000..c0f1664
 +                      if (var->bits_per_pixel == 16) {
 +                              u16 *pw = (u16 *)p;
 +
-+                              if (x == 20 || x == w - 20 ||
++                              if (x < 20 && y < 20)
++                                      *pw = 0xffff;
++                              else if (x == 20 || x == w - 20 ||
 +                                              y == 20 || y == h - 20)
 +                                      *pw = 0xffff;
 +                              else if (x == y || w - x == h - y)
@@ -694,7 +1320,9 @@ index 0000000..c0f1664
 +
 +                              int r = 0, g = 0, b = 0;
 +
-+                              if (x == 20 || x == w - 20 ||
++                              if (x < 20 && y < 20)
++                                      r = g = b = 0xff;
++                              else if (x == 20 || x == w - 20 ||
 +                                              y == 20 || y == h - 20)
 +                                      r = g = b = 0xff;
 +                              else if (x == y || w - x == h - y)
@@ -789,7 +1417,7 @@ index 0000000..c0f1664
 +      return -EINVAL;
 +}
 +
-+static void set_fb_fix(struct fb_info *fbi)
++void set_fb_fix(struct fb_info *fbi)
 +{
 +      struct fb_fix_screeninfo *fix = &fbi->fix;
 +      struct fb_var_screeninfo *var = &fbi->var;
@@ -834,7 +1462,7 @@ index 0000000..c0f1664
 +}
 +
 +/* check new var and possibly modify it to be ok */
-+static int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
++int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
 +{
 +      struct omapfb_info *ofbi = FB2OFB(fbi);
 +      struct omap_display *display = fb2display(fbi);
@@ -847,6 +1475,11 @@ index 0000000..c0f1664
 +
 +      DBG("check_fb_var %d\n", ofbi->id);
 +
++      if (ofbi->region.size == 0) {
++              memset(var, 0, sizeof(*var));
++              return 0;
++      }
++
 +      if (ofbi->num_overlays == 0) {
 +              dev_err(ofbi->fbdev->dev, "no overlays, aborting\n");
 +              return -EINVAL;
@@ -964,6 +1597,12 @@ index 0000000..c0f1664
 +
 +      if (display && display->check_timings) {
 +              struct omap_video_timings timings;
++
++              if (var->pixclock == 0) {
++                      DBG("Pixclock can't be zero.\n");
++                      return -EINVAL;
++              }
++
 +              timings.pixel_clock = PICOS2KHZ(var->pixclock);
 +              timings.hfp = var->left_margin;
 +              timings.hbp = var->right_margin;
@@ -1107,6 +1746,14 @@ index 0000000..c0f1664
 +
 +              DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
 +
++              if (ofbi->region.size == 0) {
++                      /* the fb is not available. disable the overlay */
++                      ovl->enable(ovl, 0);
++                      if (!init && ovl->manager)
++                              ovl->manager->apply(ovl->manager);
++                      continue;
++              }
++
 +              if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
 +                      outw = var->xres;
 +                      outh = var->yres;
@@ -1217,16 +1864,57 @@ index 0000000..c0f1664
 +      return r;
 +}
 +
++static void mmap_user_open(struct vm_area_struct *vma)
++{
++      struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
++
++      atomic_inc(&ofbi->map_count);
++}
++
++static void mmap_user_close(struct vm_area_struct *vma)
++{
++      struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
++
++      atomic_dec(&ofbi->map_count);
++}
++
++static struct vm_operations_struct mmap_user_ops = {
++      .open = mmap_user_open,
++      .close = mmap_user_close,
++};
++
 +static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
 +{
 +      struct omapfb_info *ofbi = FB2OFB(fbi);
-+      struct omapfb2_device *fbdev = ofbi->fbdev;
 +      struct omapfb_mem_region *rg = &ofbi->region;
++      unsigned long off;
++      unsigned long start;
++      u32 len;
 +
-+      return dma_mmap_writecombine(fbdev->dev, vma,
-+                      rg->vaddr,
-+                      rg->paddr,
-+                      rg->size);
++      if (vma->vm_end - vma->vm_start == 0)
++              return 0;
++      if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
++              return -EINVAL;
++      off = vma->vm_pgoff << PAGE_SHIFT;
++
++      start = rg->paddr;
++      len = rg->size;
++      if (off >= len)
++              return -EINVAL;
++      if ((vma->vm_end - vma->vm_start + off) > len)
++              return -EINVAL;
++      off += start;
++      vma->vm_pgoff = off >> PAGE_SHIFT;
++      vma->vm_flags |= VM_IO | VM_RESERVED;
++      vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
++      vma->vm_ops = &mmap_user_ops;
++      vma->vm_private_data = ofbi;
++      if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
++                           vma->vm_end - vma->vm_start, vma->vm_page_prot))
++              return -EAGAIN;
++      /* vm_ops.open won't be called for mmap itself. */
++      atomic_inc(&ofbi->map_count);
++      return 0;
 +}
 +
 +/* Store a single color palette entry into a pseudo palette or the hardware
@@ -1335,7 +2023,7 @@ index 0000000..c0f1664
 +      omapfb_lock(fbdev);
 +
 +      switch (blank) {
-+      case VESA_NO_BLANKING:
++      case FB_BLANK_UNBLANK:
 +              if (display->state != OMAP_DSS_DISPLAY_SUSPENDED) {
 +                      r = -EINVAL;
 +                      goto exit;
@@ -1351,7 +2039,7 @@ index 0000000..c0f1664
 +
 +              break;
 +
-+      case VESA_POWERDOWN:
++      case FB_BLANK_POWERDOWN:
 +              if (display->state != OMAP_DSS_DISPLAY_ACTIVE) {
 +                      r = -EINVAL;
 +                      goto exit;
@@ -1395,89 +2083,135 @@ index 0000000..c0f1664
 +      .fb_setcmap     = omapfb_setcmap,
 +};
 +
-+static int omapfb_free_fbmem(struct omapfb2_device *fbdev)
++static void omapfb_free_fbmem(struct omapfb2_device *fbdev, int fbnum)
++{
++      struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[fbnum]);
++      struct omapfb_mem_region *rg;
++
++      rg = &ofbi->region;
++
++      if (rg->paddr)
++              if (omap_vram_free(rg->paddr, rg->vaddr, rg->size))
++                      printk("VRAM FREE failed\n");
++
++      rg->vaddr = NULL;
++      rg->paddr = 0;
++      rg->alloc = 0;
++      rg->size = 0;
++}
++
++static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
 +{
 +      int i;
 +
-+      DBG("free fbmem\n");
++      DBG("free all fbmem\n");
 +
-+      for (i = 0; i < fbdev->num_fbs; i++) {
-+              struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
-+              struct omapfb_mem_region *rg;
++      for (i = 0; i < fbdev->num_fbs; i++)
++              omapfb_free_fbmem(fbdev, i);
 +
-+              rg = &ofbi->region;
++      return 0;
++}
 +
-+              if (rg->alloc) {
-+                      dma_free_writecombine(fbdev->dev, rg->size,
-+                                      rg->vaddr, rg->paddr);
-+              }
++static int omapfb_alloc_fbmem(struct omapfb2_device *fbdev, int fbnum,
++              unsigned long size)
++{
++      struct omapfb_info *ofbi;
++      struct omapfb_mem_region *rg;
++      unsigned long paddr;
++      void *vaddr;
 +
-+              rg->vaddr = NULL;
-+              rg->paddr = 0;
-+              rg->alloc = 0;
++      ofbi = FB2OFB(fbdev->fbs[fbnum]);
++      rg = &ofbi->region;
++      memset(rg, 0, sizeof(*rg));
++
++      DBG("allocating %lu bytes for fb %d\n",
++                      size, ofbi->id);
++
++      vaddr = omap_vram_alloc(OMAPFB_MEMTYPE_SDRAM, size, &paddr);
++      DBG("VRAM ALLOCCI paddr %lx, vaddr %p\n", paddr, vaddr);
++
++      if (vaddr == NULL) {
++              dev_err(fbdev->dev,
++                              "failed to allocate framebuffer\n");
++              return -ENOMEM;
 +      }
 +
-+      fbdev->num_fbs = 0;
++      rg->paddr = paddr;
++      rg->vaddr = vaddr;
++      rg->size = size;
++      rg->alloc = 1;
 +
 +      return 0;
 +}
 +
-+static int omapfb_allocate_fbmem(struct omapfb2_device *fbdev)
++int omapfb_realloc_fbmem(struct omapfb2_device *fbdev, int fbnum,
++              unsigned long size)
 +{
-+      int i;
-+      struct omapfb_mem_desc *plat_mem_desc;
-+      struct omapfb_platform_data *pdata = fbdev->dev->platform_data;
++      struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[fbnum]);
++      struct omapfb_mem_region *rg = &ofbi->region;
++      unsigned old_size = rg->size;
++      int r;
 +
-+      plat_mem_desc = &pdata->mem_desc;
++      omapfb_free_fbmem(fbdev, fbnum);
 +
-+      DBG("omapfb: setup mem regions, %d regions\n",
-+                      plat_mem_desc->region_cnt);
++      if (size == 0)
++              return 0;
 +
-+      for (i = 0; i < plat_mem_desc->region_cnt; i++) {
-+              struct omapfb_mem_region *plat_rg;
-+              struct omapfb_mem_region *rg;
-+              struct omapfb_info *ofb_info = FB2OFB(fbdev->fbs[i]);
++      r = omapfb_alloc_fbmem(fbdev, fbnum, size);
 +
-+              plat_rg = &plat_mem_desc->region[i];
-+              rg = &ofb_info->region;
++      if (r)
++              omapfb_alloc_fbmem(fbdev, fbnum, old_size);
 +
-+              memset(rg, 0, sizeof(*rg));
++      return r;
++}
 +
-+              DBG("platform region%d phys %08x virt %p size=%lu\n",
-+                              i,
-+                              plat_rg->paddr,
-+                              plat_rg->vaddr,
-+                              plat_rg->size);
++/* allocate fbmem using display resolution as reference */
++static int omapfb_alloc_fbmem_display(struct omapfb2_device *fbdev, int fbnum)
++{
++      struct omapfb_info *ofbi;
++      struct omap_display *display;
++      int bytespp;
++      unsigned long size;
 +
-+              if (plat_rg->paddr == 0) {
-+                      u32 paddr;
-+                      void *vaddr;
++      ofbi = FB2OFB(fbdev->fbs[fbnum]);
++      display =  fb2display(fbdev->fbs[fbnum]);
 +
-+                      vaddr = dma_alloc_writecombine(fbdev->dev,
-+                                      plat_rg->size,
-+                                      &paddr, GFP_KERNEL);
++      if (!display)
++              return 0;
 +
-+                      if (vaddr == NULL) {
-+                              dev_err(fbdev->dev,
-+                                      "failed to allocate framebuffer\n");
-+                              return -ENOMEM;
-+                      }
++      switch (display->bpp) {
++      case 16:
++              bytespp = 2;
++              break;
++      case 24:
++      case 32:
++              bytespp = 4;
++              break;
++      default:
++              bytespp = 4;
++              break;
++      }
 +
-+                      rg->paddr = paddr;
-+                      rg->vaddr = vaddr;
-+                      rg->size = plat_rg->size;
-+                      rg->alloc = 1;
-+              } else {
-+                      dev_err(fbdev->dev,
-+                              "Using preallocated fb not supported\n");
-+                      return -EINVAL;
-+              }
++      size = display->x_res * display->y_res * bytespp;
++
++      return omapfb_alloc_fbmem(fbdev, fbnum, size);
++}
++
++static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
++{
++      int i, r;
++
++      for (i = 0; i < fbdev->num_fbs; i++) {
++              r = omapfb_alloc_fbmem_display(fbdev, i);
++
++              if (r)
++                      return r;
 +      }
 +
 +      for (i = 0; i < fbdev->num_fbs; i++) {
-+              struct omapfb_info *ofb_info = FB2OFB(fbdev->fbs[i]);
++              struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
 +              struct omapfb_mem_region *rg;
-+              rg = &ofb_info->region;
++              rg = &ofbi->region;
 +
 +              DBG("region%d phys %08x virt %p size=%lu\n",
 +                              i,
@@ -1497,60 +2231,57 @@ index 0000000..c0f1664
 +      struct omap_display *display = fb2display(fbi);
 +      int r = 0;
 +
-+      if (!display) {
-+              dev_err(fbdev->dev, "cannot fbinfo_init, no display\n");
-+              return -EINVAL;
-+      }
-+
 +      fbi->fbops = &omapfb_ops;
 +      fbi->flags = FBINFO_FLAG_DEFAULT;
 +      fbi->pseudo_palette = fbdev->pseudo_palette;
 +
 +      strncpy(fix->id, MODULE_NAME, sizeof(fix->id));
 +
-+      var->xres = display->x_res;
-+      var->yres = display->y_res;
-+      var->xres_virtual = var->xres;
-+      var->yres_virtual = var->yres;
-+      /*        var->rotate       = def_rotate; */
-+
 +      var->nonstd = 0;
 +
-+      switch (display->bpp) {
-+      case 16:
-+              var->bits_per_pixel = 16;
-+              break;
-+      case 18:
-+              var->bits_per_pixel = 16;
-+              break;
-+      case 24:
-+              var->bits_per_pixel = 32;
-+              break;
-+      default:
-+              dev_err(fbdev->dev, "illegal display bpp\n");
-+              return -EINVAL;
-+      }
++      if (display) {
++              var->xres = display->x_res;
++              var->yres = display->y_res;
++              var->xres_virtual = var->xres;
++              var->yres_virtual = var->yres;
++              /*        var->rotate       = def_rotate; */
 +
-+      if (display->get_timings) {
-+              struct omap_video_timings timings;
-+              display->get_timings(display, &timings);
++              switch (display->bpp) {
++              case 16:
++                      var->bits_per_pixel = 16;
++                      break;
++              case 18:
++                      var->bits_per_pixel = 16;
++                      break;
++              case 24:
++                      var->bits_per_pixel = 32;
++                      break;
++              default:
++                      dev_err(fbdev->dev, "illegal display bpp\n");
++                      return -EINVAL;
++              }
 +
-+              /* pixclock in ps, the rest in pixclock */
-+              var->pixclock           = KHZ2PICOS(timings.pixel_clock);
-+              var->left_margin        = timings.hfp;
-+              var->right_margin       = timings.hbp;
-+              var->upper_margin       = timings.vfp;
-+              var->lower_margin       = timings.vbp;
-+              var->hsync_len          = timings.hsw;
-+              var->vsync_len          = timings.vsw;
-+      } else {
-+              var->pixclock = 0;
-+              var->left_margin = 0;
-+              var->right_margin = 0;
-+              var->upper_margin = 0;
-+              var->lower_margin = 0;
-+              var->hsync_len = 0;
-+              var->vsync_len = 0;
++              if (display->get_timings) {
++                      struct omap_video_timings timings;
++                      display->get_timings(display, &timings);
++
++                      /* pixclock in ps, the rest in pixclock */
++                      var->pixclock = KHZ2PICOS(timings.pixel_clock);
++                      var->left_margin = timings.hfp;
++                      var->right_margin = timings.hbp;
++                      var->upper_margin = timings.vfp;
++                      var->lower_margin = timings.vbp;
++                      var->hsync_len = timings.hsw;
++                      var->vsync_len = timings.vsw;
++              } else {
++                      var->pixclock = 0;
++                      var->left_margin = 0;
++                      var->right_margin = 0;
++                      var->upper_margin = 0;
++                      var->lower_margin = 0;
++                      var->hsync_len = 0;
++                      var->vsync_len = 0;
++              }
 +      }
 +
 +      r = check_fb_var(fbi, var);
@@ -1585,14 +2316,13 @@ index 0000000..c0f1664
 +              unregister_framebuffer(fbdev->fbs[i]);
 +
 +      /* free the reserved fbmem */
-+      omapfb_free_fbmem(fbdev);
++      omapfb_free_all_fbmem(fbdev);
 +
 +      for (i = 0; i < fbdev->num_fbs; i++) {
 +              fbinfo_cleanup(fbdev, fbdev->fbs[i]);
 +              framebuffer_release(fbdev->fbs[i]);
 +      }
 +
-+
 +      for (i = 0; i < fbdev->num_displays; i++) {
 +              if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED)
 +                      fbdev->displays[i]->disable(fbdev->displays[i]);
@@ -1606,19 +2336,14 @@ index 0000000..c0f1664
 +
 +static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
 +{
-+      int r;
-+      int i;
-+      struct omapfb_mem_desc *plat_mem_desc;
-+      struct omapfb_platform_data *pdata = fbdev->dev->platform_data;
-+
-+      plat_mem_desc = &pdata->mem_desc;
++      int r, i;
 +
 +      fbdev->num_fbs = 0;
 +
-+      DBG("create %d framebuffers\n", plat_mem_desc->region_cnt);
++      DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS);
 +
 +      /* allocate fb_infos */
-+      for (i = 0; i < plat_mem_desc->region_cnt; i++) {
++      for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
 +              struct fb_info *fbi;
 +              struct omapfb_info *ofbi;
 +
@@ -1635,17 +2360,22 @@ index 0000000..c0f1664
 +
 +              ofbi = FB2OFB(fbi);
 +              ofbi->fbdev = fbdev;
-+              /* XXX here we presume we have enough overlays */
-+              ofbi->overlays[0] = fbdev->overlays[i];
-+              ofbi->num_overlays = 1;
 +              ofbi->id = i;
 +              fbdev->num_fbs++;
 +      }
 +
 +      DBG("fb_infos allocated\n");
 +
++      /* assign overlays for the fbs */
++      for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
++              struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
++
++              ofbi->overlays[0] = fbdev->overlays[i];
++              ofbi->num_overlays = 1;
++      }
++
 +      /* allocate fb memories */
-+      r = omapfb_allocate_fbmem(fbdev);
++      r = omapfb_allocate_all_fbs(fbdev);
 +      if (r) {
 +              dev_err(fbdev->dev, "failed to allocate fbmem\n");
 +              return r;
@@ -1898,10 +2628,10 @@ index 0000000..c0f1664
 +MODULE_LICENSE("GPL v2");
 diff --git a/drivers/video/omap2/omapfb-sysfs.c b/drivers/video/omap2/omapfb-sysfs.c
 new file mode 100644
-index 0000000..e01edd1
+index 0000000..59b48ac
 --- /dev/null
 +++ b/drivers/video/omap2/omapfb-sysfs.c
-@@ -0,0 +1,833 @@
+@@ -0,0 +1,838 @@
 +/*
 + * linux/drivers/video/omap2/omapfb-sysfs.c
 + *
@@ -2025,8 +2755,13 @@ index 0000000..e01edd1
 +
 +      for (i = 0; i < fbdev->num_fbs; i++) {
 +              struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
++              struct omapfb_mem_region *rg;
++
++              rg = &ofbi->region;
 +
-+              l += snprintf(buf + l, size - l, "%d t:", ofbi->id);
++              l += snprintf(buf + l, size - l, "%d p:%08x v:%p size:%lu t:",
++                              ofbi->id,
++                              rg->paddr, rg->vaddr, rg->size);
 +
 +              if (ofbi->num_overlays == 0)
 +                      l += snprintf(buf + l, size - l, "none");
@@ -2737,10 +3472,10 @@ index 0000000..e01edd1
 +
 diff --git a/drivers/video/omap2/omapfb.h b/drivers/video/omap2/omapfb.h
 new file mode 100644
-index 0000000..04ca444
+index 0000000..60352da
 --- /dev/null
 +++ b/drivers/video/omap2/omapfb.h
-@@ -0,0 +1,104 @@
+@@ -0,0 +1,109 @@
 +/*
 + * linux/drivers/video/omap2/omapfb.h
 + *
@@ -2785,6 +3520,7 @@ index 0000000..04ca444
 +struct omapfb_info {
 +      int id;
 +      struct omapfb_mem_region region;
++      atomic_t map_count;
 +      int num_overlays;
 +      struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
 +      struct omapfb2_device *fbdev;
@@ -2809,6 +3545,10 @@ index 0000000..04ca444
 +      struct omap_overlay_manager *managers[10];
 +};
 +
++void set_fb_fix(struct fb_info *fbi);
++int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var);
++int omapfb_realloc_fbmem(struct omapfb2_device *fbdev, int fbnum,
++              unsigned long size);
 +int omapfb_apply_changes(struct fb_info *fbi, int init);
 +int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
 +              int posx, int posy, int outw, int outh);
index bbf96ec..3ee4882 100644 (file)
@@ -1,13 +1,11 @@
-From ff78ff9513a40be30649420bc9833793a6e70b75 Mon Sep 17 00:00:00 2001
+From 51d884828725c9e1d1c69c3a061fb5aa9d3d9814 Mon Sep 17 00:00:00 2001
 From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
 Date: Tue, 11 Nov 2008 13:52:56 +0200
 Subject: [PATCH] DSS: Add generic DVI panel
 
-For some reason we can't allocate enough mem for 1280x1024x24bpp, even if
-there should be enough continuous mem. So 1280x1024 mode defaults to
-16bpp for now.
-
 You also need DSI PLL to generate pix clock for 1280x1024.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
 ---
  drivers/video/omap2/Kconfig     |   23 ++++++
  drivers/video/omap2/Makefile    |    2 +
@@ -16,10 +14,10 @@ You also need DSI PLL to generate pix clock for 1280x1024.
  create mode 100644 drivers/video/omap2/panel-dvi.c
 
 diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
-index 4b72479..11ca6fe 100644
+index bfa1617..ab6a5fc 100644
 --- a/drivers/video/omap2/Kconfig
 +++ b/drivers/video/omap2/Kconfig
-@@ -24,6 +24,29 @@ config FB_OMAP2_FORCE_AUTO_UPDATE
+@@ -33,6 +33,29 @@ config FB_OMAP2_NUM_FBS
  menu "OMAP2/3 Display Device Drivers"
          depends on OMAP2_DSS
  
@@ -60,7 +58,7 @@ index 51c2e00..7c75340 100644
 +obj-$(CONFIG_PANEL_DVI) += panel-dvi.o
 diff --git a/drivers/video/omap2/panel-dvi.c b/drivers/video/omap2/panel-dvi.c
 new file mode 100644
-index 0000000..393eaf1
+index 0000000..7a90773
 --- /dev/null
 +++ b/drivers/video/omap2/panel-dvi.c
 @@ -0,0 +1,150 @@
@@ -191,7 +189,7 @@ index 0000000..393eaf1
 +
 +      .x_res          = 1280,
 +      .y_res          = 1024,
-+      .bpp            = 16,
++      .bpp            = 24,
 +#else
 +#error Undefined default mode
 +#endif
index 9ca1bd7..a5e2912 100644 (file)
@@ -1,18 +1,18 @@
-From 1a63704f218e5ec0bc6f94fc0629ab96f3d6ab34 Mon Sep 17 00:00:00 2001
+From eed2f51a01acd47ab83000bf6870d8b24829fa30 Mon Sep 17 00:00:00 2001
 From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
 Date: Mon, 29 Sep 2008 17:03:36 +0300
 Subject: [PATCH] DSS: support for Beagle Board
 
 Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
 ---
- arch/arm/mach-omap2/board-omap3beagle.c |  123 +++++++++++++++++++++++++++----
- 1 files changed, 107 insertions(+), 16 deletions(-)
+ arch/arm/mach-omap2/board-omap3beagle.c |  109 +++++++++++++++++++++++++++----
+ 1 files changed, 95 insertions(+), 14 deletions(-)
 
 diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
-index c1de795..cd0c776 100644
+index fe97bab..f3ef73e 100644
 --- a/arch/arm/mach-omap2/board-omap3beagle.c
 +++ b/arch/arm/mach-omap2/board-omap3beagle.c
-@@ -42,6 +42,8 @@
+@@ -43,6 +43,8 @@
  #include <mach/gpmc.h>
  #include <mach/nand.h>
  #include <mach/mux.h>
@@ -21,7 +21,7 @@ index c1de795..cd0c776 100644
  
  #include "twl4030-generic-scripts.h"
  #include "mmc-twl4030.h"
-@@ -200,15 +202,6 @@ static void __init omap3_beagle_init_irq(void)
+@@ -238,15 +240,6 @@ static void __init omap3_beagle_init_irq(void)
        omap_gpio_init();
  }
  
@@ -37,7 +37,7 @@ index c1de795..cd0c776 100644
  static struct gpio_led gpio_leds[] = {
        {
                .name                   = "beagleboard::usr0",
-@@ -262,13 +255,113 @@ static struct platform_device keys_gpio = {
+@@ -300,13 +293,94 @@ static struct platform_device keys_gpio = {
        },
  };
  
@@ -122,29 +122,10 @@ index c1de795..cd0c776 100644
 +      if (r < 0)
 +              printk(KERN_ERR "Unable to get DVI reset GPIO\n");
 +}
-+
-+static struct omap_fbmem_config beagle_fbmem0_config = {
-+      .size = 1024*768*4,
-+      .start = OMAPFB_MEMTYPE_SDRAM,
-+};
-+
-+static struct omap_fbmem_config beagle_fbmem1_config = {
-+      .size = 1024*768*4,
-+      .start = OMAPFB_MEMTYPE_SDRAM,
-+};
-+
-+static struct omap_fbmem_config beagle_fbmem2_config = {
-+      .size = 1024*768*4,
-+      .start = OMAPFB_MEMTYPE_SDRAM,
-+};
-+
 +
  static struct omap_board_config_kernel omap3_beagle_config[] __initdata = {
        { OMAP_TAG_UART,        &omap3_beagle_uart_config },
 -      { OMAP_TAG_LCD,         &omap3_beagle_lcd_config },
-+      { OMAP_TAG_FBMEM,       &beagle_fbmem0_config },
-+      { OMAP_TAG_FBMEM,       &beagle_fbmem1_config },
-+      { OMAP_TAG_FBMEM,       &beagle_fbmem2_config },
  };
  
  static struct platform_device *omap3_beagle_devices[] __initdata = {
@@ -153,12 +134,7 @@ index c1de795..cd0c776 100644
        &leds_gpio,
        &keys_gpio,
  };
-@@ -316,22 +409,20 @@ static void __init omap3_beagle_init(void)
-       omap3_beagle_i2c_init();
-       platform_add_devices(omap3_beagle_devices,
-                       ARRAY_SIZE(omap3_beagle_devices));
--      omap_board_config = omap3_beagle_config;
--      omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
+@@ -359,18 +433,25 @@ static void __init omap3_beagle_init(void)
        omap_serial_init();
  
        omap_cfg_reg(J25_34XX_GPIO170);
@@ -172,13 +148,21 @@ index c1de795..cd0c776 100644
 +      beagle_display_init();
  }
  
++static struct omap_fbmem_config omap3_beagle_vram_config[] = {
++      {
++              .size = 1280 * 1024 * 4 * 3,
++              .start = OMAPFB_MEMTYPE_SDRAM,
++      },
++};
++
  static void __init omap3_beagle_map_io(void)
  {
-+      omap_board_config = omap3_beagle_config;
-+      omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
        omap2_set_globals_343x();
++      omapfb_set_vram_config(omap3_beagle_vram_config,
++                      ARRAY_SIZE(omap3_beagle_vram_config));
        omap2_map_common_io();
  }
 -- 
 1.5.6.3
 
index 858cccf..8a7238d 100644 (file)
@@ -1,8 +1,9 @@
-From 53561526e1e9bf20dd9e17b66f2a1b1c6cfec935 Mon Sep 17 00:00:00 2001
+From 64421d1bbb3aadb91fedc6c0f0093e0496f2c0bf Mon Sep 17 00:00:00 2001
 From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
 Date: Fri, 7 Nov 2008 16:54:01 +0200
 Subject: [PATCH] DSS: BEAGLE: Enable DSS in beagle defconfig
 
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
 ---
  arch/arm/configs/omap3_beagle_defconfig |  149 +++++++++++++++++++++----------
  1 files changed, 102 insertions(+), 47 deletions(-)
index 68720a9..7e087f4 100644 (file)
@@ -1,4 +1,4 @@
-From 436d6597311770af1d3a6d42560f34d6342a1c2f Mon Sep 17 00:00:00 2001
+From 2262ea3226ee073fefa37d5706f09205ae74580d Mon Sep 17 00:00:00 2001
 From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
 Date: Fri, 14 Nov 2008 15:47:19 +0200
 Subject: [PATCH] DSS: Sharp LS037V7DW01 LCD Panel driver
@@ -12,10 +12,10 @@ Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
  create mode 100644 drivers/video/omap2/panel-sharp-ls037v7dw01.c
 
 diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
-index 11ca6fe..4bd3f87 100644
+index ab6a5fc..392f251 100644
 --- a/drivers/video/omap2/Kconfig
 +++ b/drivers/video/omap2/Kconfig
-@@ -48,5 +48,10 @@ config PANEL_DVI_1280X1024
+@@ -57,5 +57,10 @@ config PANEL_DVI_1280X1024
  
  endchoice
  
index 981a202..a8ad93c 100644 (file)
@@ -1,52 +1,32 @@
-From 0938c1e91fe69da535e06d092bdec6fcc95ad650 Mon Sep 17 00:00:00 2001
+From fc87accafe1f6266f85142ade5fc81886ba4685d Mon Sep 17 00:00:00 2001
 From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
-Date: Mon, 20 Oct 2008 13:13:15 +0300
-Subject: [PATCH] DSS: support for OMAP3 SDP board
+Date: Fri, 14 Nov 2008 15:47:55 +0200
+Subject: [PATCH] DSS: Support for OMAP3 SDP board
 
 Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
 ---
- arch/arm/mach-omap2/board-3430sdp.c |  234 +++++++++++++++++++++++++++++++++--
- drivers/video/omap2/Kconfig         |    7 +-
- drivers/video/omap2/Makefile        |    1 +
- drivers/video/omap2/panel-sdp3430.c |  110 ++++++++++++++++
- 4 files changed, 340 insertions(+), 12 deletions(-)
- create mode 100644 drivers/video/omap2/panel-sdp3430.c
+ arch/arm/mach-omap2/board-3430sdp.c |  210 +++++++++++++++++++++++++++++++++--
+ 1 files changed, 201 insertions(+), 9 deletions(-)
 
 diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
-index 7ee85e9..3a644b1 100644
+index ade186b..725b2d9 100644
 --- a/arch/arm/mach-omap2/board-3430sdp.c
 +++ b/arch/arm/mach-omap2/board-3430sdp.c
-@@ -40,6 +40,8 @@
+@@ -39,6 +39,7 @@
  #include <mach/keypad.h>
  #include <mach/dma.h>
  #include <mach/gpmc.h>
-+#include <mach/omapfb.h>
 +#include <mach/display.h>
  
  #include <asm/io.h>
  #include <asm/delay.h>
-@@ -240,14 +242,224 @@ static struct spi_board_info sdp3430_spi_board_info[] __initdata = {
+@@ -238,14 +239,209 @@ static struct spi_board_info sdp3430_spi_board_info[] __initdata = {
        },
  };
  
 -static struct platform_device sdp3430_lcd_device = {
 -      .name           = "sdp2430_lcd",
 -      .id             = -1,
-+static struct omap_fbmem_config sdp3430_fbmem0_config = {
-+      .size = 1024*768*4,
-+      .start = OMAPFB_MEMTYPE_SDRAM,
-+};
-+
-+static struct omap_fbmem_config sdp3430_fbmem1_config = {
-+      .size = 640*480*4,
-+      .start = OMAPFB_MEMTYPE_SDRAM,
- };
-+static struct omap_fbmem_config sdp3430_fbmem2_config = {
-+      .size = 640*480*4,
-+      .start = OMAPFB_MEMTYPE_SDRAM,
-+};
-+
 +
 +#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO      91
 +#define SDP2430_LCD_PANEL_ENABLE_GPIO         154
@@ -153,7 +133,7 @@ index 7ee85e9..3a644b1 100644
 +static struct omap_display_data sdp3430_display_data = {
 +      .type = OMAP_DISPLAY_TYPE_DPI,
 +      .name = "lcd",
-+      .panel_name = "panel-sdp3430",
++      .panel_name = "sharp-ls037v7dw01",
 +      .u.dpi.data_lines = 16,
 +      .panel_enable = sdp3430_panel_enable_lcd,
 +      .panel_disable = sdp3430_panel_disable_lcd,
@@ -227,8 +207,8 @@ index 7ee85e9..3a644b1 100644
 +      .u.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
 +      .panel_enable = sdp3430_panel_enable_tv,
 +      .panel_disable = sdp3430_panel_disable_tv,
-+};
-+
+ };
 +static struct omap_dss_platform_data sdp3430_dss_data = {
 +      .num_displays = 3,
 +      .displays = {
@@ -254,7 +234,7 @@ index 7ee85e9..3a644b1 100644
  };
  
  static inline void __init sdp3430_init_smc91x(void)
-@@ -294,13 +506,11 @@ static struct omap_uart_config sdp3430_uart_config __initdata = {
+@@ -292,13 +488,8 @@ static struct omap_uart_config sdp3430_uart_config __initdata = {
        .enabled_uarts  = ((1 << 0) | (1 << 1) | (1 << 2)),
  };
  
@@ -265,177 +245,17 @@ index 7ee85e9..3a644b1 100644
  static struct omap_board_config_kernel sdp3430_config[] __initdata = {
        { OMAP_TAG_UART,        &sdp3430_uart_config },
 -      { OMAP_TAG_LCD,         &sdp3430_lcd_config },
-+      { OMAP_TAG_FBMEM,       &sdp3430_fbmem0_config },
-+      { OMAP_TAG_FBMEM,       &sdp3430_fbmem1_config },
-+      { OMAP_TAG_FBMEM,       &sdp3430_fbmem2_config },
  };
  
  static int sdp3430_batt_table[] = {
-@@ -467,8 +677,6 @@ static void __init omap_3430sdp_init(void)
- {
-       omap3430_i2c_init();
-       platform_add_devices(sdp3430_devices, ARRAY_SIZE(sdp3430_devices));
--      omap_board_config = sdp3430_config;
--      omap_board_config_size = ARRAY_SIZE(sdp3430_config);
-       if (omap_rev() > OMAP3430_REV_ES1_0)
-               ts_gpio = OMAP34XX_TS_GPIO_IRQ_SDPV2;
-       else
-@@ -483,10 +691,14 @@ static void __init omap_3430sdp_init(void)
+@@ -481,6 +672,7 @@ static void __init omap_3430sdp_init(void)
        usb_musb_init();
        usb_ehci_init();
-       hsmmc_init(mmc);
+       twl4030_mmc_init(mmc);
 +      sdp3430_display_init();
  }
  
  static void __init omap_3430sdp_map_io(void)
- {
-+      omap_board_config = sdp3430_config;
-+      omap_board_config_size = ARRAY_SIZE(sdp3430_config);
-+
-       omap2_set_globals_343x();
-       omap2_map_common_io();
- }
-diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
-index 996f047..f4e450d 100644
---- a/drivers/video/omap2/Kconfig
-+++ b/drivers/video/omap2/Kconfig
-@@ -48,5 +48,10 @@ config PANEL_DVI_VERYHIGHRES
- endchoice
--endmenu
-+config PANEL_SDP3430
-+        tristate "SDP3430 Panel"
-+        depends on OMAP2_DSS
-+        help
-+          SDP3430 LCD
-+endmenu
-diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
-index 7c75340..73ab1c0 100644
---- a/drivers/video/omap2/Makefile
-+++ b/drivers/video/omap2/Makefile
-@@ -2,3 +2,4 @@ obj-$(CONFIG_FB_OMAP2) += omapfb.o
- omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
- obj-$(CONFIG_PANEL_DVI) += panel-dvi.o
-+obj-$(CONFIG_PANEL_SDP3430) += panel-sdp3430.o
-diff --git a/drivers/video/omap2/panel-sdp3430.c b/drivers/video/omap2/panel-sdp3430.c
-new file mode 100644
-index 0000000..40fe6f2
---- /dev/null
-+++ b/drivers/video/omap2/panel-sdp3430.c
-@@ -0,0 +1,110 @@
-+/*
-+ * LCD panel support for the TI 3430SDP board
-+ *
-+ * Copyright (C) 2008 Nokia Corporation
-+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
-+ *
-+ * Derived from drivers/video/omap/lcd_2430sdp.c
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program.  If not, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/delay.h>
-+
-+#include <mach/display.h>
-+
-+static int sdp3430_panel_init(struct omap_display *display)
-+{
-+      return 0;
-+}
-+
-+static void sdp3430_panel_cleanup(struct omap_display *display)
-+{
-+}
-+
-+static int sdp3430_panel_enable(struct omap_display *display)
-+{
-+      int r = 0;
-+
-+      if (display->hw_config.panel_enable)
-+              r = display->hw_config.panel_enable(display);
-+
-+      return r;
-+}
-+
-+static void sdp3430_panel_disable(struct omap_display *display)
-+{
-+      if (display->hw_config.panel_disable)
-+              display->hw_config.panel_disable(display);
-+}
-+
-+static int sdp3430_panel_suspend(struct omap_display *display)
-+{
-+      sdp3430_panel_disable(display);
-+      return 0;
-+}
-+
-+static int sdp3430_panel_resume(struct omap_display *display)
-+{
-+      return sdp3430_panel_enable(display);
-+}
-+
-+static struct omap_panel sdp3430_panel = {
-+      .owner          = THIS_MODULE,
-+      .name           = "panel-sdp3430",
-+      .init           = sdp3430_panel_init,
-+      .cleanup        = sdp3430_panel_cleanup,
-+      .enable         = sdp3430_panel_enable,
-+      .disable        = sdp3430_panel_disable,
-+      .suspend        = sdp3430_panel_suspend,
-+      .resume         = sdp3430_panel_resume,
-+      /*.set_mode     = sdp3430_set_mode, */
-+
-+      .timings = {
-+              .pixel_clock    = 19200,
-+
-+              .hsw            = 4,
-+              .hfp            = 4,
-+              .hbp            = 40,
-+
-+              .vsw            = 2,
-+              .vfp            = 1,
-+              .vbp            = 1,
-+      },
-+
-+      .acb            = 0x28,
-+
-+      .config         = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
-+              OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC,
-+
-+      .x_res = 480,
-+      .y_res = 640,
-+      .bpp = 16,
-+};
-+
-+
-+static int __init sdp3430_panel_drv_init(void)
-+{
-+      omap_dss_register_panel(&sdp3430_panel);
-+      return 0;
-+}
-+
-+static void __exit sdp3430_panel_drv_exit(void)
-+{
-+      omap_dss_unregister_panel(&sdp3430_panel);
-+}
-+
-+module_init(sdp3430_panel_drv_init);
-+module_exit(sdp3430_panel_drv_exit);
-+MODULE_LICENSE("GPL");
 -- 
 1.5.6.3
 
index 2e26110..a8aa8f6 100644 (file)
@@ -1,4 +1,4 @@
-From 21156e8a6473c293d260b18565a382283d227ef4 Mon Sep 17 00:00:00 2001
+From c50a7b6c9ceb75c1bc49bc596556fdf6b1960306 Mon Sep 17 00:00:00 2001
 From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
 Date: Fri, 14 Nov 2008 16:03:34 +0200
 Subject: [PATCH] DSS: Support for OMAP3 EVM board
@@ -11,10 +11,10 @@ Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
  1 files changed, 215 insertions(+), 9 deletions(-)
 
 diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
-index bc44cb5..edecfd3 100644
+index e4e60e2..7756dd8 100644
 --- a/arch/arm/mach-omap2/board-omap3evm.c
 +++ b/arch/arm/mach-omap2/board-omap3evm.c
-@@ -37,6 +37,8 @@
+@@ -36,6 +36,8 @@
  #include <mach/usb-ehci.h>
  #include <mach/common.h>
  #include <mach/mcspi.h>
@@ -23,7 +23,7 @@ index bc44cb5..edecfd3 100644
  
  #include "sdram-micron-mt46h32m32lf-6.h"
  #include "twl4030-generic-scripts.h"
-@@ -161,14 +163,215 @@ static int __init omap3_evm_i2c_init(void)
+@@ -159,14 +161,215 @@ static int __init omap3_evm_i2c_init(void)
        omap_register_i2c_bus(3, 400, NULL, 0);
        return 0;
  }
@@ -154,7 +154,7 @@ index bc44cb5..edecfd3 100644
 +              twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
 +                              TWL4030_VPLL2_DEV_GRP);
 +      }
-+      gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1);
++      omap_set_gpio_dataout(LCD_PANEL_ENABLE_GPIO, 1);
 +      lcd_enabled = 0;
 +}
 +
@@ -244,7 +244,7 @@ index bc44cb5..edecfd3 100644
  };
  
  static void ads7846_dev_init(void)
-@@ -227,11 +430,13 @@ static void __init omap3_evm_init_irq(void)
+@@ -225,11 +428,13 @@ static void __init omap3_evm_init_irq(void)
  
  static struct omap_board_config_kernel omap3_evm_config[] __initdata = {
        { OMAP_TAG_UART,        &omap3_evm_uart_config },
@@ -260,7 +260,7 @@ index bc44cb5..edecfd3 100644
        &omap3evm_smc911x_device,
  };
  
-@@ -250,8 +455,6 @@ static void __init omap3_evm_init(void)
+@@ -248,8 +453,6 @@ static void __init omap3_evm_init(void)
        omap3_evm_i2c_init();
  
        platform_add_devices(omap3_evm_devices, ARRAY_SIZE(omap3_evm_devices));
@@ -269,7 +269,7 @@ index bc44cb5..edecfd3 100644
  
        spi_register_board_info(omap3evm_spi_board_info,
                                ARRAY_SIZE(omap3evm_spi_board_info));
-@@ -262,10 +465,13 @@ static void __init omap3_evm_init(void)
+@@ -260,10 +463,13 @@ static void __init omap3_evm_init(void)
        usb_ehci_init();
        omap3evm_flash_init();
        ads7846_dev_init();
index 5ad4bc1..332748a 100644 (file)
@@ -10,7 +10,7 @@ SRCREV = "014ba70469e889ebb74516052c43fd06a419b17b"
 
 PV = "2.6.27+2.6.28-rc7+${PR}+gitr${SRCREV}"
 #PV = "2.6.27+${PR}+gitr${SRCREV}"
-PR = "r6"
+PR = "r7"
 
 SRC_URI = "git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git;protocol=git \
           file://defconfig"
@@ -37,7 +37,6 @@ SRC_URI_append = " \
            file://0008-DSS-BEAGLE-Enable-DSS-in-beagle-defconfig.patch;patch=1 \
            file://0009-DSS-Sharp-LS037V7DW01-LCD-Panel-driver.patch;patch=1 \
            file://0011-DSS-Support-for-OMAP3-EVM-board.patch;patch=1 \
-                  http://www.bat.org/~tomba/git/0001-DSS-OMAPFB-Check-that-var-pixclock-is-not-zero.patch;patch=1 \
            file://twl-asoc-fix-record.diff;patch=1 \
            file://tick-schedc-suppress-needless-timer-reprogramming.patch;patch=1 \
            file://fix-dpll-m4.diff;patch=1 \