]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
ARM: OMAP: omapfb: main and LCD controller module changes
authorImre Deak <imre.deak@solidboot.com>
Mon, 26 Jun 2006 12:57:29 +0000 (15:57 +0300)
committerJuha Yrjola <juha.yrjola@solidboot.com>
Mon, 26 Jun 2006 12:57:29 +0000 (15:57 +0300)
- Support for
        - overlays through separate /dev/fbX nodes
        - scaling and color space conversion
        - per-plane memory configuration either in SRAM or SDRAM

- Replace custom debug stuff with the default kernel one

Signed-off-by: Imre Deak <ext-imre.deak@nokia.com>
Signed-off-by: Juha Yrjola <juha.yrjola@solidboot.com>
drivers/video/omap/Kconfig
drivers/video/omap/Makefile
drivers/video/omap/debug.h [deleted file]
drivers/video/omap/dispc.c
drivers/video/omap/hwa742.c
drivers/video/omap/lcdc.c
drivers/video/omap/omapfb_main.c
drivers/video/omap/rfbi.c
drivers/video/omap/sossi.c
include/asm-arm/arch-omap/omapfb.h

index 6411c95095cdd459a3721dacd4f23c6678c7e5ef..17e94200479c1dfa61576db16c22a687ea1bc2b1 100644 (file)
@@ -27,12 +27,13 @@ config FB_OMAP_MANUAL_UPDATE
           the frame buffer content and thus a reload of the image data to
          the external frame buffer is required. If unsure, say N.
 
-config FB_OMAP_LCD_LPH8923
-       bool "Philips LPH8923 LCD support"
+config FB_OMAP_LCD_MIPID
+       bool "MIPI DBI-C/DCS compatible LCD support"
        depends on FB_OMAP
        help
-         Say Y here if you want to have support for the Philips
-         LPH8923 LCD.
+         Say Y here if you want to have support for LCDs compatible with
+         the Mobile Industry Processor Interface DBI-C/DCS
+         specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3)
 
 config FB_OMAP_BOOTLOADER_INIT
        bool "Check bootloader initializaion"
@@ -42,6 +43,17 @@ config FB_OMAP_BOOTLOADER_INIT
          already initialized the display controller. In this case the
          driver will skip the initialization.
 
+config FB_OMAP_CONSISTENT_DMA_SIZE
+       int "Consistent DMA memory size (MB)"
+       depends on FB_OMAP
+       range 1 14
+       default 2
+       help
+         Increase the DMA consistent memory size according to your video
+         memory needs, for example if you want to use multiple planes.
+         The size must be 2MB aligned.
+         If unsure say 1.
+
 config FB_OMAP_DMA_TUNE
         bool "Set DMA SDRAM access priority high"
         depends on FB_OMAP && ARCH_OMAP1
index 725ea29c6713592902a5810cfb275388cb8e8eb6..444643ef42fbb3dad7cfc430bb79b193fe2333a2 100644 (file)
@@ -24,7 +24,7 @@ objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
 objs-y$(CONFIG_MACH_OMAP_PERSEUS2) += lcd_p2.o
 objs-y$(CONFIG_MACH_OMAP_APOLLON) += lcd_apollon.o
 
-objs-y$(CONFIG_FB_OMAP_LCD_LPH8923) += lcd_lph8923.o
+objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o
 
 omapfb-objs := $(objs-yy)
 
diff --git a/drivers/video/omap/debug.h b/drivers/video/omap/debug.h
deleted file mode 100644 (file)
index a280412..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * File: drivers/video/omap_new/debug.c
- *
- * Debug support for the omapfb driver
- *
- * Copyright (C) 2004 Nokia Corporation
- * Author: Imre Deak <imre.deak@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * 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, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#ifndef __OMAPFB_DEBUG_H
-#define __OMAPFB_DEBUG_H
-
-#ifdef OMAPFB_DBG
-
-#define DBGPRINT(level, fmt, ...) if (level <= OMAPFB_DBG) do { \
-                                       printk(KERN_DEBUG "%s: "fmt, \
-                                               __FUNCTION__, ## __VA_ARGS__); \
-                                 } while (0)
-#define DBGENTER(level) DBGPRINT(level, "Enter\n")
-#define DBGLEAVE(level)        DBGPRINT(level, "Leave\n")
-
-#else  /* OMAPFB_DBG */
-
-#define DBGPRINT(level, format, ...)
-#define DBGENTER(level)
-#define DBGLEAVE(level)
-
-#endif /* OMAPFB_DBG */
-
-#endif /* __OMAPFB_DEBUG_H */
index 3185282887fbf785d9aa3db01c1c6aa79b0d88e1..67201d2fb773bc65df822a2bcee7e14af3a7d35d 100644 (file)
@@ -20,7 +20,6 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
-
 #include <linux/kernel.h>
 #include <linux/dma-mapping.h>
 #include <linux/vmalloc.h>
 
 #include "dispc.h"
 
-/* #define OMAPFB_DBG  1 */
-
-#include "debug.h"
-
-#define MODULE_NAME                    "omapfb-dispc"
+#define MODULE_NAME                    "dispc"
 
 #define DISPC_BASE                     0x48050400
 
 
 #define MAX_PALETTE_SIZE               (256 * 16)
 
