From e563dc81aa01bd8bbb01bc53975a15c398715f62 Mon Sep 17 00:00:00 2001
From: Imre Deak <imre.deak@solidboot.com>
Date: Mon, 26 Jun 2006 15:57:29 +0300
Subject: [PATCH] ARM: OMAP: omapfb: main and LCD controller module changes

- 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         |  20 +-
 drivers/video/omap/Makefile        |   2 +-
 drivers/video/omap/debug.h         |  44 --
 drivers/video/omap/dispc.c         | 626 ++++++++++-----------
 drivers/video/omap/hwa742.c        | 138 ++---
 drivers/video/omap/lcdc.c          | 386 ++++++-------
 drivers/video/omap/omapfb_main.c   | 844 ++++++++++++++++-------------
 drivers/video/omap/rfbi.c          |  51 +-
 drivers/video/omap/sossi.c         | 316 ++++++-----
 include/asm-arm/arch-omap/omapfb.h | 128 +++--
 10 files changed, 1258 insertions(+), 1297 deletions(-)
 delete mode 100644 drivers/video/omap/debug.h

diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
index 6411c95095..17e9420047 100644
--- a/drivers/video/omap/Kconfig
+++ b/drivers/video/omap/Kconfig
@@ -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
diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile
index 725ea29c67..444643ef42 100644
--- a/drivers/video/omap/Makefile
+++ b/drivers/video/omap/Makefile
@@ -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
index a280412aeb..0000000000
--- a/drivers/video/omap/debug.h
+++ /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 */
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
index 3185282887..67201d2fb7 100644
--- a/drivers/video/omap/dispc.c
+++ b/drivers/video/omap/dispc.c
@@ -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>
@@ -34,11 +33,7 @@
 
 #include "dispc.h"
 
-/* #define OMAPFB_DBG	1 */
-
-#include "debug.h"
-
-#define MODULE_NAME			"omapfb-dispc"
+#define MODULE_NAME			"dispc"
 
 #define DISPC_BASE			0x48050400
 
@@ -134,8 +129,6 @@
 
 #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) \
@@ -144,22 +137,11 @@
 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");
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
index f466c4b5b2..0f8e2fbee7 100644
--- a/drivers/video/omap/hwa742.c
+++ b/drivers/video/omap/hwa742.c
@@ -32,11 +32,7 @@
 #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
@@ -80,23 +76,21 @@
 
 #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();
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
index a86cd73fa9..87ae40b82b 100644
--- a/drivers/video/omap/lcdc.c
+++ b/drivers/video/omap/lcdc.c
@@ -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>
@@ -38,11 +37,7 @@
 
 #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");
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index 5a013b6eac..4e73cd49be 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -26,36 +26,19 @@
  * 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);
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
index 82415f50a6..5347e9b9d2 100644
--- a/drivers/video/omap/rfbi.c
+++ b/drivers/video/omap/rfbi.c
@@ -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>
@@ -35,14 +34,6 @@
 
 #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,
 };
 
diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
index 64dd0a46e5..447989f722 100644
--- a/drivers/video/omap/sossi.c
+++ b/drivers/video/omap/sossi.c
@@ -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>
@@ -33,10 +32,6 @@
 
 #include "lcdc.h"
 
-/* #define OMAPFB_DBG 1 */
-
-#include "debug.h"
-
 #define MODULE_NAME		"omapfb-sossi"
 
 #define OMAP_SOSSI_BASE         0xfffbac00
@@ -60,10 +55,8 @@
 
 #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,
 };
+
diff --git a/include/asm-arm/arch-omap/omapfb.h b/include/asm-arm/arch-omap/omapfb.h
index 196b5350ae..de1ded5677 100644
--- a/include/asm-arm/arch-omap/omapfb.h
+++ b/include/asm-arm/arch-omap/omapfb.h
@@ -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)
@@ -36,14 +39,14 @@
 #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);
-- 
2.25.4