linux-fbdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/12] DSS: Series description
@ 2009-01-12 11:47 Tomi Valkeinen
  2009-01-12 11:47 ` [PATCH 01/12] DSS: Documentation for DSS2 Tomi Valkeinen
                   ` (12 more replies)
  0 siblings, 13 replies; 23+ messages in thread
From: Tomi Valkeinen @ 2009-01-12 11:47 UTC (permalink / raw)
  To: linux-fbdev-devel; +Cc: linux-omap

New Display Subsystem for OMAP2/3
---------------------------------

This patch set implements new Display Subsystem (DSS) for OMAP2/3 processors.
The DSS is still under work and these patches are for review.

This is an updated version of the patch set I sent back in november:
http://marc.info/?l=linux-fbdev-devel&m=122581504222406&w=2

The first patch is a doc file that tries to explain a bit how the drivers work.

The patch set is based on the current linux-omap tree.

You can find the patches also from a git tree at
http://www.bat.org/~tomba/git/linux-omap-dss.git/

---

Tomi Valkeinen (12):
      DSS: Hacked N810 support
      DSS: Support for OMAP3 EVM board
      DSS: Support for OMAP3 SDP board
      DSS: Sharp LS037V7DW01 LCD Panel driver
      DSS: support for Beagle Board
      DSS: Add generic DVI panel
      DSS: OMAPFB: fb driver for new display subsystem
      DSS: DSI support
      DSS: VENC support
      DSS: RFBI support
      DSS: Display subsystem for OMAP2/3
      DSS: Documentation for DSS2


 Documentation/arm/OMAP/DSS                    |  270 ++
 arch/arm/configs/dss_omap3_beagle_defconfig   | 1437 +++++++++++
 arch/arm/configs/dss_omap_3430sdp_defconfig   | 1603 +++++++++++++
 arch/arm/mach-omap2/board-3430sdp.c           |  215 ++
 arch/arm/mach-omap2/board-n800.c              |  214 +-
 arch/arm/mach-omap2/board-omap3beagle.c       |  101 +
 arch/arm/mach-omap2/board-omap3evm.c          |  203 ++
 arch/arm/plat-omap/Kconfig                    |    2 
 arch/arm/plat-omap/Makefile                   |    4 
 arch/arm/plat-omap/dss/Kconfig                |   71 +
 arch/arm/plat-omap/dss/Makefile               |    6 
 arch/arm/plat-omap/dss/dispc.c                | 2113 +++++++++++++++++
 arch/arm/plat-omap/dss/display.c              |  787 ++++++
 arch/arm/plat-omap/dss/dpi.c                  |  344 +++
 arch/arm/plat-omap/dss/dsi.c                  | 3187 +++++++++++++++++++++++++
 arch/arm/plat-omap/dss/dss.c                  |  774 ++++++
 arch/arm/plat-omap/dss/dss.h                  |  274 ++
 arch/arm/plat-omap/dss/rfbi.c                 | 1262 ++++++++++
 arch/arm/plat-omap/dss/sdi.c                  |  174 +
 arch/arm/plat-omap/dss/venc.c                 |  506 ++++
 arch/arm/plat-omap/fb-vram.c                  |  646 +++++
 arch/arm/plat-omap/fb.c                       |   22 
 arch/arm/plat-omap/include/mach/display.h     |  462 ++++
 arch/arm/plat-omap/include/mach/omapfb.h      |   14 
 drivers/video/Kconfig                         |    1 
 drivers/video/Makefile                        |    1 
 drivers/video/omap/Kconfig                    |    5 
 drivers/video/omap2/Kconfig                   |   62 
 drivers/video/omap2/Makefile                  |    8 
 drivers/video/omap2/ctrl-blizzard.c           |  279 ++
 drivers/video/omap2/omapfb-ioctl.c            |  460 ++++
 drivers/video/omap2/omapfb-main.c             | 1442 +++++++++++
 drivers/video/omap2/omapfb-sysfs.c            |  901 +++++++
 drivers/video/omap2/omapfb.h                  |  115 +
 drivers/video/omap2/panel-generic.c           |   97 +
 drivers/video/omap2/panel-n800.c              |  437 +++
 drivers/video/omap2/panel-sharp-ls037v7dw01.c |  109 +
 37 files changed, 18537 insertions(+), 71 deletions(-)
 create mode 100644 Documentation/arm/OMAP/DSS
 create mode 100644 arch/arm/configs/dss_omap3_beagle_defconfig
 create mode 100644 arch/arm/configs/dss_omap_3430sdp_defconfig
 create mode 100644 arch/arm/plat-omap/dss/Kconfig
 create mode 100644 arch/arm/plat-omap/dss/Makefile
 create mode 100644 arch/arm/plat-omap/dss/dispc.c
 create mode 100644 arch/arm/plat-omap/dss/display.c
 create mode 100644 arch/arm/plat-omap/dss/dpi.c
 create mode 100644 arch/arm/plat-omap/dss/dsi.c
 create mode 100644 arch/arm/plat-omap/dss/dss.c
 create mode 100644 arch/arm/plat-omap/dss/dss.h
 create mode 100644 arch/arm/plat-omap/dss/rfbi.c
 create mode 100644 arch/arm/plat-omap/dss/sdi.c
 create mode 100644 arch/arm/plat-omap/dss/venc.c
 create mode 100644 arch/arm/plat-omap/fb-vram.c
 create mode 100644 arch/arm/plat-omap/include/mach/display.h
 create mode 100644 drivers/video/omap2/Kconfig
 create mode 100644 drivers/video/omap2/Makefile
 create mode 100644 drivers/video/omap2/ctrl-blizzard.c
 create mode 100644 drivers/video/omap2/omapfb-ioctl.c
 create mode 100644 drivers/video/omap2/omapfb-main.c
 create mode 100644 drivers/video/omap2/omapfb-sysfs.c
 create mode 100644 drivers/video/omap2/omapfb.h
 create mode 100644 drivers/video/omap2/panel-generic.c
 create mode 100644 drivers/video/omap2/panel-n800.c
 create mode 100644 drivers/video/omap2/panel-sharp-ls037v7dw01.c

-- 
 Tomi Valkeinen


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 01/12] DSS: Documentation for DSS2
  2009-01-12 11:47 [PATCH 00/12] DSS: Series description Tomi Valkeinen
@ 2009-01-12 11:47 ` Tomi Valkeinen
  2009-01-12 11:47 ` [PATCH 02/12] DSS: Display subsystem for OMAP2/3 Tomi Valkeinen
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 23+ messages in thread
From: Tomi Valkeinen @ 2009-01-12 11:47 UTC (permalink / raw)
  To: linux-fbdev-devel; +Cc: linux-omap

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
---

 Documentation/arm/OMAP/DSS |  270 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 270 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/arm/OMAP/DSS

diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
new file mode 100644
index 0000000..011fee1
--- /dev/null
+++ b/Documentation/arm/OMAP/DSS
@@ -0,0 +1,270 @@
+OMAP2/3 Display Subsystem
+-------------------------
+
+This is an almost total rewrite of the OMAP FB driver in drivers/video/omap
+(let's call it DSS1). The main differences between DSS1 and DSS2 are DSI,
+TV-out and multiple display support, but there are lots of small improvements
+also.
+
+The DSS2 driver (omap-dss module) is in arch/arm/plat-omap/dss/, and the FB,
+panel and controller drivers are in drivers/video/omap2/. DSS1 and DSS2 live
+currently side by side, you can choose which one to use.
+
+Features
+--------
+
+Working and tested features include:
+
+- MIPI DPI (parallel) output
+- MIPI DSI output in command mode
+- MIPI DBI (RFBI) output
+- SDI output
+- TV output
+- All pieces can be compiled as a module or inside kernel
+- Use DISPC to update any of the outputs
+- Use CPU to update RFBI or DSI output
+- OMAP DISPC planes
+- RGB16, RGB24 packed, RGB24 unpacked
+- YUV2, UYVY
+- Scaling
+- Adjusting DSS FCK to find a good pixel clock
+- Use DSI DPLL to create DSS FCK
+
+Tested boards include:
+- OMAP3 SDP board
+- Beagle board
+- N810
+
+omap-dss driver
+------------
+
+The DSS driver does not itself have any support for Linux framebuffer, V4L or
+such like the current ones, but it has an internal kernel API that upper level
+drivers can use.
+
+The DSS driver models OMAP's overlays, overlay managers and displays in a
+flexible way to enable non-common multi-display configuration. In addition to
+modelling the hardware overlays, omap-dss supports virtual overlays and overlay
+managers. These can be used when updating a display with CPU or system DMA.
+
+Panel and controller drivers
+----------------------------
+
+The drivers implement panel or controller specific functionality and are not
+usually visible to users except through omapfb driver.  They register
+themselves to the DSS driver.
+
+omapfb driver
+-------------
+
+The omapfb driver implements arbitrary number of standard linux framebuffers.
+These framebuffers can be routed flexibly to any overlays, thus allowing very
+dynamic display architecture.
+
+The driver exports some omapfb specific ioctls, which are compatible with the
+ioctls in the old driver.
+
+The rest of the non standard features are exported via sysfs. Whether the final
+implementation will use sysfs, or ioctls, is still open.
+
+V4L2 drivers
+------------
+
+V4L2 is being implemented in TI.
+
+From omap-dss point of view the V4L2 drivers should be similar to framebuffer
+driver.
+
+Architecture
+--------------------
+
+Some clarification what the different components do:
+
+    - Framebuffer is a memory area inside OMAP's SRAM/SDRAM that contains the
+      pixel data for the image. Framebuffer has width and height and color
+      depth.
+    - Overlay defines where the pixels are read from and where they go on the
+      screen. The overlay may be smaller than framebuffer, thus displaying only
+      part of the framebuffer. The position of the overlay may be changed if
+      the overlay is smaller than the display.
+    - Overlay manager combines the overlays in to one image and feeds them to
+      display.
+    - Display is the actual physical display device.
+
+A framebuffer can be connected to multiple overlays to show the same pixel data
+on all of the overlays. Note that in this case the overlay input sizes must be
+the same, but, in case of video overlays, the output size can be different. Any
+framebuffer can be connected to any overlay.
+
+An overlay can be connected to one overlay manager. Also DISPC overlays can be
+connected only to DISPC overlay managers, and virtual overlays can be only
+connected to virtual overlays.
+
+An overlay manager can be connected to one display. There are certain
+restrictions which kinds of displays an overlay manager can be connected:
+
+    - DISPC TV overlay manager can be only connected to TV display.
+    - Virtual overlay managers can only be connected to DBI or DSI displays.
+    - DISPC LCD overlay manager can be connected to all displays, except TV
+      display.
+
+Sysfs
+-----
+The sysfs interface is a hack, but works for testing. I don't think sysfs
+interface is the best for this in the final version, but I don't quite know
+what would be the best interfaces for these things.
+
+In /sys/devices/platform/omapfb we have four files: framebuffers,
+overlays, managers and displays. You can read them so see the current
+setup, and change them by writing to it in the form of
+"<item-id> <opt1>:<val1> <opt2>:<val2>..."
+
+"framebuffers" lists all framebuffers. Its format is:
+	<fb number>
+	p:<physical address, read only>
+	v:<virtual address, read only>
+	s:<size, read only>
+	t:<target overlay>
+
+"overlays" lists all overlays. Its format is:
+	<overlay name>
+	t:<target manager>
+	x:<xpos>
+	y:<ypos>
+	iw:<input width, read only>
+	ih:<input height, read only>
+	w:<output width>
+	h:<output height>
+	e:<enabled>
+
+"managers" lists all overlay managers. Its format is:
+	<manager name>
+	t:<target display>
+
+"displays" lists all displays. Its format is:
+	<display name>
+	e:<enabled>
+	u:<update mode>
+	t:<tear sync on/off>
+	h:<xres/hfp/hbp/hsw>
+	v:<yres/vfp/vbp/vsw>
+	p:<pix clock, in kHz>
+	m:<mode str, as in drivers/video/modedb.c:fb_find_mode>
+
+There is also a debug sysfs file at /sys/devices/platform/omap-dss/clk which
+shows how DSS has configured the clocks.
+
+Examples
+--------
+
+In the example scripts "omapfb" is a symlink to /sys/devices/platform/omapfb/.
+
+Default setup on OMAP3 SDP
+--------------------------
+
+Here's the default setup on OMAP3 SDP board. All planes go to LCD. DVI
+and TV-out are not in use. The columns from left to right are:
+framebuffers, overlays, overlay managers, displays. Framebuffers are
+handled by omapfb, and the rest by the DSS.
+
+FB0 --- GFX  -\            DVI
+FB1 --- VID1 --+- LCD ---- LCD
+FB2 --- VID2 -/   TV ----- TV
+
+Switch from LCD to DVI
+----------------------
+
+dviline=`cat omapfb/displays |grep dvi`
+w=`echo $dviline | cut -d " " -f 5 | cut -d ":" -f 2 | cut -d "/" -f 1`
+h=`echo $dviline | cut -d " " -f 6 | cut -d ":" -f 2 | cut -d "/" -f 1`
+
+echo "lcd e:0" > omapfb/displays
+echo "lcd t:none" > omapfb/managers
+fbset -fb /dev/fb0 -xres $w -yres $h -vxres $w -vyres $h
+# at this point you have to switch the dvi/lcd dip-switch from the omap board
+echo "lcd t:dvi" > omapfb/managers
+echo "dvi e:1" > omapfb/displays
+
+After this the configuration looks like:
+
+FB0 --- GFX  -\         -- DVI
+FB1 --- VID1 --+- LCD -/   LCD
+FB2 --- VID2 -/   TV ----- TV
+
+Clone GFX overlay to LCD and TV
+-------------------------------
+
+tvline=`cat /sys/devices/platform/omapfb/displays |grep tv`
+w=`echo $tvline | cut -d " " -f 5 | cut -d ":" -f 2 | cut -d "/" -f 1`
+h=`echo $tvline | cut -d " " -f 6 | cut -d ":" -f 2 | cut -d "/" -f 1`
+
+echo "1 t:none" > omapfb/framebuffers
+echo "0 t:gfx,vid1" > omapfb/framebuffers
+echo "gfx e:1" > omapfb/overlays
+echo "vid1 t:tv w:$w h:$h e:1" > omapfb/overlays
+echo "tv e:1" > omapfb/displays
+
+After this the configuration looks like (only relevant parts shown):
+
+FB0 +-- GFX  ---- LCD ---- LCD
+     \- VID1 ---- TV  ---- TV
+
+Misc notes
+----------
+
+OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator. If
+that fails, it will fall back to dma_alloc_writecombine().
+
+Using DSI DPLL to generate pixel clock it is possible produce the pixel clock
+of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI.
+
+Arguments
+---------
+
+vram
+	- Amount of total VRAM to preallocate. For example, "10M". omapfb
+	  allocates memory for framebuffers from VRAM.
+
+omapfb.video_mode
+	- Default video mode for default display. For example,
+	  "800x400MR-24@60".  See drivers/video/modedb.c
+
+omapfb.vram
+	- VRAM allocated for each framebuffer. Normally omapfb allocates vram
+	  depending on the display size. With this you can manually allocate
+	  more. For example "4M,3M" allocates 4M for fb0, 3M for fb1.
+
+omapfb.debug
+	- Enable debug printing. You have to have OMAPFB debug support enabled
+	  in kernel config.
+
+omap-dss.def_disp
+	- Name of default display, to which all overlays will be connected.
+	  Common examples are "lcd" or "tv".
+
+omap-dss.debug
+	- Enable debug printing. You have to have DSS debug support enabled in
+	  kernel config.
+
+TODO
+----
+
+DSS locking
+
+Error checking
+- Lots of checks are missing or implemented just as BUG()
+
+Rotate (external FB)
+Rotate (VRFB)
+Rotate (SMS)
+
+System DMA update for DSI
+- Can be used for RGB16 and RGB24P modes. Probably not for RGB24U (how
+  to skip the empty byte?)
+
+Power management
+- Context saving
+
+OMAP1 support
+- Not sure if needed
+


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 02/12] DSS: Display subsystem for OMAP2/3
  2009-01-12 11:47 [PATCH 00/12] DSS: Series description Tomi Valkeinen
  2009-01-12 11:47 ` [PATCH 01/12] DSS: Documentation for DSS2 Tomi Valkeinen
@ 2009-01-12 11:47 ` Tomi Valkeinen
  2009-01-12 13:02   ` [Linux-fbdev-devel] " Tony Lindgren
  2009-01-12 11:47 ` [PATCH 03/12] DSS: RFBI support Tomi Valkeinen
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 23+ messages in thread
From: Tomi Valkeinen @ 2009-01-12 11:47 UTC (permalink / raw)
  To: linux-fbdev-devel; +Cc: linux-omap

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
---

 arch/arm/plat-omap/Kconfig                |    2 
 arch/arm/plat-omap/Makefile               |    2 
 arch/arm/plat-omap/dss/Kconfig            |   71 +
 arch/arm/plat-omap/dss/Makefile           |    6 
 arch/arm/plat-omap/dss/dispc.c            | 2113 +++++++++++++++++++++++++++++
 arch/arm/plat-omap/dss/display.c          |  787 +++++++++++
 arch/arm/plat-omap/dss/dpi.c              |  344 +++++
 arch/arm/plat-omap/dss/dss.c              |  774 +++++++++++
 arch/arm/plat-omap/dss/dss.h              |  274 ++++
 arch/arm/plat-omap/dss/sdi.c              |  174 ++
 arch/arm/plat-omap/include/mach/display.h |  462 ++++++
 11 files changed, 5009 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-omap/dss/Kconfig
 create mode 100644 arch/arm/plat-omap/dss/Makefile
 create mode 100644 arch/arm/plat-omap/dss/dispc.c
 create mode 100644 arch/arm/plat-omap/dss/display.c
 create mode 100644 arch/arm/plat-omap/dss/dpi.c
 create mode 100644 arch/arm/plat-omap/dss/dss.c
 create mode 100644 arch/arm/plat-omap/dss/dss.h
 create mode 100644 arch/arm/plat-omap/dss/sdi.c
 create mode 100644 arch/arm/plat-omap/include/mach/display.h

diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 6c9f092..2ae44e6 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -260,6 +260,8 @@ config OMAP_SERIAL_WAKE
 	  to data on the serial RX line. This allows you to wake the
 	  system from serial console.
 
+source "arch/arm/plat-omap/dss/Kconfig"
+
 endmenu
 
 endif
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 1259846..2740497 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -29,3 +29,5 @@ obj-$(CONFIG_OMAP_MMU_FWK) += mmu.o
 # OMAP mailbox framework
 obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
 
+# OMAP2/3 Display Subsystem
+obj-y += dss/
diff --git a/arch/arm/plat-omap/dss/Kconfig b/arch/arm/plat-omap/dss/Kconfig
new file mode 100644
index 0000000..f0b1f1c
--- /dev/null
+++ b/arch/arm/plat-omap/dss/Kconfig
@@ -0,0 +1,71 @@
+config OMAP2_DSS
+        tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)"
+        depends on ARCH_OMAP2 || ARCH_OMAP3
+        help
+          OMAP2/3 Display Subsystem support.
+
+if OMAP2_DSS
+
+config OMAP2_DSS_DEBUG_SUPPORT
+        bool "Debug support"
+	default y
+	help
+	  This enables debug messages. You need to enable printing
+	  with 'debug' module parameter.
+
+config OMAP2_DSS_RFBI
+	bool "RFBI support"
+        default y
+
+config OMAP2_DSS_VENC
+	bool "VENC support"
+        default y
+
+if ARCH_OMAP3
+
+config OMAP2_DSS_SDI
+	bool "SDI support"
+        default y
+
+config OMAP2_DSS_DSI
+	bool "DSI support"
+        default y
+
+endif
+
+config OMAP2_DSS_USE_DSI_PLL
+	bool "Use DSI PLL for PCLK (EXPERIMENTAL)"
+	default n
+	depends on OMAP2_DSS_DSI
+	help
+	  Use DSI PLL to generate pixel clock.
+	  Currently only for DPI output.
+
+config OMAP2_DSS_FAKE_VSYNC
+	bool "Fake VSYNC irq from manual update displays"
+	default n
+	help
+	  If this is selected, DSI will fake a DISPC VSYNC interrupt
+	  when DSI has sent a frame. This is only needed with DSI or
+	  RFBI displays using manual mode, and you want VSYNC to time,
+	  for example, animation.
+
+config OMAP2_DSS_MIN_FCK_PER_PCK
+	int "Minimum FCK/PCK ratio (for scaling)"
+	range 0 32
+	default 0
+	help
+	  This can be used to adjust the minimum FCK/PCK ratio.
+
+	  With this you can make sure that DISPC FCK is at least
+	  n x PCK. Video plane scaling requires higher FCK than
+	  normally.
+
+	  If this is set to 0, there's no extra constraint on the
+	  DISPC FCK. However, the FCK will at minimum be
+	  2xPCK (if active matrix) or 3xPCK (if passive matrix).
+
+	  Max FCK is 173MHz, so this doesn't work if your PCK
+	  is very high.
+
+endif
diff --git a/arch/arm/plat-omap/dss/Makefile b/arch/arm/plat-omap/dss/Makefile
new file mode 100644
index 0000000..e98c6c1
--- /dev/null
+++ b/arch/arm/plat-omap/dss/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_OMAP2_DSS) += omap-dss.o
+omap-dss-y := dss.o display.o dispc.o dpi.o
+omap-dss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
+omap-dss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
+omap-dss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
+omap-dss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
diff --git a/arch/arm/plat-omap/dss/dispc.c b/arch/arm/plat-omap/dss/dispc.c
new file mode 100644
index 0000000..e695463
--- /dev/null
+++ b/arch/arm/plat-omap/dss/dispc.c
@@ -0,0 +1,2113 @@
+/*
+ * linux/arch/arm/plat-omap/dss/dispc.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "DISPC"
+
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+
+#include <mach/sram.h>
+#include <mach/board.h>
+#include <mach/clock.h>
+
+#include <mach/display.h>
+
+#include "dss.h"
+
+/* DISPC */
+#define DISPC_BASE			0x48050400
+
+#define DISPC_SZ_REGS			SZ_1K
+
+struct dispc_reg { u16 idx; };
+
+#define DISPC_REG(idx)			((const struct dispc_reg) { idx })
+
+/* DISPC common */
+#define DISPC_REVISION			DISPC_REG(0x0000)
+#define DISPC_SYSCONFIG			DISPC_REG(0x0010)
+#define DISPC_SYSSTATUS			DISPC_REG(0x0014)
+#define DISPC_IRQSTATUS			DISPC_REG(0x0018)
+#define DISPC_IRQENABLE			DISPC_REG(0x001C)
+#define DISPC_CONTROL			DISPC_REG(0x0040)
+#define DISPC_CONFIG			DISPC_REG(0x0044)
+#define DISPC_CAPABLE			DISPC_REG(0x0048)
+#define DISPC_DEFAULT_COLOR0		DISPC_REG(0x004C)
+#define DISPC_DEFAULT_COLOR1		DISPC_REG(0x0050)
+#define DISPC_TRANS_COLOR0		DISPC_REG(0x0054)
+#define DISPC_TRANS_COLOR1		DISPC_REG(0x0058)
+#define DISPC_LINE_STATUS		DISPC_REG(0x005C)
+#define DISPC_LINE_NUMBER		DISPC_REG(0x0060)
+#define DISPC_TIMING_H			DISPC_REG(0x0064)
+#define DISPC_TIMING_V			DISPC_REG(0x0068)
+#define DISPC_POL_FREQ			DISPC_REG(0x006C)
+#define DISPC_DIVISOR			DISPC_REG(0x0070)
+#define DISPC_GLOBAL_ALPHA		DISPC_REG(0x0074)
+#define DISPC_SIZE_DIG			DISPC_REG(0x0078)
+#define DISPC_SIZE_LCD			DISPC_REG(0x007C)
+
+/* DISPC GFX plane */
+#define DISPC_GFX_BA0			DISPC_REG(0x0080)
+#define DISPC_GFX_BA1			DISPC_REG(0x0084)
+#define DISPC_GFX_POSITION		DISPC_REG(0x0088)
+#define DISPC_GFX_SIZE			DISPC_REG(0x008C)
+#define DISPC_GFX_ATTRIBUTES		DISPC_REG(0x00A0)
+#define DISPC_GFX_FIFO_THRESHOLD	DISPC_REG(0x00A4)
+#define DISPC_GFX_FIFO_SIZE_STATUS	DISPC_REG(0x00A8)
+#define DISPC_GFX_ROW_INC		DISPC_REG(0x00AC)
+#define DISPC_GFX_PIXEL_INC		DISPC_REG(0x00B0)
+#define DISPC_GFX_WINDOW_SKIP		DISPC_REG(0x00B4)
+#define DISPC_GFX_TABLE_BA		DISPC_REG(0x00B8)
+
+#define DISPC_DATA_CYCLE1		DISPC_REG(0x01D4)
+#define DISPC_DATA_CYCLE2		DISPC_REG(0x01D8)
+#define DISPC_DATA_CYCLE3		DISPC_REG(0x01DC)
+
+#define DISPC_CPR_COEF_R		DISPC_REG(0x0220)
+#define DISPC_CPR_COEF_G		DISPC_REG(0x0224)
+#define DISPC_CPR_COEF_B		DISPC_REG(0x0228)
+
+#define DISPC_GFX_PRELOAD		DISPC_REG(0x022C)
+
+/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */
+#define DISPC_VID_REG(n, idx)		DISPC_REG(0x00BC + (n)*0x90 + idx)
+
+#define DISPC_VID_BA0(n)		DISPC_VID_REG(n, 0x0000)
+#define DISPC_VID_BA1(n)		DISPC_VID_REG(n, 0x0004)
+#define DISPC_VID_POSITION(n)		DISPC_VID_REG(n, 0x0008)
+#define DISPC_VID_SIZE(n)		DISPC_VID_REG(n, 0x000C)
+#define DISPC_VID_ATTRIBUTES(n)		DISPC_VID_REG(n, 0x0010)
+#define DISPC_VID_FIFO_THRESHOLD(n)	DISPC_VID_REG(n, 0x0014)
+#define DISPC_VID_FIFO_SIZE_STATUS(n)	DISPC_VID_REG(n, 0x0018)
+#define DISPC_VID_ROW_INC(n)		DISPC_VID_REG(n, 0x001C)
+#define DISPC_VID_PIXEL_INC(n)		DISPC_VID_REG(n, 0x0020)
+#define DISPC_VID_FIR(n)		DISPC_VID_REG(n, 0x0024)
+#define DISPC_VID_PICTURE_SIZE(n)	DISPC_VID_REG(n, 0x0028)
+#define DISPC_VID_ACCU0(n)		DISPC_VID_REG(n, 0x002C)
+#define DISPC_VID_ACCU1(n)		DISPC_VID_REG(n, 0x0030)
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+#define DISPC_VID_FIR_COEF_H(n, i)	DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8)
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+#define DISPC_VID_FIR_COEF_HV(n, i)	DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8)
+/* coef index i = {0, 1, 2, 3, 4} */
+#define DISPC_VID_CONV_COEF(n, i)	DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4)
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+#define DISPC_VID_FIR_COEF_V(n, i)	DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4)
+
+#define DISPC_VID_PRELOAD(n)		DISPC_REG(0x230 + (n)*0x04)
+
+
+#define DISPC_IRQ_MASK_ERROR            (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
+					 DISPC_IRQ_OCP_ERR | \
+					 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
+					 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
+					 DISPC_IRQ_SYNC_LOST | \
+					 DISPC_IRQ_SYNC_LOST_DIGIT)
+
+#define DISPC_MAX_NR_ISRS		8
+
+static struct {
+	omap_dispc_isr_t	isr;
+	void			*arg;
+	u32			mask;
+} registered_isr[DISPC_MAX_NR_ISRS];
+
+#define REG_GET(idx, start, end) \
+	FLD_GET(dispc_read_reg(idx), start, end)
+
+#define REG_FLD_MOD(idx, val, start, end)				\
+	dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
+
+static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES,
+	DISPC_VID_ATTRIBUTES(0),
+	DISPC_VID_ATTRIBUTES(1) };
+
+static struct {
+	void __iomem    *base;
+
+	struct clk	*dpll4_m4_ck;
+
+	spinlock_t	irq_lock;
+
+	unsigned long	cache_req_pck;
+	unsigned long	cache_prate;
+	struct dispc_clock_info cache_cinfo;
+
+	u32		ctx[DISPC_SZ_REGS / sizeof(u32)];
+} dispc;
+
+static inline void dispc_write_reg(const struct dispc_reg idx, u32 val)
+{
+	__raw_writel(val, dispc.base + idx.idx);
+}
+
+static inline u32 dispc_read_reg(const struct dispc_reg idx)
+{
+	return __raw_readl(dispc.base + idx.idx);
+}
+
+#define SR(reg) \
+	dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
+#define RR(reg) \
+	dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)])
+
+void dispc_save_context(void)
+{
+	if (cpu_is_omap24xx())
+		return;
+
+	SR(SYSCONFIG);
+	SR(IRQENABLE);
+	SR(CONTROL);
+	SR(CONFIG);
+	SR(DEFAULT_COLOR0);
+	SR(DEFAULT_COLOR1);
+	SR(TRANS_COLOR0);
+	SR(TRANS_COLOR1);
+	SR(LINE_NUMBER);
+	SR(TIMING_H);
+	SR(TIMING_V);
+	SR(POL_FREQ);
+	SR(DIVISOR);
+	SR(GLOBAL_ALPHA);
+	SR(SIZE_DIG);
+	SR(SIZE_LCD);
+
+	SR(GFX_BA0);
+	SR(GFX_BA1);
+	SR(GFX_POSITION);
+	SR(GFX_SIZE);
+	SR(GFX_ATTRIBUTES);
+	SR(GFX_FIFO_THRESHOLD);
+	SR(GFX_ROW_INC);
+	SR(GFX_PIXEL_INC);
+	SR(GFX_WINDOW_SKIP);
+	SR(GFX_TABLE_BA);
+
+	SR(DATA_CYCLE1);
+	SR(DATA_CYCLE2);
+	SR(DATA_CYCLE3);
+
+	SR(CPR_COEF_R);
+	SR(CPR_COEF_G);
+	SR(CPR_COEF_B);
+
+	SR(GFX_PRELOAD);
+
+	/* VID1 */
+	SR(VID_BA0(0));
+	SR(VID_BA1(0));
+	SR(VID_POSITION(0));
+	SR(VID_SIZE(0));
+	SR(VID_ATTRIBUTES(0));
+	SR(VID_FIFO_THRESHOLD(0));
+	SR(VID_ROW_INC(0));
+	SR(VID_PIXEL_INC(0));
+	SR(VID_FIR(0));
+	SR(VID_PICTURE_SIZE(0));
+	SR(VID_ACCU0(0));
+	SR(VID_ACCU1(0));
+
+	SR(VID_FIR_COEF_H(0, 0));
+	SR(VID_FIR_COEF_H(0, 1));
+	SR(VID_FIR_COEF_H(0, 2));
+	SR(VID_FIR_COEF_H(0, 3));
+	SR(VID_FIR_COEF_H(0, 4));
+	SR(VID_FIR_COEF_H(0, 5));
+	SR(VID_FIR_COEF_H(0, 6));
+	SR(VID_FIR_COEF_H(0, 7));
+
+	SR(VID_FIR_COEF_HV(0, 0));
+	SR(VID_FIR_COEF_HV(0, 1));
+	SR(VID_FIR_COEF_HV(0, 2));
+	SR(VID_FIR_COEF_HV(0, 3));
+	SR(VID_FIR_COEF_HV(0, 4));
+	SR(VID_FIR_COEF_HV(0, 5));
+	SR(VID_FIR_COEF_HV(0, 6));
+	SR(VID_FIR_COEF_HV(0, 7));
+
+	SR(VID_CONV_COEF(0, 0));
+	SR(VID_CONV_COEF(0, 1));
+	SR(VID_CONV_COEF(0, 2));
+	SR(VID_CONV_COEF(0, 3));
+	SR(VID_CONV_COEF(0, 4));
+
+	SR(VID_FIR_COEF_V(0, 0));
+	SR(VID_FIR_COEF_V(0, 1));
+	SR(VID_FIR_COEF_V(0, 2));
+	SR(VID_FIR_COEF_V(0, 3));
+	SR(VID_FIR_COEF_V(0, 4));
+	SR(VID_FIR_COEF_V(0, 5));
+	SR(VID_FIR_COEF_V(0, 6));
+	SR(VID_FIR_COEF_V(0, 7));
+
+	SR(VID_PRELOAD(0));
+
+	/* VID2 */
+	SR(VID_BA0(1));
+	SR(VID_BA1(1));
+	SR(VID_POSITION(1));
+	SR(VID_SIZE(1));
+	SR(VID_ATTRIBUTES(1));
+	SR(VID_FIFO_THRESHOLD(1));
+	SR(VID_ROW_INC(1));
+	SR(VID_PIXEL_INC(1));
+	SR(VID_FIR(1));
+	SR(VID_PICTURE_SIZE(1));
+	SR(VID_ACCU0(1));
+	SR(VID_ACCU1(1));
+
+	SR(VID_FIR_COEF_H(1, 0));
+	SR(VID_FIR_COEF_H(1, 1));
+	SR(VID_FIR_COEF_H(1, 2));
+	SR(VID_FIR_COEF_H(1, 3));
+	SR(VID_FIR_COEF_H(1, 4));
+	SR(VID_FIR_COEF_H(1, 5));
+	SR(VID_FIR_COEF_H(1, 6));
+	SR(VID_FIR_COEF_H(1, 7));
+
+	SR(VID_FIR_COEF_HV(1, 0));
+	SR(VID_FIR_COEF_HV(1, 1));
+	SR(VID_FIR_COEF_HV(1, 2));
+	SR(VID_FIR_COEF_HV(1, 3));
+	SR(VID_FIR_COEF_HV(1, 4));
+	SR(VID_FIR_COEF_HV(1, 5));
+	SR(VID_FIR_COEF_HV(1, 6));
+	SR(VID_FIR_COEF_HV(1, 7));
+
+	SR(VID_CONV_COEF(1, 0));
+	SR(VID_CONV_COEF(1, 1));
+	SR(VID_CONV_COEF(1, 2));
+	SR(VID_CONV_COEF(1, 3));
+	SR(VID_CONV_COEF(1, 4));
+
+	SR(VID_FIR_COEF_V(1, 0));
+	SR(VID_FIR_COEF_V(1, 1));
+	SR(VID_FIR_COEF_V(1, 2));
+	SR(VID_FIR_COEF_V(1, 3));
+	SR(VID_FIR_COEF_V(1, 4));
+	SR(VID_FIR_COEF_V(1, 5));
+	SR(VID_FIR_COEF_V(1, 6));
+	SR(VID_FIR_COEF_V(1, 7));
+
+	SR(VID_PRELOAD(1));
+}
+
+void dispc_restore_context(void)
+{
+	RR(SYSCONFIG);
+	RR(IRQENABLE);
+	/*RR(CONTROL);*/
+	RR(CONFIG);
+	RR(DEFAULT_COLOR0);
+	RR(DEFAULT_COLOR1);
+	RR(TRANS_COLOR0);
+	RR(TRANS_COLOR1);
+	RR(LINE_NUMBER);
+	RR(TIMING_H);
+	RR(TIMING_V);
+	RR(POL_FREQ);
+	RR(DIVISOR);
+	RR(GLOBAL_ALPHA);
+	RR(SIZE_DIG);
+	RR(SIZE_LCD);
+
+	RR(GFX_BA0);
+	RR(GFX_BA1);
+	RR(GFX_POSITION);
+	RR(GFX_SIZE);
+	RR(GFX_ATTRIBUTES);
+	RR(GFX_FIFO_THRESHOLD);
+	RR(GFX_ROW_INC);
+	RR(GFX_PIXEL_INC);
+	RR(GFX_WINDOW_SKIP);
+	RR(GFX_TABLE_BA);
+
+	RR(DATA_CYCLE1);
+	RR(DATA_CYCLE2);
+	RR(DATA_CYCLE3);
+
+	RR(CPR_COEF_R);
+	RR(CPR_COEF_G);
+	RR(CPR_COEF_B);
+
+	RR(GFX_PRELOAD);
+
+	/* VID1 */
+	RR(VID_BA0(0));
+	RR(VID_BA1(0));
+	RR(VID_POSITION(0));
+	RR(VID_SIZE(0));
+	RR(VID_ATTRIBUTES(0));
+	RR(VID_FIFO_THRESHOLD(0));
+	RR(VID_ROW_INC(0));
+	RR(VID_PIXEL_INC(0));
+	RR(VID_FIR(0));
+	RR(VID_PICTURE_SIZE(0));
+	RR(VID_ACCU0(0));
+	RR(VID_ACCU1(0));
+
+	RR(VID_FIR_COEF_H(0, 0));
+	RR(VID_FIR_COEF_H(0, 1));
+	RR(VID_FIR_COEF_H(0, 2));
+	RR(VID_FIR_COEF_H(0, 3));
+	RR(VID_FIR_COEF_H(0, 4));
+	RR(VID_FIR_COEF_H(0, 5));
+	RR(VID_FIR_COEF_H(0, 6));
+	RR(VID_FIR_COEF_H(0, 7));
+
+	RR(VID_FIR_COEF_HV(0, 0));
+	RR(VID_FIR_COEF_HV(0, 1));
+	RR(VID_FIR_COEF_HV(0, 2));
+	RR(VID_FIR_COEF_HV(0, 3));
+	RR(VID_FIR_COEF_HV(0, 4));
+	RR(VID_FIR_COEF_HV(0, 5));
+	RR(VID_FIR_COEF_HV(0, 6));
+	RR(VID_FIR_COEF_HV(0, 7));
+
+	RR(VID_CONV_COEF(0, 0));
+	RR(VID_CONV_COEF(0, 1));
+	RR(VID_CONV_COEF(0, 2));
+	RR(VID_CONV_COEF(0, 3));
+	RR(VID_CONV_COEF(0, 4));
+
+	RR(VID_FIR_COEF_V(0, 0));
+	RR(VID_FIR_COEF_V(0, 1));
+	RR(VID_FIR_COEF_V(0, 2));
+	RR(VID_FIR_COEF_V(0, 3));
+	RR(VID_FIR_COEF_V(0, 4));
+	RR(VID_FIR_COEF_V(0, 5));
+	RR(VID_FIR_COEF_V(0, 6));
+	RR(VID_FIR_COEF_V(0, 7));
+
+	RR(VID_PRELOAD(0));
+
+	/* VID2 */
+	RR(VID_BA0(1));
+	RR(VID_BA1(1));
+	RR(VID_POSITION(1));
+	RR(VID_SIZE(1));
+	RR(VID_ATTRIBUTES(1));
+	RR(VID_FIFO_THRESHOLD(1));
+	RR(VID_ROW_INC(1));
+	RR(VID_PIXEL_INC(1));
+	RR(VID_FIR(1));
+	RR(VID_PICTURE_SIZE(1));
+	RR(VID_ACCU0(1));
+	RR(VID_ACCU1(1));
+
+	RR(VID_FIR_COEF_H(1, 0));
+	RR(VID_FIR_COEF_H(1, 1));
+	RR(VID_FIR_COEF_H(1, 2));
+	RR(VID_FIR_COEF_H(1, 3));
+	RR(VID_FIR_COEF_H(1, 4));
+	RR(VID_FIR_COEF_H(1, 5));
+	RR(VID_FIR_COEF_H(1, 6));
+	RR(VID_FIR_COEF_H(1, 7));
+
+	RR(VID_FIR_COEF_HV(1, 0));
+	RR(VID_FIR_COEF_HV(1, 1));
+	RR(VID_FIR_COEF_HV(1, 2));
+	RR(VID_FIR_COEF_HV(1, 3));
+	RR(VID_FIR_COEF_HV(1, 4));
+	RR(VID_FIR_COEF_HV(1, 5));
+	RR(VID_FIR_COEF_HV(1, 6));
+	RR(VID_FIR_COEF_HV(1, 7));
+
+	RR(VID_CONV_COEF(1, 0));
+	RR(VID_CONV_COEF(1, 1));
+	RR(VID_CONV_COEF(1, 2));
+	RR(VID_CONV_COEF(1, 3));
+	RR(VID_CONV_COEF(1, 4));
+
+	RR(VID_FIR_COEF_V(1, 0));
+	RR(VID_FIR_COEF_V(1, 1));
+	RR(VID_FIR_COEF_V(1, 2));
+	RR(VID_FIR_COEF_V(1, 3));
+	RR(VID_FIR_COEF_V(1, 4));
+	RR(VID_FIR_COEF_V(1, 5));
+	RR(VID_FIR_COEF_V(1, 6));
+	RR(VID_FIR_COEF_V(1, 7));
+
+	RR(VID_PRELOAD(1));
+
+	/* enable last, because LCD & DIGIT enable are here */
+	RR(CONTROL);
+}
+
+#undef SR
+#undef RR
+
+static inline void enable_clocks(int enable)
+{
+	if (enable)
+		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+	else
+		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+}
+
+void dispc_go(enum omap_channel channel)
+{
+	int bit;
+	unsigned long tmo;
+
+	enable_clocks(1);
+
+	if (channel == OMAP_DSS_CHANNEL_LCD)
+		bit = 0; /* LCDENABLE */
+	else
+		bit = 1; /* DIGITALENABLE */
+
+	/* if the channel is not enabled, we don't need GO */
+	if (REG_GET(DISPC_CONTROL, bit, bit) == 0)
+		goto end;
+
+	if (channel == OMAP_DSS_CHANNEL_LCD)
+		bit = 5; /* GOLCD */
+	else
+		bit = 6; /* GODIGIT */
+
+	tmo = jiffies + msecs_to_jiffies(200);
+	while (REG_GET(DISPC_CONTROL, bit, bit) == 1) {
+		if (time_after(jiffies, tmo)) {
+			DSSERR("timeout waiting GO flag\n");
+			goto end;
+		}
+		cpu_relax();
+	}
+
+	DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT");
+
+	REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
+end:
+	enable_clocks(0);
+}
+
+static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
+{
+	BUG_ON(plane == OMAP_DSS_GFX);
+
+	dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value);
+}
+
+static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
+{
+	BUG_ON(plane == OMAP_DSS_GFX);
+
+	dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value);
+}
+
+
+static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
+		int vscaleup)
+{
+	/* Coefficients for horizontal up-sampling */
+	const u32 coef_hup[8] = {
+		0x00800000,
+		0x0D7CF800,
+		0x1E70F5FF,
+		0x335FF5FE,
+		0xF74949F7,
+		0xF55F33FB,
+		0xF5701EFE,
+		0xF87C0DFF,
+	};
+
+	/* Coefficients for horizontal down-sampling */
+	const u32 coef_hdown[8] = {
+		0x24382400,
+		0x28371FFE,
+		0x2C361BFB,
+		0x303516F9,
+		0x11343311,
+		0x1635300C,
+		0x1B362C08,
+		0x1F372804,
+	};
+
+	/* Coefficients for horizontal and vertical up-sampling */
+	const u32 coef_hvup[8] = {
+		0x00800000,
+		0x037B02FF,
+		0x0C6F05FE,
+		0x205907FB,
+		0x00404000,
+		0x075920FE,
+		0x056F0CFF,
+		0x027B0300,
+	};
+
+	/* Coefficients for horizontal and vertical down-sampling */
+	const u32 coef_hvdown[8] = {
+		0x24382400,
+		0x28391F04,
+		0x2D381B08,
+		0x3237170C,
+		0x123737F7,
+		0x173732F9,
+		0x1B382DFB,
+		0x1F3928FE,
+	};
+
+	const u32 *h_coef;
+	const u32 *hv_coef;
+	const u32 *hv_coef_mod;
+	int i;
+
+	if (hscaleup)
+		h_coef = coef_hup;
+	else
+		h_coef = coef_hdown;
+
+	if (vscaleup) {
+		hv_coef = coef_hvup;
+
+		if (hscaleup)
+			hv_coef_mod = NULL;
+		else
+			hv_coef_mod = coef_hvdown;
+	} else {
+		hv_coef = coef_hvdown;
+
+		if (hscaleup)
+			hv_coef_mod = coef_hvup;
+		else
+			hv_coef_mod = NULL;
+	}
+
+	for (i = 0; i < 8; i++) {
+		u32 h, hv;
+
+		h = h_coef[i];
+
+		hv = hv_coef[i];
+
+		if (hv_coef_mod) {
+			hv &= 0xffffff00;
+			hv |= (hv_coef_mod[i] & 0xff);
+		}
+
+		_dispc_write_firh_reg(plane, i, h);
+		_dispc_write_firhv_reg(plane, i, hv);
+	}
+}
+
+static void _dispc_setup_color_conv_coef(void)
+{
+	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,
+	};
+
+	const struct color_conv_coef *ct;
+
+#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
+
+	ct = &ctbl_bt601_5;
+
+	dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry));
+	dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy,	 ct->rcb));
+	dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr));
+	dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by));
+	dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0,       ct->bcb));
+
+	dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry));
+	dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy,	 ct->rcb));
+	dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr));
+	dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by));
+	dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0,       ct->bcb));
+
+#undef CVAL
+
+	REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11);
+	REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11);
+}
+
+
+static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr)
+{
+	const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0,
+		DISPC_VID_BA0(0),
+		DISPC_VID_BA0(1) };
+
+	dispc_write_reg(ba0_reg[plane], paddr);
+}
+
+static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr)
+{
+	const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1,
+				      DISPC_VID_BA1(0),
+				      DISPC_VID_BA1(1) };
+
+	dispc_write_reg(ba1_reg[plane], paddr);
+}
+
+static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y)
+{
+	const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION,
+				      DISPC_VID_POSITION(0),
+				      DISPC_VID_POSITION(1) };
+
+	u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
+	dispc_write_reg(pos_reg[plane], val);
+}
+
+static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
+{
+	const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE,
+				      DISPC_VID_PICTURE_SIZE(0),
+				      DISPC_VID_PICTURE_SIZE(1) };
+	u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+	dispc_write_reg(siz_reg[plane], val);
+}
+
+static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
+{
+	u32 val;
+	const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0),
+				      DISPC_VID_SIZE(1) };
+
+	BUG_ON(plane == OMAP_DSS_GFX);
+
+	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+	dispc_write_reg(vsi_reg[plane-1], val);
+}
+
+static void _dispc_set_row_inc(enum omap_plane plane, int inc)
+{
+	const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC,
+				     DISPC_VID_ROW_INC(0),
+				     DISPC_VID_ROW_INC(1) };
+
+	dispc_write_reg(ri_reg[plane], inc);
+}
+
+static void _dispc_set_color_mode(enum omap_plane plane,
+		enum omap_color_mode color_mode)
+{
+	u32 m = 0;
+
+	switch (color_mode) {
+	case OMAP_DSS_COLOR_CLUT1:
+		m = 0x0; break;
+	case OMAP_DSS_COLOR_CLUT2:
+		m = 0x1; break;
+	case OMAP_DSS_COLOR_CLUT4:
+		m = 0x2; break;
+	case OMAP_DSS_COLOR_CLUT8:
+		m = 0x3; break;
+	case OMAP_DSS_COLOR_RGB12U:
+		m = 0x4; break;
+	case OMAP_DSS_COLOR_ARGB16:
+		m = 0x5; break;
+	case OMAP_DSS_COLOR_RGB16:
+		m = 0x6; break;
+	case OMAP_DSS_COLOR_RGB24U:
+		m = 0x8; break;
+	case OMAP_DSS_COLOR_RGB24P:
+		m = 0x9; break;
+	case OMAP_DSS_COLOR_YUV2:
+		m = 0xa; break;
+	case OMAP_DSS_COLOR_UYVY:
+		m = 0xb; break;
+	case OMAP_DSS_COLOR_ARGB32:
+		m = 0xc; break;
+	case OMAP_DSS_COLOR_RGBA32:
+		m = 0xd; break;
+	case OMAP_DSS_COLOR_RGBX32:
+		m = 0xe; break;
+	default:
+		BUG(); break;
+	}
+
+	REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1);
+}
+
+static void _dispc_set_channel_out(enum omap_plane plane,
+		enum omap_channel channel)
+{
+	int shift;
+	u32 val;
+
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		shift = 8;
+		break;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+		shift = 16;
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	val = dispc_read_reg(dispc_reg_att[plane]);
+	val = FLD_MOD(val, channel, shift, shift);
+	dispc_write_reg(dispc_reg_att[plane], val);
+}
+
+void dispc_set_burst_size(enum omap_plane plane,
+		enum omap_burst_size burst_size)
+{
+	int shift;
+	u32 val;
+
+	enable_clocks(1);
+
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		shift = 6;
+		break;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+		shift = 14;
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	val = dispc_read_reg(dispc_reg_att[plane]);
+	val = FLD_MOD(val, burst_size, shift+1, shift);
+	dispc_write_reg(dispc_reg_att[plane], val);
+
+	enable_clocks(0);
+}
+
+static void _dispc_set_vid_color_conv(enum omap_plane plane, int enable)
+{
+	u32 val;
+
+	BUG_ON(plane == OMAP_DSS_GFX);
+
+	val = dispc_read_reg(dispc_reg_att[plane]);
+	val = FLD_MOD(val, enable, 9, 9);
+	dispc_write_reg(dispc_reg_att[plane], val);
+}
+
+void dispc_set_lcd_size(int width, int height)
+{
+	u32 val;
+	BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
+	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+	enable_clocks(1);
+	dispc_write_reg(DISPC_SIZE_LCD, val);
+	enable_clocks(0);
+}
+
+void dispc_set_digit_size(int width, int height)
+{
+	u32 val;
+	BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
+	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+	enable_clocks(1);
+	dispc_write_reg(DISPC_SIZE_DIG, val);
+	enable_clocks(0);
+}
+
+u32 dispc_get_plane_fifo_size(enum omap_plane plane)
+{
+	const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
+				      DISPC_VID_FIFO_SIZE_STATUS(0),
+				      DISPC_VID_FIFO_SIZE_STATUS(1) };
+	u32 size;
+
+	enable_clocks(1);
+
+	if (cpu_is_omap24xx())
+		size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0);
+	else if (cpu_is_omap34xx())
+		size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0);
+	else
+		BUG();
+
+	enable_clocks(0);
+
+	return size;
+}
+
+void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
+{
+	const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
+				       DISPC_VID_FIFO_THRESHOLD(0),
+				       DISPC_VID_FIFO_THRESHOLD(1) };
+	const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
+				      DISPC_VID_FIFO_SIZE_STATUS(0),
+				      DISPC_VID_FIFO_SIZE_STATUS(1) };
+	u32 size;
+
+	enable_clocks(1);
+
+	if (cpu_is_omap24xx())
+		size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0);
+	else if (cpu_is_omap34xx())
+		size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0);
+	else
+		BUG();
+
+	BUG_ON(low > size || high > size);
+
+	DSSDBG("fifo(%d) size %d, low/high old %u/%u, new %u/%u\n",
+			plane, size,
+			REG_GET(ftrs_reg[plane], 11, 0),
+			REG_GET(ftrs_reg[plane], 27, 16),
+			low, high);
+
+	if (cpu_is_omap24xx())
+		dispc_write_reg(ftrs_reg[plane],
+				FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0));
+	else
+		dispc_write_reg(ftrs_reg[plane],
+				FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0));
+
+	enable_clocks(0);
+}
+
+static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc)
+{
+	u32 val;
+	const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0),
+				      DISPC_VID_FIR(1) };
+
+	BUG_ON(plane == OMAP_DSS_GFX);
+
+	val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0);
+	dispc_write_reg(fir_reg[plane-1], val);
+}
+
+static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
+{
+	u32 val;
+	const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0),
+				      DISPC_VID_ACCU0(1) };
+
+	BUG_ON(plane == OMAP_DSS_GFX);
+
+	val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
+	dispc_write_reg(ac0_reg[plane-1], val);
+}
+
+static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
+{
+	u32 val;
+	const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0),
+				      DISPC_VID_ACCU1(1) };
+
+	BUG_ON(plane == OMAP_DSS_GFX);
+
+	val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
+	dispc_write_reg(ac1_reg[plane-1], val);
+}
+
+
+static void _dispc_set_scaling(enum omap_plane plane,
+			       int orig_width, int orig_height,
+			       int out_width, int out_height,
+			       int ilace)
+{
+	int fir_hinc;
+	int fir_vinc;
+	int hscaleup, vscaleup;
+	int fieldmode = 0;
+	int accu0 = 0;
+	int accu1 = 0;
+	u32 l;
+
+	BUG_ON(plane == OMAP_DSS_GFX);
+
+	hscaleup = orig_width <= out_width;
+	vscaleup = orig_height <= out_height;
+
+	_dispc_set_scale_coef(plane, hscaleup, vscaleup);
+
+	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_set_fir(plane, fir_hinc, fir_vinc);
+
+	l = dispc_read_reg(dispc_reg_att[plane]);
+	l &= ~(0x0f << 5);
+
+	l |= fir_hinc ? (1 << 5) : 0;
+	l |= fir_vinc ? (1 << 6) : 0;
+
+	l |= hscaleup ? 0 : (1 << 7);
+	l |= vscaleup ? 0 : (1 << 8);
+
+	dispc_write_reg(dispc_reg_att[plane], l);
+
+	if (ilace) {
+		if (fieldmode) {
+			accu0 = fir_vinc / 2;
+			accu1 = 0;
+		} else {
+			accu0 = 0;
+			accu1 = fir_vinc / 2;
+			if (accu1 >= 1024/2) {
+				accu0 = 1024/2;
+				accu1 -= accu0;
+			}
+		}
+	}
+
+	_dispc_set_vid_accu0(plane, 0, accu0);
+	_dispc_set_vid_accu1(plane, 0, accu1);
+}
+
+static int _dispc_setup_plane(enum omap_plane plane,
+		enum omap_channel channel_out,
+		u32 paddr, int screen_width,
+		int pos_x, int pos_y,
+		int width, int height,
+		int out_width, int out_height,
+		enum omap_color_mode color_mode,
+		int ilace)
+{
+	int fieldmode = 0;
+	int bpp;
+	int cconv;
+	int scaling = 0;
+
+	if (plane == OMAP_DSS_GFX) {
+		if (width != out_width || height != out_height)
+			return -EINVAL;
+	} else {
+		/* video plane */
+		if (width != out_width || height != out_height)
+			scaling = 1;
+
+		if (out_width < width/2 ||
+		   out_width > width*8)
+			return -EINVAL;
+
+		if (out_height < height/2 ||
+		   out_height > height*8)
+			return -EINVAL;
+	}
+
+
+	switch (color_mode) {
+	case OMAP_DSS_COLOR_RGB16:
+		bpp = 16;
+		cconv = 0;
+		break;
+
+	case OMAP_DSS_COLOR_RGB24P:
+		bpp = 24;
+		cconv = 0;
+		break;
+
+	case OMAP_DSS_COLOR_RGB24U:
+		bpp = 32;
+		cconv = 0;
+		break;
+
+	case OMAP_DSS_COLOR_YUV2:
+	case OMAP_DSS_COLOR_UYVY:
+		BUG_ON(plane == OMAP_DSS_GFX);
+		bpp = 16;
+		cconv = 1;
+		break;
+
+	default:
+		BUG();
+		return 1;
+	}
+
+	if (ilace) {
+		if (height == out_height || height > out_height)
+			fieldmode = 1;
+	}
+
+	if (fieldmode)
+		height /= 2;
+
+	if (ilace)
+		out_height /= 2;
+
+	if (plane != OMAP_DSS_GFX)
+		_dispc_set_scaling(plane, width, height,
+				   out_width, out_height,
+				   ilace);
+
+	/* attributes */
+	_dispc_set_channel_out(plane, channel_out);
+	_dispc_set_color_mode(plane, color_mode);
+	if (plane != OMAP_DSS_GFX)
+		_dispc_set_vid_color_conv(plane, cconv);
+
+	/* */
+
+	_dispc_set_plane_ba0(plane, paddr);
+
+	if (fieldmode)
+		_dispc_set_plane_ba1(plane, paddr + screen_width * bpp/8);
+	else
+		_dispc_set_plane_ba1(plane, paddr);
+
+
+	_dispc_set_plane_pos(plane, pos_x, pos_y);
+
+	_dispc_set_pic_size(plane, width, height);
+
+	if (plane != OMAP_DSS_GFX)
+		_dispc_set_vid_size(plane, out_width, out_height);
+
+	_dispc_set_row_inc(plane,
+			   (screen_width - width) * bpp / 8 +
+			   (fieldmode ? screen_width * bpp / 8 : 0) +
+			   1);
+
+	return 0;
+}
+
+static void _dispc_enable_plane(enum omap_plane plane, int enable)
+{
+	REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0);
+}
+
+
+void dispc_enable_lcd_out(int enable)
+{
+	enable_clocks(1);
+	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
+	enable_clocks(0);
+}
+
+void dispc_enable_digit_out(int enable)
+{
+	enable_clocks(1);
+	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
+	enable_clocks(0);
+}
+
+void dispc_lcd_enable_signal_polarity(int act_high)
+{
+	enable_clocks(1);
+	REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
+	enable_clocks(0);
+}
+
+void dispc_lcd_enable_signal(int enable)
+{
+	enable_clocks(1);
+	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
+	enable_clocks(0);
+}
+
+void dispc_pck_free_enable(int enable)
+{
+	enable_clocks(1);
+	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
+	enable_clocks(0);
+}
+
+void dispc_enable_fifohandcheck(int enable)
+{
+	enable_clocks(1);
+	REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
+	enable_clocks(0);
+}
+
+
+void dispc_set_lcd_display_type(enum omap_lcd_display_type type)
+{
+	int mode;
+
+	switch (type) {
+	case OMAP_DSS_LCD_DISPLAY_STN:
+		mode = 0;
+		break;
+
+	case OMAP_DSS_LCD_DISPLAY_TFT:
+		mode = 1;
+		break;
+
+	default:
+		BUG();
+		return;
+	}
+
+	enable_clocks(1);
+	REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
+	enable_clocks(0);
+}
+
+void dispc_set_loadmode(enum omap_dss_load_mode mode)
+{
+	enable_clocks(1);
+	REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
+	enable_clocks(0);
+}
+
+
+void omap_dispc_set_default_color(enum omap_channel channel, u32 color)
+{
+	const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
+				DISPC_DEFAULT_COLOR1 };
+
+	enable_clocks(1);
+	dispc_write_reg(def_reg[channel], color);
+	enable_clocks(0);
+}
+
+void omap_dispc_set_trans_key(enum omap_channel ch,
+		enum omap_dss_color_key_type type,
+		u32 trans_key)
+{
+	const struct dispc_reg tr_reg[] = {
+		DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
+
+	enable_clocks(1);
+	if (ch == OMAP_DSS_CHANNEL_LCD)
+		REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
+	else /* OMAP_DSS_CHANNEL_DIGIT */
+		REG_FLD_MOD(DISPC_CONFIG, type, 13, 13);
+
+	dispc_write_reg(tr_reg[ch], trans_key);
+	enable_clocks(0);
+}
+
+void omap_dispc_enable_trans_key(enum omap_channel ch, int enable)
+{
+	enable_clocks(1);
+	if (ch == OMAP_DSS_CHANNEL_LCD)
+		REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
+	else /* OMAP_DSS_CHANNEL_DIGIT */
+		REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
+	enable_clocks(0);
+}
+
+void dispc_set_tft_data_lines(int data_lines)
+{
+	int code;
+
+	switch (data_lines) {
+	case 12:
+		code = 0;
+		break;
+	case 16:
+		code = 1;
+		break;
+	case 18:
+		code = 2;
+		break;
+	case 24:
+		code = 3;
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	enable_clocks(1);
+	REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
+	enable_clocks(0);
+}
+
+void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode)
+{
+	u32 l;
+	int stallmode;
+	int gpout0 = 1;
+	int gpout1;
+
+	switch (mode) {
+	case OMAP_DSS_PARALLELMODE_BYPASS:
+		stallmode = 0;
+		gpout1 = 1;
+		break;
+
+	case OMAP_DSS_PARALLELMODE_RFBI:
+		stallmode = 1;
+		gpout1 = 0;
+		break;
+
+	case OMAP_DSS_PARALLELMODE_DSI:
+		stallmode = 1;
+		gpout1 = 1;
+		break;
+
+	default:
+		BUG();
+		return;
+	}
+
+	enable_clocks(1);
+
+	l = dispc_read_reg(DISPC_CONTROL);
+
+	l = FLD_MOD(l, stallmode, 11, 11);
+	l = FLD_MOD(l, gpout0, 15, 15);
+	l = FLD_MOD(l, gpout1, 16, 16);
+
+	dispc_write_reg(DISPC_CONTROL, l);
+
+	enable_clocks(0);
+}
+
+static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp,
+				   int vsw, int vfp, int vbp)
+{
+	u32 timing_h, timing_v;
+
+	BUG_ON(hsw < 1 || hsw > 64);
+	BUG_ON(hfp < 1 || hfp > 256);
+	BUG_ON(hbp < 1 || hbp > 256);
+
+	BUG_ON(vsw < 1 || vsw > 64);
+	BUG_ON(vfp < 0 || vfp > 255);
+	BUG_ON(vbp < 0 || vbp > 255);
+
+	timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) |
+		FLD_VAL(hbp-1, 27, 20);
+
+	timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) |
+		FLD_VAL(vbp, 27, 20);
+
+	enable_clocks(1);
+	dispc_write_reg(DISPC_TIMING_H, timing_h);
+	dispc_write_reg(DISPC_TIMING_V, timing_v);
+	enable_clocks(0);
+}
+
+/* change name to mode? */
+void dispc_set_lcd_timings(struct omap_video_timings *timings)
+{
+	unsigned xtot, ytot;
+	unsigned long ht, vt;
+
+	_dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp,
+			timings->vsw, timings->vfp, timings->vbp);
+
+	dispc_set_lcd_size(timings->x_res, timings->y_res);
+
+	xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
+	ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
+
+	ht = (timings->pixel_clock * 1000) / xtot;
+	vt = (timings->pixel_clock * 1000) / xtot / ytot;
+
+	DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res);
+	DSSDBG("pck %u\n", timings->pixel_clock);
+	DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
+			timings->hsw, timings->hfp, timings->hbp,
+			timings->vsw, timings->vfp, timings->vbp);
+
+	DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
+}
+
+void dispc_set_lcd_divisor(int lck_div, int pck_div)
+{
+	BUG_ON(lck_div < 1);
+	BUG_ON(pck_div < 2);
+
+	enable_clocks(1);
+	dispc_write_reg(DISPC_DIVISOR,
+			FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
+	enable_clocks(0);
+}
+
+static void dispc_get_lcd_divisor(int *lck_div, int *pck_div)
+{
+	u32 l;
+	l = dispc_read_reg(DISPC_DIVISOR);
+	*lck_div = FLD_GET(l, 23, 16);
+	*pck_div = FLD_GET(l, 7, 0);
+}
+
+unsigned long dispc_fclk_rate(void)
+{
+	unsigned long r = 0;
+
+	if (dss_get_dispc_clk_source() == 0)
+		r = dss_clk_get_rate(DSS_CLK_FCK1);
+	else
+#ifdef CONFIG_OMAP2_DSS_DSI
+		r = dsi_get_dsi1_pll_rate();
+#else
+	BUG();
+#endif
+	return r;
+}
+
+unsigned long dispc_pclk_rate(void)
+{
+	int lcd, pcd;
+	unsigned long r;
+	u32 l;
+
+	l = dispc_read_reg(DISPC_DIVISOR);
+
+	lcd = FLD_GET(l, 23, 16);
+	pcd = FLD_GET(l, 7, 0);
+
+	r = dispc_fclk_rate();
+
+	return r / lcd / pcd;
+}
+
+ssize_t dispc_print_clocks(char *buf, ssize_t size)
+{
+	ssize_t l = 0;
+	int lcd, pcd;
+
+	enable_clocks(1);
+
+	dispc_get_lcd_divisor(&lcd, &pcd);
+
+	l += snprintf(buf + l, size - l, "- dispc -\n");
+
+	l += snprintf(buf + l, size - l, "dispc fclk source = %s\n",
+			dss_get_dispc_clk_source() == 0 ?
+			"dss1_alwon_fclk" : "dsi1_pll_fclk");
+
+	l += snprintf(buf + l, size - l,
+			"pixel clk = %lu / %d / %d = %lu\n",
+			dispc_fclk_rate(),
+			lcd, pcd,
+			dispc_pclk_rate());
+
+	enable_clocks(0);
+
+	return l;
+}
+
+static void _dispc_set_pol_freq(int onoff, int rf, int ieo, int ipc,
+				int ihs, int ivs, int acbi, int acb)
+{
+	u32 l = 0;
+
+	DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n",
+			onoff, rf, ieo, ipc, ihs, ivs, acbi, acb);
+
+	l |= FLD_VAL(onoff, 17, 17);
+	l |= FLD_VAL(rf, 16, 16);
+	l |= FLD_VAL(ieo, 15, 15);
+	l |= FLD_VAL(ipc, 14, 14);
+	l |= FLD_VAL(ihs, 13, 13);
+	l |= FLD_VAL(ivs, 12, 12);
+	l |= FLD_VAL(acbi, 11, 8);
+	l |= FLD_VAL(acb, 7, 0);
+
+	enable_clocks(1);
+	dispc_write_reg(DISPC_POL_FREQ, l);
+	enable_clocks(0);
+}
+
+void dispc_set_pol_freq(struct omap_panel *panel)
+{
+	_dispc_set_pol_freq((panel->config & OMAP_DSS_LCD_ONOFF) != 0,
+				 (panel->config & OMAP_DSS_LCD_RF) != 0,
+				 (panel->config & OMAP_DSS_LCD_IEO) != 0,
+				 (panel->config & OMAP_DSS_LCD_IPC) != 0,
+				 (panel->config & OMAP_DSS_LCD_IHS) != 0,
+				 (panel->config & OMAP_DSS_LCD_IVS) != 0,
+				 panel->acbi, panel->acb);
+}
+
+void find_lck_pck_divs(int is_tft, unsigned long req_pck, unsigned long fck,
+		int *lck_div, int *pck_div)
+{
+	int pcd_min = is_tft ? 2 : 3;
+	unsigned long best_pck;
+	int best_ld, cur_ld;
+	int best_pd, cur_pd;
+
+	best_pck = 0;
+	best_ld = 0;
+	best_pd = 0;
+
+	for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
+		unsigned long lck = fck / cur_ld;
+
+		for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) {
+			unsigned long pck = lck / cur_pd;
+			long old_delta = abs(best_pck - req_pck);
+			long new_delta = abs(pck - req_pck);
+
+			if (best_pck == 0 || new_delta < old_delta) {
+				best_pck = pck;
+				best_ld = cur_ld;
+				best_pd = cur_pd;
+
+				if (pck == req_pck)
+					goto found;
+			}
+
+			if (pck < req_pck)
+				break;
+		}
+
+		if (lck / pcd_min < req_pck)
+			break;
+	}
+
+found:
+	*lck_div = best_ld;
+	*pck_div = best_pd;
+}
+
+int dispc_calc_clock_div(int is_tft, unsigned long req_pck,
+		struct dispc_clock_info *cinfo)
+{
+	unsigned long prate;
+	struct dispc_clock_info cur, best;
+	int match = 0;
+	int min_fck_per_pck;
+
+	if (cpu_is_omap34xx())
+		prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
+	else
+		prate = 0;
+
+	if (req_pck == dispc.cache_req_pck &&
+			((cpu_is_omap34xx() && prate == dispc.cache_prate) ||
+			 dispc.cache_cinfo.fck == dss_clk_get_rate(DSS_CLK_FCK1))) {
+		DSSDBG("dispc clock info found from cache.\n");
+		*cinfo = dispc.cache_cinfo;
+		return 0;
+	}
+
+	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
+
+	if (min_fck_per_pck &&
+		req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
+		DSSERR("Requested pixel clock not possible with the current "
+				"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
+				"the constraint off.\n");
+		min_fck_per_pck = 0;
+	}
+
+retry:
+	memset(&cur, 0, sizeof(cur));
+	memset(&best, 0, sizeof(best));
+
+	if (cpu_is_omap24xx()) {
+		/* XXX can we change the clock on omap2? */
+		cur.fck = dss_clk_get_rate(DSS_CLK_FCK1);
+		cur.fck_div = 1;
+
+		match = 1;
+
+		find_lck_pck_divs(is_tft, req_pck, cur.fck,
+				&cur.lck_div, &cur.pck_div);
+
+		cur.lck = cur.fck / cur.lck_div;
+		cur.pck = cur.lck / cur.pck_div;
+
+		best = cur;
+
+		goto found;
+	} else if (cpu_is_omap34xx()) {
+		for (cur.fck_div = 16; cur.fck_div > 0; --cur.fck_div) {
+			cur.fck = prate / cur.fck_div * 2;
+
+			if (cur.fck > DISPC_MAX_FCK)
+				continue;
+
+			if (min_fck_per_pck &&
+					cur.fck < req_pck * min_fck_per_pck)
+				continue;
+
+			match = 1;
+
+			find_lck_pck_divs(is_tft, req_pck, cur.fck,
+					&cur.lck_div, &cur.pck_div);
+
+			cur.lck = cur.fck / cur.lck_div;
+			cur.pck = cur.lck / cur.pck_div;
+
+			if (abs(cur.pck - req_pck) < abs(best.pck - req_pck)) {
+				best = cur;
+
+				if (cur.pck == req_pck)
+					goto found;
+			}
+		}
+	} else {
+		BUG();
+	}
+
+found:
+	if (!match) {
+		if (min_fck_per_pck) {
+			DSSERR("Could not find suitable clock settings.\n"
+					"Turning FCK/PCK constraint off and"
+					"trying again.\n");
+			min_fck_per_pck = 0;
+			goto retry;
+		}
+
+		DSSERR("Could not find suitable clock settings.\n");
+
+		return -EINVAL;
+	}
+
+	if (cinfo)
+		*cinfo = best;
+
+	dispc.cache_req_pck = req_pck;
+	dispc.cache_prate = prate;
+	dispc.cache_cinfo = best;
+
+	return 0;
+}
+
+int dispc_set_clock_div(struct dispc_clock_info *cinfo)
+{
+	unsigned long prate;
+	int r;
+
+	if (cpu_is_omap34xx()) {
+		prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
+		DSSDBG("dpll4_m4 = %ld\n", prate);
+	}
+
+	DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
+	DSSDBG("lck = %ld (%d)\n", cinfo->lck, cinfo->lck_div);
+	DSSDBG("pck = %ld (%d)\n", cinfo->pck, cinfo->pck_div);
+
+	if (cpu_is_omap34xx()) {
+		r = clk_set_rate(dispc.dpll4_m4_ck, prate / cinfo->fck_div);
+		if (r)
+			return r;
+	}
+
+	dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div);
+
+	return 0;
+}
+
+int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+{
+	int i;
+	int ret = -EBUSY;
+	unsigned long flags;
+	u32 new_mask = 0;
+
+	if (isr == NULL)
+		return -EINVAL;
+
+	spin_lock_irqsave(&dispc.irq_lock, flags);
+
+	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+		if (registered_isr[i].isr == isr) {
+			ret = -EINVAL;
+			break;
+		}
+
+		if (registered_isr[i].isr != NULL)
+			continue;
+
+		registered_isr[i].isr = isr;
+		registered_isr[i].arg = arg;
+		registered_isr[i].mask = mask;
+
+		enable_clocks(1);
+		new_mask = dispc_read_reg(DISPC_IRQENABLE);
+		new_mask |= mask;
+		dispc_write_reg(DISPC_IRQENABLE, new_mask);
+		enable_clocks(0);
+
+		ret = 0;
+		break;
+	}
+
+	spin_unlock_irqrestore(&dispc.irq_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(omap_dispc_register_isr);
+
+int omap_dispc_unregister_isr(omap_dispc_isr_t isr)
+{
+	int i, j;
+	unsigned long flags;
+	u32 new_mask = DISPC_IRQ_MASK_ERROR;
+	int ret = -EINVAL;
+
+	spin_lock_irqsave(&dispc.irq_lock, flags);
+
+	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+		if (registered_isr[i].isr != isr)
+			continue;
+
+		registered_isr[i].isr = NULL;
+		registered_isr[i].arg = NULL;
+		registered_isr[i].mask = 0;
+
+		for (j = 0; j < DISPC_MAX_NR_ISRS; j++)
+			new_mask |= registered_isr[j].mask;
+
+		enable_clocks(1);
+		dispc_write_reg(DISPC_IRQENABLE, new_mask);
+		enable_clocks(0);
+
+		ret = 0;
+		break;
+	}
+
+	spin_unlock_irqrestore(&dispc.irq_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(omap_dispc_unregister_isr);
+
+#ifdef DEBUG
+static void print_irq_status(u32 status)
+{
+	if ((status & DISPC_IRQ_MASK_ERROR) == 0)
+		return;
+
+	printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status);
+
+#define PIS(x) \
+	if (status & DISPC_IRQ_##x) \
+		printk(#x " ");
+	PIS(GFX_FIFO_UNDERFLOW);
+	PIS(OCP_ERR);
+	PIS(VID1_FIFO_UNDERFLOW);
+	PIS(VID2_FIFO_UNDERFLOW);
+	PIS(SYNC_LOST);
+	PIS(SYNC_LOST_DIGIT);
+#undef PIS
+
+	printk("\n");
+}
+#endif
+
+/* Called from dss.c. Note that we don't touch clocks here,
+ * but we presume they are on because we got an IRQ. However,
+ * an irq handler may turn the clocks off, so we may not have
+ * clock later in the function. */
+void dispc_irq_handler(void)
+{
+	int i;
+	u32 irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
+	static int errors;
+	u32 handledirqs = 0;
+
+#ifdef DEBUG
+	if (dss_debug)
+		print_irq_status(irqstatus);
+#endif
+	/* Ack the interrupt. Do it here before clocks are possibly turned
+	 * off */
+	dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
+
+	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+		if (!registered_isr[i].isr)
+			continue;
+		if (registered_isr[i].mask & irqstatus) {
+			registered_isr[i].isr(registered_isr[i].arg,
+					      irqstatus);
+			handledirqs |= registered_isr[i].mask;
+		}
+	}
+
+	if (irqstatus & ~handledirqs & DISPC_IRQ_MASK_ERROR) {
+		if (printk_ratelimit()) {
+			DSSERR("dispc irq error status %04x\n",
+			       irqstatus);
+		}
+		if (errors++ > 100) {
+			DSSERR("Excessive DISPC errors\n"
+					"Turning off lcd and digit\n");
+			dispc_enable_lcd_out(0);
+			dispc_enable_digit_out(0);
+		}
+	}
+
+}
+
+#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
+void dispc_fake_vsync_irq(void)
+{
+	u32 irqstatus = DISPC_IRQ_VSYNC;
+	int i;
+
+	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+		if (!registered_isr[i].isr)
+			continue;
+		if (registered_isr[i].mask & irqstatus)
+			registered_isr[i].isr(registered_isr[i].arg,
+					      irqstatus);
+	}
+}
+#endif
+
+static void _omap_dispc_initialize_irq(void)
+{
+	memset(registered_isr, 0, sizeof(registered_isr));
+
+	/* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
+	 * so clear it */
+	dispc_write_reg(DISPC_IRQSTATUS,
+			dispc_read_reg(DISPC_IRQSTATUS));
+
+	/* We'll handle these always */
+	dispc_write_reg(DISPC_IRQENABLE, DISPC_IRQ_MASK_ERROR);
+}
+
+static void _omap_dispc_initial_config(void)
+{
+	u32 l;
+
+	l = dispc_read_reg(DISPC_SYSCONFIG);
+	l = FLD_MOD(l, 2, 13, 12);	/* MIDLEMODE: smart standby */
+	l = FLD_MOD(l, 2, 4, 3);	/* SIDLEMODE: smart idle */
+	l = FLD_MOD(l, 1, 2, 2);	/* ENWAKEUP */
+	l = FLD_MOD(l, 1, 0, 0);	/* AUTOIDLE */
+	dispc_write_reg(DISPC_SYSCONFIG, l);
+
+	/* FUNCGATED */
+	REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
+
+	/* L3 firewall setting: enable access to OCM RAM */
+	__raw_writel(0x402000b0, IO_ADDRESS(0x680050a0));
+
+	_dispc_setup_color_conv_coef();
+
+	dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
+
+	/* Set logic clock to fck, pixel clock to fck/2 for now */
+	dispc_set_lcd_divisor(1, 2);
+}
+
+int dispc_init(void)
+{
+	u32 rev;
+
+	spin_lock_init(&dispc.irq_lock);
+
+	dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS);
+	if (!dispc.base) {
+		DSSERR("can't ioremap DISPC\n");
+		return -ENOMEM;
+	}
+
+	if (cpu_is_omap34xx()) {
+		dispc.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
+		if (IS_ERR(dispc.dpll4_m4_ck)) {
+			DSSERR("Failed to get dpll4_m4_ck\n");
+			return -ENODEV;
+		}
+	}
+
+	enable_clocks(1);
+
+	_omap_dispc_initial_config();
+
+	_omap_dispc_initialize_irq();
+
+	dispc_save_context();
+
+	rev = dispc_read_reg(DISPC_REVISION);
+	printk(KERN_INFO "OMAP DISPC rev %d.%d\n",
+	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+	enable_clocks(0);
+
+	return 0;
+}
+
+void dispc_exit(void)
+{
+	if (cpu_is_omap34xx())
+		clk_put(dispc.dpll4_m4_ck);
+	iounmap(dispc.base);
+}
+
+int dispc_enable_plane(enum omap_plane plane, int enable)
+{
+	DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
+
+	enable_clocks(1);
+	_dispc_enable_plane(plane, enable);
+	enable_clocks(0);
+
+	return 0;
+}
+
+int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
+		       u32 paddr, int screen_width,
+		       int pos_x, int pos_y,
+		       int width, int height,
+		       int out_width, int out_height,
+		       enum omap_color_mode color_mode,
+		       int ilace)
+{
+	int r = 0;
+
+	DSSDBG("dispc_setup_plane %d, ch %d, pa %x, sw %d, %d,%d, %dx%d -> "
+	       "%dx%d, ilace %d, cmode %x\n",
+	       plane, channel_out, paddr, screen_width, pos_x, pos_y,
+	       width, height,
+	       out_width, out_height,
+	       ilace, color_mode);
+
+	enable_clocks(1);
+
+	r = _dispc_setup_plane(plane, channel_out,
+			   paddr, screen_width,
+			   pos_x, pos_y,
+			   width, height,
+			   out_width, out_height,
+			   color_mode, ilace);
+
+	enable_clocks(0);
+
+	return r;
+}
+
+static int dispc_is_intersecting(int x1, int y1, int w1, int h1,
+				 int x2, int y2, int w2, int h2)
+{
+	if (x1 >= (x2+w2))
+		return 0;
+
+	if ((x1+w1) <= x2)
+		return 0;
+
+	if (y1 >= (y2+h2))
+		return 0;
+
+	if ((y1+h1) <= y2)
+		return 0;
+
+	return 1;
+}
+
+static int dispc_is_overlay_scaled(struct omap_overlay_info *pi)
+{
+	if (pi->width != pi->out_width)
+		return 1;
+
+	if (pi->height != pi->out_height)
+		return 1;
+
+	return 0;
+}
+
+/* returns the area that needs updating */
+void dispc_setup_partial_planes(struct omap_display *display,
+				    int *xi, int *yi, int *wi, int *hi)
+{
+	struct omap_overlay_manager *mgr;
+	int i;
+
+	int x, y, w, h;
+
+	x = *xi;
+	y = *yi;
+	w = *wi;
+	h = *hi;
+
+	DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n",
+		*xi, *yi, *wi, *hi);
+
+
+	mgr = display->manager;
+
+	if (!mgr) {
+		DSSDBG("no manager\n");
+		return;
+	}
+
+	for (i = 0; i < mgr->num_overlays; i++) {
+		struct omap_overlay *ovl;
+		struct omap_overlay_info *pi;
+		ovl = &mgr->overlays[i];
+
+		if (ovl->manager != mgr)
+			continue;
+
+		if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
+			continue;
+
+		pi = &ovl->info;
+
+		if (!pi->enabled)
+			continue;
+		/*
+		 * If the plane is intersecting and scaled, we
+		 * enlarge the update region to accomodate the
+		 * whole area
+		 */
+
+		if (dispc_is_intersecting(x, y, w, h,
+					  pi->pos_x, pi->pos_y,
+					  pi->out_width, pi->out_height)) {
+			if (dispc_is_overlay_scaled(pi)) {
+
+				int x1, y1, x2, y2;
+
+				if (x > pi->pos_x)
+					x1 = pi->pos_x;
+				else
+					x1 = x;
+
+				if (y > pi->pos_y)
+					y1 = pi->pos_y;
+				else
+					y1 = y;
+
+				if ((x + w) < (pi->pos_x + pi->out_width))
+					x2 = pi->pos_x + pi->out_width;
+				else
+					x2 = x + w;
+
+				if ((y + h) < (pi->pos_y + pi->out_height))
+					y2 = pi->pos_y + pi->out_height;
+				else
+					y2 = y + h;
+
+				x = x1;
+				y = y1;
+				w = x2 - x1;
+				h = y2 - y1;
+
+				DSSDBG("Update area after enlarge due to "
+					"scaling %d, %d %dx%d\n",
+					x, y, w, h);
+			}
+		}
+	}
+
+	for (i = 0; i < mgr->num_overlays; i++) {
+		struct omap_overlay *ovl = &mgr->overlays[i];
+		struct omap_overlay_info *pi = &ovl->info;
+
+		int px = pi->pos_x;
+		int py = pi->pos_y;
+		int pw = pi->width;
+		int ph = pi->height;
+		int pow = pi->out_width;
+		int poh = pi->out_height;
+		u32 pa = pi->paddr;
+		int psw = pi->screen_width;
+		int bpp;
+
+		if (ovl->manager != mgr)
+			continue;
+
+		/*
+		 * If plane is not enabled or the update region
+		 * does not intersect with the plane in question,
+		 * we really disable the plane from hardware
+		 */
+
+		if (!pi->enabled ||
+		    !dispc_is_intersecting(x, y, w, h,
+					   px, py, pow, poh)) {
+			dispc_enable_plane(ovl->id, 0);
+			continue;
+		}
+
+		switch (pi->color_mode) {
+		case OMAP_DSS_COLOR_RGB16:
+			bpp = 16;
+			break;
+
+		case OMAP_DSS_COLOR_RGB24P:
+			bpp = 24;
+			break;
+
+		case OMAP_DSS_COLOR_RGB24U:
+			bpp = 32;
+			break;
+
+		case OMAP_DSS_COLOR_YUV2:
+		case OMAP_DSS_COLOR_UYVY:
+			bpp = 16;
+			break;
+
+		default:
+			BUG();
+			return;
+		}
+
+		if (x > pi->pos_x) {
+			px = 0;
+			pw -= (x - pi->pos_x);
+			pa += (x - pi->pos_x) * bpp / 8;
+		} else {
+			px = pi->pos_x - x;
+		}
+
+		if (y > pi->pos_y) {
+			py = 0;
+			ph -= (y - pi->pos_y);
+			pa += (y - pi->pos_y) * psw * bpp / 8;
+		} else {
+			py = pi->pos_y - y;
+		}
+
+		if (w < (px+pw))
+			pw -= (px+pw) - (w);
+
+		if (h < (py+ph))
+			ph -= (py+ph) - (h);
+
+		/* Can't scale the GFX plane */
+		if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0 ||
+				dispc_is_overlay_scaled(pi) == 0) {
+			pow = pw;
+			poh = ph;
+		}
+
+		DSSDBG("calc  plane %d, %x, sw %d, %d,%d, %dx%d -> %dx%d\n",
+				ovl->id, pa, psw, px, py, pw, ph, pow, poh);
+
+		dispc_setup_plane(ovl->id, mgr->id,
+				pa, psw,
+				px, py,
+				pw, ph,
+				pow, poh,
+				pi->color_mode, 0);
+
+		dispc_enable_plane(ovl->id, 1);
+	}
+
+	*xi = x;
+	*yi = y;
+	*wi = w;
+	*hi = h;
+
+}
+
diff --git a/arch/arm/plat-omap/dss/display.c b/arch/arm/plat-omap/dss/display.c
new file mode 100644
index 0000000..e3ff778
--- /dev/null
+++ b/arch/arm/plat-omap/dss/display.c
@@ -0,0 +1,787 @@
+/*
+ * linux/arch/arm/plat-omap/dss/display.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "DISPLAY"
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/clk.h>
+
+#include <mach/display.h>
+#include <mach/clock.h>
+#include "dss.h"
+
+#define DSS_MAX_DISPLAYS                8
+
+static int num_displays;
+static struct omap_display displays[DSS_MAX_DISPLAYS];
+
+static ssize_t show_clk(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	ssize_t l, size = PAGE_SIZE;
+
+	l = 0;
+
+	l += dss_print_clocks(buf + l, size - l);
+
+	l += dispc_print_clocks(buf + l, size - l);
+#ifdef CONFIG_OMAP2_DSS_DSI
+	l += dsi_print_clocks(buf + l, size - l);
+#endif
+	return l;
+}
+
+static DEVICE_ATTR(clk, S_IRUGO, show_clk, NULL);
+
+int initialize_sysfs(struct device *dev)
+{
+	int r;
+
+	r = device_create_file(dev, &dev_attr_clk);
+	if (r)
+		DSSERR("failed to create sysfs clk file\n");
+
+	return r;
+}
+
+void uninitialize_sysfs(struct device *dev)
+{
+	device_remove_file(dev, &dev_attr_clk);
+}
+
+void initialize_displays(struct omap_dss_platform_data *pdata)
+{
+	int i;
+
+	num_displays = 0;
+
+	BUG_ON(pdata->num_displays > DSS_MAX_DISPLAYS);
+
+	for (i = 0; i < pdata->num_displays; ++i) {
+		struct omap_display *display = &displays[i];
+
+		/*atomic_set(&display->ref_count, 0);*/
+		display->ref_count = 0;
+
+		display->hw_config = *pdata->displays[i];
+		display->type = pdata->displays[i]->type;
+		display->name = pdata->displays[i]->name;
+
+		switch (display->type) {
+
+		case OMAP_DISPLAY_TYPE_DPI:
+			dpi_init_display(display);
+			break;
+#ifdef CONFIG_OMAP2_DSS_RFBI
+		case OMAP_DISPLAY_TYPE_DBI:
+			rfbi_init_display(display);
+			break;
+#endif
+#ifdef CONFIG_OMAP2_DSS_VENC
+		case OMAP_DISPLAY_TYPE_VENC:
+			venc_init_display(display);
+			break;
+#endif
+#ifdef CONFIG_OMAP2_DSS_SDI
+		case OMAP_DISPLAY_TYPE_SDI:
+			sdi_init_display(display);
+			break;
+#endif
+#ifdef CONFIG_OMAP2_DSS_DSI
+		case OMAP_DISPLAY_TYPE_DSI:
+			dsi_init_display(display);
+			break;
+#endif
+
+		default:
+			DSSERR("Support for display '%s' not compiled in.\n",
+					display->name);
+			continue;
+		}
+
+		num_displays++;
+	}
+}
+
+static int check_overlay(struct omap_overlay *ovl,
+		struct omap_display *display)
+{
+	struct omap_overlay_info *info;
+	int outw, outh;
+
+	if (!display)
+		return 0;
+
+	if (!ovl->info.enabled)
+		return 0;
+
+	info = &ovl->info;
+
+	if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
+		outw = info->width;
+		outh = info->height;
+	} else {
+		if (info->out_width == 0)
+			outw = info->width;
+		else
+			outw = info->out_width;
+
+		if (info->out_height == 0)
+			outh = info->height;
+		else
+			outh = info->out_height;
+	}
+
+	if (display->panel->timings.x_res < info->pos_x + outw)
+		return -EINVAL;
+
+	if (display->panel->timings.y_res < info->pos_y + outh)
+		return -EINVAL;
+
+	return 0;
+}
+
+
+static int omap_dss_set_manager(struct omap_overlay *ovl,
+		struct omap_overlay_manager *mgr)
+{
+	int r;
+
+	if (ovl->manager) {
+		DSSERR("overlay '%s' already has a manager '%s'\n",
+				ovl->name, ovl->manager->name);
+	}
+
+	r = check_overlay(ovl, mgr->display);
+	if (r)
+		return r;
+
+	ovl->manager = mgr;
+
+	return 0;
+}
+
+static int omap_dss_unset_manager(struct omap_overlay *ovl)
+{
+	if (!ovl->manager) {
+		DSSERR("failed to detach overlay: manager not set\n");
+		return -EINVAL;
+	}
+
+	ovl->manager = NULL;
+
+	return 0;
+}
+
+static int omap_dss_set_display(struct omap_overlay_manager *mgr,
+		struct omap_display *display)
+{
+	int i;
+	int r;
+
+	if (display->manager) {
+		DSSERR("display '%s' already has a manager '%s'\n",
+			       display->name, display->manager->name);
+		return -EINVAL;
+	}
+
+	if ((mgr->supported_displays & display->type) == 0) {
+		DSSERR("display '%s' does not support manager '%s'\n",
+			       display->name, mgr->name);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < mgr->num_overlays; i++) {
+		struct omap_overlay *ovl = &mgr->overlays[i];
+
+		if (ovl->manager != mgr || !ovl->info.enabled)
+			continue;
+
+		r = check_overlay(ovl, display);
+		if (r)
+			return r;
+	}
+
+	display->manager = mgr;
+	mgr->display = display;
+
+	return 0;
+}
+
+static int omap_dss_unset_display(struct omap_overlay_manager *mgr)
+{
+	if (!mgr->display) {
+		DSSERR("failed to unset display, display not set.\n");
+		return -EINVAL;
+	}
+
+	mgr->display->manager = NULL;
+	mgr->display = NULL;
+
+	return 0;
+}
+
+static int omap_dss_setup_overlay_input(struct omap_overlay *ovl,
+		u32 paddr, void *vaddr, int screen_width,
+		int width, int height,
+		enum omap_color_mode color_mode)
+{
+	int r;
+	struct omap_overlay_info old_info;
+
+	if ((ovl->supported_modes & color_mode) == 0) {
+		DSSERR("overlay doesn't support mode %d\n", color_mode);
+		return -EINVAL;
+	}
+
+	old_info = ovl->info;
+
+	ovl->info.paddr = paddr;
+	ovl->info.vaddr = vaddr;
+	ovl->info.screen_width = screen_width;
+
+	ovl->info.width = width;
+	ovl->info.height = height;
+	ovl->info.color_mode = color_mode;
+
+	if (ovl->manager) {
+		r = check_overlay(ovl, ovl->manager->display);
+		if (r) {
+			ovl->info = old_info;
+			return r;
+		}
+	}
+
+	return 0;
+}
+
+static int omap_dss_setup_overlay_output(struct omap_overlay *ovl,
+		int pos_x, int pos_y,
+		int out_width, int out_height)
+{
+	int r;
+	struct omap_overlay_info old_info;
+
+	old_info = ovl->info;
+
+	ovl->info.pos_x = pos_x;
+	ovl->info.pos_y = pos_y;
+	ovl->info.out_width = out_width;
+	ovl->info.out_height = out_height;
+
+	if (ovl->manager) {
+		r = check_overlay(ovl, ovl->manager->display);
+		if (r) {
+			ovl->info = old_info;
+			return r;
+		}
+	}
+
+	return 0;
+}
+
+static int omap_dss_enable_overlay(struct omap_overlay *ovl, int enable)
+{
+	struct omap_overlay_info old_info;
+	int r;
+
+	old_info = ovl->info;
+
+	ovl->info.enabled = enable ? 1 : 0;
+
+	if (ovl->manager) {
+		r = check_overlay(ovl, ovl->manager->display);
+		if (r) {
+			ovl->info = old_info;
+			return r;
+		}
+	}
+
+	return 0;
+}
+
+
+static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+{
+	int i;
+	int r = 0;
+
+	DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
+
+	if (!mgr->display) {
+		DSSDBG("no display, aborting apply\n");
+		return 0;
+	}
+
+	/* on a manual update display update() handles configuring
+	 * planes */
+	if (mgr->display->get_update_mode) {
+		enum omap_dss_update_mode mode;
+		mode = mgr->display->get_update_mode(mgr->display);
+		if (mode == OMAP_DSS_UPDATE_MANUAL)
+			return 0;
+	}
+
+	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+	for (i = 0; i < mgr->num_overlays; i++) {
+		int ilace = 0;
+		int outw, outh;
+
+		struct omap_overlay *ovl = &mgr->overlays[i];
+
+		if (!ovl->manager) {
+			dispc_enable_plane(ovl->id, 0);
+			continue;
+		}
+
+		if (ovl->manager != mgr)
+			continue;
+
+		if (!ovl->info.enabled) {
+			dispc_enable_plane(ovl->id, 0);
+			continue;
+		}
+
+		if (mgr->display->type == OMAP_DISPLAY_TYPE_VENC)
+			ilace = 1;
+
+		if (ovl->info.out_width == 0)
+			outw = ovl->info.width;
+		else
+			outw = ovl->info.out_width;
+
+		if (ovl->info.out_height == 0)
+			outh = ovl->info.height;
+		else
+			outh = ovl->info.out_height;
+
+		r = dispc_setup_plane(ovl->id, ovl->manager->id,
+				ovl->info.paddr,
+				ovl->info.screen_width,
+				ovl->info.pos_x,
+				ovl->info.pos_y,
+				ovl->info.width,
+				ovl->info.height,
+				outw,
+				outh,
+				ovl->info.color_mode,
+				ilace);
+
+		if (r) {
+			DSSERR("dispc_setup_plane failed\n");
+			goto exit;
+		}
+
+		dispc_enable_plane(ovl->id, 1);
+	}
+
+	dispc_go(mgr->id);
+
+exit:
+	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+	return r;
+}
+
+static struct omap_overlay dispc_overlays[] = {
+	{
+		.name = "gfx",
+		.id = OMAP_DSS_GFX,
+		.set_manager = &omap_dss_set_manager,
+		.unset_manager = &omap_dss_unset_manager,
+		.setup_input = &omap_dss_setup_overlay_input,
+		.setup_output = &omap_dss_setup_overlay_output,
+		.enable = &omap_dss_enable_overlay,
+		.supported_modes = OMAP_DSS_COLOR_GFX_OMAP3,
+	},
+	{
+		.name = "vid1",
+		.id = OMAP_DSS_VIDEO1,
+		.set_manager = &omap_dss_set_manager,
+		.unset_manager = &omap_dss_unset_manager,
+		.setup_input = &omap_dss_setup_overlay_input,
+		.setup_output = &omap_dss_setup_overlay_output,
+		.enable = &omap_dss_enable_overlay,
+		.supported_modes = OMAP_DSS_COLOR_VID_OMAP3,
+		.caps = OMAP_DSS_OVL_CAP_SCALE,
+	},
+	{
+		.name = "vid2",
+		.id = OMAP_DSS_VIDEO2,
+		.set_manager = &omap_dss_set_manager,
+		.unset_manager = &omap_dss_unset_manager,
+		.setup_input = &omap_dss_setup_overlay_input,
+		.setup_output = &omap_dss_setup_overlay_output,
+		.enable = &omap_dss_enable_overlay,
+		.supported_modes = OMAP_DSS_COLOR_VID_OMAP3,
+		.caps = OMAP_DSS_OVL_CAP_SCALE,
+	},
+};
+
+static struct omap_overlay_manager dispc_overlay_managers[] =
+{
+	[OMAP_DSS_OVL_MGR_LCD] = {
+		.name = "lcd",
+		.id = OMAP_DSS_CHANNEL_LCD,
+		.num_overlays = 3,
+		.overlays = dispc_overlays,
+		.set_display = &omap_dss_set_display,
+		.unset_display = &omap_dss_unset_display,
+		.apply = &omap_dss_mgr_apply,
+		.caps = OMAP_DSS_OVL_MGR_CAP_DISPC,
+		.supported_displays =
+			OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
+			OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI,
+	},
+	[OMAP_DSS_OVL_MGR_TV] = {
+		.name = "tv",
+		.id = OMAP_DSS_CHANNEL_DIGIT,
+		.num_overlays = 3,
+		.overlays = dispc_overlays,
+		.set_display = &omap_dss_set_display,
+		.unset_display = &omap_dss_unset_display,
+		.apply = &omap_dss_mgr_apply,
+		.caps = OMAP_DSS_OVL_MGR_CAP_DISPC,
+		.supported_displays = OMAP_DISPLAY_TYPE_VENC,
+	},
+};
+
+static int num_overlays = 3;
+
+static struct omap_overlay *omap_dss_overlays[10] = {
+	&dispc_overlays[0],
+	&dispc_overlays[1],
+	&dispc_overlays[2],
+};
+
+static int num_overlay_managers = 2;
+
+static struct omap_overlay_manager *omap_dss_overlay_managers[10] = {
+	&dispc_overlay_managers[0],
+	&dispc_overlay_managers[1],
+};
+
+
+static void omap_dss_add_overlay(struct omap_overlay *overlay)
+{
+	int i = num_overlays++;
+
+	omap_dss_overlays[i] = overlay;
+}
+
+static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
+{
+	int i = num_overlay_managers++;
+	omap_dss_overlay_managers[i] = manager;
+}
+
+int omap_dss_get_num_overlays(void)
+{
+	return num_overlays;
+}
+EXPORT_SYMBOL(omap_dss_get_num_overlays);
+
+struct omap_overlay *omap_dss_get_overlay(int num)
+{
+	BUG_ON(num >= num_overlays);
+	return omap_dss_overlays[num];
+}
+EXPORT_SYMBOL(omap_dss_get_overlay);
+
+int omap_dss_get_num_overlay_managers(void)
+{
+	return num_overlay_managers;
+}
+EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
+
+struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
+{
+	BUG_ON(num >= num_overlay_managers);
+	return omap_dss_overlay_managers[num];
+}
+EXPORT_SYMBOL(omap_dss_get_overlay_manager);
+
+static int ovl_mgr_apply_l4(struct omap_overlay_manager *mgr)
+{
+	DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);
+
+	return 0;
+}
+
+void initialize_overlays(const char *def_disp_name)
+{
+	int i;
+	struct omap_overlay_manager *lcd_mgr;
+	struct omap_overlay_manager *tv_mgr;
+	struct omap_overlay_manager *def_mgr = NULL;
+
+	lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD);
+	tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV);
+
+	if (def_disp_name) {
+		for (i = 0; i < num_displays; i++) {
+			struct omap_display *display = &displays[i];
+
+			if (strcmp(display->name, def_disp_name) == 0) {
+				if (display->type != OMAP_DISPLAY_TYPE_VENC) {
+					omap_dss_set_display(lcd_mgr, display);
+					def_mgr = lcd_mgr;
+				} else {
+					omap_dss_set_display(tv_mgr, display);
+					def_mgr = tv_mgr;
+				}
+
+				break;
+			}
+		}
+
+		if (!def_mgr)
+			DSSWARN("default display %s not found\n",
+					def_disp_name);
+	}
+
+	if (def_mgr != lcd_mgr) {
+		/* connect lcd manager to first non-VENC display found */
+		for (i = 0; i < num_displays; i++) {
+			struct omap_display *display = &displays[i];
+			if (display->type != OMAP_DISPLAY_TYPE_VENC) {
+				omap_dss_set_display(lcd_mgr, display);
+
+				if (!def_mgr)
+					def_mgr = lcd_mgr;
+
+				break;
+			}
+		}
+	}
+
+	if (def_mgr != tv_mgr) {
+		/* connect tv manager to first VENC display found */
+		for (i = 0; i < num_displays; i++) {
+			struct omap_display *display = &displays[i];
+			if (display->type == OMAP_DISPLAY_TYPE_VENC) {
+				omap_dss_set_display(tv_mgr, display);
+
+				if (!def_mgr)
+					def_mgr = tv_mgr;
+
+				break;
+			}
+		}
+	}
+
+	/* connect all dispc overlays to def_mgr */
+	if (def_mgr) {
+		for (i = 0; i < 3; i++) {
+			struct omap_overlay *ovl;
+			ovl = omap_dss_get_overlay(i);
+			omap_dss_set_manager(ovl, def_mgr);
+		}
+	}
+
+	/* setup L4 overlay as an example */
+	{
+		static struct omap_overlay ovl = {
+			.name = "l4-ovl",
+			.supported_modes = OMAP_DSS_COLOR_RGB24U,
+			.set_manager = &omap_dss_set_manager,
+			.unset_manager = &omap_dss_unset_manager,
+			.setup_input = &omap_dss_setup_overlay_input,
+			.setup_output = &omap_dss_setup_overlay_output,
+			.enable = &omap_dss_enable_overlay,
+		};
+
+		static struct omap_overlay_manager mgr = {
+			.name = "l4",
+			.num_overlays = 1,
+			.overlays = &ovl,
+			.set_display = &omap_dss_set_display,
+			.unset_display = &omap_dss_unset_display,
+			.apply = &ovl_mgr_apply_l4,
+			.supported_displays =
+				OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI,
+		};
+
+		omap_dss_add_overlay(&ovl);
+		omap_dss_add_overlay_manager(&mgr);
+		omap_dss_set_manager(&ovl, &mgr);
+	}
+
+}
+
+
+int omap_dss_get_num_displays(void)
+{
+	return num_displays;
+}
+EXPORT_SYMBOL(omap_dss_get_num_displays);
+
+struct omap_display *omap_dss_get_display(int no)
+{
+	struct omap_display *display;
+
+	if (no >= num_displays)
+		return NULL;
+
+	display = &displays[no];
+
+	switch (display->type) {
+	case OMAP_DISPLAY_TYPE_VENC:
+		break;
+
+	case OMAP_DISPLAY_TYPE_DPI:
+	case OMAP_DISPLAY_TYPE_SDI:
+		if (display->panel == NULL)
+			return NULL;
+		break;
+
+	case OMAP_DISPLAY_TYPE_DBI:
+	case OMAP_DISPLAY_TYPE_DSI:
+		if (display->panel == NULL || display->ctrl == NULL)
+			return NULL;
+		break;
+
+	default:
+		return NULL;
+	}
+
+	if (display->panel) {
+		if (!try_module_get(display->panel->owner))
+			goto err0;
+
+		if (display->panel->init)
+			if (display->panel->init(display) != 0)
+				goto err1;
+	}
+
+	if (display->ctrl) {
+		if (!try_module_get(display->ctrl->owner))
+			goto err2;
+
+		if (display->ctrl->init)
+			if (display->ctrl->init(display) != 0)
+				goto err3;
+	}
+
+	display->ref_count++;
+	/*
+	if (atomic_cmpxchg(&display->ref_count, 0, 1) != 0)
+		return 0;
+*/
+
+	return display;
+err3:
+	if (display->ctrl)
+		module_put(display->ctrl->owner);
+err2:
+	if (display->panel && display->panel->init)
+		display->panel->cleanup(display);
+err1:
+	if (display->panel)
+		module_put(display->panel->owner);
+err0:
+	return NULL;
+}
+EXPORT_SYMBOL(omap_dss_get_display);
+
+void omap_dss_put_display(struct omap_display *display)
+{
+	if (--display->ref_count > 0)
+		return;
+/*
+	if (atomic_cmpxchg(&display->ref_count, 1, 0) != 1)
+		return;
+*/
+	if (display->ctrl) {
+		if (display->ctrl->cleanup)
+			display->ctrl->cleanup(display);
+		module_put(display->ctrl->owner);
+	}
+
+	if (display->panel) {
+		if (display->panel->cleanup)
+			display->panel->cleanup(display);
+		module_put(display->panel->owner);
+	}
+}
+EXPORT_SYMBOL(omap_dss_put_display);
+
+void omap_dss_register_ctrl(struct omap_ctrl *ctrl)
+{
+	int i;
+
+	for (i = 0; i < num_displays; i++) {
+		struct omap_display *display = &displays[i];
+		if (display->hw_config.ctrl_name &&
+		    strcmp(display->hw_config.ctrl_name, ctrl->name) == 0) {
+			display->ctrl = ctrl;
+			DSSDBG("ctrl '%s' registered\n", ctrl->name);
+		}
+	}
+}
+EXPORT_SYMBOL(omap_dss_register_ctrl);
+
+void omap_dss_register_panel(struct omap_panel *panel)
+{
+	int i;
+
+	for (i = 0; i < num_displays; i++) {
+		struct omap_display *display = &displays[i];
+		if (display->hw_config.panel_name &&
+		    strcmp(display->hw_config.panel_name, panel->name) == 0) {
+			display->panel = panel;
+			DSSDBG("panel '%s' registered\n", panel->name);
+		}
+	}
+}
+EXPORT_SYMBOL(omap_dss_register_panel);
+
+void omap_dss_unregister_ctrl(struct omap_ctrl *ctrl)
+{
+	int i;
+
+	for (i = 0; i < num_displays; i++) {
+		struct omap_display *display = &displays[i];
+		if (display->hw_config.ctrl_name &&
+		    strcmp(display->hw_config.ctrl_name, ctrl->name) == 0)
+			display->ctrl = NULL;
+	}
+}
+EXPORT_SYMBOL(omap_dss_unregister_ctrl);
+
+void omap_dss_unregister_panel(struct omap_panel *panel)
+{
+	int i;
+
+	for (i = 0; i < num_displays; i++) {
+		struct omap_display *display = &displays[i];
+		if (display->hw_config.panel_name &&
+		    strcmp(display->hw_config.panel_name, panel->name) == 0)
+			display->panel = NULL;
+	}
+}
+EXPORT_SYMBOL(omap_dss_unregister_panel);
diff --git a/arch/arm/plat-omap/dss/dpi.c b/arch/arm/plat-omap/dss/dpi.c
new file mode 100644
index 0000000..2dd8a3b
--- /dev/null
+++ b/arch/arm/plat-omap/dss/dpi.c
@@ -0,0 +1,344 @@
+/*
+ * linux/arch/arm/plat-omap/dss/dpi.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+
+#include <mach/board.h>
+#include <mach/display.h>
+#include "dss.h"
+
+
+static struct {
+	int update_enabled;
+} dpi;
+
+static void dpi_set_mode(struct omap_display *display)
+{
+	struct omap_panel *panel = display->panel;
+	int lck_div, pck_div;
+	unsigned long fck;
+	unsigned long pck;
+	int is_tft;
+
+	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+	dispc_set_pol_freq(panel);
+
+	is_tft = (display->panel->config & OMAP_DSS_LCD_TFT) != 0;
+
+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
+	{
+		struct dsi_clock_info cinfo;
+		dsi_pll_calc_pck(is_tft,
+				display->panel->timings.pixel_clock * 1000,
+				&cinfo);
+
+		dsi_pll_program(&cinfo);
+
+		dss_select_clk_source(0, 1);
+
+		dispc_set_lcd_divisor(cinfo.lck_div, cinfo.pck_div);
+
+		fck = cinfo.dispc_fck;
+		lck_div = cinfo.lck_div;
+		pck_div = cinfo.pck_div;
+	}
+#else
+	{
+		struct dispc_clock_info cinfo;
+		dispc_calc_clock_div(is_tft, panel->timings.pixel_clock * 1000,
+				&cinfo);
+
+		if (dispc_set_clock_div(&cinfo)) {
+			DSSERR("Failed to set DSS clocks\n");
+			dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+			return;
+		}
+
+		fck = cinfo.fck;
+		lck_div = cinfo.lck_div;
+		pck_div = cinfo.pck_div;
+	}
+#endif
+
+	pck = fck / lck_div / pck_div / 1000;
+
+	if (pck != panel->timings.pixel_clock) {
+		DSSWARN("Could not find exact pixel clock. "
+				"Requested %d kHz, got %lu kHz\n",
+				panel->timings.pixel_clock, pck);
+
+		panel->timings.pixel_clock = pck;
+	}
+
+	dispc_set_lcd_timings(&panel->timings);
+
+	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+}
+
+
+static int dpi_display_enable(struct omap_display *display)
+{
+	struct omap_panel *panel = display->panel;
+	int r;
+	int is_tft;
+	unsigned high, low, burst;
+
+	if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
+		DSSERR("display already enabled\n");
+		return -EINVAL;
+	}
+
+	r = panel->enable(display);
+	if (r)
+		return r;
+
+	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
+	dss_clk_enable(DSS_CLK_FCK2);
+	r = dsi_pll_init(0, 1);
+	if (r)
+		return r;
+#endif
+	is_tft = (display->panel->config & OMAP_DSS_LCD_TFT) != 0;
+
+	dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
+	dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT :
+			OMAP_DSS_LCD_DISPLAY_STN);
+	dispc_set_tft_data_lines(display->hw_config.u.dpi.data_lines);
+
+	dispc_set_burst_size(OMAP_DSS_GFX, OMAP_DSS_BURST_16x32);
+	dispc_set_burst_size(OMAP_DSS_VIDEO1, OMAP_DSS_BURST_16x32);
+	dispc_set_burst_size(OMAP_DSS_VIDEO2, OMAP_DSS_BURST_16x32);
+
+	burst = 16 * 32 / 8;
+
+	high = dispc_get_plane_fifo_size(OMAP_DSS_GFX) - burst;
+	low = dispc_get_plane_fifo_size(OMAP_DSS_GFX) / 4;
+	dispc_setup_plane_fifo(OMAP_DSS_GFX, low, high);
+
+	high = dispc_get_plane_fifo_size(OMAP_DSS_VIDEO1) - burst;
+	low = dispc_get_plane_fifo_size(OMAP_DSS_VIDEO1) / 4;
+	dispc_setup_plane_fifo(OMAP_DSS_VIDEO1, low, high);
+
+	high = dispc_get_plane_fifo_size(OMAP_DSS_VIDEO2) - burst;
+	low = dispc_get_plane_fifo_size(OMAP_DSS_VIDEO2) / 4;
+	dispc_setup_plane_fifo(OMAP_DSS_VIDEO2, low, high);
+
+	dpi_set_mode(display);
+
+	mdelay(2);
+
+	dispc_enable_lcd_out(1);
+
+	display->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	return 0;
+}
+
+static int dpi_display_resume(struct omap_display *display);
+
+static void dpi_display_disable(struct omap_display *display)
+{
+	if (display->state == OMAP_DSS_DISPLAY_DISABLED)
+		return;
+
+	if (display->state == OMAP_DSS_DISPLAY_SUSPENDED)
+		dpi_display_resume(display);
+
+	display->panel->disable(display);
+	dispc_enable_lcd_out(0);
+
+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
+	dss_select_clk_source(0, 0);
+	dsi_pll_uninit();
+	dss_clk_disable(DSS_CLK_FCK2);
+#endif
+
+	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+	display->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static int dpi_display_suspend(struct omap_display *display)
+{
+	if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
+		return -EINVAL;
+
+	if (display->panel->suspend)
+		display->panel->suspend(display);
+
+	dispc_enable_lcd_out(0);
+
+	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+	display->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
+	return 0;
+}
+
+static int dpi_display_resume(struct omap_display *display)
+{
+	if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
+		return -EINVAL;
+
+	dispc_enable_lcd_out(1);
+
+	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+	if (display->panel->resume)
+		display->panel->resume(display);
+
+	display->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	return 0;
+}
+
+static void dpi_set_timings(struct omap_display *display,
+			struct omap_video_timings *timings)
+{
+	DSSDBG("dpi_set_timings\n");
+	display->panel->timings = *timings;
+	if (display->state == OMAP_DSS_DISPLAY_ACTIVE) {
+		dpi_set_mode(display);
+		dispc_go(OMAP_DSS_CHANNEL_LCD);
+	}
+}
+
+static int dpi_check_timings(struct omap_display *display,
+			struct omap_video_timings *timings)
+{
+	int is_tft;
+	int r;
+	int lck_div, pck_div;
+	unsigned long fck;
+	unsigned long pck;
+
+	if (timings->hsw < 1 || timings->hsw > 64 ||
+		timings->hfp < 1 || timings->hfp > 256 ||
+		timings->hbp < 1 || timings->hbp > 256) {
+		return -EINVAL;
+	}
+
+	if (timings->vsw < 1 || timings->vsw > 64 ||
+		timings->vfp > 256 || timings->vbp > 256) {
+		return -EINVAL;
+	}
+
+	if (timings->pixel_clock == 0)
+		return -EINVAL;
+
+	is_tft = (display->panel->config & OMAP_DSS_LCD_TFT) != 0;
+
+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
+	{
+		struct dsi_clock_info cinfo;
+		r = dsi_pll_calc_pck(is_tft, timings->pixel_clock * 1000,
+				&cinfo);
+
+		if (r)
+			return r;
+
+		fck = cinfo.dispc_fck;
+		lck_div = cinfo.lck_div;
+		pck_div = cinfo.pck_div;
+	}
+#else
+	{
+		struct dispc_clock_info cinfo;
+		r = dispc_calc_clock_div(is_tft, timings->pixel_clock * 1000,
+				&cinfo);
+
+		if (r)
+			return r;
+
+		fck = cinfo.fck;
+		lck_div = cinfo.lck_div;
+		pck_div = cinfo.pck_div;
+	}
+#endif
+
+	pck = fck / lck_div / pck_div / 1000;
+
+	timings->pixel_clock = pck;
+
+	return 0;
+}
+
+static void dpi_get_timings(struct omap_display *display,
+			struct omap_video_timings *timings)
+{
+	*timings = display->panel->timings;
+}
+
+static int dpi_display_set_update_mode(struct omap_display *display,
+		enum omap_dss_update_mode mode)
+{
+	if (mode == OMAP_DSS_UPDATE_MANUAL)
+		return -EINVAL;
+
+	if (mode == OMAP_DSS_UPDATE_DISABLED) {
+		dispc_enable_lcd_out(0);
+		dpi.update_enabled = 0;
+	} else {
+		dispc_enable_lcd_out(1);
+		dpi.update_enabled = 1;
+	}
+
+	return 0;
+}
+
+static enum omap_dss_update_mode dpi_display_get_update_mode(
+		struct omap_display *display)
+{
+	return dpi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
+		OMAP_DSS_UPDATE_DISABLED;
+}
+
+void dpi_init_display(struct omap_display *display)
+{
+	DSSDBG("DPI init_display\n");
+
+	display->enable = dpi_display_enable;
+	display->disable = dpi_display_disable;
+	display->suspend = dpi_display_suspend;
+	display->resume = dpi_display_resume;
+	display->set_timings = dpi_set_timings;
+	display->check_timings = dpi_check_timings;
+	display->get_timings = dpi_get_timings;
+	display->set_update_mode = dpi_display_set_update_mode;
+	display->get_update_mode = dpi_display_get_update_mode;
+}
+
+int dpi_init(void)
+{
+	return 0;
+}
+
+void dpi_exit(void)
+{
+}
+
diff --git a/arch/arm/plat-omap/dss/dss.c b/arch/arm/plat-omap/dss/dss.c
new file mode 100644
index 0000000..b9f35d8
--- /dev/null
+++ b/arch/arm/plat-omap/dss/dss.c
@@ -0,0 +1,774 @@
+/*
+ * linux/arch/arm/plat-omap/dss/dss.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "DSS"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <mach/display.h>
+#include <mach/clock.h>
+#include "dss.h"
+
+#define DSS_BASE			0x48050000
+
+#define DSS_SZ_REGS			SZ_512
+
+struct dss_reg {
+	u16 idx;
+};
+
+#define DSS_REG(idx)			((const struct dss_reg) { idx })
+
+#define DSS_REVISION			DSS_REG(0x0000)
+#define DSS_SYSCONFIG			DSS_REG(0x0010)
+#define DSS_SYSSTATUS			DSS_REG(0x0014)
+#define DSS_IRQSTATUS			DSS_REG(0x0018)
+#define DSS_CONTROL			DSS_REG(0x0040)
+#define DSS_SDI_CONTROL			DSS_REG(0x0044)
+#define DSS_PLL_CONTROL			DSS_REG(0x0048)
+#define DSS_SDI_STATUS			DSS_REG(0x005C)
+
+#define REG_GET(idx, start, end) \
+	FLD_GET(dss_read_reg(idx), start, end)
+
+#define REG_FLD_MOD(idx, val, start, end) \
+	dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
+
+static struct {
+	void __iomem    *base;
+
+	struct clk      *dss_ick;
+	struct clk	*dss1_fck;
+	struct clk	*dss2_fck;
+	struct clk      *dss_54m_fck;
+	struct clk	*dss_96m_fck;
+
+	unsigned	num_clks_enabled;
+	struct platform_device *pdev;
+	unsigned	ctx_id;
+	u32		ctx[DSS_SZ_REGS / sizeof(u32)];
+} dss;
+
+static void dss_clk_enable_all_no_ctx(void);
+static void dss_clk_disable_all_no_ctx(void);
+static void dss_clk_enable_no_ctx(enum dss_clock clks);
+static void dss_clk_disable_no_ctx(enum dss_clock clks);
+static int _omap_dss_wait_reset(void);
+
+static char *def_disp_name;
+module_param_named(def_disp, def_disp_name, charp, 0);
+MODULE_PARM_DESC(def_disp_name, "default display name");
+
+#ifdef DEBUG
+unsigned int dss_debug;
+module_param_named(debug, dss_debug, bool, 0644);
+#endif
+
+static inline void dss_write_reg(const struct dss_reg idx, u32 val)
+{
+	__raw_writel(val, dss.base + idx.idx);
+}
+
+static inline u32 dss_read_reg(const struct dss_reg idx)
+{
+	return __raw_readl(dss.base + idx.idx);
+}
+
+#define SR(reg) \
+	dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
+#define RR(reg) \
+	dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
+
+static void dss_save_context(void)
+{
+	if (cpu_is_omap24xx())
+		return;
+
+	SR(SYSCONFIG);
+	SR(CONTROL);
+	SR(SDI_CONTROL);
+	SR(PLL_CONTROL);
+}
+
+static void dss_restore_context(void)
+{
+	RR(SYSCONFIG);
+	RR(CONTROL);
+	RR(SDI_CONTROL);
+	RR(PLL_CONTROL);
+}
+
+#undef SR
+#undef RR
+
+static unsigned dss_get_ctx_id(void)
+{
+	struct omap_dss_platform_data *pdata = dss.pdev->dev.platform_data;
+
+	if (!pdata->get_last_off_on_transaction_id)
+		return 0;
+
+	return pdata->get_last_off_on_transaction_id(&dss.pdev->dev);
+}
+
+static void save_all_ctx(void)
+{
+	DSSDBG("save context\n");
+
+	dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+	dss_save_context();
+	dispc_save_context();
+#ifdef CONFIG_OMAP2_DSS_DSI
+	dsi_save_context();
+#endif
+
+	dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
+}
+
+static void restore_all_ctx(void)
+{
+	DSSDBG("restore context\n");
+
+	dss_clk_enable_all_no_ctx();
+
+	if (_omap_dss_wait_reset())
+		DSSERR("DSS not coming out of reset after sleep\n");
+
+	dss_restore_context();
+	dispc_restore_context();
+#ifdef CONFIG_OMAP2_DSS_DSI
+	dsi_restore_context();
+#endif
+
+	dss_clk_disable_all_no_ctx();
+}
+
+void dss_sdi_init(int datapairs)
+{
+	u32 l;
+
+	BUG_ON(datapairs > 3 || datapairs < 1);
+
+	l = dss_read_reg(DSS_SDI_CONTROL);
+	l = FLD_MOD(l, 0xf, 19, 15);		/* SDI_PDIV */
+	l = FLD_MOD(l, datapairs-1, 3, 2);	/* SDI_PRSEL */
+	l = FLD_MOD(l, 2, 1, 0);		/* SDI_BWSEL */
+	dss_write_reg(DSS_SDI_CONTROL, l);
+
+	l = dss_read_reg(DSS_PLL_CONTROL);
+	l = FLD_MOD(l, 0x7, 25, 22);	/* SDI_PLL_FREQSEL */
+	l = FLD_MOD(l, 0xb, 16, 11);	/* SDI_PLL_REGN */
+	l = FLD_MOD(l, 0xb4, 10, 1);	/* SDI_PLL_REGM */
+	dss_write_reg(DSS_PLL_CONTROL, l);
+
+	/* Reset SDI PLL */
+	REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
+	udelay(1);	/* wait 2x PCLK */
+
+	/* Lock SDI PLL */
+	REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
+
+	/* Waiting for PLL lock request to complete */
+	while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6))
+		;
+
+	/* Clearing PLL_GO bit */
+	REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
+
+	/* Waiting for PLL to lock */
+	while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5)))
+		;
+
+	dispc_lcd_enable_signal(1);
+
+	/* Waiting for SDI reset to complete */
+	while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5)))
+		;
+}
+
+ssize_t dss_print_clocks(char *buf, ssize_t size)
+{
+	ssize_t l = 0;
+	int i;
+	struct clk *clocks[5] = {
+		dss.dss_ick,
+		dss.dss1_fck,
+		dss.dss2_fck,
+		dss.dss_54m_fck,
+		dss.dss_96m_fck
+	};
+
+	l += snprintf(buf + l, size - l, "- dss -\n");
+
+	l += snprintf(buf + l, size - l, "internal clk count\t%u\n",
+			dss.num_clks_enabled);
+
+	for (i = 0; i < 5; i++) {
+		if (!clocks[i])
+			continue;
+		l += snprintf(buf + l, size - l, "%-15s\t%lu\t%d\n",
+				clocks[i]->name,
+				clk_get_rate(clocks[i]),
+				clocks[i]->usecount);
+	}
+
+	return l;
+}
+
+static int get_dss_clocks(void)
+{
+	const struct {
+		struct clk **clock;
+		char *omap2_name;
+		char *omap3_name;
+	} clocks[5] = {
+		{ &dss.dss_ick, "dss_ick", "dss_ick" },	/* L3 & L4 ick */
+		{ &dss.dss1_fck, "dss1_fck", "dss1_alwon_fck" },
+		{ &dss.dss2_fck, "dss2_fck", "dss2_alwon_fck" },
+		{ &dss.dss_54m_fck, "dss_54m_fck", "dss_tv_fck" },
+		{ &dss.dss_96m_fck, NULL, "dss_96m_fck" },
+	};
+
+	int r = 0;
+	int i;
+	const int num_clocks = 5;
+
+	for (i = 0; i < num_clocks; i++)
+		*clocks[i].clock = NULL;
+
+	for (i = 0; i < num_clocks; i++) {
+		struct clk *clk;
+		const char *clk_name;
+
+		clk_name = cpu_is_omap34xx() ? clocks[i].omap3_name
+			: clocks[i].omap2_name;
+
+		if (!clk_name)
+			continue;
+
+		clk = clk_get(NULL, clk_name);
+
+		if (IS_ERR(clk)) {
+			DSSERR("can't get clock %s", clk_name);
+			r = PTR_ERR(clk);
+			goto err;
+		}
+
+		DSSDBG("clk %s, rate %ld\n",
+				clk_name, clk_get_rate(clk));
+
+		*clocks[i].clock = clk;
+	}
+
+	return 0;
+
+err:
+	for (i = 0; i < num_clocks; i++) {
+		if (!IS_ERR(*clocks[i].clock))
+			clk_put(*clocks[i].clock);
+	}
+
+	return r;
+}
+
+static void put_dss_clocks(void)
+{
+	if (dss.dss_96m_fck)
+		clk_put(dss.dss_96m_fck);
+	clk_put(dss.dss_54m_fck);
+	clk_put(dss.dss1_fck);
+	clk_put(dss.dss2_fck);
+	clk_put(dss.dss_ick);
+}
+
+unsigned long dss_clk_get_rate(enum dss_clock clk)
+{
+	switch (clk) {
+	case DSS_CLK_ICK:
+		return clk_get_rate(dss.dss_ick);
+	case DSS_CLK_FCK1:
+		return clk_get_rate(dss.dss1_fck);
+	case DSS_CLK_FCK2:
+		return clk_get_rate(dss.dss2_fck);
+	case DSS_CLK_54M:
+		return clk_get_rate(dss.dss_54m_fck);
+	case DSS_CLK_96M:
+		return clk_get_rate(dss.dss_96m_fck);
+	}
+
+	BUG();
+	return 0;
+}
+
+static unsigned count_clk_bits(enum dss_clock clks)
+{
+	unsigned num_clks = 0;
+
+	if (clks & DSS_CLK_ICK)
+		++num_clks;
+	if (clks & DSS_CLK_FCK1)
+		++num_clks;
+	if (clks & DSS_CLK_FCK2)
+		++num_clks;
+	if (clks & DSS_CLK_54M)
+		++num_clks;
+	if (clks & DSS_CLK_96M)
+		++num_clks;
+
+	return num_clks;
+}
+
+static void dss_clk_enable_no_ctx(enum dss_clock clks)
+{
+	unsigned num_clks = count_clk_bits(clks);
+
+	if (clks & DSS_CLK_ICK)
+		clk_enable(dss.dss_ick);
+	if (clks & DSS_CLK_FCK1)
+		clk_enable(dss.dss1_fck);
+	if (clks & DSS_CLK_FCK2)
+		clk_enable(dss.dss2_fck);
+	if (clks & DSS_CLK_54M)
+		clk_enable(dss.dss_54m_fck);
+	if (clks & DSS_CLK_96M)
+		clk_enable(dss.dss_96m_fck);
+
+	dss.num_clks_enabled += num_clks;
+}
+
+void dss_clk_enable(enum dss_clock clks)
+{
+	dss_clk_enable_no_ctx(clks);
+
+	if (cpu_is_omap34xx()) {
+		int id = dss_get_ctx_id();
+
+		if (id != dss.ctx_id) {
+			DSSDBG("ctx id %u -> id %u\n",
+					dss.ctx_id, id);
+			restore_all_ctx();
+			dss.ctx_id = id;
+		}
+	}
+}
+
+static void dss_clk_disable_no_ctx(enum dss_clock clks)
+{
+	unsigned num_clks = count_clk_bits(clks);
+
+	if (clks & DSS_CLK_ICK)
+		clk_disable(dss.dss_ick);
+	if (clks & DSS_CLK_FCK1)
+		clk_disable(dss.dss1_fck);
+	if (clks & DSS_CLK_FCK2)
+		clk_disable(dss.dss2_fck);
+	if (clks & DSS_CLK_54M)
+		clk_disable(dss.dss_54m_fck);
+	if (clks & DSS_CLK_96M)
+		clk_disable(dss.dss_96m_fck);
+
+	dss.num_clks_enabled -= num_clks;
+}
+
+void dss_clk_disable(enum dss_clock clks)
+{
+	if (cpu_is_omap34xx()) {
+		unsigned num_clks = count_clk_bits(clks);
+
+		BUG_ON(dss.num_clks_enabled < num_clks);
+
+		if (dss.num_clks_enabled == num_clks)
+			save_all_ctx();
+	}
+
+	dss_clk_disable_no_ctx(clks);
+}
+
+static void dss_clk_enable_all_no_ctx(void)
+{
+	enum dss_clock clks;
+
+	clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
+	if (cpu_is_omap34xx())
+		clks |= DSS_CLK_96M;
+	dss_clk_enable_no_ctx(clks);
+}
+
+static void dss_clk_disable_all_no_ctx(void)
+{
+	enum dss_clock clks;
+
+	clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
+	if (cpu_is_omap34xx())
+		clks |= DSS_CLK_96M;
+	dss_clk_disable_no_ctx(clks);
+}
+
+static void dss_clk_disable_all(void)
+{
+	enum dss_clock clks;
+
+	clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
+	if (cpu_is_omap34xx())
+		clks |= DSS_CLK_96M;
+	dss_clk_disable(clks);
+}
+
+void dss_select_clk_source(int dsi, int dispc)
+{
+	u32 r;
+	r = dss_read_reg(DSS_CONTROL);
+	r = FLD_MOD(r, dsi, 1, 1);	/* DSI_CLK_SWITCH */
+	r = FLD_MOD(r, dispc, 0, 0);	/* DISPC_CLK_SWITCH */
+	dss_write_reg(DSS_CONTROL, r);
+}
+
+int dss_get_dsi_clk_source(void)
+{
+	return FLD_GET(dss_read_reg(DSS_CONTROL), 1, 1);
+}
+
+int dss_get_dispc_clk_source(void)
+{
+	return FLD_GET(dss_read_reg(DSS_CONTROL), 0, 0);
+}
+
+static irqreturn_t dss_irq_handler_omap2(int irq, void *arg)
+{
+	dispc_irq_handler();
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t dss_irq_handler_omap3(int irq, void *arg)
+{
+	u32 irqstatus;
+
+	irqstatus = dss_read_reg(DSS_IRQSTATUS);
+
+	if (irqstatus & (1<<0))	/* DISPC_IRQ */
+		dispc_irq_handler();
+#ifdef CONFIG_OMAP2_DSS_DSI
+	if (irqstatus & (1<<1))	/* DSI_IRQ */
+		dsi_irq_handler();
+#endif
+
+	return IRQ_HANDLED;
+}
+
+static int _omap_dss_wait_reset(void)
+{
+	unsigned timeout = 1000;
+
+	while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
+		udelay(1);
+		if (!--timeout) {
+			DSSERR("soft reset failed\n");
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
+static int _omap_dss_reset(void)
+{
+	/* Soft reset */
+	REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
+	return _omap_dss_wait_reset();
+}
+
+void dss_set_venc_output(enum omap_dss_venc_type type)
+{
+	int l = 0;
+
+	if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
+		l = 0;
+	else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
+		l = 1;
+	else
+		BUG();
+
+	/* venc out selection. 0 = comp, 1 = svideo */
+	REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
+}
+
+void dss_set_dac_pwrdn_bgz(int enable)
+{
+	REG_FLD_MOD(DSS_CONTROL, enable, 5, 5);	/* DAC Power-Down Control */
+}
+
+int dss_init(void)
+{
+	int r;
+	u32 rev;
+
+	dss.base = ioremap(DSS_BASE, DSS_SZ_REGS);
+	if (!dss.base) {
+		DSSERR("can't ioremap DSS\n");
+		r = -ENOMEM;
+		goto fail0;
+	}
+
+	/* We need to wait here a bit, otherwise we sometimes start to get
+	 * synclost errors. I believe we could wait for one framedone or
+	 * perhaps vsync interrupt, but, because dispc is not initialized yet,
+	 * we don't have access to the irq register.
+	 */
+	msleep(400);
+
+	_omap_dss_reset();
+
+	/* autoidle */
+	REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
+
+	/* Select DPLL */
+	REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
+
+#ifdef CONFIG_OMAP2_DSS_VENC
+	REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);	/* venc dac demen */
+	REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);	/* venc clock 4x enable */
+	REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);	/* venc clock mode = normal */
+#endif
+
+	r = request_irq(INT_24XX_DSS_IRQ,
+			cpu_is_omap24xx()
+			? dss_irq_handler_omap2
+			: dss_irq_handler_omap3,
+			0, "OMAP DSS", NULL);
+
+	if (r < 0) {
+		DSSERR("omap2 dss: request_irq failed\n");
+		goto fail1;
+	}
+
+	dss_save_context();
+
+	rev = dss_read_reg(DSS_REVISION);
+	printk(KERN_INFO "OMAP DSS rev %d.%d\n",
+			FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+	return 0;
+
+fail1:
+	iounmap(dss.base);
+fail0:
+	return r;
+}
+
+void dss_exit(void)
+{
+	int c;
+
+	free_irq(INT_24XX_DSS_IRQ, NULL);
+
+	/* these should be removed at some point */
+	c = dss.dss_ick->usecount;
+	if (c > 0) {
+		DSSERR("warning: dss_ick usecount %d, disabling\n", c);
+		while (c-- > 0)
+			clk_disable(dss.dss_ick);
+	}
+
+	c = dss.dss1_fck->usecount;
+	if (c > 0) {
+		DSSERR("warning: dss1_fck usecount %d, disabling\n", c);
+		while (c-- > 0)
+			clk_disable(dss.dss1_fck);
+	}
+
+	c = dss.dss2_fck->usecount;
+	if (c > 0) {
+		DSSERR("warning: dss2_fck usecount %d, disabling\n", c);
+		while (c-- > 0)
+			clk_disable(dss.dss2_fck);
+	}
+
+	c = dss.dss_54m_fck->usecount;
+	if (c > 0) {
+		DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c);
+		while (c-- > 0)
+			clk_disable(dss.dss_54m_fck);
+	}
+
+	if (dss.dss_96m_fck) {
+		c = dss.dss_96m_fck->usecount;
+		if (c > 0) {
+			DSSERR("warning: dss_96m_fck usecount %d, disabling\n",
+					c);
+			while (c-- > 0)
+				clk_disable(dss.dss_96m_fck);
+		}
+	}
+
+	put_dss_clocks();
+
+	iounmap(dss.base);
+}
+
+
+
+static int omap_dss_probe(struct platform_device *pdev)
+{
+	struct omap_dss_platform_data *pdata = pdev->dev.platform_data;
+
+	int r;
+
+	dss.pdev = pdev;
+
+	r = get_dss_clocks();
+	if (r)
+		goto fail0;
+
+	dss_clk_enable_all_no_ctx();
+
+	dss.ctx_id = dss_get_ctx_id();
+	DSSDBG("initial ctx id %u\n", dss.ctx_id);
+
+	r = dss_init();
+	if (r) {
+		DSSERR("Failed to initialize DSS\n");
+		goto fail0;
+	}
+
+#ifdef CONFIG_OMAP2_DSS_RFBI
+	r = rfbi_init();
+	if (r) {
+		DSSERR("Failed to initialize rfbi\n");
+		goto fail0;
+	}
+#endif
+
+	r = dpi_init();
+	if (r) {
+		DSSERR("Failed to initialize dpi\n");
+		goto fail0;
+	}
+
+	r = dispc_init();
+	if (r) {
+		DSSERR("Failed to initialize dispc\n");
+		goto fail0;
+	}
+#ifdef CONFIG_OMAP2_DSS_VENC
+	r = venc_init();
+	if (r) {
+		DSSERR("Failed to initialize venc\n");
+		goto fail0;
+	}
+#endif
+	if (cpu_is_omap34xx()) {
+#ifdef CONFIG_OMAP2_DSS_SDI
+		r = sdi_init();
+		if (r) {
+			DSSERR("Failed to initialize SDI\n");
+			goto fail0;
+		}
+#endif
+#ifdef CONFIG_OMAP2_DSS_DSI
+		r = dsi_init();
+		if (r) {
+			DSSERR("Failed to initialize DSI\n");
+			goto fail0;
+		}
+#endif
+	}
+
+	initialize_displays(pdata);
+
+	r = initialize_sysfs(&pdev->dev);
+	if (r)
+		goto fail0;
+
+	initialize_overlays(def_disp_name);
+
+	dss_clk_disable_all();
+
+	return 0;
+
+	/* XXX fail correctly */
+fail0:
+	return r;
+}
+
+static int omap_dss_remove(struct platform_device *pdev)
+{
+	uninitialize_sysfs(&pdev->dev);
+
+#ifdef CONFIG_OMAP2_DSS_VENC
+	venc_exit();
+#endif
+	dispc_exit();
+	dpi_exit();
+#ifdef CONFIG_OMAP2_DSS_RFBI
+	rfbi_exit();
+#endif
+	if (cpu_is_omap34xx()) {
+#ifdef CONFIG_OMAP2_DSS_DSI
+		dsi_exit();
+#endif
+#ifdef CONFIG_OMAP2_DSS_SDI
+		sdi_exit();
+#endif
+	}
+
+	dss_exit();
+
+	return 0;
+}
+
+
+static struct platform_driver omap_dss_driver = {
+	.probe          = omap_dss_probe,
+	.remove         = omap_dss_remove,
+	.driver         = {
+		.name   = "omap-dss",
+		.owner  = THIS_MODULE,
+	},
+};
+
+static int __init omap_dss_init(void)
+{
+	return platform_driver_register(&omap_dss_driver);
+}
+
+static void __exit omap_dss_exit(void)
+{
+	platform_driver_unregister(&omap_dss_driver);
+}
+
+subsys_initcall(omap_dss_init);
+module_exit(omap_dss_exit);
+
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
+MODULE_DESCRIPTION("OMAP2/3 Display Subsystem");
+MODULE_LICENSE("GPL v2");
+
diff --git a/arch/arm/plat-omap/dss/dss.h b/arch/arm/plat-omap/dss/dss.h
new file mode 100644
index 0000000..da628a7
--- /dev/null
+++ b/arch/arm/plat-omap/dss/dss.h
@@ -0,0 +1,274 @@
+/*
+ * linux/arch/arm/plat-omap/dss/dss.h
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OMAP2_DSS_H
+#define __OMAP2_DSS_H
+
+#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT
+#define DEBUG
+#endif
+
+#ifdef DEBUG
+extern unsigned int dss_debug;
+#ifdef DSS_SUBSYS_NAME
+#define DSSDBG(format, ...) \
+	if (dss_debug) \
+		printk(KERN_DEBUG "omap-dss " DSS_SUBSYS_NAME ": " format, \
+		## __VA_ARGS__)
+#else
+#define DSSDBG(format, ...) \
+	if (dss_debug) \
+		printk(KERN_DEBUG "omap-dss: " format, ## __VA_ARGS__)
+#endif
+#else
+#define DSSDBG(format, ...)
+#endif
+
+#ifdef DSS_SUBSYS_NAME
+#define DSSERR(format, ...) \
+	printk(KERN_ERR "omap-dss " DSS_SUBSYS_NAME " error: " format, \
+	## __VA_ARGS__)
+#else
+#define DSSERR(format, ...) \
+	printk(KERN_ERR "omap-dss error: " format, ## __VA_ARGS__)
+#endif
+
+#ifdef DSS_SUBSYS_NAME
+#define DSSINFO(format, ...) \
+	printk(KERN_INFO "omap-dss " DSS_SUBSYS_NAME ": " format, \
+	## __VA_ARGS__)
+#else
+#define DSSINFO(format, ...) \
+	printk(KERN_INFO "omap-dss: " format, ## __VA_ARGS__)
+#endif
+
+#ifdef DSS_SUBSYS_NAME
+#define DSSWARN(format, ...) \
+	printk(KERN_WARNING "omap-dss " DSS_SUBSYS_NAME ": " format, \
+	## __VA_ARGS__)
+#else
+#define DSSWARN(format, ...) \
+	printk(KERN_WARNING "omap-dss: " format, ## __VA_ARGS__)
+#endif
+
+/* OMAP TRM gives bitfields as start:end, where start is the higher bit
+   number. For example 7:0 */
+#define FLD_MASK(start, end)	(((1 << (start - end + 1)) - 1) << (end))
+#define FLD_VAL(val, start, end) (((val) << end) & FLD_MASK(start, end))
+#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
+#define FLD_MOD(orig, val, start, end) \
+	(((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
+
+#define DISPC_MAX_FCK 173000000
+
+enum omap_burst_size {
+	OMAP_DSS_BURST_4x32 = 0,
+	OMAP_DSS_BURST_8x32 = 1,
+	OMAP_DSS_BURST_16x32 = 2,
+};
+
+enum omap_parallel_interface_mode {
+	OMAP_DSS_PARALLELMODE_BYPASS,		/* MIPI DPI */
+	OMAP_DSS_PARALLELMODE_RFBI,		/* MIPI DBI */
+	OMAP_DSS_PARALLELMODE_DSI,
+};
+
+enum dss_clock {
+	DSS_CLK_ICK	= 1 << 0,
+	DSS_CLK_FCK1	= 1 << 1,
+	DSS_CLK_FCK2	= 1 << 2,
+	DSS_CLK_54M	= 1 << 3,
+	DSS_CLK_96M	= 1 << 4,
+};
+
+struct dispc_clock_info {
+	/* rates that we get with dividers below */
+	unsigned long fck;
+	unsigned long lck;
+	unsigned long pck;
+
+	/* dividers */
+	int fck_div;
+	int lck_div;
+	int pck_div;
+};
+
+struct dsi_clock_info {
+	/* rates that we get with dividers below */
+	unsigned long fint;
+	unsigned long dsiphy;
+	unsigned long clkin;	/* input clk for DSI PLL */
+	unsigned long dispc_fck;	/* output clk, DSI1_PLL_FCLK */
+	unsigned long dsi_fck;	/* output clk, DSI2_PLL_FCLK */
+	unsigned long lck;
+	unsigned long pck;
+
+	/* dividers */
+	int regn;
+	int regm;
+	int regm3;
+	int regm4;
+
+	int lck_div;
+	int pck_div;
+
+	int highfreq;
+	int use_dss2_fck;
+};
+
+int initialize_sysfs(struct device *dev);
+void uninitialize_sysfs(struct device *dev);
+void initialize_displays(struct omap_dss_platform_data *pdata);
+void initialize_overlays(const char *def_disp_name);
+
+/* DSS */
+int dss_init(void);
+void dss_exit(void);
+
+void dss_clk_enable(enum dss_clock clks);
+void dss_clk_disable(enum dss_clock clks);
+
+void dss_sdi_init(int datapairs);
+void dss_select_clk_source(int dsi, int dispc);
+int dss_get_dsi_clk_source(void);
+int dss_get_dispc_clk_source(void);
+void dss_set_venc_output(enum omap_dss_venc_type type);
+void dss_set_dac_pwrdn_bgz(int enable);
+unsigned long dss_clk_get_rate(enum dss_clock clk);
+ssize_t dss_print_clocks(char *buf, ssize_t size);
+
+/* SDI */
+int sdi_init(void);
+void sdi_exit(void);
+void sdi_init_display(struct omap_display *display);
+
+
+/* DSI */
+int dsi_init(void);
+void dsi_exit(void);
+
+void dsi_save_context(void);
+void dsi_restore_context(void);
+
+void dsi_init_display(struct omap_display *display);
+void dsi_irq_handler(void);
+unsigned long dsi_get_dsi1_pll_rate(void);
+unsigned long dsi_get_dsi2_pll_rate(void);
+int dsi_pll_calc_pck(int is_tft, unsigned long req_pck,
+		struct dsi_clock_info *cinfo);
+int dsi_pll_program(struct dsi_clock_info *cinfo);
+int dsi_pll_init(int enable_hsclk, int enable_hsdiv);
+void dsi_pll_uninit(void);
+ssize_t dsi_print_clocks(char *buf, ssize_t size);
+
+/* DPI */
+int dpi_init(void);
+void dpi_exit(void);
+void dpi_init_display(struct omap_display *display);
+
+/* DISPC */
+int dispc_init(void);
+void dispc_exit(void);
+void dispc_irq_handler(void);
+void dispc_fake_vsync_irq(void);
+
+void dispc_save_context(void);
+void dispc_restore_context(void);
+
+void dispc_lcd_enable_signal_polarity(int act_high);
+void dispc_lcd_enable_signal(int enable);
+void dispc_pck_free_enable(int enable);
+void dispc_enable_fifohandcheck(int enable);
+
+void dispc_set_lcd_size(int width, int height);
+void dispc_set_digit_size(int width, int height);
+u32 dispc_get_plane_fifo_size(enum omap_plane plane);
+void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high);
+void dispc_set_burst_size(enum omap_plane plane,
+		enum omap_burst_size burst_size);
+
+void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
+void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
+void dispc_set_plane_pos(enum omap_plane plane, int x, int y);
+void dispc_set_plane_size(enum omap_plane plane, int width, int height);
+void dispc_set_row_inc(enum omap_plane plane, int inc);
+
+int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
+		      u32 paddr, int screen_width,
+		      int pos_x, int pos_y,
+		      int width, int height,
+		      int out_width, int out_height,
+		      enum omap_color_mode color_mode,
+		      int ilace);
+
+void dispc_go(enum omap_channel channel);
+void dispc_enable_lcd_out(int enable);
+void dispc_enable_digit_out(int enable);
+int dispc_enable_plane(enum omap_plane plane, int enable);
+
+void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode);
+void dispc_set_tft_data_lines(int data_lines);
+void dispc_set_lcd_display_type(enum omap_lcd_display_type type);
+void dispc_set_loadmode(enum omap_dss_load_mode mode);
+
+void dispc_set_default_color(enum omap_channel channel, u32 color);
+void dispc_set_trans_key(enum omap_channel ch,
+		enum omap_dss_color_key_type type,
+		u32 trans_key);
+void dispc_enable_trans_key(enum omap_channel ch, int enable);
+
+void dispc_set_lcd_timings(struct omap_video_timings *timings);
+unsigned long dispc_fclk_rate(void);
+unsigned long dispc_pclk_rate(void);
+void dispc_set_pol_freq(struct omap_panel *panel);
+void find_lck_pck_divs(int is_tft, unsigned long req_pck, unsigned long fck,
+		int *lck_div, int *pck_div);
+int dispc_calc_clock_div(int is_tft, unsigned long req_pck,
+		struct dispc_clock_info *cinfo);
+int dispc_set_clock_div(struct dispc_clock_info *cinfo);
+void dispc_set_lcd_divisor(int lck_div, int pck_div);
+
+void dispc_setup_partial_planes(struct omap_display *display,
+				int *x, int *y, int *w, int *h);
+void dispc_draw_partial_planes(struct omap_display *display);
+
+
+ssize_t dispc_print_clocks(char *buf, ssize_t size);
+
+/* VENC */
+int venc_init(void);
+void venc_exit(void);
+void venc_init_display(struct omap_display *display);
+
+/* RFBI */
+int rfbi_init(void);
+void rfbi_exit(void);
+
+int rfbi_configure(int rfbi_module, int bpp, int lines);
+void rfbi_enable_rfbi(int enable);
+void rfbi_transfer_area(int width, int height,
+			     void (callback)(void *data), void *data);
+void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
+unsigned long rfbi_get_max_tx_rate(void);
+void rfbi_init_display(struct omap_display *display);
+
+#endif
diff --git a/arch/arm/plat-omap/dss/sdi.c b/arch/arm/plat-omap/dss/sdi.c
new file mode 100644
index 0000000..02d549b
--- /dev/null
+++ b/arch/arm/plat-omap/dss/sdi.c
@@ -0,0 +1,174 @@
+/*
+ * linux/arch/arm/plat-omap/dss/sdi.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "SDI"
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+#include <mach/board.h>
+#include <mach/display.h>
+#include "dss.h"
+
+
+static struct {
+	int update_enabled;
+} sdi;
+
+static int sdi_display_enable(struct omap_display *display)
+{
+	struct dispc_clock_info cinfo;
+	int lck_div, pck_div;
+	unsigned long fck;
+	struct omap_panel *panel = display->panel;
+	unsigned high, low, burst;
+	unsigned long pck;
+
+	if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
+		DSSERR("display already enabled\n");
+		return -EINVAL;
+	}
+
+	panel->enable(display);
+
+	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+	dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
+
+	dispc_set_burst_size(OMAP_DSS_GFX, OMAP_DSS_BURST_16x32);
+	dispc_set_burst_size(OMAP_DSS_VIDEO1, OMAP_DSS_BURST_16x32);
+	dispc_set_burst_size(OMAP_DSS_VIDEO2, OMAP_DSS_BURST_16x32);
+
+	burst = 16 * 32 / 8;
+
+	high = dispc_get_plane_fifo_size(OMAP_DSS_GFX) - burst;
+	low = dispc_get_plane_fifo_size(OMAP_DSS_GFX) / 4 * 3;
+	dispc_setup_plane_fifo(OMAP_DSS_GFX, low, high);
+
+	high = dispc_get_plane_fifo_size(OMAP_DSS_VIDEO1) - burst;
+	low = dispc_get_plane_fifo_size(OMAP_DSS_VIDEO1) / 4 * 3;
+	dispc_setup_plane_fifo(OMAP_DSS_VIDEO1, low, high);
+
+	high = dispc_get_plane_fifo_size(OMAP_DSS_VIDEO2) - burst;
+	low = dispc_get_plane_fifo_size(OMAP_DSS_VIDEO2) / 4 * 3;
+	dispc_setup_plane_fifo(OMAP_DSS_VIDEO2, low, high);
+
+	/* 15.5.9.1.2 */
+	panel->config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
+
+	dispc_set_pol_freq(panel);
+
+	dispc_calc_clock_div(1, panel->timings.pixel_clock * 1000,
+			&cinfo);
+
+	if (dispc_set_clock_div(&cinfo)) {
+		DSSERR("Failed to set DSS clocks\n");
+		return -EINVAL;
+	}
+
+	fck = cinfo.fck;
+	lck_div = cinfo.lck_div;
+	pck_div = cinfo.pck_div;
+
+	pck = fck / lck_div / pck_div / 1000;
+
+	if (pck != panel->timings.pixel_clock) {
+		DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
+				"got %lu kHz\n",
+				panel->timings.pixel_clock, pck);
+
+		panel->timings.pixel_clock = pck;
+	}
+
+	dispc_set_lcd_timings(&panel->timings);
+
+	dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
+	dispc_set_tft_data_lines(24);
+	dispc_lcd_enable_signal_polarity(1);
+	dispc_pck_free_enable(1);
+
+	dss_sdi_init(display->hw_config.u.sdi.datapairs);
+
+	mdelay(2);
+
+	dispc_enable_lcd_out(1);
+
+	display->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	return 0;
+}
+
+static void sdi_display_disable(struct omap_display *display)
+{
+	if (display->state == OMAP_DSS_DISPLAY_DISABLED)
+		return;
+
+	display->panel->disable(display);
+	dispc_enable_lcd_out(0);
+
+	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+	display->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static int sdi_display_set_update_mode(struct omap_display *display,
+		enum omap_dss_update_mode mode)
+{
+	if (mode == OMAP_DSS_UPDATE_MANUAL)
+		return -EINVAL;
+
+	if (mode == OMAP_DSS_UPDATE_DISABLED) {
+		dispc_enable_lcd_out(0);
+		sdi.update_enabled = 0;
+	} else {
+		dispc_enable_lcd_out(1);
+		sdi.update_enabled = 1;
+	}
+
+	return 0;
+}
+
+static enum omap_dss_update_mode sdi_display_get_update_mode(
+		struct omap_display *display)
+{
+	return sdi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
+		OMAP_DSS_UPDATE_DISABLED;
+}
+
+
+void sdi_init_display(struct omap_display *display)
+{
+	DSSDBG("SDI init\n");
+
+	display->enable = sdi_display_enable;
+	display->disable = sdi_display_disable;
+	display->set_update_mode = sdi_display_set_update_mode;
+	display->get_update_mode = sdi_display_get_update_mode;
+}
+
+int sdi_init(void)
+{
+	return 0;
+}
+
+void sdi_exit(void)
+{
+}
diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
new file mode 100644
index 0000000..49ab00a
--- /dev/null
+++ b/arch/arm/plat-omap/include/mach/display.h
@@ -0,0 +1,462 @@
+/*
+ * linux/include/asm-arm/arch-omap/display.h
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_ARCH_OMAP_DISPLAY_H
+#define __ASM_ARCH_OMAP_DISPLAY_H
+
+#include <asm/atomic.h>
+
+#define DISPC_IRQ_FRAMEDONE		(1 << 0)
+#define DISPC_IRQ_VSYNC			(1 << 1)
+#define DISPC_IRQ_EVSYNC_EVEN		(1 << 2)
+#define DISPC_IRQ_EVSYNC_ODD		(1 << 3)
+#define DISPC_IRQ_ACBIAS_COUNT_STAT	(1 << 4)
+#define DISPC_IRQ_PROG_LINE_NUM		(1 << 5)
+#define DISPC_IRQ_GFX_FIFO_UNDERFLOW	(1 << 6)
+#define DISPC_IRQ_GFX_END_WIN		(1 << 7)
+#define DISPC_IRQ_PAL_GAMMA_MASK	(1 << 8)
+#define DISPC_IRQ_OCP_ERR		(1 << 9)
+#define DISPC_IRQ_VID1_FIFO_UNDERFLOW	(1 << 10)
+#define DISPC_IRQ_VID1_END_WIN		(1 << 11)
+#define DISPC_IRQ_VID2_FIFO_UNDERFLOW	(1 << 12)
+#define DISPC_IRQ_VID2_END_WIN		(1 << 13)
+#define DISPC_IRQ_SYNC_LOST		(1 << 14)
+#define DISPC_IRQ_SYNC_LOST_DIGIT	(1 << 15)
+
+enum omap_display_type {
+	OMAP_DISPLAY_TYPE_NONE		= 0,
+	OMAP_DISPLAY_TYPE_DPI		= 1 << 0,
+	OMAP_DISPLAY_TYPE_DBI		= 1 << 1,
+	OMAP_DISPLAY_TYPE_SDI		= 1 << 2,
+	OMAP_DISPLAY_TYPE_DSI		= 1 << 3,
+	OMAP_DISPLAY_TYPE_VENC		= 1 << 4,
+};
+
+enum omap_plane {
+	OMAP_DSS_GFX	= 0,
+	OMAP_DSS_VIDEO1	= 1,
+	OMAP_DSS_VIDEO2	= 2
+};
+
+enum omap_channel {
+	OMAP_DSS_CHANNEL_LCD	= 0,
+	OMAP_DSS_CHANNEL_DIGIT	= 1,
+};
+
+enum omap_color_mode {
+	OMAP_DSS_COLOR_CLUT1	= 1 << 0,  /* BITMAP 1 */
+	OMAP_DSS_COLOR_CLUT2	= 1 << 1,  /* BITMAP 2 */
+	OMAP_DSS_COLOR_CLUT4	= 1 << 2,  /* BITMAP 4 */
+	OMAP_DSS_COLOR_CLUT8	= 1 << 3,  /* BITMAP 8 */
+	OMAP_DSS_COLOR_RGB12U	= 1 << 4,  /* RGB12, 16-bit container */
+	OMAP_DSS_COLOR_ARGB16	= 1 << 5,  /* ARGB16 */
+	OMAP_DSS_COLOR_RGB16	= 1 << 6,  /* RGB16 */
+	OMAP_DSS_COLOR_RGB24U	= 1 << 7,  /* RGB24, 32-bit container */
+	OMAP_DSS_COLOR_RGB24P	= 1 << 8,  /* RGB24, 24-bit container */
+	OMAP_DSS_COLOR_YUV2	= 1 << 9,  /* YUV2 4:2:2 co-sited */
+	OMAP_DSS_COLOR_UYVY	= 1 << 10, /* UYVY 4:2:2 co-sited */
+	OMAP_DSS_COLOR_ARGB32	= 1 << 11, /* ARGB32 */
+	OMAP_DSS_COLOR_RGBA32	= 1 << 12, /* RGBA32 */
+	OMAP_DSS_COLOR_RGBX32	= 1 << 13, /* RGBx32 */
+
+	OMAP_DSS_COLOR_GFX_OMAP3 =
+		OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
+		OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
+		OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
+		OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+		OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
+		OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
+
+	OMAP_DSS_COLOR_VID_OMAP3 =
+		OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
+		OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+		OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
+		OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 |
+		OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
+};
+
+enum omap_lcd_display_type {
+	OMAP_DSS_LCD_DISPLAY_STN,
+	OMAP_DSS_LCD_DISPLAY_TFT,
+};
+
+enum omap_dss_load_mode {
+	OMAP_DSS_LOAD_CLUT_AND_FRAME	= 0,
+	OMAP_DSS_LOAD_CLUT_ONLY		= 1,
+	OMAP_DSS_LOAD_FRAME_ONLY	= 2,
+	OMAP_DSS_LOAD_CLUT_ONCE_FRAME	= 3,
+};
+
+enum omap_dss_color_key_type {
+	OMAP_DSS_COLOR_KEY_GFX_DST = 0,
+	OMAP_DSS_COLOR_KEY_VID_SRC = 1,
+};
+
+enum omap_rfbi_te_mode {
+	OMAP_DSS_RFBI_TE_MODE_1 = 1,
+	OMAP_DSS_RFBI_TE_MODE_2 = 2,
+};
+
+enum omap_panel_config {
+	OMAP_DSS_LCD_IVS		= 1<<0,
+	OMAP_DSS_LCD_IHS		= 1<<1,
+	OMAP_DSS_LCD_IPC		= 1<<2,
+	OMAP_DSS_LCD_IEO		= 1<<3,
+	OMAP_DSS_LCD_RF			= 1<<4,
+	OMAP_DSS_LCD_ONOFF		= 1<<5,
+
+	OMAP_DSS_LCD_TFT		= 1<<20,
+};
+
+enum omap_dss_venc_type {
+	OMAP_DSS_VENC_TYPE_COMPOSITE,
+	OMAP_DSS_VENC_TYPE_SVIDEO,
+};
+
+struct omap_display;
+struct omap_panel;
+struct omap_ctrl;
+
+/* RFBI */
+
+struct rfbi_timings {
+	int cs_on_time;
+	int cs_off_time;
+	int we_on_time;
+	int we_off_time;
+	int re_on_time;
+	int re_off_time;
+	int we_cycle_time;
+	int re_cycle_time;
+	int cs_pulse_width;
+	int access_time;
+
+	int clk_div;
+
+	u32 tim[5];             /* set by rfbi_convert_timings() */
+
+	int converted;
+};
+
+void omap_rfbi_write_command(const void *buf, u32 len);
+void omap_rfbi_read_data(void *buf, u32 len);
+void omap_rfbi_write_data(const void *buf, u32 len);
+void omap_rfbi_write_pixels(const void *buf, int scr_width, int x, int y,
+			    int w, int h);
+int omap_rfbi_enable_te(int enable, unsigned line);
+int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
+			     unsigned hs_pulse_time, unsigned vs_pulse_time,
+			     int hs_pol_inv, int vs_pol_inv, int extif_div);
+
+/* DSI */
+int dsi_vc_dcs_write(int channel, u8 *data, int len);
+int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len);
+int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen);
+int dsi_vc_set_max_rx_packet_size(int channel, u16 len);
+int dsi_vc_send_null(int channel);
+
+/* Board specific data */
+struct omap_display_data {
+	enum omap_display_type type;
+
+	union {
+		struct {
+			int data_lines;
+		} dpi;
+
+		struct {
+			int channel;
+			int data_lines;
+		} rfbi;
+
+		struct {
+			int datapairs;
+		} sdi;
+
+		struct {
+			int clk_lane;
+			int clk_pol;
+			int data1_lane;
+			int data1_pol;
+			int data2_lane;
+			int data2_pol;
+			unsigned long ddr_clk_hz;
+		} dsi;
+
+		struct {
+			enum omap_dss_venc_type type;
+		} venc;
+	} u;
+
+	int panel_reset_gpio;
+	int ctrl_reset_gpio;
+
+	const char *name;		/* for debug */
+	const char *ctrl_name;
+	const char *panel_name;
+
+	void *priv;
+
+	/* platform specific enable/disable */
+	int (*panel_enable)(struct omap_display *display);
+	void (*panel_disable)(struct omap_display *display);
+	int (*ctrl_enable)(struct omap_display *display);
+	void (*ctrl_disable)(struct omap_display *display);
+	int (*set_backlight)(struct omap_display *display,
+			int level);
+};
+
+struct device;
+
+/* Board specific data */
+struct omap_dss_platform_data {
+	unsigned (*get_last_off_on_transaction_id)(struct device *dev);
+	int num_displays;
+	struct omap_display_data *displays[];
+};
+
+struct omap_ctrl {
+	struct module *owner;
+
+	const char *name;
+
+	int (*init)(struct omap_display *display);
+	void (*cleanup)(struct omap_display *display);
+	int (*enable)(struct omap_display *display);
+	void (*disable)(struct omap_display *display);
+	int (*suspend)(struct omap_display *display);
+	int (*resume)(struct omap_display *display);
+	void (*setup_update)(struct omap_display *display,
+			     int x, int y, int w, int h);
+
+	int (*enable_te)(struct omap_display *display, int enable);
+
+	int (*rotate)(struct omap_display *display, int rotate);
+	int (*mirror)(struct omap_display *display, int enable);
+
+	int (*run_test)(struct omap_display *display, int test);
+
+	int pixel_size;
+
+	struct rfbi_timings timings;
+
+	void *priv;
+};
+
+struct omap_video_timings {
+	/* Unit: pixels */
+	u16 x_res;
+	/* Unit: pixels */
+	u16 y_res;
+	/* Unit: KHz */
+	u32 pixel_clock;
+	/* Unit: pixel clocks */
+	u16 hsw;	/* Horizontal synchronization pulse width */
+	/* Unit: pixel clocks */
+	u16 hfp;	/* Horizontal front porch */
+	/* Unit: pixel clocks */
+	u16 hbp;	/* Horizontal back porch */
+	/* Unit: line clocks */
+	u16 vsw;	/* Vertical synchronization pulse width */
+	/* Unit: line clocks */
+	u16 vfp;	/* Vertical front porch */
+	/* Unit: line clocks */
+	u16 vbp;	/* Vertical back porch */
+
+};
+
+struct omap_panel {
+	struct module *owner;
+
+	const char *name;
+
+	int (*init)(struct omap_display *display);
+	void (*cleanup)(struct omap_display *display);
+	int (*remove)(struct omap_display *display);
+	int (*enable)(struct omap_display *display);
+	void (*disable)(struct omap_display *display);
+	int (*suspend)(struct omap_display *display);
+	int (*resume)(struct omap_display *display);
+	int (*run_test)(struct omap_display *display, int test);
+
+	struct omap_video_timings timings;
+
+	int acbi;	/* ac-bias pin transitions per interrupt */
+	/* Unit: line clocks */
+	int acb;	/* ac-bias pin frequency */
+
+	enum omap_panel_config config;
+
+	int bpp;
+
+	void *priv;
+};
+
+/* XXX perhaps this should be removed */
+enum omap_dss_overlay_managers {
+	OMAP_DSS_OVL_MGR_LCD,
+	OMAP_DSS_OVL_MGR_TV,
+};
+
+struct omap_overlay_manager;
+
+struct omap_overlay_info {
+	int enabled;
+	u32 paddr;
+	void *vaddr;
+	int screen_width;
+	int pos_x;
+	int pos_y;
+	int width;
+	int height;
+	int out_width;	/* if 0, out_width == width */
+	int out_height;	/* if 0, out_height == height */
+	enum omap_color_mode color_mode;
+};
+
+enum omap_overlay_caps {
+	OMAP_DSS_OVL_CAP_SCALE = 1 << 0,
+};
+
+struct omap_overlay {
+
+	const char *name;
+	int id;
+	struct omap_overlay_manager *manager;
+	enum omap_color_mode supported_modes;
+	struct omap_overlay_info info;
+	enum omap_overlay_caps caps;
+
+	int (*set_manager)(struct omap_overlay *ovl,
+		struct omap_overlay_manager *mgr);
+	int (*unset_manager)(struct omap_overlay *ovl);
+
+	int (*setup_input)(struct omap_overlay *ovl,
+			u32 paddr, void *vaddr,
+			int screen_width,
+			int width, int height,
+			enum omap_color_mode color_mode);
+	int (*setup_output)(struct omap_overlay *ovl,
+			int pos_x, int pos_y,
+			int out_width, int out_height);
+	int (*enable)(struct omap_overlay *ovl, int enable);
+};
+
+enum omap_overlay_manager_caps {
+	OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0,
+};
+
+struct omap_overlay_manager {
+
+	const char *name;
+	int id;
+	enum omap_overlay_manager_caps caps;
+	struct omap_display *display;
+	int num_overlays;
+	struct omap_overlay *overlays;
+	enum omap_display_type supported_displays;
+
+	int (*set_display)(struct omap_overlay_manager *mgr,
+		struct omap_display *display);
+	int (*unset_display)(struct omap_overlay_manager *mgr);
+
+	int (*apply)(struct omap_overlay_manager *mgr);
+};
+
+enum omap_display_caps {
+	OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0,
+};
+
+enum omap_dss_update_mode {
+	OMAP_DSS_UPDATE_DISABLED = 0,
+	OMAP_DSS_UPDATE_AUTO,
+	OMAP_DSS_UPDATE_MANUAL,
+};
+
+enum omap_dss_display_state {
+	OMAP_DSS_DISPLAY_DISABLED = 0,
+	OMAP_DSS_DISPLAY_ACTIVE,
+	OMAP_DSS_DISPLAY_SUSPENDED,
+};
+
+struct omap_display {
+	/*atomic_t ref_count;*/
+	int ref_count;
+
+	enum omap_display_type type;
+	const char *name;
+
+	enum omap_display_caps caps;
+
+	struct omap_overlay_manager *manager;
+
+	enum omap_dss_display_state state;
+
+	struct omap_display_data hw_config;	/* board specific data */
+	struct omap_ctrl *ctrl;			/* static common data */
+	struct omap_panel *panel;		/* static common data */
+
+	int (*enable)(struct omap_display *display);
+	void (*disable)(struct omap_display *display);
+
+	int (*suspend)(struct omap_display *display);
+	int (*resume)(struct omap_display *display);
+
+	int (*check_timings)(struct omap_display *display,
+			struct omap_video_timings *timings);
+	void (*set_timings)(struct omap_display *display,
+			struct omap_video_timings *timings);
+	void (*get_timings)(struct omap_display *display,
+			struct omap_video_timings *timings);
+	int (*update)(struct omap_display *display,
+			       int x, int y, int w, int h);
+	int (*sync)(struct omap_display *display);
+
+	int (*set_update_mode)(struct omap_display *display,
+			enum omap_dss_update_mode);
+	enum omap_dss_update_mode (*get_update_mode)
+		(struct omap_display *display);
+
+	int (*enable_te)(struct omap_display *display, int enable);
+	int (*get_te)(struct omap_display *display);
+
+	int (*run_test)(struct omap_display *display, int test);
+};
+
+int omap_dss_get_num_displays(void);
+struct omap_display *omap_dss_get_display(int no);
+void omap_dss_put_display(struct omap_display *display);
+
+void omap_dss_register_ctrl(struct omap_ctrl *ctrl);
+void omap_dss_unregister_ctrl(struct omap_ctrl *ctrl);
+
+void omap_dss_register_panel(struct omap_panel *panel);
+void omap_dss_unregister_panel(struct omap_panel *panel);
+
+int omap_dss_get_num_overlay_managers(void);
+struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
+
+int omap_dss_get_num_overlays(void);
+struct omap_overlay *omap_dss_get_overlay(int num);
+
+typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
+int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
+int omap_dispc_unregister_isr(omap_dispc_isr_t isr);
+
+#endif


------------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It is the best place to buy or sell services for
just about anything Open Source.
http://p.sf.net/sfu/Xq1LFB

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 03/12] DSS: RFBI support
  2009-01-12 11:47 [PATCH 00/12] DSS: Series description Tomi Valkeinen
  2009-01-12 11:47 ` [PATCH 01/12] DSS: Documentation for DSS2 Tomi Valkeinen
  2009-01-12 11:47 ` [PATCH 02/12] DSS: Display subsystem for OMAP2/3 Tomi Valkeinen
@ 2009-01-12 11:47 ` Tomi Valkeinen
  2009-01-12 13:03   ` Tony Lindgren
  2009-01-12 11:47 ` [PATCH 04/12] DSS: VENC support Tomi Valkeinen
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 23+ messages in thread
From: Tomi Valkeinen @ 2009-01-12 11:47 UTC (permalink / raw)
  To: linux-fbdev-devel; +Cc: linux-omap

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
---

 arch/arm/plat-omap/dss/rfbi.c | 1262 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1262 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-omap/dss/rfbi.c

diff --git a/arch/arm/plat-omap/dss/rfbi.c b/arch/arm/plat-omap/dss/rfbi.c
new file mode 100644
index 0000000..b4b65e6
--- /dev/null
+++ b/arch/arm/plat-omap/dss/rfbi.c
@@ -0,0 +1,1262 @@
+/*
+ * linux/arch/arm/plat-omap/dss/rfbi.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "RFBI"
+
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/kfifo.h>
+#include <linux/ktime.h>
+#include <linux/hrtimer.h>
+
+#include <mach/board.h>
+#include <mach/display.h>
+#include "dss.h"
+
+/*#define MEASURE_PERF*/
+
+#define RFBI_BASE               0x48050800
+
+struct rfbi_reg { u16 idx; };
+
+#define RFBI_REG(idx)		((const struct rfbi_reg) { idx })
+
+#define RFBI_REVISION		RFBI_REG(0x0000)
+#define RFBI_SYSCONFIG		RFBI_REG(0x0010)
+#define RFBI_SYSSTATUS		RFBI_REG(0x0014)
+#define RFBI_CONTROL		RFBI_REG(0x0040)
+#define RFBI_PIXEL_CNT		RFBI_REG(0x0044)
+#define RFBI_LINE_NUMBER	RFBI_REG(0x0048)
+#define RFBI_CMD		RFBI_REG(0x004c)
+#define RFBI_PARAM		RFBI_REG(0x0050)
+#define RFBI_DATA		RFBI_REG(0x0054)
+#define RFBI_READ		RFBI_REG(0x0058)
+#define RFBI_STATUS		RFBI_REG(0x005c)
+
+#define RFBI_CONFIG(n)		RFBI_REG(0x0060 + (n)*0x18)
+#define RFBI_ONOFF_TIME(n)	RFBI_REG(0x0064 + (n)*0x18)
+#define RFBI_CYCLE_TIME(n)	RFBI_REG(0x0068 + (n)*0x18)
+#define RFBI_DATA_CYCLE1(n)	RFBI_REG(0x006c + (n)*0x18)
+#define RFBI_DATA_CYCLE2(n)	RFBI_REG(0x0070 + (n)*0x18)
+#define RFBI_DATA_CYCLE3(n)	RFBI_REG(0x0074 + (n)*0x18)
+
+#define RFBI_VSYNC_WIDTH	RFBI_REG(0x0090)
+#define RFBI_HSYNC_WIDTH	RFBI_REG(0x0094)
+
+#define RFBI_CMD_FIFO_LEN_BYTES (16 * sizeof(struct update_param))
+
+#define REG_FLD_MOD(idx, val, start, end) \
+	rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
+
+/* To work around an RFBI transfer rate limitation */
+#define OMAP_RFBI_RATE_LIMIT    1
+
+enum omap_rfbi_cycleformat {
+	OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0,
+	OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1,
+	OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2,
+	OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3,
+};
+
+enum omap_rfbi_datatype {
+	OMAP_DSS_RFBI_DATATYPE_12 = 0,
+	OMAP_DSS_RFBI_DATATYPE_16 = 1,
+	OMAP_DSS_RFBI_DATATYPE_18 = 2,
+	OMAP_DSS_RFBI_DATATYPE_24 = 3,
+};
+
+enum omap_rfbi_parallelmode {
+	OMAP_DSS_RFBI_PARALLELMODE_8 = 0,
+	OMAP_DSS_RFBI_PARALLELMODE_9 = 1,
+	OMAP_DSS_RFBI_PARALLELMODE_12 = 2,
+	OMAP_DSS_RFBI_PARALLELMODE_16 = 3,
+};
+
+enum update_cmd {
+	RFBI_CMD_UPDATE = 0,
+	RFBI_CMD_SYNC   = 1,
+};
+
+static int rfbi_convert_timings(struct rfbi_timings *t);
+static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
+static void process_cmd_fifo(void);
+
+static struct {
+	void __iomem	*base;
+
+	unsigned long	l4_khz;
+
+	enum omap_rfbi_datatype datatype;
+	enum omap_rfbi_parallelmode parallelmode;
+
+	enum omap_rfbi_te_mode te_mode;
+	int te_enabled;
+
+	void (*framedone_callback)(void *data);
+	void *framedone_callback_data;
+
+	struct omap_display *display[2];
+
+	struct kfifo      *cmd_fifo;
+	spinlock_t        cmd_lock;
+	struct completion cmd_done;
+	atomic_t          cmd_fifo_full;
+	atomic_t          cmd_pending;
+#ifdef MEASURE_PERF
+	unsigned perf_bytes;
+	ktime_t perf_setup_time;
+	ktime_t perf_start_time;
+#endif
+} rfbi;
+
+struct update_region {
+	u16	x;
+	u16     y;
+	u16     w;
+	u16     h;
+};
+
+struct update_param {
+	u8 rfbi_module;
+	u8 cmd;
+
+	union {
+		struct update_region r;
+		struct completion *sync;
+	} par;
+};
+
+static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
+{
+	__raw_writel(val, rfbi.base + idx.idx);
+}
+
+static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
+{
+	return __raw_readl(rfbi.base + idx.idx);
+}
+
+static void rfbi_enable_clocks(int enable)
+{
+	if (enable)
+		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+	else
+		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+}
+
+void omap_rfbi_write_command(const void *buf, u32 len)
+{
+	rfbi_enable_clocks(1);
+	switch (rfbi.parallelmode) {
+	case OMAP_DSS_RFBI_PARALLELMODE_8:
+	{
+		const u8 *b = buf;
+		for (; len; len--)
+			rfbi_write_reg(RFBI_CMD, *b++);
+		break;
+	}
+
+	case OMAP_DSS_RFBI_PARALLELMODE_16:
+	{
+		const u16 *w = buf;
+		BUG_ON(len & 1);
+		for (; len; len -= 2)
+			rfbi_write_reg(RFBI_CMD, *w++);
+		break;
+	}
+
+	case OMAP_DSS_RFBI_PARALLELMODE_9:
+	case OMAP_DSS_RFBI_PARALLELMODE_12:
+	default:
+		BUG();
+	}
+	rfbi_enable_clocks(0);
+}
+EXPORT_SYMBOL(omap_rfbi_write_command);
+
+void omap_rfbi_read_data(void *buf, u32 len)
+{
+	rfbi_enable_clocks(1);
+	switch (rfbi.parallelmode) {
+	case OMAP_DSS_RFBI_PARALLELMODE_8:
+	{
+		u8 *b = buf;
+		for (; len; len--) {
+			rfbi_write_reg(RFBI_READ, 0);
+			*b++ = rfbi_read_reg(RFBI_READ);
+		}
+		break;
+	}
+
+	case OMAP_DSS_RFBI_PARALLELMODE_16:
+	{
+		u16 *w = buf;
+		BUG_ON(len & ~1);
+		for (; len; len -= 2) {
+			rfbi_write_reg(RFBI_READ, 0);
+			*w++ = rfbi_read_reg(RFBI_READ);
+		}
+		break;
+	}
+
+	case OMAP_DSS_RFBI_PARALLELMODE_9:
+	case OMAP_DSS_RFBI_PARALLELMODE_12:
+	default:
+		BUG();
+	}
+	rfbi_enable_clocks(0);
+}
+EXPORT_SYMBOL(omap_rfbi_read_data);
+
+void omap_rfbi_write_data(const void *buf, u32 len)
+{
+	rfbi_enable_clocks(1);
+	switch (rfbi.parallelmode) {
+	case OMAP_DSS_RFBI_PARALLELMODE_8:
+	{
+		const u8 *b = buf;
+		for (; len; len--)
+			rfbi_write_reg(RFBI_PARAM, *b++);
+		break;
+	}
+
+	case OMAP_DSS_RFBI_PARALLELMODE_16:
+	{
+		const u16 *w = buf;
+		BUG_ON(len & 1);
+		for (; len; len -= 2)
+			rfbi_write_reg(RFBI_PARAM, *w++);
+		break;
+	}
+
+	case OMAP_DSS_RFBI_PARALLELMODE_9:
+	case OMAP_DSS_RFBI_PARALLELMODE_12:
+	default:
+		BUG();
+
+	}
+	rfbi_enable_clocks(0);
+}
+EXPORT_SYMBOL(omap_rfbi_write_data);
+
+void omap_rfbi_write_pixels(const void *buf, int scr_width, int x, int y,
+			    int w, int h)
+{
+	int start_offset = scr_width * y + x;
+	int horiz_offset = scr_width - w;
+	int i;
+
+	rfbi_enable_clocks(1);
+
+	if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
+	   rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
+		const u16 *pd = buf;
+		pd += start_offset;
+
+		for (; h; --h) {
+			for (i = 0; i < w; ++i) {
+				const u8 *b = (const u8 *)pd;
+				rfbi_write_reg(RFBI_PARAM, *(b+1));
+				rfbi_write_reg(RFBI_PARAM, *(b+0));
+				++pd;
+			}
+			pd += horiz_offset;
+		}
+	} else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 &&
+	   rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
+		const u32 *pd = buf;
+		pd += start_offset;
+
+		for (; h; --h) {
+			for (i = 0; i < w; ++i) {
+				const u8 *b = (const u8 *)pd;
+				rfbi_write_reg(RFBI_PARAM, *(b+2));
+				rfbi_write_reg(RFBI_PARAM, *(b+1));
+				rfbi_write_reg(RFBI_PARAM, *(b+0));
+				++pd;
+			}
+			pd += horiz_offset;
+		}
+	} else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
+	   rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) {
+		const u16 *pd = buf;
+		pd += start_offset;
+
+		for (; h; --h) {
+			for (i = 0; i < w; ++i) {
+				rfbi_write_reg(RFBI_PARAM, *pd);
+				++pd;
+			}
+			pd += horiz_offset;
+		}
+	} else {
+		BUG();
+	}
+
+	rfbi_enable_clocks(0);
+}
+EXPORT_SYMBOL(omap_rfbi_write_pixels);
+
+#ifdef MEASURE_PERF
+static void perf_mark_setup(void)
+{
+	rfbi.perf_setup_time = ktime_get();
+}
+
+static void perf_mark_start(void)
+{
+	rfbi.perf_start_time = ktime_get();
+}
+
+static void perf_show(const char *name)
+{
+	ktime_t t, setup_time, trans_time;
+	u32 total_bytes;
+	u32 setup_us, trans_us, total_us;
+
+	t = ktime_get();
+
+	setup_time = ktime_sub(rfbi.perf_start_time, rfbi.perf_setup_time);
+	setup_us = (u32)ktime_to_us(setup_time);
+	if (setup_us == 0)
+		setup_us = 1;
+
+	trans_time = ktime_sub(t, rfbi.perf_start_time);
+	trans_us = (u32)ktime_to_us(trans_time);
+	if (trans_us == 0)
+		trans_us = 1;
+
+	total_us = setup_us + trans_us;
+
+	total_bytes = rfbi.perf_bytes;
+
+	DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, "
+			"%u kbytes/sec\n",
+			name,
+			setup_us,
+			trans_us,
+			total_us,
+			1000*1000 / total_us,
+			total_bytes,
+			total_bytes * 1000 / total_us);
+}
+#else
+#define perf_mark_setup()
+#define perf_mark_start()
+#define perf_show(x)
+#endif
+
+void rfbi_transfer_area(int width, int height,
+			     void (callback)(void *data), void *data)
+{
+	u32 l;
+
+	/*BUG_ON(callback == 0);*/
+	BUG_ON(rfbi.framedone_callback != NULL);
+
+	DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
+
+	dispc_set_lcd_size(width, height);
+
+	dispc_enable_lcd_out(1);
+
+	rfbi.framedone_callback = callback;
+	rfbi.framedone_callback_data = data;
+
+	rfbi_enable_clocks(1);
+
+	rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
+
+	l = rfbi_read_reg(RFBI_CONTROL);
+	l = FLD_MOD(l, 1, 0, 0); /* enable */
+	if (!rfbi.te_enabled)
+		l = FLD_MOD(l, 1, 4, 4); /* ITE */
+
+	perf_mark_start();
+
+	rfbi_write_reg(RFBI_CONTROL, l);
+}
+
+static void framedone_callback(void *data, u32 mask)
+{
+	void (*callback)(void *data);
+
+	DSSDBG("FRAMEDONE\n");
+
+	perf_show("DISPC");
+
+	REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0);
+
+	rfbi_enable_clocks(0);
+
+	callback = rfbi.framedone_callback;
+	rfbi.framedone_callback = NULL;
+
+	/*callback(rfbi.framedone_callback_data);*/
+
+	atomic_set(&rfbi.cmd_pending, 0);
+
+	process_cmd_fifo();
+}
+
+#if 1 /* VERBOSE */
+static void rfbi_print_timings(void)
+{
+	u32 l;
+	u32 time;
+
+	l = rfbi_read_reg(RFBI_CONFIG(0));
+	time = 1000000000 / rfbi.l4_khz;
+	if (l & (1 << 4))
+		time *= 2;
+
+	DSSDBG("Tick time %u ps\n", time);
+	l = rfbi_read_reg(RFBI_ONOFF_TIME(0));
+	DSSDBG("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_TIME(0));
+	DSSDBG("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) {}
+#endif
+
+
+
+
+static u32 extif_clk_period;
+
+static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
+{
+	int bus_tick = extif_clk_period * div;
+	return (ps + bus_tick - 1) / bus_tick * bus_tick;
+}
+
+static int calc_reg_timing(struct rfbi_timings *t, int div)
+{
+	t->clk_div = div;
+
+	t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div);
+
+	t->we_on_time = round_to_extif_ticks(t->we_on_time, div);
+	t->we_off_time = round_to_extif_ticks(t->we_off_time, div);
+	t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div);
+
+	t->re_on_time = round_to_extif_ticks(t->re_on_time, div);
+	t->re_off_time = round_to_extif_ticks(t->re_off_time, div);
+	t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div);
+
+	t->access_time = round_to_extif_ticks(t->access_time, div);
+	t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div);
+	t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div);
+
+	DSSDBG("[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);
+	DSSDBG("[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);
+	DSSDBG("[reg]rdaccess %d cspulse %d\n",
+	       t->access_time, t->cs_pulse_width);
+
+	return rfbi_convert_timings(t);
+}
+
+static int calc_extif_timings(struct rfbi_timings *t)
+{
+	u32 max_clk_div;
+	int div;
+
+	rfbi_get_clk_info(&extif_clk_period, &max_clk_div);
+	for (div = 1; div <= max_clk_div; div++) {
+		if (calc_reg_timing(t, div) == 0)
+			break;
+	}
+
+	if (div <= max_clk_div)
+		return 0;
+
+	DSSERR("can't setup timings\n");
+	return -1;
+}
+
+
+void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
+{
+	int r;
+
+	if (!t->converted) {
+		r = calc_extif_timings(t);
+		if (r < 0)
+			DSSERR("Failed to calc timings\n");
+	}
+
+	BUG_ON(!t->converted);
+
+	rfbi_enable_clocks(1);
+	rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]);
+	rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]);
+
+	/* TIMEGRANULARITY */
+	REG_FLD_MOD(RFBI_CONFIG(rfbi_module),
+		    (t->tim[2] ? 1 : 0), 4, 4);
+
+	rfbi_print_timings();
+	rfbi_enable_clocks(0);
+}
+
+static int ps_to_rfbi_ticks(int time, int div)
+{
+	unsigned long tick_ps;
+	int ret;
+
+	/* Calculate in picosecs to yield more exact results */
+	tick_ps = 1000000000 / (rfbi.l4_khz) * div;
+
+	ret = (time + tick_ps - 1) / tick_ps;
+
+	return ret;
+}
+
+#ifdef OMAP_RFBI_RATE_LIMIT
+unsigned long rfbi_get_max_tx_rate(void)
+{
+	unsigned long   l4_rate, dss1_rate;
+	int             min_l4_ticks = 0;
+	int             i;
+
+	/* According to TI this can't be calculated so make the
+	 * adjustments for a couple of known frequencies and warn for
+	 * others.
+	 */
+	static const struct {
+		unsigned long l4_clk;           /* HZ */
+		unsigned long dss1_clk;         /* HZ */
+		unsigned long min_l4_ticks;
+	} ftab[] = {
+		{ 55,   132,    7, },           /* 7.86 MPix/s */
+		{ 110,  110,    12, },          /* 9.16 MPix/s */
+		{ 110,  132,    10, },          /* 11   Mpix/s */
+		{ 120,  120,    10, },          /* 12   Mpix/s */
+		{ 133,  133,    10, },          /* 13.3 Mpix/s */
+	};
+
+	l4_rate = rfbi.l4_khz / 1000;
+	dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000;
+
+	for (i = 0; i < ARRAY_SIZE(ftab); i++) {
+		/* Use a window instead of an exact match, to account
+		 * for different DPLL multiplier / divider pairs.
+		 */
+		if (abs(ftab[i].l4_clk - l4_rate) < 3 &&
+		    abs(ftab[i].dss1_clk - dss1_rate) < 3) {
+			min_l4_ticks = ftab[i].min_l4_ticks;
+			break;
+		}
+	}
+	if (i == ARRAY_SIZE(ftab)) {
+		/* Can't be sure, return anyway the maximum not
+		 * rate-limited. This might cause a problem only for the
+		 * tearing synchronisation.
+		 */
+		DSSERR("can't determine maximum RFBI transfer rate\n");
+		return rfbi.l4_khz * 1000;
+	}
+	return rfbi.l4_khz * 1000 / min_l4_ticks;
+}
+#else
+int rfbi_get_max_tx_rate(void)
+{
+	return rfbi.l4_khz * 1000;
+}
+#endif
+
+static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
+{
+	*clk_period = 1000000000 / rfbi.l4_khz;
+	*max_clk_div = 2;
+}
+
+static int rfbi_convert_timings(struct rfbi_timings *t)
+{
+	u32 l;
+	int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
+	int actim, recyc, wecyc;
+	int div = t->clk_div;
+
+	if (div <= 0 || div > 2)
+		return -1;
+
+	/* Make sure that after conversion it still holds that:
+	 * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
+	 * csoff > cson, csoff >= max(weoff, reoff), actim > reon
+	 */
+	weon = ps_to_rfbi_ticks(t->we_on_time, div);
+	weoff = ps_to_rfbi_ticks(t->we_off_time, div);
+	if (weoff <= weon)
+		weoff = weon + 1;
+	if (weon > 0x0f)
+		return -1;
+	if (weoff > 0x3f)
+		return -1;
+
+	reon = ps_to_rfbi_ticks(t->re_on_time, div);
+	reoff = ps_to_rfbi_ticks(t->re_off_time, div);
+	if (reoff <= reon)
+		reoff = reon + 1;
+	if (reon > 0x0f)
+		return -1;
+	if (reoff > 0x3f)
+		return -1;
+
+	cson = ps_to_rfbi_ticks(t->cs_on_time, div);
+	csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
+	if (csoff <= cson)
+		csoff = cson + 1;
+	if (csoff < max(weoff, reoff))
+		csoff = max(weoff, reoff);
+	if (cson > 0x0f)
+		return -1;
+	if (csoff > 0x3f)
+		return -1;
+
+	l =  cson;
+	l |= csoff << 4;
+	l |= weon  << 10;
+	l |= weoff << 14;
+	l |= reon  << 20;
+	l |= reoff << 24;
+
+	t->tim[0] = l;
+
+	actim = ps_to_rfbi_ticks(t->access_time, div);
+	if (actim <= reon)
+		actim = reon + 1;
+	if (actim > 0x3f)
+		return -1;
+
+	wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
+	if (wecyc < weoff)
+		wecyc = weoff;
+	if (wecyc > 0x3f)
+		return -1;
+
+	recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
+	if (recyc < reoff)
+		recyc = reoff;
+	if (recyc > 0x3f)
+		return -1;
+
+	cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
+	if (cs_pulse > 0x3f)
+		return -1;
+
+	l =  wecyc;
+	l |= recyc    << 6;
+	l |= cs_pulse << 12;
+	l |= actim    << 22;
+
+	t->tim[1] = l;
+
+	t->tim[2] = div - 1;
+
+	t->converted = 1;
+
+	return 0;
+}
+
+/* xxx FIX module selection missing */
+int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
+			     unsigned hs_pulse_time, unsigned vs_pulse_time,
+			     int hs_pol_inv, int vs_pol_inv, int extif_div)
+{
+	int hs, vs;
+	int min;
+	u32 l;
+
+	hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
+	vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
+	if (hs < 2)
+		return -EDOM;
+	if (mode == OMAP_DSS_RFBI_TE_MODE_2)
+		min = 2;
+	else /* OMAP_DSS_RFBI_TE_MODE_1 */
+		min = 4;
+	if (vs < min)
+		return -EDOM;
+	if (vs == hs)
+		return -EINVAL;
+	rfbi.te_mode = mode;
+	DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n",
+		mode, hs, vs, hs_pol_inv, vs_pol_inv);
+
+	rfbi_enable_clocks(1);
+	rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
+	rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
+
+	l = rfbi_read_reg(RFBI_CONFIG(0));
+	if (hs_pol_inv)
+		l &= ~(1 << 21);
+	else
+		l |= 1 << 21;
+	if (vs_pol_inv)
+		l &= ~(1 << 20);
+	else
+		l |= 1 << 20;
+	rfbi_enable_clocks(0);
+
+	return 0;
+}
+EXPORT_SYMBOL(omap_rfbi_setup_te);
+
+/* xxx FIX module selection missing */
+int omap_rfbi_enable_te(int enable, unsigned line)
+{
+	u32 l;
+
+	DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode);
+	if (line > (1 << 11) - 1)
+		return -EINVAL;
+
+	rfbi_enable_clocks(1);
+	l = rfbi_read_reg(RFBI_CONFIG(0));
+	l &= ~(0x3 << 2);
+	if (enable) {
+		rfbi.te_enabled = 1;
+		l |= rfbi.te_mode << 2;
+	} else
+		rfbi.te_enabled = 0;
+	rfbi_write_reg(RFBI_CONFIG(0), l);
+	rfbi_write_reg(RFBI_LINE_NUMBER, line);
+	rfbi_enable_clocks(0);
+
+	return 0;
+}
+EXPORT_SYMBOL(omap_rfbi_enable_te);
+
+#if 0
+static void rfbi_enable_config(int enable1, int enable2)
+{
+	u32 l;
+	int cs = 0;
+
+	if (enable1)
+		cs |= 1<<0;
+	if (enable2)
+		cs |= 1<<1;
+
+	rfbi_enable_clocks(1);
+
+	l = rfbi_read_reg(RFBI_CONTROL);
+
+	l = FLD_MOD(l, cs, 3, 2);
+	l = FLD_MOD(l, 0, 1, 1);
+
+	rfbi_write_reg(RFBI_CONTROL, l);
+
+
+	l = rfbi_read_reg(RFBI_CONFIG(0));
+	l = FLD_MOD(l, 0, 3, 2); /* TRIGGERMODE: ITE */
+	/*l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
+	/*l |= FLD_VAL(0, 8, 7); */ /* L4FORMAT, 1pix/L4 */
+
+	l = FLD_MOD(l, 0, 16, 16); /* A0POLARITY */
+	l = FLD_MOD(l, 1, 20, 20); /* TE_VSYNC_POLARITY */
+	l = FLD_MOD(l, 1, 21, 21); /* HSYNCPOLARITY */
+
+	l = FLD_MOD(l, OMAP_DSS_RFBI_PARALLELMODE_8, 1, 0);
+	rfbi_write_reg(RFBI_CONFIG(0), l);
+
+	rfbi_enable_clocks(0);
+}
+#endif
+
+int rfbi_configure(int rfbi_module, int bpp, int lines)
+{
+	u32 l;
+	int cycle1 = 0, cycle2 = 0, cycle3 = 0;
+	enum omap_rfbi_cycleformat cycleformat;
+	enum omap_rfbi_datatype datatype;
+	enum omap_rfbi_parallelmode parallelmode;
+
+	switch (bpp) {
+	case 12:
+		datatype = OMAP_DSS_RFBI_DATATYPE_12;
+		break;
+	case 16:
+		datatype = OMAP_DSS_RFBI_DATATYPE_16;
+		break;
+	case 18:
+		datatype = OMAP_DSS_RFBI_DATATYPE_18;
+		break;
+	case 24:
+		datatype = OMAP_DSS_RFBI_DATATYPE_24;
+		break;
+	default:
+		BUG();
+		return 1;
+	}
+	rfbi.datatype = datatype;
+
+	switch (lines) {
+	case 8:
+		parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8;
+		break;
+	case 9:
+		parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9;
+		break;
+	case 12:
+		parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12;
+		break;
+	case 16:
+		parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16;
+		break;
+	default:
+		BUG();
+		return 1;
+	}
+	rfbi.parallelmode = parallelmode;
+
+	if ((bpp % lines) == 0) {
+		switch (bpp / lines) {
+		case 1:
+			cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1;
+			break;
+		case 2:
+			cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1;
+			break;
+		case 3:
+			cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1;
+			break;
+		default:
+			BUG();
+			return 1;
+		}
+	} else if ((2 * bpp % lines) == 0) {
+		if ((2 * bpp / lines) == 3)
+			cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2;
+		else {
+			BUG();
+			return 1;
+		}
+	} else {
+		BUG();
+		return 1;
+	}
+
+	switch (cycleformat) {
+	case OMAP_DSS_RFBI_CYCLEFORMAT_1_1:
+		cycle1 = lines;
+		break;
+
+	case OMAP_DSS_RFBI_CYCLEFORMAT_2_1:
+		cycle1 = lines;
+		cycle2 = lines;
+		break;
+
+	case OMAP_DSS_RFBI_CYCLEFORMAT_3_1:
+		cycle1 = lines;
+		cycle2 = lines;
+		cycle3 = lines;
+		break;
+
+	case OMAP_DSS_RFBI_CYCLEFORMAT_3_2:
+		cycle1 = lines;
+		cycle2 = (lines / 2) | ((lines / 2) << 16);
+		cycle3 = (lines << 16);
+		break;
+	}
+
+	rfbi_enable_clocks(1);
+
+	REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */
+
+	l = 0;
+	l |= FLD_VAL(parallelmode, 1, 0);
+	l |= FLD_VAL(0, 3, 2);		/* TRIGGERMODE: ITE */
+	l |= FLD_VAL(0, 4, 4);		/* TIMEGRANULARITY */
+	l |= FLD_VAL(datatype, 6, 5);
+	/* l |= FLD_VAL(2, 8, 7); */	/* L4FORMAT, 2pix/L4 */
+	l |= FLD_VAL(0, 8, 7);	/* L4FORMAT, 1pix/L4 */
+	l |= FLD_VAL(cycleformat, 10, 9);
+	l |= FLD_VAL(0, 12, 11);	/* UNUSEDBITS */
+	l |= FLD_VAL(0, 16, 16);	/* A0POLARITY */
+	l |= FLD_VAL(0, 17, 17);	/* REPOLARITY */
+	l |= FLD_VAL(0, 18, 18);	/* WEPOLARITY */
+	l |= FLD_VAL(0, 19, 19);	/* CSPOLARITY */
+	l |= FLD_VAL(1, 20, 20);	/* TE_VSYNC_POLARITY */
+	l |= FLD_VAL(1, 21, 21);	/* HSYNCPOLARITY */
+	rfbi_write_reg(RFBI_CONFIG(rfbi_module), l);
+
+	rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1);
+	rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2);
+	rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3);
+
+
+	l = rfbi_read_reg(RFBI_CONTROL);
+	l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */
+	l = FLD_MOD(l, 0, 1, 1); /* clear bypass */
+	rfbi_write_reg(RFBI_CONTROL, l);
+
+
+	DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n",
+	       bpp, lines, cycle1, cycle2, cycle3);
+
+	rfbi_enable_clocks(0);
+
+	return 0;
+}
+EXPORT_SYMBOL(rfbi_configure);
+
+static int rfbi_find_display(struct omap_display *disp)
+{
+	if (disp == rfbi.display[0])
+		return 0;
+
+	if (disp == rfbi.display[1])
+		return 1;
+
+	BUG();
+	return -1;
+}
+
+
+static void signal_fifo_waiters(void)
+{
+	if (atomic_read(&rfbi.cmd_fifo_full) > 0) {
+		/* DSSDBG("SIGNALING: Fifo not full for waiter!\n"); */
+		complete(&rfbi.cmd_done);
+		atomic_dec(&rfbi.cmd_fifo_full);
+	}
+}
+
+/* returns 1 for async op, and 0 for sync op */
+static int do_update(struct omap_display *display, struct update_region *upd)
+{
+	int x = upd->x;
+	int y = upd->y;
+	int w = upd->w;
+	int h = upd->h;
+
+	perf_mark_setup();
+
+	if (display->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+		/*display->ctrl->enable_te(display, 1); */
+		dispc_setup_partial_planes(display, &x, &y, &w, &h);
+	}
+
+#ifdef MEASURE_PERF
+	rfbi.perf_bytes = w * h * 2; /* XXX always 16bit */
+#endif
+
+	display->ctrl->setup_update(display, x, y, w, h);
+
+	if (display->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+		rfbi_transfer_area(w, h, NULL, NULL);
+		return 1;
+	} else {
+		struct omap_overlay *ovl;
+		void *addr;
+		int scr_width;
+
+		ovl = &display->manager->overlays[0];
+		scr_width = ovl->info.screen_width;
+		addr = ovl->info.vaddr;
+
+		omap_rfbi_write_pixels(addr, scr_width, x, y, w, h);
+
+		perf_show("L4");
+
+		return 0;
+	}
+}
+
+static void process_cmd_fifo(void)
+{
+	int len;
+	struct update_param p;
+	struct omap_display *display;
+	unsigned long flags;
+
+	if (atomic_inc_return(&rfbi.cmd_pending) != 1)
+		return;
+
+	while (true) {
+		spin_lock_irqsave(rfbi.cmd_fifo->lock, flags);
+
+		len = __kfifo_get(rfbi.cmd_fifo, (unsigned char *)&p,
+				  sizeof(struct update_param));
+		if (len == 0) {
+			DSSDBG("nothing more in fifo\n");
+			atomic_set(&rfbi.cmd_pending, 0);
+			spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
+			break;
+		}
+
+		/* DSSDBG("fifo full %d\n", rfbi.cmd_fifo_full.counter);*/
+
+		spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
+
+		BUG_ON(len != sizeof(struct update_param));
+		BUG_ON(p.rfbi_module > 1);
+
+		display = rfbi.display[p.rfbi_module];
+
+		if (p.cmd == RFBI_CMD_UPDATE) {
+			if (do_update(display, &p.par.r))
+				break; /* async op */
+		} else if (p.cmd == RFBI_CMD_SYNC) {
+			DSSDBG("Signaling SYNC done!\n");
+			complete(p.par.sync);
+		} else
+			BUG();
+	}
+
+	signal_fifo_waiters();
+}
+
+static void rfbi_push_cmd(struct update_param *p)
+{
+	int ret;
+
+	while (1) {
+		unsigned long flags;
+		int available;
+
+		spin_lock_irqsave(rfbi.cmd_fifo->lock, flags);
+		available = RFBI_CMD_FIFO_LEN_BYTES -
+			__kfifo_len(rfbi.cmd_fifo);
+
+/*		DSSDBG("%d bytes left in fifo\n", available); */
+		if (available < sizeof(struct update_param)) {
+			DSSDBG("Going to wait because FIFO FULL..\n");
+			spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
+			atomic_inc(&rfbi.cmd_fifo_full);
+			wait_for_completion(&rfbi.cmd_done);
+			/*DSSDBG("Woke up because fifo not full anymore\n");*/
+			continue;
+		}
+
+		ret = __kfifo_put(rfbi.cmd_fifo, (unsigned char *)p,
+				  sizeof(struct update_param));
+/*		DSSDBG("pushed %d bytes\n", ret);*/
+
+		spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
+
+		BUG_ON(ret != sizeof(struct update_param));
+
+		break;
+	}
+}
+
+static void rfbi_push_update(int rfbi_module, int x, int y, int w, int h)
+{
+	struct update_param p;
+
+	p.rfbi_module = rfbi_module;
+	p.cmd = RFBI_CMD_UPDATE;
+
+	p.par.r.x = x;
+	p.par.r.y = y;
+	p.par.r.w = w;
+	p.par.r.h = h;
+
+	DSSDBG("RFBI pushed %d,%d %dx%d\n", x, y, w, h);
+
+	rfbi_push_cmd(&p);
+
+	process_cmd_fifo();
+}
+
+static void rfbi_push_sync(int rfbi_module, struct completion *sync_comp)
+{
+	struct update_param p;
+
+	p.rfbi_module = rfbi_module;
+	p.cmd = RFBI_CMD_SYNC;
+	p.par.sync = sync_comp;
+
+	rfbi_push_cmd(&p);
+
+	DSSDBG("RFBI sync pushed to cmd fifo\n");
+
+	process_cmd_fifo();
+}
+
+int rfbi_init(void)
+{
+	u32 rev;
+	u32 l;
+
+	spin_lock_init(&rfbi.cmd_lock);
+	rfbi.cmd_fifo = kfifo_alloc(RFBI_CMD_FIFO_LEN_BYTES, GFP_KERNEL,
+				    &rfbi.cmd_lock);
+	if (IS_ERR(rfbi.cmd_fifo))
+		return -ENOMEM;
+
+	init_completion(&rfbi.cmd_done);
+	atomic_set(&rfbi.cmd_fifo_full, 0);
+	atomic_set(&rfbi.cmd_pending, 0);
+
+	rfbi.base = ioremap(RFBI_BASE, SZ_256);
+	if (!rfbi.base) {
+		DSSERR("can't ioremap RFBI\n");
+		return -ENOMEM;
+	}
+
+	rfbi_enable_clocks(1);
+
+	msleep(10);
+
+	rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
+
+	/* Enable autoidle and smart-idle */
+	l = rfbi_read_reg(RFBI_SYSCONFIG);
+	l |= (1 << 0) | (2 << 3);
+	rfbi_write_reg(RFBI_SYSCONFIG, l);
+
+	rev = rfbi_read_reg(RFBI_REVISION);
+	printk(KERN_INFO "OMAP RFBI rev %d.%d\n",
+	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+	rfbi_enable_clocks(0);
+
+	return 0;
+}
+
+void rfbi_exit(void)
+{
+	DSSDBG("rfbi_exit\n");
+
+	kfifo_free(rfbi.cmd_fifo);
+
+	iounmap(rfbi.base);
+}
+
+/* struct omap_display support */
+static int rfbi_display_update(struct omap_display *display,
+			int x, int y, int w, int h)
+{
+	int rfbi_module;
+
+	if (w == 0 || h == 0)
+		return 0;
+
+	rfbi_module = rfbi_find_display(display);
+
+	rfbi_push_update(rfbi_module, x, y, w, h);
+
+	return 0;
+}
+
+static int rfbi_display_sync(struct omap_display *display)
+{
+	struct completion sync_comp;
+	int rfbi_module;
+
+	rfbi_module = rfbi_find_display(display);
+
+	init_completion(&sync_comp);
+	rfbi_push_sync(rfbi_module, &sync_comp);
+	DSSDBG("Waiting for SYNC to happen...\n");
+	wait_for_completion(&sync_comp);
+	DSSDBG("Released from SYNC\n");
+	return 0;
+}
+
+static int rfbi_display_enable_te(struct omap_display *display, int enable)
+{
+	display->ctrl->enable_te(display, enable);
+	return 0;
+}
+
+static int rfbi_display_enable(struct omap_display *display)
+{
+	int r;
+
+	BUG_ON(display->panel == NULL || display->ctrl == NULL);
+
+	r = omap_dispc_register_isr(framedone_callback, NULL,
+			DISPC_IRQ_FRAMEDONE);
+	if (r) {
+		DSSERR("can't get FRAMEDONE irq\n");
+		return r;
+	}
+
+	dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
+
+	dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_RFBI);
+
+	dispc_set_tft_data_lines(display->ctrl->pixel_size);
+
+	rfbi_configure(display->hw_config.u.rfbi.channel,
+			       display->ctrl->pixel_size,
+			       display->hw_config.u.rfbi.data_lines);
+
+	rfbi_set_timings(display->hw_config.u.rfbi.channel,
+			 &display->ctrl->timings);
+
+
+	if (display->ctrl && display->ctrl->enable) {
+		r = display->ctrl->enable(display);
+		if (r)
+			goto err;
+	}
+
+	if (display->panel && display->panel->enable) {
+		r = display->panel->enable(display);
+		if (r)
+			goto err;
+	}
+
+	return 0;
+err:
+	return -ENODEV;
+}
+
+static void rfbi_display_disable(struct omap_display *display)
+{
+	display->ctrl->disable(display);
+	omap_dispc_unregister_isr(framedone_callback);
+}
+
+void rfbi_init_display(struct omap_display *display)
+{
+	display->enable = rfbi_display_enable;
+	display->disable = rfbi_display_disable;
+	display->update = rfbi_display_update;
+	display->sync = rfbi_display_sync;
+	display->enable_te = rfbi_display_enable_te;
+
+	rfbi.display[display->hw_config.u.rfbi.channel] = display;
+
+	display->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
+}


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 04/12] DSS: VENC support
  2009-01-12 11:47 [PATCH 00/12] DSS: Series description Tomi Valkeinen
                   ` (2 preceding siblings ...)
  2009-01-12 11:47 ` [PATCH 03/12] DSS: RFBI support Tomi Valkeinen
@ 2009-01-12 11:47 ` Tomi Valkeinen
  2009-01-12 11:47 ` [PATCH 05/12] DSS: DSI support Tomi Valkeinen
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 23+ messages in thread
From: Tomi Valkeinen @ 2009-01-12 11:47 UTC (permalink / raw)
  To: linux-fbdev-devel; +Cc: linux-omap

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
---

 arch/arm/plat-omap/dss/venc.c |  506 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 506 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-omap/dss/venc.c

diff --git a/arch/arm/plat-omap/dss/venc.c b/arch/arm/plat-omap/dss/venc.c
new file mode 100644
index 0000000..81319e4
--- /dev/null
+++ b/arch/arm/plat-omap/dss/venc.c
@@ -0,0 +1,506 @@
+/*
+ * linux/arch/arm/plat-omap/dss/venc.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * VENC settings from TI's DSS driver
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "VENC"
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+
+#include <mach/display.h>
+#include <mach/cpu.h>
+
+#include "dss.h"
+
+#define VENC_BASE	0x48050C00
+
+/* Venc registers */
+#define VENC_REV_ID				0x00
+#define VENC_STATUS				0x04
+#define VENC_F_CONTROL				0x08
+#define VENC_VIDOUT_CTRL			0x10
+#define VENC_SYNC_CTRL				0x14
+#define VENC_LLEN				0x1C
+#define VENC_FLENS				0x20
+#define VENC_HFLTR_CTRL				0x24
+#define VENC_CC_CARR_WSS_CARR			0x28
+#define VENC_C_PHASE				0x2C
+#define VENC_GAIN_U				0x30
+#define VENC_GAIN_V				0x34
+#define VENC_GAIN_Y				0x38
+#define VENC_BLACK_LEVEL			0x3C
+#define VENC_BLANK_LEVEL			0x40
+#define VENC_X_COLOR				0x44
+#define VENC_M_CONTROL				0x48
+#define VENC_BSTAMP_WSS_DATA			0x4C
+#define VENC_S_CARR				0x50
+#define VENC_LINE21				0x54
+#define VENC_LN_SEL				0x58
+#define VENC_L21__WC_CTL			0x5C
+#define VENC_HTRIGGER_VTRIGGER			0x60
+#define VENC_SAVID__EAVID			0x64
+#define VENC_FLEN__FAL				0x68
+#define VENC_LAL__PHASE_RESET			0x6C
+#define VENC_HS_INT_START_STOP_X		0x70
+#define VENC_HS_EXT_START_STOP_X		0x74
+#define VENC_VS_INT_START_X			0x78
+#define VENC_VS_INT_STOP_X__VS_INT_START_Y	0x7C
+#define VENC_VS_INT_STOP_Y__VS_EXT_START_X	0x80
+#define VENC_VS_EXT_STOP_X__VS_EXT_START_Y	0x84
+#define VENC_VS_EXT_STOP_Y			0x88
+#define VENC_AVID_START_STOP_X			0x90
+#define VENC_AVID_START_STOP_Y			0x94
+#define VENC_FID_INT_START_X__FID_INT_START_Y	0xA0
+#define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X	0xA4
+#define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y	0xA8
+#define VENC_TVDETGP_INT_START_STOP_X		0xB0
+#define VENC_TVDETGP_INT_START_STOP_Y		0xB4
+#define VENC_GEN_CTRL				0xB8
+#define VENC_OUTPUT_CONTROL			0xC4
+#define VENC_DAC_B__DAC_C			0xC8
+
+struct venc_config {
+	u32 f_control;
+	u32 vidout_ctrl;
+	u32 sync_ctrl;
+	u32 llen;
+	u32 flens;
+	u32 hfltr_ctrl;
+	u32 cc_carr_wss_carr;
+	u32 c_phase;
+	u32 gain_u;
+	u32 gain_v;
+	u32 gain_y;
+	u32 black_level;
+	u32 blank_level;
+	u32 x_color;
+	u32 m_control;
+	u32 bstamp_wss_data;
+	u32 s_carr;
+	u32 line21;
+	u32 ln_sel;
+	u32 l21__wc_ctl;
+	u32 htrigger_vtrigger;
+	u32 savid__eavid;
+	u32 flen__fal;
+	u32 lal__phase_reset;
+	u32 hs_int_start_stop_x;
+	u32 hs_ext_start_stop_x;
+	u32 vs_int_start_x;
+	u32 vs_int_stop_x__vs_int_start_y;
+	u32 vs_int_stop_y__vs_ext_start_x;
+	u32 vs_ext_stop_x__vs_ext_start_y;
+	u32 vs_ext_stop_y;
+	u32 avid_start_stop_x;
+	u32 avid_start_stop_y;
+	u32 fid_int_start_x__fid_int_start_y;
+	u32 fid_int_offset_y__fid_ext_start_x;
+	u32 fid_ext_start_y__fid_ext_offset_y;
+	u32 tvdetgp_int_start_stop_x;
+	u32 tvdetgp_int_start_stop_y;
+	u32 gen_ctrl;
+
+	int width;
+	int height;
+};
+
+/* from TRM */
+static const struct venc_config venc_config_pal_trm = {
+	.f_control				= 0,
+	.vidout_ctrl				= 1,
+	.sync_ctrl				= 0x40,
+	.llen					= 0x35F, /* 863 */
+	.flens					= 0x270, /* 624 */
+	.hfltr_ctrl				= 0,
+	.cc_carr_wss_carr			= 0x2F7225ED,
+	.c_phase				= 0,
+	.gain_u					= 0x111,
+	.gain_v					= 0x181,
+	.gain_y					= 0x140,
+	.black_level				= 0x3B,
+	.blank_level				= 0x3B,
+	.x_color				= 0x7,
+	.m_control				= 0x2,
+	.bstamp_wss_data			= 0x3F,
+	.s_carr					= 0x2A098ACB,
+	.line21					= 0,
+	.ln_sel					= 0x01290015,
+	.l21__wc_ctl				= 0x0000F603,
+	.htrigger_vtrigger			= 0,
+
+	.savid__eavid				= 0x06A70108,
+	.flen__fal				= 0x00180270,
+	.lal__phase_reset			= 0x00180270,
+	.hs_int_start_stop_x			= 0x00880358,
+	.hs_ext_start_stop_x			= 0x000F035F,
+	.vs_int_start_x				= 0x01A70000,
+	.vs_int_stop_x__vs_int_start_y		= 0x000001A7,
+	.vs_int_stop_y__vs_ext_start_x		= 0x01AF0000,
+	.vs_ext_stop_x__vs_ext_start_y		= 0x000101AF,
+	.vs_ext_stop_y				= 0x00000025,
+	.avid_start_stop_x			= 0x03530083,
+	.avid_start_stop_y			= 0x026C002E,
+	.fid_int_start_x__fid_int_start_y	= 0x0001008A,
+	.fid_int_offset_y__fid_ext_start_x	= 0x002E0138,
+	.fid_ext_start_y__fid_ext_offset_y	= 0x01380001,
+
+	.tvdetgp_int_start_stop_x		= 0x00140001,
+	.tvdetgp_int_start_stop_y		= 0x00010001,
+	.gen_ctrl				= 0x00FF0000,
+
+	.width = 720,
+	.height = 574, /* for some reason, this isn't 576 */
+};
+
+/* from TRM */
+static const struct venc_config venc_config_ntsc_trm = {
+	.f_control				= 0,
+	.vidout_ctrl				= 1,
+	.sync_ctrl				= 0x8040,
+	.llen					= 0x359,
+	.flens					= 0x20C,
+	.hfltr_ctrl				= 0,
+	.cc_carr_wss_carr			= 0x043F2631,
+	.c_phase				= 0,
+	.gain_u					= 0x102,
+	.gain_v					= 0x16C,
+	.gain_y					= 0x12F,
+	.black_level				= 0x43,
+	.blank_level				= 0x38,
+	.x_color				= 0x7,
+	.m_control				= 0x1,
+	.bstamp_wss_data			= 0x38,
+	.s_carr					= 0x21F07C1F,
+	.line21					= 0,
+	.ln_sel					= 0x01310011,
+	.l21__wc_ctl				= 0x0000F003,
+	.htrigger_vtrigger			= 0,
+
+	.savid__eavid				= 0x069300F4,
+	.flen__fal				= 0x0016020C,
+	.lal__phase_reset			= 0x00060107,
+	.hs_int_start_stop_x			= 0x008E0350,
+	.hs_ext_start_stop_x			= 0x000F0359,
+	.vs_int_start_x				= 0x01A00000,
+	.vs_int_stop_x__vs_int_start_y		= 0x020701A0,
+	.vs_int_stop_y__vs_ext_start_x		= 0x01AC0024,
+	.vs_ext_stop_x__vs_ext_start_y		= 0x020D01AC,
+	.vs_ext_stop_y				= 0x00000006,
+	.avid_start_stop_x			= 0x03480078,
+	.avid_start_stop_y			= 0x02060024,
+	.fid_int_start_x__fid_int_start_y	= 0x0001008A,
+	.fid_int_offset_y__fid_ext_start_x	= 0x01AC0106,
+	.fid_ext_start_y__fid_ext_offset_y	= 0x01060006,
+
+	.tvdetgp_int_start_stop_x		= 0x00140001,
+	.tvdetgp_int_start_stop_y		= 0x00010001,
+	.gen_ctrl				= 0x00F90000,
+
+	.width = 720,
+	.height = 482,
+};
+
+static const struct venc_config venc_config_pal_bdghi = {
+	.f_control				= 0,
+	.vidout_ctrl				= 0,
+	.sync_ctrl				= 0,
+	.hfltr_ctrl				= 0,
+	.x_color				= 0,
+	.line21					= 0,
+	.ln_sel					= 21,
+	.htrigger_vtrigger			= 0,
+	.tvdetgp_int_start_stop_x		= 0x00140001,
+	.tvdetgp_int_start_stop_y		= 0x00010001,
+	.gen_ctrl				= 0x00FB0000,
+
+	.llen					= 864-1,
+	.flens					= 625-1,
+	.cc_carr_wss_carr			= 0x2F7625ED,
+	.c_phase				= 0xDF,
+	.gain_u					= 0x111,
+	.gain_v					= 0x181,
+	.gain_y					= 0x140,
+	.black_level				= 0x3e,
+	.blank_level				= 0x3e,
+	.m_control				= 0<<2 | 1<<1,
+	.bstamp_wss_data			= 0x42,
+	.s_carr					= 0x2a098acb,
+	.l21__wc_ctl				= 0<<13 | 0x16<<8 | 0<<0,
+	.savid__eavid				= 0x06A70108,
+	.flen__fal				= 23<<16 | 624<<0,
+	.lal__phase_reset			= 2<<17 | 310<<0,
+	.hs_int_start_stop_x			= 0x00920358,
+	.hs_ext_start_stop_x			= 0x000F035F,
+	.vs_int_start_x				= 0x1a7<<16,
+	.vs_int_stop_x__vs_int_start_y		= 0x000601A7,
+	.vs_int_stop_y__vs_ext_start_x		= 0x01AF0036,
+	.vs_ext_stop_x__vs_ext_start_y		= 0x27101af,
+	.vs_ext_stop_y				= 0x05,
+	.avid_start_stop_x			= 0x03530082,
+	.avid_start_stop_y			= 0x0270002E,
+	.fid_int_start_x__fid_int_start_y	= 0x0005008A,
+	.fid_int_offset_y__fid_ext_start_x	= 0x002E0138,
+	.fid_ext_start_y__fid_ext_offset_y	= 0x01380005,
+
+	.width = 720,
+	.height = 576,
+};
+
+static struct {
+	void __iomem *base;
+	const struct venc_config *config;
+	struct mutex venc_lock;
+} venc;
+
+static struct omap_panel venc_panel = {
+	.name = "tv-out",
+	.bpp = 24,
+};
+
+static inline void venc_write_reg(int idx, u32 val)
+{
+	__raw_writel(val, venc.base + idx);
+}
+
+static inline u32 venc_read_reg(int idx)
+{
+	u32 l = __raw_readl(venc.base + idx);
+	return l;
+}
+
+static void venc_write_config(const struct venc_config *config)
+{
+	DSSDBG("write venc conf\n");
+
+	venc_write_reg(VENC_LLEN, config->llen);
+	venc_write_reg(VENC_FLENS, config->flens);
+	venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr);
+	venc_write_reg(VENC_C_PHASE, config->c_phase);
+	venc_write_reg(VENC_GAIN_U, config->gain_u);
+	venc_write_reg(VENC_GAIN_V, config->gain_v);
+	venc_write_reg(VENC_GAIN_Y, config->gain_y);
+	venc_write_reg(VENC_BLACK_LEVEL, config->black_level);
+	venc_write_reg(VENC_BLANK_LEVEL, config->blank_level);
+	venc_write_reg(VENC_M_CONTROL, config->m_control);
+	venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data);
+	venc_write_reg(VENC_S_CARR, config->s_carr);
+	venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl);
+	venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid);
+	venc_write_reg(VENC_FLEN__FAL, config->flen__fal);
+	venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset);
+	venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x);
+	venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x);
+	venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x);
+	venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y,
+		       config->vs_int_stop_x__vs_int_start_y);
+	venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X,
+		       config->vs_int_stop_y__vs_ext_start_x);
+	venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y,
+		       config->vs_ext_stop_x__vs_ext_start_y);
+	venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y);
+	venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x);
+	venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y);
+	venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y,
+		       config->fid_int_start_x__fid_int_start_y);
+	venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X,
+		       config->fid_int_offset_y__fid_ext_start_x);
+	venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y,
+		       config->fid_ext_start_y__fid_ext_offset_y);
+
+	venc_write_reg(VENC_DAC_B__DAC_C,  venc_read_reg(VENC_DAC_B__DAC_C));
+	venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl);
+	venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl);
+	venc_write_reg(VENC_X_COLOR, config->x_color);
+	venc_write_reg(VENC_LINE21, config->line21);
+	venc_write_reg(VENC_LN_SEL, config->ln_sel);
+	venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger);
+	venc_write_reg(VENC_TVDETGP_INT_START_STOP_X,
+		       config->tvdetgp_int_start_stop_x);
+	venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y,
+		       config->tvdetgp_int_start_stop_y);
+	venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl);
+	venc_write_reg(VENC_F_CONTROL, config->f_control);
+	venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl);
+}
+
+static void venc_reset(void)
+{
+	int t = 1000;
+
+	venc_write_reg(VENC_F_CONTROL, venc_read_reg(VENC_F_CONTROL) | (1<<8));
+	while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) {
+		if (--t == 0) {
+			DSSERR("Failed to reset venc\n");
+			return;
+		}
+	}
+}
+
+static void venc_enable_clocks(int enable)
+{
+	if (enable)
+		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
+				DSS_CLK_96M);
+	else
+		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
+				DSS_CLK_96M);
+}
+
+int venc_init(void)
+{
+	u8 rev_id;
+	int use_pal = 1; /* XXX */
+
+	mutex_init(&venc.venc_lock);
+
+	if (use_pal)
+		venc.config = &venc_config_pal_trm;
+	else
+		venc.config = &venc_config_ntsc_trm;
+
+	venc_panel.timings.x_res = venc.config->width;
+	venc_panel.timings.y_res = venc.config->height;
+
+	venc.base = ioremap(VENC_BASE, SZ_1K);
+	if (!venc.base) {
+		DSSERR("can't ioremap VENC\n");
+		return -ENOMEM;
+	}
+
+	/* enable clocks */
+	venc_enable_clocks(1);
+
+	/* configure venc */
+	venc_reset();
+	venc_write_config(venc.config);
+
+	rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
+	printk(KERN_INFO "OMAP VENC rev %d\n", rev_id);
+
+	venc_enable_clocks(0);
+
+	return 0;
+}
+
+void venc_exit(void)
+{
+	iounmap(venc.base);
+}
+
+static void venc_sync_lost_handler(void *arg, u32 mask)
+{
+	/* we just catch SYNC_LOST_DIGIT here so that
+	 * dispc doesn't take it as an error */
+}
+
+static int venc_enable_display(struct omap_display *display)
+{
+	DSSDBG("venc_enable_display\n");
+
+	mutex_lock(&venc.venc_lock);
+
+	if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
+		mutex_unlock(&venc.venc_lock);
+		return -EINVAL;
+	}
+
+	venc_enable_clocks(1);
+
+	dss_set_venc_output(display->hw_config.u.venc.type);
+	dss_set_dac_pwrdn_bgz(1);
+
+	if (display->hw_config.u.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE) {
+		if (cpu_is_omap24xx())
+			venc_write_reg(VENC_OUTPUT_CONTROL, 0x2);
+		else
+			venc_write_reg(VENC_OUTPUT_CONTROL, 0xa);
+	} else { /* S-Video */
+		venc_write_reg(VENC_OUTPUT_CONTROL, 0xd);
+	}
+
+	venc_write_config(venc.config);
+
+	dispc_set_digit_size(venc.config->width, venc.config->height/2);
+
+	if (display->hw_config.panel_enable)
+		display->hw_config.panel_enable(display);
+
+	dispc_go(OMAP_DSS_CHANNEL_DIGIT);
+
+	omap_dispc_register_isr(venc_sync_lost_handler, NULL,
+			DISPC_IRQ_SYNC_LOST_DIGIT);
+
+	dispc_enable_digit_out(1);
+
+	mdelay(20);
+
+	omap_dispc_unregister_isr(venc_sync_lost_handler);
+
+	display->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	mutex_unlock(&venc.venc_lock);
+
+	return 0;
+}
+
+static void venc_disable_display(struct omap_display *display)
+{
+	DSSDBG("venc_disable_display\n");
+
+	mutex_lock(&venc.venc_lock);
+
+	if (display->state == OMAP_DSS_DISPLAY_DISABLED) {
+		mutex_unlock(&venc.venc_lock);
+		return;
+	}
+
+	venc_write_reg(VENC_OUTPUT_CONTROL, 0);
+	dss_set_dac_pwrdn_bgz(0);
+
+	dispc_enable_digit_out(0);
+
+	if (display->hw_config.panel_disable)
+		display->hw_config.panel_disable(display);
+
+	venc_enable_clocks(0);
+
+	display->state = OMAP_DSS_DISPLAY_DISABLED;
+
+	mutex_unlock(&venc.venc_lock);
+}
+
+static void venc_get_timings(struct omap_display *display,
+			struct omap_video_timings *timings)
+{
+	*timings = venc_panel.timings;
+}
+
+void venc_init_display(struct omap_display *display)
+{
+	display->panel = &venc_panel;
+	display->enable = venc_enable_display;
+	display->disable = venc_disable_display;
+	display->get_timings = venc_get_timings;
+}


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 05/12] DSS: DSI support
  2009-01-12 11:47 [PATCH 00/12] DSS: Series description Tomi Valkeinen
                   ` (3 preceding siblings ...)
  2009-01-12 11:47 ` [PATCH 04/12] DSS: VENC support Tomi Valkeinen
@ 2009-01-12 11:47 ` Tomi Valkeinen
  2009-01-12 11:47 ` [PATCH 06/12] DSS: OMAPFB: fb driver for new display subsystem Tomi Valkeinen
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 23+ messages in thread
From: Tomi Valkeinen @ 2009-01-12 11:47 UTC (permalink / raw)
  To: linux-fbdev-devel; +Cc: linux-omap

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
---

 arch/arm/plat-omap/dss/dsi.c | 3187 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 3187 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-omap/dss/dsi.c

diff --git a/arch/arm/plat-omap/dss/dsi.c b/arch/arm/plat-omap/dss/dsi.c
new file mode 100644
index 0000000..e279571
--- /dev/null
+++ b/arch/arm/plat-omap/dss/dsi.c
@@ -0,0 +1,3187 @@
+/*
+ * linux/arch/arm/plat-omap/dss/dsi.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "DSI"
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+
+#include <mach/board.h>
+#include <mach/display.h>
+#include <mach/clock.h>
+
+#include "dss.h"
+
+/*#define VERBOSE*/
+/*#define VERBOSE_IRQ*/
+/*#define MEASURE_PERF*/
+
+#define DSI_BASE		0x4804FC00
+
+struct dsi_reg { u16 idx; };
+
+#define DSI_REG(idx)		((const struct dsi_reg) { idx })
+
+#define DSI_SZ_REGS		SZ_1K
+/* DSI Protocol Engine */
+
+#define DSI_REVISION			DSI_REG(0x0000)
+#define DSI_SYSCONFIG			DSI_REG(0x0010)
+#define DSI_SYSSTATUS			DSI_REG(0x0014)
+#define DSI_IRQSTATUS			DSI_REG(0x0018)
+#define DSI_IRQENABLE			DSI_REG(0x001C)
+#define DSI_CTRL			DSI_REG(0x0040)
+#define DSI_COMPLEXIO_CFG1		DSI_REG(0x0048)
+#define DSI_COMPLEXIO_IRQ_STATUS	DSI_REG(0x004C)
+#define DSI_COMPLEXIO_IRQ_ENABLE	DSI_REG(0x0050)
+#define DSI_CLK_CTRL			DSI_REG(0x0054)
+#define DSI_TIMING1			DSI_REG(0x0058)
+#define DSI_TIMING2			DSI_REG(0x005C)
+#define DSI_VM_TIMING1			DSI_REG(0x0060)
+#define DSI_VM_TIMING2			DSI_REG(0x0064)
+#define DSI_VM_TIMING3			DSI_REG(0x0068)
+#define DSI_CLK_TIMING			DSI_REG(0x006C)
+#define DSI_TX_FIFO_VC_SIZE		DSI_REG(0x0070)
+#define DSI_RX_FIFO_VC_SIZE		DSI_REG(0x0074)
+#define DSI_COMPLEXIO_CFG2		DSI_REG(0x0078)
+#define DSI_RX_FIFO_VC_FULLNESS		DSI_REG(0x007C)
+#define DSI_VM_TIMING4			DSI_REG(0x0080)
+#define DSI_TX_FIFO_VC_EMPTINESS	DSI_REG(0x0084)
+#define DSI_VM_TIMING5			DSI_REG(0x0088)
+#define DSI_VM_TIMING6			DSI_REG(0x008C)
+#define DSI_VM_TIMING7			DSI_REG(0x0090)
+#define DSI_STOPCLK_TIMING		DSI_REG(0x0094)
+#define DSI_VC_CTRL(n)			DSI_REG(0x0100 + (n * 0x20))
+#define DSI_VC_TE(n)			DSI_REG(0x0104 + (n * 0x20))
+#define DSI_VC_LONG_PACKET_HEADER(n)	DSI_REG(0x0108 + (n * 0x20))
+#define DSI_VC_LONG_PACKET_PAYLOAD(n)	DSI_REG(0x010C + (n * 0x20))
+#define DSI_VC_SHORT_PACKET_HEADER(n)	DSI_REG(0x0110 + (n * 0x20))
+#define DSI_VC_IRQSTATUS(n)		DSI_REG(0x0118 + (n * 0x20))
+#define DSI_VC_IRQENABLE(n)		DSI_REG(0x011C + (n * 0x20))
+
+/* DSIPHY_SCP */
+
+#define DSI_DSIPHY_CFG0			DSI_REG(0x200 + 0x0000)
+#define DSI_DSIPHY_CFG1			DSI_REG(0x200 + 0x0004)
+#define DSI_DSIPHY_CFG2			DSI_REG(0x200 + 0x0008)
+#define DSI_DSIPHY_CFG5			DSI_REG(0x200 + 0x0014)
+
+/* DSI_PLL_CTRL_SCP */
+
+#define DSI_PLL_CONTROL			DSI_REG(0x300 + 0x0000)
+#define DSI_PLL_STATUS			DSI_REG(0x300 + 0x0004)
+#define DSI_PLL_GO			DSI_REG(0x300 + 0x0008)
+#define DSI_PLL_CONFIGURATION1		DSI_REG(0x300 + 0x000C)
+#define DSI_PLL_CONFIGURATION2		DSI_REG(0x300 + 0x0010)
+
+#define REG_GET(idx, start, end) \
+	FLD_GET(dsi_read_reg(idx), start, end)
+
+#define REG_FLD_MOD(idx, val, start, end) \
+	dsi_write_reg(idx, FLD_MOD(dsi_read_reg(idx), val, start, end))
+
+/* Global interrupts */
+#define DSI_IRQ_VC0		(1 << 0)
+#define DSI_IRQ_VC1		(1 << 1)
+#define DSI_IRQ_VC2		(1 << 2)
+#define DSI_IRQ_VC3		(1 << 3)
+#define DSI_IRQ_WAKEUP		(1 << 4)
+#define DSI_IRQ_RESYNC		(1 << 5)
+#define DSI_IRQ_PLL_LOCK	(1 << 7)
+#define DSI_IRQ_PLL_UNLOCK	(1 << 8)
+#define DSI_IRQ_PLL_RECALL	(1 << 9)
+#define DSI_IRQ_COMPLEXIO_ERR	(1 << 10)
+#define DSI_IRQ_HS_TX_TIMEOUT	(1 << 14)
+#define DSI_IRQ_LP_RX_TIMEOUT	(1 << 15)
+#define DSI_IRQ_TE_TRIGGER	(1 << 16)
+#define DSI_IRQ_ACK_TRIGGER	(1 << 17)
+#define DSI_IRQ_SYNC_LOST	(1 << 18)
+#define DSI_IRQ_LDO_POWER_GOOD	(1 << 19)
+#define DSI_IRQ_TA_TIMEOUT	(1 << 20)
+#define DSI_IRQ_ERROR_MASK \
+	(DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
+	DSI_IRQ_TA_TIMEOUT)
+#define DSI_IRQ_CHANNEL_MASK	0xf
+
+/* Virtual channel interrupts */
+#define DSI_VC_IRQ_CS		(1 << 0)
+#define DSI_VC_IRQ_ECC_CORR	(1 << 1)
+#define DSI_VC_IRQ_PACKET_SENT	(1 << 2)
+#define DSI_VC_IRQ_FIFO_TX_OVF	(1 << 3)
+#define DSI_VC_IRQ_FIFO_RX_OVF	(1 << 4)
+#define DSI_VC_IRQ_BTA		(1 << 5)
+#define DSI_VC_IRQ_ECC_NO_CORR	(1 << 6)
+#define DSI_VC_IRQ_FIFO_TX_UDF	(1 << 7)
+#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8)
+#define DSI_VC_IRQ_ERROR_MASK \
+	(DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \
+	DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \
+	DSI_VC_IRQ_FIFO_TX_UDF)
+
+/* ComplexIO interrupts */
+#define DSI_CIO_IRQ_ERRSYNCESC1		(1 << 0)
+#define DSI_CIO_IRQ_ERRSYNCESC2		(1 << 1)
+#define DSI_CIO_IRQ_ERRSYNCESC3		(1 << 2)
+#define DSI_CIO_IRQ_ERRESC1		(1 << 5)
+#define DSI_CIO_IRQ_ERRESC2		(1 << 6)
+#define DSI_CIO_IRQ_ERRESC3		(1 << 7)
+#define DSI_CIO_IRQ_ERRCONTROL1		(1 << 10)
+#define DSI_CIO_IRQ_ERRCONTROL2		(1 << 11)
+#define DSI_CIO_IRQ_ERRCONTROL3		(1 << 12)
+#define DSI_CIO_IRQ_STATEULPS1		(1 << 15)
+#define DSI_CIO_IRQ_STATEULPS2		(1 << 16)
+#define DSI_CIO_IRQ_STATEULPS3		(1 << 17)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1	(1 << 20)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1	(1 << 21)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2	(1 << 22)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2	(1 << 23)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3	(1 << 24)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3	(1 << 25)
+#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0	(1 << 30)
+#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1	(1 << 31)
+
+#define DSI_DT_DCS_SHORT_WRITE_0	0x05
+#define DSI_DT_DCS_SHORT_WRITE_1	0x15
+#define DSI_DT_DCS_READ			0x06
+#define DSI_DT_SET_MAX_RET_PKG_SIZE	0x37
+#define DSI_DT_NULL_PACKET		0x09
+#define DSI_DT_DCS_LONG_WRITE		0x39
+
+#define DSI_DT_RX_ACK_WITH_ERR		0x02
+#define DSI_DT_RX_DCS_LONG_READ		0x1c
+#define DSI_DT_RX_SHORT_READ_1		0x21
+#define DSI_DT_RX_SHORT_READ_2		0x22
+
+#define FINT_MAX 2100000
+#define FINT_MIN 750000
+#define REGN_MAX (1 << 7)
+#define REGM_MAX ((1 << 11) - 1)
+#define REGM3_MAX (1 << 4)
+#define REGM4_MAX (1 << 4)
+
+enum fifo_size {
+	DSI_FIFO_SIZE_0		= 0,
+	DSI_FIFO_SIZE_32	= 1,
+	DSI_FIFO_SIZE_64	= 2,
+	DSI_FIFO_SIZE_96	= 3,
+	DSI_FIFO_SIZE_128	= 4,
+};
+
+static struct
+{
+	void __iomem	*base;
+
+	unsigned long	dsi1_pll_fclk;	/* Hz */
+	unsigned long	dsi2_pll_fclk;	/* Hz */
+	unsigned long	dsiphy;		/* Hz */
+	unsigned long	ddr_clk;	/* Hz */
+
+	u32		ctx[DSI_SZ_REGS / sizeof(u32)];
+
+	struct {
+		enum fifo_size	fifo_size;
+		int dest_per;	/* destination peripheral 0-3 */
+	} vc[4];
+
+	struct mutex lock;
+
+	unsigned pll_locked;
+
+	struct completion bta_completion;
+
+	spinlock_t update_lock;
+	int update_ongoing;
+	int update_syncers;
+	struct completion update_completion;
+	struct delayed_work framedone_work;
+
+	enum omap_dss_update_mode user_update_mode; /* what the user wants */
+	enum omap_dss_update_mode update_mode; /* current mode */
+	int use_te;
+	int framedone_scheduled; /* helps to catch strange framedone bugs */
+
+	struct {
+		struct omap_display *display;
+		int x, y, w, h;
+		int bytespp;
+	} update_region;
+
+	unsigned long cache_req_pck;
+	unsigned long cache_clk_freq;
+	struct dsi_clock_info cache_cinfo;
+
+#ifdef MEASURE_PERF
+	ktime_t perf_setup_time;
+	ktime_t perf_start_time;
+	int perf_measure_frames;
+#endif
+} dsi;
+
+static inline void dsi_write_reg(const struct dsi_reg idx, u32 val)
+{
+	__raw_writel(val, dsi.base + idx.idx);
+}
+
+static inline u32 dsi_read_reg(const struct dsi_reg idx)
+{
+	return __raw_readl(dsi.base + idx.idx);
+}
+
+
+#define SR(reg) \
+	dsi.ctx[(DSI_##reg).idx / sizeof(u32)] = dsi_read_reg(DSI_##reg)
+#define RR(reg) \
+	dsi_write_reg(DSI_##reg, dsi.ctx[(DSI_##reg).idx / sizeof(u32)])
+
+void dsi_save_context(void)
+{
+	SR(SYSCONFIG);
+	SR(IRQENABLE);
+	SR(CTRL);
+	SR(COMPLEXIO_CFG1);
+	SR(COMPLEXIO_IRQ_ENABLE);
+	SR(CLK_CTRL);
+	SR(TIMING1);
+	SR(TIMING2);
+	SR(VM_TIMING1);
+	SR(VM_TIMING2);
+	SR(VM_TIMING3);
+	SR(CLK_TIMING);
+	SR(TX_FIFO_VC_SIZE);
+	SR(RX_FIFO_VC_SIZE);
+	SR(COMPLEXIO_CFG2);
+	SR(VM_TIMING4);
+	SR(VM_TIMING5);
+	SR(VM_TIMING6);
+	SR(VM_TIMING7);
+	SR(STOPCLK_TIMING);
+
+	SR(VC_CTRL(0));
+	SR(VC_TE(0));
+	SR(VC_IRQENABLE(0));
+
+	SR(VC_CTRL(1));
+	SR(VC_TE(1));
+	SR(VC_IRQENABLE(1));
+
+	SR(VC_CTRL(2));
+	SR(VC_TE(2));
+	SR(VC_IRQENABLE(2));
+
+	SR(VC_CTRL(3));
+	SR(VC_TE(3));
+	SR(VC_IRQENABLE(3));
+
+	SR(DSIPHY_CFG0);
+	SR(DSIPHY_CFG1);
+	SR(DSIPHY_CFG2);
+	SR(DSIPHY_CFG5);
+
+	SR(PLL_CONTROL);
+	SR(PLL_CONFIGURATION1);
+	SR(PLL_CONFIGURATION2);
+}
+
+void dsi_restore_context(void)
+{
+	RR(SYSCONFIG);
+	RR(IRQENABLE);
+	RR(CTRL);
+	RR(COMPLEXIO_CFG1);
+	RR(COMPLEXIO_IRQ_ENABLE);
+	RR(CLK_CTRL);
+	RR(TIMING1);
+	RR(TIMING2);
+	RR(VM_TIMING1);
+	RR(VM_TIMING2);
+	RR(VM_TIMING3);
+	RR(CLK_TIMING);
+	RR(TX_FIFO_VC_SIZE);
+	RR(RX_FIFO_VC_SIZE);
+	RR(COMPLEXIO_CFG2);
+	RR(VM_TIMING4);
+	RR(VM_TIMING5);
+	RR(VM_TIMING6);
+	RR(VM_TIMING7);
+	RR(STOPCLK_TIMING);
+
+	RR(VC_CTRL(0));
+	RR(VC_IRQENABLE(0));
+
+	RR(VC_CTRL(1));
+	RR(VC_IRQENABLE(1));
+
+	RR(VC_CTRL(2));
+	RR(VC_IRQENABLE(2));
+
+	RR(VC_CTRL(3));
+	RR(VC_IRQENABLE(3));
+
+	RR(DSIPHY_CFG0);
+	RR(DSIPHY_CFG1);
+	RR(DSIPHY_CFG2);
+	RR(DSIPHY_CFG5);
+
+	RR(PLL_CONTROL);
+	RR(PLL_CONFIGURATION1);
+	RR(PLL_CONFIGURATION2);
+}
+
+#undef SR
+#undef RR
+
+static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
+		int value)
+{
+	int t = 100000;
+
+	while (REG_GET(idx, bitnum, bitnum) != value) {
+		if (--t == 0)
+			return !value;
+	}
+
+	return value;
+}
+
+
+#ifdef MEASURE_PERF
+static void perf_mark_setup(void)
+{
+	dsi.perf_setup_time = ktime_get();
+}
+
+static void perf_mark_start(void)
+{
+	dsi.perf_start_time = ktime_get();
+}
+
+static void perf_show(const char *name)
+{
+	ktime_t t, setup_time, trans_time;
+	u32 total_bytes;
+	u32 setup_us, trans_us, total_us;
+	const int numframes = 100;
+	static u32 s_trans_us, s_min_us = 0xffffffff, s_max_us;
+
+	if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED)
+		return;
+
+	t = ktime_get();
+
+	setup_time = ktime_sub(dsi.perf_start_time, dsi.perf_setup_time);
+	setup_us = (u32)ktime_to_us(setup_time);
+	if (setup_us == 0)
+		setup_us = 1;
+
+	trans_time = ktime_sub(t, dsi.perf_start_time);
+	trans_us = (u32)ktime_to_us(trans_time);
+	if (trans_us == 0)
+		trans_us = 1;
+
+	total_us = setup_us + trans_us;
+
+	total_bytes = dsi.update_region.w *
+		dsi.update_region.h *
+		dsi.update_region.bytespp;
+
+	if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
+		dsi.perf_measure_frames++;
+
+		if (trans_us < s_min_us)
+			s_min_us = trans_us;
+
+		if (trans_us > s_max_us)
+			s_max_us = trans_us;
+
+		s_trans_us += trans_us;
+
+		if (dsi.perf_measure_frames < numframes)
+			return;
+
+		DSSINFO("%s update: %d frames in %u us (min/max %u/%u), "
+				"%u fps\n",
+				name, numframes,
+				s_trans_us,
+				s_min_us,
+				s_max_us,
+				1000*1000 / (s_trans_us / numframes));
+
+		dsi.perf_measure_frames = 0;
+		s_trans_us = 0;
+		s_min_us = 0xffffffff;
+		s_max_us = 0;
+	} else {
+		DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, "
+				"%u kbytes/sec\n",
+				name,
+				setup_us,
+				trans_us,
+				total_us,
+				1000*1000 / total_us,
+				total_bytes,
+				total_bytes * 1000 / total_us);
+	}
+}
+#else
+#define perf_mark_setup()
+#define perf_mark_start()
+#define perf_show(x)
+#endif
+
+
+
+
+static void print_irq_status(u32 status)
+{
+#ifndef VERBOSE_IRQ
+	if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
+		return;
+#endif
+	printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status);
+
+#define PIS(x) \
+	if (status & DSI_IRQ_##x) \
+		printk(#x " ");
+#ifdef VERBOSE_IRQ
+	PIS(VC0);
+	PIS(VC1);
+	PIS(VC2);
+	PIS(VC3);
+#endif
+	PIS(WAKEUP);
+	PIS(RESYNC);
+	PIS(PLL_LOCK);
+	PIS(PLL_UNLOCK);
+	PIS(PLL_RECALL);
+	PIS(COMPLEXIO_ERR);
+	PIS(HS_TX_TIMEOUT);
+	PIS(LP_RX_TIMEOUT);
+	PIS(TE_TRIGGER);
+	PIS(ACK_TRIGGER);
+	PIS(SYNC_LOST);
+	PIS(LDO_POWER_GOOD);
+	PIS(TA_TIMEOUT);
+#undef PIS
+
+	printk("\n");
+}
+
+static void print_irq_status_vc(int channel, u32 status)
+{
+#ifndef VERBOSE_IRQ
+	if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
+		return;
+#endif
+	printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status);
+
+#define PIS(x) \
+	if (status & DSI_VC_IRQ_##x) \
+		printk(#x " ");
+	PIS(CS);
+	PIS(ECC_CORR);
+#ifdef VERBOSE_IRQ
+	PIS(PACKET_SENT);
+#endif
+	PIS(FIFO_TX_OVF);
+	PIS(FIFO_RX_OVF);
+	PIS(BTA);
+	PIS(ECC_NO_CORR);
+	PIS(FIFO_TX_UDF);
+	PIS(PP_BUSY_CHANGE);
+#undef PIS
+	printk("\n");
+}
+
+static void print_irq_status_cio(u32 status)
+{
+	printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
+
+#define PIS(x) \
+	if (status & DSI_CIO_IRQ_##x) \
+		printk(#x " ");
+	PIS(ERRSYNCESC1);
+	PIS(ERRSYNCESC2);
+	PIS(ERRSYNCESC3);
+	PIS(ERRESC1);
+	PIS(ERRESC2);
+	PIS(ERRESC3);
+	PIS(ERRCONTROL1);
+	PIS(ERRCONTROL2);
+	PIS(ERRCONTROL3);
+	PIS(STATEULPS1);
+	PIS(STATEULPS2);
+	PIS(STATEULPS3);
+	PIS(ERRCONTENTIONLP0_1);
+	PIS(ERRCONTENTIONLP1_1);
+	PIS(ERRCONTENTIONLP0_2);
+	PIS(ERRCONTENTIONLP1_2);
+	PIS(ERRCONTENTIONLP0_3);
+	PIS(ERRCONTENTIONLP1_3);
+	PIS(ULPSACTIVENOT_ALL0);
+	PIS(ULPSACTIVENOT_ALL1);
+#undef PIS
+
+	printk("\n");
+}
+
+static int debug_irq;
+
+/* called from dss */
+void dsi_irq_handler(void)
+{
+	u32 irqstatus, vcstatus, ciostatus;
+	int i;
+
+	irqstatus = dsi_read_reg(DSI_IRQSTATUS);
+
+	if (irqstatus & DSI_IRQ_ERROR_MASK) {
+		DSSERR("DSI error, irqstatus %x\n", irqstatus);
+		print_irq_status(irqstatus);
+	} else if (debug_irq) {
+		print_irq_status(irqstatus);
+	}
+
+	for (i = 0; i < 4; ++i) {
+		if ((irqstatus & (1<<i)) == 0)
+			continue;
+
+		vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i));
+
+		if (vcstatus & DSI_VC_IRQ_BTA)
+			complete(&dsi.bta_completion);
+
+		if (vcstatus & DSI_VC_IRQ_ERROR_MASK) {
+			DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
+				       i, vcstatus);
+			print_irq_status_vc(i, vcstatus);
+		} else if (debug_irq) {
+			print_irq_status_vc(i, vcstatus);
+		}
+
+		dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus);
+	}
+
+	if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
+		ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
+
+		dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
+
+		DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
+		print_irq_status_cio(ciostatus);
+	}
+
+	dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
+}
+
+
+static void _dsi_initialize_irq(void)
+{
+	u32 l;
+	int i;
+
+	/* disable all interrupts */
+	dsi_write_reg(DSI_IRQENABLE, 0);
+	for (i = 0; i < 4; ++i)
+		dsi_write_reg(DSI_VC_IRQENABLE(i), 0);
+	dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0);
+
+	/* clear interrupt status */
+	l = dsi_read_reg(DSI_IRQSTATUS);
+	dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK);
+
+	for (i = 0; i < 4; ++i) {
+		l = dsi_read_reg(DSI_VC_IRQSTATUS(i));
+		dsi_write_reg(DSI_VC_IRQSTATUS(i), l);
+	}
+
+	l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
+	dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l);
+
+	/* enable error irqs */
+	l = DSI_IRQ_ERROR_MASK;
+	dsi_write_reg(DSI_IRQENABLE, l);
+
+	l = DSI_VC_IRQ_ERROR_MASK;
+	for (i = 0; i < 4; ++i)
+		dsi_write_reg(DSI_VC_IRQENABLE(i), l);
+
+	/* XXX zonda responds incorrectly, causing control error:
+	   Exit from LP-ESC mode to LP11 uses wrong transition states on the
+	   data lines LP0 and LN0. */
+	dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE,
+			-1 & (~DSI_CIO_IRQ_ERRCONTROL2));
+}
+
+static void dsi_vc_enable_bta_irq(int channel)
+{
+	u32 l;
+
+	l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
+	l |= DSI_VC_IRQ_BTA;
+	dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
+}
+
+static void dsi_vc_disable_bta_irq(int channel)
+{
+	u32 l;
+
+	l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
+	l &= ~DSI_VC_IRQ_BTA;
+	dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
+}
+
+/* DSI func clock. this could also be DSI2_PLL_FCLK */
+static inline void enable_clocks(int enable)
+{
+	if (enable)
+		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+	else
+		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+}
+
+/* source clock for DSI PLL. this could also be PCLKFREE */
+static inline void dsi_enable_pll_clock(int enable)
+{
+	if (enable)
+		dss_clk_enable(DSS_CLK_FCK2);
+	else
+		dss_clk_disable(DSS_CLK_FCK2);
+
+	if (enable && dsi.pll_locked) {
+		if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1)
+			DSSERR("cannot lock PLL when enabling clocks\n");
+	}
+}
+
+#ifdef DEBUG
+static void _dsi_print_reset_status(void)
+{
+	u32 l;
+
+	if (!dss_debug)
+		return;
+
+	/* A dummy read using the SCP interface to any DSIPHY register is
+	 * required after DSIPHY reset to complete the reset of the DSI complex
+	 * I/O. */
+	l = dsi_read_reg(DSI_DSIPHY_CFG5);
+
+	printk(KERN_DEBUG "DSI resets: ");
+
+	l = dsi_read_reg(DSI_PLL_STATUS);
+	printk("PLL (%d) ", FLD_GET(l, 0, 0));
+
+	l = dsi_read_reg(DSI_COMPLEXIO_CFG1);
+	printk("CIO (%d) ", FLD_GET(l, 29, 29));
+
+	l = dsi_read_reg(DSI_DSIPHY_CFG5);
+	printk("PHY (%x, %d, %d, %d)\n",
+			FLD_GET(l, 28, 26),
+			FLD_GET(l, 29, 29),
+			FLD_GET(l, 30, 30),
+			FLD_GET(l, 31, 31));
+}
+#else
+#define _dsi_print_reset_status()
+#endif
+
+static inline int dsi_if_enable(int enable)
+{
+	DSSDBG("dsi_if_enable(%d)\n", enable);
+
+	enable = enable ? 1 : 0;
+	REG_FLD_MOD(DSI_CTRL, enable, 0, 0); /* IF_EN */
+
+	if (wait_for_bit_change(DSI_CTRL, 0, enable) != enable) {
+			DSSERR("Failed to set dsi_if_enable to %d\n", enable);
+			return -EIO;
+	}
+
+	return 0;
+}
+
+static unsigned long dsi_fclk_rate(void)
+{
+	unsigned long r;
+
+	if (dss_get_dsi_clk_source() == 0) {
+		/* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */
+		r = dss_clk_get_rate(DSS_CLK_FCK1);
+	} else {
+		/* DSI FCLK source is DSI2_PLL_FCLK */
+		r = dsi.dsi2_pll_fclk;
+	}
+
+	return r;
+}
+
+static int dsi_set_lp_clk_divisor(void)
+{
+	int n;
+	unsigned long dsi_fclk;
+	unsigned long mhz;
+
+	/* LP_CLK_DIVISOR, DSI fclk/n, should be 20MHz - 32kHz */
+
+	dsi_fclk = dsi_fclk_rate();
+
+	for (n = 1; n < (1 << 13) - 1; ++n) {
+		mhz = dsi_fclk / n;
+		if (mhz <= 20*1000*1000)
+			break;
+	}
+
+	if (n == (1 << 13) - 1) {
+		DSSERR("Failed to find LP_CLK_DIVISOR\n");
+		return -EINVAL;
+	}
+
+	DSSDBG("LP_CLK_DIV %d, LP_CLK %ld\n", n, mhz);
+
+	REG_FLD_MOD(DSI_CLK_CTRL, n, 12, 0);	/* LP_CLK_DIVISOR */
+	if (dsi_fclk > 30*1000*1000)
+		REG_FLD_MOD(DSI_CLK_CTRL, 1, 21, 21); /* LP_RX_SYNCHRO_ENABLE */
+
+	return 0;
+}
+
+
+enum dsi_pll_power_state {
+	DSI_PLL_POWER_OFF	= 0x0,
+	DSI_PLL_POWER_ON_HSCLK	= 0x1,
+	DSI_PLL_POWER_ON_ALL	= 0x2,
+	DSI_PLL_POWER_ON_DIV	= 0x3,
+};
+
+static int dsi_pll_power(enum dsi_pll_power_state state)
+{
+	int t = 0;
+
+	REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30);	/* PLL_PWR_CMD */
+
+	/* PLL_PWR_STATUS */
+	while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) {
+		udelay(1);
+		if (t++ > 1000) {
+			DSSERR("Failed to set DSI PLL power mode to %d\n",
+					state);
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
+int dsi_pll_calc_pck(int is_tft, unsigned long req_pck,
+		struct dsi_clock_info *cinfo)
+{
+	struct dsi_clock_info cur, best;
+	int min_fck_per_pck;
+	int match = 0;
+
+	if (req_pck == dsi.cache_req_pck &&
+			dsi.cache_cinfo.clkin == dss_clk_get_rate(DSS_CLK_FCK2)) {
+		DSSDBG("DSI clock info found from cache\n");
+		*cinfo = dsi.cache_cinfo;
+		return 0;
+	}
+
+	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
+
+	if (min_fck_per_pck &&
+		req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
+		DSSERR("Requested pixel clock not possible with the current "
+				"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
+				"the constraint off.\n");
+		min_fck_per_pck = 0;
+	}
+
+	DSSDBG("dsi_pll_calc\n");
+
+retry:
+	memset(&best, 0, sizeof(best));
+
+	memset(&cur, 0, sizeof(cur));
+	cur.clkin = dss_clk_get_rate(DSS_CLK_FCK2);
+	cur.use_dss2_fck = 1;
+	cur.highfreq = 0;
+
+	/* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
+	/* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
+	/* To reduce PLL lock time, keep Fint high (around 2 MHz) */
+	for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
+		if (cur.highfreq == 0)
+			cur.fint = cur.clkin / cur.regn;
+		else
+			cur.fint = cur.clkin / (2 * cur.regn);
+
+		if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
+			continue;
+
+		/* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
+		for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
+			unsigned long a, b;
+
+			a = 2 * cur.regm * (cur.clkin/1000);
+			b = cur.regn * (cur.highfreq + 1);
+			cur.dsiphy = a / b * 1000;
+
+			if (cur.dsiphy > 1800 * 1000 * 1000)
+				break;
+
+			/* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3  < 173MHz */
+			for (cur.regm3 = 1; cur.regm3 < REGM3_MAX;
+					++cur.regm3) {
+				cur.dispc_fck = cur.dsiphy / cur.regm3;
+
+				/* this will narrow down the search a bit,
+				 * but still give pixclocks below what was
+				 * requested */
+				if (cur.dispc_fck  < req_pck)
+					break;
+
+				if (cur.dispc_fck > DISPC_MAX_FCK)
+					continue;
+
+				if (min_fck_per_pck &&
+					cur.dispc_fck <
+						req_pck * min_fck_per_pck)
+					continue;
+
+				match = 1;
+
+				find_lck_pck_divs(is_tft, req_pck,
+						cur.dispc_fck,
+						&cur.lck_div,
+						&cur.pck_div);
+
+				cur.lck = cur.dispc_fck / cur.lck_div;
+				cur.pck = cur.lck / cur.pck_div;
+
+				if (abs(cur.pck - req_pck) <
+						abs(best.pck - req_pck)) {
+					best = cur;
+
+					if (cur.pck == req_pck)
+						goto found;
+				}
+			}
+		}
+	}
+found:
+	if (!match) {
+		if (min_fck_per_pck) {
+			DSSERR("Could not find suitable clock settings.\n"
+					"Turning FCK/PCK constraint off and"
+					"trying again.\n");
+			min_fck_per_pck = 0;
+			goto retry;
+		}
+
+		DSSERR("Could not find suitable clock settings.\n");
+
+		return -EINVAL;
+	}
+
+	/* DSI2_PLL_FCLK(MHz) = DSIPHY(MHz) / regm4  < 173MHz */
+	/* hardcoded 48MHz for now. what should it be? */
+	best.regm4 = best.dsiphy / 48000000;
+	if (best.regm4 > REGM4_MAX)
+		best.regm4 = REGM4_MAX;
+	best.dsi_fck = best.dsiphy / best.regm4;
+
+	if (cinfo)
+		*cinfo = best;
+
+	dsi.cache_req_pck = req_pck;
+	dsi.cache_clk_freq = 0;
+	dsi.cache_cinfo = best;
+
+	return 0;
+}
+
+static int dsi_pll_calc_ddrfreq(unsigned long clk_freq,
+		struct dsi_clock_info *cinfo)
+{
+	struct dsi_clock_info cur, best;
+	const int use_dss2_fck = 1;
+	unsigned long datafreq;
+
+	DSSDBG("dsi_pll_calc_ddrfreq\n");
+
+	if (clk_freq == dsi.cache_clk_freq &&
+			dsi.cache_cinfo.clkin == dss_clk_get_rate(DSS_CLK_FCK2)) {
+		DSSDBG("DSI clock info found from cache\n");
+		*cinfo = dsi.cache_cinfo;
+		return 0;
+	}
+
+	datafreq = clk_freq * 4;
+
+	memset(&best, 0, sizeof(best));
+
+	memset(&cur, 0, sizeof(cur));
+	cur.use_dss2_fck = use_dss2_fck;
+	if (use_dss2_fck) {
+		cur.clkin = dss_clk_get_rate(DSS_CLK_FCK2);
+		cur.highfreq = 0;
+	} else {
+		cur.clkin = dispc_pclk_rate();
+		if (cur.clkin < 32000000)
+			cur.highfreq = 0;
+		else
+			cur.highfreq = 1;
+	}
+
+	/* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
+	/* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
+	/* To reduce PLL lock time, keep Fint high (around 2 MHz) */
+	for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
+		if (cur.highfreq == 0)
+			cur.fint = cur.clkin / cur.regn;
+		else
+			cur.fint = cur.clkin / (2 * cur.regn);
+
+		if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
+			continue;
+
+		/* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
+		for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
+			unsigned long a, b;
+
+			a = 2 * cur.regm * (cur.clkin/1000);
+			b = cur.regn * (cur.highfreq + 1);
+			cur.dsiphy = a / b * 1000;
+
+			if (cur.dsiphy > 1800 * 1000 * 1000)
+				break;
+
+			if (abs(cur.dsiphy - datafreq) <
+					abs(best.dsiphy - datafreq)) {
+				best = cur;
+				/* DSSDBG("best %ld\n", best.dsiphy); */
+			}
+
+			if (cur.dsiphy == datafreq)
+				goto found;
+		}
+	}
+found:
+	/* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3  < 173MHz */
+	/* hardcoded 48MHz for now. what should it be? */
+	best.regm3 = best.dsiphy / (48000000);
+	if (best.regm3 > REGM3_MAX)
+		best.regm3 = REGM3_MAX;
+	best.dispc_fck = best.dsiphy / best.regm3;
+
+	/* DSI2_PLL_FCLK(MHz) = DSIPHY(MHz) / regm4  < 173MHz */
+	/* hardcoded 48MHz for now. what should it be? */
+	best.regm4 = best.dsiphy / (48000000);
+	if (best.regm4 > REGM4_MAX)
+		best.regm4 = REGM4_MAX;
+	best.dsi_fck = best.dsiphy / best.regm4;
+
+	if (cinfo)
+		*cinfo = best;
+
+	dsi.cache_clk_freq = clk_freq;
+	dsi.cache_req_pck = 0;
+	dsi.cache_cinfo = best;
+
+	return 0;
+}
+
+int dsi_pll_program(struct dsi_clock_info *cinfo)
+{
+	int r = 0;
+	u32 l;
+
+	DSSDBG("dsi_pll_program\n");
+
+	enable_clocks(1);
+	dsi_enable_pll_clock(1);
+
+	dsi.dsiphy = cinfo->dsiphy;
+	dsi.ddr_clk = dsi.dsiphy / 4;
+	dsi.dsi1_pll_fclk = cinfo->dispc_fck;
+	dsi.dsi2_pll_fclk = cinfo->dsi_fck;
+
+	DSSDBG("DSI Fint %ld\n", cinfo->fint);
+
+	DSSDBG("clkin (%s) rate %ld, highfreq %d\n",
+			cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree",
+			cinfo->clkin,
+			cinfo->highfreq);
+
+	/* DSIPHY == CLKIN4DDR */
+	DSSDBG("DSIPHY = 2 * %d / %d * %lu / %d = %lu\n",
+			cinfo->regm,
+			cinfo->regn,
+			cinfo->clkin,
+			cinfo->highfreq + 1,
+			cinfo->dsiphy);
+
+	DSSDBG("Data rate on 1 DSI lane %ld Mbps\n",
+			dsi.dsiphy / 1000 / 1000 / 2);
+
+	DSSDBG("Clock lane freq %ld Hz\n", dsi.ddr_clk);
+
+	DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n",
+			cinfo->regm3, cinfo->dispc_fck);
+	DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n",
+			cinfo->regm4, cinfo->dsi_fck);
+
+	REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */
+
+	l = dsi_read_reg(DSI_PLL_CONFIGURATION1);
+	l = FLD_MOD(l, 1, 0, 0);		/* DSI_PLL_STOPMODE */
+	l = FLD_MOD(l, cinfo->regn - 1, 7, 1);	/* DSI_PLL_REGN */
+	l = FLD_MOD(l, cinfo->regm, 18, 8);	/* DSI_PLL_REGM */
+	l = FLD_MOD(l, cinfo->regm3 - 1, 22, 19);	/* DSI_CLOCK_DIV */
+	l = FLD_MOD(l, cinfo->regm4 - 1, 26, 23);	/* DSIPROTO_CLOCK_DIV */
+	dsi_write_reg(DSI_PLL_CONFIGURATION1, l);
+
+	l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
+	l = FLD_MOD(l, 7, 4, 1);		/* DSI_PLL_FREQSEL */
+	/* DSI_PLL_CLKSEL */
+	l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1, 11, 11);
+	l = FLD_MOD(l, cinfo->highfreq, 12, 12);	/* DSI_PLL_HIGHFREQ */
+	l = FLD_MOD(l, 1, 13, 13);		/* DSI_PLL_REFEN */
+	l = FLD_MOD(l, 0, 14, 14);		/* DSIPHY_CLKINEN */
+	l = FLD_MOD(l, 1, 20, 20);		/* DSI_HSDIVBYPASS */
+	dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
+
+	REG_FLD_MOD(DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
+
+	if (wait_for_bit_change(DSI_PLL_GO, 0, 0) != 0) {
+		DSSERR("dsi pll go bit not going down.\n");
+		r = -EIO;
+		goto err;
+	}
+
+	if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) {
+		DSSERR("cannot lock PLL\n");
+		r = -EIO;
+		goto err;
+	}
+
+	dsi.pll_locked = 1;
+
+	l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
+	l = FLD_MOD(l, 0, 0, 0);	/* DSI_PLL_IDLE */
+	l = FLD_MOD(l, 0, 5, 5);	/* DSI_PLL_PLLLPMODE */
+	l = FLD_MOD(l, 0, 6, 6);	/* DSI_PLL_LOWCURRSTBY */
+	l = FLD_MOD(l, 0, 7, 7);	/* DSI_PLL_TIGHTPHASELOCK */
+	l = FLD_MOD(l, 0, 8, 8);	/* DSI_PLL_DRIFTGUARDEN */
+	l = FLD_MOD(l, 0, 10, 9);	/* DSI_PLL_LOCKSEL */
+	l = FLD_MOD(l, 1, 13, 13);	/* DSI_PLL_REFEN */
+	l = FLD_MOD(l, 1, 14, 14);	/* DSIPHY_CLKINEN */
+	l = FLD_MOD(l, 0, 15, 15);	/* DSI_BYPASSEN */
+	l = FLD_MOD(l, 1, 16, 16);	/* DSS_CLOCK_EN */
+	l = FLD_MOD(l, 0, 17, 17);	/* DSS_CLOCK_PWDN */
+	l = FLD_MOD(l, 1, 18, 18);	/* DSI_PROTO_CLOCK_EN */
+	l = FLD_MOD(l, 0, 19, 19);	/* DSI_PROTO_CLOCK_PWDN */
+	l = FLD_MOD(l, 0, 20, 20);	/* DSI_HSDIVBYPASS */
+	dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
+
+	DSSDBG("PLL config done\n");
+err:
+	enable_clocks(0);
+	dsi_enable_pll_clock(0);
+
+	return r;
+}
+
+int dsi_pll_init(int enable_hsclk, int enable_hsdiv)
+{
+	int r = 0;
+	enum dsi_pll_power_state pwstate;
+	struct dispc_clock_info cinfo;
+
+	DSSDBG("PLL init\n");
+
+	enable_clocks(1);
+	dsi_enable_pll_clock(1);
+
+	/* configure dispc fck and pixel clock to something sane */
+	r = dispc_calc_clock_div(1, 48 * 1000 * 1000, &cinfo);
+	if (r)
+		return r;
+
+	r = dispc_set_clock_div(&cinfo);
+	if (r) {
+		DSSERR("Failed to set basic clocks\n");
+		return r;
+	}
+
+	/* PLL does not come out of reset without this... */
+	dispc_pck_free_enable(1);
+
+	if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) {
+		DSSERR("PLL not coming out of reset.\n");
+		r = -ENODEV;
+		goto err;
+	}
+
+	/* ... but if left on, we get problems when planes do not
+	 * fill the whole display. No idea about this XXX */
+	dispc_pck_free_enable(0);
+
+	if (enable_hsclk && enable_hsdiv)
+		pwstate = DSI_PLL_POWER_ON_ALL;
+	else if (enable_hsclk)
+		pwstate = DSI_PLL_POWER_ON_HSCLK;
+	else if (enable_hsdiv)
+		pwstate = DSI_PLL_POWER_ON_DIV;
+	else
+		pwstate = DSI_PLL_POWER_OFF;
+
+	r = dsi_pll_power(pwstate);
+
+	if (r)
+		goto err;
+
+	enable_clocks(0);
+	dsi_enable_pll_clock(0);
+
+	DSSDBG("PLL init done\n");
+
+	return 0;
+err:
+	enable_clocks(0);
+	dsi_enable_pll_clock(0);
+	return r;
+}
+
+void dsi_pll_uninit(void)
+{
+	dsi.pll_locked = 0;
+	dsi_pll_power(DSI_PLL_POWER_OFF);
+	DSSDBG("PLL uninit done\n");
+}
+
+unsigned long dsi_get_dsi1_pll_rate(void)
+{
+	return dsi.dsi1_pll_fclk;
+}
+
+unsigned long dsi_get_dsi2_pll_rate(void)
+{
+	return dsi.dsi2_pll_fclk;
+}
+
+ssize_t dsi_print_clocks(char *buf, ssize_t size)
+{
+	ssize_t l = 0;
+	int clksel;
+
+	enable_clocks(1);
+
+	clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11);
+
+	l += snprintf(buf + l, size - l, "- dsi -\n");
+
+	l += snprintf(buf + l, size - l, "dsi fclk source = %s\n",
+			dss_get_dsi_clk_source() == 0 ?
+			"dss1_alwon_fclk" : "dsi2_pll_fclk");
+
+	l += snprintf(buf + l, size - l, "dsi pll source = %s\n",
+			clksel == 0 ?
+			"dss2_alwon_fclk" : "pclkfree");
+
+	l += snprintf(buf + l, size - l,
+			"DSIPHY\t\t%lu\nDDR_CLK\t\t%lu\n",
+			dsi.dsiphy, dsi.ddr_clk);
+
+	l += snprintf(buf + l, size - l,
+			"dsi1_pll_fck\t%lu (%s)\n"
+			"dsi2_pll_fck\t%lu (%s)\n",
+			dsi.dsi1_pll_fclk,
+			dss_get_dispc_clk_source() == 0 ? "off" : "on",
+			dsi.dsi2_pll_fclk,
+			dss_get_dsi_clk_source() == 0 ? "off" : "on");
+
+	enable_clocks(0);
+
+	return l;
+}
+
+
+enum dsi_complexio_power_state {
+	DSI_COMPLEXIO_POWER_OFF		= 0x0,
+	DSI_COMPLEXIO_POWER_ON		= 0x1,
+	DSI_COMPLEXIO_POWER_ULPS	= 0x2,
+};
+
+static int dsi_complexio_power(enum dsi_complexio_power_state state)
+{
+	int t = 0;
+
+	/* PWR_CMD */
+	REG_FLD_MOD(DSI_COMPLEXIO_CFG1, state, 28, 27);
+
+	/* PWR_STATUS */
+	while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) {
+		udelay(1);
+		if (t++ > 1000) {
+			DSSERR("failed to set complexio power state to "
+					"%d\n", state);
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
+static void dsi_complexio_config(struct omap_display *display)
+{
+	u32 r;
+
+	int clk_lane   = display->hw_config.u.dsi.clk_lane;
+	int data1_lane = display->hw_config.u.dsi.data1_lane;
+	int data2_lane = display->hw_config.u.dsi.data2_lane;
+	int clk_pol    = display->hw_config.u.dsi.clk_pol;
+	int data1_pol  = display->hw_config.u.dsi.data1_pol;
+	int data2_pol  = display->hw_config.u.dsi.data2_pol;
+
+	r = dsi_read_reg(DSI_COMPLEXIO_CFG1);
+	r = FLD_MOD(r, clk_lane, 2, 0);
+	r = FLD_MOD(r, clk_pol, 3, 3);
+	r = FLD_MOD(r, data1_lane, 6, 4);
+	r = FLD_MOD(r, data1_pol, 7, 7);
+	r = FLD_MOD(r, data2_lane, 10, 8);
+	r = FLD_MOD(r, data2_pol, 11, 11);
+	dsi_write_reg(DSI_COMPLEXIO_CFG1, r);
+
+	/* The configuration of the DSI complex I/O (number of data lanes,
+	   position, differential order) should not be changed while
+	   DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for
+	   the hardware to take into account a new configuration of the complex
+	   I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to
+	   follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1,
+	   then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set
+	   DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the
+	   DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the
+	   DSI complex I/O configuration is unknown. */
+
+	/*
+	REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
+	REG_FLD_MOD(DSI_CTRL, 0, 0, 0);
+	REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20);
+	REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
+	*/
+}
+
+static inline int ns2ddr(int ns)
+{
+	/* convert time in ns to ddr ticks, rounding up */
+	return (ns * (dsi.ddr_clk/1000/1000) + 999) / 1000;
+}
+
+static void dsi_complexio_timings(void)
+{
+	u32 r;
+	u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
+	u32 tlpx_half, tclk_trail, tclk_zero;
+	u32 tclk_prepare;
+
+	/* calculate timings */
+
+	/* 1 * DDR_CLK = 2 * UI */
+
+	/* min 40ns + 4*UI	max 85ns + 6*UI */
+	ths_prepare = ns2ddr(59) + 2;
+
+	/* min 145ns + 10*UI */
+	ths_prepare_ths_zero = ns2ddr(145) + 5;
+
+	/* min max(8*UI, 60ns+4*UI) */
+	ths_trail = max(4, ns2ddr(60) + 2);
+
+	/* min 100ns */
+	ths_exit = ns2ddr(100);
+
+	/* tlpx min 50n */
+	tlpx_half = ns2ddr(25);
+
+	/* min 60ns */
+	tclk_trail = ns2ddr(60);
+
+	/* min 38ns, max 95ns */
+	tclk_prepare = ns2ddr(38);
+
+	/* min tclk-prepare + tclk-zero = 300ns */
+	tclk_zero = ns2ddr(300 - 38);
+
+#ifdef VERBOSE
+	DSSDBG("ths_prepare %d, ths_prepare_ths_zero %d\n",
+		ths_prepare, ths_prepare_ths_zero);
+	DSSDBG("ths_trail %d, ths_exit %d\n", ths_trail, ths_exit);
+
+
+	DSSDBG("tlpx_half %d, tclk_trail %d, tclk_zero %d\n", tlpx_half,
+			tclk_trail, tclk_zero);
+	DSSDBG("tclk_prepare %d\n", tclk_prepare);
+#endif
+
+	/* program timings */
+
+	r = dsi_read_reg(DSI_DSIPHY_CFG0);
+	r = FLD_MOD(r, ths_prepare, 31, 24);
+	r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16);
+	r = FLD_MOD(r, ths_trail, 15, 8);
+	r = FLD_MOD(r, ths_exit, 7, 0);
+	dsi_write_reg(DSI_DSIPHY_CFG0, r);
+
+	r = dsi_read_reg(DSI_DSIPHY_CFG1);
+	r = FLD_MOD(r, tlpx_half, 22, 16);
+	r = FLD_MOD(r, tclk_trail, 15, 8);
+	r = FLD_MOD(r, tclk_zero, 7, 0);
+	dsi_write_reg(DSI_DSIPHY_CFG1, r);
+
+	r = dsi_read_reg(DSI_DSIPHY_CFG2);
+	r = FLD_MOD(r, tclk_prepare, 7, 0);
+	dsi_write_reg(DSI_DSIPHY_CFG2, r);
+}
+
+
+static int dsi_complexio_init(struct omap_display *display)
+{
+	int r = 0;
+
+	DSSDBG("dsi_complexio_init\n");
+
+	/* CIO_CLK_ICG, enable L3 clk to CIO */
+	REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
+
+	/* A dummy read using the SCP interface to any DSIPHY register is
+	 * required after DSIPHY reset to complete the reset of the DSI complex
+	 * I/O. */
+	dsi_read_reg(DSI_DSIPHY_CFG5);
+
+	if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) {
+		DSSERR("ComplexIO PHY not coming out of reset.\n");
+		r = -ENODEV;
+		goto err;
+	}
+
+	dsi_complexio_config(display);
+
+	r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON);
+
+	if (r)
+		goto err;
+
+	if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
+		DSSERR("ComplexIO not coming out of reset.\n");
+		r = -ENODEV;
+		goto err;
+	}
+
+	if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
+		DSSERR("ComplexIO LDO power down.\n");
+		r = -ENODEV;
+		goto err;
+	}
+
+	dsi_complexio_timings();
+
+	/*
+	   The configuration of the DSI complex I/O (number of data lanes,
+	   position, differential order) should not be changed while
+	   DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the
+	   hardware to recognize a new configuration of the complex I/O (done
+	   in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow
+	   this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next
+	   reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20]
+	   LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN
+	   bit to 1. If the sequence is not followed, the DSi complex I/O
+	   configuration is undetermined.
+	   */
+	dsi_if_enable(1);
+	dsi_if_enable(0);
+	REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
+	dsi_if_enable(1);
+	dsi_if_enable(0);
+
+	DSSDBG("CIO init done\n");
+err:
+	return r;
+}
+
+static void dsi_complexio_uninit(void)
+{
+	dsi_complexio_power(DSI_COMPLEXIO_POWER_OFF);
+}
+
+
+
+static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2,
+		enum fifo_size size3, enum fifo_size size4)
+{
+	u32 r = 0;
+	int add = 0;
+	int i;
+
+	dsi.vc[0].fifo_size = size1;
+	dsi.vc[1].fifo_size = size2;
+	dsi.vc[2].fifo_size = size3;
+	dsi.vc[3].fifo_size = size4;
+
+	for (i = 0; i < 4; i++) {
+		u8 v;
+		int size = dsi.vc[i].fifo_size;
+
+		if (add + size > 4) {
+			DSSERR("Illegal FIFO configuration\n");
+			BUG();
+		}
+
+		v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
+		r |= v << (8 * i);
+		/*DSSDBG("TX FIFO vc %d: size %d, add %d\n", i, size, add); */
+		add += size;
+	}
+
+	dsi_write_reg(DSI_TX_FIFO_VC_SIZE, r);
+}
+
+static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2,
+		enum fifo_size size3, enum fifo_size size4)
+{
+	u32 r = 0;
+	int add = 0;
+	int i;
+
+	dsi.vc[0].fifo_size = size1;
+	dsi.vc[1].fifo_size = size2;
+	dsi.vc[2].fifo_size = size3;
+	dsi.vc[3].fifo_size = size4;
+
+	for (i = 0; i < 4; i++) {
+		u8 v;
+		int size = dsi.vc[i].fifo_size;
+
+		if (add + size > 4) {
+			DSSERR("Illegal FIFO configuration\n");
+			BUG();
+		}
+
+		v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
+		r |= v << (8 * i);
+		/*DSSDBG("RX FIFO vc %d: size %d, add %d\n", i, size, add); */
+		add += size;
+	}
+
+	dsi_write_reg(DSI_RX_FIFO_VC_SIZE, r);
+}
+
+static int dsi_force_tx_stop_mode_io(void)
+{
+	u32 r;
+
+	r = dsi_read_reg(DSI_TIMING1);
+	r = FLD_MOD(r, 1, 15, 15);	/* FORCE_TX_STOP_MODE_IO */
+	dsi_write_reg(DSI_TIMING1, r);
+
+	if (wait_for_bit_change(DSI_TIMING1, 15, 0) != 0) {
+		DSSERR("TX_STOP bit not going down\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void dsi_vc_print_status(int channel)
+{
+	u32 r;
+
+	r = dsi_read_reg(DSI_VC_CTRL(channel));
+	DSSDBG("vc %d: TX_FIFO_NOT_EMPTY %d, BTA_EN %d, VC_BUSY %d, "
+			"TX_FIFO_FULL %d, RX_FIFO_NOT_EMPTY %d, ",
+			channel,
+			FLD_GET(r, 5, 5),
+			FLD_GET(r, 6, 6),
+			FLD_GET(r, 15, 15),
+			FLD_GET(r, 16, 16),
+			FLD_GET(r, 20, 20));
+
+	r = dsi_read_reg(DSI_TX_FIFO_VC_EMPTINESS);
+	DSSDBG("EMPTINESS %d\n", (r >> (8 * channel)) & 0xff);
+}
+
+static void dsi_vc_config(int channel)
+{
+	u32 r;
+
+	DSSDBG("dsi_vc_config %d\n", channel);
+
+	r = dsi_read_reg(DSI_VC_CTRL(channel));
+
+	r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */
+	r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN  */
+	r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
+	r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
+	r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
+	r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
+	r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
+
+	r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
+	r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
+
+	dsi_write_reg(DSI_VC_CTRL(channel), r);
+}
+
+static void dsi_vc_config_vp(int channel)
+{
+	u32 r;
+
+	DSSDBG("dsi_vc_config_vp\n");
+
+	r = dsi_read_reg(DSI_VC_CTRL(channel));
+
+	r = FLD_MOD(r, 1, 1, 1); /* SOURCE, 1 = video port */
+	r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */
+	r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
+	r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
+	r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
+	r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
+	r = FLD_MOD(r, 1, 9, 9); /* MODE_SPEED, high speed on/off */
+
+	r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
+	r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
+
+	dsi_write_reg(DSI_VC_CTRL(channel), r);
+}
+
+
+static int dsi_vc_enable(int channel, int enable)
+{
+	DSSDBG("dsi_vc_enable channel %d, enable %d\n", channel, enable);
+
+	enable = enable ? 1 : 0;
+
+	REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0);
+
+	if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) {
+			DSSERR("Failed to set dsi_vc_enable to %d\n", enable);
+			return -EIO;
+	}
+
+	return 0;
+}
+
+static void dsi_vc_enable_hs(int channel, int enable)
+{
+	DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
+
+	dsi_vc_enable(channel, 0);
+	dsi_if_enable(0);
+
+	REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 9, 9);
+
+	dsi_vc_enable(channel, 1);
+	dsi_if_enable(1);
+
+	dsi_force_tx_stop_mode_io();
+}
+
+static void dsi_vc_flush_long_data(int channel)
+{
+	while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
+		u32 val;
+		val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
+		DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n",
+				(val >> 0) & 0xff,
+				(val >> 8) & 0xff,
+				(val >> 16) & 0xff,
+				(val >> 24) & 0xff);
+	}
+}
+
+static u16 dsi_vc_flush_receive_data(int channel)
+{
+	/* RX_FIFO_NOT_EMPTY */
+	while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
+		u32 val;
+		u8 dt;
+		val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
+		DSSDBG("\trawval %#08x\n", val);
+		dt = FLD_GET(val, 7, 0);
+		if (dt == DSI_DT_RX_ACK_WITH_ERR) {
+			u16 err = FLD_GET(val, 23, 8);
+			DSSERR("\tACK with ERROR: %#x\n", err);
+			if (err & (1 << 9))
+				DSSERR("\t\tECC multibit\n");
+			if (err & (1 << 11))
+				DSSERR("\t\tData type not recognized\n");
+			if (err & (1 << 12))
+				DSSERR("\t\tInvalid VC ID\n");
+
+		} else if (dt == DSI_DT_RX_SHORT_READ_1) {
+			DSSDBG("\tDCS short response, 1 byte: %#x\n",
+					FLD_GET(val, 23, 8));
+			return FLD_GET(val, 23, 8);
+		} else if (dt == DSI_DT_RX_SHORT_READ_2) {
+			DSSDBG("\tDCS short response, 2 byte: %#x\n",
+					FLD_GET(val, 23, 8));
+			return FLD_GET(val, 23, 8);
+		} else if (dt == DSI_DT_RX_DCS_LONG_READ) {
+			DSSDBG("\tDCS long response, len %d\n",
+					FLD_GET(val, 23, 8));
+			dsi_vc_flush_long_data(channel);
+		} else {
+			DSSERR("\tunknown datatype\n");
+		}
+	}
+	return 0;
+}
+
+static int dsi_vc_send_bta(int channel)
+{
+	unsigned long tmo;
+
+	/*DSSDBG("dsi_vc_send_bta_sync %d\n", channel); */
+
+	if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {	/* RX_FIFO_NOT_EMPTY */
+		DSSERR("rx fifo not empty when sending BTA, dumping data:\n");
+		dsi_vc_flush_receive_data(channel);
+	}
+
+	REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
+
+	tmo = jiffies + msecs_to_jiffies(10);
+	while (REG_GET(DSI_VC_CTRL(channel), 6, 6) == 1) {
+		if (time_after(jiffies, tmo)) {
+			DSSERR("Failed to send BTA\n");
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+static int dsi_vc_send_bta_sync(int channel)
+{
+	int r = 0;
+
+	init_completion(&dsi.bta_completion);
+
+	dsi_vc_enable_bta_irq(channel);
+
+	r = dsi_vc_send_bta(channel);
+	if (r)
+		goto err;
+
+	if (wait_for_completion_timeout(&dsi.bta_completion,
+				msecs_to_jiffies(500)) == 0) {
+		DSSERR("Failed to receive BTA\n");
+		r = -EIO;
+		goto err;
+	}
+err:
+	dsi_vc_disable_bta_irq(channel);
+
+	return r;
+}
+
+static inline void dsi_vc_write_long_header(int channel, u8 data_type,
+		u16 len, u8 ecc)
+{
+	u32 val;
+	u8 data_id;
+
+	/*data_id = data_type | channel << 6; */
+	data_id = data_type | dsi.vc[channel].dest_per << 6;
+
+	val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
+		FLD_VAL(ecc, 31, 24);
+
+	dsi_write_reg(DSI_VC_LONG_PACKET_HEADER(channel), val);
+}
+
+static inline void dsi_vc_write_long_payload(int channel,
+		u8 b1, u8 b2, u8 b3, u8 b4)
+{
+	u32 val;
+
+	val = b4 << 24 | b3 << 16 | b2 << 8  | b1 << 0;
+
+/*	DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n",
+			b1, b2, b3, b4, val); */
+
+	dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(channel), val);
+}
+
+static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len,
+		u8 ecc)
+{
+	/*u32 val; */
+	int i;
+	u8 *p;
+	int r = 0;
+	u8 b1, b2, b3, b4;
+
+	/*DSSDBG("dsi_vc_send_long, %d bytes\n", len); */
+
+	/* len + header */
+	if (dsi.vc[channel].fifo_size * 32 * 4 < len + 4) {
+		DSSERR("unable to send long packet: packet too long.\n");
+		return -EINVAL;
+	}
+
+	dsi_vc_write_long_header(channel, data_type, len, ecc);
+
+	/*dsi_vc_print_status(0); */
+
+	p = data;
+	for (i = 0; i < len >> 2; i++) {
+		/*DSSDBG("\tsending full packet %d\n", i); */
+		/*dsi_vc_print_status(0); */
+
+		b1 = *p++;
+		b2 = *p++;
+		b3 = *p++;
+		b4 = *p++;
+
+		dsi_vc_write_long_payload(channel, b1, b2, b3, b4);
+	}
+
+	i = len % 4;
+	if (i) {
+		b1 = 0; b2 = 0; b3 = 0;
+
+		/*DSSDBG("\tsending remainder bytes %d\n", i); */
+
+		switch (i) {
+		case 3:
+			b1 = *p++;
+			b2 = *p++;
+			b3 = *p++;
+			break;
+		case 2:
+			b1 = *p++;
+			b2 = *p++;
+			break;
+		case 1:
+			b1 = *p++;
+			break;
+		}
+
+		dsi_vc_write_long_payload(channel, b1, b2, b3, 0);
+	}
+
+	return r;
+}
+
+static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc)
+{
+	u32 r;
+	u8 data_id;
+/*
+	DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
+			channel,
+			data_type, data & 0xff, (data >> 8) & 0xff);
+*/
+	if (FLD_GET(dsi_read_reg(DSI_VC_CTRL(channel)), 16, 16)) {
+		DSSERR("ERROR FIFO FULL, aborting transfer\n");
+		return -EINVAL;
+	}
+
+	data_id = data_type | channel << 6;
+
+	r = (data_id << 0) | (data << 8) | (ecc << 24);
+
+	dsi_write_reg(DSI_VC_SHORT_PACKET_HEADER(channel), r);
+
+	return 0;
+}
+
+int dsi_vc_send_null(int channel)
+{
+	u8 nullpkg[] = {0, 0, 0, 0};
+	return dsi_vc_send_long(0, DSI_DT_NULL_PACKET, nullpkg, 4, 0);
+}
+EXPORT_SYMBOL(dsi_vc_send_null);
+
+int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len)
+{
+	int r;
+
+	BUG_ON(len == 0);
+
+	if (len == 1) {
+		r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_0,
+				data[0], 0);
+	} else if (len == 2) {
+		r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_1,
+				data[0] | (data[1] << 8), 0);
+	} else {
+		/* 0x39 = DCS Long Write */
+		r = dsi_vc_send_long(channel, DSI_DT_DCS_LONG_WRITE,
+				data, len, 0);
+	}
+
+	return r;
+}
+EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
+
+int dsi_vc_dcs_write(int channel, u8 *data, int len)
+{
+	int r;
+
+	r = dsi_vc_dcs_write_nosync(channel, data, len);
+	if (r)
+		return r;
+
+	/* Some devices need time to process the msg in low power mode.
+	   This also makes the write synchronous, and checks that
+	   the peripheral is still alive */
+	r = dsi_vc_send_bta_sync(channel);
+
+	return r;
+}
+EXPORT_SYMBOL(dsi_vc_dcs_write);
+
+int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
+{
+	u32 val;
+	u8 dt;
+	int debug = 0;
+
+	if (debug)
+		DSSDBG("dsi_vc_dcs_read\n");
+
+	dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0);
+
+	dsi_vc_send_bta_sync(channel);
+
+	val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
+	if (debug)
+		DSSDBG("\trawval %#08x\n", val);
+	dt = FLD_GET(val, 7, 0);
+	if (dt == DSI_DT_RX_ACK_WITH_ERR) {
+		u16 err = FLD_GET(val, 23, 8);
+		DSSERR("\tACK with ERROR: %#x\n", err);
+		if (err & (1 << 9))
+			DSSERR("\t\tECC multibit\n");
+		if (err & (1 << 11))
+			DSSERR("\t\tData type not recognized\n");
+		if (err & (1 << 12))
+			DSSERR("\t\tInvalid VC ID\n");
+		return -1;
+
+	} else if (dt == DSI_DT_RX_SHORT_READ_1) {
+		u8 data = FLD_GET(val, 15, 8);
+		if (debug)
+			DSSDBG("\tDCS short response, 1 byte: %#x\n", data);
+
+		if (buflen < 1)
+			return -1;
+
+		buf[0] = data;
+
+		return 1;
+	} else if (dt == DSI_DT_RX_SHORT_READ_2) {
+		u16 data = FLD_GET(val, 23, 8);
+		if (debug)
+			DSSDBG("\tDCS short response, 2 byte: %#x\n", data);
+
+		if (buflen < 2)
+			return -1;
+
+		buf[0] = data & 0xff;
+		buf[1] = (data >> 8) & 0xff;
+
+		return 2;
+	} else if (dt == DSI_DT_RX_DCS_LONG_READ) {
+		int x;
+		int len = FLD_GET(val, 23, 8);
+		if (debug)
+			DSSDBG("\tDCS long response, len %d\n", len);
+
+		if (len > buflen)
+			return -1;
+
+		x = 0;
+		while (x < len) {
+			val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
+			if (debug)
+				DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 "
+						"%#02x\n",
+						(val >> 0) & 0xff,
+						(val >> 8) & 0xff,
+						(val >> 16) & 0xff,
+						(val >> 24) & 0xff);
+
+			if (x < len)
+				buf[x++] = (val >> 0) & 0xff;
+			if (x < len)
+				buf[x++] = (val >> 8) & 0xff;
+			if (x < len)
+				buf[x++] = (val >> 16) & 0xff;
+			if (x < len)
+				buf[x++] = (val >> 24) & 0xff;
+		}
+
+		return len;
+	} else {
+		DSSERR("\tunknown datatype\n");
+		return -1;
+	}
+}
+EXPORT_SYMBOL(dsi_vc_dcs_read);
+
+
+int dsi_vc_set_max_rx_packet_size(int channel, u16 len)
+{
+	return dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
+			len, 0);
+}
+EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
+
+
+static int dsi_set_lp_rx_timeout(int ns, int x4, int x16)
+{
+	u32 r;
+	unsigned long fck;
+	int ticks;
+
+	/* ticks in DSI_FCK */
+
+	fck = dsi_fclk_rate();
+	ticks = (fck / 1000 / 1000) * ns / 1000;
+
+	if (ticks > 0x1fff) {
+		DSSERR("LP_TX_TO too high\n");
+		return -EINVAL;
+	}
+
+	r = dsi_read_reg(DSI_TIMING2);
+	r = FLD_MOD(r, 1, 15, 15);	/* LP_RX_TO */
+	r = FLD_MOD(r, x16, 14, 14);	/* LP_RX_TO_X16 */
+	r = FLD_MOD(r, x4, 13, 13);	/* LP_RX_TO_X4 */
+	r = FLD_MOD(r, ticks, 12, 0);	/* LP_RX_COUNTER */
+	dsi_write_reg(DSI_TIMING2, r);
+
+	DSSDBG("LP_RX_TO %ld ns (%#x ticks)\n",
+			(ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
+			(fck / 1000 / 1000),
+			ticks);
+
+	return 0;
+}
+
+static int dsi_set_ta_timeout(int ns, int x8, int x16)
+{
+	u32 r;
+	unsigned long fck;
+	int ticks;
+
+	/* ticks in DSI_FCK */
+
+	fck = dsi_fclk_rate();
+	ticks = (fck / 1000 / 1000) * ns / 1000;
+
+	if (ticks > 0x1fff) {
+		DSSERR("TA_TO too high\n");
+		return -EINVAL;
+	}
+
+	r = dsi_read_reg(DSI_TIMING1);
+	r = FLD_MOD(r, 1, 31, 31);	/* TA_TO */
+	r = FLD_MOD(r, x16, 30, 30);	/* TA_TO_X16 */
+	r = FLD_MOD(r, x8, 29, 29);	/* TA_TO_X8 */
+	r = FLD_MOD(r, ticks, 28, 16);	/* TA_TO_COUNTER */
+	dsi_write_reg(DSI_TIMING1, r);
+
+	DSSDBG("TA_TO %ld ns (%#x ticks)\n",
+			(ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1) * 1000) /
+			(fck / 1000 / 1000),
+			ticks);
+
+	return 0;
+}
+
+static int dsi_set_stop_state_counter(int ns, int x4, int x16)
+{
+	u32 r;
+	unsigned long fck;
+	int ticks;
+
+	/* ticks in DSI_FCK */
+
+	fck = dsi_fclk_rate();
+	ticks = (fck / 1000 / 1000) * ns / 1000;
+
+	if (ticks > 0x1fff) {
+		DSSERR("STOP_STATE_COUNTER_IO too high\n");
+		return -EINVAL;
+	}
+
+	r = dsi_read_reg(DSI_TIMING1);
+	r = FLD_MOD(r, 1, 15, 15);	/* FORCE_TX_STOP_MODE_IO */
+	r = FLD_MOD(r, x16, 14, 14);	/* STOP_STATE_X16_IO */
+	r = FLD_MOD(r, x4, 13, 13);	/* STOP_STATE_X4_IO */
+	r = FLD_MOD(r, ticks, 12, 0);	/* STOP_STATE_COUNTER_IO */
+	dsi_write_reg(DSI_TIMING1, r);
+
+	DSSDBG("STOP_STATE_COUNTER %ld ns (%#x ticks)\n",
+			(ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
+			(fck / 1000 / 1000),
+			ticks);
+
+	return 0;
+}
+
+static int dsi_set_hs_tx_timeout(int ns, int x4, int x16)
+{
+	u32 r;
+	unsigned long fck;
+	int ticks;
+
+	/* ticks in TxByteClkHS */
+
+	fck = dsi.ddr_clk / 4;
+	ticks = (fck / 1000 / 1000) * ns / 1000;
+
+	if (ticks > 0x1fff) {
+		DSSERR("HS_TX_TO too high\n");
+		return -EINVAL;
+	}
+
+	r = dsi_read_reg(DSI_TIMING2);
+	r = FLD_MOD(r, 1, 31, 31);	/* HS_TX_TO */
+	r = FLD_MOD(r, x16, 30, 30);	/* HS_TX_TO_X16 */
+	r = FLD_MOD(r, x4, 29, 29);	/* HS_TX_TO_X8 (4 really) */
+	r = FLD_MOD(r, ticks, 28, 16);	/* HS_TX_TO_COUNTER */
+	dsi_write_reg(DSI_TIMING2, r);
+
+	DSSDBG("HS_TX_TO %ld ns (%#x ticks)\n",
+			(ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
+			(fck / 1000 / 1000),
+			ticks);
+
+	return 0;
+}
+static int dsi_proto_config(struct omap_display *display)
+{
+	u32 r;
+	int buswidth = 0;
+
+	dsi_config_tx_fifo(DSI_FIFO_SIZE_128,
+			DSI_FIFO_SIZE_0,
+			DSI_FIFO_SIZE_0,
+			DSI_FIFO_SIZE_0);
+
+	dsi_config_rx_fifo(DSI_FIFO_SIZE_128,
+			DSI_FIFO_SIZE_0,
+			DSI_FIFO_SIZE_0,
+			DSI_FIFO_SIZE_0);
+
+	/* XXX what values for the timeouts? */
+	dsi_set_stop_state_counter(1000, 0, 0);
+
+	dsi_set_ta_timeout(50000, 1, 1);
+
+	/* 3000ns * 16 */
+	dsi_set_lp_rx_timeout(3000, 0, 1);
+
+	/* 10000ns * 4 */
+	dsi_set_hs_tx_timeout(10000, 1, 0);
+
+	switch (display->ctrl->pixel_size) {
+	case 16:
+		buswidth = 0;
+		break;
+	case 18:
+		buswidth = 1;
+		break;
+	case 24:
+		buswidth = 2;
+		break;
+	default:
+		BUG();
+	}
+
+	r = dsi_read_reg(DSI_CTRL);
+	r = FLD_MOD(r, 1, 1, 1);	/* CS_RX_EN */
+	r = FLD_MOD(r, 1, 2, 2);	/* ECC_RX_EN */
+	r = FLD_MOD(r, 1, 3, 3);	/* TX_FIFO_ARBITRATION */
+	/* XXX what should the ratio be */
+	r = FLD_MOD(r, 0, 4, 4);	/* VP_CLK_RATIO, VP_PCLK = VP_CLK/2 */
+	r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
+	r = FLD_MOD(r, 0, 8, 8);	/* VP_CLK_POL */
+	r = FLD_MOD(r, 2, 13, 12);	/* LINE_BUFFER, 2 lines */
+	r = FLD_MOD(r, 1, 14, 14);	/* TRIGGER_RESET_MODE */
+	r = FLD_MOD(r, 1, 19, 19);	/* EOT_ENABLE */
+	r = FLD_MOD(r, 1, 24, 24);	/* DCS_CMD_ENABLE */
+	r = FLD_MOD(r, 0, 25, 25);	/* DCS_CMD_CODE, 1=start, 0=continue */
+
+	dsi_write_reg(DSI_CTRL, r);
+
+	/* we configure vc0 for L4 communication, and
+	 * vc1 for dispc */
+	dsi_vc_config(0);
+	dsi_vc_config_vp(1);
+
+	/* set all vc targets to peripheral 0 */
+	dsi.vc[0].dest_per = 0;
+	dsi.vc[1].dest_per = 0;
+	dsi.vc[2].dest_per = 0;
+	dsi.vc[3].dest_per = 0;
+
+	return 0;
+}
+
+static void dsi_proto_timings(void)
+{
+	int tlpx_half, tclk_zero, tclk_prepare, tclk_trail;
+	int tclk_pre, tclk_post;
+	int ddr_clk_pre, ddr_clk_post;
+	u32 r;
+
+	r = dsi_read_reg(DSI_DSIPHY_CFG1);
+	tlpx_half = FLD_GET(r, 22, 16);
+	tclk_trail = FLD_GET(r, 15, 8);
+	tclk_zero = FLD_GET(r, 7, 0);
+
+	r = dsi_read_reg(DSI_DSIPHY_CFG2);
+	tclk_prepare = FLD_GET(r, 7, 0);
+
+	/* min 8*UI */
+	tclk_pre = 20;
+	/* min 60ns + 52*UI */
+	tclk_post = ns2ddr(60) + 26;
+
+	ddr_clk_pre = (tclk_pre + tlpx_half*2 + tclk_zero + tclk_prepare) / 4;
+	ddr_clk_post = (tclk_post + tclk_trail) / 4;
+
+	r = dsi_read_reg(DSI_CLK_TIMING);
+	r = FLD_MOD(r, ddr_clk_pre, 15, 8);
+	r = FLD_MOD(r, ddr_clk_post, 7, 0);
+	dsi_write_reg(DSI_CLK_TIMING, r);
+
+#ifdef VERBOSE
+	DSSDBG("ddr_clk_pre %d, ddr_clk_post %d\n",
+			ddr_clk_pre,
+			ddr_clk_post);
+#endif
+}
+
+
+#define DSI_DECL_VARS \
+	int __dsi_cb = 0; u32 __dsi_cv = 0;
+
+#define DSI_FLUSH(ch) \
+	if (__dsi_cb > 0) { \
+		/*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \
+		dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \
+		__dsi_cb = __dsi_cv = 0; \
+	}
+
+#define DSI_PUSH(ch, data) \
+	do { \
+		__dsi_cv |= (data) << (__dsi_cb * 8); \
+		/*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \
+		if (++__dsi_cb > 3) \
+			DSI_FLUSH(ch); \
+	} while (0)
+
+static int dsi_update_screen_l4(struct omap_display *display,
+			int x, int y, int w, int h)
+{
+	/* Note: supports only 24bit colors in 32bit container */
+	int first = 1;
+	int fifo_stalls = 0;
+	int max_dsi_packet_size;
+	int max_data_per_packet;
+	int max_pixels_per_packet;
+	int pixels_left;
+	int bytespp = 3;
+	int scr_width;
+	u32 *data;
+	int start_offset;
+	int horiz_inc;
+	int current_x;
+	struct omap_overlay *ovl;
+
+	debug_irq = 0;
+
+	DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n",
+			x, y, w, h);
+
+	ovl = &display->manager->overlays[0];
+
+	if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U)
+		return -EINVAL;
+
+	if (display->ctrl->pixel_size != 24)
+		return -EINVAL;
+
+	enable_clocks(1);
+	dsi_enable_pll_clock(1);
+
+	scr_width = ovl->info.screen_width;
+	data = ovl->info.vaddr;
+
+	start_offset = scr_width * y + x;
+	horiz_inc = scr_width - w;
+	current_x = x;
+
+	/* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes
+	 * in fifo */
+
+	/* When using CPU, max long packet size is TX buffer size */
+	max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4;
+
+	/* we seem to get better perf if we divide the tx fifo to half,
+	   and while the other half is being sent, we fill the other half
+	   max_dsi_packet_size /= 2; */
+
+	max_data_per_packet = max_dsi_packet_size - 4 - 1;
+
+	max_pixels_per_packet = max_data_per_packet / bytespp;
+
+	DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet);
+
+	display->ctrl->setup_update(display, x, y, w, h);
+
+	pixels_left = w * h;
+
+	DSSDBG("total pixels %d\n", pixels_left);
+
+	data += start_offset;
+
+	dsi.update_region.x = x;
+	dsi.update_region.y = y;
+	dsi.update_region.w = w;
+	dsi.update_region.h = h;
+	dsi.update_region.bytespp = bytespp;
+
+	perf_mark_start();
+
+	while (pixels_left > 0) {
+		/* 0x2c = write_memory_start */
+		/* 0x3c = write_memory_continue */
+		u8 dcs_cmd = first ? 0x2c : 0x3c;
+		int pixels;
+		DSI_DECL_VARS;
+		first = 0;
+
+#if 1
+		/* using fifo not empty */
+		/* TX_FIFO_NOT_EMPTY */
+		while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) {
+			udelay(1);
+			fifo_stalls++;
+			if (fifo_stalls > 0xfffff) {
+				DSSERR("fifo stalls overflow, pixels left %d\n",
+						pixels_left);
+				dsi_if_enable(0);
+				enable_clocks(0);
+				return -EIO;
+			}
+		}
+#elif 1
+		/* using fifo emptiness */
+		while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 <
+				max_dsi_packet_size) {
+			fifo_stalls++;
+			if (fifo_stalls > 0xfffff) {
+				DSSERR("fifo stalls overflow, pixels left %d\n",
+					       pixels_left);
+				dsi_if_enable(0);
+				enable_clocks(0);
+				return -EIO;
+			}
+		}
+#else
+		while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 == 0) {
+			fifo_stalls++;
+			if (fifo_stalls > 0xfffff) {
+				DSSERR("fifo stalls overflow, pixels left %d\n",
+					       pixels_left);
+				dsi_if_enable(0);
+				enable_clocks(0);
+				return -EIO;
+			}
+		}
+#endif
+		pixels = min(max_pixels_per_packet, pixels_left);
+
+		pixels_left -= pixels;
+
+		dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE,
+				1 + pixels * bytespp, 0);
+
+		DSI_PUSH(0, dcs_cmd);
+
+		while (pixels-- > 0) {
+			u32 pix = *data++;
+
+			DSI_PUSH(0, (pix >> 16) & 0xff);
+			DSI_PUSH(0, (pix >> 8) & 0xff);
+			DSI_PUSH(0, (pix >> 0) & 0xff);
+
+			current_x++;
+			if (current_x == x+w) {
+				current_x = x;
+				data += horiz_inc;
+			}
+		}
+
+		DSI_FLUSH(0);
+	}
+
+	perf_show("L4");
+
+	enable_clocks(0);
+	dsi_enable_pll_clock(0);
+
+	return 0;
+}
+
+#if 0
+static void dsi_clear_screen_l4(struct omap_display *display,
+			int x, int y, int w, int h)
+{
+	int first = 1;
+	int fifo_stalls = 0;
+	int max_dsi_packet_size;
+	int max_data_per_packet;
+	int max_pixels_per_packet;
+	int pixels_left;
+	int bytespp = 3;
+	int pixnum;
+
+	debug_irq = 0;
+
+	DSSDBG("dsi_clear_screen_l4 (%d,%d %dx%d)\n",
+			x, y, w, h);
+
+	if (display->ctrl->bpp != 24)
+		return -EINVAL;
+
+	/* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp)
+	 * bytes in fifo */
+
+	/* When using CPU, max long packet size is TX buffer size */
+	max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4;
+
+	max_data_per_packet = max_dsi_packet_size - 4 - 1;
+
+	max_pixels_per_packet = max_data_per_packet / bytespp;
+
+	enable_clocks(1);
+
+	display->ctrl->setup_update(display, x, y, w, h);
+
+	pixels_left = w * h;
+
+	dsi.update_region.x = x;
+	dsi.update_region.y = y;
+	dsi.update_region.w = w;
+	dsi.update_region.h = h;
+	dsi.update_region.bytespp = bytespp;
+
+	start_measuring();
+
+	pixnum = 0;
+
+	while (pixels_left > 0) {
+		/* 0x2c = write_memory_start */
+		/* 0x3c = write_memory_continue */
+		u8 dcs_cmd = first ? 0x2c : 0x3c;
+		int pixels;
+		DSI_DECL_VARS;
+		first = 0;
+
+		/* TX_FIFO_NOT_EMPTY */
+		while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) {
+			fifo_stalls++;
+			if (fifo_stalls > 0xfffff) {
+				DSSERR("fifo stalls overflow\n");
+				dsi_if_enable(0);
+				enable_clocks(0);
+				return;
+			}
+		}
+
+		pixels = min(max_pixels_per_packet, pixels_left);
+
+		pixels_left -= pixels;
+
+		dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE,
+				1 + pixels * bytespp, 0);
+
+		DSI_PUSH(0, dcs_cmd);
+
+		while (pixels-- > 0) {
+			u32 pix;
+
+			pix = 0x000000;
+
+			DSI_PUSH(0, (pix >> 16) & 0xff);
+			DSI_PUSH(0, (pix >> 8) & 0xff);
+			DSI_PUSH(0, (pix >> 0) & 0xff);
+		}
+
+		DSI_FLUSH(0);
+	}
+
+	enable_clocks(0);
+
+	end_measuring("L4 CLEAR");
+}
+#endif
+
+static int dsi_wait_for_framedone(int stop_update)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dsi.update_lock, flags);
+	if (dsi.update_ongoing) {
+		long wait = msecs_to_jiffies(1000);
+		dsi.update_syncers++;
+		if (stop_update)
+			dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
+		spin_unlock_irqrestore(&dsi.update_lock, flags);
+		wait = wait_for_completion_timeout(&dsi.update_completion,
+				wait);
+		if (wait == 0) {
+			DSSERR("timeout waiting sync\n");
+			return -ETIME;
+		}
+	} else {
+		spin_unlock_irqrestore(&dsi.update_lock, flags);
+	}
+
+	return 0;
+}
+
+static void dsi_setup_update_dispc(struct omap_display *display,
+			int x, int y, int w, int h)
+{
+	int bytespp = 3;
+
+	DSSDBG("dsi_setup_update_dispc(%d,%d %dx%d)\n",
+			x, y, w, h);
+
+	dsi.update_region.display = display;
+	dsi.update_region.x = x;
+	dsi.update_region.y = y;
+	dsi.update_region.w = w;
+	dsi.update_region.h = h;
+	dsi.update_region.bytespp = bytespp;
+
+	enable_clocks(1);
+
+	dispc_setup_partial_planes(display, &x, &y, &w, &h);
+
+	dispc_set_lcd_size(w, h);
+
+	enable_clocks(0);
+}
+
+static void dsi_update_screen_dispc(struct omap_display *display)
+{
+	int bytespp = 3;
+	int total_len;
+	int line_packet_len;
+	int x, y, w, h;
+	u32 l;
+
+	x = dsi.update_region.x;
+	y = dsi.update_region.y;
+	w = dsi.update_region.w;
+	h = dsi.update_region.h;
+
+	if (dsi.user_update_mode != OMAP_DSS_UPDATE_AUTO)
+		DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
+				x, y, w, h);
+
+	enable_clocks(1);
+	dsi_enable_pll_clock(1);
+
+	/* TODO: one packet could be longer, I think? Max is the line buffer */
+	line_packet_len = w * bytespp + 1;	/* 1 byte for DCS cmd */
+	total_len = line_packet_len * h;
+
+	display->ctrl->setup_update(display, x, y, w, h);
+
+	if (0)
+		dsi_vc_print_status(1);
+
+	perf_mark_start();
+
+	l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
+	dsi_write_reg(DSI_VC_TE(1), l);
+
+	dsi_vc_write_long_header(1, DSI_DT_DCS_LONG_WRITE, line_packet_len, 0);
+
+	if (dsi.use_te)
+		l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
+	else
+		l = FLD_MOD(l, 1, 31, 31); /* TE_START */
+	dsi_write_reg(DSI_VC_TE(1), l);
+
+	dispc_enable_lcd_out(1);
+
+	if (dsi.use_te)
+		dsi_vc_send_bta(1);
+}
+
+static void framedone_callback(void *data, u32 mask)
+{
+	if (dsi.framedone_scheduled) {
+		DSSERR("Framedone already scheduled. Bogus FRAMEDONE IRQ?\n");
+		return;
+	}
+
+	dsi.framedone_scheduled = 1;
+
+	/* We get FRAMEDONE when DISPC has finished sending pixels and turns
+	 * itself off. However, DSI still has the pixels in its buffers, and
+	 * is sending the data. Thus we have to wait until we can do a new
+	 * transfer or turn the clocks off. We do that in a separate work
+	 * func. */
+	/* XXX When using auto update and delay value 0, the kernel seems to be
+	 * very relaxed about when to call our callback. It may take a second.
+	 * Thus we use a delay of 1 */
+	if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
+		schedule_delayed_work(&dsi.framedone_work, 1);
+	else
+		schedule_delayed_work(&dsi.framedone_work, 0);
+}
+
+static void framedone_worker(struct work_struct *work)
+{
+	unsigned long flags;
+	u32 l;
+	unsigned long tmo;
+	int i = 0;
+
+	l = REG_GET(DSI_VC_TE(1), 23, 0); /* TE_SIZE */
+
+	/* There shouldn't be much stuff in DSI buffers, if any, so we'll
+	 * just busyloop */
+	if (l > 0) {
+		tmo = jiffies + msecs_to_jiffies(50);
+		while (REG_GET(DSI_VC_TE(1), 23, 0) > 0) { /* TE_SIZE */
+			i++;
+			if (time_after(jiffies, tmo)) {
+				DSSERR("timeout waiting TE_SIZE to zero\n");
+				break;
+			}
+			cpu_relax();
+		}
+	}
+
+	if (REG_GET(DSI_VC_TE(1), 30, 30))
+		DSSERR("TE_EN not zero\n");
+
+	if (REG_GET(DSI_VC_TE(1), 31, 31))
+		DSSERR("TE_START not zero\n");
+
+	spin_lock_irqsave(&dsi.update_lock, flags);
+	if (dsi.update_ongoing == 0) {
+		spin_unlock_irqrestore(&dsi.update_lock, flags);
+		DSSERR("framedone irq without update request\n");
+		return;
+	}
+	spin_unlock_irqrestore(&dsi.update_lock, flags);
+
+	perf_show("DISPC");
+
+	if (dsi.user_update_mode != OMAP_DSS_UPDATE_AUTO)
+		DSSDBG("FRAMEDONE\n");
+
+#if 0
+	if (l)
+		DSSWARN("FRAMEDONE irq too early, %d bytes, %d loops\n", l, i);
+#else
+	if (l > 1024*3)
+		DSSWARN("FRAMEDONE irq too early, %d bytes, %d loops\n", l, i);
+#endif
+
+#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
+	dispc_fake_vsync_irq();
+#endif
+	enable_clocks(0);
+	dsi_enable_pll_clock(0);
+
+	dsi.framedone_scheduled = 0;
+
+	spin_lock_irqsave(&dsi.update_lock, flags);
+
+	if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
+		dsi.update_ongoing = 0;
+
+	while (dsi.update_syncers > 0) {
+		complete(&dsi.update_completion);
+		--dsi.update_syncers;
+	}
+
+	if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
+		spin_unlock_irqrestore(&dsi.update_lock, flags);
+		dsi_update_screen_dispc(dsi.update_region.display);
+	} else {
+		spin_unlock_irqrestore(&dsi.update_lock, flags);
+	}
+}
+
+static void dsi_start_auto_update(struct omap_display *display)
+{
+	unsigned long flags;
+	int bytespp = 3;
+
+	DSSDBG("starting auto update\n");
+
+	dsi.update_region.display = display;
+	dsi.update_region.x = 0;
+	dsi.update_region.y = 0;
+	dsi.update_region.w = display->panel->timings.x_res;
+	dsi.update_region.h = display->panel->timings.y_res;
+	dsi.update_region.bytespp = bytespp;
+
+	enable_clocks(1);
+	dsi_enable_pll_clock(1);
+
+	dispc_set_lcd_size(display->panel->timings.x_res,
+			display->panel->timings.y_res);
+
+	spin_lock_irqsave(&dsi.update_lock, flags);
+	dsi.update_ongoing = 1;
+	spin_unlock_irqrestore(&dsi.update_lock, flags);
+	dsi_update_screen_dispc(display);
+}
+
+static void dsi_stop_auto_update(void)
+{
+	DSSDBG("waiting for display to finish.\n");
+	dsi_wait_for_framedone(1);
+	DSSDBG("done waiting\n");
+
+	enable_clocks(0);
+	dsi_enable_pll_clock(0);
+}
+
+static int dsi_set_update_mode(struct omap_display *display,
+		enum omap_dss_update_mode mode)
+{
+	if (mode == dsi.update_mode)
+		return 0;
+
+	if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
+		dsi_stop_auto_update();
+	else if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
+		dsi_wait_for_framedone(0);
+
+	dsi.update_mode = mode;
+
+	if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
+		dsi_start_auto_update(display);
+
+	return 0;
+}
+
+/* Display funcs */
+
+static int dsi_display_enable(struct omap_display *display)
+{
+	int r = 0;
+	struct dsi_clock_info cinfo;
+	u32 low, high;
+
+	DSSDBG("dsi_display_enable\n");
+
+	mutex_lock(&dsi.lock);
+
+	if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
+		DSSERR("display already enabled\n");
+		r = -EINVAL;
+		goto err0;
+	}
+
+	enable_clocks(1);
+	dsi_enable_pll_clock(1);
+
+	r = omap_dispc_register_isr(framedone_callback, NULL,
+			DISPC_IRQ_FRAMEDONE);
+	if (r) {
+		DSSERR("can't get FRAMEDONE irq\n");
+		goto err1;
+	}
+
+	dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
+
+	dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_DSI);
+	dispc_enable_fifohandcheck(1);
+
+	dispc_set_burst_size(OMAP_DSS_GFX, OMAP_DSS_BURST_16x32);
+	dispc_set_burst_size(OMAP_DSS_VIDEO1, OMAP_DSS_BURST_16x32);
+	dispc_set_burst_size(OMAP_DSS_VIDEO2, OMAP_DSS_BURST_16x32);
+
+	high = dispc_get_plane_fifo_size(OMAP_DSS_GFX) - (16*32/8);
+	low = 0;
+	dispc_setup_plane_fifo(OMAP_DSS_GFX, low, high);
+
+	high = dispc_get_plane_fifo_size(OMAP_DSS_VIDEO1) - (16*32/8);
+	low = 0;
+	dispc_setup_plane_fifo(OMAP_DSS_VIDEO1, low, high);
+
+	high = dispc_get_plane_fifo_size(OMAP_DSS_VIDEO2) - (16*32/8);
+	low = 0;
+	dispc_setup_plane_fifo(OMAP_DSS_VIDEO2, low, high);
+
+	dispc_set_tft_data_lines(display->ctrl->pixel_size);
+
+	{
+		struct omap_video_timings timings = {
+			.hsw		= 1,
+			.hfp		= 1,
+			.hbp		= 1,
+			.vsw		= 1,
+			.vfp		= 0,
+			.vbp		= 0,
+		};
+
+		dispc_set_lcd_timings(&timings);
+	}
+
+	_dsi_print_reset_status();
+
+	r = dsi_pll_init(1, 0);
+	if (r)
+		goto err2;
+
+	r = dsi_pll_calc_ddrfreq(display->hw_config.u.dsi.ddr_clk_hz, &cinfo);
+	if (r)
+		goto err3;
+
+	r = dsi_pll_program(&cinfo);
+	if (r)
+		goto err3;
+
+	DSSDBG("PLL OK\n");
+
+	r = dsi_complexio_init(display);
+	if (r)
+		goto err3;
+
+	_dsi_print_reset_status();
+
+	dsi_proto_timings();
+	dsi_set_lp_clk_divisor();
+
+	if (1)
+		_dsi_print_reset_status();
+
+	r = dsi_proto_config(display);
+	if (r)
+		goto err4;
+
+	/* enable interface */
+	dsi_vc_enable(0, 1);
+	dsi_vc_enable(1, 1);
+	dsi_if_enable(1);
+	dsi_force_tx_stop_mode_io();
+
+
+	if (display->ctrl && display->ctrl->enable) {
+		r = display->ctrl->enable(display);
+		if (r)
+			goto err5;
+	}
+
+	if (display->panel && display->panel->enable) {
+		r = display->panel->enable(display);
+		if (r)
+			goto err6;
+	}
+
+	if (dsi.use_te) {
+		r = display->ctrl->enable_te(display, 1);
+		if (r)
+			goto err7;
+	}
+
+	/* enable high-speed after initial config */
+	dsi_vc_enable_hs(0, 1);
+
+	display->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	dsi_set_update_mode(display, dsi.user_update_mode);
+
+	enable_clocks(0);
+	dsi_enable_pll_clock(0);
+	mutex_unlock(&dsi.lock);
+
+	return 0;
+err7:
+	if (display->panel && display->panel->disable)
+		display->panel->disable(display);
+err6:
+	if (display->ctrl && display->ctrl->disable)
+		display->ctrl->disable(display);
+err5:
+	dsi_if_enable(0);
+err4:
+	dsi_complexio_uninit();
+err3:
+	dsi_pll_uninit();
+err2:
+	omap_dispc_unregister_isr(framedone_callback);
+err1:
+	enable_clocks(0);
+	dsi_enable_pll_clock(0);
+err0:
+	mutex_unlock(&dsi.lock);
+	DSSDBG("dsi_display_enable FAILED\n");
+	return r;
+}
+
+static void dsi_display_disable(struct omap_display *display)
+{
+	DSSDBG("dsi_display_disable\n");
+
+	mutex_lock(&dsi.lock);
+
+	if (display->state == OMAP_DSS_DISPLAY_DISABLED)
+		goto end;
+
+	enable_clocks(1);
+	dsi_enable_pll_clock(1);
+
+	dsi_set_update_mode(display, OMAP_DSS_UPDATE_DISABLED);
+
+	display->state = OMAP_DSS_DISPLAY_DISABLED;
+
+	omap_dispc_unregister_isr(framedone_callback);
+
+	if (display->panel && display->panel->disable)
+		display->panel->disable(display);
+	if (display->ctrl && display->ctrl->disable)
+		display->ctrl->disable(display);
+
+	dsi_complexio_uninit();
+	dsi_pll_uninit();
+
+	enable_clocks(0);
+	dsi_enable_pll_clock(0);
+end:
+	mutex_unlock(&dsi.lock);
+}
+
+static int dsi_display_suspend(struct omap_display *display)
+{
+	if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
+		return -EINVAL;
+
+	if (display->panel->suspend)
+		display->panel->suspend(display);
+
+	if (display->ctrl->suspend)
+		display->ctrl->suspend(display);
+
+	display->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
+	return 0;
+}
+
+static int dsi_display_resume(struct omap_display *display)
+{
+	if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
+		return -EINVAL;
+
+	if (display->panel->resume)
+		display->panel->resume(display);
+
+	if (display->ctrl->resume)
+		display->ctrl->resume(display);
+
+	display->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	return 0;
+}
+
+static int dsi_display_update(struct omap_display *display,
+			int x, int y, int w, int h)
+{
+	unsigned long flags;
+	int r = 0;
+
+	DSSDBG("dsi_display_update(%d,%d %dx%d)\n", x, y, w, h);
+
+	if (w == 0 || h == 0)
+		return 0;
+
+	mutex_lock(&dsi.lock);
+
+	if (dsi.update_mode != OMAP_DSS_UPDATE_MANUAL)
+		goto end; /* XXX return error? */
+
+	spin_lock_irqsave(&dsi.update_lock, flags);
+
+	if (dsi.update_ongoing) {
+		spin_unlock_irqrestore(&dsi.update_lock, flags);
+		DSSERR("DSI is busy\n");
+		r = -EBUSY;
+		goto end;
+	}
+
+	perf_mark_setup();
+
+	dsi.update_ongoing = 1;
+
+	if (dsi.update_syncers > 0)
+		DSSERR("someone waiting for sync, and no update ongoing\n");
+
+	spin_unlock_irqrestore(&dsi.update_lock, flags);
+
+	if (display->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+		dsi_setup_update_dispc(display, x, y, w, h);
+		dsi_update_screen_dispc(display);
+	} else {
+		r = dsi_update_screen_l4(display, x, y, w, h);
+		if (r)
+			goto end;
+
+		spin_lock_irqsave(&dsi.update_lock, flags);
+		dsi.update_ongoing = 0;
+		while (dsi.update_syncers > 0) {
+			complete(&dsi.update_completion);
+			--dsi.update_syncers;
+		}
+		spin_unlock_irqrestore(&dsi.update_lock, flags);
+	}
+
+end:
+	mutex_unlock(&dsi.lock);
+	return r;
+}
+
+static int dsi_display_sync(struct omap_display *display)
+{
+	int r = 0;
+
+	DSSDBG("dsi_display_sync\n");
+
+	mutex_lock(&dsi.lock);
+
+	if (dsi.update_mode != OMAP_DSS_UPDATE_MANUAL)
+		goto end;
+
+	r = dsi_wait_for_framedone(0);
+
+end:
+	mutex_unlock(&dsi.lock);
+	return r;
+}
+
+static int dsi_display_set_update_mode(struct omap_display *display,
+		enum omap_dss_update_mode mode)
+{
+	int r;
+
+	DSSDBG("dsi_display_set_update_mode\n");
+
+	mutex_lock(&dsi.lock);
+
+	r = dsi_set_update_mode(display, mode);
+	dsi.user_update_mode = mode;
+
+	mutex_unlock(&dsi.lock);
+
+	return r;
+}
+
+static enum omap_dss_update_mode dsi_display_get_update_mode(
+		struct omap_display *display)
+{
+	return dsi.user_update_mode;
+}
+
+static int dsi_display_enable_te(struct omap_display *display, int enable)
+{
+	DSSDBG("dsi_display_enable_te\n");
+
+	mutex_lock(&dsi.lock);
+
+	enable_clocks(1);
+	dsi_enable_pll_clock(1);
+
+	dsi_set_update_mode(display, OMAP_DSS_UPDATE_DISABLED);
+
+	dsi.use_te = enable;
+	display->ctrl->enable_te(display, enable);
+	if (enable) {
+		/* disable LP_RX_TO, so that we can receive TE.
+		 * Time to wait for TE is longer than the timer allows */
+		REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
+	} else {
+		REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
+	}
+
+	/* restore the old update mode */
+	dsi_set_update_mode(display, dsi.user_update_mode);
+
+	enable_clocks(0);
+	dsi_enable_pll_clock(0);
+
+	mutex_unlock(&dsi.lock);
+
+	return 0;
+}
+
+static int dsi_display_get_te(struct omap_display *display)
+{
+	return dsi.use_te;
+}
+
+static int dsi_display_run_test(struct omap_display *display, int test_num)
+{
+	int r = 0;
+
+	DSSDBG("dsi_display_run_test %d\n", test_num);
+
+	mutex_lock(&dsi.lock);
+
+	enable_clocks(1);
+	dsi_enable_pll_clock(1);
+
+	dsi_set_update_mode(display, OMAP_DSS_UPDATE_DISABLED);
+
+	/* run test first in low speed mode */
+	dsi_vc_enable_hs(0, 0);
+
+	if (display->ctrl->run_test) {
+		r = display->ctrl->run_test(display, test_num);
+		if (r)
+			goto fail;
+	}
+
+	if (display->panel->run_test) {
+		r = display->panel->run_test(display, test_num);
+		if (r)
+			goto fail;
+	}
+
+	/* then in high speed */
+	dsi_vc_enable_hs(0, 1);
+
+	if (display->ctrl->run_test) {
+		r = display->ctrl->run_test(display, test_num);
+		if (r)
+			goto fail;
+	}
+
+	if (display->panel->run_test)
+		r = display->panel->run_test(display, test_num);
+
+fail:
+	dsi_vc_enable_hs(0, 1);
+
+	/* restore the old update mode */
+	dsi_set_update_mode(display, dsi.user_update_mode);
+
+	enable_clocks(0);
+	dsi_enable_pll_clock(0);
+
+	mutex_unlock(&dsi.lock);
+
+	return r;
+}
+
+void dsi_init_display(struct omap_display *display)
+{
+	DSSDBG("DSI init\n");
+
+	display->enable = dsi_display_enable;
+	display->disable = dsi_display_disable;
+	display->suspend = dsi_display_suspend;
+	display->resume = dsi_display_resume;
+	display->update = dsi_display_update;
+	display->sync = dsi_display_sync;
+	display->set_update_mode = dsi_display_set_update_mode;
+	display->get_update_mode = dsi_display_get_update_mode;
+	display->enable_te = dsi_display_enable_te;
+	display->get_te = dsi_display_get_te;
+	display->run_test = dsi_display_run_test;
+
+	display->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
+}
+
+int dsi_init(void)
+{
+	u32 rev;
+
+	init_completion(&dsi.bta_completion);
+	INIT_DELAYED_WORK(&dsi.framedone_work, framedone_worker);
+
+	init_completion(&dsi.update_completion);
+	spin_lock_init(&dsi.update_lock);
+	dsi.update_ongoing = 0;
+	dsi.update_syncers = 0;
+
+	mutex_init(&dsi.lock);
+
+	dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS);
+	if (!dsi.base) {
+		DSSERR("can't ioremap DSI\n");
+		return -ENOMEM;
+	}
+
+	enable_clocks(1);
+
+	/* Autoidle */
+	REG_FLD_MOD(DSI_SYSCONFIG, 1, 0, 0);
+
+	/* ENWAKEUP */
+	REG_FLD_MOD(DSI_SYSCONFIG, 1, 2, 2);
+
+	/* SIDLEMODE smart-idle */
+	REG_FLD_MOD(DSI_SYSCONFIG, 2, 4, 3);
+
+	_dsi_initialize_irq();
+
+	rev = dsi_read_reg(DSI_REVISION);
+	printk(KERN_INFO "OMAP DSI rev %d.%d\n",
+	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+	enable_clocks(0);
+
+	return 0;
+}
+
+void dsi_exit(void)
+{
+	iounmap(dsi.base);
+
+	DSSDBG("omap_dsi_exit\n");
+}
+


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 06/12] DSS: OMAPFB: fb driver for new display subsystem
  2009-01-12 11:47 [PATCH 00/12] DSS: Series description Tomi Valkeinen
                   ` (4 preceding siblings ...)
  2009-01-12 11:47 ` [PATCH 05/12] DSS: DSI support Tomi Valkeinen
@ 2009-01-12 11:47 ` Tomi Valkeinen
  2009-01-12 11:48 ` [PATCH 07/12] DSS: Add generic DVI panel Tomi Valkeinen
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 23+ messages in thread
From: Tomi Valkeinen @ 2009-01-12 11:47 UTC (permalink / raw)
  To: linux-fbdev-devel; +Cc: linux-omap

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
---

 arch/arm/plat-omap/Makefile              |    2 
 arch/arm/plat-omap/fb-vram.c             |  646 +++++++++++++
 arch/arm/plat-omap/fb.c                  |   22 
 arch/arm/plat-omap/include/mach/omapfb.h |   14 
 drivers/video/Kconfig                    |    1 
 drivers/video/Makefile                   |    1 
 drivers/video/omap/Kconfig               |    5 
 drivers/video/omap2/Kconfig              |   42 +
 drivers/video/omap2/Makefile             |    2 
 drivers/video/omap2/omapfb-ioctl.c       |  460 ++++++++++
 drivers/video/omap2/omapfb-main.c        | 1442 ++++++++++++++++++++++++++++++
 drivers/video/omap2/omapfb-sysfs.c       |  901 +++++++++++++++++++
 drivers/video/omap2/omapfb.h             |  115 ++
 13 files changed, 3650 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/plat-omap/fb-vram.c
 create mode 100644 drivers/video/omap2/Kconfig
 create mode 100644 drivers/video/omap2/Makefile
 create mode 100644 drivers/video/omap2/omapfb-ioctl.c
 create mode 100644 drivers/video/omap2/omapfb-main.c
 create mode 100644 drivers/video/omap2/omapfb-sysfs.c
 create mode 100644 drivers/video/omap2/omapfb.h

diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 2740497..7d602a6 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := common.o sram.o clock.o devices.o dma.o mux.o gpio.o \
-	 usb.o fb.o io.o
+	 usb.o fb.o fb-vram.o io.o
 obj-m :=
 obj-n :=
 obj-  :=
diff --git a/arch/arm/plat-omap/fb-vram.c b/arch/arm/plat-omap/fb-vram.c
new file mode 100644
index 0000000..2994f8f
--- /dev/null
+++ b/arch/arm/plat-omap/fb-vram.c
@@ -0,0 +1,646 @@
+/*
+ * linux/arch/arm/plat-omap/fb-vram.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//#define DEBUG
+
+#include <linux/vmalloc.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/dma-mapping.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/bootmem.h>
+
+#include <asm/setup.h>
+
+#include <mach/sram.h>
+#include <mach/omapfb.h>
+
+#ifdef DEBUG
+#define DBG(format, ...) printk(KERN_DEBUG "VRAM: " format, ## __VA_ARGS__)
+#else
+#define DBG(format, ...)
+#endif
+
+#define OMAP2_SRAM_START		0x40200000
+/* Maximum size, in reality this is smaller if SRAM is partially locked. */
+#define OMAP2_SRAM_SIZE			0xa0000		/* 640k */
+
+#define REG_MAP_SIZE(_page_cnt)						\
+	((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8)
+#define REG_MAP_PTR(_rg, _page_nr)					\
+	(((_rg)->map) + (_page_nr) / (sizeof(unsigned long) * 8))
+#define REG_MAP_MASK(_page_nr)						\
+	(1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1)))
+
+#if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
+
+/* postponed regions are used to temporarily store region information at boot
+ * time when we cannot yet allocate the region list */
+#define MAX_POSTPONED_REGIONS 10
+
+static int postponed_cnt __initdata;
+static struct {
+	unsigned long paddr;
+	size_t size;
+} postponed_regions[MAX_POSTPONED_REGIONS] __initdata;
+
+struct vram_alloc {
+	struct list_head list;
+	unsigned long paddr;
+	unsigned pages;
+};
+
+struct vram_region {
+	struct list_head list;
+	struct list_head alloc_list;
+	unsigned long	paddr;
+	void		*vaddr;
+	unsigned	pages;
+	unsigned	dma_alloced:1;
+};
+
+static DEFINE_MUTEX(region_mutex);
+static LIST_HEAD(region_list);
+
+static inline int region_mem_type(unsigned long paddr)
+{
+	if (paddr >= OMAP2_SRAM_START &&
+	    paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
+		return OMAPFB_MEMTYPE_SRAM;
+	else
+		return OMAPFB_MEMTYPE_SDRAM;
+}
+
+static struct vram_region *omap_vram_create_region(unsigned long paddr,
+		void *vaddr, unsigned pages)
+{
+	struct vram_region *rm;
+
+	rm = kzalloc(sizeof(*rm), GFP_KERNEL);
+
+	if (rm) {
+		INIT_LIST_HEAD(&rm->alloc_list);
+		rm->paddr = paddr;
+		rm->vaddr = vaddr;
+		rm->pages = pages;
+	}
+
+	return rm;
+}
+
+static void omap_vram_free_region(struct vram_region *vr)
+{
+	list_del(&vr->list);
+	kfree(vr);
+}
+
+static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr,
+		unsigned long paddr, unsigned pages)
+{
+	struct vram_alloc *va;
+	struct vram_alloc *new;
+
+	new = kzalloc(sizeof(*va), GFP_KERNEL);
+
+	if (!new)
+		return NULL;
+
+	new->paddr = paddr;
+	new->pages = pages;
+
+	list_for_each_entry(va, &vr->alloc_list, list) {
+		if (va->paddr > new->paddr)
+			break;
+	}
+
+	list_add_tail(&new->list, &va->list);
+
+	return new;
+}
+
+static void omap_vram_free_allocation(struct vram_alloc *va)
+{
+	list_del(&va->list);
+	kfree(va);
+}
+
+static __init int omap_vram_add_region_postponed(unsigned long paddr, size_t size)
+{
+	if (postponed_cnt == MAX_POSTPONED_REGIONS)
+		return -ENOMEM;
+
+	postponed_regions[postponed_cnt].paddr = paddr;
+	postponed_regions[postponed_cnt].size = size;
+
+	++postponed_cnt;
+
+	return 0;
+}
+
+/* add/remove_region can be exported if there's need to add/remove regions
+ * runtime */
+static int omap_vram_add_region(unsigned long paddr, size_t size)
+{
+	struct vram_region *rm;
+	void *vaddr;
+	unsigned pages;
+
+	DBG("adding region paddr %08lx size %d\n",
+			paddr, size);
+
+	size &= PAGE_MASK;
+	pages = size >> PAGE_SHIFT;
+
+	vaddr = ioremap_wc(paddr, size);
+	if (vaddr == NULL)
+		return -ENOMEM;
+
+	rm = omap_vram_create_region(paddr, vaddr, pages);
+	if (rm == NULL) {
+		iounmap(vaddr);
+		return -ENOMEM;
+	}
+
+	list_add(&rm->list, &region_list);
+
+	return 0;
+}
+
+#if 0
+int omap_vram_remove_region(unsigned long paddr)
+{
+	struct region *rm;
+	unsigned i;
+
+	DBG("remove region paddr %08lx\n", paddr);
+	list_for_each_entry(rm, &region_list, list)
+		if (rm->paddr != paddr)
+			continue;
+
+	if (rm->paddr != paddr)
+		return -EINVAL;
+
+	for (i = 0; i < rm->page_cnt; i++)
+		if (region_page_reserved(rm, i))
+			return -EBUSY;
+
+	iounmap(rm->vaddr);
+
+	list_del(&rm->list);
+
+	kfree(rm);
+
+	return 0;
+}
+#endif
+
+int omap_vram_free(unsigned long paddr, void *vaddr, size_t size)
+{
+	struct vram_region *rm;
+	struct vram_alloc *alloc;
+	unsigned start, end;
+
+	DBG("free mem paddr %08lx vaddr %p size %d\n",
+			paddr, vaddr, size);
+
+	size = PAGE_ALIGN(size);
+
+	mutex_lock(&region_mutex);
+
+	list_for_each_entry(rm, &region_list, list) {
+		list_for_each_entry(alloc, &rm->alloc_list, list) {
+			start = alloc->paddr;
+			end = alloc->paddr + (alloc->pages >> PAGE_SHIFT);
+
+			if (start >= paddr && end < paddr + size)
+				goto found;
+		}
+	}
+
+	mutex_unlock(&region_mutex);
+	return -EINVAL;
+
+found:
+	if (rm->dma_alloced) {
+		DBG("freeing dma-alloced\n");
+		dma_free_writecombine(NULL, size, vaddr, paddr);
+		omap_vram_free_allocation(alloc);
+		omap_vram_free_region(rm);
+	} else {
+		omap_vram_free_allocation(alloc);
+	}
+
+	mutex_unlock(&region_mutex);
+	return 0;
+}
+EXPORT_SYMBOL(omap_vram_free);
+
+#if 0
+void *omap_vram_reserve(unsigned long paddr, size_t size)
+{
+
+	struct region *rm;
+	unsigned start_page;
+	unsigned end_page;
+	unsigned i;
+	void *vaddr;
+
+	size = PAGE_ALIGN(size);
+
+	rm = region_find_region(paddr, size);
+
+	DBG("reserve mem paddr %08lx size %d\n",
+			paddr, size);
+
+	BUG_ON(rm == NULL);
+
+	start_page = (paddr - rm->paddr) >> PAGE_SHIFT;
+	end_page = start_page + (size >> PAGE_SHIFT);
+	for (i = start_page; i < end_page; i++)
+		region_reserve_page(rm, i);
+
+	vaddr = rm->vaddr + (start_page << PAGE_SHIFT);
+
+	return vaddr;
+}
+EXPORT_SYMBOL(omap_vram_reserve);
+#endif
+static void *_omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr)
+{
+	struct vram_region *rm;
+	struct vram_alloc *alloc;
+	void *vaddr;
+
+	list_for_each_entry(rm, &region_list, list) {
+		unsigned long start, end;
+
+		DBG("checking region %lx %d\n", rm->paddr, rm->pages);
+
+		if (region_mem_type(rm->paddr) != mtype)
+			continue;
+
+		start = rm->paddr;
+
+		list_for_each_entry(alloc, &rm->alloc_list, list) {
+			end = alloc->paddr;
+
+			if (end - start >= pages << PAGE_SHIFT)
+				goto found;
+
+			start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
+		}
+
+		end = rm->paddr + (rm->pages << PAGE_SHIFT);
+found:
+		if (end - start < pages << PAGE_SHIFT)
+			continue;
+
+		DBG("FOUND %lx, end %lx\n", start, end);
+
+		if (omap_vram_create_allocation(rm, start, pages) == NULL)
+			return NULL;
+
+		*paddr = start;
+		vaddr = rm->vaddr + (start - rm->paddr);
+
+		return vaddr;
+	}
+
+	return NULL;
+}
+
+static void *_omap_vram_alloc_dma(unsigned pages, unsigned long *paddr)
+{
+	struct vram_region *rm;
+	void *vaddr;
+
+	vaddr = dma_alloc_writecombine(NULL, pages << PAGE_SHIFT,
+			(dma_addr_t *)paddr, GFP_KERNEL);
+
+	if (vaddr == NULL)
+		return NULL;
+
+	rm = omap_vram_create_region(*paddr, vaddr, pages);
+	if (rm == NULL) {
+		dma_free_writecombine(NULL, pages << PAGE_SHIFT, vaddr,
+				(dma_addr_t)*paddr);
+		return NULL;
+	}
+
+	rm->dma_alloced = 1;
+
+	if (omap_vram_create_allocation(rm, *paddr, pages) == NULL) {
+		dma_free_writecombine(NULL, pages << PAGE_SHIFT, vaddr,
+				(dma_addr_t)*paddr);
+		kfree(rm);
+		return NULL;
+	}
+
+	list_add(&rm->list, &region_list);
+
+	return vaddr;
+}
+
+void *omap_vram_alloc(int mtype, size_t size, unsigned long *paddr)
+{
+	void *vaddr;
+	unsigned pages;
+
+	BUG_ON(mtype > OMAPFB_MEMTYPE_MAX || !size);
+
+	DBG("alloc mem type %d size %d\n", mtype, size);
+
+	size = PAGE_ALIGN(size);
+	pages = size >> PAGE_SHIFT;
+
+	mutex_lock(&region_mutex);
+
+	vaddr = _omap_vram_alloc(mtype, pages, paddr);
+
+	if (vaddr == NULL && mtype == OMAPFB_MEMTYPE_SDRAM) {
+		DBG("fallback to dma_alloc\n");
+
+		vaddr = _omap_vram_alloc_dma(pages, paddr);
+	}
+
+	mutex_unlock(&region_mutex);
+
+	return vaddr;
+}
+EXPORT_SYMBOL(omap_vram_alloc);
+
+#ifdef CONFIG_PROC_FS
+static void *r_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	struct list_head *l = v;
+
+	(*pos)++;
+
+	if (list_is_last(l, &region_list))
+		return 0;
+
+	return l->next;
+}
+
+static void *r_start(struct seq_file *m, loff_t *pos)
+{
+	loff_t p = *pos;
+	struct list_head *l = &region_list;
+
+	mutex_lock(&region_mutex);
+
+	do {
+		l = l->next;
+		if (l == &region_list)
+			return NULL;
+	} while (p--);
+
+	return l;
+}
+
+static void r_stop(struct seq_file *m, void *v)
+{
+	mutex_unlock(&region_mutex);
+}
+
+static int r_show(struct seq_file *m, void *v)
+{
+	struct vram_region *vr;
+	struct vram_alloc *va;
+	unsigned size;
+
+	vr = list_entry(v, struct vram_region, list);
+
+	size = vr->pages << PAGE_SHIFT;
+	seq_printf(m, "%08lx-%08lx v:%p-%p (%d bytes) %s\n",
+			vr->paddr, vr->paddr + size,
+			vr->vaddr, vr->vaddr + size,
+			size,
+			vr->dma_alloced ? "dma_alloc" : "");
+
+	list_for_each_entry(va, &vr->alloc_list, list) {
+		size = va->pages << PAGE_SHIFT;
+		seq_printf(m, "    %08lx-%08lx (%d bytes)\n",
+				va->paddr, va->paddr + size,
+				size);
+	}
+
+
+
+	return 0;
+}
+
+static const struct seq_operations resource_op = {
+	.start	= r_start,
+	.next	= r_next,
+	.stop	= r_stop,
+	.show	= r_show,
+};
+
+static int vram_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &resource_op);
+}
+
+static const struct file_operations proc_vram_operations = {
+	.open		= vram_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+static int __init omap_vram_create_proc(void)
+{
+	proc_create("omap-vram", 0, NULL, &proc_vram_operations);
+
+	return 0;
+}
+#endif
+
+static __init int omap_vram_init(void)
+{
+	int i, r;
+
+	for (i = 0; i < postponed_cnt; i++)
+		omap_vram_add_region(postponed_regions[i].paddr,
+				postponed_regions[i].size);
+
+#ifdef CONFIG_PROC_FS
+	r = omap_vram_create_proc();
+	if (r)
+		return -ENOMEM;
+#endif
+
+	return 0;
+}
+
+arch_initcall(omap_vram_init);
+
+/* boottime vram alloc stuff */
+static u32 omapfb_sram_vram_start __initdata;
+static u32 omapfb_sram_vram_size __initdata;
+
+static u32 omapfb_sdram_vram_start __initdata;
+static u32 omapfb_sdram_vram_size __initdata;
+
+static u32 omapfb_def_sdram_vram_size __initdata;
+
+static void __init omapfb_early_vram(char **p)
+{
+	unsigned long size;
+	size  = memparse(*p, p);
+	omapfb_def_sdram_vram_size = size;
+}
+__early_param("vram=", omapfb_early_vram);
+
+/*
+ * Called from map_io. We need to call to this early enough so that we
+ * can reserve the fixed SDRAM regions before VM could get hold of them.
+ */
+void __init omapfb_reserve_sdram(void)
+{
+	struct bootmem_data	*bdata;
+	unsigned long		sdram_start, sdram_size;
+	unsigned long		reserved;
+	u32 paddr;
+	u32 size;
+
+	bdata = NODE_DATA(0)->bdata;
+	sdram_start = bdata->node_min_pfn << PAGE_SHIFT;
+	sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start;
+	reserved = 0;
+
+	/* cmdline arg overrides the board file definition */
+	if (omapfb_def_sdram_vram_size) {
+		size = omapfb_def_sdram_vram_size;
+		paddr = 0;
+	} else {
+		size = omapfb_sdram_vram_size;
+		paddr = omapfb_sdram_vram_start;
+	}
+
+	if (size) {
+		if (paddr) {
+			if (paddr < sdram_start ||
+					paddr + size > sdram_start + sdram_size) {
+				printk(KERN_ERR "Illegal SDRAM region for VRAM\n");
+				return;
+			}
+
+			reserve_bootmem(paddr, size, BOOTMEM_DEFAULT);
+		} else {
+			if (size > sdram_size) {
+				printk(KERN_ERR "Illegal SDRAM size for VRAM\n");
+				return;
+			}
+
+			paddr = virt_to_phys(alloc_bootmem(size));
+		}
+
+		reserved += size;
+		omap_vram_add_region_postponed(paddr, size);
+	}
+
+	if (reserved)
+		pr_info("Reserving %lu bytes SDRAM for VRAM\n", reserved);
+}
+
+/*
+ * Called at sram init time, before anything is pushed to the SRAM stack.
+ * Because of the stack scheme, we will allocate everything from the
+ * start of the lowest address region to the end of SRAM. This will also
+ * include padding for page alignment and possible holes between regions.
+ *
+ * As opposed to the SDRAM case, we'll also do any dynamic allocations at
+ * this point, since the driver built as a module would have problem with
+ * freeing / reallocating the regions.
+ */
+unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
+				  unsigned long sram_vstart,
+				  unsigned long sram_size,
+				  unsigned long pstart_avail,
+				  unsigned long size_avail)
+{
+	unsigned long			pend_avail;
+	unsigned long			reserved;
+	u32 paddr;
+	u32 size;
+
+	paddr = omapfb_sram_vram_start;
+	size = omapfb_sram_vram_size;
+
+	reserved = 0;
+	pend_avail = pstart_avail + size_avail;
+
+
+	if (!paddr) {
+		/* Dynamic allocation */
+		if ((size_avail & PAGE_MASK) < size) {
+			printk(KERN_ERR "Not enough SRAM for VRAM\n");
+			return 0;
+		}
+		size_avail = (size_avail - size) & PAGE_MASK;
+		paddr = pstart_avail + size_avail;
+	}
+
+	if (paddr < sram_pstart ||
+			paddr + size > sram_pstart + sram_size) {
+		printk(KERN_ERR "Illegal SRAM region for VRAM\n");
+		return 0;
+	}
+
+	/* Reserve everything above the start of the region. */
+	if (pend_avail - paddr > reserved)
+		reserved = pend_avail - paddr;
+	size_avail = pend_avail - reserved - pstart_avail;
+
+	/*
+	 * We have a kernel mapping for this already, so the
+	 * driver won't have to make one.
+	 */
+	/* XXX do we need the vaddr? */
+	/* rg.vaddr = (void *)(sram_vstart + paddr - sram_pstart); */
+
+	omap_vram_add_region_postponed(paddr, size);
+
+	if (reserved)
+		pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved);
+
+	return reserved;
+}
+
+void __init omap2_set_sdram_vram(u32 size, u32 start)
+{
+	omapfb_sdram_vram_start = start;
+	omapfb_sdram_vram_size = size;
+}
+
+void __init omap2_set_sram_vram(u32 size, u32 start)
+{
+	omapfb_sram_vram_start = start;
+	omapfb_sram_vram_size = size;
+}
+
+#endif
+
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
index 3746222..ee2cc6f 100644
--- a/arch/arm/plat-omap/fb.c
+++ b/arch/arm/plat-omap/fb.c
@@ -327,6 +327,28 @@ static inline int omap_init_fb(void)
 
 arch_initcall(omap_init_fb);
 
+#elif defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
+
+static u64 omap_fb_dma_mask = ~(u32)0;
+
+static struct platform_device omap_fb_device = {
+	.name		= "omapfb",
+	.id		= -1,
+	.dev = {
+		.dma_mask		= &omap_fb_dma_mask,
+		.coherent_dma_mask	= ~(u32)0,
+		.platform_data		= NULL,
+	},
+	.num_resources = 0,
+};
+
+static inline int omap_init_fb(void)
+{
+	return platform_device_register(&omap_fb_device);
+}
+
+arch_initcall(omap_init_fb);
+
 #else
 
 void omapfb_reserve_sdram(void) {}
diff --git a/arch/arm/plat-omap/include/mach/omapfb.h b/arch/arm/plat-omap/include/mach/omapfb.h
index b226bdf..0800f92 100644
--- a/arch/arm/plat-omap/include/mach/omapfb.h
+++ b/arch/arm/plat-omap/include/mach/omapfb.h
@@ -90,6 +90,13 @@ enum omapfb_color_format {
 	OMAPFB_COLOR_CLUT_1BPP,
 	OMAPFB_COLOR_RGB444,
 	OMAPFB_COLOR_YUY422,
+
+	OMAPFB_COLOR_ARGB16,
+	OMAPFB_COLOR_RGB24U,	/* RGB24, 32-bit container */
+	OMAPFB_COLOR_RGB24P,	/* RGB24, 24-bit container */
+	OMAPFB_COLOR_ARGB32,
+	OMAPFB_COLOR_RGBA32,
+	OMAPFB_COLOR_RGBX32,
 };
 
 struct omapfb_update_window {
@@ -393,6 +400,13 @@ extern int  omapfb_update_window_async(struct fb_info *fbi,
 /* in arch/arm/plat-omap/fb.c */
 extern void omapfb_set_ctrl_platform_data(void *pdata);
 
+/* in arch/arm/plat-omap/fb-vram */
+int omap_vram_free(unsigned long paddr, void *vaddr, size_t size);
+void *omap_vram_reserve(unsigned long paddr, size_t size);
+void *omap_vram_alloc(int mtype, size_t size, unsigned long *paddr);
+extern void omap2_set_sdram_vram(u32 size, u32 start);
+extern void omap2_set_sram_vram(u32 size, u32 start);
+
 #endif /* __KERNEL__ */
 
 #endif /* __OMAPFB_H */
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 3f3ce13..689a3b1 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2116,6 +2116,7 @@ config FB_PRE_INIT_FB
 	  the bootloader.
 
 source "drivers/video/omap/Kconfig"
+source "drivers/video/omap2/Kconfig"
 
 source "drivers/video/backlight/Kconfig"
 source "drivers/video/display/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index e39e33e..3d9d50e 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -120,6 +120,7 @@ obj-$(CONFIG_FB_SM501)            += sm501fb.o
 obj-$(CONFIG_FB_XILINX)           += xilinxfb.o
 obj-$(CONFIG_FB_SH_MOBILE_LCDC)	  += sh_mobile_lcdcfb.o
 obj-$(CONFIG_FB_OMAP)             += omap/
+obj-$(CONFIG_OMAP2_DSS)           += omap2/
 obj-$(CONFIG_XEN_FBDEV_FRONTEND)  += xen-fbfront.o
 obj-$(CONFIG_FB_CARMINE)          += carminefb.o
 obj-$(CONFIG_FB_MB862XX)	  += mb862xx/
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
index c355b59..541fab3 100644
--- a/drivers/video/omap/Kconfig
+++ b/drivers/video/omap/Kconfig
@@ -1,6 +1,7 @@
 config FB_OMAP
 	tristate "OMAP frame buffer support (EXPERIMENTAL)"
-	depends on FB && ARCH_OMAP
+	depends on FB && ARCH_OMAP && (OMAP2_DSS = "n")
+
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -80,7 +81,7 @@ config FB_OMAP_BOOTLOADER_INIT
 
 config FB_OMAP_CONSISTENT_DMA_SIZE
 	int "Consistent DMA memory size (MB)"
-	depends on FB_OMAP
+	depends on FB && ARCH_OMAP
 	range 1 14
 	default 2
 	help
diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
new file mode 100644
index 0000000..8be51a3
--- /dev/null
+++ b/drivers/video/omap2/Kconfig
@@ -0,0 +1,42 @@
+config FB_OMAP2
+        tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)"
+        depends on FB && OMAP2_DSS
+
+        select FB_CFB_FILLRECT
+        select FB_CFB_COPYAREA
+        select FB_CFB_IMAGEBLIT
+        help
+          Frame buffer driver for OMAP2/3 based boards.
+
+config FB_OMAP2_DEBUG
+	bool "Debug support for OMAP2/3 FB"
+	default y
+	depends on FB_OMAP2
+	help
+	  Support for debug output. You have to enable the actual printing
+	  with debug module parameter.
+
+config FB_OMAP2_FORCE_AUTO_UPDATE
+	bool "Force main display to automatic update mode"
+	depends on FB_OMAP2
+	help
+	  Forces main display to automatic update mode (if possible),
+	  and also enables tearsync (if possible). By default
+	  displays that support manual update are started in manual
+	  update mode.
+
+config FB_OMAP2_NUM_FBS
+	int "Number of framebuffers"
+	range 1 10
+	default 3
+	depends on FB_OMAP2
+	help
+	  Select the number of framebuffers created. OMAP2/3 has 3 overlays
+	  so normally this would be 3.
+
+menu "OMAP2/3 Display Device Drivers"
+        depends on OMAP2_DSS
+
+
+endmenu
+
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
new file mode 100644
index 0000000..51c2e00
--- /dev/null
+++ b/drivers/video/omap2/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_FB_OMAP2) += omapfb.o
+omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
diff --git a/drivers/video/omap2/omapfb-ioctl.c b/drivers/video/omap2/omapfb-ioctl.c
new file mode 100644
index 0000000..0cb0370
--- /dev/null
+++ b/drivers/video/omap2/omapfb-ioctl.c
@@ -0,0 +1,460 @@
+/*
+ * linux/drivers/video/omap2/omapfb-ioctl.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/fb.h>
+#include <linux/device.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/mm.h>
+
+#include <mach/display.h>
+#include <mach/omapfb.h>
+
+#include "omapfb.h"
+
+static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omap_display *display = fb2display(fbi);
+	struct omap_overlay *ovl;
+	int r = 0;
+
+	DBG("omapfb_setup_plane\n");
+
+	omapfb_lock(fbdev);
+
+	if (ofbi->num_overlays != 1) {
+		r = -EINVAL;
+		goto out;
+	}
+
+	/* XXX uses only the first overlay */
+	ovl = ofbi->overlays[0];
+
+	if (pi->enabled && !ofbi->region.size) {
+		/*
+		 * This plane's memory was freed, can't enable it
+		 * until it's reallocated.
+		 */
+		r = -EINVAL;
+		goto out;
+	}
+
+	if (pi->enabled) {
+		r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
+				pi->out_width, pi->out_height);
+		if (r)
+			goto out;
+	}
+
+	ovl->enable(ovl, pi->enabled);
+
+	if (ovl->manager)
+		ovl->manager->apply(ovl->manager);
+
+	if (display) {
+		if (display->sync)
+			display->sync(display);
+
+		if (display->update)
+			display->update(display, 0, 0,
+					display->panel->timings.x_res,
+					display->panel->timings.y_res);
+	}
+
+out:
+	omapfb_unlock(fbdev);
+	if (r)
+		dev_err(fbdev->dev, "setup_plane failed\n");
+	return r;
+}
+
+static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+
+	omapfb_lock(fbdev);
+
+	if (ofbi->num_overlays != 1) {
+		memset(pi, 0, sizeof(*pi));
+	} else {
+		struct omap_overlay_info *ovli;
+		struct omap_overlay *ovl;
+
+		ovl = ofbi->overlays[0];
+		ovli = &ovl->info;
+
+		pi->pos_x = ovli->pos_x;
+		pi->pos_y = ovli->pos_y;
+		pi->enabled = ovli->enabled;
+		pi->channel_out = 0; /* xxx */
+		pi->mirror = 0;
+		pi->out_width = ovli->out_width;
+		pi->out_height = ovli->out_height;
+	}
+
+	omapfb_unlock(fbdev);
+
+	return 0;
+}
+
+static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omapfb_mem_region *rg;
+	struct omap_display *display = fb2display(fbi);
+	int r, i;
+	size_t size;
+
+	if (mi->type > OMAPFB_MEMTYPE_MAX)
+		return -EINVAL;
+
+	size = PAGE_ALIGN(mi->size);
+
+	rg = &ofbi->region;
+
+	omapfb_lock(fbdev);
+
+	for (i = 0; i < ofbi->num_overlays; i++) {
+		if (ofbi->overlays[i]->info.enabled) {
+			r = -EBUSY;
+			goto out;
+		}
+	}
+
+	if (rg->size != size || rg->type != mi->type) {
+		struct fb_var_screeninfo new_var;
+		unsigned long old_size = rg->size;
+
+		if (display->sync)
+			display->sync(display);
+
+		r = omapfb_realloc_fbmem(fbdev, ofbi->id, size);
+		if (r)
+			goto out;
+
+		if (old_size != size) {
+			if (size) {
+				memcpy(&new_var, &fbi->var, sizeof(new_var));
+				r = check_fb_var(fbi, &new_var);
+				if (r < 0)
+					goto out;
+				memcpy(&fbi->var, &new_var, sizeof(fbi->var));
+				set_fb_fix(fbi);
+			} else {
+				/*
+				 * Set these explicitly to indicate that the
+				 * plane memory is dealloce'd, the other
+				 * screen parameters in var / fix are invalid.
+				 */
+				fbi->fix.smem_start = 0;
+				fbi->fix.smem_len = 0;
+			}
+		}
+	}
+
+	r = 0;
+out:
+	omapfb_unlock(fbdev);
+
+	return r;
+}
+
+static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omapfb_mem_region *rg;
+
+	rg = &ofbi->region;
+	memset(mi, 0, sizeof(*mi));
+
+	omapfb_lock(fbdev);
+	mi->size = rg->size;
+	mi->type = rg->type;
+	omapfb_unlock(fbdev);
+
+	return 0;
+}
+
+static int omapfb_update_window(struct fb_info *fbi,
+		u32 x, u32 y, u32 w, u32 h)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omap_display *display = fb2display(fbi);
+
+	if (!display)
+		return 0;
+
+	if (w == 0 || h == 0)
+		return 0;
+
+	if (x + w > display->panel->timings.x_res ||
+			y + h > display->panel->timings.y_res)
+		return -EINVAL;
+
+	omapfb_lock(fbdev);
+	display->update(display, x, y, w, h);
+	omapfb_unlock(fbdev);
+
+	return 0;
+}
+
+static int omapfb_set_update_mode(struct fb_info *fbi,
+				   enum omapfb_update_mode mode)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omap_display *display = fb2display(fbi);
+	enum omap_dss_update_mode um;
+	int r;
+
+	if (!display || !display->set_update_mode)
+		return -EINVAL;
+
+	switch (mode) {
+	case OMAPFB_UPDATE_DISABLED:
+		um = OMAP_DSS_UPDATE_DISABLED;
+		break;
+
+	case OMAPFB_AUTO_UPDATE:
+		um = OMAP_DSS_UPDATE_AUTO;
+		break;
+
+	case OMAPFB_MANUAL_UPDATE:
+		um = OMAP_DSS_UPDATE_MANUAL;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	omapfb_lock(fbdev);
+	r = display->set_update_mode(display, um);
+	omapfb_unlock(fbdev);
+
+	return r;
+}
+
+static int omapfb_get_update_mode(struct fb_info *fbi,
+		enum omapfb_update_mode *mode)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omap_display *display = fb2display(fbi);
+	enum omap_dss_update_mode m;
+
+	if (!display || !display->get_update_mode)
+		return -EINVAL;
+
+	omapfb_lock(fbdev);
+	m = display->get_update_mode(display);
+	omapfb_unlock(fbdev);
+
+	switch (m) {
+	case OMAP_DSS_UPDATE_DISABLED:
+		*mode = OMAPFB_UPDATE_DISABLED;
+		break;
+	case OMAP_DSS_UPDATE_AUTO:
+		*mode = OMAPFB_AUTO_UPDATE;
+		break;
+	case OMAP_DSS_UPDATE_MANUAL:
+		*mode = OMAPFB_MANUAL_UPDATE;
+		break;
+	default:
+		BUG();
+	}
+
+	return 0;
+}
+
+int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omap_display *display = fb2display(fbi);
+
+	union {
+		struct omapfb_update_window_old	uwnd_o;
+		struct omapfb_update_window	uwnd;
+		struct omapfb_plane_info	plane_info;
+		struct omapfb_caps		caps;
+		struct omapfb_mem_info          mem_info;
+		enum omapfb_update_mode		update_mode;
+		int test_num;
+	} p;
+
+	int r = 0;
+
+	DBG("ioctl %x (%d)\n", cmd, cmd & 0xff);
+
+	switch (cmd) {
+	case OMAPFB_SYNC_GFX:
+		if (!display || !display->sync) {
+			/* DSS1 never returns an error here, so we neither */
+			/*r = -EINVAL;*/
+			break;
+		}
+
+		omapfb_lock(fbdev);
+		r = display->sync(display);
+		omapfb_unlock(fbdev);
+		break;
+
+	case OMAPFB_UPDATE_WINDOW_OLD:
+		if (!display || !display->update) {
+			r = -EINVAL;
+			break;
+		}
+
+		if (copy_from_user(&p.uwnd_o,
+					(void __user *)arg,
+					sizeof(p.uwnd_o))) {
+			r = -EFAULT;
+			break;
+		}
+
+		r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y,
+				p.uwnd_o.width, p.uwnd_o.height);
+		break;
+
+	case OMAPFB_UPDATE_WINDOW:
+		if (!display || !display->update) {
+			r = -EINVAL;
+			break;
+		}
+
+		if (copy_from_user(&p.uwnd, (void __user *)arg,
+					sizeof(p.uwnd))) {
+			r = -EFAULT;
+			break;
+		}
+
+		r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y,
+				p.uwnd.width, p.uwnd.height);
+		break;
+
+	case OMAPFB_SETUP_PLANE:
+		if (copy_from_user(&p.plane_info, (void __user *)arg,
+					sizeof(p.plane_info)))
+			r = -EFAULT;
+		else
+			r = omapfb_setup_plane(fbi, &p.plane_info);
+		break;
+
+	case OMAPFB_QUERY_PLANE:
+		r = omapfb_query_plane(fbi, &p.plane_info);
+		if (r < 0)
+			break;
+		if (copy_to_user((void __user *)arg, &p.plane_info,
+					sizeof(p.plane_info)))
+			r = -EFAULT;
+		break;
+
+	case OMAPFB_SETUP_MEM:
+		if (copy_from_user(&p.mem_info, (void __user *)arg,
+					sizeof(p.mem_info)))
+			r = -EFAULT;
+		else
+			r = omapfb_setup_mem(fbi, &p.mem_info);
+		break;
+
+	case OMAPFB_QUERY_MEM:
+		r = omapfb_query_mem(fbi, &p.mem_info);
+		if (r < 0)
+			break;
+		if (copy_to_user((void __user *)arg, &p.mem_info,
+					sizeof(p.mem_info)))
+			r = -EFAULT;
+		break;
+
+	case OMAPFB_GET_CAPS:
+		if (!display) {
+			r = -EINVAL;
+			break;
+		}
+
+		p.caps.ctrl = display->caps;
+
+		if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
+			r = -EFAULT;
+		break;
+
+	case OMAPFB_SET_UPDATE_MODE:
+		if (get_user(p.update_mode, (int __user *)arg))
+			r = -EFAULT;
+		else
+			r = omapfb_set_update_mode(fbi, p.update_mode);
+		break;
+
+	case OMAPFB_GET_UPDATE_MODE:
+		r = omapfb_get_update_mode(fbi, &p.update_mode);
+		if (r)
+			break;
+		if (put_user(p.update_mode,
+					(enum omapfb_update_mode __user *)arg))
+			r = -EFAULT;
+		break;
+
+	/* LCD and CTRL tests do the same thing for backward
+	 * compatibility */
+	case OMAPFB_LCD_TEST:
+		if (get_user(p.test_num, (int __user *)arg)) {
+			r = -EFAULT;
+			break;
+		}
+		if (!display || !display->run_test) {
+			r = -EINVAL;
+			break;
+		}
+
+		r = display->run_test(display, p.test_num);
+
+		break;
+
+	case OMAPFB_CTRL_TEST:
+		if (get_user(p.test_num, (int __user *)arg)) {
+			r = -EFAULT;
+			break;
+		}
+		if (!display || !display->run_test) {
+			r = -EINVAL;
+			break;
+		}
+
+		r = display->run_test(display, p.test_num);
+
+		break;
+
+	default:
+		DBG("ioctl unhandled\n");
+		r = -EINVAL;
+	}
+
+	return r;
+}
+
+
diff --git a/drivers/video/omap2/omapfb-main.c b/drivers/video/omap2/omapfb-main.c
new file mode 100644
index 0000000..d043c43
--- /dev/null
+++ b/drivers/video/omap2/omapfb-main.c
@@ -0,0 +1,1442 @@
+/*
+ * linux/drivers/video/omap2/omapfb-main.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
+#include <mach/display.h>
+#include <mach/omapfb.h>
+
+#include "omapfb.h"
+
+#define MODULE_NAME     "omapfb"
+
+static char *def_mode;
+static char *def_vram;
+
+#ifdef DEBUG
+unsigned int omapfb_debug;
+module_param_named(debug, omapfb_debug, bool, 0644);
+#endif
+
+#ifdef DEBUG
+static void fill_fb(void *addr, struct fb_info *fbi)
+{
+	struct fb_var_screeninfo *var = &fbi->var;
+
+	const short w = var->xres_virtual;
+	const short h = var->yres_virtual;
+
+	int y, x;
+	u8 *p = addr;
+
+	for (y = 0; y < h; y++) {
+		for (x = 0; x < w; x++) {
+			if (var->bits_per_pixel == 16) {
+				u16 *pw = (u16 *)p;
+
+				if (x < 20 && y < 20)
+					*pw = 0xffff;
+				else if (x == 20 || x == w - 20 ||
+						y == 20 || y == h - 20)
+					*pw = 0xffff;
+				else if (x == y || w - x == h - y)
+					*pw = ((1<<5)-1)<<11;
+				else if (w - x == y || x == h - y)
+					*pw = ((1<<6)-1)<<5;
+				else {
+					int t = x / (w/3);
+					if (t == 0)
+						*pw = y % 32;
+					else if (t == 1)
+						*pw = (y % 64) << 5;
+					else if (t == 2)
+						*pw = (y % 32) << 11;
+				}
+			} else if (var->bits_per_pixel == 24) {
+				u8 *pb = (u8 *)p;
+
+				int r = 0, g = 0, b = 0;
+
+				if (x < 20 && y < 20)
+					r = g = b = 0xff;
+				else if (x == 20 || x == w - 20 ||
+						y == 20 || y == h - 20)
+					r = g = b = 0xff;
+				else if (x == y || w - x == h - y)
+					r = 0xff;
+				else if (w - x == y || x == h - y)
+					g = 0xff;
+				else {
+					int q = x / (w / 3);
+					u8 base = 255 - (y % 256);
+					if (q == 0)
+						r = base;
+					else if (q == 1)
+						g = base;
+					else if (q == 2)
+						b = base;
+				}
+
+				pb[0] = b;
+				pb[1] = g;
+				pb[2] = r;
+
+			} else if (var->bits_per_pixel == 32) {
+				u32 *pd = (u32 *)p;
+
+				if (x < 20 && y < 20)
+					*pd = 0xffffff;
+				else if (x == 20 || x == w - 20 ||
+						y == 20 || y == h - 20)
+					*pd = 0xffffff;
+				else if (x == y || w - x == h - y)
+					*pd = 0xff0000;
+				else if (w - x == y || x == h - y)
+					*pd = 0x00ff00;
+				else {
+					u8 base = 255 - (y % 256);
+					*pd = base << ((x / (w/3)) << 3);
+				}
+			}
+
+			p += var->bits_per_pixel >> 3;
+		}
+	}
+}
+#endif
+
+static enum omap_color_mode fb_mode_to_dss_mode(struct fb_var_screeninfo *var)
+{
+	switch (var->nonstd) {
+	case 0:
+		break;
+	case OMAPFB_COLOR_YUV422:
+		return OMAP_DSS_COLOR_UYVY;
+
+	case OMAPFB_COLOR_YUY422:
+		return OMAP_DSS_COLOR_YUV2;
+
+	case OMAPFB_COLOR_ARGB16:
+		return OMAP_DSS_COLOR_ARGB16;
+
+	case OMAPFB_COLOR_ARGB32:
+		return OMAP_DSS_COLOR_ARGB32;
+
+	case OMAPFB_COLOR_RGBA32:
+		return OMAP_DSS_COLOR_RGBA32;
+
+	case OMAPFB_COLOR_RGBX32:
+		return OMAP_DSS_COLOR_RGBX32;
+
+	default:
+		return -EINVAL;
+	}
+
+	switch (var->bits_per_pixel) {
+	case 1:
+		return OMAP_DSS_COLOR_CLUT1;
+	case 2:
+		return OMAP_DSS_COLOR_CLUT2;
+	case 4:
+		return OMAP_DSS_COLOR_CLUT4;
+	case 8:
+		return OMAP_DSS_COLOR_CLUT8;
+	case 12:
+		return OMAP_DSS_COLOR_RGB12U;
+	case 16:
+		return OMAP_DSS_COLOR_RGB16;
+	case 24:
+		return OMAP_DSS_COLOR_RGB24P;
+	case 32:
+		return OMAP_DSS_COLOR_RGB24U;
+	default:
+		return -EINVAL;
+	}
+
+	return -EINVAL;
+}
+
+void set_fb_fix(struct fb_info *fbi)
+{
+	struct fb_fix_screeninfo *fix = &fbi->fix;
+	struct fb_var_screeninfo *var = &fbi->var;
+	struct omapfb_mem_region *rg = &FB2OFB(fbi)->region;
+
+	DBG("set_fb_fix\n");
+
+	/* used by open/write in fbmem.c */
+	fbi->screen_base        = (char __iomem *)rg->vaddr;
+
+	/* used by mmap in fbmem.c */
+	fix->smem_start         = rg->paddr;
+	fix->smem_len           = rg->size;
+
+	fix->type = FB_TYPE_PACKED_PIXELS;
+
+	if (var->nonstd)
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+	else {
+		switch (var->bits_per_pixel) {
+		case 32:
+		case 24:
+		case 16:
+		case 12:
+			fix->visual = FB_VISUAL_TRUECOLOR;
+			/* 12bpp is stored in 16 bits */
+			break;
+		case 1:
+		case 2:
+		case 4:
+		case 8:
+			fix->visual = FB_VISUAL_PSEUDOCOLOR;
+			break;
+		}
+	}
+
+	fix->accel = FB_ACCEL_NONE;
+	fix->line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
+
+	fix->xpanstep = 1;
+	fix->ypanstep = 1;
+}
+
+/* check new var and possibly modify it to be ok */
+int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omap_display *display = fb2display(fbi);
+	unsigned long max_frame_size;
+	unsigned long line_size;
+	int xres_min, xres_max;
+	int yres_min, yres_max;
+	enum omap_color_mode mode = 0;
+	struct omap_overlay *ovl;
+
+	DBG("check_fb_var %d\n", ofbi->id);
+
+	if (ofbi->region.size == 0) {
+		memset(var, 0, sizeof(*var));
+		return 0;
+	}
+
+	if (ofbi->num_overlays == 0) {
+		dev_err(ofbi->fbdev->dev, "no overlays, aborting\n");
+		return -EINVAL;
+	}
+
+	/* XXX: uses the first overlay */
+	ovl = ofbi->overlays[0];
+
+	/* if we are using non standard mode, fix the bpp first */
+	switch (var->nonstd) {
+	case 0:
+		break;
+	case OMAPFB_COLOR_YUV422:
+	case OMAPFB_COLOR_YUY422:
+	case OMAPFB_COLOR_ARGB16:
+		var->bits_per_pixel = 16;
+		break;
+	case OMAPFB_COLOR_ARGB32:
+	case OMAPFB_COLOR_RGBA32:
+	case OMAPFB_COLOR_RGBX32:
+		var->bits_per_pixel = 32;
+		break;
+	default:
+		DBG("invalid nonstd mode\n");
+		return -EINVAL;
+	}
+
+	mode = fb_mode_to_dss_mode(var);
+	if (mode < 0) {
+		DBG("cannot convert var to omap dss mode\n");
+		return -EINVAL;
+	}
+
+	if ((ovl->supported_modes & mode) == 0) {
+		DBG("invalid mode\n");
+		return -EINVAL;
+	}
+
+	xres_min = OMAPFB_PLANE_XRES_MIN;
+	xres_max = (display ? display->panel->timings.x_res : 2048) - ovl->info.pos_x;
+	yres_min = OMAPFB_PLANE_YRES_MIN;
+	yres_max = (display ? display->panel->timings.y_res : 2048) - ovl->info.pos_y;
+
+	if (var->xres < xres_min)
+		var->xres = xres_min;
+	if (var->yres < yres_min)
+		var->yres = yres_min;
+	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 = ofbi->region.size;
+	line_size = (var->xres_virtual * var->bits_per_pixel) >> 3;
+
+	if (line_size * var->yres_virtual > max_frame_size) {
+		/* Try to keep yres_virtual first */
+		line_size = max_frame_size / var->yres_virtual;
+		var->xres_virtual = line_size * 8 / var->bits_per_pixel;
+		if (var->xres_virtual < var->xres) {
+			/* Still doesn't fit. Shrink yres_virtual too */
+			var->xres_virtual = var->xres;
+			line_size = var->xres * var->bits_per_pixel / 8;
+			var->yres_virtual = max_frame_size / line_size;
+		}
+		/* Recheck this, as the virtual size changed. */
+		if (var->xres_virtual < var->xres)
+			var->xres = var->xres_virtual;
+		if (var->yres_virtual < var->yres)
+			var->yres = var->yres_virtual;
+		if (var->xres < xres_min || var->yres < yres_min) {
+			DBG("Cannot fit FB to memory\n");
+			return -EINVAL;
+		}
+	}
+	if (var->xres + var->xoffset > var->xres_virtual)
+		var->xoffset = var->xres_virtual - var->xres;
+	if (var->yres + var->yoffset > var->yres_virtual)
+		var->yoffset = var->yres_virtual - var->yres;
+
+	if (var->bits_per_pixel == 16) {
+		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;
+	} else if (var->bits_per_pixel == 24) {
+		var->red.offset  = 16; var->red.length   = 8;
+		var->red.msb_right   = 0;
+		var->green.offset = 8;  var->green.length = 8;
+		var->green.msb_right = 0;
+		var->blue.offset = 0;  var->blue.length  = 8;
+		var->blue.msb_right  = 0;
+		var->transp.offset = 0; var->transp.length = 0;
+	} else if (var->bits_per_pixel == 32) {
+		var->red.offset  = 16; var->red.length   = 8;
+		var->red.msb_right   = 0;
+		var->green.offset = 8;  var->green.length = 8;
+		var->green.msb_right = 0;
+		var->blue.offset = 0;  var->blue.length  = 8;
+		var->blue.msb_right  = 0;
+		var->transp.offset = 0; var->transp.length = 0;
+	} else {
+		DBG("failed to setup fb color mask\n");
+		return -EINVAL;
+	}
+
+	DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n",
+			var->xres, var->yres,
+			var->xres_virtual, var->yres_virtual);
+
+	var->height             = -1;
+	var->width              = -1;
+	var->grayscale          = 0;
+
+	if (display && display->get_timings) {
+		struct omap_video_timings timings;
+		display->get_timings(display, &timings);
+
+		/* pixclock in ps, the rest in pixclock */
+		var->pixclock = timings.pixel_clock != 0 ?
+			KHZ2PICOS(timings.pixel_clock) :
+			0;
+		var->left_margin = timings.hfp;
+		var->right_margin = timings.hbp;
+		var->upper_margin = timings.vfp;
+		var->lower_margin = timings.vbp;
+		var->hsync_len = timings.hsw;
+		var->vsync_len = timings.vsw;
+	} else {
+		var->pixclock = 0;
+		var->left_margin = 0;
+		var->right_margin = 0;
+		var->upper_margin = 0;
+		var->lower_margin = 0;
+		var->hsync_len = 0;
+		var->vsync_len = 0;
+	}
+
+	/* TODO: get these from panel->config */
+	var->vmode              = FB_VMODE_NONINTERLACED;
+	var->sync               = 0;
+
+	return 0;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * fbdev framework callbacks
+ * ---------------------------------------------------------------------------
+ */
+static int omapfb_open(struct fb_info *fbi, int user)
+{
+	return 0;
+}
+
+static int omapfb_release(struct fb_info *fbi, int user)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omap_display *display = fb2display(fbi);
+
+	DBG("Closing fb with plane index %d\n", ofbi->id);
+
+	omapfb_lock(fbdev);
+#if 1
+	if (display) {
+		/* XXX Is this really needed ? */
+		if (display->sync)
+			display->sync(display);
+
+		if (display->update)
+			display->update(display,
+					0, 0,
+					display->panel->timings.x_res,
+					display->panel->timings.y_res);
+	}
+#endif
+
+	if (display && display->sync)
+		display->sync(display);
+
+	omapfb_unlock(fbdev);
+
+	return 0;
+}
+
+/* setup overlay according to the fb */
+int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
+		int posx, int posy, int outw, int outh)
+{
+	int r = 0;
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct fb_var_screeninfo *var = &fbi->var;
+	enum omap_color_mode mode = 0;
+	int offset;
+	u32 data_start_p;
+	void *data_start_v;
+
+	DBG("setup_overlay %d\n", ofbi->id);
+
+	if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0 &&
+			(outw != var->xres || outh != var->yres)) {
+		r = -EINVAL;
+		goto err;
+	}
+
+	offset = ((var->yoffset * var->xres_virtual +
+				var->xoffset) * var->bits_per_pixel) >> 3;
+
+	data_start_p = ofbi->region.paddr + offset;
+	data_start_v = ofbi->region.vaddr + offset;
+
+	mode = fb_mode_to_dss_mode(var);
+
+	if (mode == -EINVAL) {
+		r = -EINVAL;
+		goto err;
+	}
+
+	r = ovl->setup_input(ovl,
+			data_start_p, data_start_v,
+			var->xres_virtual,
+			var->xres, var->yres,
+			mode);
+
+	if (r)
+		goto err;
+
+	r = ovl->setup_output(ovl,
+			posx, posy,
+			outw, outh);
+
+	if (r)
+		goto err;
+
+	return 0;
+
+err:
+	DBG("setup_overlay failed\n");
+	return r;
+}
+
+/* apply var to the overlay */
+int omapfb_apply_changes(struct fb_info *fbi, int init)
+{
+	int r = 0;
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct fb_var_screeninfo *var = &fbi->var;
+	struct omap_overlay *ovl;
+	int posx, posy;
+	int outw, outh;
+	int i;
+
+	for (i = 0; i < ofbi->num_overlays; i++) {
+		ovl = ofbi->overlays[i];
+
+		DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
+
+		if (ofbi->region.size == 0) {
+			/* the fb is not available. disable the overlay */
+			ovl->enable(ovl, 0);
+			if (!init && ovl->manager)
+				ovl->manager->apply(ovl->manager);
+			continue;
+		}
+
+		if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
+			outw = var->xres;
+			outh = var->yres;
+		} else {
+			outw = ovl->info.out_width;
+			outh = ovl->info.out_height;
+		}
+
+		if (init) {
+			posx = 0;
+			posy = 0;
+		} else {
+			posx = ovl->info.pos_x;
+			posy = ovl->info.pos_y;
+		}
+
+		r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
+		if (r)
+			goto err;
+
+		if (!init && ovl->manager)
+			ovl->manager->apply(ovl->manager);
+	}
+	return 0;
+err:
+	DBG("apply_changes failed\n");
+	return r;
+}
+
+/* checks var and eventually tweaks it to something supported,
+ * DO NOT MODIFY PAR */
+static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
+{
+	int r;
+
+	DBG("check_var(%d)\n", FB2OFB(fbi)->id);
+
+	r = check_fb_var(fbi, var);
+
+	return r;
+}
+
+/* set the video mode according to info->var */
+static int omapfb_set_par(struct fb_info *fbi)
+{
+	int r;
+
+	DBG("set_par(%d)\n", FB2OFB(fbi)->id);
+
+	set_fb_fix(fbi);
+	r = omapfb_apply_changes(fbi, 0);
+
+	return r;
+}
+
+static void omapfb_rotate(struct fb_info *fbi, int rotate)
+{
+	DBG("rotate(%d)\n", FB2OFB(fbi)->id);
+	return;
+}
+
+static int omapfb_pan_display(struct fb_var_screeninfo *var,
+		struct fb_info *fbi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	int r = 0;
+
+	DBG("pan_display(%d)\n", ofbi->id);
+
+	omapfb_lock(fbdev);
+
+	if (var->xoffset != fbi->var.xoffset ||
+	    var->yoffset != fbi->var.yoffset) {
+		struct fb_var_screeninfo new_var;
+
+		new_var = fbi->var;
+		new_var.xoffset = var->xoffset;
+		new_var.yoffset = var->yoffset;
+
+		r = check_fb_var(fbi, &new_var);
+
+		if (r == 0) {
+			fbi->var = new_var;
+			set_fb_fix(fbi);
+			r = omapfb_apply_changes(fbi, 0);
+		}
+	}
+
+	omapfb_unlock(fbdev);
+
+	return r;
+}
+
+static void mmap_user_open(struct vm_area_struct *vma)
+{
+	struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
+
+	atomic_inc(&ofbi->map_count);
+}
+
+static void mmap_user_close(struct vm_area_struct *vma)
+{
+	struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
+
+	atomic_dec(&ofbi->map_count);
+}
+
+static struct vm_operations_struct mmap_user_ops = {
+	.open = mmap_user_open,
+	.close = mmap_user_close,
+};
+
+static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb_mem_region *rg = &ofbi->region;
+	unsigned long off;
+	unsigned long start;
+	u32 len;
+
+	if (vma->vm_end - vma->vm_start == 0)
+		return 0;
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+		return -EINVAL;
+	off = vma->vm_pgoff << PAGE_SHIFT;
+
+	start = rg->paddr;
+	len = rg->size;
+	if (off >= len)
+		return -EINVAL;
+	if ((vma->vm_end - vma->vm_start + off) > len)
+		return -EINVAL;
+	off += start;
+	vma->vm_pgoff = off >> PAGE_SHIFT;
+	vma->vm_flags |= VM_IO | VM_RESERVED;
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+	vma->vm_ops = &mmap_user_ops;
+	vma->vm_private_data = ofbi;
+	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
+		return -EAGAIN;
+	/* vm_ops.open won't be called for mmap itself. */
+	atomic_inc(&ofbi->map_count);
+	return 0;
+}
+
+/* Store a single color palette entry into a pseudo palette or the hardware
+ * palette if one is available. For now we support only 16bpp and thus store
+ * the entry only to the pseudo palette.
+ */
+static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
+		u_int blue, u_int transp, int update_hw_pal)
+{
+	/*struct omapfb_info *ofbi = FB2OFB(fbi);*/
+	/*struct omapfb2_device *fbdev = ofbi->fbdev;*/
+	struct fb_var_screeninfo *var = &fbi->var;
+	int r = 0;
+
+	enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */
+
+	/*switch (plane->color_mode) {*/
+	switch (mode) {
+	case OMAPFB_COLOR_YUV422:
+	case OMAPFB_COLOR_YUV420:
+	case OMAPFB_COLOR_YUY422:
+		r = -EINVAL;
+		break;
+	case OMAPFB_COLOR_CLUT_8BPP:
+	case OMAPFB_COLOR_CLUT_4BPP:
+	case OMAPFB_COLOR_CLUT_2BPP:
+	case OMAPFB_COLOR_CLUT_1BPP:
+		/*
+		   if (fbdev->ctrl->setcolreg)
+		   r = fbdev->ctrl->setcolreg(regno, red, green, blue,
+		   transp, update_hw_pal);
+		   */
+		/* Fallthrough */
+		r = -EINVAL;
+		break;
+	case OMAPFB_COLOR_RGB565:
+	case OMAPFB_COLOR_RGB444:
+	case OMAPFB_COLOR_RGB24P:
+	case OMAPFB_COLOR_RGB24U:
+		if (r != 0)
+			break;
+
+		if (regno < 0) {
+			r = -EINVAL;
+			break;
+		}
+
+		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));
+			((u32 *)(fbi->pseudo_palette))[regno] = pal;
+		}
+		break;
+	default:
+		BUG();
+	}
+	return r;
+}
+
+static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+		u_int transp, struct fb_info *info)
+{
+	DBG("setcolreg\n");
+
+	return _setcolreg(info, regno, red, green, blue, transp, 1);
+}
+
+static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+	int count, index, r;
+	u16 *red, *green, *blue, *transp;
+	u16 trans = 0xffff;
+
+	DBG("setcmap\n");
+
+	red     = cmap->red;
+	green   = cmap->green;
+	blue    = cmap->blue;
+	transp  = cmap->transp;
+	index   = cmap->start;
+
+	for (count = 0; count < cmap->len; count++) {
+		if (transp)
+			trans = *transp++;
+		r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
+				count == cmap->len - 1);
+		if (r != 0)
+			return r;
+	}
+
+	return 0;
+}
+
+static int omapfb_blank(int blank, struct fb_info *fbi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omap_display *display = fb2display(fbi);
+	int do_update = 0;
+	int r = 0;
+
+	omapfb_lock(fbdev);
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+		if (display->state != OMAP_DSS_DISPLAY_SUSPENDED) {
+			r = -EINVAL;
+			goto exit;
+		}
+
+		if (display->resume)
+			r = display->resume(display);
+
+		if (r == 0 && display->get_update_mode &&
+				display->get_update_mode(display) ==
+				OMAP_DSS_UPDATE_MANUAL)
+			do_update = 1;
+
+		break;
+
+	case FB_BLANK_POWERDOWN:
+		if (display->state != OMAP_DSS_DISPLAY_ACTIVE) {
+			r = -EINVAL;
+			goto exit;
+		}
+
+		if (display->suspend)
+			r = display->suspend(display);
+
+		break;
+
+	default:
+		r = -EINVAL;
+	}
+
+exit:
+	omapfb_unlock(fbdev);
+
+	if (r == 0 && do_update && display->update)
+		r = display->update(display,
+				0, 0,
+				display->panel->timings.x_res,
+				display->panel->timings.y_res);
+
+	return r;
+}
+
+static struct fb_ops omapfb_ops = {
+	.owner          = THIS_MODULE,
+	.fb_open        = omapfb_open,
+	.fb_release     = omapfb_release,
+	.fb_fillrect    = cfb_fillrect,
+	.fb_copyarea    = cfb_copyarea,
+	.fb_imageblit   = cfb_imageblit,
+	.fb_blank       = omapfb_blank,
+	.fb_ioctl       = omapfb_ioctl,
+	.fb_check_var   = omapfb_check_var,
+	.fb_set_par     = omapfb_set_par,
+	.fb_rotate      = omapfb_rotate,
+	.fb_pan_display = omapfb_pan_display,
+	.fb_mmap	= omapfb_mmap,
+	.fb_setcolreg	= omapfb_setcolreg,
+	.fb_setcmap	= omapfb_setcmap,
+};
+
+static void omapfb_free_fbmem(struct omapfb2_device *fbdev, int fbnum)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[fbnum]);
+	struct omapfb_mem_region *rg;
+
+	rg = &ofbi->region;
+
+	if (rg->paddr)
+		if (omap_vram_free(rg->paddr, rg->vaddr, rg->size))
+			dev_err(fbdev->dev, "VRAM FREE failed\n");
+
+	rg->vaddr = NULL;
+	rg->paddr = 0;
+	rg->alloc = 0;
+	rg->size = 0;
+}
+
+static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
+{
+	int i;
+
+	DBG("free all fbmem\n");
+
+	for (i = 0; i < fbdev->num_fbs; i++)
+		omapfb_free_fbmem(fbdev, i);
+
+	return 0;
+}
+
+static int omapfb_alloc_fbmem(struct omapfb2_device *fbdev, int fbnum,
+		unsigned long size)
+{
+	struct omapfb_info *ofbi;
+	struct omapfb_mem_region *rg;
+	unsigned long paddr;
+	void *vaddr;
+
+	size = PAGE_ALIGN(size);
+
+	ofbi = FB2OFB(fbdev->fbs[fbnum]);
+	rg = &ofbi->region;
+	memset(rg, 0, sizeof(*rg));
+
+	DBG("allocating %lu bytes for fb %d\n",
+			size, ofbi->id);
+
+	vaddr = omap_vram_alloc(OMAPFB_MEMTYPE_SDRAM, size, &paddr);
+	DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
+
+	if (vaddr == NULL) {
+		dev_err(fbdev->dev,
+				"failed to allocate framebuffer\n");
+		return -ENOMEM;
+	}
+
+	rg->paddr = paddr;
+	rg->vaddr = vaddr;
+	rg->size = size;
+	rg->alloc = 1;
+
+	return 0;
+}
+
+int omapfb_realloc_fbmem(struct omapfb2_device *fbdev, int fbnum,
+		unsigned long size)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[fbnum]);
+	struct omapfb_mem_region *rg = &ofbi->region;
+	unsigned old_size = rg->size;
+	int r;
+
+	size = PAGE_ALIGN(size);
+
+	omapfb_free_fbmem(fbdev, fbnum);
+
+	if (size == 0)
+		return 0;
+
+	r = omapfb_alloc_fbmem(fbdev, fbnum, size);
+
+	if (r)
+		omapfb_alloc_fbmem(fbdev, fbnum, old_size);
+
+	return r;
+}
+
+/* allocate fbmem using display resolution as reference */
+static int omapfb_alloc_fbmem_display(struct omapfb2_device *fbdev, int fbnum,
+		unsigned long def_vram)
+{
+	struct omapfb_info *ofbi;
+	struct omap_display *display;
+	int bytespp;
+	unsigned long size;
+
+	ofbi = FB2OFB(fbdev->fbs[fbnum]);
+	display =  fb2display(fbdev->fbs[fbnum]);
+
+	if (!display)
+		return 0;
+
+	switch (display->panel->bpp) {
+	case 16:
+		bytespp = 2;
+		break;
+	case 24:
+	case 32:
+		bytespp = 4;
+		break;
+	default:
+		bytespp = 4;
+		break;
+	}
+
+	if (def_vram)
+		size = def_vram;
+	else
+		size = display->panel->timings.x_res *
+			display->panel->timings.y_res *
+			bytespp;
+
+	return omapfb_alloc_fbmem(fbdev, fbnum, size);
+}
+
+static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
+{
+	int i, r;
+	unsigned long vrams[10];
+
+	memset(vrams, 0, sizeof(vrams));
+
+	if (def_vram) {
+		char str[64];
+		char *tok, *s;
+
+		if (strlen(def_vram) > sizeof(str) - 1) {
+			dev_err(fbdev->dev, "Illegal vram parameters\n");
+			return -EINVAL;
+		}
+
+		strcpy(str, def_vram);
+
+		s = str;
+		i = 0;
+
+		while ((tok = strsep(&s, ","))) {
+			unsigned long size;
+
+			size = memparse(tok, NULL);
+
+			if (size == 0) {
+				dev_err(fbdev->dev, "illegal vram size\n");
+				break;
+			}
+
+			vrams[i++] = size;
+		}
+	}
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		/* allocate memory automatically only for fb0, or if
+		 * excplicitly defined with vram option */
+		if (i == 0 || vrams[i] != 0) {
+			r = omapfb_alloc_fbmem_display(fbdev, i, vrams[i]);
+
+			if (r)
+				return r;
+		}
+	}
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
+		struct omapfb_mem_region *rg;
+		rg = &ofbi->region;
+
+		DBG("region%d phys %08x virt %p size=%lu\n",
+				i,
+				rg->paddr,
+				rg->vaddr,
+				rg->size);
+	}
+
+	return 0;
+}
+
+/* initialize fb_info, var, fix to something sane based on the display */
+static int fbinfo_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
+{
+	struct fb_var_screeninfo *var = &fbi->var;
+	struct fb_fix_screeninfo *fix = &fbi->fix;
+	struct omap_display *display = fb2display(fbi);
+	int r = 0;
+
+	fbi->fbops = &omapfb_ops;
+	fbi->flags = FBINFO_FLAG_DEFAULT;
+	fbi->pseudo_palette = fbdev->pseudo_palette;
+
+	strncpy(fix->id, MODULE_NAME, sizeof(fix->id));
+
+	var->nonstd = 0;
+
+	if (display) {
+		var->xres = display->panel->timings.x_res;
+		var->yres = display->panel->timings.y_res;
+		var->xres_virtual = var->xres;
+		var->yres_virtual = var->yres;
+		/*        var->rotate       = def_rotate; */
+
+		switch (display->panel->bpp) {
+		case 16:
+			var->bits_per_pixel = 16;
+			break;
+		case 18:
+			var->bits_per_pixel = 16;
+			break;
+		case 24:
+			var->bits_per_pixel = 32;
+			break;
+		default:
+			dev_err(fbdev->dev, "illegal display bpp\n");
+			return -EINVAL;
+		}
+	}
+
+	r = check_fb_var(fbi, var);
+	if (r)
+		goto err;
+
+	set_fb_fix(fbi);
+
+#ifdef DEBUG
+	if (omapfb_debug)
+		fill_fb(FB2OFB(fbi)->region.vaddr, fbi);
+#endif
+err:
+	return r;
+}
+
+static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi)
+{
+	fb_dealloc_cmap(&fbi->cmap);
+}
+
+
+static void omapfb_free_resources(struct omapfb2_device *fbdev)
+{
+	int i;
+
+	DBG("free_resources\n");
+
+	if (fbdev == NULL)
+		return;
+
+	for (i = 0; i < fbdev->num_fbs; i++)
+		unregister_framebuffer(fbdev->fbs[i]);
+
+	/* free the reserved fbmem */
+	omapfb_free_all_fbmem(fbdev);
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		fbinfo_cleanup(fbdev, fbdev->fbs[i]);
+		framebuffer_release(fbdev->fbs[i]);
+	}
+
+	for (i = 0; i < fbdev->num_displays; i++) {
+		if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED)
+			fbdev->displays[i]->disable(fbdev->displays[i]);
+
+		omap_dss_put_display(fbdev->displays[i]);
+	}
+
+	dev_set_drvdata(fbdev->dev, NULL);
+	kfree(fbdev);
+}
+
+static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
+{
+	int r, i;
+
+	fbdev->num_fbs = 0;
+
+	DBG("create %d framebuffers\n",	CONFIG_FB_OMAP2_NUM_FBS);
+
+	/* allocate fb_infos */
+	for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
+		struct fb_info *fbi;
+		struct omapfb_info *ofbi;
+
+		fbi = framebuffer_alloc(sizeof(struct omapfb_info),
+				fbdev->dev);
+
+		if (fbi == NULL) {
+			dev_err(fbdev->dev,
+				"unable to allocate memory for plane info\n");
+			return -ENOMEM;
+		}
+
+		fbdev->fbs[i] = fbi;
+
+		ofbi = FB2OFB(fbi);
+		ofbi->fbdev = fbdev;
+		ofbi->id = i;
+		fbdev->num_fbs++;
+	}
+
+	DBG("fb_infos allocated\n");
+
+	/* assign overlays for the fbs */
+	for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
+		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
+
+		ofbi->overlays[0] = fbdev->overlays[i];
+		ofbi->num_overlays = 1;
+	}
+
+	/* allocate fb memories */
+	r = omapfb_allocate_all_fbs(fbdev);
+	if (r) {
+		dev_err(fbdev->dev, "failed to allocate fbmem\n");
+		return r;
+	}
+
+	DBG("fbmems allocated\n");
+
+	/* setup fb_infos */
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		r = fbinfo_init(fbdev, fbdev->fbs[i]);
+		if (r) {
+			dev_err(fbdev->dev, "failed to setup fb_info\n");
+			return r;
+		}
+	}
+
+	DBG("fb_infos initialized\n");
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		r = register_framebuffer(fbdev->fbs[i]);
+		if (r != 0) {
+			dev_err(fbdev->dev,
+				"registering framebuffer %d failed\n", i);
+			return r;
+		}
+	}
+
+	DBG("framebuffers registered\n");
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		r = omapfb_apply_changes(fbdev->fbs[i], 1);
+		if (r)
+			dev_err(fbdev->dev, "failed to change mode\n");
+	}
+
+	/* Enable fb0 */
+	if (fbdev->num_fbs > 0) {
+		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
+
+		if (ofbi->num_overlays > 0 ) {
+			struct omap_overlay *ovl = ofbi->overlays[0];
+
+			ovl->enable(ovl, 1);
+		}
+	}
+
+	DBG("create_framebuffers done\n");
+
+	return 0;
+}
+
+int omapfb_mode_to_timings(const char *mode_str,
+		struct omap_video_timings *timings, unsigned *bpp)
+{
+	struct fb_info fbi;
+	struct fb_var_screeninfo var;
+	struct fb_ops fbops;
+	int r;
+
+	/* this is quite a hack, but I wanted to use the modedb and for
+	 * that we need fb_info and var, so we create dummy ones */
+
+	memset(&fbi, 0, sizeof(fbi));
+	memset(&var, 0, sizeof(var));
+	memset(&fbops, 0, sizeof(fbops));
+	fbi.fbops = &fbops;
+
+	r = fb_find_mode(&var, &fbi, mode_str, NULL, 0, NULL, 24);
+
+	if (r != 0) {
+		timings->pixel_clock = PICOS2KHZ(var.pixclock);
+		timings->hfp = var.left_margin;
+		timings->hbp = var.right_margin;
+		timings->vfp = var.upper_margin;
+		timings->vbp = var.lower_margin;
+		timings->hsw = var.hsync_len;
+		timings->vsw = var.vsync_len;
+		timings->x_res = var.xres;
+		timings->y_res = var.yres;
+
+		switch (var.bits_per_pixel) {
+		case 16:
+			*bpp = 16;
+			break;
+		case 24:
+		case 32:
+		default:
+			*bpp = 24;
+			break;
+		}
+
+		return 0;
+	} else {
+		return -EINVAL;
+	}
+}
+
+static int omapfb_probe(struct platform_device *pdev)
+{
+	struct omapfb2_device *fbdev = NULL;
+	int r = 0;
+	int i, t;
+	struct omap_overlay *ovl;
+	struct omap_display *def_display;
+
+	DBG("omapfb_probe\n");
+
+	if (pdev->num_resources != 0) {
+		dev_err(&pdev->dev, "probed for an unknown device\n");
+		r = -ENODEV;
+		goto err0;
+	}
+
+	fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL);
+	if (fbdev == NULL) {
+		r = -ENOMEM;
+		goto err0;
+	}
+
+	mutex_init(&fbdev->mtx);
+
+	fbdev->dev = &pdev->dev;
+	platform_set_drvdata(pdev, fbdev);
+
+	fbdev->num_displays = 0;
+	t = omap_dss_get_num_displays();
+	for (i = 0; i < t; i++) {
+		struct omap_display *display;
+		display = omap_dss_get_display(i);
+		if (!display) {
+			dev_err(&pdev->dev, "can't get display %d\n", i);
+			r = -EINVAL;
+			goto cleanup;
+		}
+
+		fbdev->displays[fbdev->num_displays++] = display;
+	}
+
+	if (fbdev->num_displays == 0) {
+		dev_err(&pdev->dev, "no displays\n");
+		r = -EINVAL;
+		goto cleanup;
+	}
+
+	fbdev->num_overlays = omap_dss_get_num_overlays();
+	for (i = 0; i < fbdev->num_overlays; i++)
+		fbdev->overlays[i] = omap_dss_get_overlay(i);
+
+	fbdev->num_managers = omap_dss_get_num_overlay_managers();
+	for (i = 0; i < fbdev->num_managers; i++)
+		fbdev->managers[i] = omap_dss_get_overlay_manager(i);
+
+
+	/* gfx overlay should be the default one. find a display
+	 * connected to that, and use it as default display */
+	ovl = omap_dss_get_overlay(0);
+	if (ovl->manager && ovl->manager->display) {
+		def_display = ovl->manager->display;
+	} else {
+		dev_err(&pdev->dev, "cannot find default display\n");
+		r = -EINVAL;
+		goto cleanup;
+	}
+
+	if (def_mode && strlen(def_mode) > 0)
+	{
+		struct omap_video_timings timings;
+		unsigned bpp;
+
+		if (omapfb_mode_to_timings(def_mode, &timings, &bpp) == 0) {
+			if (def_display->set_timings)
+				def_display->set_timings(def_display, &timings);
+
+			def_display->panel->bpp = bpp;
+		}
+	}
+
+	r = omapfb_create_framebuffers(fbdev);
+	if (r)
+		goto cleanup;
+
+	for (i = 0; i < fbdev->num_managers; i++) {
+		struct omap_overlay_manager *mgr;
+		mgr = fbdev->managers[i];
+		r = mgr->apply(mgr);
+		if (r) {
+			dev_err(fbdev->dev, "failed to apply dispc config\n");
+			goto cleanup;
+		}
+	}
+
+	DBG("mgr->apply'ed\n");
+
+	r = def_display->enable(def_display);
+	if (r) {
+		dev_err(fbdev->dev, "Failed to enable display '%s'\n",
+				def_display->name);
+		goto cleanup;
+	}
+
+	/* set the update mode */
+	if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE
+		if (def_display->set_update_mode)
+			def_display->set_update_mode(def_display,
+					OMAP_DSS_UPDATE_AUTO);
+		if (def_display->enable_te)
+			def_display->enable_te(def_display, 1);
+#else
+		if (def_display->set_update_mode)
+			def_display->set_update_mode(def_display,
+					OMAP_DSS_UPDATE_MANUAL);
+		if (def_display->enable_te)
+			def_display->enable_te(def_display, 0);
+#endif
+	} else {
+		if (def_display->set_update_mode)
+			def_display->set_update_mode(def_display,
+					OMAP_DSS_UPDATE_AUTO);
+	}
+
+	for (i = 0; i < fbdev->num_displays; i++) {
+		struct omap_display *display = fbdev->displays[i];
+
+		if (display->update)
+			display->update(display,
+					0, 0,
+					display->panel->timings.x_res,
+					display->panel->timings.y_res);
+	}
+
+	DBG("display->updated\n");
+
+	omapfb_create_sysfs(fbdev);
+	DBG("sysfs created\n");
+
+	return 0;
+
+cleanup:
+	omapfb_free_resources(fbdev);
+err0:
+	dev_err(&pdev->dev, "failed to setup omapfb\n");
+	return r;
+}
+
+static int omapfb_remove(struct platform_device *pdev)
+{
+	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
+
+	/* FIXME: wait till completion of pending events */
+
+	omapfb_remove_sysfs(fbdev);
+
+	omapfb_free_resources(fbdev);
+
+	return 0;
+}
+
+static struct platform_driver omapfb_driver = {
+	.probe          = omapfb_probe,
+	.remove         = omapfb_remove,
+	.driver         = {
+		.name   = "omapfb",
+		.owner  = THIS_MODULE,
+	},
+};
+
+static int __init omapfb_init(void)
+{
+	DBG("omapfb_init\n");
+
+	if (platform_driver_register(&omapfb_driver)) {
+		printk(KERN_ERR "failed to register omapfb driver\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit omapfb_exit(void)
+{
+	DBG("omapfb_exit\n");
+	platform_driver_unregister(&omapfb_driver);
+}
+
+module_param_named(video_mode, def_mode, charp, 0);
+module_param_named(vram, def_vram, charp, 0);
+
+/* late_initcall to let panel/ctrl drivers loaded first.
+ * I guess better option would be a more dynamic approach,
+ * so that omapfb reacts to new panels when they are loaded */
+late_initcall(omapfb_init);
+/*module_init(omapfb_init);*/
+module_exit(omapfb_exit);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
+MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/omap2/omapfb-sysfs.c b/drivers/video/omap2/omapfb-sysfs.c
new file mode 100644
index 0000000..0e153b9
--- /dev/null
+++ b/drivers/video/omap2/omapfb-sysfs.c
@@ -0,0 +1,901 @@
+/*
+ * linux/drivers/video/omap2/omapfb-sysfs.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/fb.h>
+#include <linux/sysfs.h>
+#include <linux/device.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+
+#include <mach/display.h>
+#include <mach/omapfb.h>
+
+#include "omapfb.h"
+
+static int omapfb_attach_framebuffer(struct fb_info *fbi,
+		struct omap_overlay *ovl)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	int i, t;
+	int r;
+
+	if (ofbi->num_overlays >= OMAPFB_MAX_OVL_PER_FB) {
+		dev_err(fbdev->dev, "fb has max number of overlays already\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ofbi->num_overlays; i++) {
+		if (ofbi->overlays[i] == ovl) {
+			dev_err(fbdev->dev, "fb already attached to overlay\n");
+			return -EINVAL;
+		}
+	}
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
+		for (t = 0; t < ofbi2->num_overlays; t++) {
+			if (ofbi2->overlays[t] == ovl) {
+				dev_err(fbdev->dev, "overlay already in use\n");
+				return -EINVAL;
+			}
+		}
+	}
+
+	ofbi->overlays[ofbi->num_overlays++] = ovl;
+
+/*
+	if (ovl->manager && ovl->manager->display)
+		omapfb_adjust_fb(fbi, ovl, 0, 0);
+*/
+	r = omapfb_apply_changes(fbi, 1);
+	if (r)
+		return r;
+
+	if (ovl->manager)
+		ovl->manager->apply(ovl->manager);
+
+	return 0;
+}
+
+static int omapfb_detach_framebuffer(struct fb_info *fbi,
+		struct omap_overlay *ovl)
+{
+	int i;
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+
+	for (i = 0; i < ofbi->num_overlays; i++) {
+		if (ofbi->overlays[i] == ovl)
+			break;
+	}
+
+	if (i == ofbi->num_overlays) {
+		dev_err(fbdev->dev, "cannot detach fb, overlay not attached\n");
+		return -EINVAL;
+	}
+
+	ovl->enable(ovl, 0);
+
+	if (ovl->manager)
+		ovl->manager->apply(ovl->manager);
+
+	for (i = i + 1; i < ofbi->num_overlays; i++)
+		ofbi->overlays[i-1] = ofbi->overlays[i];
+
+	ofbi->num_overlays--;
+
+	return 0;
+}
+
+
+static ssize_t show_framebuffers(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
+	ssize_t l = 0, size = PAGE_SIZE;
+	int i, t;
+
+	omapfb_lock(fbdev);
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
+		struct omapfb_mem_region *rg;
+
+		rg = &ofbi->region;
+
+		l += snprintf(buf + l, size - l, "%d p:%08x v:%p size:%lu t:",
+				ofbi->id,
+				rg->paddr, rg->vaddr, rg->size);
+
+		if (ofbi->num_overlays == 0)
+			l += snprintf(buf + l, size - l, "none");
+
+		for (t = 0; t < ofbi->num_overlays; t++) {
+			struct omap_overlay *ovl;
+			ovl = ofbi->overlays[t];
+
+			l += snprintf(buf + l, size - l, "%s%s",
+					t == 0 ? "" : ",",
+					ovl->name);
+		}
+
+		l += snprintf(buf + l, size - l, "\n");
+	}
+
+	omapfb_unlock(fbdev);
+
+	return l;
+}
+
+static struct omap_overlay *find_overlay_by_name(struct omapfb2_device *fbdev,
+		char *name)
+{
+	int i;
+
+	for (i = 0; i < fbdev->num_overlays; i++)
+		if (strcmp(name, fbdev->overlays[i]->name) == 0)
+			return fbdev->overlays[i];
+
+	return NULL;
+}
+
+static struct omap_display *find_display_by_name(struct omapfb2_device *fbdev,
+		char *name)
+{
+	int i;
+
+	for (i = 0; i < fbdev->num_displays; i++)
+		if (strcmp(name, fbdev->displays[i]->name) == 0)
+			return fbdev->displays[i];
+
+	return NULL;
+}
+
+static struct omap_overlay_manager *find_manager_by_name(
+		struct omapfb2_device *fbdev,
+		char *name)
+{
+	int i;
+
+	for (i = 0; i < fbdev->num_managers; i++)
+		if (strcmp(name, fbdev->managers[i]->name) == 0)
+			return fbdev->managers[i];
+
+	return NULL;
+}
+
+static int parse_overlays(struct omapfb2_device *fbdev, char *str,
+		struct omap_overlay *ovls[])
+{
+	int num_ovls = 0;
+	int s, e = 0;
+	char ovlname[10];
+
+	while (1) {
+		struct omap_overlay *ovl;
+
+		s = e;
+
+		while (e < strlen(str) && str[e] != ',')
+			e++;
+
+		strncpy(ovlname, str + s, e - s);
+		ovlname[e-s] = 0;
+
+		DBG("searching for '%s'\n", ovlname);
+		ovl = find_overlay_by_name(fbdev, ovlname);
+
+		if (ovl) {
+			DBG("found an overlay\n");
+			ovls[num_ovls] = ovl;
+			num_ovls++;
+		} else {
+			DBG("unknown overlay %s\n", str);
+			return 0;
+		}
+
+		if (e == strlen(str))
+			break;
+
+		e++;
+	}
+
+	return num_ovls;
+}
+
+static ssize_t store_framebuffers(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
+	int idx;
+	char fbname[3];
+	unsigned long fbnum;
+	char ovlnames[40];
+	int num_ovls = 0;
+	struct omap_overlay *ovls[OMAPFB_MAX_OVL_PER_FB];
+	struct fb_info *fbi;
+	struct omapfb_info *ofbi;
+	int r, i;
+
+	idx = 0;
+	while (idx < count && buf[idx] != ' ')
+		++idx;
+
+	if (idx == count)
+		return -EINVAL;
+
+	if (idx >= sizeof(fbname))
+		return -EINVAL;
+
+	strncpy(fbname, buf, idx);
+	fbname[idx] = 0;
+	idx++;
+
+	if (strict_strtoul(fbname, 10, &fbnum))
+		return -EINVAL;
+
+	r = sscanf(buf + idx, "t:%39s", ovlnames);
+
+	if (r != 1) {
+		r = -EINVAL;
+		goto err;
+	}
+
+	omapfb_lock(fbdev);
+
+	if (fbnum >= fbdev->num_fbs) {
+		dev_err(dev, "fb not found\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	fbi = fbdev->fbs[fbnum];
+	ofbi = FB2OFB(fbi);
+
+	if (strcmp(ovlnames, "none") == 0) {
+		num_ovls = 0;
+	} else {
+		num_ovls = parse_overlays(fbdev, ovlnames, ovls);
+
+		if (num_ovls == 0) {
+			dev_err(dev, "overlays not found\n");
+			r = -EINVAL;
+			goto err;
+		}
+	}
+
+	for (i = 0; i < ofbi->num_overlays; i++) {
+		r = omapfb_detach_framebuffer(fbi, ofbi->overlays[i]);
+		if (r) {
+			dev_err(dev, "detach failed\n");
+			goto err;
+		}
+	}
+
+	if (num_ovls > 0) {
+		for (i = 0; i < num_ovls; i++) {
+			r = omapfb_attach_framebuffer(fbi, ovls[i]);
+			if (r) {
+				dev_err(dev, "attach failed\n");
+				goto err;
+			}
+		}
+	}
+
+	omapfb_unlock(fbdev);
+	return count;
+
+err:
+	omapfb_unlock(fbdev);
+	return r;
+}
+
+static ssize_t show_overlays(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
+	ssize_t l = 0, size = PAGE_SIZE;
+	int i, mgr_num;
+
+	omapfb_lock(fbdev);
+
+	for (i = 0; i < fbdev->num_overlays; i++) {
+		struct omap_overlay *ovl;
+		struct omap_overlay_manager *mgr;
+
+		ovl = fbdev->overlays[i];
+		mgr = ovl->manager;
+
+		for (mgr_num = 0; mgr_num < fbdev->num_managers; mgr_num++)
+			if (fbdev->managers[mgr_num] == mgr)
+				break;
+
+		l += snprintf(buf + l, size - l,
+			"%s t:%s x:%d y:%d iw:%d ih:%d w:%d h:%d e:%d\n",
+			ovl->name,
+			mgr ? mgr->name : "none",
+			ovl->info.pos_x,
+			ovl->info.pos_y,
+			ovl->info.width,
+			ovl->info.height,
+			ovl->info.out_width,
+			ovl->info.out_height,
+			ovl->info.enabled);
+	}
+
+	omapfb_unlock(fbdev);
+
+	return l;
+}
+
+static ssize_t store_overlays(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
+	int idx;
+	struct omap_overlay *ovl = NULL;
+	struct omap_overlay_manager *mgr;
+	int r;
+	char ovlname[10];
+	int posx, posy, outw, outh;
+	int enabled;
+
+	idx = 0;
+	while (idx < count && buf[idx] != ' ')
+		++idx;
+
+	if (idx == count)
+		return -EINVAL;
+
+	if (idx >= sizeof(ovlname))
+		return -EINVAL;
+
+	strncpy(ovlname, buf, idx);
+	ovlname[idx] = 0;
+	idx++;
+
+	omapfb_lock(fbdev);
+
+	ovl = find_overlay_by_name(fbdev, ovlname);
+
+	if (!ovl) {
+		dev_err(dev, "ovl not found\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	DBG("ovl %s found\n", ovl->name);
+
+	mgr = ovl->manager;
+
+	posx = ovl->info.pos_x;
+	posy = ovl->info.pos_y;
+	outw = ovl->info.out_width;
+	outh = ovl->info.out_height;
+	enabled = ovl->info.enabled;
+
+	while (idx < count) {
+		char c;
+		int val;
+		int len;
+		char sval[10];
+
+		r = sscanf(buf + idx, "%c:%d%n", &c, &val, &len);
+
+		if (r != 2) {
+			val = 0;
+
+			r = sscanf(buf + idx, "%c:%9s%n", &c, sval, &len);
+
+			if (r != 2) {
+				dev_err(dev, "sscanf failed, aborting\n");
+				r = -EINVAL;
+				goto err;
+			}
+		} else {
+			sval[0] = 0;
+		}
+
+		switch (c) {
+		case 't':
+			if (strcmp(sval, "none") == 0) {
+				mgr = NULL;
+			} else {
+				mgr = find_manager_by_name(fbdev, sval);
+
+				if (mgr == NULL) {
+					dev_err(dev, "no such manager\n");
+					r = -EINVAL;
+					goto err;
+				}
+
+				DBG("manager %s found\n", mgr->name);
+			}
+
+			break;
+
+		case 'x':
+			posx = val;
+			break;
+
+		case 'y':
+			posy = val;
+			break;
+
+		case 'w':
+			if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE)
+				outw = val;
+			break;
+
+		case 'h':
+			if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE)
+				outh = val;
+			break;
+
+		case 'e':
+			enabled = val;
+			break;
+
+		default:
+			dev_err(dev, "unknown option %c\n", c);
+			r = -EINVAL;
+			goto err;
+		}
+
+		idx += len + 1;
+	}
+
+	r = ovl->setup_output(ovl, posx, posy, outw, outh);
+
+	if (r) {
+		dev_err(dev, "setup overlay failed\n");
+		goto err;
+	}
+
+	if (mgr != ovl->manager) {
+		/* detach old manager */
+		if (ovl->manager) {
+			r = ovl->unset_manager(ovl);
+			if (r) {
+				dev_err(dev, "detach failed\n");
+				goto err;
+			}
+		}
+
+		if (mgr) {
+			r = ovl->set_manager(ovl, mgr);
+			if (r) {
+				dev_err(dev, "Failed to attach overlay\n");
+				goto err;
+			}
+		}
+	}
+
+	r = ovl->enable(ovl, enabled);
+
+	if (r) {
+		dev_err(dev, "enable overlay failed\n");
+		goto err;
+	}
+
+	if (mgr) {
+		r = mgr->apply(mgr);
+		if (r) {
+			dev_err(dev, "failed to apply dispc config\n");
+			goto err;
+		}
+	} else {
+		ovl->enable(ovl, 0);
+	}
+
+	if (mgr && mgr->display && mgr->display->update)
+		mgr->display->update(mgr->display,
+				0, 0,
+				mgr->display->panel->timings.x_res,
+				mgr->display->panel->timings.y_res);
+
+	omapfb_unlock(fbdev);
+	return count;
+
+err:
+	omapfb_unlock(fbdev);
+	return r;
+}
+
+static ssize_t show_managers(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
+	ssize_t l = 0, size = PAGE_SIZE;
+	int i;
+
+	omapfb_lock(fbdev);
+
+	for (i = 0; i < fbdev->num_managers; i++) {
+		struct omap_display *display;
+		struct omap_overlay_manager *mgr;
+
+		mgr = fbdev->managers[i];
+		display = mgr->display;
+
+		l += snprintf(buf + l, size - l, "%s t:%s\n",
+				mgr->name, display ? display->name : "none");
+	}
+
+	omapfb_unlock(fbdev);
+
+	return l;
+}
+
+static ssize_t store_managers(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
+	int idx;
+	struct omap_overlay_manager *mgr;
+	struct omap_display *display;
+	char mgrname[10];
+	char displayname[10];
+	int r;
+
+	idx = 0;
+	while (idx < count && buf[idx] != ' ')
+		++idx;
+
+	if (idx == count)
+		return -EINVAL;
+
+	if (idx >= sizeof(mgrname))
+		return -EINVAL;
+
+	strncpy(mgrname, buf, idx);
+	mgrname[idx] = 0;
+	idx++;
+
+	omapfb_lock(fbdev);
+
+	mgr = find_manager_by_name(fbdev, mgrname);
+
+	if (!mgr) {
+		dev_err(dev, "manager not found\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	r = sscanf(buf + idx, "t:%9s", displayname);
+
+	if (r != 1) {
+		r = -EINVAL;
+		goto err;
+	}
+
+	if (strcmp(displayname, "none") == 0) {
+		display = NULL;
+	} else {
+		display = find_display_by_name(fbdev, displayname);
+
+		if (!display) {
+			dev_err(dev, "display not found\n");
+			r = -EINVAL;
+			goto err;
+		}
+	}
+
+	if (mgr->display) {
+		r = mgr->unset_display(mgr);
+		if (r) {
+			dev_err(dev, "failed to unset display\n");
+			goto err;
+		}
+	}
+
+	if (display) {
+		r = mgr->set_display(mgr, display);
+		if (r) {
+			dev_err(dev, "failed to set manager\n");
+			goto err;
+		}
+
+		r = mgr->apply(mgr);
+		if (r) {
+			dev_err(dev, "failed to apply dispc config\n");
+			goto err;
+		}
+	}
+
+	omapfb_unlock(fbdev);
+	return count;
+
+err:
+	omapfb_unlock(fbdev);
+	return r;
+}
+
+static ssize_t show_displays(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
+	ssize_t l = 0, size = PAGE_SIZE;
+	int i;
+	struct omap_video_timings timings;
+
+	omapfb_lock(fbdev);
+
+	for (i = 0; i < fbdev->num_displays; i++) {
+		struct omap_display *display;
+		enum omap_dss_update_mode mode = -1;
+		int te = 0;
+
+		display = fbdev->displays[i];
+
+		if (display->get_update_mode)
+			mode = display->get_update_mode(display);
+
+		if (display->get_te)
+			te = display->get_te(display);
+
+		if (display->get_timings)
+			display->get_timings(display, &timings);
+		else
+			memset(&timings, 0, sizeof(timings));
+
+		l += snprintf(buf + l, size - l,
+				"%s e:%d u:%d t:%d h:%u/%u/%u/%u "
+				"v:%u/%u/%u/%u p:%u\n",
+				display->name,
+				display->state != OMAP_DSS_DISPLAY_DISABLED,
+				mode, te,
+				timings.x_res,
+				timings.hfp, timings.hbp, timings.hsw,
+				timings.y_res,
+				timings.vfp, timings.vbp, timings.vsw,
+				timings.pixel_clock);
+	}
+
+	omapfb_unlock(fbdev);
+
+	return l;
+}
+
+static ssize_t store_displays(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
+	int enable;
+	struct omap_video_timings old_timings;
+	struct omap_video_timings new_timings;
+	enum omap_dss_update_mode mode;
+	struct omap_display *display = NULL;
+	int r;
+	int te;
+	char str[128];
+	char *s, *tok;
+
+	if (strlen(buf) > sizeof(str) - 1)
+		return -EINVAL;
+
+	strcpy(str, buf);
+
+	/* remove trailing linefeeds */
+	s = str + strlen(str) - 1;
+	while (s >= str	&& *s == '\n') {
+		*s = 0;
+		s--;
+	}
+
+	s = str;
+
+	if ((tok = strsep(&s, " ")) == 0)
+		return -EINVAL;
+
+	omapfb_lock(fbdev);
+
+	display = find_display_by_name(fbdev, tok);
+
+	if (!display) {
+		dev_err(dev, "display not found\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	enable = display->state != OMAP_DSS_DISPLAY_DISABLED;
+	if (display->get_update_mode)
+		mode = display->get_update_mode(display);
+	else
+		mode = 0;
+
+	if (display->get_te)
+		te = display->get_te(display);
+	else
+		te = 0;
+
+	if (display->get_timings)
+		display->get_timings(display, &old_timings);
+	else
+		memset(&old_timings, 0, sizeof(old_timings));
+
+	memcpy(&new_timings, &old_timings, sizeof(new_timings));
+
+	while ((tok = strsep(&s, " "))) {
+		char c, *o;
+
+		if (strlen(tok) < 3 || tok[1] != ':') {
+			dev_err(dev, "illegal option\n");
+			r = -EINVAL;
+			goto err;
+		}
+
+		c = tok[0];
+		o = tok + 2;
+
+		switch (c) {
+		case 'e':
+			enable = simple_strtoul(o, NULL, 0);
+			break;
+
+		case 'u':
+			mode = simple_strtoul(o, NULL, 0);
+			break;
+
+		case 't':
+			te = simple_strtoul(o, NULL, 0);
+			break;
+
+		case 'm': {
+			unsigned bpp;
+			if (omapfb_mode_to_timings(o, &new_timings, &bpp) != 0)
+				memset(&new_timings, 0, sizeof(new_timings));
+
+			break;
+		}
+
+		case 'h': {
+			unsigned xres, hfp, hbp, hsw;
+
+			if (sscanf(o, "%u/%u/%u/%u",
+						&xres, &hfp, &hbp, &hsw) != 4) {
+				dev_err(dev, "illegal horizontal timings\n");
+				r = -EINVAL;
+				goto err;
+			}
+
+			new_timings.x_res = xres;
+			new_timings.hfp = hfp;
+			new_timings.hbp = hbp;
+			new_timings.hsw = hsw;
+			break;
+		}
+
+		case 'v': {
+			unsigned yres, vfp, vbp, vsw;
+
+			if (sscanf(o, "%u/%u/%u/%u",
+						&yres, &vfp, &vbp, &vsw) != 4) {
+				dev_err(dev, "illegal vertical timings\n");
+				r = -EINVAL;
+				goto err;
+			}
+
+			new_timings.y_res = yres;
+			new_timings.vfp = vfp;
+			new_timings.vbp = vbp;
+			new_timings.vsw = vsw;
+			break;
+		}
+
+		case 'p':
+			new_timings.pixel_clock = simple_strtoul(o, NULL, 0);
+			break;
+
+		default:
+			dev_err(dev, "unknown option %c\n", c);
+			r = -EINVAL;
+			goto err;
+		}
+	}
+
+	if (memcmp(&new_timings, &old_timings, sizeof(new_timings)) != 0) {
+		if (display->set_timings)
+			display->set_timings(display, &new_timings);
+
+		/* sigh, bpp is not a setting of the display, but
+		 * the overlay. */
+		//def_display->panel->bpp = bpp;
+	}
+
+	if (enable != (display->state != OMAP_DSS_DISPLAY_DISABLED)) {
+		if (enable) {
+			r = display->enable(display);
+			if (r)
+				dev_err(dev, "failed to enable display\n");
+		} else {
+			display->disable(display);
+		}
+	}
+
+	if (display->set_update_mode && display->get_update_mode) {
+		if (mode != display->get_update_mode(display))
+			display->set_update_mode(display, mode);
+	}
+
+	if (display->enable_te && display->get_te) {
+		if (te != display->get_te(display))
+			display->enable_te(display, te);
+	}
+
+	r = count;
+err:
+	omapfb_unlock(fbdev);
+	return r;
+}
+
+
+static DEVICE_ATTR(framebuffers, S_IRUGO | S_IWUSR,
+		show_framebuffers, store_framebuffers);
+static DEVICE_ATTR(overlays, S_IRUGO | S_IWUSR,
+		show_overlays, store_overlays);
+static DEVICE_ATTR(managers, S_IRUGO | S_IWUSR,
+		show_managers, store_managers);
+static DEVICE_ATTR(displays, S_IRUGO | S_IWUSR,
+		show_displays, store_displays);
+
+static struct attribute *omapfb_attrs[] = {
+	&dev_attr_framebuffers.attr,
+	&dev_attr_overlays.attr,
+	&dev_attr_managers.attr,
+	&dev_attr_displays.attr,
+	NULL,
+};
+
+static struct attribute_group omapfb_attr_group = {
+	.attrs = omapfb_attrs,
+};
+
+void omapfb_create_sysfs(struct omapfb2_device *fbdev)
+{
+	int r;
+
+	r = sysfs_create_group(&fbdev->dev->kobj, &omapfb_attr_group);
+	if (r)
+		dev_err(fbdev->dev, "failed to create sysfs clk file\n");
+}
+
+void omapfb_remove_sysfs(struct omapfb2_device *fbdev)
+{
+	sysfs_remove_group(&fbdev->dev->kobj, &omapfb_attr_group);
+}
+
diff --git a/drivers/video/omap2/omapfb.h b/drivers/video/omap2/omapfb.h
new file mode 100644
index 0000000..9ba4f1b
--- /dev/null
+++ b/drivers/video/omap2/omapfb.h
@@ -0,0 +1,115 @@
+/*
+ * linux/drivers/video/omap2/omapfb.h
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
+#define __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
+
+#ifdef CONFIG_FB_OMAP2_DEBUG
+#define DEBUG
+#endif
+
+#ifdef DEBUG
+extern unsigned int omapfb_debug;
+#define DBG(format, ...) \
+	if (omapfb_debug) \
+		printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__)
+#else
+#define DBG(format, ...)
+#endif
+
+#define FB2OFB(fb_info) ((struct omapfb_info *)(fb_info->par))
+
+/* max number of overlays to which a framebuffer data can be direct */
+#define OMAPFB_MAX_OVL_PER_FB 3
+
+/* appended to fb_info */
+struct omapfb_info {
+	int id;
+	struct omapfb_mem_region region;
+	atomic_t map_count;
+	int num_overlays;
+	struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
+	struct omapfb2_device *fbdev;
+};
+
+struct omapfb2_device {
+	struct device *dev;
+	struct mutex  mtx;
+
+	u32 pseudo_palette[17];
+
+	int state;
+
+	int num_fbs;
+	struct fb_info *fbs[10];
+
+	int num_displays;
+	struct omap_display *displays[10];
+	int num_overlays;
+	struct omap_overlay *overlays[10];
+	int num_managers;
+	struct omap_overlay_manager *managers[10];
+};
+
+void set_fb_fix(struct fb_info *fbi);
+int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var);
+int omapfb_realloc_fbmem(struct omapfb2_device *fbdev, int fbnum,
+		unsigned long size);
+int omapfb_apply_changes(struct fb_info *fbi, int init);
+int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
+		int posx, int posy, int outw, int outh);
+
+void omapfb_create_sysfs(struct omapfb2_device *fbdev);
+void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
+
+int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
+
+int omapfb_mode_to_timings(const char *mode_str,
+		struct omap_video_timings *timings, unsigned *bpp);
+
+/* find the display connected to this fb, if any */
+static inline struct omap_display *fb2display(struct fb_info *fbi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	int i;
+
+	/* XXX: returns the display connected to first attached overlay */
+	for (i = 0; i < ofbi->num_overlays; i++) {
+		if (ofbi->overlays[i]->manager)
+			return ofbi->overlays[i]->manager->display;
+	}
+
+	return NULL;
+}
+
+static inline void omapfb_lock(struct omapfb2_device *fbdev)
+{
+	mutex_lock(&fbdev->mtx);
+}
+
+static inline void omapfb_unlock(struct omapfb2_device *fbdev)
+{
+	mutex_unlock(&fbdev->mtx);
+}
+
+
+#endif


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 07/12] DSS: Add generic DVI panel
  2009-01-12 11:47 [PATCH 00/12] DSS: Series description Tomi Valkeinen
                   ` (5 preceding siblings ...)
  2009-01-12 11:47 ` [PATCH 06/12] DSS: OMAPFB: fb driver for new display subsystem Tomi Valkeinen
@ 2009-01-12 11:48 ` Tomi Valkeinen
  2009-01-12 11:48 ` [PATCH 08/12] DSS: support for Beagle Board Tomi Valkeinen
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 23+ messages in thread
From: Tomi Valkeinen @ 2009-01-12 11:48 UTC (permalink / raw)
  To: linux-fbdev-devel; +Cc: linux-omap

You also need DSI PLL to generate pix clock for 1280x1024.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
---

 drivers/video/omap2/Kconfig         |    5 ++
 drivers/video/omap2/Makefile        |    2 +
 drivers/video/omap2/panel-generic.c |   97 +++++++++++++++++++++++++++++++++++
 3 files changed, 104 insertions(+), 0 deletions(-)
 create mode 100644 drivers/video/omap2/panel-generic.c

diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
index 8be51a3..be00882 100644
--- a/drivers/video/omap2/Kconfig
+++ b/drivers/video/omap2/Kconfig
@@ -37,6 +37,11 @@ config FB_OMAP2_NUM_FBS
 menu "OMAP2/3 Display Device Drivers"
         depends on OMAP2_DSS
 
+config PANEL_GENERIC
+        tristate "Generic Panel"
+        help
+	  Generic panel driver.
+	  Used for DVI output for Beagle and OMAP3 SDP.
 
 endmenu
 
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
index 51c2e00..f471a2b 100644
--- a/drivers/video/omap2/Makefile
+++ b/drivers/video/omap2/Makefile
@@ -1,2 +1,4 @@
 obj-$(CONFIG_FB_OMAP2) += omapfb.o
 omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
+
+obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o
diff --git a/drivers/video/omap2/panel-generic.c b/drivers/video/omap2/panel-generic.c
new file mode 100644
index 0000000..5c8fecd
--- /dev/null
+++ b/drivers/video/omap2/panel-generic.c
@@ -0,0 +1,97 @@
+/*
+ * Generic panel support
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+
+#include <mach/display.h>
+
+static int generic_panel_init(struct omap_display *display)
+{
+	return 0;
+}
+
+static int generic_panel_enable(struct omap_display *display)
+{
+	int r = 0;
+
+	if (display->hw_config.panel_enable)
+		r = display->hw_config.panel_enable(display);
+
+	return r;
+}
+
+static void generic_panel_disable(struct omap_display *display)
+{
+	if (display->hw_config.panel_disable)
+		display->hw_config.panel_disable(display);
+}
+
+static int generic_panel_suspend(struct omap_display *display)
+{
+	generic_panel_disable(display);
+	return 0;
+}
+
+static int generic_panel_resume(struct omap_display *display)
+{
+	return generic_panel_enable(display);
+}
+
+static struct omap_panel generic_panel = {
+	.owner		= THIS_MODULE,
+	.name		= "panel-generic",
+	.init		= generic_panel_init,
+	.enable		= generic_panel_enable,
+	.disable	= generic_panel_disable,
+	.suspend	= generic_panel_suspend,
+	.resume		= generic_panel_resume,
+
+	.timings = {
+		/* 640 x 480 @ 60 Hz  Reduced blanking VESA CVT 0.31M3-R */
+		.x_res		= 640,
+		.y_res		= 480,
+		.pixel_clock	= 23500,
+		.hfp		= 48,
+		.hsw		= 32,
+		.hbp		= 80,
+		.vfp		= 3,
+		.vsw		= 4,
+		.vbp		= 7,
+	},
+
+	.bpp		= 24,
+	.config		= OMAP_DSS_LCD_TFT,
+};
+
+
+static int __init generic_panel_drv_init(void)
+{
+	omap_dss_register_panel(&generic_panel);
+	return 0;
+}
+
+static void __exit generic_panel_drv_exit(void)
+{
+	omap_dss_unregister_panel(&generic_panel);
+}
+
+module_init(generic_panel_drv_init);
+module_exit(generic_panel_drv_exit);
+MODULE_LICENSE("GPL");


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 08/12] DSS: support for Beagle Board
  2009-01-12 11:47 [PATCH 00/12] DSS: Series description Tomi Valkeinen
                   ` (6 preceding siblings ...)
  2009-01-12 11:48 ` [PATCH 07/12] DSS: Add generic DVI panel Tomi Valkeinen
@ 2009-01-12 11:48 ` Tomi Valkeinen
  2009-01-13 11:14   ` David Brownell
  2009-01-12 11:48 ` [PATCH 09/12] DSS: Sharp LS037V7DW01 LCD Panel driver Tomi Valkeinen
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 23+ messages in thread
From: Tomi Valkeinen @ 2009-01-12 11:48 UTC (permalink / raw)
  To: linux-fbdev-devel; +Cc: linux-omap

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
---

 arch/arm/configs/dss_omap3_beagle_defconfig | 1437 +++++++++++++++++++++++++++
 arch/arm/mach-omap2/board-omap3beagle.c     |  101 ++
 2 files changed, 1524 insertions(+), 14 deletions(-)
 create mode 100644 arch/arm/configs/dss_omap3_beagle_defconfig

diff --git a/arch/arm/configs/dss_omap3_beagle_defconfig b/arch/arm/configs/dss_omap3_beagle_defconfig
new file mode 100644
index 0000000..f39167f
--- /dev/null
+++ b/arch/arm/configs/dss_omap3_beagle_defconfig
@@ -0,0 +1,1437 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.28-omap1
+# Wed Jan  7 15:22:00 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+# CONFIG_OMAP_SMARTREFLEX is not set
+# CONFIG_OMAP_RESET_CLOCKS is not set
+CONFIG_OMAP_BOOT_TAG=y
+CONFIG_OMAP_BOOT_REASON=y
+# CONFIG_OMAP_COMPONENT_VERSION is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+# CONFIG_OMAP_MUX is not set
+# CONFIG_OMAP_MCBSP is not set
+# CONFIG_OMAP_MMU_FWK is not set
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+CONFIG_OMAP2_DSS=m
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+# CONFIG_OMAP2_DSS_DSI is not set
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_OMAP3EVM is not set
+CONFIG_MACH_OMAP3_BEAGLE=y
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+CONFIG_OMAP_TICK_GPTIMER=12
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/home/user/buildroot ip=192.168.0.2:192.168.0.1:192.168.0.1:255.255.255.0:tgt:eth0:off rw console=ttyS2,115200n8"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+# CONFIG_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SUSPEND is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_NET_ETHERNET is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C2_OMAP_BEAGLE is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_MADC is not set
+# CONFIG_TWL4030_PWRBUTTON is not set
+# CONFIG_TWL4030_POWEROFF is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_LP5521 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_POWER is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=4
+CONFIG_FB_OMAP2=m
+# CONFIG_FB_OMAP2_DEBUG is not set
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=m
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=y
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index fe97bab..61f0fc9 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -43,6 +43,8 @@
 #include <mach/gpmc.h>
 #include <mach/nand.h>
 #include <mach/mux.h>
+#include <mach/omapfb.h>
+#include <mach/display.h>
 
 #include "twl4030-generic-scripts.h"
 #include "mmc-twl4030.h"
@@ -238,15 +240,6 @@ static void __init omap3_beagle_init_irq(void)
 	omap_gpio_init();
 }
 
-static struct platform_device omap3_beagle_lcd_device = {
-	.name		= "omap3beagle_lcd",
-	.id		= -1,
-};
-
-static struct omap_lcd_config omap3_beagle_lcd_config __initdata = {
-	.ctrl_name	= "internal",
-};
-
 static struct gpio_led gpio_leds[] = {
 	{
 		.name			= "beagleboard::usr0",
@@ -300,13 +293,94 @@ static struct platform_device keys_gpio = {
 	},
 };
 
+/* DSS */
+
+static int beagle_enable_dvi(struct omap_display *display)
+{
+	if (display->hw_config.panel_reset_gpio != -1)
+		gpio_direction_output(display->hw_config.panel_reset_gpio, 1);
+
+	return 0;
+}
+
+static void beagle_disable_dvi(struct omap_display *display)
+{
+	if (display->hw_config.panel_reset_gpio != -1)
+		gpio_direction_output(display->hw_config.panel_reset_gpio, 0);
+}
+
+static struct omap_display_data beagle_display_data_dvi = {
+	.type = OMAP_DISPLAY_TYPE_DPI,
+	.name = "dvi",
+	.panel_name = "panel-generic",
+	.u.dpi.data_lines = 24,
+	.panel_reset_gpio = 170,
+	.panel_enable = beagle_enable_dvi,
+	.panel_disable = beagle_disable_dvi,
+};
+
+
+static int beagle_panel_enable_tv(struct omap_display *display)
+{
+#define ENABLE_VDAC_DEDICATED           0x03
+#define ENABLE_VDAC_DEV_GRP             0x20
+
+	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+			ENABLE_VDAC_DEDICATED,
+			TWL4030_VDAC_DEDICATED);
+	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+			ENABLE_VDAC_DEV_GRP, TWL4030_VDAC_DEV_GRP);
+
+	return 0;
+}
+
+static void beagle_panel_disable_tv(struct omap_display *display)
+{
+	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+			TWL4030_VDAC_DEDICATED);
+	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+			TWL4030_VDAC_DEV_GRP);
+}
+
+static struct omap_display_data beagle_display_data_tv = {
+	.type = OMAP_DISPLAY_TYPE_VENC,
+	.name = "tv",
+	.u.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
+	.panel_enable = beagle_panel_enable_tv,
+	.panel_disable = beagle_panel_disable_tv,
+};
+
+static struct omap_dss_platform_data beagle_dss_data = {
+	.num_displays = 2,
+	.displays = {
+		&beagle_display_data_dvi,
+		&beagle_display_data_tv,
+	}
+};
+
+static struct platform_device beagle_dss_device = {
+	.name          = "omap-dss",
+	.id            = -1,
+	.dev            = {
+		.platform_data = &beagle_dss_data,
+	},
+};
+
+static void __init beagle_display_init(void)
+{
+	int r;
+
+	r = gpio_request(beagle_display_data_dvi.panel_reset_gpio, "DVI reset");
+	if (r < 0)
+		printk(KERN_ERR "Unable to get DVI reset GPIO\n");
+}
+
 static struct omap_board_config_kernel omap3_beagle_config[] __initdata = {
 	{ OMAP_TAG_UART,	&omap3_beagle_uart_config },
-	{ OMAP_TAG_LCD,		&omap3_beagle_lcd_config },
 };
 
 static struct platform_device *omap3_beagle_devices[] __initdata = {
-	&omap3_beagle_lcd_device,
+	&beagle_dss_device,
 	&leds_gpio,
 	&keys_gpio,
 };
@@ -359,18 +433,17 @@ static void __init omap3_beagle_init(void)
 	omap_serial_init();
 
 	omap_cfg_reg(J25_34XX_GPIO170);
-	gpio_request(170, "DVI_nPD");
-	/* REVISIT leave DVI powered down until it's needed ... */
-	gpio_direction_output(170, true);
 
 	usb_musb_init();
 	usb_ehci_init();
 	omap3beagle_flash_init();
+	beagle_display_init();
 }
 
 static void __init omap3_beagle_map_io(void)
 {
 	omap2_set_globals_343x();
+	omap2_set_sdram_vram(1280 * 1024 * 4 * 3, 0);
 	omap2_map_common_io();
 }
 


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 09/12] DSS: Sharp LS037V7DW01 LCD Panel driver
  2009-01-12 11:47 [PATCH 00/12] DSS: Series description Tomi Valkeinen
                   ` (7 preceding siblings ...)
  2009-01-12 11:48 ` [PATCH 08/12] DSS: support for Beagle Board Tomi Valkeinen
@ 2009-01-12 11:48 ` Tomi Valkeinen
  2009-01-12 11:48 ` [PATCH 10/12] DSS: Support for OMAP3 SDP board Tomi Valkeinen
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 23+ messages in thread
From: Tomi Valkeinen @ 2009-01-12 11:48 UTC (permalink / raw)
  To: linux-fbdev-devel; +Cc: linux-omap

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
---

 drivers/video/omap2/Kconfig                   |    7 +-
 drivers/video/omap2/Makefile                  |    1 
 drivers/video/omap2/panel-sharp-ls037v7dw01.c |  109 +++++++++++++++++++++++++
 3 files changed, 116 insertions(+), 1 deletions(-)
 create mode 100644 drivers/video/omap2/panel-sharp-ls037v7dw01.c

diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
index be00882..b54c955 100644
--- a/drivers/video/omap2/Kconfig
+++ b/drivers/video/omap2/Kconfig
@@ -43,5 +43,10 @@ config PANEL_GENERIC
 	  Generic panel driver.
 	  Used for DVI output for Beagle and OMAP3 SDP.
 
-endmenu
+config PANEL_SHARP_LS037V7DW01
+        tristate "Sharp LS037V7DW01 LCD Panel"
+        depends on OMAP2_DSS
+        help
+          LCD Panel used in TI's SDP3430 and EVM boards
 
+endmenu
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
index f471a2b..fe6858e 100644
--- a/drivers/video/omap2/Makefile
+++ b/drivers/video/omap2/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_FB_OMAP2) += omapfb.o
 omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
 
 obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o
+obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
diff --git a/drivers/video/omap2/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/panel-sharp-ls037v7dw01.c
new file mode 100644
index 0000000..7d67b6d
--- /dev/null
+++ b/drivers/video/omap2/panel-sharp-ls037v7dw01.c
@@ -0,0 +1,109 @@
+/*
+ * LCD panel driver for Sharp LS037V7DW01
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+
+#include <mach/display.h>
+
+static int sharp_ls_panel_init(struct omap_display *display)
+{
+	return 0;
+}
+
+static void sharp_ls_panel_cleanup(struct omap_display *display)
+{
+}
+
+static int sharp_ls_panel_enable(struct omap_display *display)
+{
+	int r = 0;
+
+	if (display->hw_config.panel_enable)
+		r = display->hw_config.panel_enable(display);
+
+	return r;
+}
+
+static void sharp_ls_panel_disable(struct omap_display *display)
+{
+	if (display->hw_config.panel_disable)
+		display->hw_config.panel_disable(display);
+}
+
+static int sharp_ls_panel_suspend(struct omap_display *display)
+{
+	sharp_ls_panel_disable(display);
+	return 0;
+}
+
+static int sharp_ls_panel_resume(struct omap_display *display)
+{
+	return sharp_ls_panel_enable(display);
+}
+
+static struct omap_panel sharp_ls_panel = {
+	.owner		= THIS_MODULE,
+	.name		= "sharp-ls037v7dw01",
+	.init		= sharp_ls_panel_init,
+	.cleanup	= sharp_ls_panel_cleanup,
+	.enable		= sharp_ls_panel_enable,
+	.disable	= sharp_ls_panel_disable,
+	.suspend	= sharp_ls_panel_suspend,
+	.resume		= sharp_ls_panel_resume,
+	/*.set_mode	= sharp_ls_set_mode, */
+
+	.timings = {
+		.x_res = 480,
+		.y_res = 640,
+
+		.pixel_clock	= 19200,
+
+		.hsw		= 2,
+		.hfp		= 1,
+		.hbp		= 28,
+
+		.vsw		= 1,
+		.vfp		= 1,
+		.vbp		= 1,
+	},
+
+	.acb		= 0x28,
+
+	.config		= OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+		OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC,
+
+	.bpp = 16,
+};
+
+
+static int __init sharp_ls_panel_drv_init(void)
+{
+	omap_dss_register_panel(&sharp_ls_panel);
+	return 0;
+}
+
+static void __exit sharp_ls_panel_drv_exit(void)
+{
+	omap_dss_unregister_panel(&sharp_ls_panel);
+}
+
+module_init(sharp_ls_panel_drv_init);
+module_exit(sharp_ls_panel_drv_exit);
+MODULE_LICENSE("GPL");


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 10/12] DSS: Support for OMAP3 SDP board
  2009-01-12 11:47 [PATCH 00/12] DSS: Series description Tomi Valkeinen
                   ` (8 preceding siblings ...)
  2009-01-12 11:48 ` [PATCH 09/12] DSS: Sharp LS037V7DW01 LCD Panel driver Tomi Valkeinen
@ 2009-01-12 11:48 ` Tomi Valkeinen
  2009-01-13 11:15   ` David Brownell
  2009-01-12 11:48 ` [PATCH 11/12] DSS: Support for OMAP3 EVM board Tomi Valkeinen
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 23+ messages in thread
From: Tomi Valkeinen @ 2009-01-12 11:48 UTC (permalink / raw)
  To: linux-fbdev-devel; +Cc: linux-omap

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
---

 arch/arm/configs/dss_omap_3430sdp_defconfig | 1603 +++++++++++++++++++++++++++
 arch/arm/mach-omap2/board-3430sdp.c         |  215 +++-
 2 files changed, 1809 insertions(+), 9 deletions(-)
 create mode 100644 arch/arm/configs/dss_omap_3430sdp_defconfig

diff --git a/arch/arm/configs/dss_omap_3430sdp_defconfig b/arch/arm/configs/dss_omap_3430sdp_defconfig
new file mode 100644
index 0000000..42d7f5e
--- /dev/null
+++ b/arch/arm/configs/dss_omap_3430sdp_defconfig
@@ -0,0 +1,1603 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.28-omap1
+# Wed Jan  7 15:22:34 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+CONFIG_OMAP_SMARTREFLEX=y
+# CONFIG_OMAP_SMARTREFLEX_TESTING is not set
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_BOOT_TAG=y
+CONFIG_OMAP_BOOT_REASON=y
+# CONFIG_OMAP_COMPONENT_VERSION is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+CONFIG_OMAP_MUX=y
+CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_MUX_WARNINGS=y
+# CONFIG_OMAP_MCBSP is not set
+# CONFIG_OMAP_MMU_FWK is not set
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
+CONFIG_OMAP2_DSS=m
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+# CONFIG_OMAP2_DSS_DSI is not set
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP_LDP is not set
+CONFIG_MACH_OMAP_3430SDP=y
+# CONFIG_MACH_OMAP3EVM is not set
+# CONFIG_MACH_OMAP3_BEAGLE is not set
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+CONFIG_OMAP_TICK_GPTIMER=1
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/home/user/buildroot ip=192.168.0.2:192.168.0.1:192.168.0.1:255.255.255.0:tgt:eth0:off rw console=ttyS2,115200n8"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+# CONFIG_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_OMAP_NOR=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+CONFIG_MTD_ONENAND=y
+CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OMAP2=y
+# CONFIG_MTD_ONENAND_OTP is not set
+# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
+# CONFIG_MTD_ONENAND_SIM is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_OMAP_STI is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_SMC911X is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_TWL4030=y
+# CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
+# CONFIG_TOUCHSCREEN_TSC210X is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_MADC is not set
+# CONFIG_TWL4030_PWRBUTTON is not set
+# CONFIG_TWL4030_POWEROFF is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_LP5521 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_TSC210X is not set
+# CONFIG_SPI_TSC2301 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_POWER is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_OMAP_LCD_VGA is not set
+CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2
+CONFIG_FB_OMAP2=m
+CONFIG_FB_OMAP2_DEBUG=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=m
+CONFIG_PANEL_SHARP_LS037V7DW01=m
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_BRIGHT=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DELL=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=m
+CONFIG_OMAP_EHCI_PHY_MODE=y
+# CONFIG_OMAP_EHCI_TLL_MODE is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=y
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+# CONFIG_USB_ZERO_HNPTEST is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=m
+# CONFIG_MMC_SPI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index ade186b..529322f 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -39,6 +39,7 @@
 #include <mach/keypad.h>
 #include <mach/dma.h>
 #include <mach/gpmc.h>
+#include <mach/display.h>
 
 #include <asm/io.h>
 #include <asm/delay.h>
@@ -238,14 +239,214 @@ static struct spi_board_info sdp3430_spi_board_info[] __initdata = {
 	},
 };
 
-static struct platform_device sdp3430_lcd_device = {
-	.name		= "sdp2430_lcd",
-	.id		= -1,
+
+#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO	91
+#define SDP2430_LCD_PANEL_ENABLE_GPIO		154
+#if 0
+#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO	24
+#define SDP3430_LCD_PANEL_ENABLE_GPIO		28
+#else
+#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO	8
+#define SDP3430_LCD_PANEL_ENABLE_GPIO		5
+#endif
+
+#define PM_RECEIVER             TWL4030_MODULE_PM_RECEIVER
+#define ENABLE_VAUX2_DEDICATED  0x09
+#define ENABLE_VAUX2_DEV_GRP    0x20
+#define ENABLE_VAUX3_DEDICATED	0x03
+#define ENABLE_VAUX3_DEV_GRP	0x20
+
+#define ENABLE_VPLL2_DEDICATED	0x05
+#define ENABLE_VPLL2_DEV_GRP	0xE0
+#define TWL4030_VPLL2_DEV_GRP	0x33
+#define TWL4030_VPLL2_DEDICATED	0x36
+
+#define t2_out(c, r, v) twl4030_i2c_write_u8(c, r, v)
+
+static unsigned backlight_gpio;
+static unsigned enable_gpio;
+static int lcd_enabled;
+static int dvi_enabled;
+
+static void __init sdp3430_display_init(void)
+{
+	int r;
+
+	enable_gpio    = SDP3430_LCD_PANEL_ENABLE_GPIO;
+	backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO;
+
+	r = gpio_request(enable_gpio, "LCD reset");
+	if (r) {
+		printk(KERN_ERR "failed to get LCD reset GPIO\n");
+		goto err0;
+	}
+
+	r = gpio_request(backlight_gpio, "LCD Backlight");
+	if (r) {
+		printk(KERN_ERR "failed to get LCD backlight GPIO\n");
+		goto err1;
+	}
+
+	gpio_direction_output(enable_gpio, 0);
+	gpio_direction_output(backlight_gpio, 0);
+
+	return;
+err1:
+	gpio_free(enable_gpio);
+err0:
+	return;
+}
+
+
+static int sdp3430_panel_enable_lcd(struct omap_display *display)
+{
+	u8 ded_val, ded_reg;
+	u8 grp_val, grp_reg;
+
+	if (dvi_enabled) {
+		printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
+		return -EINVAL;
+	}
+
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED,
+				TWL4030_VPLL2_DEDICATED);
+		t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP,
+				TWL4030_VPLL2_DEV_GRP);
+	}
+
+	ded_reg = TWL4030_VAUX3_DEDICATED;
+	ded_val = ENABLE_VAUX3_DEDICATED;
+	grp_reg = TWL4030_VAUX3_DEV_GRP;
+	grp_val = ENABLE_VAUX3_DEV_GRP;
+
+	gpio_direction_output(enable_gpio, 1);
+	gpio_direction_output(backlight_gpio, 1);
+
+	if (0 != t2_out(PM_RECEIVER, ded_val, ded_reg))
+		return -EIO;
+	if (0 != t2_out(PM_RECEIVER, grp_val, grp_reg))
+		return -EIO;
+
+	lcd_enabled = 1;
+
+	return 0;
+}
+
+static void sdp3430_panel_disable_lcd(struct omap_display *display)
+{
+	lcd_enabled = 0;
+
+	gpio_direction_output(enable_gpio, 0);
+	gpio_direction_output(backlight_gpio, 0);
+
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED);
+		t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP);
+		mdelay(4);
+	}
+}
+
+static struct omap_display_data sdp3430_display_data = {
+	.type = OMAP_DISPLAY_TYPE_DPI,
+	.name = "lcd",
+	.panel_name = "sharp-ls037v7dw01",
+	.u.dpi.data_lines = 16,
+	.panel_enable = sdp3430_panel_enable_lcd,
+	.panel_disable = sdp3430_panel_disable_lcd,
+};
+
+static int sdp3430_panel_enable_dvi(struct omap_display *display)
+{
+	if (lcd_enabled) {
+		printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
+		return -EINVAL;
+	}
+
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED,
+				TWL4030_VPLL2_DEDICATED);
+		t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP,
+				TWL4030_VPLL2_DEV_GRP);
+	}
+
+	dvi_enabled = 1;
+
+	return 0;
+}
+
+static void sdp3430_panel_disable_dvi(struct omap_display *display)
+{
+	dvi_enabled = 0;
+
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED);
+		t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP);
+		mdelay(4);
+	}
+}
+
+
+static struct omap_display_data sdp3430_display_data_dvi = {
+	.type = OMAP_DISPLAY_TYPE_DPI,
+	.name = "dvi",
+	.panel_name = "panel-generic",
+	.u.dpi.data_lines = 24,
+	.panel_enable = sdp3430_panel_enable_dvi,
+	.panel_disable = sdp3430_panel_disable_dvi,
 };
 
+static int sdp3430_panel_enable_tv(struct omap_display *display)
+{
+#define ENABLE_VDAC_DEDICATED           0x03
+#define ENABLE_VDAC_DEV_GRP             0x20
+
+	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+			ENABLE_VDAC_DEDICATED,
+			TWL4030_VDAC_DEDICATED);
+	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+			ENABLE_VDAC_DEV_GRP, TWL4030_VDAC_DEV_GRP);
+
+	return 0;
+}
+
+static void sdp3430_panel_disable_tv(struct omap_display *display)
+{
+	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+			TWL4030_VDAC_DEDICATED);
+	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+			TWL4030_VDAC_DEV_GRP);
+}
+
+static struct omap_display_data sdp3430_display_data_tv = {
+	.type = OMAP_DISPLAY_TYPE_VENC,
+	.name = "tv",
+	.u.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
+	.panel_enable = sdp3430_panel_enable_tv,
+	.panel_disable = sdp3430_panel_disable_tv,
+};
+
+static struct omap_dss_platform_data sdp3430_dss_data = {
+	.num_displays = 3,
+	.displays = {
+		&sdp3430_display_data,
+		&sdp3430_display_data_dvi,
+		&sdp3430_display_data_tv,
+	}
+};
+
+static struct platform_device sdp3430_dss_device = {
+	.name          = "omap-dss",
+	.id            = -1,
+	.dev            = {
+		.platform_data = &sdp3430_dss_data,
+	},
+};
+
+
 static struct platform_device *sdp3430_devices[] __initdata = {
 	&sdp3430_smc91x_device,
-	&sdp3430_lcd_device,
+	&sdp3430_dss_device,
 };
 
 static inline void __init sdp3430_init_smc91x(void)
@@ -292,13 +493,8 @@ static struct omap_uart_config sdp3430_uart_config __initdata = {
 	.enabled_uarts	= ((1 << 0) | (1 << 1) | (1 << 2)),
 };
 
-static struct omap_lcd_config sdp3430_lcd_config __initdata = {
-	.ctrl_name	= "internal",
-};
-
 static struct omap_board_config_kernel sdp3430_config[] __initdata = {
 	{ OMAP_TAG_UART,	&sdp3430_uart_config },
-	{ OMAP_TAG_LCD,		&sdp3430_lcd_config },
 };
 
 static int sdp3430_batt_table[] = {
@@ -481,6 +677,7 @@ static void __init omap_3430sdp_init(void)
 	usb_musb_init();
 	usb_ehci_init();
 	twl4030_mmc_init(mmc);
+	sdp3430_display_init();
 }
 
 static void __init omap_3430sdp_map_io(void)


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 11/12] DSS: Support for OMAP3 EVM board
  2009-01-12 11:47 [PATCH 00/12] DSS: Series description Tomi Valkeinen
                   ` (9 preceding siblings ...)
  2009-01-12 11:48 ` [PATCH 10/12] DSS: Support for OMAP3 SDP board Tomi Valkeinen
@ 2009-01-12 11:48 ` Tomi Valkeinen
  2009-01-12 11:48 ` [PATCH 12/12] DSS: Hacked N810 support Tomi Valkeinen
  2009-01-12 13:44 ` [PATCH 00/12] DSS: Series description Koen Kooi
  12 siblings, 0 replies; 23+ messages in thread
From: Tomi Valkeinen @ 2009-01-12 11:48 UTC (permalink / raw)
  To: linux-fbdev-devel; +Cc: linux-omap

Coded by Vaibhav Hiremath <hvaibhav@ti.com>

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
---

 arch/arm/mach-omap2/board-omap3evm.c |  203 +++++++++++++++++++++++++++++++++-
 1 files changed, 196 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index e4e60e2..e7ec9e6 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -36,6 +36,7 @@
 #include <mach/usb-ehci.h>
 #include <mach/common.h>
 #include <mach/mcspi.h>
+#include <mach/display.h>
 
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "twl4030-generic-scripts.h"
@@ -160,13 +161,201 @@ static int __init omap3_evm_i2c_init(void)
 	return 0;
 }
 
-static struct platform_device omap3_evm_lcd_device = {
-	.name		= "omap3evm_lcd",
-	.id		= -1,
+#define LCD_PANEL_LR		2
+#define LCD_PANEL_UD		3
+#define LCD_PANEL_INI		152
+#define LCD_PANEL_ENABLE_GPIO	153
+#define LCD_PANEL_QVGA		154
+#define LCD_PANEL_RESB		155
+
+#define ENABLE_VDAC_DEDICATED	0x03
+#define ENABLE_VDAC_DEV_GRP	0x20
+#define ENABLE_VPLL2_DEDICATED	0x05
+#define ENABLE_VPLL2_DEV_GRP	0xE0
+
+#define TWL4030_GPIODATA_IN3	0x03
+#define TWL4030_GPIODATA_DIR3	0x06
+#define TWL4030_VPLL2_DEV_GRP	0x33
+#define TWL4030_VPLL2_DEDICATED	0x36
+
+static int lcd_enabled;
+static int dvi_enabled;
+
+static void __init omap3_evm_display_init(void)
+{
+	int r;
+	r = gpio_request(LCD_PANEL_LR, "lcd_panel_lr");
+	if (r) {
+		printk(KERN_ERR "failed to get LCD_PANEL_LR\n");
+		return;
+	}
+	r = gpio_request(LCD_PANEL_UD, "lcd_panel_ud");
+	if (r) {
+		printk(KERN_ERR "failed to get LCD_PANEL_UD\n");
+		goto err_1;
+	}
+
+	r = gpio_request(LCD_PANEL_INI, "lcd_panel_ini");
+	if (r) {
+		printk(KERN_ERR "failed to get LCD_PANEL_INI\n");
+		goto err_2;
+	}
+	r = gpio_request(LCD_PANEL_RESB, "lcd_panel_resb");
+	if (r) {
+		printk(KERN_ERR "failed to get LCD_PANEL_RESB\n");
+		goto err_3;
+	}
+	r = gpio_request(LCD_PANEL_QVGA, "lcd_panel_qvga");
+	if (r) {
+		printk(KERN_ERR "failed to get LCD_PANEL_QVGA\n");
+		goto err_4;
+	}
+
+	gpio_direction_output(LCD_PANEL_LR, 0);
+	gpio_direction_output(LCD_PANEL_UD, 0);
+	gpio_direction_output(LCD_PANEL_INI, 0);
+	gpio_direction_output(LCD_PANEL_RESB, 0);
+	gpio_direction_output(LCD_PANEL_QVGA, 0);
+
+#define TWL_LED_LEDEN           0x00
+#define TWL_PWMA_PWMAON         0x00
+#define TWL_PWMA_PWMAOFF        0x01
+
+	twl4030_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
+	twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
+	twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
+
+	gpio_direction_output(LCD_PANEL_RESB, 1);
+	gpio_direction_output(LCD_PANEL_INI, 1);
+	gpio_direction_output(LCD_PANEL_QVGA, 0);
+	gpio_direction_output(LCD_PANEL_LR, 1);
+	gpio_direction_output(LCD_PANEL_UD, 1);
+
+	return;
+
+err_4:
+	gpio_free(LCD_PANEL_RESB);
+err_3:
+	gpio_free(LCD_PANEL_INI);
+err_2:
+	gpio_free(LCD_PANEL_UD);
+err_1:
+	gpio_free(LCD_PANEL_LR);
+
+}
+
+static int omap3_evm_panel_enable_lcd(struct omap_display *display)
+{
+	if (dvi_enabled) {
+		printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
+		return -EINVAL;
+	}
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+			ENABLE_VPLL2_DEDICATED, TWL4030_VPLL2_DEDICATED);
+		twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+			ENABLE_VPLL2_DEV_GRP, TWL4030_VPLL2_DEV_GRP);
+	}
+	gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0);
+	lcd_enabled = 1;
+	return 0;
+}
+
+static void omap3_evm_panel_disable_lcd(struct omap_display *display)
+{
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
+				TWL4030_VPLL2_DEDICATED);
+		twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
+				TWL4030_VPLL2_DEV_GRP);
+	}
+	gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 1);
+	lcd_enabled = 0;
+}
+
+static struct omap_display_data omap3_evm_display_data = {
+	.type = OMAP_DISPLAY_TYPE_DPI,
+	.name = "lcd",
+	.panel_name = "sharp-ls037v7dw01",
+	.u.dpi.data_lines = 18,
+	.panel_enable = omap3_evm_panel_enable_lcd,
+	.panel_disable = omap3_evm_panel_disable_lcd,
 };
 
-static struct omap_lcd_config omap3_evm_lcd_config __initdata = {
-	.ctrl_name	= "internal",
+static int omap3_evm_panel_enable_tv(struct omap_display *display)
+{
+	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+			ENABLE_VDAC_DEDICATED, TWL4030_VDAC_DEDICATED);
+	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+			ENABLE_VDAC_DEV_GRP, TWL4030_VDAC_DEV_GRP);
+	return 0;
+}
+
+static void omap3_evm_panel_disable_tv(struct omap_display *display)
+{
+	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+			TWL4030_VDAC_DEDICATED);
+	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+			TWL4030_VDAC_DEV_GRP);
+}
+
+static struct omap_display_data omap3_evm_display_data_tv = {
+	.type = OMAP_DISPLAY_TYPE_VENC,
+	.name = "tv",
+	.u.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
+	.panel_enable = omap3_evm_panel_enable_tv,
+	.panel_disable = omap3_evm_panel_disable_tv,
+};
+
+
+static int omap3_evm_panel_enable_dvi(struct omap_display *display)
+{
+	if (lcd_enabled) {
+		printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
+		return -EINVAL;
+	}
+	twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x80,
+			TWL4030_GPIODATA_IN3);
+	twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x80,
+			TWL4030_GPIODATA_DIR3);
+	dvi_enabled = 1;
+
+	return 0;
+}
+
+static void omap3_evm_panel_disable_dvi(struct omap_display *display)
+{
+	twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x00,
+			TWL4030_GPIODATA_IN3);
+	twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x00,
+			TWL4030_GPIODATA_DIR3);
+	dvi_enabled = 0;
+}
+
+
+static struct omap_display_data omap3_evm_display_data_dvi = {
+	.type = OMAP_DISPLAY_TYPE_DPI,
+	.name = "dvi",
+	.panel_name = "panel-generic",
+	.u.dpi.data_lines = 24,
+	.panel_enable = omap3_evm_panel_enable_dvi,
+	.panel_disable = omap3_evm_panel_disable_dvi,
+};
+
+static struct omap_dss_platform_data omap3_evm_dss_data = {
+	.num_displays = 3,
+	.displays = {
+		&omap3_evm_display_data,
+		&omap3_evm_display_data_dvi,
+		&omap3_evm_display_data_tv,
+	}
+};
+static struct platform_device omap3_evm_dss_device = {
+	.name		= "omap-dss",
+	.id		= -1,
+	.dev            = {
+		.platform_data = &omap3_evm_dss_data,
+	},
 };
 
 static void ads7846_dev_init(void)
@@ -225,11 +414,10 @@ static void __init omap3_evm_init_irq(void)
 
 static struct omap_board_config_kernel omap3_evm_config[] __initdata = {
 	{ OMAP_TAG_UART,	&omap3_evm_uart_config },
-	{ OMAP_TAG_LCD,		&omap3_evm_lcd_config },
 };
 
 static struct platform_device *omap3_evm_devices[] __initdata = {
-	&omap3_evm_lcd_device,
+	&omap3_evm_dss_device,
 	&omap3evm_smc911x_device,
 };
 
@@ -260,6 +448,7 @@ static void __init omap3_evm_init(void)
 	usb_ehci_init();
 	omap3evm_flash_init();
 	ads7846_dev_init();
+	omap3_evm_display_init();
 }
 
 static void __init omap3_evm_map_io(void)


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 12/12] DSS: Hacked N810 support
  2009-01-12 11:47 [PATCH 00/12] DSS: Series description Tomi Valkeinen
                   ` (10 preceding siblings ...)
  2009-01-12 11:48 ` [PATCH 11/12] DSS: Support for OMAP3 EVM board Tomi Valkeinen
@ 2009-01-12 11:48 ` Tomi Valkeinen
  2009-01-12 13:44 ` [PATCH 00/12] DSS: Series description Koen Kooi
  12 siblings, 0 replies; 23+ messages in thread
From: Tomi Valkeinen @ 2009-01-12 11:48 UTC (permalink / raw)
  To: linux-fbdev-devel; +Cc: linux-omap

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
---

 arch/arm/mach-omap2/board-n800.c    |  214 ++++++++++++++---
 drivers/video/omap2/Kconfig         |   10 +
 drivers/video/omap2/Makefile        |    3 
 drivers/video/omap2/ctrl-blizzard.c |  279 ++++++++++++++++++++++
 drivers/video/omap2/panel-n800.c    |  437 +++++++++++++++++++++++++++++++++++
 5 files changed, 905 insertions(+), 38 deletions(-)
 create mode 100644 drivers/video/omap2/ctrl-blizzard.c
 create mode 100644 drivers/video/omap2/panel-n800.c

diff --git a/arch/arm/mach-omap2/board-n800.c b/arch/arm/mach-omap2/board-n800.c
index b38b295..ffa5aad 100644
--- a/arch/arm/mach-omap2/board-n800.c
+++ b/arch/arm/mach-omap2/board-n800.c
@@ -40,6 +40,7 @@
 #include <mach/gpio-switch.h>
 #include <mach/omapfb.h>
 #include <mach/blizzard.h>
+#include <mach/display.h>
 
 #include <../drivers/cbus/tahvo.h>
 #include <../drivers/media/video/tcm825x.h>
@@ -156,23 +157,175 @@ static struct omap_uart_config n800_uart_config __initdata = {
 
 #include "../../../drivers/cbus/retu.h"
 
-static struct omap_fbmem_config n800_fbmem0_config __initdata = {
-	.size = 752 * 1024,
+static struct omap_tmp105_config n800_tmp105_config __initdata = {
+	.tmp105_irq_pin = 125,
+	.set_power = n800_tmp105_set_power,
 };
 
-static struct omap_fbmem_config n800_fbmem1_config __initdata = {
-	.size = 752 * 1024,
-};
 
-static struct omap_fbmem_config n800_fbmem2_config __initdata = {
-	.size = 752 * 1024,
+
+
+/* DISPLAY */
+static struct {
+	struct clk *sys_ck;
+} blizzard;
+
+static int blizzard_get_clocks(void)
+{
+	blizzard.sys_ck = clk_get(0, "osc_ck");
+	if (IS_ERR(blizzard.sys_ck)) {
+		printk(KERN_ERR "can't get Blizzard clock\n");
+		return PTR_ERR(blizzard.sys_ck);
+	}
+	return 0;
+}
+
+static unsigned long blizzard_get_clock_rate(void)
+{
+	return clk_get_rate(blizzard.sys_ck);
+}
+
+static int n800_pn800_enable(struct omap_display *display)
+{
+	if (display->hw_config.panel_reset_gpio != -1) {
+		printk("enabling panel gpio\n");
+		gpio_direction_output(display->hw_config.panel_reset_gpio, 1);
+	}
+
+	return 0;
+}
+
+static void n800_pn800_disable(struct omap_display *display)
+{
+	if (display->hw_config.panel_reset_gpio != -1) {
+		printk("disabling panel gpio\n");
+		gpio_direction_output(display->hw_config.panel_reset_gpio, 0);
+		msleep(120);
+	}
+}
+
+static int n800_blizzard_enable(struct omap_display *display)
+{
+	printk("enabling bliz powers\n");
+
+	/* Vcore to 1.475V */
+	tahvo_set_clear_reg_bits(0x07, 0, 0xf);
+	msleep(10);
+
+	clk_enable(blizzard.sys_ck);
+
+	if (display->hw_config.ctrl_reset_gpio != -1)
+		gpio_direction_output(display->hw_config.ctrl_reset_gpio, 1);
+
+	printk("osc_ck %lu\n", blizzard_get_clock_rate());
+
+	return 0;
+}
+
+static void n800_blizzard_disable(struct omap_display *display)
+{
+	printk("disabling bliz powers\n");
+
+	if (display->hw_config.ctrl_reset_gpio != -1)
+		gpio_direction_output(display->hw_config.ctrl_reset_gpio, 0);
+
+	clk_disable(blizzard.sys_ck);
+
+	/* Vcore to 1.005V */
+	tahvo_set_clear_reg_bits(0x07, 0xf, 0);
+}
+
+static int n800_set_backlight_level(struct omap_display *display, int level)
+{
+	return 0;
+}
+
+static struct omap_display_data n800_dsi_display_data = {
+	.type = OMAP_DISPLAY_TYPE_DBI,
+	.name = "lcd",
+	.ctrl_name = "ctrl-blizzard",
+	.panel_name = "panel-pn800",
+	.panel_reset_gpio = -1,
+	.ctrl_reset_gpio = N800_BLIZZARD_POWERDOWN_GPIO,
+	.panel_enable = n800_pn800_enable,
+	.panel_disable = n800_pn800_disable,
+	.ctrl_enable = n800_blizzard_enable,
+	.ctrl_disable = n800_blizzard_disable,
+	.set_backlight = n800_set_backlight_level,
+	.u.rfbi = {
+		.channel = 0,
+		/* 8 for cmd mode, 16 for pixel data. ctrl-blizzard handles switching */
+		.data_lines = 8,
+	},
+	.priv = 0, // XXX used for panel datalines
+};
+static struct omap_dss_platform_data n800_dss_data = {
+	.num_displays = 1,
+	.displays = {
+		&n800_dsi_display_data,
+	},
 };
 
-static struct omap_tmp105_config n800_tmp105_config __initdata = {
-	.tmp105_irq_pin = 125,
-	.set_power = n800_tmp105_set_power,
+static struct platform_device n800_dss_device = {
+	.name          = "omap-dss",
+	.id            = -1,
+	.dev            = {
+		.platform_data = &n800_dss_data,
+	},
 };
 
+static void __init n800_display_init(void)
+{
+	int r;
+	const struct omap_lcd_config *conf;
+
+	conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
+	if (conf != NULL) {
+		n800_dsi_display_data.panel_reset_gpio = conf->nreset_gpio;
+		n800_dsi_display_data.priv = (void*)(u32)conf->data_lines; // XXX
+		//printk("\n\nTULI %d\n\n", conf->data_lines);
+	} else {
+		printk("\n\nEI TULLU MIOTÄÄÄ\n\n");
+	}
+
+	blizzard_get_clocks();
+	clk_enable(blizzard.sys_ck); // XXX always enable
+
+	//omapfb_set_ctrl_platform_data(&n800_blizzard_data);
+	//
+	if (n800_dsi_display_data.ctrl_reset_gpio != -1) {
+		r = gpio_request(n800_dsi_display_data.ctrl_reset_gpio,
+				"Blizzard pd");
+		if (r < 0) {
+			n800_dsi_display_data.ctrl_reset_gpio = -1;
+			printk(KERN_ERR "Unable to get Blizzard GPIO\n");
+		} else {
+			gpio_direction_output(n800_dsi_display_data.ctrl_reset_gpio,
+					1);
+			// XXX always enable
+		}
+	}
+
+	if (n800_dsi_display_data.panel_reset_gpio != -1) {
+		r = gpio_request(n800_dsi_display_data.panel_reset_gpio,
+				"panel reset");
+		if (r < 0) {
+			n800_dsi_display_data.panel_reset_gpio = -1;
+			printk(KERN_ERR "Unable to get pn800 GPIO\n");
+		} else {
+			gpio_direction_output(n800_dsi_display_data.panel_reset_gpio,
+					1);
+			// XXX always enable
+		}
+	}
+}
+
+/* DISPLAY END */
+
+
+
+
+
 static void mipid_shutdown(struct mipid_platform_data *pdata)
 {
 	if (pdata->nreset_gpio != -1) {
@@ -186,6 +339,7 @@ static struct mipid_platform_data n800_mipid_platform_data = {
 	.shutdown = mipid_shutdown,
 };
 
+#if 0
 static void __init mipid_dev_init(void)
 {
 	const struct omap_lcd_config *conf;
@@ -196,26 +350,9 @@ static void __init mipid_dev_init(void)
 		n800_mipid_platform_data.data_lines = conf->data_lines;
 	}
 }
+#endif
 
-static struct {
-	struct clk *sys_ck;
-} blizzard;
-
-static int blizzard_get_clocks(void)
-{
-	blizzard.sys_ck = clk_get(0, "osc_ck");
-	if (IS_ERR(blizzard.sys_ck)) {
-		printk(KERN_ERR "can't get Blizzard clock\n");
-		return PTR_ERR(blizzard.sys_ck);
-	}
-	return 0;
-}
-
-static unsigned long blizzard_get_clock_rate(struct device *dev)
-{
-	return clk_get_rate(blizzard.sys_ck);
-}
-
+#if 0
 static void blizzard_enable_clocks(int enable)
 {
 	if (enable)
@@ -260,14 +397,12 @@ static void __init blizzard_dev_init(void)
 	gpio_direction_output(N800_BLIZZARD_POWERDOWN_GPIO, 1);
 
 	blizzard_get_clocks();
-	omapfb_set_ctrl_platform_data(&n800_blizzard_data);
+	//omapfb_set_ctrl_platform_data(&n800_blizzard_data);
 }
+#endif
 
 static struct omap_board_config_kernel n800_config[] __initdata = {
 	{ OMAP_TAG_UART,	                &n800_uart_config },
-	{ OMAP_TAG_FBMEM,			&n800_fbmem0_config },
-	{ OMAP_TAG_FBMEM,			&n800_fbmem1_config },
-	{ OMAP_TAG_FBMEM,			&n800_fbmem2_config },
 	{ OMAP_TAG_TMP105,			&n800_tmp105_config },
 };
 
@@ -374,7 +509,7 @@ static struct omap2_mcspi_device_config tsc2005_mcspi_config = {
 
 static struct spi_board_info n800_spi_board_info[] __initdata = {
 	{
-		.modalias	= "lcd_mipid",
+		.modalias	= "panel-n800",
 		.bus_num	= 1,
 		.chip_select	= 1,
 		.max_speed_hz	= 4000000,
@@ -399,7 +534,7 @@ static struct spi_board_info n800_spi_board_info[] __initdata = {
 
 static struct spi_board_info n810_spi_board_info[] __initdata = {
 	{
-		.modalias	 = "lcd_mipid",
+		.modalias	 = "panel-n800",
 		.bus_num	 = 1,
 		.chip_select	 = 1,
 		.max_speed_hz	 = 4000000,
@@ -567,6 +702,7 @@ static struct platform_device *n800_devices[] __initdata = {
 #if defined(CONFIG_CBUS_RETU) && defined(CONFIG_LEDS_OMAP_PWM)
 	&n800_keypad_led_device,
 #endif
+	&n800_dss_device,
 };
 
 #ifdef CONFIG_MENELAUS
@@ -689,9 +825,10 @@ void __init nokia_n800_common_init(void)
 	if (machine_is_nokia_n810())
 		i2c_register_board_info(2, n810_i2c_board_info_2,
 			ARRAY_SIZE(n810_i2c_board_info_2));
-		
-	mipid_dev_init();
-	blizzard_dev_init();
+
+	//mipid_dev_init();
+	//blizzard_dev_init();
+	n800_display_init();
 }
 
 static void __init nokia_n800_init(void)
@@ -712,6 +849,7 @@ void __init nokia_n800_map_io(void)
 	omap_board_config_size = ARRAY_SIZE(n800_config);
 
 	omap2_set_globals_242x();
+	omap2_set_sdram_vram(800 * 480 * 2 * 3, 0);
 	omap2_map_common_io();
 }
 
diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
index b54c955..4e9211e 100644
--- a/drivers/video/omap2/Kconfig
+++ b/drivers/video/omap2/Kconfig
@@ -49,4 +49,14 @@ config PANEL_SHARP_LS037V7DW01
         help
           LCD Panel used in TI's SDP3430 and EVM boards
 
+config PANEL_N800
+        tristate "panel n800"
+        help
+          N800 LCD
+
+config CTRL_BLIZZARD
+        tristate "blizzard ctrl"
+        help
+          Blizzard Ctrl
+
 endmenu
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
index fe6858e..7727f9c 100644
--- a/drivers/video/omap2/Makefile
+++ b/drivers/video/omap2/Makefile
@@ -3,3 +3,6 @@ omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
 
 obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o
 obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
+
+obj-$(CONFIG_CTRL_BLIZZARD) += ctrl-blizzard.o
+obj-$(CONFIG_PANEL_N800) += panel-n800.o
diff --git a/drivers/video/omap2/ctrl-blizzard.c b/drivers/video/omap2/ctrl-blizzard.c
new file mode 100644
index 0000000..e1e5569
--- /dev/null
+++ b/drivers/video/omap2/ctrl-blizzard.c
@@ -0,0 +1,279 @@
+
+//#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+#include <mach/display.h>
+#include <mach/dma.h>
+
+#ifdef DEBUG
+#define DBG(format, ...) printk(KERN_DEBUG "Blizzard: " format, ## __VA_ARGS__)
+#else
+#define DBG(format, ...)
+#endif
+
+#define BLIZZARD_REV_CODE			0x00
+#define BLIZZARD_CONFIG				0x02
+#define BLIZZARD_PLL_DIV			0x04
+#define BLIZZARD_PLL_LOCK_RANGE			0x06
+#define BLIZZARD_PLL_CLOCK_SYNTH_0		0x08
+#define BLIZZARD_PLL_CLOCK_SYNTH_1		0x0a
+#define BLIZZARD_PLL_MODE			0x0c
+#define BLIZZARD_CLK_SRC			0x0e
+#define BLIZZARD_MEM_BANK0_ACTIVATE		0x10
+#define BLIZZARD_MEM_BANK0_STATUS		0x14
+#define BLIZZARD_PANEL_CONFIGURATION		0x28
+#define BLIZZARD_HDISP				0x2a
+#define BLIZZARD_HNDP				0x2c
+#define BLIZZARD_VDISP0				0x2e
+#define BLIZZARD_VDISP1				0x30
+#define BLIZZARD_VNDP				0x32
+#define BLIZZARD_HSW				0x34
+#define BLIZZARD_VSW				0x38
+#define BLIZZARD_DISPLAY_MODE			0x68
+#define BLIZZARD_INPUT_WIN_X_START_0		0x6c
+#define BLIZZARD_DATA_SOURCE_SELECT		0x8e
+#define BLIZZARD_DISP_MEM_DATA_PORT		0x90
+#define BLIZZARD_DISP_MEM_READ_ADDR0		0x92
+#define BLIZZARD_POWER_SAVE			0xE6
+#define BLIZZARD_NDISP_CTRL_STATUS		0xE8
+
+/* Data source select */
+/* For S1D13745 */
+#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND	0x00
+#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE	0x01
+#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE	0x04
+#define BLIZZARD_SRC_DISABLE_OVERLAY		0x05
+/* For S1D13744 */
+#define BLIZZARD_SRC_WRITE_LCD			0x00
+#define BLIZZARD_SRC_BLT_LCD			0x06
+
+#define BLIZZARD_COLOR_RGB565			0x01
+#define BLIZZARD_COLOR_YUV420			0x09
+
+#define BLIZZARD_VERSION_S1D13745		0x01	/* Hailstorm */
+#define BLIZZARD_VERSION_S1D13744		0x02	/* Blizzard */
+
+#define BLIZZARD_AUTO_UPDATE_TIME		(HZ / 20)
+
+
+
+static struct {
+	int			version;
+} blizzard;
+
+
+static inline void blizzard_cmd(u8 cmd)
+{
+        omap_rfbi_write_command(&cmd, 1);
+}
+
+static inline void blizzard_write(u8 cmd, const u8 *buf, int len)
+{
+        omap_rfbi_write_command(&cmd, 1);
+        omap_rfbi_write_data(buf, len);
+}
+
+static inline void blizzard_read(u8 cmd, u8 *buf, int len)
+{
+        omap_rfbi_write_command(&cmd, 1);
+        omap_rfbi_read_data(buf, len);
+}
+
+static u8 blizzard_read_reg(u8 cmd)
+{
+	u8 data;
+	blizzard_read(cmd, &data, 1);
+	return data;
+}
+
+static int blizzard_ctrl_init(struct omap_display *display)
+{
+	DBG("blizzard_ctrl_init\n");
+
+	return 0;
+}
+
+
+static int blizzard_ctrl_enable(struct omap_display *display)
+{
+	int r = 0;
+	u8 rev, conf;
+
+	DBG("blizzard_ctrl_enable\n");
+
+	if (display->hw_config.ctrl_enable) {
+		r = display->hw_config.ctrl_enable(display);
+		if (r)
+			return r;
+	}
+
+	msleep(100);
+
+	rev = blizzard_read_reg(BLIZZARD_CLK_SRC);
+	printk("CLK_SRC %x\n", rev);
+
+	rev = blizzard_read_reg(BLIZZARD_PLL_DIV);
+	printk("PLLDIV %x\n", rev);
+
+	rev = blizzard_read_reg(BLIZZARD_REV_CODE);
+	conf = blizzard_read_reg(BLIZZARD_CONFIG);
+
+	printk("rev %x, conf %x\n", rev, conf);
+
+	switch (rev & 0xfc) {
+	case 0x9c:
+		blizzard.version = BLIZZARD_VERSION_S1D13744;
+		pr_info("omapfb: s1d13744 LCD controller rev %d "
+			"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+		break;
+	case 0xa4:
+		blizzard.version = BLIZZARD_VERSION_S1D13745;
+		pr_info("omapfb: s1d13745 LCD controller rev %d "
+			"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+		break;
+	default:
+		printk("invalid s1d1374x revision %02x\n",
+			rev);
+		r = -ENODEV;
+	}
+
+	return r;
+}
+
+static void blizzard_ctrl_disable(struct omap_display *display)
+{
+	DBG("blizzard_ctrl_disable\n");
+
+	if (display->hw_config.ctrl_disable)
+		display->hw_config.ctrl_disable(display);
+}
+
+int rfbi_configure(int rfbi_module, int bpp, int lines);
+
+static void blizzard_ctrl_setup_update(struct omap_display *display,
+				    int x, int y, int w, int h)
+{
+	u8 tmp[18];
+	int x_end, y_end;
+
+	DBG("blizzard_ctrl_setup_update\n");
+
+	x_end = x + w - 1;
+	y_end = y + h - 1;
+
+	tmp[0] = x;
+	tmp[1] = x >> 8;
+	tmp[2] = y;
+	tmp[3] = y >> 8;
+	tmp[4] = x_end;
+	tmp[5] = x_end >> 8;
+	tmp[6] = y_end;
+	tmp[7] = y_end >> 8;
+
+	/* scaling? */
+	tmp[8] = x;
+	tmp[9] = x >> 8;
+	tmp[10] = y;
+	tmp[11] = y >> 8;
+	tmp[12] = x_end;
+	tmp[13] = x_end >> 8;
+	tmp[14] = y_end;
+	tmp[15] = y_end >> 8;
+
+	tmp[16] = BLIZZARD_COLOR_RGB565; //color_mode;
+
+	if (blizzard.version == BLIZZARD_VERSION_S1D13745)
+		tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
+	else
+		tmp[17] = blizzard.version == BLIZZARD_VERSION_S1D13744 ?
+				BLIZZARD_SRC_WRITE_LCD :
+				BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
+
+	rfbi_configure(display->hw_config.u.rfbi.channel,
+		       16,
+		       8);
+
+	blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
+
+	rfbi_configure(display->hw_config.u.rfbi.channel,
+		       16,
+		       16);
+}
+
+static int blizzard_ctrl_enable_te(struct omap_display *display, int enable)
+{
+	return 0;
+}
+
+static int blizzard_ctrl_rotate(struct omap_display *display, int rotate)
+{
+	return 0;
+}
+
+static int blizzard_ctrl_mirror(struct omap_display *display, int enable)
+{
+	return 0;
+}
+
+static int blizzard_run_test(struct omap_display *display, int test_num)
+{
+	return 0;
+}
+
+static struct omap_ctrl blizzard_ctrl = {
+	.owner = THIS_MODULE,
+	.name = "ctrl-blizzard",
+	.init = blizzard_ctrl_init,
+	.enable = blizzard_ctrl_enable,
+	.disable = blizzard_ctrl_disable,
+	.setup_update = blizzard_ctrl_setup_update,
+	.enable_te = blizzard_ctrl_enable_te,
+	.rotate = blizzard_ctrl_rotate,
+	.mirror = blizzard_ctrl_mirror,
+	.run_test = blizzard_run_test,
+	.pixel_size = 16,
+
+	.timings = {
+                .cs_on_time     = 0,
+
+                .we_on_time     = 9000,
+                .we_off_time    = 18000,
+                .we_cycle_time  = 36000,
+
+                .re_on_time     = 9000,
+                .re_off_time    = 27000,
+                .re_cycle_time  = 36000,
+
+                .access_time    = 27000,
+                .cs_off_time    = 36000,
+
+                .cs_pulse_width = 0,
+        },
+};
+
+
+static int __init blizzard_init(void)
+{
+	DBG("blizzard_init\n");
+	omap_dss_register_ctrl(&blizzard_ctrl);
+	return 0;
+}
+
+static void __exit blizzard_exit(void)
+{
+	DBG("blizzard_exit\n");
+
+	omap_dss_unregister_ctrl(&blizzard_ctrl);
+}
+
+module_init(blizzard_init);
+module_exit(blizzard_exit);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
+MODULE_DESCRIPTION("Blizzard Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/panel-n800.c b/drivers/video/omap2/panel-n800.c
new file mode 100644
index 0000000..3ae0a16
--- /dev/null
+++ b/drivers/video/omap2/panel-n800.c
@@ -0,0 +1,437 @@
+
+/*#define DEBUG*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
+
+#include <mach/display.h>
+#include <mach/dma.h>
+
+#define MIPID_CMD_READ_DISP_ID		0x04
+#define MIPID_CMD_READ_RED		0x06
+#define MIPID_CMD_READ_GREEN		0x07
+#define MIPID_CMD_READ_BLUE		0x08
+#define MIPID_CMD_READ_DISP_STATUS	0x09
+#define MIPID_CMD_RDDSDR		0x0F
+#define MIPID_CMD_SLEEP_IN		0x10
+#define MIPID_CMD_SLEEP_OUT		0x11
+#define MIPID_CMD_DISP_OFF		0x28
+#define MIPID_CMD_DISP_ON		0x29
+
+#define MIPID_VER_LPH8923		3
+#define MIPID_VER_LS041Y3		4
+
+#define MIPID_ESD_CHECK_PERIOD		msecs_to_jiffies(5000)
+
+#ifdef DEBUG
+#define DBG(format, ...) printk(KERN_DEBUG "PN800: " format, ## __VA_ARGS__)
+#else
+#define DBG(format, ...)
+#endif
+
+struct pn800_device {
+	struct backlight_device *bl_dev;
+	int		enabled;
+	int		model;
+	int		revision;
+	u8		display_id[3];
+	unsigned int	saved_bklight_level;
+	unsigned long	hw_guard_end;		/* next value of jiffies
+						   when we can issue the
+						   next sleep in/out command */
+	unsigned long	hw_guard_wait;		/* max guard time in jiffies */
+
+	struct spi_device	*spi;
+	struct mutex		mutex;
+	struct omap_panel	panel;
+	struct omap_display	*display;
+};
+
+
+static void pn800_transfer(struct pn800_device *md, int cmd,
+			      const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+{
+	struct spi_message	m;
+	struct spi_transfer	*x, xfer[4];
+	u16			w;
+	int			r;
+
+	BUG_ON(md->spi == NULL);
+
+	spi_message_init(&m);
+
+	memset(xfer, 0, sizeof(xfer));
+	x = &xfer[0];
+
+	cmd &=  0xff;
+	x->tx_buf = &cmd;
+	x->bits_per_word = 9;
+	x->len = 2;
+	spi_message_add_tail(x, &m);
+
+	if (wlen) {
+		x++;
+		x->tx_buf = wbuf;
+		x->len = wlen;
+		x->bits_per_word = 9;
+		spi_message_add_tail(x, &m);
+	}
+
+	if (rlen) {
+		x++;
+		x->rx_buf = &w;
+		x->len = 1;
+		spi_message_add_tail(x, &m);
+
+		if (rlen > 1) {
+			/* Arrange for the extra clock before the first
+			 * data bit.
+			 */
+			x->bits_per_word = 9;
+			x->len		 = 2;
+
+			x++;
+			x->rx_buf	 = &rbuf[1];
+			x->len		 = rlen - 1;
+			spi_message_add_tail(x, &m);
+		}
+	}
+
+	r = spi_sync(md->spi, &m);
+	if (r < 0)
+		dev_dbg(&md->spi->dev, "spi_sync %d\n", r);
+
+	if (rlen)
+		rbuf[0] = w & 0xff;
+}
+
+static inline void pn800_cmd(struct pn800_device *md, int cmd)
+{
+	pn800_transfer(md, cmd, NULL, 0, NULL, 0);
+}
+
+static inline void pn800_write(struct pn800_device *md,
+			       int reg, const u8 *buf, int len)
+{
+	pn800_transfer(md, reg, buf, len, NULL, 0);
+}
+
+static inline void pn800_read(struct pn800_device *md,
+			      int reg, u8 *buf, int len)
+{
+	pn800_transfer(md, reg, NULL, 0, buf, len);
+}
+
+static void set_data_lines(struct pn800_device *md, int data_lines)
+{
+	u16 par;
+
+	switch (data_lines) {
+	case 16:
+		par = 0x150;
+		break;
+	case 18:
+		par = 0x160;
+		break;
+	case 24:
+		par = 0x170;
+		break;
+	}
+	pn800_write(md, 0x3a, (u8 *)&par, 2);
+}
+
+static void send_init_string(struct pn800_device *md)
+{
+	u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
+	int data_lines;
+
+	pn800_write(md, 0xc2, (u8 *)initpar, sizeof(initpar));
+
+	data_lines = (int)md->display->hw_config.priv; // XXX
+
+	set_data_lines(md, data_lines);
+}
+
+static void hw_guard_start(struct pn800_device *md, int guard_msec)
+{
+	md->hw_guard_wait = msecs_to_jiffies(guard_msec);
+	md->hw_guard_end = jiffies + md->hw_guard_wait;
+}
+
+static void hw_guard_wait(struct pn800_device *md)
+{
+	unsigned long wait = md->hw_guard_end - jiffies;
+
+	if ((long)wait > 0 && wait <= md->hw_guard_wait) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(wait);
+	}
+}
+
+static void set_sleep_mode(struct pn800_device *md, int on)
+{
+	int cmd, sleep_time = 50;
+
+	if (on)
+		cmd = MIPID_CMD_SLEEP_IN;
+	else
+		cmd = MIPID_CMD_SLEEP_OUT;
+	hw_guard_wait(md);
+	pn800_cmd(md, cmd);
+	hw_guard_start(md, 120);
+	/*
+	 * When we enable the panel, it seems we _have_ to sleep
+	 * 120 ms before sending the init string. When disabling the
+	 * panel we'll sleep for the duration of 2 frames, so that the
+	 * controller can still provide the PCLK,HS,VS signals. */
+	if (!on)
+		sleep_time = 120;
+	msleep(sleep_time);
+}
+
+static void set_display_state(struct pn800_device *md, int enabled)
+{
+	int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
+
+	pn800_cmd(md, cmd);
+}
+
+static int panel_enabled(struct pn800_device *md)
+{
+	u32 disp_status;
+	int enabled;
+
+	pn800_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
+	disp_status = __be32_to_cpu(disp_status);
+	enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
+	dev_dbg(&md->spi->dev,
+		"LCD panel %s enabled by bootloader (status 0x%04x)\n",
+		enabled ? "" : "not ", disp_status);
+	DBG("status %#08x\n", disp_status);
+	return enabled;
+}
+
+static int panel_detect(struct pn800_device *md)
+{
+	pn800_read(md, MIPID_CMD_READ_DISP_ID, md->display_id, 3);
+	dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n",
+		md->display_id[0], md->display_id[1], md->display_id[2]);
+
+	switch (md->display_id[0]) {
+	case 0x45:
+		md->model = MIPID_VER_LPH8923;
+		md->panel.name = "lph8923";
+		break;
+	case 0x83:
+		md->model = MIPID_VER_LS041Y3;
+		md->panel.name = "ls041y3";
+		//md->esd_check = ls041y3_esd_check;
+		break;
+	default:
+		md->panel.name = "unknown";
+		dev_err(&md->spi->dev, "invalid display ID\n");
+		return -ENODEV;
+	}
+
+	md->revision = md->display_id[1];
+	pr_info("omapfb: %s rev %02x LCD detected\n",
+			md->panel.name, md->revision);
+
+	return 0;
+}
+
+
+
+static int pn800_panel_enable(struct omap_display *display)
+{
+	int r;
+	struct pn800_device *md =
+		(struct pn800_device *)display->panel->priv;
+
+	DBG("pn800_panel_enable\n");
+
+	mutex_lock(&md->mutex);
+
+	if (display->hw_config.panel_enable)
+		display->hw_config.panel_enable(display);
+
+	msleep(50); // wait for power up
+
+	r = panel_detect(md);
+	if (r) {
+		mutex_unlock(&md->mutex);
+		return r;
+	}
+
+	md->enabled = panel_enabled(md);
+
+	if (md->enabled) {
+		DBG("panel already enabled\n");
+		; /*pn800_esd_start_check(md);*/
+	} else {
+		; /*md->saved_bklight_level = pn800_get_bklight_level(panel);*/
+	}
+
+
+	if (md->enabled) {
+		mutex_unlock(&md->mutex);
+		return 0;
+	}
+
+	set_sleep_mode(md, 0);
+	md->enabled = 1;
+	send_init_string(md);
+	set_display_state(md, 1);
+	//mipid_set_bklight_level(panel, md->saved_bklight_level);
+	//mipid_esd_start_check(md);
+
+	mutex_unlock(&md->mutex);
+	return 0;
+}
+
+static void pn800_panel_disable(struct omap_display *display)
+{
+	struct pn800_device *md =
+		(struct pn800_device *)display->panel->priv;
+
+	DBG("pn800_panel_disable\n");
+
+	mutex_lock(&md->mutex);
+
+	if (!md->enabled) {
+		mutex_unlock(&md->mutex);
+		return;
+	}
+	/*md->saved_bklight_level = pn800_get_bklight_level(panel);*/
+	/*pn800_set_bklight_level(panel, 0);*/
+
+	set_display_state(md, 0);
+	set_sleep_mode(md, 1);
+	md->enabled = 0;
+
+
+	if (display->hw_config.panel_disable)
+		display->hw_config.panel_disable(display);
+
+	mutex_unlock(&md->mutex);
+}
+
+static int pn800_panel_init(struct omap_display *display)
+{
+	struct pn800_device *md =
+		(struct pn800_device *)display->panel->priv;
+
+	DBG("pn800_panel_init\n");
+
+	mutex_init(&md->mutex);
+	md->display = display;
+
+	return 0;
+}
+
+static int pn800_run_test(struct omap_display *display, int test_num)
+{
+	return 0;
+}
+
+static struct omap_panel pn800_panel = {
+	.owner		= THIS_MODULE,
+	.name		= "panel-pn800",
+	.init		= pn800_panel_init,
+	/*.remove	= pn800_cleanup,*/
+	.enable		= pn800_panel_enable,
+	.disable	= pn800_panel_disable,
+	//.set_mode	= pn800_set_mode,
+	.run_test	= pn800_run_test,
+
+	.timings = {
+		.x_res = 800,
+		.y_res = 480,
+
+		.pixel_clock	= 21940,
+		.hsw		= 50,
+		.hfp		= 20,
+		.hbp		= 15,
+
+		.vsw		= 2,
+		.vfp		= 1,
+		.vbp		= 3,
+	},
+	.config		= OMAP_DSS_LCD_TFT,
+
+	.bpp = 16,
+};
+
+static int pn800_spi_probe(struct spi_device *spi)
+{
+	struct pn800_device *md;
+
+	DBG("pn800_spi_probe\n");
+
+	md = kzalloc(sizeof(*md), GFP_KERNEL);
+	if (md == NULL) {
+		dev_err(&spi->dev, "out of memory\n");
+		return -ENOMEM;
+	}
+
+	spi->mode = SPI_MODE_0;
+	md->spi = spi;
+	dev_set_drvdata(&spi->dev, md);
+	md->panel = pn800_panel;
+	pn800_panel.priv = md;
+
+	omap_dss_register_panel(&pn800_panel);
+
+	return 0;
+}
+
+static int pn800_spi_remove(struct spi_device *spi)
+{
+	struct pn800_device *md = dev_get_drvdata(&spi->dev);
+
+	DBG("pn800_spi_remove\n");
+
+	omap_dss_unregister_panel(&pn800_panel);
+
+	/*pn800_disable(&md->panel);*/
+	kfree(md);
+
+	return 0;
+}
+
+static struct spi_driver pn800_spi_driver = {
+	.driver = {
+		.name	= "panel-n800",
+		.bus	= &spi_bus_type,
+		.owner	= THIS_MODULE,
+	},
+	.probe	= pn800_spi_probe,
+	.remove	= __devexit_p(pn800_spi_remove),
+};
+
+static int __init pn800_init(void)
+{
+	DBG("pn800_init\n");
+	return spi_register_driver(&pn800_spi_driver);
+}
+
+static void __exit pn800_exit(void)
+{
+	DBG("pn800_exit\n");
+	spi_unregister_driver(&pn800_spi_driver);
+}
+
+module_init(pn800_init);
+module_exit(pn800_exit);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
+MODULE_DESCRIPTION("N800 LCD Driver");
+MODULE_LICENSE("GPL");

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [Linux-fbdev-devel] [PATCH 02/12] DSS: Display subsystem for OMAP2/3
  2009-01-12 11:47 ` [PATCH 02/12] DSS: Display subsystem for OMAP2/3 Tomi Valkeinen
@ 2009-01-12 13:02   ` Tony Lindgren
  2009-01-12 13:06     ` Shah, Hardik
  0 siblings, 1 reply; 23+ messages in thread
From: Tony Lindgren @ 2009-01-12 13:02 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-fbdev-devel, linux-omap

* Tomi Valkeinen <tomi.valkeinen@nokia.com> [090112 14:37]:
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
> ---
> 
>  arch/arm/plat-omap/Kconfig                |    2 
>  arch/arm/plat-omap/Makefile               |    2 
>  arch/arm/plat-omap/dss/Kconfig            |   71 +
>  arch/arm/plat-omap/dss/Makefile           |    6 
>  arch/arm/plat-omap/dss/dispc.c            | 2113 +++++++++++++++++++++++++++++
>  arch/arm/plat-omap/dss/display.c          |  787 +++++++++++
>  arch/arm/plat-omap/dss/dpi.c              |  344 +++++
>  arch/arm/plat-omap/dss/dss.c              |  774 +++++++++++
>  arch/arm/plat-omap/dss/dss.h              |  274 ++++
>  arch/arm/plat-omap/dss/sdi.c              |  174 ++
>  arch/arm/plat-omap/include/mach/display.h |  462 ++++++
>  11 files changed, 5009 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/plat-omap/dss/Kconfig
>  create mode 100644 arch/arm/plat-omap/dss/Makefile
>  create mode 100644 arch/arm/plat-omap/dss/dispc.c
>  create mode 100644 arch/arm/plat-omap/dss/display.c
>  create mode 100644 arch/arm/plat-omap/dss/dpi.c
>  create mode 100644 arch/arm/plat-omap/dss/dss.c
>  create mode 100644 arch/arm/plat-omap/dss/dss.h
>  create mode 100644 arch/arm/plat-omap/dss/sdi.c
>  create mode 100644 arch/arm/plat-omap/include/mach/display.h

Sorry, no subdirectories allowed under arch/arm/*omap*. Please move
these to live under drivers/video somewhere.

Also, you should not need to use cpu_is_omapxxxx() macros under
drivers, please separate out the low-level init to happen under
arch/arm/*omap* and pass the necessary things to the driver in
the platform_data. See how usb and mmc are doing it for example.

Regards,

Tony

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 03/12] DSS: RFBI support
  2009-01-12 11:47 ` [PATCH 03/12] DSS: RFBI support Tomi Valkeinen
@ 2009-01-12 13:03   ` Tony Lindgren
  0 siblings, 0 replies; 23+ messages in thread
From: Tony Lindgren @ 2009-01-12 13:03 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-fbdev-devel, linux-omap

* Tomi Valkeinen <tomi.valkeinen@nokia.com> [090112 14:19]:

Please add a patch description here so other people will have
a clue what the patch is about. Might as well add something
to the header too. The same goes for the other patches.

Regards,

Tony

^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: [Linux-fbdev-devel] [PATCH 02/12] DSS: Display subsystem for OMAP2/3
  2009-01-12 13:02   ` [Linux-fbdev-devel] " Tony Lindgren
@ 2009-01-12 13:06     ` Shah, Hardik
  2009-01-12 13:17       ` Tony Lindgren
  0 siblings, 1 reply; 23+ messages in thread
From: Shah, Hardik @ 2009-01-12 13:06 UTC (permalink / raw)
  To: Tony Lindgren, Tomi Valkeinen
  Cc: linux-fbdev-devel@lists.sourceforge.net,
	linux-omap@vger.kernel.org



> -----Original Message-----
> From: linux-omap-owner@vger.kernel.org [mailto:linux-omap-
> owner@vger.kernel.org] On Behalf Of Tony Lindgren
> Sent: Monday, January 12, 2009 6:32 PM
> To: Tomi Valkeinen
> Cc: linux-fbdev-devel@lists.sourceforge.net; linux-omap@vger.kernel.org
> Subject: Re: [Linux-fbdev-devel] [PATCH 02/12] DSS: Display subsystem for
> OMAP2/3
> 
> * Tomi Valkeinen <tomi.valkeinen@nokia.com> [090112 14:37]:
> > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
> > ---
> >
> >  arch/arm/plat-omap/Kconfig                |    2
> >  arch/arm/plat-omap/Makefile               |    2
> >  arch/arm/plat-omap/dss/Kconfig            |   71 +
> >  arch/arm/plat-omap/dss/Makefile           |    6
> >  arch/arm/plat-omap/dss/dispc.c            | 2113
> +++++++++++++++++++++++++++++
> >  arch/arm/plat-omap/dss/display.c          |  787 +++++++++++
> >  arch/arm/plat-omap/dss/dpi.c              |  344 +++++
> >  arch/arm/plat-omap/dss/dss.c              |  774 +++++++++++
> >  arch/arm/plat-omap/dss/dss.h              |  274 ++++
> >  arch/arm/plat-omap/dss/sdi.c              |  174 ++
> >  arch/arm/plat-omap/include/mach/display.h |  462 ++++++
> >  11 files changed, 5009 insertions(+), 0 deletions(-)
> >  create mode 100644 arch/arm/plat-omap/dss/Kconfig
> >  create mode 100644 arch/arm/plat-omap/dss/Makefile
> >  create mode 100644 arch/arm/plat-omap/dss/dispc.c
> >  create mode 100644 arch/arm/plat-omap/dss/display.c
> >  create mode 100644 arch/arm/plat-omap/dss/dpi.c
> >  create mode 100644 arch/arm/plat-omap/dss/dss.c
> >  create mode 100644 arch/arm/plat-omap/dss/dss.h
> >  create mode 100644 arch/arm/plat-omap/dss/sdi.c
> >  create mode 100644 arch/arm/plat-omap/include/mach/display.h
> 
> Sorry, no subdirectories allowed under arch/arm/*omap*. Please move
> these to live under drivers/video somewhere.
> 
> Also, you should not need to use cpu_is_omapxxxx() macros under
> drivers, please separate out the low-level init to happen under
> arch/arm/*omap* and pass the necessary things to the driver in
> the platform_data. See how usb and mmc are doing it for example.
> 
[Shah, Hardik] Hi Tony,
DSS library will be used by both V4L2 driver and the FBDEV driver.  So will you please suggest the ideal directory for the DSS library?  Moving the DSS library files under /drivers/video will break V4L2 will moving it under /drivers/media/video/ will break fbdev.

Thanks and Regards,
Hardik Shah

> Regards,
> 
> Tony
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Linux-fbdev-devel] [PATCH 02/12] DSS: Display subsystem for OMAP2/3
  2009-01-12 13:06     ` Shah, Hardik
@ 2009-01-12 13:17       ` Tony Lindgren
  0 siblings, 0 replies; 23+ messages in thread
From: Tony Lindgren @ 2009-01-12 13:17 UTC (permalink / raw)
  To: Shah, Hardik
  Cc: Tomi Valkeinen, linux-fbdev-devel@lists.sourceforge.net,
	linux-omap@vger.kernel.org

* Shah, Hardik <hardik.shah@ti.com> [090112 15:06]:
> 
> 
> > -----Original Message-----
> > From: linux-omap-owner@vger.kernel.org [mailto:linux-omap-
> > owner@vger.kernel.org] On Behalf Of Tony Lindgren
> > Sent: Monday, January 12, 2009 6:32 PM
> > To: Tomi Valkeinen
> > Cc: linux-fbdev-devel@lists.sourceforge.net; linux-omap@vger.kernel.org
> > Subject: Re: [Linux-fbdev-devel] [PATCH 02/12] DSS: Display subsystem for
> > OMAP2/3
> > 
> > * Tomi Valkeinen <tomi.valkeinen@nokia.com> [090112 14:37]:
> > > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
> > > ---
> > >
> > >  arch/arm/plat-omap/Kconfig                |    2
> > >  arch/arm/plat-omap/Makefile               |    2
> > >  arch/arm/plat-omap/dss/Kconfig            |   71 +
> > >  arch/arm/plat-omap/dss/Makefile           |    6
> > >  arch/arm/plat-omap/dss/dispc.c            | 2113
> > +++++++++++++++++++++++++++++
> > >  arch/arm/plat-omap/dss/display.c          |  787 +++++++++++
> > >  arch/arm/plat-omap/dss/dpi.c              |  344 +++++
> > >  arch/arm/plat-omap/dss/dss.c              |  774 +++++++++++
> > >  arch/arm/plat-omap/dss/dss.h              |  274 ++++
> > >  arch/arm/plat-omap/dss/sdi.c              |  174 ++
> > >  arch/arm/plat-omap/include/mach/display.h |  462 ++++++
> > >  11 files changed, 5009 insertions(+), 0 deletions(-)
> > >  create mode 100644 arch/arm/plat-omap/dss/Kconfig
> > >  create mode 100644 arch/arm/plat-omap/dss/Makefile
> > >  create mode 100644 arch/arm/plat-omap/dss/dispc.c
> > >  create mode 100644 arch/arm/plat-omap/dss/display.c
> > >  create mode 100644 arch/arm/plat-omap/dss/dpi.c
> > >  create mode 100644 arch/arm/plat-omap/dss/dss.c
> > >  create mode 100644 arch/arm/plat-omap/dss/dss.h
> > >  create mode 100644 arch/arm/plat-omap/dss/sdi.c
> > >  create mode 100644 arch/arm/plat-omap/include/mach/display.h
> > 
> > Sorry, no subdirectories allowed under arch/arm/*omap*. Please move
> > these to live under drivers/video somewhere.
> > 
> > Also, you should not need to use cpu_is_omapxxxx() macros under
> > drivers, please separate out the low-level init to happen under
> > arch/arm/*omap* and pass the necessary things to the driver in
> > the platform_data. See how usb and mmc are doing it for example.
> > 
> [Shah, Hardik] Hi Tony,
> DSS library will be used by both V4L2 driver and the FBDEV driver.  So will you please suggest the ideal directory for the DSS library?  Moving the DSS library files under /drivers/video will break V4L2 will moving it under /drivers/media/video/ will break fbdev.

How about drivers/video/omap/dss? You should be able to compile
in the common modules even if CONFIG_FB is not set.

Tony

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 00/12] DSS: Series description
  2009-01-12 11:47 [PATCH 00/12] DSS: Series description Tomi Valkeinen
                   ` (11 preceding siblings ...)
  2009-01-12 11:48 ` [PATCH 12/12] DSS: Hacked N810 support Tomi Valkeinen
@ 2009-01-12 13:44 ` Koen Kooi
  2009-01-12 14:52   ` Hiremath, Vaibhav
  12 siblings, 1 reply; 23+ messages in thread
From: Koen Kooi @ 2009-01-12 13:44 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-fbdev-devel, linux-omap

[-- Attachment #1: Type: text/plain, Size: 5602 bytes --]


Op 12 jan 2009, om 12:47 heeft Tomi Valkeinen het volgende geschreven:

> New Display Subsystem for OMAP2/3
> ---------------------------------
>
> This patch set implements new Display Subsystem (DSS) for OMAP2/3  
> processors.
> The DSS is still under work and these patches are for review.

I've tested these patches on beagleboard and omap35x EVM. The  
beagleboard is fully functional with it, the EVM has some glitches  
with DVI, but that might be due to differences between revisions of  
the EVM board (or rather the PMIC + SoC daugtherboards). The internal  
LCD works great on the EVM, the "3 dots in the corner" problem that  
DSS1 had is gone.

Summary: please merge this, for beagleboard and omap3evm there are no  
regressions, only feature additions (s-video, better pixclock, etc)  
over the current code.

regards,

Koen



> This is an updated version of the patch set I sent back in november:
> http://marc.info/?l=linux-fbdev-devel&m=122581504222406&w=2
>
> The first patch is a doc file that tries to explain a bit how the  
> drivers work.
>
> The patch set is based on the current linux-omap tree.
>
> You can find the patches also from a git tree at
> http://www.bat.org/~tomba/git/linux-omap-dss.git/
>
> ---
>
> Tomi Valkeinen (12):
>     DSS: Hacked N810 support
>     DSS: Support for OMAP3 EVM board
>     DSS: Support for OMAP3 SDP board
>     DSS: Sharp LS037V7DW01 LCD Panel driver
>     DSS: support for Beagle Board
>     DSS: Add generic DVI panel
>     DSS: OMAPFB: fb driver for new display subsystem
>     DSS: DSI support
>     DSS: VENC support
>     DSS: RFBI support
>     DSS: Display subsystem for OMAP2/3
>     DSS: Documentation for DSS2
>
>
> Documentation/arm/OMAP/DSS                    |  270 ++
> arch/arm/configs/dss_omap3_beagle_defconfig   | 1437 +++++++++++
> arch/arm/configs/dss_omap_3430sdp_defconfig   | 1603 +++++++++++++
> arch/arm/mach-omap2/board-3430sdp.c           |  215 ++
> arch/arm/mach-omap2/board-n800.c              |  214 +-
> arch/arm/mach-omap2/board-omap3beagle.c       |  101 +
> arch/arm/mach-omap2/board-omap3evm.c          |  203 ++
> arch/arm/plat-omap/Kconfig                    |    2
> arch/arm/plat-omap/Makefile                   |    4
> arch/arm/plat-omap/dss/Kconfig                |   71 +
> arch/arm/plat-omap/dss/Makefile               |    6
> arch/arm/plat-omap/dss/dispc.c                | 2113 +++++++++++++++++
> arch/arm/plat-omap/dss/display.c              |  787 ++++++
> arch/arm/plat-omap/dss/dpi.c                  |  344 +++
> arch/arm/plat-omap/dss/dsi.c                  | 3187 ++++++++++++++++ 
> +++++++++
> arch/arm/plat-omap/dss/dss.c                  |  774 ++++++
> arch/arm/plat-omap/dss/dss.h                  |  274 ++
> arch/arm/plat-omap/dss/rfbi.c                 | 1262 ++++++++++
> arch/arm/plat-omap/dss/sdi.c                  |  174 +
> arch/arm/plat-omap/dss/venc.c                 |  506 ++++
> arch/arm/plat-omap/fb-vram.c                  |  646 +++++
> arch/arm/plat-omap/fb.c                       |   22
> arch/arm/plat-omap/include/mach/display.h     |  462 ++++
> arch/arm/plat-omap/include/mach/omapfb.h      |   14
> drivers/video/Kconfig                         |    1
> drivers/video/Makefile                        |    1
> drivers/video/omap/Kconfig                    |    5
> drivers/video/omap2/Kconfig                   |   62
> drivers/video/omap2/Makefile                  |    8
> drivers/video/omap2/ctrl-blizzard.c           |  279 ++
> drivers/video/omap2/omapfb-ioctl.c            |  460 ++++
> drivers/video/omap2/omapfb-main.c             | 1442 +++++++++++
> drivers/video/omap2/omapfb-sysfs.c            |  901 +++++++
> drivers/video/omap2/omapfb.h                  |  115 +
> drivers/video/omap2/panel-generic.c           |   97 +
> drivers/video/omap2/panel-n800.c              |  437 +++
> drivers/video/omap2/panel-sharp-ls037v7dw01.c |  109 +
> 37 files changed, 18537 insertions(+), 71 deletions(-)
> create mode 100644 Documentation/arm/OMAP/DSS
> create mode 100644 arch/arm/configs/dss_omap3_beagle_defconfig
> create mode 100644 arch/arm/configs/dss_omap_3430sdp_defconfig
> create mode 100644 arch/arm/plat-omap/dss/Kconfig
> create mode 100644 arch/arm/plat-omap/dss/Makefile
> create mode 100644 arch/arm/plat-omap/dss/dispc.c
> create mode 100644 arch/arm/plat-omap/dss/display.c
> create mode 100644 arch/arm/plat-omap/dss/dpi.c
> create mode 100644 arch/arm/plat-omap/dss/dsi.c
> create mode 100644 arch/arm/plat-omap/dss/dss.c
> create mode 100644 arch/arm/plat-omap/dss/dss.h
> create mode 100644 arch/arm/plat-omap/dss/rfbi.c
> create mode 100644 arch/arm/plat-omap/dss/sdi.c
> create mode 100644 arch/arm/plat-omap/dss/venc.c
> create mode 100644 arch/arm/plat-omap/fb-vram.c
> create mode 100644 arch/arm/plat-omap/include/mach/display.h
> create mode 100644 drivers/video/omap2/Kconfig
> create mode 100644 drivers/video/omap2/Makefile
> create mode 100644 drivers/video/omap2/ctrl-blizzard.c
> create mode 100644 drivers/video/omap2/omapfb-ioctl.c
> create mode 100644 drivers/video/omap2/omapfb-main.c
> create mode 100644 drivers/video/omap2/omapfb-sysfs.c
> create mode 100644 drivers/video/omap2/omapfb.h
> create mode 100644 drivers/video/omap2/panel-generic.c
> create mode 100644 drivers/video/omap2/panel-n800.c
> create mode 100644 drivers/video/omap2/panel-sharp-ls037v7dw01.c
>
> -- 
> Tomi Valkeinen
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux- 
> omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


[-- Attachment #2: Dit deel van het bericht is digitaal ondertekend --]
[-- Type: application/pgp-signature, Size: 186 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: [PATCH 00/12] DSS: Series description
  2009-01-12 13:44 ` [PATCH 00/12] DSS: Series description Koen Kooi
@ 2009-01-12 14:52   ` Hiremath, Vaibhav
  2009-01-12 15:39     ` Koen Kooi
  0 siblings, 1 reply; 23+ messages in thread
From: Hiremath, Vaibhav @ 2009-01-12 14:52 UTC (permalink / raw)
  To: Koen Kooi, Tomi Valkeinen
  Cc: linux-fbdev-devel@lists.sourceforge.net,
	linux-omap@vger.kernel.org



Thanks,
Vaibhav Hiremath

> -----Original Message-----
> From: linux-omap-owner@vger.kernel.org [mailto:linux-omap-
> owner@vger.kernel.org] On Behalf Of Koen Kooi
> Sent: Monday, January 12, 2009 7:14 PM
> To: Tomi Valkeinen
> Cc: linux-fbdev-devel@lists.sourceforge.net; linux-
> omap@vger.kernel.org
> Subject: Re: [PATCH 00/12] DSS: Series description
> 
> 
> Op 12 jan 2009, om 12:47 heeft Tomi Valkeinen het volgende
> geschreven:
> 
> > New Display Subsystem for OMAP2/3
> > ---------------------------------
> >
> > This patch set implements new Display Subsystem (DSS) for OMAP2/3
> > processors.
> > The DSS is still under work and these patches are for review.
> 
> I've tested these patches on beagleboard and omap35x EVM. The
> beagleboard is fully functional with it, the EVM has some glitches
> with DVI, but that might be due to differences between revisions of
> the EVM board (or rather the PMIC + SoC daugtherboards). 

[Hiremath, Vaibhav] Koen, I have also tested DVI output on EVM and facing same issues but I believe they are not because of board revisions. I have validated the DVI output with our previous (TI version of DSS library) on the same board and it comes absolutely fine. I need to dig bit more to find where exactly the issue is.

> The
> internal
> LCD works great on the EVM, the "3 dots in the corner" problem that
> DSS1 had is gone.
> 
> Summary: please merge this, for beagleboard and omap3evm there are
> no
> regressions, only feature additions (s-video, better pixclock, etc)
> over the current code.
> 
> regards,
> 
> Koen
> 
> 
> 
> > This is an updated version of the patch set I sent back in
> november:
> > http://marc.info/?l=linux-fbdev-devel&m=122581504222406&w=2
> >
> > The first patch is a doc file that tries to explain a bit how the
> > drivers work.
> >
> > The patch set is based on the current linux-omap tree.
> >
> > You can find the patches also from a git tree at
> > http://www.bat.org/~tomba/git/linux-omap-dss.git/
> >
> > ---
> >
> > Tomi Valkeinen (12):
> >     DSS: Hacked N810 support
> >     DSS: Support for OMAP3 EVM board
> >     DSS: Support for OMAP3 SDP board
> >     DSS: Sharp LS037V7DW01 LCD Panel driver
> >     DSS: support for Beagle Board
> >     DSS: Add generic DVI panel
> >     DSS: OMAPFB: fb driver for new display subsystem
> >     DSS: DSI support
> >     DSS: VENC support
> >     DSS: RFBI support
> >     DSS: Display subsystem for OMAP2/3
> >     DSS: Documentation for DSS2
> >
> >
> > Documentation/arm/OMAP/DSS                    |  270 ++
> > arch/arm/configs/dss_omap3_beagle_defconfig   | 1437 +++++++++++
> > arch/arm/configs/dss_omap_3430sdp_defconfig   | 1603 +++++++++++++
> > arch/arm/mach-omap2/board-3430sdp.c           |  215 ++
> > arch/arm/mach-omap2/board-n800.c              |  214 +-
> > arch/arm/mach-omap2/board-omap3beagle.c       |  101 +
> > arch/arm/mach-omap2/board-omap3evm.c          |  203 ++
> > arch/arm/plat-omap/Kconfig                    |    2
> > arch/arm/plat-omap/Makefile                   |    4
> > arch/arm/plat-omap/dss/Kconfig                |   71 +
> > arch/arm/plat-omap/dss/Makefile               |    6
> > arch/arm/plat-omap/dss/dispc.c                | 2113
> +++++++++++++++++
> > arch/arm/plat-omap/dss/display.c              |  787 ++++++
> > arch/arm/plat-omap/dss/dpi.c                  |  344 +++
> > arch/arm/plat-omap/dss/dsi.c                  | 3187
> ++++++++++++++++
> > +++++++++
> > arch/arm/plat-omap/dss/dss.c                  |  774 ++++++
> > arch/arm/plat-omap/dss/dss.h                  |  274 ++
> > arch/arm/plat-omap/dss/rfbi.c                 | 1262 ++++++++++
> > arch/arm/plat-omap/dss/sdi.c                  |  174 +
> > arch/arm/plat-omap/dss/venc.c                 |  506 ++++
> > arch/arm/plat-omap/fb-vram.c                  |  646 +++++
> > arch/arm/plat-omap/fb.c                       |   22
> > arch/arm/plat-omap/include/mach/display.h     |  462 ++++
> > arch/arm/plat-omap/include/mach/omapfb.h      |   14
> > drivers/video/Kconfig                         |    1
> > drivers/video/Makefile                        |    1
> > drivers/video/omap/Kconfig                    |    5
> > drivers/video/omap2/Kconfig                   |   62
> > drivers/video/omap2/Makefile                  |    8
> > drivers/video/omap2/ctrl-blizzard.c           |  279 ++
> > drivers/video/omap2/omapfb-ioctl.c            |  460 ++++
> > drivers/video/omap2/omapfb-main.c             | 1442 +++++++++++
> > drivers/video/omap2/omapfb-sysfs.c            |  901 +++++++
> > drivers/video/omap2/omapfb.h                  |  115 +
> > drivers/video/omap2/panel-generic.c           |   97 +
> > drivers/video/omap2/panel-n800.c              |  437 +++
> > drivers/video/omap2/panel-sharp-ls037v7dw01.c |  109 +
> > 37 files changed, 18537 insertions(+), 71 deletions(-)
> > create mode 100644 Documentation/arm/OMAP/DSS
> > create mode 100644 arch/arm/configs/dss_omap3_beagle_defconfig
> > create mode 100644 arch/arm/configs/dss_omap_3430sdp_defconfig
> > create mode 100644 arch/arm/plat-omap/dss/Kconfig
> > create mode 100644 arch/arm/plat-omap/dss/Makefile
> > create mode 100644 arch/arm/plat-omap/dss/dispc.c
> > create mode 100644 arch/arm/plat-omap/dss/display.c
> > create mode 100644 arch/arm/plat-omap/dss/dpi.c
> > create mode 100644 arch/arm/plat-omap/dss/dsi.c
> > create mode 100644 arch/arm/plat-omap/dss/dss.c
> > create mode 100644 arch/arm/plat-omap/dss/dss.h
> > create mode 100644 arch/arm/plat-omap/dss/rfbi.c
> > create mode 100644 arch/arm/plat-omap/dss/sdi.c
> > create mode 100644 arch/arm/plat-omap/dss/venc.c
> > create mode 100644 arch/arm/plat-omap/fb-vram.c
> > create mode 100644 arch/arm/plat-omap/include/mach/display.h
> > create mode 100644 drivers/video/omap2/Kconfig
> > create mode 100644 drivers/video/omap2/Makefile
> > create mode 100644 drivers/video/omap2/ctrl-blizzard.c
> > create mode 100644 drivers/video/omap2/omapfb-ioctl.c
> > create mode 100644 drivers/video/omap2/omapfb-main.c
> > create mode 100644 drivers/video/omap2/omapfb-sysfs.c
> > create mode 100644 drivers/video/omap2/omapfb.h
> > create mode 100644 drivers/video/omap2/panel-generic.c
> > create mode 100644 drivers/video/omap2/panel-n800.c
> > create mode 100644 drivers/video/omap2/panel-sharp-ls037v7dw01.c
> >
> > --
> > Tomi Valkeinen
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-
> > omap" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 00/12] DSS: Series description
  2009-01-12 14:52   ` Hiremath, Vaibhav
@ 2009-01-12 15:39     ` Koen Kooi
  0 siblings, 0 replies; 23+ messages in thread
From: Koen Kooi @ 2009-01-12 15:39 UTC (permalink / raw)
  To: Hiremath, Vaibhav
  Cc: Tomi Valkeinen, linux-fbdev-devel@lists.sourceforge.net,
	linux-omap@vger.kernel.org

[-- Attachment #1: Type: text/plain, Size: 6795 bytes --]


Op 12 jan 2009, om 15:52 heeft Hiremath, Vaibhav het volgende  
geschreven:

>
>
> Thanks,
> Vaibhav Hiremath
>
>> -----Original Message-----
>> From: linux-omap-owner@vger.kernel.org [mailto:linux-omap-
>> owner@vger.kernel.org] On Behalf Of Koen Kooi
>> Sent: Monday, January 12, 2009 7:14 PM
>> To: Tomi Valkeinen
>> Cc: linux-fbdev-devel@lists.sourceforge.net; linux-
>> omap@vger.kernel.org
>> Subject: Re: [PATCH 00/12] DSS: Series description
>>
>>
>> Op 12 jan 2009, om 12:47 heeft Tomi Valkeinen het volgende
>> geschreven:
>>
>>> New Display Subsystem for OMAP2/3
>>> ---------------------------------
>>>
>>> This patch set implements new Display Subsystem (DSS) for OMAP2/3
>>> processors.
>>> The DSS is still under work and these patches are for review.
>>
>> I've tested these patches on beagleboard and omap35x EVM. The
>> beagleboard is fully functional with it, the EVM has some glitches
>> with DVI, but that might be due to differences between revisions of
>> the EVM board (or rather the PMIC + SoC daugtherboards).
>
> [Hiremath, Vaibhav] Koen, I have also tested DVI output on EVM and  
> facing same issues but I believe they are not because of board  
> revisions. I have validated the DVI output with our previous (TI  
> version of DSS library) on the same board and it comes absolutely  
> fine. I need to dig bit more to find where exactly the issue is.

The LCD redtint was fixed by adding guards for OMAP3 ES >= 2.0, so I  
was thinking DVI would need the same :)

regards,

KOen

>> The
>> internal
>> LCD works great on the EVM, the "3 dots in the corner" problem that
>> DSS1 had is gone.
>>
>> Summary: please merge this, for beagleboard and omap3evm there are
>> no
>> regressions, only feature additions (s-video, better pixclock, etc)
>> over the current code.
>>
>> regards,
>>
>> Koen
>>
>>
>>
>>> This is an updated version of the patch set I sent back in
>> november:
>>> http://marc.info/?l=linux-fbdev-devel&m=122581504222406&w=2
>>>
>>> The first patch is a doc file that tries to explain a bit how the
>>> drivers work.
>>>
>>> The patch set is based on the current linux-omap tree.
>>>
>>> You can find the patches also from a git tree at
>>> http://www.bat.org/~tomba/git/linux-omap-dss.git/
>>>
>>> ---
>>>
>>> Tomi Valkeinen (12):
>>>    DSS: Hacked N810 support
>>>    DSS: Support for OMAP3 EVM board
>>>    DSS: Support for OMAP3 SDP board
>>>    DSS: Sharp LS037V7DW01 LCD Panel driver
>>>    DSS: support for Beagle Board
>>>    DSS: Add generic DVI panel
>>>    DSS: OMAPFB: fb driver for new display subsystem
>>>    DSS: DSI support
>>>    DSS: VENC support
>>>    DSS: RFBI support
>>>    DSS: Display subsystem for OMAP2/3
>>>    DSS: Documentation for DSS2
>>>
>>>
>>> Documentation/arm/OMAP/DSS                    |  270 ++
>>> arch/arm/configs/dss_omap3_beagle_defconfig   | 1437 +++++++++++
>>> arch/arm/configs/dss_omap_3430sdp_defconfig   | 1603 +++++++++++++
>>> arch/arm/mach-omap2/board-3430sdp.c           |  215 ++
>>> arch/arm/mach-omap2/board-n800.c              |  214 +-
>>> arch/arm/mach-omap2/board-omap3beagle.c       |  101 +
>>> arch/arm/mach-omap2/board-omap3evm.c          |  203 ++
>>> arch/arm/plat-omap/Kconfig                    |    2
>>> arch/arm/plat-omap/Makefile                   |    4
>>> arch/arm/plat-omap/dss/Kconfig                |   71 +
>>> arch/arm/plat-omap/dss/Makefile               |    6
>>> arch/arm/plat-omap/dss/dispc.c                | 2113
>> +++++++++++++++++
>>> arch/arm/plat-omap/dss/display.c              |  787 ++++++
>>> arch/arm/plat-omap/dss/dpi.c                  |  344 +++
>>> arch/arm/plat-omap/dss/dsi.c                  | 3187
>> ++++++++++++++++
>>> +++++++++
>>> arch/arm/plat-omap/dss/dss.c                  |  774 ++++++
>>> arch/arm/plat-omap/dss/dss.h                  |  274 ++
>>> arch/arm/plat-omap/dss/rfbi.c                 | 1262 ++++++++++
>>> arch/arm/plat-omap/dss/sdi.c                  |  174 +
>>> arch/arm/plat-omap/dss/venc.c                 |  506 ++++
>>> arch/arm/plat-omap/fb-vram.c                  |  646 +++++
>>> arch/arm/plat-omap/fb.c                       |   22
>>> arch/arm/plat-omap/include/mach/display.h     |  462 ++++
>>> arch/arm/plat-omap/include/mach/omapfb.h      |   14
>>> drivers/video/Kconfig                         |    1
>>> drivers/video/Makefile                        |    1
>>> drivers/video/omap/Kconfig                    |    5
>>> drivers/video/omap2/Kconfig                   |   62
>>> drivers/video/omap2/Makefile                  |    8
>>> drivers/video/omap2/ctrl-blizzard.c           |  279 ++
>>> drivers/video/omap2/omapfb-ioctl.c            |  460 ++++
>>> drivers/video/omap2/omapfb-main.c             | 1442 +++++++++++
>>> drivers/video/omap2/omapfb-sysfs.c            |  901 +++++++
>>> drivers/video/omap2/omapfb.h                  |  115 +
>>> drivers/video/omap2/panel-generic.c           |   97 +
>>> drivers/video/omap2/panel-n800.c              |  437 +++
>>> drivers/video/omap2/panel-sharp-ls037v7dw01.c |  109 +
>>> 37 files changed, 18537 insertions(+), 71 deletions(-)
>>> create mode 100644 Documentation/arm/OMAP/DSS
>>> create mode 100644 arch/arm/configs/dss_omap3_beagle_defconfig
>>> create mode 100644 arch/arm/configs/dss_omap_3430sdp_defconfig
>>> create mode 100644 arch/arm/plat-omap/dss/Kconfig
>>> create mode 100644 arch/arm/plat-omap/dss/Makefile
>>> create mode 100644 arch/arm/plat-omap/dss/dispc.c
>>> create mode 100644 arch/arm/plat-omap/dss/display.c
>>> create mode 100644 arch/arm/plat-omap/dss/dpi.c
>>> create mode 100644 arch/arm/plat-omap/dss/dsi.c
>>> create mode 100644 arch/arm/plat-omap/dss/dss.c
>>> create mode 100644 arch/arm/plat-omap/dss/dss.h
>>> create mode 100644 arch/arm/plat-omap/dss/rfbi.c
>>> create mode 100644 arch/arm/plat-omap/dss/sdi.c
>>> create mode 100644 arch/arm/plat-omap/dss/venc.c
>>> create mode 100644 arch/arm/plat-omap/fb-vram.c
>>> create mode 100644 arch/arm/plat-omap/include/mach/display.h
>>> create mode 100644 drivers/video/omap2/Kconfig
>>> create mode 100644 drivers/video/omap2/Makefile
>>> create mode 100644 drivers/video/omap2/ctrl-blizzard.c
>>> create mode 100644 drivers/video/omap2/omapfb-ioctl.c
>>> create mode 100644 drivers/video/omap2/omapfb-main.c
>>> create mode 100644 drivers/video/omap2/omapfb-sysfs.c
>>> create mode 100644 drivers/video/omap2/omapfb.h
>>> create mode 100644 drivers/video/omap2/panel-generic.c
>>> create mode 100644 drivers/video/omap2/panel-n800.c
>>> create mode 100644 drivers/video/omap2/panel-sharp-ls037v7dw01.c
>>>
>>> --
>>> Tomi Valkeinen
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-
>>> omap" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>
>
>


[-- Attachment #2: Dit deel van het bericht is digitaal ondertekend --]
[-- Type: application/pgp-signature, Size: 186 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 08/12] DSS: support for Beagle Board
  2009-01-12 11:48 ` [PATCH 08/12] DSS: support for Beagle Board Tomi Valkeinen
@ 2009-01-13 11:14   ` David Brownell
  2009-01-13 11:37     ` Tomi Valkeinen
  0 siblings, 1 reply; 23+ messages in thread
From: David Brownell @ 2009-01-13 11:14 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-fbdev-devel, linux-omap

On Monday 12 January 2009, Tomi Valkeinen wrote:
>  arch/arm/configs/dss_omap3_beagle_defconfig | 1437 +++++++++++++++++++++++++++

This is a complete replacement.  The patch would be a lot
more comprehensible if changed the standard config to just
add support for this board's video options (DVI and S-Video).

Also it'd be good to have a brief textual summary of what
each board's default video config is; maybe one of those
little multicolumn charts as in your first patch, with a
one sentence summary.  (In the board-*.c file.)

Note that after this merges, some work will be needed to
make the regulator framework handle the power switching.
Such logic should move out of board files (except for
setting up "S-Video is supplied using the twl VDAC").
It's not quite time for that yet; heads-up, that's all.

- Dave

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 10/12] DSS: Support for OMAP3 SDP board
  2009-01-12 11:48 ` [PATCH 10/12] DSS: Support for OMAP3 SDP board Tomi Valkeinen
@ 2009-01-13 11:15   ` David Brownell
  0 siblings, 0 replies; 23+ messages in thread
From: David Brownell @ 2009-01-13 11:15 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev-devel

On Monday 12 January 2009, Tomi Valkeinen wrote:
>  arch/arm/configs/dss_omap_3430sdp_defconfig | 1603 +++++++++++++++++++++++++++

Likewise.  In fact, defconfig updates are a lot nicer as
patches that don't touch source code...


------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 08/12] DSS: support for Beagle Board
  2009-01-13 11:14   ` David Brownell
@ 2009-01-13 11:37     ` Tomi Valkeinen
  0 siblings, 0 replies; 23+ messages in thread
From: Tomi Valkeinen @ 2009-01-13 11:37 UTC (permalink / raw)
  To: ext David Brownell; +Cc: linux-fbdev-devel, linux-omap

On Tue, 2009-01-13 at 03:14 -0800, ext David Brownell wrote:
> On Monday 12 January 2009, Tomi Valkeinen wrote:
> >  arch/arm/configs/dss_omap3_beagle_defconfig | 1437 +++++++++++++++++++++++++++
> 
> This is a complete replacement.  The patch would be a lot
> more comprehensible if changed the standard config to just
> add support for this board's video options (DVI and S-Video).

The dss_* defconfigs were actually just for my own use. I seem to have
forgotten them there. Well, they can serve as examples though.

> 
> Also it'd be good to have a brief textual summary of what
> each board's default video config is; maybe one of those
> little multicolumn charts as in your first patch, with a
> one sentence summary.  (In the board-*.c file.)

Well, perhaps. But on the other hand, there are no descriptions of other
hardware components either. But I agree that, at least for the time
being, we could have description of the boards display interfaces to
make validation and review easier.

> Note that after this merges, some work will be needed to
> make the regulator framework handle the power switching.
> Such logic should move out of board files (except for
> setting up "S-Video is supplied using the twl VDAC").
> It's not quite time for that yet; heads-up, that's all.
> 
> - Dave
> 

 Tomi



^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2009-01-13 11:37 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-12 11:47 [PATCH 00/12] DSS: Series description Tomi Valkeinen
2009-01-12 11:47 ` [PATCH 01/12] DSS: Documentation for DSS2 Tomi Valkeinen
2009-01-12 11:47 ` [PATCH 02/12] DSS: Display subsystem for OMAP2/3 Tomi Valkeinen
2009-01-12 13:02   ` [Linux-fbdev-devel] " Tony Lindgren
2009-01-12 13:06     ` Shah, Hardik
2009-01-12 13:17       ` Tony Lindgren
2009-01-12 11:47 ` [PATCH 03/12] DSS: RFBI support Tomi Valkeinen
2009-01-12 13:03   ` Tony Lindgren
2009-01-12 11:47 ` [PATCH 04/12] DSS: VENC support Tomi Valkeinen
2009-01-12 11:47 ` [PATCH 05/12] DSS: DSI support Tomi Valkeinen
2009-01-12 11:47 ` [PATCH 06/12] DSS: OMAPFB: fb driver for new display subsystem Tomi Valkeinen
2009-01-12 11:48 ` [PATCH 07/12] DSS: Add generic DVI panel Tomi Valkeinen
2009-01-12 11:48 ` [PATCH 08/12] DSS: support for Beagle Board Tomi Valkeinen
2009-01-13 11:14   ` David Brownell
2009-01-13 11:37     ` Tomi Valkeinen
2009-01-12 11:48 ` [PATCH 09/12] DSS: Sharp LS037V7DW01 LCD Panel driver Tomi Valkeinen
2009-01-12 11:48 ` [PATCH 10/12] DSS: Support for OMAP3 SDP board Tomi Valkeinen
2009-01-13 11:15   ` David Brownell
2009-01-12 11:48 ` [PATCH 11/12] DSS: Support for OMAP3 EVM board Tomi Valkeinen
2009-01-12 11:48 ` [PATCH 12/12] DSS: Hacked N810 support Tomi Valkeinen
2009-01-12 13:44 ` [PATCH 00/12] DSS: Series description Koen Kooi
2009-01-12 14:52   ` Hiremath, Vaibhav
2009-01-12 15:39     ` Koen Kooi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).