-#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
-
 #define FLD_MASK(pos, len)     (((1 << len) - 1) << pos)
 
 #define MOD_REG_FLD(reg, mask, val) \
 static struct {
        u32             base;
 
-       dma_addr_t      fb_sram_paddr;
-       u32             fb_sram_size;
-       int             fb_sram_lines;
-
-       dma_addr_t      fb_sdram_paddr;
-       void            *fb_sdram_vaddr;
-       u32             fb_sdram_size;
-       int             fb_sdram_lines;
+       struct omapfb_mem_desc  mem_desc;
 
        dma_addr_t      palette_paddr;
        void            *palette_vaddr;
 
-       void            *fb_kern_vaddr;
-
-       int             multiplane_head;
-
        int             ext_mode;
        int             fbmem_allocated;
 
@@ -168,11 +150,16 @@ static struct {
        void            *irq_callback_data;
        struct completion       frame_done;
 
+       int             fir_hinc[OMAPFB_PLANE_NUM];
+       int             fir_vinc[OMAPFB_PLANE_NUM];
+
        struct clk      *dss_ick, *dss1_fck;
        struct clk      *dss_54m_fck;
 
        enum omapfb_update_mode update_mode;
        struct omapfb_device    *fbdev;
+
+       struct omapfb_color_key color_key;
 } dispc;
 
 static void inline dispc_write_reg(int idx, u32 val)
@@ -302,22 +289,31 @@ static inline int _setup_plane(int plane, int channel_out,
        const u32 ps_reg[] = { DISPC_GFX_POSITION,
                                DISPC_VID1_BASE + DISPC_VID_POSITION,
                                DISPC_VID2_BASE + DISPC_VID_POSITION };
-       const u32 sz_reg[] = { DISPC_GFX_SIZE, DISPC_VID1_BASE + DISPC_VID_SIZE,
-                               DISPC_VID2_BASE + DISPC_VID_SIZE };
+       const u32 sz_reg[] = { DISPC_GFX_SIZE,
+                               DISPC_VID1_BASE + DISPC_VID_PICTURE_SIZE,
+                               DISPC_VID2_BASE + DISPC_VID_PICTURE_SIZE };
        const u32 ri_reg[] = { DISPC_GFX_ROW_INC,
                                DISPC_VID1_BASE + DISPC_VID_ROW_INC,
                                DISPC_VID2_BASE + DISPC_VID_ROW_INC };
+       const u32 vs_reg[]= { 0, DISPC_VID1_BASE + DISPC_VID_SIZE,
+                               DISPC_VID2_BASE + DISPC_VID_SIZE };
+
        int chout_shift, burst_shift;
        int chout_val;
        int color_code;
        int bpp;
+       int cconv_en;
+       int set_vsize;
        u32 l;
 
-       DBGPRINT(2, "plane %d channel %d paddr %u scr_width %d pos_x %d pos_y %d "
-                   "width %d height %d color_mode %d\n",
+#ifdef VERBOSE
+       dev_dbg(dispc.fbdev->dev, "plane %d channel %d paddr %#08x scr_width %d "
+                   "pos_x %d pos_y %d width %d height %d color_mode %d\n",
                    plane, channel_out, paddr, screen_width, pos_x, pos_y,
                    width, height, color_mode);
+#endif
 
+       set_vsize = 0;
        switch (plane) {
        case OMAPFB_PLANE_GFX:
                burst_shift = 6;
@@ -327,6 +323,7 @@ static inline int _setup_plane(int plane, int channel_out,
        case OMAPFB_PLANE_VID2:
                burst_shift = 14;
                chout_shift = 16;
+               set_vsize = 1;
                break;
        default:
                return -EINVAL;
@@ -343,22 +340,25 @@ static inline int _setup_plane(int plane, int channel_out,
                return -EINVAL;
        }
 
+       cconv_en = 0;
        switch (color_mode) {
        case OMAPFB_COLOR_RGB565:
                color_code = DISPC_RGB_16_BPP;
                bpp = 16;
                break;
        case OMAPFB_COLOR_YUV422:
-               if (plane != 0)
+               if (plane == 0)
                        return -EINVAL;
                color_code = DISPC_UYVY_422;
+               cconv_en = 1;
                bpp = 16;
                break;
-       case OMAPFB_COLOR_YUV420:
-               if (plane != 0)
+       case OMAPFB_COLOR_YUY422:
+               if (plane == 0)
                        return -EINVAL;
                color_code = DISPC_YUV2_422;
-               bpp = 12;
+               cconv_en = 1;
+               bpp = 16;
                break;
        default:
                return -EINVAL;
@@ -368,6 +368,8 @@ static inline int _setup_plane(int plane, int channel_out,
 
        l &= ~(0x0f << 1);
        l |= color_code << 1;
+       l &= ~(1 << 9);
+       l |= cconv_en << 9;
 
        l &= ~(0x03 << burst_shift);
        l |= DISPC_BURST_8x32 << burst_shift;
@@ -384,53 +386,145 @@ static inline int _setup_plane(int plane, int channel_out,
        MOD_REG_FLD(sz_reg[plane], FLD_MASK(16, 11) | FLD_MASK(0, 11),
                        ((height - 1) << 16) | (width - 1));
 
+       if (set_vsize) {
+               /* Set video size if set_scale hasn't set it */
+               if (!dispc.fir_hinc[plane])
+                       MOD_REG_FLD(vs_reg[plane],
+                               FLD_MASK(16, 11), (height - 1) << 16);
+               if (!dispc.fir_vinc[plane])
+                       MOD_REG_FLD(vs_reg[plane],
+                               FLD_MASK(0, 11), width - 1);
+       }
+
        dispc_write_reg(ri_reg[plane], (screen_width - width) * bpp / 8 + 1);
 
        return height * screen_width * bpp / 8;
 }
 
 static int omap_dispc_setup_plane(int plane, int channel_out,
-                                 unsigned long offset, int screen_width,
+                                 unsigned long offset,
+                                 int screen_width,
                                  int pos_x, int pos_y, int width, int height,
                                  int color_mode)
 {
-       int yspan;
        u32 paddr;
-       int mp_head = -1;
-       int r;
 
-       if (offset > dispc.fb_sram_size + dispc.fb_sdram_size)
+       if ((unsigned)plane > dispc.mem_desc.region_cnt)
                return -EINVAL;
+       paddr = dispc.mem_desc.region[plane].paddr + offset;
+       return _setup_plane(plane, channel_out, paddr,
+                       screen_width,
+                       pos_x, pos_y, width, height, color_mode);
+}
 
-       if (offset < dispc.fb_sram_size) {
-               paddr = dispc.fb_sram_paddr + offset;
-               yspan = min_t(int, height, dispc.fb_sram_lines);
-               if (yspan) {
-                       if ((r = _setup_plane(plane, channel_out, paddr,
-                                       screen_width, pos_x, pos_y,
-                                       width, height, color_mode)) < 0)
-                               return r;
-                       offset += r;
-                       height -= yspan;
-                       pos_y += yspan;
-                       mp_head = plane;
-                       if (++plane > 2)
-                               plane = OMAPFB_PLANE_GFX;
-               }
+static void write_firh_reg(int plane, int reg, u32 value)
+{
+       u32 base;
+
+       if (plane == 1)
+               base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_H0;
+       else
+               base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_H0;
+       dispc_write_reg(base + reg * 8, value);
+}
+
+static void write_firhv_reg(int plane, int reg, u32 value)
+{
+       u32 base;
+
+       if (plane == 1)
+               base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_HV0;
+       else
+               base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_HV0;
+       dispc_write_reg(base + reg * 8, value);
+}
+
+static void set_upsampling_coef_table(int plane)
+{
+       const u32 coef[][2] = {
+               { 0x00800000, 0x00800000 },
+               { 0x0D7CF800, 0x037B02FF },
+               { 0x1E70F5FF, 0x0C6F05FE },
+               { 0x335FF5FE, 0x205907FB },
+               { 0xF74949F7, 0x00404000 },
+               { 0xF55F33FB, 0x075920FE },
+               { 0xF5701EFE, 0x056F0CFF },
+               { 0xF87C0DFF, 0x027B0300 },
+       };
+       int i;
+
+       for (i = 0; i < 8; i++) {
+               write_firh_reg(plane, i, coef[i][0]);
+               write_firhv_reg(plane, i, coef[i][1]);
        }
-       if (height) {
-               offset -= dispc.fb_sram_size;
-               paddr = dispc.fb_sdram_paddr + offset;
-               yspan = min_t(int, height, dispc.fb_sdram_lines);
-               if (yspan) {
-                       if ((r = _setup_plane(plane, channel_out, paddr,
-                                       screen_width, pos_x, pos_y,
-                                       width, height, color_mode)) < 0)
-                               return r;
-                       if (mp_head != -1)
-                               dispc.multiplane_head = mp_head;
-               }
+}
+
+static int omap_dispc_set_scale(int plane,
+                               int orig_width, int orig_height,
+                               int out_width, int out_height)
+{
+       const u32 at_reg[]  = { 0, DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
+                                  DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
+       const u32 vs_reg[]  = { 0, DISPC_VID1_BASE + DISPC_VID_SIZE,
+                                  DISPC_VID2_BASE + DISPC_VID_SIZE };
+       const u32 fir_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_FIR,
+                                  DISPC_VID2_BASE + DISPC_VID_FIR };
+
+       u32 l;
+       int fir_hinc;
+       int fir_vinc;
+
+       if ((unsigned)plane > OMAPFB_PLANE_NUM)
+               return -ENODEV;
+
+       if (plane == OMAPFB_PLANE_GFX &&
+           (out_width != orig_width || out_height != orig_height))
+               return -EINVAL;
+
+       if (orig_width < out_width) {
+               /* Upsampling.
+                * Currently you can only scale both dimensions in one way.
+                */
+               if (orig_height > out_height ||
+                   orig_width * 8 < out_width ||
+                   orig_height * 8 < out_height)
+                       return -EINVAL;
+               set_upsampling_coef_table(plane);
+       } else if (orig_width > out_width) {
+               /* Downsampling not yet supported
+               */
+               return -EINVAL;
        }
+       if (!orig_width || orig_width == out_width)
+               fir_hinc = 0;
+       else
+               fir_hinc = 1024 * orig_width / out_width;
+       if (!orig_height || orig_height == out_height)
+               fir_vinc = 0;
+       else
+               fir_vinc = 1024 * orig_height / out_height;
+       dispc.fir_hinc[plane] = fir_hinc;
+       dispc.fir_vinc[plane] = fir_vinc;
+
+       MOD_REG_FLD(fir_reg[plane],
+                   FLD_MASK(16, 12) | FLD_MASK(0, 12),
+                   ((fir_vinc & 4095) << 16) |
+                   (fir_hinc & 4095));
+
+       dev_dbg(dispc.fbdev->dev, "out_width %d out_height %d orig_width %d "
+               "orig_height %d fir_hinc  %d fir_vinc %d\n",
+               out_width, out_height, orig_width, orig_height,
+               fir_hinc, fir_vinc);
+
+       MOD_REG_FLD(vs_reg[plane],
+                   FLD_MASK(16, 11) | FLD_MASK(0, 11),
+                   ((out_height - 1) << 16) | (out_width - 1));
+
+       l = dispc_read_reg(at_reg[plane]);
+       l &= ~(0x03 << 5);
+       l |= fir_hinc ? (1 << 5) : 0;
+       l |= fir_vinc ? (1 << 6) : 0;
+       dispc_write_reg(at_reg[plane], l);
 
        return 0;
 }
@@ -439,17 +533,10 @@ static int omap_dispc_enable_plane(int plane, int enable)
 {
        const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,
                                DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
-                               DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
-       DBGENTER(2);
-
-       if ((unsigned int)plane > 2)
+                               DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
+       if ((unsigned int)plane > dispc.mem_desc.region_cnt)
                return -EINVAL;
        MOD_REG_FLD(at_reg[plane], 1, enable ? 1 : 0);
-       if (plane == dispc.multiplane_head) {
-               if (++plane > 2)
-                       plane = OMAPFB_PLANE_GFX;
-               MOD_REG_FLD(at_reg[plane], 1, enable ? 1 : 0);
-       }
 
        return 0;
 }
@@ -492,6 +579,14 @@ static int omap_dispc_set_color_key(struct omapfb_color_key *ck)
                dispc_write_reg(tr_reg, ck->trans_key);
        dispc_write_reg(df_reg, ck->background);
 
+       dispc.color_key = *ck;
+
+       return 0;
+}
+
+static int omap_dispc_get_color_key(struct omapfb_color_key *ck)
+{
+       *ck = dispc.color_key;
        return 0;
 }
 
@@ -503,8 +598,6 @@ static int omap_dispc_set_update_mode(enum omapfb_update_mode mode)
 {
        int r = 0;
 
-       DBGENTER(1);
-
        if (mode != dispc.update_mode) {
                switch (mode) {
                case OMAPFB_AUTO_UPDATE:
@@ -517,7 +610,8 @@ static int omap_dispc_set_update_mode(enum omapfb_update_mode mode)
                        omap_dispc_enable_lcd_out(0);
                        if (!wait_for_completion_timeout(&dispc.frame_done,
                                        msecs_to_jiffies(500))) {
-                               pr_err("timeout waiting for FRAME DONE\n");
+                               dev_err(dispc.fbdev->dev,
+                                        "timeout waiting for FRAME DONE\n");
                        }
                        dispc.update_mode = mode;
                        break;
@@ -526,16 +620,62 @@ static int omap_dispc_set_update_mode(enum omapfb_update_mode mode)
                }
        }
 
-       DBGLEAVE(1);
-
        return r;
 }
 
+static unsigned long omap_dispc_get_caps(void)
+{
+       return 0;
+}
+
 static enum omapfb_update_mode omap_dispc_get_update_mode(void)
 {
        return dispc.update_mode;
 }
 
+static void setup_color_conv_coef(void)
+{
+       u32 mask = FLD_MASK(16, 11) | FLD_MASK(0, 11);
+       int cf1_reg = DISPC_VID1_BASE + DISPC_VID_CONV_COEF0;
+       int cf2_reg = DISPC_VID2_BASE + DISPC_VID_CONV_COEF0;
+       int at1_reg = DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES;
+       int at2_reg = DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES;
+       const struct color_conv_coef {
+               int  ry,  rcr,  rcb,   gy,  gcr,  gcb,   by,  bcr,  bcb;
+               int  full_range;
+       }  ctbl_bt601_5 = {
+                   298,  409,    0,  298, -208, -100,  298,    0,  517, 0,
+       };
+#if 0
+       const struct color_conv_coef ctbl_bt601_5_full = {
+                   256,  351,    0,  256, -179,  -86,  256,    0,  443, 1,
+       }, ctbl_bt709 = {
+                   298,  459,    0,  298, -137,  -55,  298,    0,  541, 0,
+       }, ctbl_bt709_f = {
+                   256,  394,    0,  256, -118,  -47,  256,    0,  465, 1,     },
+#endif
+       const struct color_conv_coef *ct;
+#define CVAL(x, y)     (((x & 2047) << 16) | (y & 2047))
+
+       ct = &ctbl_bt601_5;
+
+       MOD_REG_FLD(cf1_reg,            mask,   CVAL(ct->rcr, ct->ry));
+       MOD_REG_FLD(cf1_reg + 4,        mask,   CVAL(ct->gy,  ct->rcb));
+       MOD_REG_FLD(cf1_reg + 8,        mask,   CVAL(ct->gcb, ct->gcr));
+       MOD_REG_FLD(cf1_reg + 12,       mask,   CVAL(ct->bcr, ct->by));
+       MOD_REG_FLD(cf1_reg + 16,       mask,   CVAL(0,       ct->bcb));
+
+       MOD_REG_FLD(cf2_reg,            mask,   CVAL(ct->rcr, ct->ry));
+       MOD_REG_FLD(cf2_reg + 4,        mask,   CVAL(ct->gy,  ct->rcb));
+       MOD_REG_FLD(cf2_reg + 8,        mask,   CVAL(ct->gcb, ct->gcr));
+       MOD_REG_FLD(cf2_reg + 12,       mask,   CVAL(ct->bcr, ct->by));
+       MOD_REG_FLD(cf2_reg + 16,       mask,   CVAL(0,       ct->bcb));
+#undef CVAL
+
+       MOD_REG_FLD(at1_reg, (1 << 11), ct->full_range);
+       MOD_REG_FLD(at2_reg, (1 << 11), ct->full_range);
+}
+
 static void calc_ck_div(int is_tft, int pck, int *lck_div, int *pck_div)
 {
        unsigned long fck, lck;
@@ -556,8 +696,7 @@ static void calc_ck_div(int is_tft, int pck, int *lck_div, int *pck_div)
                BUG_ON(*lck_div < 1);
                if (*lck_div > 255) {
                        *lck_div = 255;
-                       printk(KERN_WARNING
-                               MODULE_NAME ": pixclock %d kHz too low.\n",
+                       dev_warn(dispc.fbdev->dev, "pixclock %d kHz too low.\n",
                                 pck / 1000);
                }
        }
@@ -579,8 +718,6 @@ static void set_lcd_timings(void)
        int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;
        unsigned long fck;
 
-       DBGENTER(1);
-
        l = dispc_read_reg(DISPC_TIMING_H);
        l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
        l |= ( max(1, (min(64,  panel->hsw))) - 1 ) << 0;
@@ -659,16 +796,15 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev, struct pt_regs *re
        u32 stat = dispc_read_reg(DISPC_IRQSTATUS);
        static int jabber;
 
-       DBGENTER(2);
-
        if (stat & DISPC_IRQ_FRAMEMASK)
                complete(&dispc.frame_done);
 
        if (stat & DISPC_IRQ_MASK_ERROR) {
                if (jabber++ < 5) {
-                       pr_err("irq error status %04x\n", stat & 0x7fff);
+                       dev_err(dispc.fbdev->dev, "irq error status %04x\n",
+                               stat & 0x7fff);
                } else {
-                       pr_err("disable irq\n");
+                       dev_err(dispc.fbdev->dev, "disable irq\n");
                        dispc_write_reg(DISPC_IRQENABLE, 0);
                }
        }
@@ -684,19 +820,19 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev, struct pt_regs *re
 static int get_dss_clocks(void)
 {
        if (IS_ERR((dispc.dss_ick = clk_get(dispc.fbdev->dev, "dss_ick")))) {
-               pr_err("can't get dss_ick");
+               dev_err(dispc.fbdev->dev, "can't get dss_ick");
                return PTR_ERR(dispc.dss_ick);
        }
 
        if (IS_ERR((dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck")))) {
-               pr_err("can't get dss1_fck");
+               dev_err(dispc.fbdev->dev, "can't get dss1_fck");
                clk_put(dispc.dss_ick);
                return PTR_ERR(dispc.dss1_fck);
        }
 
        if (IS_ERR((dispc.dss_54m_fck =
                                clk_get(dispc.fbdev->dev, "dss_54m_fck")))) {
-               pr_err("can't get dss_54m_fck");
+               dev_err(dispc.fbdev->dev, "can't get dss_54m_fck");
                clk_put(dispc.dss_ick);
                clk_put(dispc.dss1_fck);
                return PTR_ERR(dispc.dss_54m_fck);
@@ -733,199 +869,69 @@ static void enable_digit_clocks(int enable)
 
 static void omap_dispc_suspend(void)
 {
-       DBGENTER(1);
-
        if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
                init_completion(&dispc.frame_done);
                omap_dispc_enable_lcd_out(0);
                if (!wait_for_completion_timeout(&dispc.frame_done,
                                msecs_to_jiffies(500))) {
-                       pr_err("timeout waiting for FRAME DONE\n");
+                       dev_err(dispc.fbdev->dev,
+                               "timeout waiting for FRAME DONE\n");
                }
                enable_lcd_clocks(0);
        }
-
-       DBGLEAVE(1);
 }
 
 static void omap_dispc_resume(void)
 {
-       DBGENTER(1);
-
        if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
                enable_lcd_clocks(1);
                set_lcd_timings();
                load_palette();
                omap_dispc_enable_lcd_out(1);
        }
-
-       DBGLEAVE(1);
 }
 
 
-static int omap_dispc_update_window(struct omapfb_update_window *win,
+static int omap_dispc_update_window(struct fb_info *fbi,
+                                struct omapfb_update_window *win,
                                 void (*complete_callback)(void *arg),
                                 void *complete_callback_data)
 {
        return dispc.update_mode == OMAPFB_UPDATE_DISABLED ? -ENODEV : 0;
 }
 
-/* Greatest common divisor */
-static int calc_gcd(int a, int b)
-{
-       int tmp;
-
-       if (a < b) {
-               tmp = a;
-               a = b;
-               b = tmp;
-       }
-       for (;;) {
-               tmp = a % b;
-               if (tmp != 0) {
-                       a = b;
-                       b = tmp;
-               } else
-                       break;
-       }
-
-       return b;
-}
-
-/* Least common multiple */
-static int calc_lcm(int a, int b)
-{
-       return a * b / calc_gcd(a, b);
-}
-
-static void omap_dispc_get_vram_layout(unsigned long *size, void **virt,
-                                       dma_addr_t *phys)
-{
-       *size = dispc.fb_sram_size + dispc.fb_sdram_size;
-       *virt = dispc.fb_kern_vaddr;
-       /* Physical vram might not be contiguous. No one except own mmap
-        * should use this addr.
-        */
-       *phys = 0;
-}
-
-static int omap_dispc_mmap_user(struct vm_area_struct *vma)
-{
-       unsigned long len;
-       unsigned long offset;
-       unsigned long vaddr;
-       int r;
-
-       DBGPRINT(1, "vm_pgoff 0x%08lx vm_start 0x%08lx vm_end 0x%08lx\n",
-                       vma->vm_pgoff, vma->vm_start, vma->vm_end);
-
-       if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-               return -EINVAL;
-       offset = vma->vm_pgoff << PAGE_SHIFT;
-
-       if (offset >= dispc.fb_sram_size + dispc.fb_sdram_size)
-               return -EINVAL;
-
-       len = vma->vm_end - vma->vm_start;
-       if (offset + len > dispc.fb_sram_size + dispc.fb_sdram_size)
-               return -EINVAL;
-
-       vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-       vma->vm_flags |= VM_PFNMAP;
-
-       vaddr = vma->vm_start;
-
-       if (dispc.fb_sram_size) {
-               if (offset < dispc.fb_sram_size) {
-                       int chunk = min_t(int, dispc.fb_sram_size - offset, len);
-                       DBGPRINT(1, "map sram va %08lx pa %08lx size %d\n",
-                                vaddr, dispc.fb_sram_paddr + offset, chunk);
-                       r = io_remap_pfn_range(vma, vaddr,
-                                          (dispc.fb_sram_paddr +
-                                          offset) >> PAGE_SHIFT, chunk,
-                                          vma->vm_page_prot);
-                       if (r == -EINVAL)
-                               return r;
-                       if (r < 0)
-                               return -EAGAIN;
-
-                       vaddr += chunk;
-                       len -= chunk;
-                       offset = 0;
-               } else
-                       offset -= dispc.fb_sram_size;
-       }
-
-       if (len) {
-               DBGPRINT(1, "map sdram va %08lx pa %08lx size %ld\n",
-                                vaddr, dispc.fb_sdram_paddr + offset, len);
-               BUG_ON(offset > dispc.fb_sdram_size ||
-                       offset + len > dispc.fb_sdram_size ||
-                       vma->vm_end - vaddr != len);
-               r = io_remap_pfn_range(vma, vaddr, (dispc.fb_sdram_paddr +
-                                  offset) >> PAGE_SHIFT, len,
-                                  vma->vm_page_prot);
-               /* no teardown of the previous mapping here.
-                * do_mmap_pgoff will take core of that. */
-               if (r == -EINVAL)
-                       return r;
-               if (r < 0)
-                       return -EAGAIN;
-       }
-
-       return 0;
-}
-
-static int mmap_kern(void)
+static int mmap_kern(struct omapfb_mem_region *region)
 {
        struct vm_struct        *kvma;
        struct vm_area_struct   vma;
        pgprot_t                pgprot;
        unsigned long           vaddr;
 
-       DBGENTER(1);
-
-       kvma = get_vm_area(dispc.fb_sram_size + dispc.fb_sdram_size, VM_IOREMAP);
+       kvma = get_vm_area(region->size, VM_IOREMAP);
        if (kvma == NULL) {
-               pr_err("can't get kernel vm area\n");
+               dev_err(dispc.fbdev->dev, "can't get kernel vm area\n");
                return -ENOMEM;
        }
        vma.vm_mm = &init_mm;
 
-       dispc.fb_kern_vaddr = kvma->addr;
        vaddr = (unsigned long)kvma->addr;
 
        pgprot = pgprot_writecombine(pgprot_kernel);
-       if (dispc.fb_sram_size) {
-               vma.vm_start = vaddr;
-               vma.vm_end = vaddr + dispc.fb_sram_size;
-               if (io_remap_pfn_range(&vma, vaddr,
-                                  dispc.fb_sram_paddr >> PAGE_SHIFT,
-                                  dispc.fb_sram_size, pgprot) < 0) {
-                       pr_err("kernel mmap for FBMEM failed\n");
-                       return -EAGAIN;
-               }
-               vaddr += dispc.fb_sram_size;
-       }
-       if (dispc.fb_sdram_size) {
-               vma.vm_start = vaddr;
-               vma.vm_end = vaddr + dispc.fb_sdram_size;
-               if (io_remap_pfn_range(&vma, vaddr,
-                                  dispc.fb_sdram_paddr >> PAGE_SHIFT,
-                                  dispc.fb_sdram_size, pgprot) < 0) {
-                       pr_err("kernel mmap for FBMEM failed\n");
-                       return -EAGAIN;
-               }
+       vma.vm_start = vaddr;
+       vma.vm_end = vaddr + region->size;
+       if (io_remap_pfn_range(&vma, vaddr, region->paddr >> PAGE_SHIFT,
+                          region->size, pgprot) < 0) {
+               dev_err(dispc.fbdev->dev, "kernel mmap for FBMEM failed\n");
+               return -EAGAIN;
        }
-
-       DBGLEAVE(1);
+       region->vaddr = (void *)vaddr;
 
        return 0;
 }
 
-static void unmap_kern(void)
+static void unmap_kern(struct omapfb_mem_region *region)
 {
-       vunmap(dispc.fb_kern_vaddr);
+       vunmap(region->vaddr);
 }
 
 static int alloc_palette_ram(void)
@@ -933,7 +939,7 @@ static int alloc_palette_ram(void)
        dispc.palette_vaddr = dma_alloc_writecombine(dispc.fbdev->dev,
                MAX_PALETTE_SIZE, &dispc.palette_paddr, GFP_KERNEL);
        if (dispc.palette_vaddr == NULL) {
-               pr_err("failed to alloc palette memory\n");
+               dev_err(dispc.fbdev->dev, "failed to alloc palette memory\n");
                return -ENOMEM;
        }
 
@@ -946,107 +952,76 @@ static void free_palette_ram(void)
                        dispc.palette_vaddr, dispc.palette_paddr);
 }
 
-static int alloc_fbmem(int req_size)
+static int alloc_fbmem(struct omapfb_mem_region *region)
 {
-       int frame_size;
-       struct lcd_panel *panel = dispc.fbdev->panel;
+       region->vaddr = dma_alloc_writecombine(dispc.fbdev->dev,
+                       region->size, &region->paddr, GFP_KERNEL);
 
-       frame_size = PAGE_ALIGN(panel->x_res * panel->bpp / 8 * panel->y_res);
-       if (req_size > frame_size)
-               frame_size = req_size;
-       dispc.fb_sdram_size = PAGE_ALIGN(MAX_PALETTE_SIZE) + frame_size;
-       dispc.fb_kern_vaddr = dma_alloc_writecombine(dispc.fbdev->dev,
-                       dispc.fb_sdram_size, &dispc.fb_sdram_paddr, GFP_KERNEL);
-
-       if (dispc.fb_kern_vaddr == 0) {
-               pr_err("unable to allocate fb DMA memory\n");
+       if (region->vaddr == NULL) {
+               dev_err(dispc.fbdev->dev, "unable to allocate FB DMA memory\n");
                return -ENOMEM;
        }
 
        return 0;
 }
 
-static void free_fbmem(void)
+static void free_fbmem(struct omapfb_mem_region *region)
 {
-       dma_free_writecombine(dispc.fbdev->dev, dispc.fb_sdram_size,
-                             dispc.fb_kern_vaddr, dispc.fb_sdram_paddr);
+       dma_free_writecombine(dispc.fbdev->dev, region->size,
+                             region->vaddr, region->paddr);
 }
 
-static int setup_fbmem(int req_size)
+static int setup_fbmem(struct omapfb_mem_desc *req_md)
 {
-       struct lcd_panel *panel = dispc.fbdev->panel;
-       struct omapfb_platform_data *conf;
-       unsigned long size_align;
-       int line_size;
-       int frame_size;
-       int lines;
+       struct omapfb_mem_region        *rg;
+       int i;
        int r;
 
-       conf = dispc.fbdev->dev->platform_data;
-
-       if (conf->fbmem.fb_sram_size + conf->fbmem.fb_sdram_size == 0) {
-               if ((r = alloc_fbmem(req_size)) < 0)
-                       return r;
-               dispc.fbmem_allocated = 1;
-               dispc.fb_sdram_lines = panel->y_res;
-               return 0;
+       if (!req_md->region_cnt) {
+               dev_err(dispc.fbdev->dev, "no memory regions defined\n");
+               return -ENOENT;
        }
 
-       dispc.fb_sram_paddr = conf->fbmem.fb_sram_start;
-       dispc.fb_sram_size = conf->fbmem.fb_sram_size;
-       dispc.fb_sdram_paddr = conf->fbmem.fb_sdram_start;
-       dispc.fb_sdram_size = conf->fbmem.fb_sdram_size;
-
-       line_size = panel->x_res * panel->bpp / 8;
-       frame_size = PAGE_ALIGN(line_size * panel->y_res);
+       rg = &req_md->region[0];
 
-       size_align = calc_lcm(line_size, PAGE_SIZE);
-
-       if (dispc.fb_sram_size + dispc.fb_sdram_size < frame_size ||
-           (dispc.fb_sdram_size && (dispc.fb_sram_size % size_align))) {
-               pr_err("Invalid FB memory configuration\n");
-               return -EINVAL;
-       }
-
-       if (dispc.fb_sram_size + dispc.fb_sdram_size < req_size) {
-               pr_err("%d vram was requested, but only %u is available\n",
-                       req_size, dispc.fb_sram_size + dispc.fb_sdram_size);
+       for (i = 0; i < req_md->region_cnt; i++, rg++) {
+               if (rg->paddr) {
+                       rg->alloc = 0;
+                       if ((r = mmap_kern(rg)) < 0)
+                               return r;
+               } else {
+                       rg->alloc = 1;
+                       if ((r = alloc_fbmem(rg)) < 0)
+                               return r;
+               }
        }
 
-       lines = dispc.fb_sram_size / line_size;
-       lines = min_t(int, panel->y_res, lines);
-       dispc.fb_sram_lines = lines;
-       lines = panel->y_res - lines;
-       dispc.fb_sdram_lines = lines;
-
-       if ((r = mmap_kern()) < 0)
-               return r;
-
-       DBGPRINT(1, "fb_sram %08x size %08x fb_sdram %08x size %08x\n",
-                dispc.fb_sram_paddr, dispc.fb_sram_size,
-                dispc.fb_sdram_paddr, dispc.fb_sdram_size);
+       dispc.mem_desc = *req_md;
 
        return 0;
 }
 
 static void cleanup_fbmem(void)
 {
-       if (dispc.fbmem_allocated)
-               free_fbmem();
-       else
-               unmap_kern();
+       int i;
+
+       for (i = 0; i < dispc.mem_desc.region_cnt; i++) {
+               if (dispc.mem_desc.region[i].alloc)
+                       free_fbmem(&dispc.mem_desc.region[i]);
+               else
+                       unmap_kern(&dispc.mem_desc.region[i]);
+       }
 }
 
 static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
-                          int req_vram_size)
+                          struct omapfb_mem_desc *req_vram)
 {
        int r;
        u32 l;
        struct lcd_panel *panel = fbdev->panel;
        int tmo = 10000;
        int skip_init = 0;
-
-       DBGENTER(1);
+       int i;
 
        memset(&dispc, 0, sizeof(dispc));
 
@@ -1054,13 +1029,6 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
        dispc.fbdev = fbdev;
        dispc.ext_mode = ext_mode;
 
-       dispc.multiplane_head = -1;
-
-       if (fbdev->dev->platform_data == NULL) {
-               pr_err("missing FB configuration\n");
-               return -ENOENT;
-       }
-
        init_completion(&dispc.frame_done);
 
        if ((r = get_dss_clocks()) < 0)
@@ -1068,14 +1036,11 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
 
        enable_lcd_clocks(1);
 
-       l = dispc_read_reg(DISPC_REVISION);
-       pr_info(MODULE_NAME ": version %d.%d\n", l >> 4 & 0x0f, l & 0x0f);
-
 #ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
        l = dispc_read_reg(DISPC_CONTROL);
        /* LCD enabled ? */
        if (l & 1) {
-               pr_info(MODULE_NAME ": skipping hardware initialization\n");
+               pr_info("omapfb: skipping hardware initialization\n");
                skip_init = 1;
        }
 #endif
@@ -1089,7 +1054,7 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
 
                while (!(dispc_read_reg(DISPC_SYSSTATUS) & 1)) {
                        if (!--tmo) {
-                               pr_err("soft reset failed\n");
+                               dev_err(dispc.fbdev->dev, "soft reset failed\n");
                                r = -ENODEV;
                                enable_digit_clocks(0);
                                goto fail1;
@@ -1106,8 +1071,8 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
        omap_dispc_enable_irqs(DISPC_IRQ_FRAMEMASK);
 
        if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler,
-                          0, MODULE_NAME, NULL)) < 0) {
-               pr_err("can't get DSS IRQ\n");
+                          0, MODULE_NAME, fbdev)) < 0) {
+               dev_err(dispc.fbdev->dev, "can't get DSS IRQ\n");
                goto fail1;
        }
 
@@ -1117,12 +1082,14 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
        if ((r = alloc_palette_ram()) < 0)
                goto fail2;
 
-       if ((r = setup_fbmem(req_vram_size)) < 0)
+       if ((r = setup_fbmem(req_vram)) < 0)
                goto fail3;
 
        if (!skip_init) {
-               memset(dispc.fb_kern_vaddr, 0,
-                       dispc.fb_sram_size + dispc.fb_sdram_size);
+               for (i = 0; i < dispc.mem_desc.region_cnt; i++) {
+                       memset(dispc.mem_desc.region[i].vaddr, 0,
+                               dispc.mem_desc.region[i].size);
+               }
 
                /* Set logic clock to fck, pixel clock to fck/2 for now */
                MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(16, 8), 1 << 16);
@@ -1132,22 +1099,29 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
                setup_plane_fifo(1);
                setup_plane_fifo(2);
 
+               setup_color_conv_coef();
+
                set_lcd_tft_mode(panel->config & OMAP_LCDC_PANEL_TFT);
-               set_lcd_data_lines(panel->data_lines);
                set_load_mode(DISPC_LOAD_FRAME_ONLY);
 
                if (!ext_mode) {
+                       set_lcd_data_lines(panel->data_lines);
                        omap_dispc_set_lcd_size(panel->x_res, panel->y_res);
                        set_lcd_timings();
-               }
+               } else
+                       set_lcd_data_lines(panel->bpp);
                enable_rfbi_mode(ext_mode);
        }
 
+       l = dispc_read_reg(DISPC_REVISION);
+       pr_info("omapfb: DISPC version %d.%d initialized\n",
+                l >> 4 & 0x0f, l & 0x0f);
+
        return 0;
 fail3:
        free_palette_ram();
 fail2:
-       free_irq(INT_24XX_DSS_IRQ, NULL);
+       free_irq(INT_24XX_DSS_IRQ, fbdev);
 fail1:
        enable_lcd_clocks(0);
        put_dss_clocks();
@@ -1164,17 +1138,10 @@ static void omap_dispc_cleanup(void)
        put_dss_clocks();
 }
 
-static unsigned long omap_dispc_get_caps(void)
-{
-       return 0;
-}
-
-struct lcd_ctrl omap2_int_ctrl = {
+const struct lcd_ctrl omap2_int_ctrl = {
        .name                   = "internal",
        .init                   = omap_dispc_init,
        .cleanup                = omap_dispc_cleanup,
-       .get_vram_layout        = omap_dispc_get_vram_layout,
-       .mmap                   = omap_dispc_mmap_user,
        .get_caps               = omap_dispc_get_caps,
        .set_update_mode        = omap_dispc_set_update_mode,
        .get_update_mode        = omap_dispc_get_update_mode,
@@ -1182,9 +1149,8 @@ struct lcd_ctrl omap2_int_ctrl = {
        .suspend                = omap_dispc_suspend,
        .resume                 = omap_dispc_resume,
        .setup_plane            = omap_dispc_setup_plane,
+       .set_scale              = omap_dispc_set_scale,
        .enable_plane           = omap_dispc_enable_plane,
        .set_color_key          = omap_dispc_set_color_key,
+       .get_color_key          = omap_dispc_get_color_key,
 };
-
-MODULE_DESCRIPTION("TI OMAP LCDC controller");
-MODULE_LICENSE("GPL");
index f466c4b5b2b889aaf420c7fe7c9b11cf2ebc15b3..0f8e2fbee7167a072c87045acaa7b7ff6a269eab 100644 (file)
 #include <asm/arch/dma.h>
 #include <asm/arch/omapfb.h>
 
-/* #define OMAPFB_DBG 1 */
-
-#include "debug.h"
-
-#define MODULE_NAME                    "omapfb-hwa742"
+#define MODULE_NAME              "hwa742"
 
 #define HWA742_REV_CODE_REG       0x0
 #define HWA742_CONFIG_REG         0x2
 
 #define HWA742_AUTO_UPDATE_TIME                (HZ / 20)
 
-#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
-
 /* Reserve 4 request slots for requests in irq context */
 #define REQ_POOL_SIZE                  24
 #define IRQ_REQ_POOL_SIZE              4
 
+#define REQ_FROM_IRQ_POOL 0x01
+
+#define REQ_COMPLETE   0
+#define REQ_PENDING    1
+
 struct update_param {
        int     x, y, width, height;
        int     color_mode;
        int     flags;
 };
 
-#define REQ_FROM_IRQ_POOL 0x01
-
-#define REQ_COMPLETE   0
-#define REQ_PENDING    1
-
 struct hwa742_request {
        struct list_head entry;
        unsigned int     flags;
@@ -111,7 +105,7 @@ struct hwa742_request {
        } par;
 };
 
-struct hwa742_struct {
+struct {
        enum omapfb_update_mode update_mode;
        enum omapfb_update_mode update_mode_before_suspend;
 
@@ -140,6 +134,8 @@ struct hwa742_struct {
        struct lcd_ctrl         *int_ctrl;
 } hwa742;
 
+struct lcd_ctrl hwa742_ctrl;
+
 static u8 hwa742_read_reg(u8 reg)
 {
        u8 data;
@@ -186,10 +182,14 @@ static void set_format_regs(int conv, int transl, int flags)
 {
        if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) {
                hwa742.window_type = ((hwa742.window_type & 0xfc) | 0x01);
-               DBGPRINT(2, "hwa742: enabled pixel doubling\n");
+#ifdef VERBOSE
+               dev_dbg(hwa742.fbdev->dev, "hwa742: enabled pixel doubling\n");
+#endif
        } else {
                hwa742.window_type = (hwa742.window_type & 0xfc);
-               DBGPRINT(2, "hwa742: disabled pixel doubling\n");
+#ifdef VERBOSE
+               dev_dbg(hwa742.fbdev->dev, "hwa742: disabled pixel doubling\n");
+#endif
        }
 
        hwa742_write_reg(HWA742_INPUT_MODE_REG, conv);
@@ -239,8 +239,6 @@ static void process_pending_requests(void)
 {
        unsigned long flags;
 
-       DBGENTER(2);
-
        spin_lock_irqsave(&hwa742.req_lock, flags);
 
        while (!list_empty(&hwa742.pending_req_list)) {
@@ -266,8 +264,6 @@ static void process_pending_requests(void)
        }
 
        spin_unlock_irqrestore(&hwa742.req_lock, flags);
-
-       DBGLEAVE(2);
 }
 
 static void submit_req_list(struct list_head *head)
@@ -275,8 +271,6 @@ static void submit_req_list(struct list_head *head)
        unsigned long flags;
        int process = 1;
 
-       DBGENTER(2);
-
        spin_lock_irqsave(&hwa742.req_lock, flags);
        if (likely(!list_empty(&hwa742.pending_req_list)))
                process = 0;
@@ -285,8 +279,6 @@ static void submit_req_list(struct list_head *head)
 
        if (process)
                process_pending_requests();
-
-       DBGLEAVE(2);
 }
 
 static void request_complete(void *data)
@@ -320,8 +312,11 @@ static int send_frame_handler(struct hwa742_request *req)
        int flags = par->flags;
        int scr_width = 800;
 
-       DBGPRINT(2, "x %d y %d w %d h %d scr_width %d color_mode %d flags %d\n",
+#ifdef VERBOSE
+       dev_dbg(hwa742.fbdev->dev, "x %d y %d w %d h %d scr_width %d "
+               "color_mode %d flags %d\n",
                x, y, w, h, scr_width, color_mode, flags);
+#endif
 
        switch (color_mode) {
        case OMAPFB_COLOR_YUV422:
@@ -425,13 +420,9 @@ static void create_req_list(struct omapfb_update_window *win,
 
 static void auto_update_complete(void *data)
 {
-       DBGENTER(2);
-
        if (!hwa742.stop_auto_update)
                mod_timer(&hwa742.auto_update_timer,
                          jiffies + HWA742_AUTO_UPDATE_TIME);
-
-       DBGLEAVE(2);
 }
 
 static void hwa742_update_window_auto(unsigned long arg)
@@ -439,8 +430,6 @@ static void hwa742_update_window_auto(unsigned long arg)
        LIST_HEAD(req_list);
        struct hwa742_request *last;
 
-       DBGENTER(2);
-
        create_req_list(&hwa742.auto_update_window, &req_list);
        last = list_entry(req_list.prev, struct hwa742_request, entry);
 
@@ -448,11 +437,10 @@ static void hwa742_update_window_auto(unsigned long arg)
        last->complete_data = NULL;
 
        submit_req_list(&req_list);
-
-       DBGLEAVE(2);
 }
 
-int hwa742_update_window_async(struct omapfb_update_window *win,
+int hwa742_update_window_async(struct fb_info *fbi,
+                                struct omapfb_update_window *win,
                                 void (*complete_callback)(void *arg),
                                 void *complete_callback_data)
 {
@@ -460,15 +448,13 @@ int hwa742_update_window_async(struct omapfb_update_window *win,
        struct hwa742_request *last;
        int r = 0;
 
-       DBGENTER(2);
-
        if (hwa742.update_mode != OMAPFB_MANUAL_UPDATE) {
-               DBGPRINT(1, "invalid update mode\n");
+               dev_dbg(hwa742.fbdev->dev, "invalid update mode\n");
                r = -EINVAL;
                goto out;
        }
        if (unlikely(win->format & ~(0x03 | OMAPFB_FORMAT_FLAG_DOUBLE))) {
-               DBGPRINT(1, "invalid window flag");
+               dev_dbg(hwa742.fbdev->dev, "invalid window flag");
                r = -EINVAL;
                goto out;
        }
@@ -482,7 +468,6 @@ int hwa742_update_window_async(struct omapfb_update_window *win,
        submit_req_list(&req_list);
 
 out:
-       DBGLEAVE(2);
        return r;
 }
 EXPORT_SYMBOL(hwa742_update_window_async);
@@ -521,8 +506,6 @@ static void hwa742_sync(void)
        struct hwa742_request *req;
        struct completion comp;
 
-       DBGENTER(2);
-
        req = alloc_req();
 
        req->handler = sync_handler;
@@ -534,13 +517,11 @@ static void hwa742_sync(void)
        submit_req_list(&req_list);
 
        wait_for_completion(&comp);
-
-       DBGLEAVE(2);
 }
 
 static void hwa742_bind_client(struct omapfb_notifier_block *nb)
 {
-       DBGPRINT(1, "update_mode %d\n", hwa742.update_mode);
+       dev_dbg(hwa742.fbdev->dev, "update_mode %d\n", hwa742.update_mode);
        if (hwa742.update_mode == OMAPFB_MANUAL_UPDATE) {
                omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY);
        }
@@ -548,20 +529,14 @@ static void hwa742_bind_client(struct omapfb_notifier_block *nb)
 
 static int hwa742_set_update_mode(enum omapfb_update_mode mode)
 {
-       int r = 0;
-
-       DBGENTER(1);
-
        if (mode != OMAPFB_MANUAL_UPDATE && mode != OMAPFB_AUTO_UPDATE &&
-           mode != OMAPFB_UPDATE_DISABLED) {
-               r = -EINVAL;
-               goto out;
-       }
+           mode != OMAPFB_UPDATE_DISABLED)
+               return -EINVAL;
 
        if (mode == hwa742.update_mode)
-               goto out;
+               return 0;
 
-       printk(KERN_INFO "hwa742: setting update mode to %s\n",
+       pr_info("omapfb: hwa742: setting update mode to %s\n",
                        mode == OMAPFB_UPDATE_DISABLED ? "disabled" :
                        (mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual"));
 
@@ -591,10 +566,8 @@ static int hwa742_set_update_mode(enum omapfb_update_mode mode)
        case OMAPFB_UPDATE_DISABLED:
                break;
        }
-out:
 
-       DBGLEAVE(1);
-       return r;
+       return 0;
 }
 
 static enum omapfb_update_mode hwa742_get_update_mode(void)
@@ -622,7 +595,7 @@ static int calc_reg_timing(unsigned long sysclk, int div)
         * WriteCycle = 2*SYSCLK + 2 ns,
         * CSPulseWidth = 10 ns */
        systim = 1000000000 / (sysclk / 1000);
-       DBGPRINT(1, "HWA742 systim %lu ps extif_clk_period %u ps"
+       dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps"
                  "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div);
 
        t = &hwa742.reg_timings;
@@ -643,12 +616,12 @@ static int calc_reg_timing(unsigned long sysclk, int div)
                t->re_cycle_time = t->re_off_time;
        t->cs_pulse_width = 0;
 
-       DBGPRINT(1, "[reg]cson %d csoff %d reon %d reoff %d\n",
+       dev_dbg(hwa742.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n",
                 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
-       DBGPRINT(1, "[reg]weon %d weoff %d recyc %d wecyc %d\n",
+       dev_dbg(hwa742.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n",
                 t->we_on_time, t->we_off_time, t->re_cycle_time,
                 t->we_cycle_time);
-       DBGPRINT(1, "[reg]rdaccess %d cspulse %d\n",
+       dev_dbg(hwa742.fbdev->dev, "[reg]rdaccess %d cspulse %d\n",
                 t->access_time, t->cs_pulse_width);
 
        return hwa742.extif->convert_timings(t);
@@ -669,7 +642,7 @@ static int calc_lut_timing(unsigned long sysclk, int div)
         * CSPulseWidth = 10 ns
         */
        systim = 1000000000 / (sysclk / 1000);
-       DBGPRINT(1, "HWA742 systim %lu ps extif_clk_period %u ps"
+       dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps"
                  "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div);
 
        t = &hwa742.lut_timings;
@@ -694,12 +667,12 @@ static int calc_lut_timing(unsigned long sysclk, int div)
                t->re_cycle_time = t->re_off_time;
        t->cs_pulse_width = 0;
 
-       DBGPRINT(1, "[lut]cson %d csoff %d reon %d reoff %d\n",
+       dev_dbg(hwa742.fbdev->dev, "[lut]cson %d csoff %d reon %d reoff %d\n",
                 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
-       DBGPRINT(1, "[lut]weon %d weoff %d recyc %d wecyc %d\n",
+       dev_dbg(hwa742.fbdev->dev, "[lut]weon %d weoff %d recyc %d wecyc %d\n",
                 t->we_on_time, t->we_off_time, t->re_cycle_time,
                 t->we_cycle_time);
-       DBGPRINT(1, "[lut]rdaccess %d cspulse %d\n",
+       dev_dbg(hwa742.fbdev->dev, "[lut]rdaccess %d cspulse %d\n",
                 t->access_time, t->cs_pulse_width);
 
        return hwa742.extif->convert_timings(t);
@@ -727,7 +700,7 @@ static int calc_extif_timings(unsigned long sysclk)
                return 0;
 
 err:
-       pr_err("can't setup timings\n");
+       dev_err(hwa742.fbdev->dev, "can't setup timings\n");
        return -1;
 }
 
@@ -748,7 +721,7 @@ static void hwa742_suspend(void)
 static void hwa742_resume(void)
 {
        if (clk_enable(hwa742.sys_ck) != 0)
-               pr_err("failed to enable SYS clock\n");
+               dev_err(hwa742.fbdev->dev, "failed to enable SYS clock\n");
        /* Disable sleep mode */
        hwa742_write_reg(HWA742_POWER_SAVE, 0);
        while (1) {
@@ -761,25 +734,24 @@ static void hwa742_resume(void)
        hwa742_set_update_mode(hwa742.update_mode_before_suspend);
 }
 
-struct lcd_ctrl hwa742_ctrl;
-
-static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, int req_vram_size)
+static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
+                      struct omapfb_mem_desc *req_vram)
 {
        int r = 0, i;
        u8 rev, conf;
        unsigned long sysfreq;
        int div, nd;
 
-       DBGENTER(1);
+       hwa742.fbdev = fbdev;
 
        hwa742.sys_ck = clk_get(0, "bclk");
        if (IS_ERR(hwa742.sys_ck)) {
-               pr_err("can't get SYS clock\n");
+               dev_err(fbdev->dev, "can't get SYS clock\n");
                return PTR_ERR(hwa742.sys_ck);
        }
 
        if ((r = clk_enable(hwa742.sys_ck)) != 0) {
-               pr_err("can't enable SYS clock\n");
+               dev_err(fbdev->dev, "can't enable SYS clock\n");
                clk_put(hwa742.sys_ck);
                return r;
        }
@@ -792,15 +764,12 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, int req_vram_s
 
        spin_lock_init(&hwa742.req_lock);
 
-       if ((r = hwa742.int_ctrl->init(fbdev, 1, req_vram_size)) < 0)
+       if ((r = hwa742.int_ctrl->init(fbdev, 1, req_vram)) < 0)
                goto err1;
 
-       if ((r = hwa742.extif->init()) < 0)
+       if ((r = hwa742.extif->init(fbdev)) < 0)
                goto err2;
 
-       hwa742_ctrl.get_vram_layout = hwa742.int_ctrl->get_vram_layout;
-       hwa742_ctrl.mmap = hwa742.int_ctrl->mmap;
-
        sysfreq = clk_get_rate(hwa742.sys_ck);
        if ((r = calc_extif_timings(sysfreq)) < 0)
                goto err3;
@@ -816,17 +785,14 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, int req_vram_s
 
        rev = hwa742_read_reg(HWA742_REV_CODE_REG);
        if ((rev & 0xfc) != 0x80) {
-               pr_err("invalid revision %02x\n", rev);
+               dev_err(fbdev->dev, "invalid revision %02x\n", rev);
                r = -ENODEV;
                goto err3;
        }
 
-       conf = hwa742_read_reg(HWA742_CONFIG_REG);
-       pr_info(MODULE_NAME ": Epson HWA742 LCD controller rev. %d "
-                       "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
-
        if (!(hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x80)) {
-               pr_err("controller not initialized by the bootloader\n");
+               dev_err(hwa742.fbdev->dev,
+                       "controller not initialized by the bootloader\n");
                r = -ENODEV;
                goto err2;
        }
@@ -848,8 +814,6 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, int req_vram_s
        hwa742.prev_color_mode = -1;
        hwa742.prev_flags = 0;
 
-       hwa742.fbdev = fbdev;
-
        INIT_LIST_HEAD(&hwa742.free_req_list);
        INIT_LIST_HEAD(&hwa742.pending_req_list);
        for (i = 0; i < ARRAY_SIZE(hwa742.req_pool); i++)
@@ -857,6 +821,10 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, int req_vram_s
        BUG_ON(i <= IRQ_REQ_POOL_SIZE);
        sema_init(&hwa742.req_sema, i - IRQ_REQ_POOL_SIZE);
 
+       conf = hwa742_read_reg(HWA742_CONFIG_REG);
+       pr_info("omapfb: hwa742 LCD controller rev. %d "
+                       "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+
        return 0;
 err3:
        hwa742.extif->cleanup();
index a86cd73fa9167e926900281eca344d4dcf2dfae9..87ae40b82bceda61d2d1452f48a3a3835b110c02 100644 (file)
@@ -20,7 +20,6 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/device.h>
 
 #include <asm/mach-types.h>
 
-/* #define OMAPFB_DBG 1 */
-
-#include "debug.h"
-
-#define MODULE_NAME                    "omapfb-lcdc"
+#define MODULE_NAME                    "lcdc"
 
 #define OMAP_LCDC_BASE                 0xfffec000
 #define OMAP_LCDC_SIZE                 256
@@ -78,8 +73,6 @@
 
 #define MAX_PALETTE_SIZE               PAGE_SIZE
 
-#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
-
 enum lcdc_load_mode {
        OMAP_LCDC_LOAD_PALETTE,
        OMAP_LCDC_LOAD_FRAME,
@@ -115,16 +108,16 @@ static struct omap_lcd_controller {
        dma_addr_t              vram_phys;
        void                    *vram_virt;
        unsigned long           vram_size;
-} omap_lcdc;
+} lcdc;
 
 static void inline enable_irqs(int mask)
 {
-       omap_lcdc.irq_mask |= mask;
+       lcdc.irq_mask |= mask;
 }
 
 static void inline disable_irqs(int mask)
 {
-       omap_lcdc.irq_mask &= ~mask;
+       lcdc.irq_mask &= ~mask;
 }
 
 static void set_load_mode(enum lcdc_load_mode mode)
@@ -155,7 +148,7 @@ static void enable_controller(void)
        l = omap_readl(OMAP_LCDC_CONTROL);
        l |= OMAP_LCDC_CTRL_LCD_EN;
        l &= ~OMAP_LCDC_IRQ_MASK;
-       l |= omap_lcdc.irq_mask | OMAP_LCDC_IRQ_DONE;   /* enabled IRQs */
+       l |= lcdc.irq_mask | OMAP_LCDC_IRQ_DONE;        /* enabled IRQs */
        omap_writel(l, OMAP_LCDC_CONTROL);
 }
 
@@ -176,11 +169,11 @@ static void disable_controller_async(void)
 
 static void disable_controller(void)
 {
-       init_completion(&omap_lcdc.last_frame_complete);
+       init_completion(&lcdc.last_frame_complete);
        disable_controller_async();
-       if (!wait_for_completion_timeout(&omap_lcdc.last_frame_complete,
+       if (!wait_for_completion_timeout(&lcdc.last_frame_complete,
                                msecs_to_jiffies(500)))
-               pr_err("timeout waiting for FRAME DONE\n");
+               dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n");
 }
 
 static void reset_controller(u32 status)
@@ -191,7 +184,8 @@ static void reset_controller(u32 status)
        disable_controller_async();
        reset_count++;
        if (reset_count == 1 || time_after(jiffies, last_jiffies + HZ)) {
-               pr_err("resetting (status %#010x,reset count %lu)\n",
+               dev_err(lcdc.fbdev->dev,
+                         "resetting (status %#010x,reset count %lu)\n",
                          status, reset_count);
                last_jiffies = jiffies;
        }
@@ -199,12 +193,13 @@ static void reset_controller(u32 status)
                enable_controller();
        } else {
                reset_count = 0;
-               pr_err("too many reset attempts, giving up.\n");
+               dev_err(lcdc.fbdev->dev,
+                       "too many reset attempts, giving up.\n");
        }
 }
 
 /* Configure the LCD DMA according to the current mode specified by parameters
- * in omap_lcdc.fbdev and fbdev->var.
+ * in lcdc.fbdev and fbdev->var.
  */
 static void setup_lcd_dma(void)
 {
@@ -215,22 +210,23 @@ static void setup_lcd_dma(void)
                0,
                OMAP_DMA_DATA_TYPE_S32,
        };
-       struct fb_var_screeninfo *var = &omap_lcdc.fbdev->fb_info->var;
+       struct omapfb_plane_struct *plane = lcdc.fbdev->fb_info[0]->par;
+       struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var;
        unsigned long   src;
        int             esize, xelem, yelem;
 
-       src = omap_lcdc.vram_phys + omap_lcdc.frame_offset;
+       src = lcdc.vram_phys + lcdc.frame_offset;
 
        switch (var->rotate) {
        case 0:
-               if (omap_lcdc.fbdev->mirror || (src & 3) ||
-                   omap_lcdc.color_mode == OMAPFB_COLOR_YUV420 ||
-                   (omap_lcdc.xres & 1))
+               if (plane->info.mirror || (src & 3) ||
+                   lcdc.color_mode == OMAPFB_COLOR_YUV420 ||
+                   (lcdc.xres & 1))
                        esize = 2;
                else
                        esize = 4;
-               xelem = omap_lcdc.xres * omap_lcdc.bpp / 8 / esize;
-               yelem = omap_lcdc.yres;
+               xelem = lcdc.xres * lcdc.bpp / 8 / esize;
+               yelem = lcdc.yres;
                break;
        case 90:
        case 180:
@@ -239,30 +235,33 @@ static void setup_lcd_dma(void)
                        BUG();
                }
                esize = 2;
-               xelem = omap_lcdc.yres * omap_lcdc.bpp / 16;
-               yelem = omap_lcdc.xres;
+               xelem = lcdc.yres * lcdc.bpp / 16;
+               yelem = lcdc.xres;
                break;
        default:
                BUG();
                return;
        }
-       DBGPRINT(2, "setup_dma: src %#010lx esize %d xelem %d yelem %d\n",
+#ifdef VERBOSE
+       dev_dbg(lcdc.fbdev->dev,
+                "setup_dma: src %#010lx esize %d xelem %d yelem %d\n",
                 src, esize, xelem, yelem);
+#endif
        omap_set_lcd_dma_b1(src, xelem, yelem, dma_elem_type[esize]);
        if (!cpu_is_omap15xx()) {
-               int bpp = omap_lcdc.bpp;
+               int bpp = lcdc.bpp;
 
                /* YUV support is only for external mode when we have the
                 * YUV window embedded in a 16bpp frame buffer.
                 */
-               if (omap_lcdc.color_mode == OMAPFB_COLOR_YUV420)
+               if (lcdc.color_mode == OMAPFB_COLOR_YUV420)
                        bpp = 16;
                /* Set virtual xres elem size */
                omap_set_lcd_dma_b1_vxres(
-                       omap_lcdc.screen_width * bpp / 8 / esize);
+                       lcdc.screen_width * bpp / 8 / esize);
                /* Setup transformations */
                omap_set_lcd_dma_b1_rotation(var->rotate);
-               omap_set_lcd_dma_b1_mirror(omap_lcdc.fbdev->mirror);
+               omap_set_lcd_dma_b1_mirror(plane->info.mirror);
        }
        omap_setup_lcd_dma();
 }
@@ -286,11 +285,11 @@ static irqreturn_t lcdc_irq_handler(int irq, void *dev_id, struct pt_regs *fp)
                        l = omap_readl(OMAP_LCDC_CONTROL);
                        l &= ~OMAP_LCDC_IRQ_DONE;
                        omap_writel(l, OMAP_LCDC_CONTROL);
-                       complete(&omap_lcdc.last_frame_complete);
+                       complete(&lcdc.last_frame_complete);
                }
                if (status & OMAP_LCDC_STAT_LOADED_PALETTE) {
                        disable_controller_async();
-                       complete(&omap_lcdc.palette_load_complete);
+                       complete(&lcdc.palette_load_complete);
                }
        }
 
@@ -319,12 +318,10 @@ static int omap_lcdc_setup_plane(int plane, int channel_out,
                                 int pos_x, int pos_y, int width, int height,
                                 int color_mode)
 {
-       struct fb_var_screeninfo *var = &omap_lcdc.fbdev->fb_info->var;
-       struct lcd_panel *panel = omap_lcdc.fbdev->panel;
+       struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var;
+       struct lcd_panel *panel = lcdc.fbdev->panel;
        int rot_x, rot_y;
 
-       DBGENTER(2);
-
        if (var->rotate == 0) {
                rot_x = panel->x_res;
                rot_y = panel->y_res;
@@ -334,43 +331,45 @@ static int omap_lcdc_setup_plane(int plane, int channel_out,
        }
        if (plane != 0 || channel_out != 0 || pos_x != 0 || pos_y != 0 ||
            width > rot_x || height > rot_y) {
-               DBGPRINT(1, "invalid plane params plane %d pos_x %d "
-                       "pos_y %d w %d h %d\n", plane, pos_x, pos_y,
-                       width, height);
+#ifdef VERBOSE
+               dev_dbg(lcdc.fbdev->dev,
+                       "invalid plane params plane %d pos_x %d pos_y %d "
+                       "w %d h %d\n", plane, pos_x, pos_y, width, height);
+#endif
                return -EINVAL;
        }
 
-       omap_lcdc.frame_offset = offset;
-       omap_lcdc.xres = width;
-       omap_lcdc.yres = height;
-       omap_lcdc.screen_width = screen_width;
-       omap_lcdc.color_mode = color_mode;
+       lcdc.frame_offset = offset;
+       lcdc.xres = width;
+       lcdc.yres = height;
+       lcdc.screen_width = screen_width;
+       lcdc.color_mode = color_mode;
 
        switch (color_mode) {
        case OMAPFB_COLOR_CLUT_8BPP:
-               omap_lcdc.bpp = 8;
-               omap_lcdc.palette_code = 0x3000;
-               omap_lcdc.palette_size = 512;
+               lcdc.bpp = 8;
+               lcdc.palette_code = 0x3000;
+               lcdc.palette_size = 512;
                break;
        case OMAPFB_COLOR_RGB565:
-               omap_lcdc.bpp = 16;
-               omap_lcdc.palette_code = 0x4000;
-               omap_lcdc.palette_size = 32;
+               lcdc.bpp = 16;
+               lcdc.palette_code = 0x4000;
+               lcdc.palette_size = 32;
                break;
        case OMAPFB_COLOR_RGB444:
-               omap_lcdc.bpp = 16;
-               omap_lcdc.palette_code = 0x4000;
-               omap_lcdc.palette_size = 32;
+               lcdc.bpp = 16;
+               lcdc.palette_code = 0x4000;
+               lcdc.palette_size = 32;
                break;
        case OMAPFB_COLOR_YUV420:
-               if (omap_lcdc.ext_mode) {
-                       omap_lcdc.bpp = 12;
+               if (lcdc.ext_mode) {
+                       lcdc.bpp = 12;
                        break;
                }
                /* fallthrough */
        case OMAPFB_COLOR_YUV422:
-               if (omap_lcdc.ext_mode) {
-                       omap_lcdc.bpp = 16;
+               if (lcdc.ext_mode) {
+                       lcdc.bpp = 16;
                        break;
                }
                /* fallthrough */
@@ -381,32 +380,31 @@ static int omap_lcdc_setup_plane(int plane, int channel_out,
                 * bpp4: code  0x2000 size 256
                 * bpp12: code 0x4000 size 32
                 */
-               DBGPRINT(1, "invalid color mode %d\n", color_mode);
+               dev_dbg(lcdc.fbdev->dev, "invalid color mode %d\n", color_mode);
+               BUG();
                return -1;
        }
 
-       if (omap_lcdc.ext_mode) {
+       if (lcdc.ext_mode) {
                setup_lcd_dma();
                return 0;
        }
 
-       if (omap_lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
+       if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
                disable_controller();
                omap_stop_lcd_dma();
                setup_lcd_dma();
                enable_controller();
        }
 
-       DBGLEAVE(2);
-
        return 0;
 }
 
 static int omap_lcdc_enable_plane(int plane, int enable)
 {
-       DBGPRINT(2, "plane %d enable %d update_mode %d ext_mode %d\n",
-               plane, enable, omap_lcdc.update_mode,
-               omap_lcdc.ext_mode);
+       dev_dbg(lcdc.fbdev->dev,
+               "plane %d enable %d update_mode %d ext_mode %d\n",
+               plane, enable, lcdc.update_mode, lcdc.ext_mode);
        if (plane != OMAPFB_PLANE_GFX)
                return -EINVAL;
 
@@ -421,33 +419,29 @@ static void load_palette(void)
 {
        u16     *palette;
 
-       DBGENTER(1);
-
-       palette = (u16 *)omap_lcdc.palette_virt;
+       palette = (u16 *)lcdc.palette_virt;
 
        *(u16 *)palette &= 0x0fff;
-       *(u16 *)palette |= omap_lcdc.palette_code;
+       *(u16 *)palette |= lcdc.palette_code;
 
-       omap_set_lcd_dma_b1(omap_lcdc.palette_phys,
-               omap_lcdc.palette_size / 4 + 1, 1, OMAP_DMA_DATA_TYPE_S32);
+       omap_set_lcd_dma_b1(lcdc.palette_phys,
+               lcdc.palette_size / 4 + 1, 1, OMAP_DMA_DATA_TYPE_S32);
 
        omap_set_lcd_dma_single_transfer(1);
        omap_setup_lcd_dma();
 
-       init_completion(&omap_lcdc.palette_load_complete);
+       init_completion(&lcdc.palette_load_complete);
        enable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);
        set_load_mode(OMAP_LCDC_LOAD_PALETTE);
        enable_controller();
-       if (!wait_for_completion_timeout(&omap_lcdc.palette_load_complete,
+       if (!wait_for_completion_timeout(&lcdc.palette_load_complete,
                                msecs_to_jiffies(500)))
-               pr_err("timeout waiting for FRAME DONE\n");
+               dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n");
        /* The controller gets disabled in the irq handler */
        disable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);
        omap_stop_lcd_dma();
 
-       omap_set_lcd_dma_single_transfer(omap_lcdc.ext_mode);
-
-       DBGLEAVE(1);
+       omap_set_lcd_dma_single_transfer(lcdc.ext_mode);
 }
 
 /* Used only in internal controller mode */
@@ -456,10 +450,10 @@ static int omap_lcdc_setcolreg(u_int regno, u16 red, u16 green, u16 blue,
 {
        u16 *palette;
 
-       if (omap_lcdc.color_mode != OMAPFB_COLOR_CLUT_8BPP || regno > 255)
+       if (lcdc.color_mode != OMAPFB_COLOR_CLUT_8BPP || regno > 255)
                return -EINVAL;
 
-       palette = (u16 *)omap_lcdc.palette_virt;
+       palette = (u16 *)lcdc.palette_virt;
 
        palette[regno] &= ~0x0fff;
        palette[regno] |= ((red >> 12) << 8) | ((green >> 12) << 4 ) |
@@ -482,7 +476,7 @@ static void calc_ck_div(int is_tft, int pck, int *pck_div)
        unsigned long lck;
 
        pck = max(1, pck);
-       lck = clk_get_rate(omap_lcdc.lcd_ck);
+       lck = clk_get_rate(lcdc.lcd_ck);
        *pck_div = (lck + pck - 1) / pck;
        if (is_tft)
                *pck_div = max(2, *pck_div);
@@ -491,15 +485,15 @@ static void calc_ck_div(int is_tft, int pck, int *pck_div)
        if (*pck_div > 255) {
                /* FIXME: try to adjust logic clock divider as well */
                *pck_div = 255;
-               printk(KERN_WARNING MODULE_NAME ": pixclock %d kHz too low.\n",
-                               pck / 1000);
+               dev_warn(lcdc.fbdev->dev, "pixclock %d kHz too low.\n",
+                        pck / 1000);
        }
 }
 
 static void inline setup_regs(void)
 {
        u32 l;
-       struct lcd_panel *panel = omap_lcdc.fbdev->panel;
+       struct lcd_panel *panel = lcdc.fbdev->panel;
        int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;
        unsigned long lck;
        int pcd;
@@ -535,14 +529,14 @@ static void inline setup_regs(void)
        l = omap_readl(OMAP_LCDC_TIMING2);
        l &= ~0xff;
 
-       lck = clk_get_rate(omap_lcdc.lcd_ck);
+       lck = clk_get_rate(lcdc.lcd_ck);
 
        if (!panel->pcd)
                calc_ck_div(is_tft, panel->pixel_clock * 1000, &pcd);
        else {
-               printk(KERN_WARNING
-                   MODULE_NAME ": Pixel clock divider value is obsolete.\n"
-                   MODULE_NAME ": Try to set pixel_clock to %lu and pcd to 0 "
+               dev_warn(lcdc.fbdev->dev,
+                   "Pixel clock divider value is obsolete.\n"
+                   "Try to set pixel_clock to %lu and pcd to 0 "
                    "in drivers/video/omap/lcd_%s.c and submit a patch.\n",
                        lck / panel->pcd / 1000, panel->name);
 
@@ -564,9 +558,7 @@ static int omap_lcdc_set_update_mode(enum omapfb_update_mode mode)
 {
        int r = 0;
 
-       DBGENTER(1);
-
-       if (mode != omap_lcdc.update_mode) {
+       if (mode != lcdc.update_mode) {
                switch (mode) {
                case OMAPFB_AUTO_UPDATE:
                        setup_regs();
@@ -579,31 +571,30 @@ static int omap_lcdc_set_update_mode(enum omapfb_update_mode mode)
                        enable_irqs(OMAP_LCDC_IRQ_DONE);
                        /* This will start the actual DMA transfer */
                        enable_controller();
-                       omap_lcdc.update_mode = mode;
+                       lcdc.update_mode = mode;
                        break;
                case OMAPFB_UPDATE_DISABLED:
                        disable_controller();
                        omap_stop_lcd_dma();
-                       omap_lcdc.update_mode = mode;
+                       lcdc.update_mode = mode;
                        break;
                default:
                        r = -EINVAL;
                }
        }
 
-       DBGLEAVE(1);
        return r;
 }
 
 static enum omapfb_update_mode omap_lcdc_get_update_mode(void)
 {
-       return omap_lcdc.update_mode;
+       return lcdc.update_mode;
 }
 
 /* PM code called only in internal controller mode */
 static void omap_lcdc_suspend(void)
 {
-       if (omap_lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
+       if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
                disable_controller();
                omap_stop_lcd_dma();
        }
@@ -611,7 +602,7 @@ static void omap_lcdc_suspend(void)
 
 static void omap_lcdc_resume(void)
 {
-       if (omap_lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
+       if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
                setup_regs();
                load_palette();
                setup_lcd_dma();
@@ -626,23 +617,15 @@ static unsigned long omap_lcdc_get_caps(void)
        return 0;
 }
 
-static void omap_lcdc_get_vram_layout(unsigned long *size, void **virt,
-                                       dma_addr_t *phys)
-{
-       *size = omap_lcdc.vram_size;
-       *virt = (u8 *)omap_lcdc.vram_virt;
-       *phys = omap_lcdc.vram_phys;
-}
-
 int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data)
 {
        BUG_ON(callback == NULL);
 
-       if (omap_lcdc.dma_callback)
+       if (lcdc.dma_callback)
                return -EBUSY;
        else {
-               omap_lcdc.dma_callback = callback;
-               omap_lcdc.dma_callback_data = data;
+               lcdc.dma_callback = callback;
+               lcdc.dma_callback_data = data;
        }
        return 0;
 }
@@ -650,15 +633,14 @@ EXPORT_SYMBOL(omap_lcdc_set_dma_callback);
 
 void omap_lcdc_free_dma_callback(void)
 {
-       omap_lcdc.dma_callback = NULL;
+       lcdc.dma_callback = NULL;
 }
 EXPORT_SYMBOL(omap_lcdc_free_dma_callback);
 
 static void lcdc_dma_handler(u16 status, void *data)
 {
-       DBGENTER(2);
-       if (omap_lcdc.dma_callback)
-               omap_lcdc.dma_callback(omap_lcdc.dma_callback_data);
+       if (lcdc.dma_callback)
+               lcdc.dma_callback(lcdc.dma_callback_data);
 }
 
 static int mmap_kern(void)
@@ -668,158 +650,141 @@ static int mmap_kern(void)
        pgprot_t                pgprot;
        unsigned long           vaddr;
 
-       DBGENTER(1);
-
-       kvma = get_vm_area(omap_lcdc.vram_size, VM_IOREMAP);
+       kvma = get_vm_area(lcdc.vram_size, VM_IOREMAP);
        if (kvma == NULL) {
-               pr_err("can't get kernel vm area\n");
+               dev_err(lcdc.fbdev->dev, "can't get kernel vm area\n");
                return -ENOMEM;
        }
        vma.vm_mm = &init_mm;
 
        vaddr = (unsigned long)kvma->addr;
        vma.vm_start = vaddr;
-       vma.vm_end = vaddr + omap_lcdc.vram_size;
+       vma.vm_end = vaddr + lcdc.vram_size;
 
        pgprot = pgprot_writecombine(pgprot_kernel);
        if (io_remap_pfn_range(&vma, vaddr,
-                          omap_lcdc.vram_phys >> PAGE_SHIFT,
-                          omap_lcdc.vram_size, pgprot) < 0) {
-               pr_err("kernel mmap for FB memory failed\n");
+                          lcdc.vram_phys >> PAGE_SHIFT,
+                          lcdc.vram_size, pgprot) < 0) {
+               dev_err(lcdc.fbdev->dev, "kernel mmap for FB memory failed\n");
                return -EAGAIN;
        }
 
-       omap_lcdc.vram_virt = (void *)vaddr;
-
-       DBGLEAVE(1);
+       lcdc.vram_virt = (void *)vaddr;
 
        return 0;
 }
 
 static void unmap_kern(void)
 {
-       vunmap(omap_lcdc.vram_virt);
+       vunmap(lcdc.vram_virt);
 }
 
 static int alloc_palette_ram(void)
 {
-       omap_lcdc.palette_virt = dma_alloc_writecombine(omap_lcdc.fbdev->dev,
-               MAX_PALETTE_SIZE, &omap_lcdc.palette_phys, GFP_KERNEL);
-       if (omap_lcdc.palette_virt == NULL) {
-               pr_err("failed to alloc palette memory\n");
+       lcdc.palette_virt = dma_alloc_writecombine(lcdc.fbdev->dev,
+               MAX_PALETTE_SIZE, &lcdc.palette_phys, GFP_KERNEL);
+       if (lcdc.palette_virt == NULL) {
+               dev_err(lcdc.fbdev->dev, "failed to alloc palette memory\n");
                return -ENOMEM;
        }
-       memset(omap_lcdc.palette_virt, 0, MAX_PALETTE_SIZE);
+       memset(lcdc.palette_virt, 0, MAX_PALETTE_SIZE);
 
        return 0;
 }
 
 static void free_palette_ram(void)
 {
-       dma_free_writecombine(omap_lcdc.fbdev->dev, MAX_PALETTE_SIZE,
-                       omap_lcdc.palette_virt, omap_lcdc.palette_phys);
+       dma_free_writecombine(lcdc.fbdev->dev, MAX_PALETTE_SIZE,
+                       lcdc.palette_virt, lcdc.palette_phys);
 }
 
-static int alloc_fbmem(int req_size)
+static int alloc_fbmem(struct omapfb_mem_region *region)
 {
+       int bpp;
        int frame_size;
-       struct lcd_panel *panel = omap_lcdc.fbdev->panel;
-
-       frame_size = PAGE_ALIGN(panel->x_res * panel->bpp / 8 * panel->y_res);
-       if (req_size > frame_size)
-               frame_size = req_size;
-       omap_lcdc.vram_size = frame_size;
-       omap_lcdc.vram_virt = dma_alloc_writecombine(omap_lcdc.fbdev->dev,
-                       omap_lcdc.vram_size, &omap_lcdc.vram_phys, GFP_KERNEL);
-
-       if (omap_lcdc.vram_virt == NULL) {
-               pr_err("unable to allocate FB DMA memory\n");
+       struct lcd_panel *panel = lcdc.fbdev->panel;
+
+       bpp = panel->bpp;
+       if (bpp == 12)
+               bpp = 16;
+       frame_size = PAGE_ALIGN(panel->x_res * bpp / 8 * panel->y_res);
+       if (region->size > frame_size)
+               frame_size = region->size;
+       lcdc.vram_size = frame_size;
+       lcdc.vram_virt = dma_alloc_writecombine(lcdc.fbdev->dev,
+                       lcdc.vram_size, &lcdc.vram_phys, GFP_KERNEL);
+       if (lcdc.vram_virt == NULL) {
+               dev_err(lcdc.fbdev->dev, "unable to allocate FB DMA memory\n");
                return -ENOMEM;
        }
+       region->size = frame_size;
+       region->paddr = lcdc.vram_phys;
+       region->alloc = 1;
 
-       memset(omap_lcdc.vram_virt, 0, omap_lcdc.vram_size);
+       memset(lcdc.vram_virt, 0, lcdc.vram_size);
 
        return 0;
 }
 
 static void free_fbmem(void)
 {
-       dma_free_writecombine(omap_lcdc.fbdev->dev, omap_lcdc.vram_size,
-                             omap_lcdc.vram_virt, omap_lcdc.vram_phys);
+       dma_free_writecombine(lcdc.fbdev->dev, lcdc.vram_size,
+                             lcdc.vram_virt, lcdc.vram_phys);
 }
 
-static int setup_fbmem(int req_size)
+static int setup_fbmem(struct omapfb_mem_desc *req_md)
 {
-       struct lcd_panel *panel = omap_lcdc.fbdev->panel;
-       struct omapfb_platform_data *conf;
-       int frame_size;
        int r;
 
-       conf = omap_lcdc.fbdev->dev->platform_data;
-
-       if (conf->fbmem.fb_sram_size) {
-               pr_err("can't use FB SRAM in OMAP1\n");
+       if (!req_md->region_cnt) {
+               dev_err(lcdc.fbdev->dev, "no memory regions defined\n");
                return -EINVAL;
        }
 
-       if (conf->fbmem.fb_sdram_size == 0) {
-               omap_lcdc.fbmem_allocated = 1;
-               if ((r = alloc_fbmem(req_size)) < 0)
-                       return r;
-               return 0;
-       }
-
-       if (panel->bpp == 12)
-               frame_size = PAGE_ALIGN(panel->x_res * 16 / 8 * panel->y_res);
-       else
-               frame_size = PAGE_ALIGN(panel->x_res * panel->bpp / 8 * panel->y_res);
-
-       if (conf->fbmem.fb_sdram_size < frame_size) {
-               pr_err("invalid FB memory configuration\n");
-               return -EINVAL;
+       if (req_md->region_cnt > 1) {
+               dev_err(lcdc.fbdev->dev, "only one plane is supported\n");
+               req_md->region_cnt = 1;
        }
 
-       if (conf->fbmem.fb_sdram_size < req_size) {
-               pr_err("%d vram was requested, but only %u is available\n",
-                       req_size, conf->fbmem.fb_sdram_size);
+       if (req_md->region[0].paddr == 0) {
+               lcdc.fbmem_allocated = 1;
+               if ((r = alloc_fbmem(&req_md->region[0])) < 0)
+                       return r;
+               return 0;
        }
 
-       omap_lcdc.vram_phys = conf->fbmem.fb_sdram_start;
-       omap_lcdc.vram_size = conf->fbmem.fb_sdram_size;
+       lcdc.vram_phys = req_md->region[0].paddr;
+       lcdc.vram_size = req_md->region[0].size;
 
        if ((r = mmap_kern()) < 0)
                return r;
 
-       DBGPRINT(1, "vram at %08x size %08lx mapped to 0x%p\n",
-                omap_lcdc.vram_phys, omap_lcdc.vram_size, omap_lcdc.vram_virt);
+       dev_dbg(lcdc.fbdev->dev, "vram at %08x size %08lx mapped to 0x%p\n",
+                lcdc.vram_phys, lcdc.vram_size, lcdc.vram_virt);
 
        return 0;
 }
 
 static void cleanup_fbmem(void)
 {
-       if (omap_lcdc.fbmem_allocated)
+       if (lcdc.fbmem_allocated)
                free_fbmem();
        else
                unmap_kern();
 }
 
 static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
-                         int req_vram_size)
+                         struct omapfb_mem_desc *req_vram)
 {
        int r;
        u32 l;
        int rate;
        struct clk *tc_ck;
 
-       DBGENTER(1);
-
-       omap_lcdc.irq_mask = 0;
+       lcdc.irq_mask = 0;
 
-       omap_lcdc.fbdev = fbdev;
-       omap_lcdc.ext_mode = ext_mode;
-
-       pr_info(MODULE_NAME ": init\n");
+       lcdc.fbdev = fbdev;
+       lcdc.ext_mode = ext_mode;
 
        l = 0;
        omap_writel(l, OMAP_LCDC_CONTROL);
@@ -827,16 +792,16 @@ static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
        /* FIXME:
         * According to errata some platforms have a clock rate limitiation
         */
-       omap_lcdc.lcd_ck = clk_get(NULL, "lcd_ck");
-       if (IS_ERR(omap_lcdc.lcd_ck)) {
-               pr_err("unable to access LCD clock\n");
-               r = PTR_ERR(omap_lcdc.lcd_ck);
+       lcdc.lcd_ck = clk_get(NULL, "lcd_ck");
+       if (IS_ERR(lcdc.lcd_ck)) {
+               dev_err(fbdev->dev, "unable to access LCD clock\n");
+               r = PTR_ERR(lcdc.lcd_ck);
                goto fail0;
        }
 
        tc_ck = clk_get(NULL, "tc_ck");
        if (IS_ERR(tc_ck)) {
-               pr_err("unable to access TC clock\n");
+               dev_err(fbdev->dev, "unable to access TC clock\n");
                r = PTR_ERR(tc_ck);
                goto fail1;
        }
@@ -846,23 +811,22 @@ static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
 
        if (machine_is_omap_h3())
                rate /= 3;
-       r = clk_set_rate(omap_lcdc.lcd_ck, rate);
+       r = clk_set_rate(lcdc.lcd_ck, rate);
        if (r) {
-               pr_err("failed to adjust LCD rate\n");
+               dev_err(fbdev->dev, "failed to adjust LCD rate\n");
                goto fail1;
        }
-       clk_enable(omap_lcdc.lcd_ck);
+       clk_enable(lcdc.lcd_ck);
 
-       r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, "omap-lcdc",
-                       omap_lcdc.fbdev);
+       r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, MODULE_NAME, fbdev);
        if (r) {
-               pr_err("unable to get IRQ\n");
+               dev_err(fbdev->dev, "unable to get IRQ\n");
                goto fail2;
        }
 
        r = omap_request_lcd_dma(lcdc_dma_handler, NULL);
        if (r) {
-               pr_err("unable to get LCD DMA\n");
+               dev_err(fbdev->dev, "unable to get LCD DMA\n");
                goto fail3;
        }
 
@@ -873,12 +837,11 @@ static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
                if ((r = alloc_palette_ram()) < 0)
                        goto fail4;
 
-       req_vram_size = 1024 * 1024;
-       if ((r = setup_fbmem(req_vram_size)) < 0)
+       if ((r = setup_fbmem(req_vram)) < 0)
                goto fail5;
 
+       pr_info("omapfb: LCDC initialized\n");
 
-       DBGLEAVE(1);
        return 0;
 fail5:
        if (!ext_mode)
@@ -886,32 +849,30 @@ fail5:
 fail4:
        omap_free_lcd_dma();
 fail3:
-       free_irq(OMAP_LCDC_IRQ, omap_lcdc.fbdev);
+       free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
 fail2:
-       clk_disable(omap_lcdc.lcd_ck);
+       clk_disable(lcdc.lcd_ck);
 fail1:
-       clk_put(omap_lcdc.lcd_ck);
+       clk_put(lcdc.lcd_ck);
 fail0:
-       DBGLEAVE(1);
         return r;
 }
 
 static void omap_lcdc_cleanup(void)
 {
-       if (!omap_lcdc.ext_mode)
+       if (!lcdc.ext_mode)
                free_palette_ram();
        cleanup_fbmem();
        omap_free_lcd_dma();
-       free_irq(OMAP_LCDC_IRQ, omap_lcdc.fbdev);
-       clk_disable(omap_lcdc.lcd_ck);
-       clk_put(omap_lcdc.lcd_ck);
+       free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
+       clk_disable(lcdc.lcd_ck);
+       clk_put(lcdc.lcd_ck);
 }
 
-struct lcd_ctrl omap1_int_ctrl = {
+const struct lcd_ctrl omap1_int_ctrl = {
        .name                   = "internal",
        .init                   = omap_lcdc_init,
        .cleanup                = omap_lcdc_cleanup,
-       .get_vram_layout        = omap_lcdc_get_vram_layout,
        .get_caps               = omap_lcdc_get_caps,
        .set_update_mode        = omap_lcdc_set_update_mode,
        .get_update_mode        = omap_lcdc_get_update_mode,
@@ -922,6 +883,3 @@ struct lcd_ctrl omap1_int_ctrl = {
        .enable_plane           = omap_lcdc_enable_plane,
        .setcolreg              = omap_lcdc_setcolreg,
 };
-
-MODULE_DESCRIPTION("TI OMAP LCDC controller");
-MODULE_LICENSE("GPL");
index 5a013b6eaca6b3337b04c939bb3b24f8f2e1693f..4e73cd49be6300f813b41a2ac1910e443a66016b 100644 (file)
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
-
 #include <linux/config.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/delay.h>
 #include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
 
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
 #include <asm/mach-types.h>
-
 #include <asm/arch/dma.h>
-#include <asm/arch/irqs.h>
-#include <asm/arch/mux.h>
-#include <asm/arch/board.h>
 #include <asm/arch/omapfb.h>
 
-/* #define OMAPFB_DBG 1 */
-
-#include "debug.h"
-
-#define OMAPFB_DRIVER  "omapfb"
 #define MODULE_NAME    "omapfb"
 
-#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
-
 static unsigned int    def_accel;
-static unsigned long   def_vram;
+static unsigned long   def_vram[OMAPFB_PLANE_NUM];
+static int             def_vram_cnt;
 static unsigned long   def_vxres;
 static unsigned long   def_vyres;
 static unsigned int    def_rotate;
@@ -87,7 +70,6 @@ static struct caps_table_struct {
 extern struct lcd_ctrl omap1_int_ctrl;
 extern struct lcd_ctrl omap2_int_ctrl;
 extern struct lcd_ctrl hwa742_ctrl;
-extern struct lcd_ctrl blizzard_ctrl;
 
 static struct lcd_ctrl *ctrls[] = {
 #ifdef CONFIG_ARCH_OMAP1
@@ -103,9 +85,9 @@ static struct lcd_ctrl *ctrls[] = {
 
 #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
 #ifdef CONFIG_ARCH_OMAP1
-extern struct lcd_ctrl_extif sossi_extif;
+extern struct lcd_ctrl_extif omap1_ext_if;
 #else
-extern struct lcd_ctrl_extif rfbi_extif;
+extern struct lcd_ctrl_extif omap2_ext_if;
 #endif
 #endif
 
@@ -141,27 +123,48 @@ static const int dma_elem_type[] = {
 static int ctrl_init(struct omapfb_device *fbdev)
 {
        int r;
+       int i;
 
-       DBGENTER(1);
+       /* kernel/module vram parameters override boot tags/board config */
+       if (def_vram_cnt) {
+               for (i = 0; i < def_vram_cnt; i++)
+                       fbdev->mem_desc.region[i].size = def_vram[i];
+               fbdev->mem_desc.region_cnt = i;
+       } else {
+               struct omapfb_platform_data *conf;
 
-       r = fbdev->ctrl->init(fbdev, 0, def_vram);
-       if (r < 0) {
-               pr_err("controller initialization failed\n");
-               goto exit;
+               conf = fbdev->dev->platform_data;
+               fbdev->mem_desc = conf->mem_desc;
        }
 
-       fbdev->ctrl->get_vram_layout(&fbdev->vram_size, &fbdev->vram_virt_base,
-                                    &fbdev->vram_phys_base);
-
-       DBGPRINT(1, "vram_phys %08x vram_virt %p vram_size=%lu\n",
-                fbdev->vram_phys_base, fbdev->vram_virt_base,
-                fbdev->vram_size);
+       if (!fbdev->mem_desc.region_cnt) {
+               struct lcd_panel *panel = fbdev->panel;
+               int def_size;
+               int bpp = panel->bpp;
+
+               /* 12 bpp is packed in 16 bits */
+               if (bpp == 12)
+                       bpp = 16;
+               def_size = def_vxres * def_vyres * bpp / 8;
+               fbdev->mem_desc.region_cnt = 1;
+               fbdev->mem_desc.region[0].size = def_size;
+       }
+       r = fbdev->ctrl->init(fbdev, 0, &fbdev->mem_desc);
+       if (r < 0) {
+               dev_err(fbdev->dev, "controller initialization failed (%d)\n", r);
+               return r;
+       }
 
-       DBGLEAVE(1);
+#ifdef DEBUG
+       for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+               dev_dbg(fbdev->dev, "region%d phys %08x virt %p size=%lu\n",
+                        i,
+                        fbdev->mem_desc.region[i].paddr,
+                        fbdev->mem_desc.region[i].vaddr,
+                        fbdev->mem_desc.region[i].size);
+       }
+#endif
        return 0;
-exit:
-       DBGLEAVE(1);
-       return r;
 }
 
 static void ctrl_cleanup(struct omapfb_device *fbdev)
@@ -169,21 +172,28 @@ static void ctrl_cleanup(struct omapfb_device *fbdev)
        fbdev->ctrl->cleanup();
 }
 
-static int ctrl_change_mode(struct omapfb_device *fbdev)
+static int ctrl_change_mode(struct fb_info *fbi)
 {
        int r;
        unsigned long offset;
-       struct fb_var_screeninfo *var = &fbdev->fb_info->var;
+       struct omapfb_plane_struct *plane = fbi->par;
+       struct omapfb_device *fbdev = plane->fbdev;
+       struct fb_var_screeninfo *var = &fbi->var;
 
-       DBGPRINT(1, "xoffset %d yoffset %d line_length %d bits_per_pixel %d\n",
-               var->xoffset, var->yoffset, fbdev->fb_info->fix.line_length,
-               var->bits_per_pixel);
-       offset = var->yoffset * fbdev->fb_info->fix.line_length +
+       offset = var->yoffset * fbi->fix.line_length +
                 var->xoffset * var->bits_per_pixel / 8;
-       r = fbdev->ctrl->setup_plane(OMAPFB_PLANE_GFX, OMAPFB_CHANNEL_OUT_LCD,
-                                offset, var->xres_virtual, 0, 0, var->xres,
-                                var->yres, fbdev->color_mode);
-       DBGLEAVE(1);
+
+       omapfb_rqueue_lock(fbdev);
+       r = fbdev->ctrl->setup_plane(plane->idx, plane->info.channel_out,
+                                offset, var->xres_virtual,
+                                plane->info.pos_x, plane->info.pos_y,
+                                var->xres, var->yres, plane->color_mode);
+       if (fbdev->ctrl->set_scale != NULL)
+               r = fbdev->ctrl->set_scale(plane->idx,
+                                  var->xres, var->yres,
+                                  plane->info.out_width,
+                                  plane->info.out_height);
+       omapfb_rqueue_unlock(fbdev);
 
        return r;
 }
@@ -196,8 +206,6 @@ static int ctrl_change_mode(struct omapfb_device *fbdev)
 /* Called each time the omapfb device is opened */
 static int omapfb_open(struct fb_info *info, int user)
 {
-       DBGENTER(1);
-       DBGLEAVE(1);
        return 0;
 }
 
@@ -207,11 +215,7 @@ static void omapfb_sync(struct fb_info *info);
  * gfx DMA operations are ended, before we return. */
 static int omapfb_release(struct fb_info *info, int user)
 {
-       DBGENTER(1);
-
        omapfb_sync(info);
-
-       DBGLEAVE(1);
        return 0;
 }
 
@@ -222,13 +226,15 @@ static int omapfb_release(struct fb_info *info, int user)
 static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green,
                        u_int blue, u_int transp, int update_hw_pal)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)info->par;
+       struct omapfb_plane_struct *plane = info->par;
+       struct omapfb_device *fbdev = plane->fbdev;
        struct fb_var_screeninfo *var = &info->var;
        int r = 0;
 
-       switch (fbdev->color_mode) {
+       switch (plane->color_mode) {
        case OMAPFB_COLOR_YUV422:
        case OMAPFB_COLOR_YUV420:
+       case OMAPFB_COLOR_YUY422:
                r = -EINVAL;
                break;
        case OMAPFB_COLOR_CLUT_8BPP:
@@ -251,9 +257,11 @@ static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green,
 
                if (regno < 16) {
                        u16 pal;
-                       pal = ((red >> (16 - var->red.length)) << var->red.offset) |
-                               ((green >> (16 - var->green.length)) << var->green.offset) |
-                               (blue >> (16 - var->blue.length));
+                       pal = ((red >> (16 - var->red.length)) <<
+                                       var->red.offset) |
+                             ((green >> (16 - var->green.length)) <<
+                                       var->green.offset) |
+                             (blue >> (16 - var->blue.length));
                        ((u32 *)(info->pseudo_palette))[regno] = pal;
                }
                break;
@@ -266,15 +274,7 @@ static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green,
 static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                            u_int transp, struct fb_info *info)
 {
-       int r = 0;
-
-       DBGENTER(2);
-
-       _setcolreg(info, regno, red, green, blue, transp, 1);
-
-       DBGLEAVE(2);
-
-       return r;
+       return _setcolreg(info, regno, red, green, blue, transp, 1);
 }
 
 static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
@@ -301,35 +301,22 @@ static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
        return 0;
 }
 
-static int omapfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-       struct omapfb_device *fbdev = info->par;
-       int r;
-
-       omapfb_rqueue_lock(fbdev);
-       r = fbdev->ctrl->mmap(vma);
-       omapfb_rqueue_unlock(fbdev);
-
-       return r;
-}
-
-static void omapfb_update_full_screen(struct omapfb_device *fbdev);
+static int omapfb_update_full_screen(struct fb_info *fbi);
 
 static int omapfb_blank(int blank, struct fb_info *fbi)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
+       struct omapfb_plane_struct *plane = fbi->par;
+       struct omapfb_device *fbdev = plane->fbdev;
        int do_update = 0;
        int r = 0;
 
-       DBGENTER(1);
-
        omapfb_rqueue_lock(fbdev);
        switch (blank) {
        case VESA_NO_BLANKING:
                if (fbdev->state == OMAPFB_SUSPENDED) {
                        if (fbdev->ctrl->resume)
                                fbdev->ctrl->resume();
-                       fbdev->panel->enable();
+                       fbdev->panel->enable(fbdev->panel);
                        fbdev->state = OMAPFB_ACTIVE;
                        if (fbdev->ctrl->get_update_mode() ==
                                        OMAPFB_MANUAL_UPDATE)
@@ -338,7 +325,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
                break;
        case VESA_POWERDOWN:
                if (fbdev->state == OMAPFB_ACTIVE) {
-                       fbdev->panel->disable();
+                       fbdev->panel->disable(fbdev->panel);
                        if (fbdev->ctrl->suspend)
                                fbdev->ctrl->suspend();
                        fbdev->state = OMAPFB_SUSPENDED;
@@ -349,16 +336,16 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
        }
        omapfb_rqueue_unlock(fbdev);
 
-       if (do_update)
-               omapfb_update_full_screen(fbdev);
+       if (r == 0 && do_update)
+               r = omapfb_update_full_screen(fbi);
 
-       DBGLEAVE(1);
        return r;
 }
 
 static void omapfb_sync(struct fb_info *fbi)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
+       struct omapfb_plane_struct *plane = fbi->par;
+       struct omapfb_device *fbdev = plane->fbdev;
 
        omapfb_rqueue_lock(fbdev);
        if (fbdev->ctrl->sync)
@@ -369,17 +356,22 @@ static void omapfb_sync(struct fb_info *fbi)
 /* Set fb_info.fix fields and also updates fbdev.
  * When calling this fb_info.var must be set up already.
  */
-static void set_fb_fix(struct omapfb_device *fbdev)
+static void set_fb_fix(struct fb_info *fbi)
 {
-       struct fb_info           *fbi = fbdev->fb_info;
        struct fb_fix_screeninfo *fix = &fbi->fix;
        struct fb_var_screeninfo *var = &fbi->var;
+       int bpp;
 
-       strncpy(fix->id, OMAPFB_DRIVER, sizeof(fix->id));
        fix->type = FB_TYPE_PACKED_PIXELS;
-       switch (var->bits_per_pixel) {
+       bpp = var->bits_per_pixel;
+       if (var->nonstd)
+               fix->visual = FB_VISUAL_PSEUDOCOLOR;
+       else switch (var->bits_per_pixel) {
        case 16:
+       case 12:
                fix->visual = FB_VISUAL_TRUECOLOR;
+               /* 12bpp is stored in 16 bits */
+               bpp = 16;
                break;
        case 1:
        case 2:
@@ -389,61 +381,118 @@ static void set_fb_fix(struct omapfb_device *fbdev)
                break;
        }
        fix->accel              = FB_ACCEL_OMAP1610;
-       fix->line_length        = var->xres_virtual * var->bits_per_pixel / 8;
-       fix->smem_len           = fbdev->vram_size;
-       fix->smem_start         = fbdev->vram_phys_base;
+       fix->line_length        = var->xres_virtual * bpp / 8;
+}
+
+static int set_color_mode(struct omapfb_plane_struct *plane,
+                         struct fb_var_screeninfo *var)
+{
+       switch (var->nonstd) {
+       case 0:
+               break;
+       case OMAPFB_COLOR_YUV422:
+               var->bits_per_pixel = 16;
+               plane->color_mode = var->nonstd;
+               return 0;
+       case OMAPFB_COLOR_YUV420:
+               var->bits_per_pixel = 12;
+               plane->color_mode = var->nonstd;
+               return 0;
+       case OMAPFB_COLOR_YUY422:
+               var->bits_per_pixel = 16;
+               plane->color_mode = var->nonstd;
+               return 0;
+       default:
+               return -EINVAL;
+       }
+
+       switch (var->bits_per_pixel) {
+       case 1:
+               plane->color_mode = OMAPFB_COLOR_CLUT_1BPP;
+               return 0;
+       case 2:
+               plane->color_mode = OMAPFB_COLOR_CLUT_2BPP;
+               return 0;
+       case 4:
+               plane->color_mode = OMAPFB_COLOR_CLUT_4BPP;
+               return 0;
+       case 8:
+               plane->color_mode = OMAPFB_COLOR_CLUT_8BPP;
+               return 0;
+       case 12:
+               plane->color_mode = OMAPFB_COLOR_RGB444;
+               return 0;
+       case 16:
+               plane->color_mode = OMAPFB_COLOR_RGB565;
+               return 0;
+       default:
+               return -EINVAL;
+       }
 }
 
 /* Check the values in var against our capabilities and in case of out of
  * bound values try to adjust them.
  */
-static int set_fb_var(struct omapfb_device *fbdev,
+static int set_fb_var(struct fb_info *fbi,
                      struct fb_var_screeninfo *var)
 {
        int             bpp;
        unsigned long   max_frame_size;
        unsigned long   line_size;
+       int             xres_min, xres_max;
+       int             yres_min, yres_max;
+       struct omapfb_plane_struct *plane = fbi->par;
+       struct omapfb_device *fbdev = plane->fbdev;
        struct lcd_panel *panel = fbdev->panel;
 
-       if (panel->bpp == 12)
-               bpp = var->bits_per_pixel = 16; /* 12-bit bpp mode stores colours in 16-bits */
-       else
-               bpp = var->bits_per_pixel = panel->bpp;
-
-       switch (panel->bpp) {
-       case 16:
-               fbdev->color_mode = OMAPFB_COLOR_RGB565;
-               break;
-       case 12:
-               fbdev->color_mode = OMAPFB_COLOR_RGB444;
-               break;
-       case 8:
-               fbdev->color_mode = OMAPFB_COLOR_CLUT_8BPP;
-               break;
-       default:
-               /* FIXME: other BPPs not yet supported */
+       if (set_color_mode(plane, var) < 0)
                return -EINVAL;
-       }
+
+       bpp = var->bits_per_pixel;
+       if (plane->color_mode == OMAPFB_COLOR_RGB444)
+               bpp = 16;
 
        switch (var->rotate) {
        case 0:
        case 180:
-               var->xres = fbdev->panel->x_res;
-               var->yres = fbdev->panel->y_res;
+               xres_min = OMAPFB_PLANE_XRES_MIN;
+               xres_max = panel->x_res;
+               yres_min = OMAPFB_PLANE_YRES_MIN;
+               yres_max = panel->y_res;
+               if (cpu_is_omap1510()) {
+                       var->xres = panel->x_res;
+                       var->yres = panel->y_res;
+               }
                break;
        case 90:
        case 270:
-               var->xres = fbdev->panel->y_res;
-               var->yres = fbdev->panel->x_res;
+               xres_min = OMAPFB_PLANE_YRES_MIN;
+               xres_max = panel->y_res;
+               yres_min = OMAPFB_PLANE_XRES_MIN;
+               yres_max = panel->x_res;
+               if (cpu_is_omap1510()) {
+                       var->xres = panel->y_res;
+                       var->yres = panel->x_res;
+               }
                break;
        default:
                return -EINVAL;
        }
+
+       if (var->xres < xres_min)
+               var->xres = xres_min;
+       if (var->yres < yres_min)
+               var->yres = yres_min;
+       if (var->xres > xres_max)
+               var->xres = xres_max;
+       if (var->yres > yres_max)
+               var->yres = yres_max;
+
        if (var->xres_virtual < var->xres)
                var->xres_virtual = var->xres;
        if (var->yres_virtual < var->yres)
                var->yres_virtual = var->yres;
-       max_frame_size = fbdev->vram_size;
+       max_frame_size = fbdev->mem_desc.region[plane->idx].size;
        line_size = var->xres_virtual * bpp / 8;
        if (line_size * var->yres_virtual > max_frame_size) {
                /* Try to keep yres_virtual first */
@@ -462,23 +511,25 @@ static int set_fb_var(struct omapfb_device *fbdev,
                var->yoffset = var->yres_virtual - var->yres;
        line_size = var->xres * bpp / 8;
 
-       if (fbdev->color_mode == OMAPFB_COLOR_RGB444)
-       {
-               var->red.offset  = 8; var->red.length    = 4; var->red.msb_right   = 0;
-               var->green.offset= 4;  var->green.length = 4; var->green.msb_right = 0;
-               var->blue.offset = 0;  var->blue.length  = 4; var->blue.msb_right  = 0;
-       }
-       else
-       {
-               var->red.offset  = 11; var->red.length   = 5; var->red.msb_right   = 0;
-               var->green.offset= 5;  var->green.length = 6; var->green.msb_right = 0;
-               var->blue.offset = 0;  var->blue.length  = 5; var->blue.msb_right  = 0;
+       if (plane->color_mode == OMAPFB_COLOR_RGB444) {
+               var->red.offset   = 8; var->red.length   = 4;
+                                               var->red.msb_right   = 0;
+               var->green.offset = 4; var->green.length = 4;
+                                               var->green.msb_right = 0;
+               var->blue.offset  = 0; var->blue.length  = 4;
+                                               var->blue.msb_right  = 0;
+       } else {
+               var->red.offset  = 11; var->red.length   = 5;
+                                               var->red.msb_right   = 0;
+               var->green.offset= 5;  var->green.length = 6;
+                                               var->green.msb_right = 0;
+               var->blue.offset = 0;  var->blue.length  = 5;
+                                               var->blue.msb_right  = 0;
        }
 
        var->height             = -1;
        var->width              = -1;
        var->grayscale          = 0;
-       var->nonstd             = 0;
 
        /* pixclock in ps, the rest in pixclock */
        var->pixclock           = 10000000 / (panel->pixel_clock / 100);
@@ -501,21 +552,15 @@ static struct fb_var_screeninfo new_var;
 /* Set rotation (0, 90, 180, 270 degree), and switch to the new mode. */
 static void omapfb_rotate(struct fb_info *fbi, int rotate)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
-
-       DBGENTER(1);
-
-       if (cpu_is_omap1510() && rotate != fbdev->fb_info->var.rotate) {
+       if (cpu_is_omap1510() && rotate != fbi->var.rotate) {
                memcpy(&new_var, &fbi->var, sizeof(new_var));
                new_var.rotate = rotate;
-               if (set_fb_var(fbdev, &new_var) == 0 &&
+               if (set_fb_var(fbi, &new_var) == 0 &&
                    memcmp(&new_var, &fbi->var, sizeof(new_var))) {
                        memcpy(&fbi->var, &new_var, sizeof(new_var));
-                       ctrl_change_mode(fbdev);
+                       ctrl_change_mode(fbi);
                }
        }
-
-       DBGLEAVE(1);
 }
 
 /* Set new x,y offsets in the virtual display for the visible area and switch
@@ -524,44 +569,38 @@ static void omapfb_rotate(struct fb_info *fbi, int rotate)
 static int omapfb_pan_display(struct fb_var_screeninfo *var,
                               struct fb_info *fbi)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
        int r = 0;
 
-       DBGENTER(1);
-
        if (var->xoffset != fbi->var.xoffset ||
            var->yoffset != fbi->var.yoffset) {
                memcpy(&new_var, &fbi->var, sizeof(new_var));
                new_var.xoffset = var->xoffset;
                new_var.yoffset = var->yoffset;
-               if (set_fb_var(fbdev, &new_var))
+               if (set_fb_var(fbi, &new_var))
                        r = -EINVAL;
                else {
                        memcpy(&fbi->var, &new_var, sizeof(new_var));
-                       ctrl_change_mode(fbdev);
+                       ctrl_change_mode(fbi);
                }
        }
 
-       DBGLEAVE(1);
        return r;
 }
 
 /* Set mirror to vertical axis and switch to the new mode. */
-static int omapfb_mirror(struct omapfb_device *fbdev, int mirror)
+static int omapfb_mirror(struct fb_info *fbi, int mirror)
 {
+       struct omapfb_plane_struct *plane = fbi->par;
        int r = 0;
 
-       DBGENTER(1);
-
        mirror = mirror ? 1 : 0;
        if (cpu_is_omap1510())
                r = -EINVAL;
-       else if (mirror != fbdev->mirror) {
-               fbdev->mirror = mirror;
-               r = ctrl_change_mode(fbdev);
+       else if (mirror != plane->info.mirror) {
+               plane->info.mirror = mirror;
+               r = ctrl_change_mode(fbi);
        }
 
-       DBGLEAVE(1);
        return r;
 }
 
@@ -570,15 +609,7 @@ static int omapfb_mirror(struct omapfb_device *fbdev, int mirror)
  */
 static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
-       int r;
-
-       DBGENTER(1);
-
-       r = set_fb_var(fbdev, var);
-
-       DBGLEAVE(1);
-       return r;
+       return set_fb_var(fbi, var);
 }
 
 /* Switch to a new mode. The parameters for it has been check already by
@@ -586,139 +617,158 @@ static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
  */
 static int omapfb_set_par(struct fb_info *fbi)
 {
-       int r;
-       struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
-
-       DBGENTER(1);
-
-       set_fb_fix(fbdev);
-       r = ctrl_change_mode(fbdev);
-
-       DBGLEAVE(1);
-       return r;
+       set_fb_fix(fbi);
+       return ctrl_change_mode(fbi);
 }
 
-int omapfb_update_window_async(struct omapfb_update_window *win,
-                                       void (*callback)(void *),
-                                       void *callback_data)
+int omapfb_update_window_async(struct fb_info *fbi,
+                               struct omapfb_update_window *win,
+                               void (*callback)(void *),
+                               void *callback_data)
 {
-       struct omapfb_device *fbdev = omapfb_dev;
+       struct omapfb_plane_struct *plane = fbi->par;
+       struct omapfb_device *fbdev = plane->fbdev;
        struct fb_var_screeninfo *var;
 
-       DBGENTER(2);
-       if (fbdev == NULL) {
-               DBGPRINT(1, "no fbdev\n");
-               return -ENODEV;
-       }
-
-       var = &fbdev->fb_info->var;
+       var = &fbi->var;
 
-       if (win->x >= var->xres || win->y >= var->yres) {
-               DBGPRINT(1, "invalid x %d, y %d\n", win->x, win->y);
+       if (win->x >= var->xres || win->y >= var->yres)
                return -EINVAL;
-       }
 
        if (!fbdev->ctrl->update_window ||
-           fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE) {
-               DBGPRINT(1, "invalid update mode\n");
+           fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
                return -ENODEV;
-       }
 
        if (win->x + win->width >= var->xres)
                win->width = var->xres - win->x;
        if (win->y + win->height >= var->yres)
                win->height = var->yres - win->y;
-       if (!win->width || !win->height) {
-               DBGPRINT(1, "zero size window\n");
+       if (!win->width || !win->height)
                return 0;
-       }
 
-       return fbdev->ctrl->update_window(win, callback, callback_data);
+       return fbdev->ctrl->update_window(fbi, win, callback, callback_data);
 }
 EXPORT_SYMBOL(omapfb_update_window_async);
 
-static int omapfb_update_win(struct omapfb_device *fbdev,
+static int omapfb_update_win(struct fb_info *fbi,
                                struct omapfb_update_window *win)
 {
+       struct omapfb_plane_struct *plane = fbi->par;
        int ret;
 
-       omapfb_rqueue_lock(fbdev);
-       ret = omapfb_update_window_async(win, NULL, 0);
-       omapfb_rqueue_unlock(fbdev);
+       omapfb_rqueue_lock(plane->fbdev);
+       ret = omapfb_update_window_async(fbi, win, NULL, 0);
+       omapfb_rqueue_unlock(plane->fbdev);
 
        return ret;
 }
 
-static void omapfb_update_full_screen(struct omapfb_device *fbdev)
+static int omapfb_update_full_screen(struct fb_info *fbi)
 {
+       struct omapfb_plane_struct *plane = fbi->par;
+       struct omapfb_device *fbdev = plane->fbdev;
        struct omapfb_update_window win;
+       int r;
+
+       if (!fbdev->ctrl->update_window ||
+           fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
+               return -ENODEV;
 
        win.x = 0;
        win.y = 0;
-       win.width = fbdev->panel->x_res;
-       win.height = fbdev->panel->y_res;
+       win.width = fbi->var.xres;
+       win.height = fbi->var.yres;
        win.format = 0;
 
        omapfb_rqueue_lock(fbdev);
-       fbdev->ctrl->update_window(&win, NULL, 0);
+       r = fbdev->ctrl->update_window(fbi, &win, NULL, 0);
        omapfb_rqueue_unlock(fbdev);
+
+       return r;
 }
 
-static int omapfb_setup_plane(struct omapfb_device *fbdev,
-                             struct omapfb_setup_plane *sp)
+static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
 {
+       struct omapfb_plane_struct *plane = fbi->par;
+       struct omapfb_device *fbdev = plane->fbdev;
        int r;
 
-       omapfb_rqueue_lock(fbdev);
-       r = fbdev->ctrl->setup_plane(sp->plane, sp->channel_out, sp->offset,
-                                sp->width, sp->pos_x, sp->pos_y, sp->width,
-                                sp->height, sp->color_mode);
-       omapfb_rqueue_unlock(fbdev);
+       plane->info = *pi;
+       r = ctrl_change_mode(fbi);
+       if (r < 0)
+               return r;
+       return fbdev->ctrl->enable_plane(plane->idx, pi->enabled);
+}
 
-       return r;
+static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+{
+       struct omapfb_plane_struct *plane = fbi->par;
+
+       *pi = plane->info;
+       return 0;
 }
 
-static int omapfb_enable_plane(struct omapfb_device *fbdev, int plane,
-                               int enable)
+static int omapfb_set_color_key(struct omapfb_device *fbdev,
+                               struct omapfb_color_key *ck)
 {
        int r;
 
+       if (!fbdev->ctrl->set_color_key)
+               return -ENODEV;
+
        omapfb_rqueue_lock(fbdev);
-       r = fbdev->ctrl->enable_plane(plane, enable);
+       r = fbdev->ctrl->set_color_key(ck);
        omapfb_rqueue_unlock(fbdev);
 
        return r;
 }
 
-static int omapfb_set_color_key(struct omapfb_device *fbdev,
+static int omapfb_get_color_key(struct omapfb_device *fbdev,
                                struct omapfb_color_key *ck)
 {
        int r;
 
-       if (!fbdev->ctrl->set_color_key)
+       if (!fbdev->ctrl->get_color_key)
                return -ENODEV;
 
        omapfb_rqueue_lock(fbdev);
-       r = fbdev->ctrl->set_color_key(ck);
+       r = fbdev->ctrl->get_color_key(ck);
        omapfb_rqueue_unlock(fbdev);
 
        return r;
 }
 
-static BLOCKING_NOTIFIER_HEAD(omapfb_notifier_list);
+static struct blocking_notifier_head omapfb_client_list[OMAPFB_PLANE_NUM];
+static int notifier_inited;
+
+static void omapfb_init_notifier(void)
+{
+       int i;
+
+       for (i = 0; i < OMAPFB_PLANE_NUM; i++)
+               BLOCKING_INIT_NOTIFIER_HEAD(&omapfb_client_list[i]);
+}
 
 int omapfb_register_client(struct omapfb_notifier_block *omapfb_nb,
-                           omapfb_notifier_callback_t callback,
-                           void *callback_data)
+                           omapfb_notifier_callback_t callback,
+                           void *callback_data)
 {
        int r;
 
-       DBGENTER(1);
+       if ((unsigned)omapfb_nb->plane_idx > OMAPFB_PLANE_NUM)
+               return -EINVAL;
+
+       if (!notifier_inited) {
+               omapfb_init_notifier();
+               notifier_inited = 1;
+       }
 
        omapfb_nb->nb.notifier_call = (int (*)(struct notifier_block *,
                                        unsigned long, void *))callback;
        omapfb_nb->data = callback_data;
-       r = blocking_notifier_chain_register(&omapfb_notifier_list, &omapfb_nb->nb);
+       r = blocking_notifier_chain_register(
+                               &omapfb_client_list[omapfb_nb->plane_idx],
+                               &omapfb_nb->nb);
        if (r)
                return r;
        if (omapfb_dev != NULL &&
@@ -732,15 +782,22 @@ EXPORT_SYMBOL(omapfb_register_client);
 
 int omapfb_unregister_client(struct omapfb_notifier_block *omapfb_nb)
 {
-       return blocking_notifier_chain_unregister(&omapfb_notifier_list,
-                                               &omapfb_nb->nb);
+       return blocking_notifier_chain_unregister(
+               &omapfb_client_list[omapfb_nb->plane_idx], &omapfb_nb->nb);
 }
 EXPORT_SYMBOL(omapfb_unregister_client);
 
 void omapfb_notify_clients(struct omapfb_device *fbdev, unsigned long event)
 {
-       DBGENTER(1);
-       blocking_notifier_call_chain(&omapfb_notifier_list, event, fbdev);
+       int i;
+
+       if (!notifier_inited)
+               /* no client registered yet */
+               return;
+
+       for (i = 0; i < OMAPFB_PLANE_NUM; i++)
+               blocking_notifier_call_chain(&omapfb_client_list[i], event,
+                                   fbdev->fb_info[i]);
 }
 EXPORT_SYMBOL(omapfb_notify_clients);
 
@@ -767,13 +824,12 @@ static enum omapfb_update_mode omapfb_get_update_mode(struct omapfb_device *fbde
        return r;
 }
 
-static unsigned long omapfb_get_caps(struct fb_info *fbi)
+static unsigned long omapfb_get_caps(struct omapfb_device *fbdev)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
        unsigned long caps;
 
        caps = 0;
-       caps |= fbdev->panel->get_caps();
+       caps |= fbdev->panel->get_caps(fbdev->panel);
        caps |= fbdev->ctrl->get_caps();
        return caps;
 }
@@ -782,7 +838,7 @@ static unsigned long omapfb_get_caps(struct fb_info *fbi)
 void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval)
 {
        omapfb_rqueue_lock(fbdev);
-       *(u16 *)fbdev->vram_virt_base = pixval;
+       *(u16 *)fbdev->mem_desc.region[0].vaddr = pixval;
        if (fbdev->ctrl->get_update_mode() == OMAPFB_MANUAL_UPDATE) {
                struct omapfb_update_window win;
 
@@ -791,42 +847,41 @@ void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval)
                win.width = 1;
                win.height = 1;
                win.format = 0;
-               fbdev->ctrl->update_window(&win, NULL, 0);
+               fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, 0);
        }
        omapfb_rqueue_unlock(fbdev);
 }
 EXPORT_SYMBOL(omapfb_write_first_pixel);
 
 /* Ioctl interface. Part of the kernel mode frame buffer API is duplicated
- * here to be accessible by user mode code. In addition transparent copy
- * graphics transformations, frame flipping support is provided through this
- * interface.
+ * here to be accessible by user mode code.
  */
 static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd,
                        unsigned long arg)
 {
-       struct omapfb_device    *fbdev = (struct omapfb_device *)fbi->par;
+       struct omapfb_plane_struct *plane = fbi->par;
+       struct omapfb_device    *fbdev = plane->fbdev;
        struct fb_ops           *ops = fbi->fbops;
        union {
                struct omapfb_update_window     update_window;
-               struct omapfb_setup_plane       setup_plane;
-               struct omapfb_enable_plane      enable_plane;
+               struct omapfb_plane_info        plane_info;
                struct omapfb_color_key         color_key;
                enum omapfb_update_mode         update_mode;
                unsigned long           caps;
                unsigned int            mirror;
+               int                     plane_out;
+               int                     enable_plane;
        } p;
        int r = 0;
 
        BUG_ON(!ops);
-       DBGPRINT(2, "cmd=%010x\n", cmd);
        switch (cmd)
        {
        case OMAPFB_MIRROR:
                if (get_user(p.mirror, (int __user *)arg))
                        r = -EFAULT;
                else
-                       omapfb_mirror(fbdev, p.mirror);
+                       omapfb_mirror(fbi, p.mirror);
                break;
        case OMAPFB_SYNC_GFX:
                omapfb_sync(fbi);
@@ -851,7 +906,7 @@ static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd,
                        r = -EFAULT;
                else {
                        p.update_window.format = 0;
-                       r = omapfb_update_win(fbdev, &p.update_window);
+                       r = omapfb_update_win(fbi, &p.update_window);
                }
                break;
        case OMAPFB_UPDATE_WINDOW:
@@ -859,22 +914,21 @@ static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd,
                                   sizeof(p.update_window)))
                        r = -EFAULT;
                else
-                       r = omapfb_update_win(fbdev, &p.update_window);
+                       r = omapfb_update_win(fbi, &p.update_window);
                break;
        case OMAPFB_SETUP_PLANE:
-               if (copy_from_user(&p.setup_plane, (void __user *)arg,
-                                  sizeof(p.setup_plane)))
+               if (copy_from_user(&p.plane_info, (void __user *)arg,
+                                  sizeof(p.plane_info)))
                        r = -EFAULT;
                else
-                       r = omapfb_setup_plane(fbdev, &p.setup_plane);
+                       r = omapfb_setup_plane(fbi, &p.plane_info);
                break;
-       case OMAPFB_ENABLE_PLANE:
-               if (copy_from_user(&p.enable_plane, (void __user *)arg,
-                                  sizeof(p.enable_plane)))
+       case OMAPFB_QUERY_PLANE:
+               if ((r = omapfb_query_plane(fbi, &p.plane_info)) < 0)
+                       break;
+               if (copy_to_user((void __user *)arg, &p.plane_info,
+                                  sizeof(p.plane_info)))
                        r = -EFAULT;
-               else
-                       r = omapfb_enable_plane(fbdev,
-                               p.enable_plane.plane, p.enable_plane.enable);
                break;
        case OMAPFB_SET_COLOR_KEY:
                if (copy_from_user(&p.color_key, (void __user *)arg,
@@ -883,9 +937,11 @@ static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd,
                else
                        r = omapfb_set_color_key(fbdev, &p.color_key);
                break;
-       case OMAPFB_GET_CAPS:
-               p.caps = omapfb_get_caps(fbi);
-               if (put_user(p.caps, (unsigned long __user *)arg))
+       case OMAPFB_GET_COLOR_KEY:
+               if ((r = omapfb_get_color_key(fbdev, &p.color_key)) < 0)
+                       break;
+               if (copy_to_user((void __user *)arg, &p.color_key,
+                                sizeof(p.color_key)))
                        r = -EFAULT;
                break;
        case OMAPFB_LCD_TEST:
@@ -900,7 +956,7 @@ static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd,
                                r = -EINVAL;
                                break;
                        }
-                       r = fbdev->panel->run_test(test_num);
+                       r = fbdev->panel->run_test(fbdev->panel, test_num);
                        break;
                }
        case OMAPFB_CTRL_TEST:
@@ -922,7 +978,6 @@ static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd,
                r = -EINVAL;
        }
 
-       DBGLEAVE(2);
        return r;
 }
 
@@ -956,8 +1011,7 @@ static ssize_t omapfb_show_caps_num(struct device *dev, struct device_attribute
 {
        struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
 
-       return snprintf(buf, PAGE_SIZE, "%#010lx\n",
-               omapfb_get_caps(fbdev->fb_info));
+       return snprintf(buf, PAGE_SIZE, "%#010lx\n", omapfb_get_caps(fbdev));
 }
 
 static ssize_t omapfb_show_caps_text(struct device *dev, struct device_attribute *attr, char *buf)
@@ -967,7 +1021,7 @@ static ssize_t omapfb_show_caps_text(struct device *dev, struct device_attribute
        int i;
        unsigned long caps;
 
-       caps = omapfb_get_caps(fbdev->fb_info);
+       caps = omapfb_get_caps(fbdev);
        for (i = 0; i < ARRAY_SIZE(omapfb_caps_table) && pos < PAGE_SIZE; i++) {
                if (omapfb_caps_table[i].flag & caps) {
                        pos += snprintf(&buf[pos], PAGE_SIZE - pos, "%s\n",
@@ -998,7 +1052,7 @@ static ssize_t omapfb_show_bklight_level(struct device *dev,
 
        if (fbdev->panel->get_bklight_level) {
                r = snprintf(buf, PAGE_SIZE, "%d\n",
-                            fbdev->panel->get_bklight_level());
+                            fbdev->panel->get_bklight_level(fbdev->panel));
        } else
                r = -ENODEV;
        return r;
@@ -1015,7 +1069,7 @@ static ssize_t omapfb_store_bklight_level(struct device *dev,
                unsigned int level;
 
                if (sscanf(buf, "%10d", &level) == 1) {
-                       r = fbdev->panel->set_bklight_level(level);
+                       r = fbdev->panel->set_bklight_level(fbdev->panel, level);
                } else
                        r = -EINVAL;
        } else
@@ -1031,7 +1085,7 @@ static ssize_t omapfb_show_bklight_max(struct device *dev,
 
        if (fbdev->panel->get_bklight_level) {
                r = snprintf(buf, PAGE_SIZE, "%d\n",
-                            fbdev->panel->get_bklight_max());
+                            fbdev->panel->get_bklight_max(fbdev->panel));
        } else
                r = -ENODEV;
        return r;
@@ -1101,7 +1155,7 @@ fail2:
 fail1:
        device_remove_file(fbdev->dev, &dev_attr_caps_num);
 fail0:
-       pr_err("unable to register sysfs interface\n");
+       dev_err(fbdev->dev, "unable to register sysfs interface\n");
        return r;
 }
 
@@ -1121,48 +1175,92 @@ static void omapfb_unregister_sysfs(struct omapfb_device *fbdev)
 /* Initialize system fb_info object and set the default video mode.
  * The frame buffer memory already allocated by lcddma_init
  */
-static int fbinfo_init(struct omapfb_device *fbdev)
+static int fbinfo_init(struct omapfb_device *fbdev, struct fb_info *info,
+                       struct omapfb_mem_region *region)
 {
-       struct fb_info                  *info = fbdev->fb_info;
        struct fb_var_screeninfo        *var = &info->var;
+       struct fb_fix_screeninfo        *fix = &info->fix;
        int                             r = 0;
 
-       DBGENTER(1);
-
-       BUG_ON(!fbdev->vram_virt_base);
-
        info->fbops = &omapfb_ops;
        info->flags = FBINFO_FLAG_DEFAULT;
-       info->screen_base = (char __iomem *)fbdev->vram_virt_base;
+
+       strncpy(fix->id, MODULE_NAME, sizeof(fix->id));
+
+       info->screen_base       = (char __iomem *)region->vaddr;
+       fix->smem_start         = region->paddr;
+       fix->smem_len           = region->size;
 
        info->pseudo_palette = fbdev->pseudo_palette;
 
        var->accel_flags  = def_accel ? FB_ACCELF_TEXT : 0;
+       var->xres = def_vxres;
+       var->yres = def_vyres;
        var->xres_virtual = def_vxres;
        var->yres_virtual = def_vyres;
        var->rotate       = def_rotate;
+       var->bits_per_pixel = fbdev->panel->bpp;
 
-       fbdev->mirror = def_mirror;
-
-       set_fb_var(fbdev, var);
-       set_fb_fix(fbdev);
+       set_fb_var(info, var);
+       set_fb_fix(info);
 
        r = fb_alloc_cmap(&info->cmap, 16, 0);
        if (r != 0)
-               pr_err("unable to allocate color map memory\n");
+               dev_err(fbdev->dev, "unable to allocate color map memory\n");
 
-       DBGLEAVE(1);
        return r;
 }
 
 /* Release the fb_info object */
-static void fbinfo_cleanup(struct omapfb_device *fbdev)
+static void fbinfo_cleanup(struct omapfb_device *fbdev, struct fb_info *fbi)
 {
-       DBGENTER(1);
+       fb_dealloc_cmap(&fbi->cmap);
+}
 
-       fb_dealloc_cmap(&fbdev->fb_info->cmap);
+static void planes_cleanup(struct omapfb_device *fbdev)
+{
+       int i;
 
-       DBGLEAVE(1);
+       for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+               if (fbdev->fb_info[i] == NULL)
+                       break;
+               fbinfo_cleanup(fbdev, fbdev->fb_info[i]);
+               framebuffer_release(fbdev->fb_info[i]);
+       }
+}
+
+static int planes_init(struct omapfb_device *fbdev)
+{
+       struct fb_info *fbi;
+       int i;
+       int r;
+
+       for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+               struct omapfb_plane_struct *plane;
+               fbi = framebuffer_alloc(sizeof(struct omapfb_plane_struct),
+                                       fbdev->dev);
+               if (fbi == NULL) {
+                       dev_err(fbdev->dev,
+                               "unable to allocate memory for plane info\n");
+                       planes_cleanup(fbdev);
+                       return -ENOMEM;
+               }
+               plane = fbi->par;
+               plane->idx = i;
+               plane->fbdev = fbdev;
+               plane->info.mirror = def_mirror;
+               fbdev->fb_info[i] = fbi;
+
+               if ((r = fbinfo_init(fbdev, fbi,
+                                       &fbdev->mem_desc.region[i])) < 0) {
+                       framebuffer_release(fbi);
+                       planes_cleanup(fbdev);
+                       return r;
+               }
+               plane->info.out_width = fbi->var.xres;
+               plane->info.out_height = fbi->var.yres;
+       }
+       return 0;
 }
 
 /* Free driver resources. Can be called to rollback an aborted initialization
@@ -1170,24 +1268,27 @@ static void fbinfo_cleanup(struct omapfb_device *fbdev)
  */
 static void omapfb_free_resources(struct omapfb_device *fbdev, int state)
 {
+       int i;
+
        switch (state) {
        case OMAPFB_ACTIVE:
-               unregister_framebuffer(fbdev->fb_info);
+               for (i = 0; i < fbdev->mem_desc.region_cnt; i++)
+                       unregister_framebuffer(fbdev->fb_info[i]);
        case 7:
                omapfb_unregister_sysfs(fbdev);
        case 6:
-               fbdev->panel->disable();
+               fbdev->panel->disable(fbdev->panel);
        case 5:
                omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED);
        case 4:
-               fbinfo_cleanup(fbdev);
+               planes_cleanup(fbdev);
        case 3:
                ctrl_cleanup(fbdev);
        case 2:
-               fbdev->panel->cleanup();
+               fbdev->panel->cleanup(fbdev->panel);
        case 1:
                dev_set_drvdata(fbdev->dev, NULL);
-               framebuffer_release(fbdev->fb_info);
+               kfree(fbdev);
        case 0:
                /* nothing to free */
                break;
@@ -1202,13 +1303,9 @@ static int omapfb_find_ctrl(struct omapfb_device *fbdev)
        char name[17];
        int i;
 
-       conf = (struct omapfb_platform_data *)fbdev->dev->platform_data;
+       conf = fbdev->dev->platform_data;
 
        fbdev->ctrl = NULL;
-       if (conf == NULL) {
-               DBGPRINT(1, "omap_lcd_config not found\n");
-               return -1;
-       }
 
        strncpy(name, conf->lcd.ctrl_name, sizeof(name) - 1);
        name[sizeof(name) - 1] = '\0';
@@ -1219,7 +1316,7 @@ static int omapfb_find_ctrl(struct omapfb_device *fbdev)
        }
 
        for (i = 0; i < ARRAY_SIZE(ctrls); i++) {
-               DBGPRINT(1, "ctrl %s\n", ctrls[i]->name);
+               dev_dbg(fbdev->dev, "ctrl %s\n", ctrls[i]->name);
                if (strcmp(ctrls[i]->name, name) == 0) {
                        fbdev->ctrl = ctrls[i];
                        break;
@@ -1227,7 +1324,7 @@ static int omapfb_find_ctrl(struct omapfb_device *fbdev)
        }
 
        if (fbdev->ctrl == NULL) {
-               DBGPRINT(1, "ctrl %s not supported\n", name);
+               dev_dbg(fbdev->dev, "ctrl %s not supported\n", name);
                return -1;
        }
 
@@ -1249,44 +1346,48 @@ static void check_required_callbacks(struct omapfb_device *fbdev)
 
 /* Called by LDM binding to probe and attach a new device.
  * Initialization sequence:
- *   1. allocate system fb_info structure
- *      select panel type according to machine type
- *   2. init LCD panel
+ *   1. allocate system omapfb_device structure
+ *   2. select controller type according to platform configuration
+ *      init LCD panel
  *   3. init LCD controller and LCD DMA
- *   4. init system fb_info structure
- *   5. init gfx DMA
+ *   4. init system fb_info structure for all planes
+ *   5. setup video mode for first plane and enable it
  *   6. enable LCD panel
- *      start LCD frame transfer
- *   7. register system fb_info structure
+ *   7. register sysfs attributes
+ *   OMAPFB_ACTIVE: register system fb_info structure for all planes
  */
 static int omapfb_do_probe(struct platform_device *pdev, struct lcd_panel *panel)
 {
        struct omapfb_device    *fbdev = NULL;
-       struct fb_info          *fbi;
        int                     init_state;
        unsigned long           phz, hhz, vhz;
+       unsigned long           vram;
+       int                     i;
        int                     r = 0;
 
-       DBGENTER(1);
-
        init_state = 0;
 
        if (pdev->num_resources != 0) {
-               pr_err("probed for an unknown device\n");
+               dev_err(&pdev->dev, "probed for an unknown device\n");
                r = -ENODEV;
                goto cleanup;
        }
 
-       fbi = framebuffer_alloc(sizeof(struct omapfb_device), &pdev->dev);
-       if (fbi == NULL) {
-               pr_err("unable to allocate memory for device info\n");
+       if (pdev->dev.platform_data == NULL) {
+               dev_err(&pdev->dev, "missing platform data\n");
+               r = -ENOENT;
+               goto cleanup;
+       }
+
+       fbdev = kzalloc(sizeof(struct omapfb_device), GFP_KERNEL);
+       if (fbdev == NULL) {
+               dev_err(&pdev->dev,
+                       "unable to allocate memory for device info\n");
                r = -ENOMEM;
                goto cleanup;
        }
        init_state++;
 
-       fbdev = (struct omapfb_device *)fbi->par;
-       fbdev->fb_info = fbi;
        fbdev->dev = &pdev->dev;
        fbdev->panel = panel;
        platform_set_drvdata(pdev, fbdev);
@@ -1296,25 +1397,30 @@ static int omapfb_do_probe(struct platform_device *pdev, struct lcd_panel *panel
 #ifdef CONFIG_ARCH_OMAP1
        fbdev->int_ctrl = &omap1_int_ctrl;
 #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
-       fbdev->ext_if = &sossi_extif;
+       fbdev->ext_if = &omap1_ext_if;
 #endif
 #else  /* OMAP2 */
        fbdev->int_ctrl = &omap2_int_ctrl;
 #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
-       fbdev->ext_if = &rfbi_extif;
+       fbdev->ext_if = &omap2_ext_if;
 #endif
 #endif
        if (omapfb_find_ctrl(fbdev) < 0) {
-               pr_err("LCD controller not found, board not supported\n");
+               dev_err(fbdev->dev,
+                       "LCD controller not found, board not supported\n");
                r = -ENODEV;
                goto cleanup;
        }
 
-       pr_info(MODULE_NAME ": configured for panel %s\n", fbdev->panel->name);
-
-       r = fbdev->panel->init(fbdev);
+       r = fbdev->panel->init(fbdev->panel, fbdev);
        if (r)
                goto cleanup;
+
+       pr_info("omapfb: configured for panel %s\n", fbdev->panel->name);
+
+       def_vxres = def_vxres ? : fbdev->panel->x_res;
+       def_vyres = def_vyres ? : fbdev->panel->y_res;
+
        init_state++;
 
        r = ctrl_init(fbdev);
@@ -1322,15 +1428,9 @@ static int omapfb_do_probe(struct platform_device *pdev, struct lcd_panel *panel
                goto cleanup;
        init_state++;
 
-       /* We depend on doing this after ctrl_init, since it can redefine
-        * member functions.
-        */
-       if (fbdev->ctrl->mmap)
-               omapfb_ops.fb_mmap = omapfb_mmap;
-
        check_required_callbacks(fbdev);
 
-       r = fbinfo_init(fbdev);
+       r = planes_init(fbdev);
        if (r)
                goto cleanup;
        init_state++;
@@ -1338,23 +1438,25 @@ static int omapfb_do_probe(struct platform_device *pdev, struct lcd_panel *panel
 #ifdef CONFIG_FB_OMAP_DMA_TUNE
        /* Set DMA priority for EMIFF access to highest */
        if (cpu_class_is_omap1())
-               omap_set_dma_priority(0, OMAP_DMA_PORT_EMIFF, 15);
+               omap_set_dma_priority(OMAP_DMA_PORT_EMIFF, 15);
 #endif
 
-       r = ctrl_change_mode(fbdev);
+       r = ctrl_change_mode(fbdev->fb_info[0]);
        if (r) {
-               pr_err("mode setting failed\n");
+               dev_err(fbdev->dev, "mode setting failed\n");
                goto cleanup;
        }
 
-       if (!manual_update)
-               omapfb_enable_plane(fbdev, OMAPFB_PLANE_GFX, 1);
+       /* GFX plane is enabled by default */
+       r = fbdev->ctrl->enable_plane(OMAPFB_PLANE_GFX, 1);
+       if (r)
+               goto cleanup;
 
        omapfb_set_update_mode(fbdev, manual_update ?
                                   OMAPFB_MANUAL_UPDATE : OMAPFB_AUTO_UPDATE);
        init_state++;
 
-       r = fbdev->panel->enable();
+       r = fbdev->panel->enable(fbdev->panel);
        if (r)
                goto cleanup;
        init_state++;
@@ -1364,10 +1466,15 @@ static int omapfb_do_probe(struct platform_device *pdev, struct lcd_panel *panel
                goto cleanup;
        init_state++;
 
-       r = register_framebuffer(fbdev->fb_info);
-       if (r != 0) {
-               pr_err("register_framebuffer failed\n");
-               goto cleanup;
+       vram = 0;
+       for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+               r = register_framebuffer(fbdev->fb_info[i]);
+               if (r != 0) {
+                       dev_err(fbdev->dev,
+                               "registering framebuffer %d failed\n", i);
+                       goto cleanup;
+               }
+               vram += fbdev->mem_desc.region[i].size;
        }
 
        fbdev->state = OMAPFB_ACTIVE;
@@ -1379,18 +1486,17 @@ static int omapfb_do_probe(struct platform_device *pdev, struct lcd_panel *panel
 
        omapfb_dev = fbdev;
 
-       pr_info(MODULE_NAME ": initialized vram=%lu "
-                       "pixclock %lu kHz hfreq %lu.%lu kHz vfreq %lu.%lu Hz\n",
-                       fbdev->vram_size,
+       pr_info("omapfb: Framebuffer initialized. Total vram %lu planes %d\n",
+                       vram, fbdev->mem_desc.region_cnt);
+       pr_info("omapfb: Pixclock %lu kHz hfreq %lu.%lu kHz "
+                       "vfreq %lu.%lu Hz\n",
                        phz / 1000, hhz / 10000, hhz % 10, vhz / 10, vhz % 10);
 
-       DBGLEAVE(1);
        return 0;
 
 cleanup:
        omapfb_free_resources(fbdev, init_state);
 
-       DBGLEAVE(1);
        return r;
 }
 
@@ -1398,7 +1504,7 @@ static int omapfb_probe(struct platform_device *pdev)
 {
        BUG_ON(fbdev_pdev != NULL);
 
-       DBGENTER(1);
+       /* Delay actual initialization until the LCD is registered */
        fbdev_pdev = pdev;
        if (fbdev_panel != NULL)
                omapfb_do_probe(fbdev_pdev, fbdev_panel);
@@ -1409,7 +1515,6 @@ void omapfb_register_panel(struct lcd_panel *panel)
 {
        BUG_ON(fbdev_panel != NULL);
 
-       DBGENTER(1);
        fbdev_panel = panel;
        if (fbdev_pdev != NULL)
                omapfb_do_probe(fbdev_pdev, fbdev_panel);
@@ -1421,13 +1526,11 @@ static int omapfb_remove(struct platform_device *pdev)
        struct omapfb_device *fbdev = platform_get_drvdata(pdev);
        enum omapfb_state saved_state = fbdev->state;
 
-       DBGENTER(1);
        /* FIXME: wait till completion of pending events */
 
        fbdev->state = OMAPFB_DISABLED;
        omapfb_free_resources(fbdev, saved_state);
 
-       DBGLEAVE(1);
        return 0;
 }
 
@@ -1436,11 +1539,7 @@ static int omapfb_suspend(struct platform_device *pdev, pm_message_t mesg)
 {
        struct omapfb_device *fbdev = platform_get_drvdata(pdev);
 
-       DBGENTER(1);
-
-       omapfb_blank(VESA_POWERDOWN, fbdev->fb_info);
-
-       DBGLEAVE(1);
+       omapfb_blank(VESA_POWERDOWN, fbdev->fb_info[0]);
 
        return 0;
 }
@@ -1450,11 +1549,7 @@ static int omapfb_resume(struct platform_device *pdev)
 {
        struct omapfb_device *fbdev = platform_get_drvdata(pdev);
 
-       DBGENTER(1);
-
-       omapfb_blank(VESA_NO_BLANKING, fbdev->fb_info);
-
-       DBGLEAVE(1);
+       omapfb_blank(VESA_NO_BLANKING, fbdev->fb_info[0]);
        return 0;
 }
 
@@ -1464,7 +1559,7 @@ static struct platform_driver omapfb_driver = {
        .suspend        = omapfb_suspend,
        .resume         = omapfb_resume,
        .driver         = {
-               .name   = OMAPFB_DRIVER,
+               .name   = MODULE_NAME,
                .owner  = THIS_MODULE,
        },
 };
@@ -1477,32 +1572,35 @@ static int __init omapfb_setup(char *options)
        char *this_opt = NULL;
        int r = 0;
 
-       DBGENTER(1);
+       pr_debug("omapfb: options %s\n", options);
 
        if (!options || !*options)
-               goto exit;
+               return 0;
 
        while (!r && (this_opt = strsep(&options, ",")) != NULL) {
                if (!strncmp(this_opt, "accel", 5))
                        def_accel = 1;
                else if (!strncmp(this_opt, "vram:", 5)) {
                        char *suffix;
-                       def_vram = (simple_strtoul(this_opt + 5, &suffix, 0));
+                       unsigned long vram;
+                       vram = (simple_strtoul(this_opt + 5, &suffix, 0));
                        switch (suffix[0]) {
                        case '\0':
                                break;
                        case 'm':
                        case 'M':
-                               def_vram *= 1024;
+                               vram *= 1024;
                                /* Fall through */
                        case 'k':
                        case 'K':
-                               def_vram *= 1024;
+                               vram *= 1024;
                                break;
                        default:
-                               pr_err("invalid vram suffix\n");
+                               pr_debug("omapfb: invalid vram suffix %c\n",
+                                        suffix[0]);
                                r = -1;
                        }
+                       def_vram[def_vram_cnt++] = vram;
                }
                else if (!strncmp(this_opt, "vxres:", 6))
                        def_vxres = simple_strtoul(this_opt + 6, NULL, 0);
@@ -1515,12 +1613,11 @@ static int __init omapfb_setup(char *options)
                else if (!strncmp(this_opt, "manual_update", 13))
                        manual_update = 1;
                else {
-                       pr_err("invalid option\n");
+                       pr_debug("omapfb: invalid option\n");
                        r = -1;
                }
        }
-exit:
-       DBGLEAVE(1);
+
        return r;
 }
 
@@ -1529,44 +1626,29 @@ exit:
 /* Register both the driver and the device */
 static int __init omapfb_init(void)
 {
-       int r = 0;
-
-       DBGENTER(1);
-
 #ifndef MODULE
-       {
-               char *option;
+       char *option;
 
-               if (fb_get_options("omapfb", &option)) {
-                       r = -ENODEV;
-                       goto exit;
-               }
-               omapfb_setup(option);
-       }
+       if (fb_get_options("omapfb", &option))
+               return -ENODEV;
+       omapfb_setup(option);
 #endif
        /* Register the driver with LDM */
        if (platform_driver_register(&omapfb_driver)) {
-               pr_err("failed to register omapfb driver\n");
-               r = -ENODEV;
-               goto exit;
+               pr_debug("failed to register omapfb driver\n");
+               return -ENODEV;
        }
 
-exit:
-       DBGLEAVE(1);
-       return r;
+       return 0;
 }
 
 static void __exit omapfb_cleanup(void)
 {
-       DBGENTER(1);
-
        platform_driver_unregister(&omapfb_driver);
-
-       DBGLEAVE(1);
 }
 
 module_param_named(accel, def_accel, uint, 0664);
-module_param_named(vram, def_vram, ulong, 0664);
+module_param_array_named(vram, def_vram, ulong, &def_vram_cnt, 0664);
 module_param_named(vxres, def_vxres, long, 0664);
 module_param_named(vyres, def_vyres, long, 0664);
 module_param_named(rotate, def_rotate, uint, 0664);
index 82415f50a6961d2fb5ff0b438f998a4f60356a3e..5347e9b9d22d29185ba8a8e606f06eb690fbde5b 100644 (file)
@@ -21,7 +21,6 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
-
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
 
 #include "dispc.h"
 
-/* #define OMAPFB_DBG 1 */
-
-#include "debug.h"
-
-#define MODULE_NAME "omapfb-rfbi"
-
-#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
-
 #define RFBI_BASE              0x48050800
 #define RFBI_REVISION          0x0000
 #define RFBI_SYSCONFIG         0x0010
@@ -73,10 +64,9 @@ static struct {
        void            *lcdc_callback_data;
        unsigned long   l4_khz;
        int             bits_per_cycle;
+       struct omapfb_device *fbdev;
 } rfbi;
 
-struct lcd_ctrl_extif rfbi_extif;
-
 static inline void rfbi_write_reg(int idx, u32 val)
 {
        __raw_writel(val, rfbi.base + idx);
@@ -87,7 +77,7 @@ static inline u32 rfbi_read_reg(int idx)
        return __raw_readl(rfbi.base + idx);
 }
 
-#ifdef OMAPFB_DBG
+#ifdef VERBOSE
 static void rfbi_print_timings(void)
 {
        u32 l;
@@ -98,16 +88,20 @@ static void rfbi_print_timings(void)
        if (l & (1 << 4))
                time *= 2;
 
-       DBGPRINT(1, "Tick time %u ps\n", time);
+       dev_dbg(rfbi.fbdev->dev, "Tick time %u ps\n", time);
        l = rfbi_read_reg(RFBI_ONOFF_TIME0);
-       DBGPRINT(1, "CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
-              "REONTIME %d, REOFFTIME %d\n",
-              l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
-              (l >> 20) & 0x0f, (l >> 24) & 0x3f);
+       dev_dbg(rfbi.fbdev->dev,
+               "CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
+               "REONTIME %d, REOFFTIME %d\n",
+               l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
+               (l >> 20) & 0x0f, (l >> 24) & 0x3f);
+
        l = rfbi_read_reg(RFBI_CYCLE_TIME0);
-       DBGPRINT(1, "WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
-              "ACCESSTIME %d\n",
-              (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f, (l >> 22) & 0x3f);
+       dev_dbg(rfbi.fbdev->dev,
+               "WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
+               "ACCESSTIME %d\n",
+               (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
+               (l >> 22) & 0x3f);
 }
 #else
 static void rfbi_print_timings(void) {}
@@ -341,20 +335,18 @@ static void rfbi_set_bits_per_cycle(int bpc)
        rfbi.bits_per_cycle = bpc;
 }
 
-static int rfbi_init(void)
+static int rfbi_init(struct omapfb_device *fbdev)
 {
        u32 l;
        int r;
        struct clk *dss_ick;
 
+       rfbi.fbdev = fbdev;
        rfbi.base = io_p2v(RFBI_BASE);
 
-       l = rfbi_read_reg(RFBI_REVISION);
-       pr_info(MODULE_NAME ": version %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
-
        dss_ick = clk_get(NULL, "dss_ick");
        if (IS_ERR(dss_ick)) {
-               pr_err("can't get dss_ick\n");
+               dev_err(fbdev->dev, "can't get dss_ick\n");
                return PTR_ERR(dss_ick);
        }
 
@@ -383,10 +375,14 @@ static int rfbi_init(void)
        rfbi_write_reg(RFBI_CONTROL, l);
 
        if ((r = omap_dispc_request_irq(rfbi_dma_callback, NULL)) < 0) {
-               pr_err("can't get DISPC irq\n");
+               dev_err(fbdev->dev, "can't get DISPC irq\n");
                return r;
        }
 
+       l = rfbi_read_reg(RFBI_REVISION);
+       pr_info("omapfb: RFBI version %d.%d initialized\n",
+               (l >> 4) & 0x0f, l & 0x0f);
+
        return 0;
 }
 
@@ -395,7 +391,7 @@ static void rfbi_cleanup(void)
        omap_dispc_free_irq();
 }
 
-struct lcd_ctrl_extif rfbi_extif = {
+const struct lcd_ctrl_extif omap2_ext_if = {
        .init                   = rfbi_init,
        .cleanup                = rfbi_cleanup,
        .get_clk_info           = rfbi_get_clk_info,
@@ -406,6 +402,7 @@ struct lcd_ctrl_extif rfbi_extif = {
        .read_data              = rfbi_read_data,
        .write_data             = rfbi_write_data,
        .transfer_area          = rfbi_transfer_area,
+
        .max_transmit_size      = (u32)~0,
 };
 
index 64dd0a46e5155a7cbf9ccbf64c03c3f2802350e6..447989f7221550711769fddcec73b795ad54d4f7 100644 (file)
@@ -20,7 +20,6 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/mm.h>
 
 #include "lcdc.h"
 
-/* #define OMAPFB_DBG 1 */
-
-#include "debug.h"
-
 #define MODULE_NAME            "omapfb-sossi"
 
 #define OMAP_SOSSI_BASE         0xfffbac00
 
 #define SOSSI_MAX_XMIT_BYTES   (512 * 1024)
 
-#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
-
-static struct sossi {
-       int             base;
+static struct {
+       void __iomem    *base;
        unsigned long   dpll_khz;
        int             bus_pick_width;
        void            (*lcdc_callback)(void *data);
@@ -76,9 +69,10 @@ static struct sossi {
         * the timings
         */
        int             last_access;
-} sossi;
 
-struct lcd_ctrl_extif sossi_extif;
+       struct omapfb_device    *fbdev;
+       struct lcd_ctrl_extif   *extif;
+} sossi;
 
 static inline u32 sossi_read_reg(int reg)
 {
@@ -126,86 +120,8 @@ static void sossi_clear_bits(int reg, u32 bits)
 
 static void sossi_dma_callback(void *data);
 
-static int sossi_init(void)
-{
-       u32 l, k;
-       struct clk *dpll_clk;
-       int r;
-
-       sossi.base = IO_ADDRESS(OMAP_SOSSI_BASE);
-
-       dpll_clk = clk_get(NULL, "ck_dpll1");
-       if (IS_ERR(dpll_clk)) {
-               pr_err("can't get dpll1 clock\n");
-               return PTR_ERR(dpll_clk);
-       }
-
-       sossi.dpll_khz = clk_get_rate(dpll_clk) / 1000;
-       clk_put(dpll_clk);
-
-       sossi_extif.max_transmit_size = SOSSI_MAX_XMIT_BYTES;
-
-       /* Reset and enable the SoSSI module */
-       l = omap_readl(MOD_CONF_CTRL_1);
-       l |= CONF_SOSSI_RESET_R;
-       omap_writel(l, MOD_CONF_CTRL_1);
-       l &= ~CONF_SOSSI_RESET_R;
-       omap_writel(l, MOD_CONF_CTRL_1);
-
-       l |= CONF_MOD_SOSSI_CLK_EN_R;
-       omap_writel(l, MOD_CONF_CTRL_1);
-
-       omap_writel(omap_readl(ARM_IDLECT2) | (1 << 11), ARM_IDLECT2);
-       omap_writel(omap_readl(ARM_IDLECT1) | (1 << 6), ARM_IDLECT1);
-
-       l = sossi_read_reg(SOSSI_INIT2_REG);
-       /* Enable and reset the SoSSI block */
-       l |= (1 << 0) | (1 << 1);
-       sossi_write_reg(SOSSI_INIT2_REG, l);
-       /* Take SoSSI out of reset */
-       l &= ~(1 << 1);
-       sossi_write_reg(SOSSI_INIT2_REG, l);
-
-       sossi_write_reg(SOSSI_ID_REG, 0);
-       l = sossi_read_reg(SOSSI_ID_REG);
-       k = sossi_read_reg(SOSSI_ID_REG);
-
-       if (l != 0x55555555 || k != 0xaaaaaaaa) {
-               pr_err("Invalid SoSSI sync pattern: %08x, %08x\n", l, k);
-               return -ENODEV;
-       }
-
-       if ((r = omap_lcdc_set_dma_callback(sossi_dma_callback, NULL)) < 0) {
-               pr_err("can't get LCDC IRQ\n");
-               return r;
-       }
-
-       l = sossi_read_reg(SOSSI_ID_REG); /* Component code */
-       l = sossi_read_reg(SOSSI_ID_REG);
-       pr_info(KERN_INFO MODULE_NAME ": version %d.%d initialized\n",
-                       l >> 16, l & 0xffff);
-
-       l = sossi_read_reg(SOSSI_INIT1_REG);
-       l |= (1 << 19); /* DMA_MODE */
-       l &= ~(1 << 31); /* REORDERING */
-       sossi_write_reg(SOSSI_INIT1_REG, l);
-
-       return 0;
-}
-
-static void sossi_cleanup(void)
-{
-       omap_lcdc_free_dma_callback();
-}
-
 #define KHZ_TO_PS(x)   (1000000000 / (x))
 
-static void sossi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
-{
-       *clk_period = KHZ_TO_PS(sossi.dpll_khz);
-       *max_clk_div = 8;
-}
-
 static u32 ps_to_sossi_ticks(u32 ps, int div)
 {
        u32 clk_period = KHZ_TO_PS(sossi.dpll_khz) * div;
@@ -299,49 +215,14 @@ static int calc_wr_timings(struct extif_timings *t)
        return 0;
 }
 
-static int sossi_convert_timings(struct extif_timings *t)
-{
-       int r = 0;
-       int div = t->clk_div;
-
-       t->converted = 0;
-
-       if (div <= 0 || div > 8)
-               return -1;
-
-       /* no CS on SOSSI, so ignore cson, csoff, cs_pulsewidth */
-       if ((r = calc_rd_timings(t)) < 0)
-               return r;
-
-       if ((r = calc_wr_timings(t)) < 0)
-               return r;
-
-       t->tim[4] = div - 1;
-
-       t->converted = 1;
-
-       return 0;
-}
-
-static void sossi_set_timings(const struct extif_timings *t)
-{
-       BUG_ON(!t->converted);
-
-       sossi.clk_tw0[RD_ACCESS] = t->tim[0];
-       sossi.clk_tw1[RD_ACCESS] = t->tim[1];
-
-       sossi.clk_tw0[WR_ACCESS] = t->tim[2];
-       sossi.clk_tw1[WR_ACCESS] = t->tim[3];
-
-       sossi.clk_div = t->tim[4];
-}
-
 static void _set_timing(int div, int tw0, int tw1)
 {
        u32 l;
 
-       DBGPRINT(2, "Using TW0 = %d, TW1 = %d, div = %d\n",
+#ifdef VERBOSE
+       dev_dbg(sossi.fbdev->dev, "Using TW0 = %d, TW1 = %d, div = %d\n",
                 tw0 + 1, tw1 + 1, div + 1);
+#endif
 
        l = omap_readl(MOD_CONF_CTRL_1);
        l &= ~(7 << 17);
@@ -363,36 +244,6 @@ static inline void set_timing(int access)
        }
 }
 
-static void sossi_set_bits_per_cycle(int bpc)
-{
-       u32 l;
-       int bus_pick_count, bus_pick_width;
-
-       DBGPRINT(2, "bits_per_cycle %d\n", bpc);
-       /* We set explicitly the the bus_pick_count as well, although
-        * with remapping/reordering disabled it will be calculated by HW
-        * as (32 / bus_pick_width).
-        */
-       switch (bpc) {
-       case 8:
-               bus_pick_count = 4;
-               bus_pick_width = 8;
-               break;
-       case 16:
-               bus_pick_count = 2;
-               bus_pick_width = 16;
-               break;
-       default:
-               BUG();
-               return;
-       }
-       l = sossi_read_reg(SOSSI_INIT3_REG);
-       sossi.bus_pick_width = bus_pick_width;
-       l &= ~0x3ff;
-       l |= ((bus_pick_count - 1) << 5) | ((bus_pick_width - 1) & 0x1f);
-       sossi_write_reg(SOSSI_INIT3_REG, l);
-}
-
 static void sossi_start_transfer(void)
 {
        /* WE */
@@ -446,6 +297,78 @@ static void set_cycles(unsigned int len)
        sossi_set_bits(SOSSI_INIT1_REG, (nr_cycles - 1) & 0x3ffff);
 }
 
+static int sossi_convert_timings(struct extif_timings *t)
+{
+       int r = 0;
+       int div = t->clk_div;
+
+       t->converted = 0;
+
+       if (div <= 0 || div > 8)
+               return -1;
+
+       /* no CS on SOSSI, so ignore cson, csoff, cs_pulsewidth */
+       if ((r = calc_rd_timings(t)) < 0)
+               return r;
+
+       if ((r = calc_wr_timings(t)) < 0)
+               return r;
+
+       t->tim[4] = div - 1;
+
+       t->converted = 1;
+
+       return 0;
+}
+
+static void sossi_set_timings(const struct extif_timings *t)
+{
+       BUG_ON(!t->converted);
+
+       sossi.clk_tw0[RD_ACCESS] = t->tim[0];
+       sossi.clk_tw1[RD_ACCESS] = t->tim[1];
+
+       sossi.clk_tw0[WR_ACCESS] = t->tim[2];
+       sossi.clk_tw1[WR_ACCESS] = t->tim[3];
+
+       sossi.clk_div = t->tim[4];
+}
+
+static void sossi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
+{
+       *clk_period = KHZ_TO_PS(sossi.dpll_khz);
+       *max_clk_div = 8;
+}
+
+static void sossi_set_bits_per_cycle(int bpc)
+{
+       u32 l;
+       int bus_pick_count, bus_pick_width;
+
+       /* We set explicitly the the bus_pick_count as well, although
+        * with remapping/reordering disabled it will be calculated by HW
+        * as (32 / bus_pick_width).
+        */
+       switch (bpc) {
+       case 8:
+               bus_pick_count = 4;
+               bus_pick_width = 8;
+               break;
+       case 16:
+               bus_pick_count = 2;
+               bus_pick_width = 16;
+               break;
+       default:
+               BUG();
+               return;
+       }
+       l = sossi_read_reg(SOSSI_INIT3_REG);
+       sossi.bus_pick_width = bus_pick_width;
+       l &= ~0x3ff;
+       l |= ((bus_pick_count - 1) << 5) | ((bus_pick_width - 1) & 0x1f);
+       sossi_write_reg(SOSSI_INIT3_REG, l);
+}
+
 static void sossi_write_command(const void *data, unsigned int len)
 {
        set_timing(WR_ACCESS);
@@ -483,8 +406,6 @@ static void sossi_transfer_area(int width, int height,
        sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
        set_cycles(width * height * sossi.bus_pick_width / 8);
 
-       DBGPRINT(2, "SOSSI_INIT1_REG %08x\n", sossi_read_reg(SOSSI_INIT1_REG));
-
        sossi_start_transfer();
        omap_enable_lcd_dma();
 }
@@ -521,7 +442,79 @@ static void sossi_read_data(void *data, unsigned int len)
        sossi_stop_transfer();
 }
 
-struct lcd_ctrl_extif sossi_extif = {
+static int sossi_init(struct omapfb_device *fbdev)
+{
+       u32 l, k;
+       struct clk *dpll_clk;
+       int r;
+
+       sossi.fbdev = fbdev;
+
+       sossi.base = (void __iomem *)IO_ADDRESS(OMAP_SOSSI_BASE);
+       dpll_clk = clk_get(fbdev->dev, "ck_dpll1");
+       if (IS_ERR(dpll_clk)) {
+               dev_err(fbdev->dev, "can't get dpll1 clock\n");
+               return PTR_ERR(dpll_clk);
+       }
+
+       sossi.dpll_khz = clk_get_rate(dpll_clk) / 1000;
+       clk_put(dpll_clk);
+
+       /* Reset and enable the SoSSI module */
+       l = omap_readl(MOD_CONF_CTRL_1);
+       l |= CONF_SOSSI_RESET_R;
+       omap_writel(l, MOD_CONF_CTRL_1);
+       l &= ~CONF_SOSSI_RESET_R;
+       omap_writel(l, MOD_CONF_CTRL_1);
+
+       l |= CONF_MOD_SOSSI_CLK_EN_R;
+       omap_writel(l, MOD_CONF_CTRL_1);
+
+       omap_writel(omap_readl(ARM_IDLECT2) | (1 << 11), ARM_IDLECT2);
+       omap_writel(omap_readl(ARM_IDLECT1) | (1 << 6), ARM_IDLECT1);
+
+       l = sossi_read_reg(SOSSI_INIT2_REG);
+       /* Enable and reset the SoSSI block */
+       l |= (1 << 0) | (1 << 1);
+       sossi_write_reg(SOSSI_INIT2_REG, l);
+       /* Take SoSSI out of reset */
+       l &= ~(1 << 1);
+       sossi_write_reg(SOSSI_INIT2_REG, l);
+
+       sossi_write_reg(SOSSI_ID_REG, 0);
+       l = sossi_read_reg(SOSSI_ID_REG);
+       k = sossi_read_reg(SOSSI_ID_REG);
+
+       if (l != 0x55555555 || k != 0xaaaaaaaa) {
+               dev_err(fbdev->dev,
+                       "invalid SoSSI sync pattern: %08x, %08x\n", l, k);
+               return -ENODEV;
+       }
+
+       if ((r = omap_lcdc_set_dma_callback(sossi_dma_callback, NULL)) < 0) {
+               dev_err(fbdev->dev, "can't get LCDC IRQ\n");
+               return r;
+       }
+
+       l = sossi_read_reg(SOSSI_ID_REG); /* Component code */
+       l = sossi_read_reg(SOSSI_ID_REG);
+       pr_info("omapfb: SoSSI version %d.%d initialized\n",
+               l >> 16, l & 0xffff);
+
+       l = sossi_read_reg(SOSSI_INIT1_REG);
+       l |= (1 << 19); /* DMA_MODE */
+       l &= ~(1 << 31); /* REORDERING */
+       sossi_write_reg(SOSSI_INIT1_REG, l);
+
+       return 0;
+}
+
+static void sossi_cleanup(void)
+{
+       omap_lcdc_free_dma_callback();
+}
+
+const struct lcd_ctrl_extif omap1_ext_if = {
        .init                   = sossi_init,
        .cleanup                = sossi_cleanup,
        .get_clk_info           = sossi_get_clk_info,
@@ -532,4 +525,7 @@ struct lcd_ctrl_extif sossi_extif = {
        .read_data              = sossi_read_data,
        .write_data             = sossi_write_data,
        .transfer_area          = sossi_transfer_area,
+
+       .max_transmit_size      = SOSSI_MAX_XMIT_BYTES,
 };
+
index 196b5350aecc95a6a20853f8406fc03648214956..de1ded5677b15af48f15e1a3aa61b9ec59b806d4 100644 (file)
@@ -24,6 +24,9 @@
 #ifndef __OMAPFB_H
 #define __OMAPFB_H
 
+#include <asm/ioctl.h>
+#include <asm/types.h>
+
 /* IOCTL commands. */
 
 #define OMAP_IOW(num, dtype)   _IOW('O', num, dtype)
 #define OMAPFB_VSYNC           OMAP_IO(38)
 #define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int)
 #define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(41, struct omapfb_update_window_old)
-#define OMAPFB_GET_CAPS                OMAP_IOR(42, unsigned long)
 #define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int)
 #define OMAPFB_LCD_TEST                OMAP_IOW(45, int)
 #define OMAPFB_CTRL_TEST       OMAP_IOW(46, int)
 #define OMAPFB_UPDATE_WINDOW   OMAP_IOW(47, struct omapfb_update_window)
-#define OMAPFB_SETUP_PLANE     OMAP_IOW(48, struct omapfb_setup_plane)
-#define OMAPFB_ENABLE_PLANE    OMAP_IOW(49, struct omapfb_enable_plane)
 #define OMAPFB_SET_COLOR_KEY   OMAP_IOW(50, struct omapfb_color_key)
+#define OMAPFB_GET_COLOR_KEY   OMAP_IOW(51, struct omapfb_color_key)
+#define OMAPFB_SETUP_PLANE     OMAP_IOW(52, struct omapfb_plane_info)
+#define OMAPFB_QUERY_PLANE     OMAP_IOW(53, struct omapfb_plane_info)
 
 #define OMAPFB_CAPS_GENERIC_MASK       0x00000fff
 #define OMAPFB_CAPS_LCDC_MASK          0x00fff000
@@ -56,6 +59,9 @@
 #define OMAPFB_FORMAT_MASK         0x00ff
 #define OMAPFB_FORMAT_FLAG_DOUBLE  0x0100
 
+#define OMAPFB_EVENT_READY     1
+#define OMAPFB_EVENT_DISABLED  2
+
 enum omapfb_color_format {
        OMAPFB_COLOR_RGB565 = 0,
        OMAPFB_COLOR_YUV422,
@@ -65,6 +71,7 @@ enum omapfb_color_format {
        OMAPFB_COLOR_CLUT_2BPP,
        OMAPFB_COLOR_CLUT_1BPP,
        OMAPFB_COLOR_RGB444,
+       OMAPFB_COLOR_YUY422,
 };
 
 struct omapfb_update_window {
@@ -89,18 +96,16 @@ enum omapfb_channel_out {
        OMAPFB_CHANNEL_OUT_DIGIT,
 };
 
-struct omapfb_setup_plane {
-       __u8  plane;
+struct omapfb_plane_info {
+       __u32 pos_x;
+       __u32 pos_y;
+       __u8  enabled;
        __u8  channel_out;
-       __u32 offset;
-       __u32 pos_x, pos_y;
-       __u32 width, height;
-       __u32 color_mode;
-};
-
-struct omapfb_enable_plane {
-       __u8  plane;
-       __u8  enable;
+       __u8  mirror;
+       __u8  reserved1;
+       __u32 out_width;
+       __u32 out_height;
+       __u32 reserved2[12];
 };
 
 enum omapfb_color_key_type {
@@ -142,6 +147,9 @@ enum omapfb_update_mode {
 
 #define OMAP_LCDC_PANEL_TFT            0x0100
 
+#define OMAPFB_PLANE_XRES_MIN          8
+#define OMAPFB_PLANE_YRES_MIN          8
+
 #ifdef CONFIG_ARCH_OMAP1
 #define OMAPFB_PLANE_NUM               1
 #else
@@ -170,15 +178,17 @@ struct lcd_panel {
        int             pcd;            /* pixel clock divider.
                                           Obsolete use pixel_clock instead */
 
-       int             (*init)         (struct omapfb_device *fbdev);
-       void            (*cleanup)      (void);
-       int             (*enable)       (void);
-       void            (*disable)      (void);
-       unsigned long   (*get_caps)     (void);
-       int             (*set_bklight_level)(unsigned int level);
-       unsigned int    (*get_bklight_level)(void);
-       unsigned int    (*get_bklight_max)  (void);
-       int             (*run_test)     (int test_num);
+       int             (*init)         (struct lcd_panel *panel,
+                                        struct omapfb_device *fbdev);
+       void            (*cleanup)      (struct lcd_panel *panel);
+       int             (*enable)       (struct lcd_panel *panel);
+       void            (*disable)      (struct lcd_panel *panel);
+       unsigned long   (*get_caps)     (struct lcd_panel *panel);
+       int             (*set_bklight_level)(struct lcd_panel *panel,
+                                            unsigned int level);
+       unsigned int    (*get_bklight_level)(struct lcd_panel *panel);
+       unsigned int    (*get_bklight_max)  (struct lcd_panel *panel);
+       int             (*run_test)     (struct lcd_panel *panel, int test_num);
 };
 
 struct omapfb_device;
@@ -203,7 +213,7 @@ struct extif_timings {
 };
 
 struct lcd_ctrl_extif {
-       int  (*init)            (void);
+       int  (*init)            (struct omapfb_device *fbdev);
        void (*cleanup)         (void);
        void (*get_clk_info)    (u32 *clk_period, u32 *max_clk_div);
        int  (*convert_timings) (struct extif_timings *timings);
@@ -214,30 +224,41 @@ struct lcd_ctrl_extif {
        void (*write_data)      (const void *buf, unsigned int len);
        void (*transfer_area)   (int width, int height,
                                 void (callback)(void * data), void *data);
+
        unsigned long           max_transmit_size;
 };
 
 struct omapfb_notifier_block {
        struct notifier_block   nb;
        void                    *data;
+       int                     plane_idx;
 };
 
-typedef int (*omapfb_notifier_callback_t)(struct omapfb_notifier_block *,
-                                          unsigned long event,
-                                          struct omapfb_device *fbdev);
+typedef int (*omapfb_notifier_callback_t)(struct notifier_block *,
+                                         unsigned long event,
+                                         void *fbi);
+
+struct omapfb_mem_region {
+       dma_addr_t      paddr;
+       void            *vaddr;
+       unsigned long   size;
+       int             alloc:1;
+};
+
+struct omapfb_mem_desc {
+       int                             region_cnt;
+       struct omapfb_mem_region        region[OMAPFB_PLANE_NUM];
+};
 
 struct lcd_ctrl {
        const char      *name;
        void            *data;
 
        int             (*init)           (struct omapfb_device *fbdev,
-                                          int ext_mode, int req_vram_size);
+                                          int ext_mode,
+                                          struct omapfb_mem_desc *req_md);
        void            (*cleanup)        (void);
        void            (*bind_client)    (struct omapfb_notifier_block *nb);
-       void            (*get_vram_layout)(unsigned long *size,
-                                          void **virt_base,
-                                          dma_addr_t *phys_base);
-       int             (*mmap)           (struct vm_area_struct *vma);
        unsigned long   (*get_caps)       (void);
        int             (*set_update_mode)(enum omapfb_update_mode mode);
        enum omapfb_update_mode (*get_update_mode)(void);
@@ -246,8 +267,12 @@ struct lcd_ctrl {
                                           int screen_width,
                                           int pos_x, int pos_y, int width,
                                           int height, int color_mode);
+       int             (*set_scale)      (int plane,
+                                          int orig_width, int orig_height,
+                                          int out_width, int out_height);
        int             (*enable_plane)   (int plane, int enable);
-       int             (*update_window)  (struct omapfb_update_window *win,
+       int             (*update_window)  (struct fb_info *fbi,
+                                          struct omapfb_update_window *win,
                                           void (*callback)(void *),
                                           void *callback_data);
        void            (*sync)           (void);
@@ -258,6 +283,7 @@ struct lcd_ctrl {
                                           u16 blue, u16 transp,
                                           int update_hw_mem);
        int             (*set_color_key)  (struct omapfb_color_key *ck);
+       int             (*get_color_key)  (struct omapfb_color_key *ck);
 
 };
 
@@ -267,19 +293,20 @@ enum omapfb_state {
        OMAPFB_ACTIVE   = 100
 };
 
+struct omapfb_plane_struct {
+       int                             idx;
+       struct omapfb_plane_info        info;
+       enum omapfb_color_format        color_mode;
+       struct omapfb_device            *fbdev;
+};
+
 struct omapfb_device {
        int                     state;
        int                     ext_lcdc;               /* Using external
                                                            LCD controller */
        struct mutex            rqueue_mutex;
 
-       void                    *vram_virt_base;
-       dma_addr_t              vram_phys_base;
-       unsigned long           vram_size;
-
-       int                     color_mode;
        int                     palette_size;
-       int                     mirror;
        u32                     pseudo_palette[17];
 
        struct lcd_panel        *panel;                 /* LCD panel */
@@ -287,19 +314,17 @@ struct omapfb_device {
        struct lcd_ctrl         *int_ctrl;              /* internal LCD ctrl */
        struct lcd_ctrl_extif   *ext_if;                /* LCD ctrl external
                                                           interface */
-       struct fb_info          *fb_info;
-
        struct device           *dev;
+
+       struct omapfb_mem_desc          mem_desc;
+       struct fb_info                  *fb_info[OMAPFB_PLANE_NUM];
 };
 
 struct omapfb_platform_data {
-       struct omap_lcd_config   lcd;
-       struct omap_fbmem_config fbmem;
+       struct omap_lcd_config          lcd;
+       struct omapfb_mem_desc          mem_desc;
 };
 
-#define OMAPFB_EVENT_READY     1
-#define OMAPFB_EVENT_DISABLED  2
-
 #ifdef CONFIG_ARCH_OMAP1
 extern struct lcd_ctrl omap1_lcd_ctrl;
 #else
@@ -311,12 +336,13 @@ extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
 extern void omapfb_notify_clients(struct omapfb_device *fbdev,
                                  unsigned long event);
 extern int  omapfb_register_client(struct omapfb_notifier_block *nb,
-                                   omapfb_notifier_callback_t callback,
-                                   void *callback_data);
+                                  omapfb_notifier_callback_t callback,
+                                  void *callback_data);
 extern int  omapfb_unregister_client(struct omapfb_notifier_block *nb);
-extern int  omapfb_update_window_async(struct omapfb_update_window *win,
-                                       void (*callback)(void *),
-                                       void *callback_data);
+extern int  omapfb_update_window_async(struct fb_info *fbi,
+                                      struct omapfb_update_window *win,
+                                      void (*callback)(void *),
+                                      void *callback_data);
 
 /* in arch/arm/plat-omap/devices.c */
 extern void omapfb_reserve_mem(void);