summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0003-DSS2-OMAP2-3-Display-Subsystem-driver.patch
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:14:24 +0100
committerRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:29:45 +0100
commit29d6678fd546377459ef75cf54abeef5b969b5cf (patch)
tree8edd65790e37a00d01c3f203f773fe4b5012db18 /meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0003-DSS2-OMAP2-3-Display-Subsystem-driver.patch
parentda49de6885ee1bc424e70bc02f21f6ab920efb55 (diff)
downloadpoky-29d6678fd546377459ef75cf54abeef5b969b5cf.tar.gz
Major layout change to the packages directory
Having one monolithic packages directory makes it hard to find things and is generally overwhelming. This commit splits it into several logical sections roughly based on function, recipes.txt gives more information about the classifications used. The opportunity is also used to switch from "packages" to "recipes" as used in OpenEmbedded as the term "packages" can be confusing to people and has many different meanings. Not all recipes have been classified yet, this is just a first pass at separating things out. Some packages are moved to meta-extras as they're no longer actively used or maintained. Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0003-DSS2-OMAP2-3-Display-Subsystem-driver.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0003-DSS2-OMAP2-3-Display-Subsystem-driver.patch14450
1 files changed, 14450 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0003-DSS2-OMAP2-3-Display-Subsystem-driver.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0003-DSS2-OMAP2-3-Display-Subsystem-driver.patch
new file mode 100644
index 0000000000..c3523362c6
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0003-DSS2-OMAP2-3-Display-Subsystem-driver.patch
@@ -0,0 +1,14450 @@
1From 284deec412f9c6f15c971d8eaf4d0156a51a2f3b Mon Sep 17 00:00:00 2001
2From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
3Date: Thu, 2 Apr 2009 10:23:42 +0300
4Subject: [PATCH] DSS2: OMAP2/3 Display Subsystem driver
5
6Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
7---
8 Documentation/arm/OMAP/DSS | 311 +++
9 arch/arm/plat-omap/Makefile | 2 +-
10 arch/arm/plat-omap/include/mach/display.h | 520 ++++
11 arch/arm/plat-omap/include/mach/vram.h | 33 +
12 arch/arm/plat-omap/include/mach/vrfb.h | 47 +
13 arch/arm/plat-omap/vram.c | 615 +++++
14 arch/arm/plat-omap/vrfb.c | 159 ++
15 drivers/video/Kconfig | 1 +
16 drivers/video/Makefile | 1 +
17 drivers/video/omap2/Kconfig | 3 +
18 drivers/video/omap2/Makefile | 4 +
19 drivers/video/omap2/dss/Kconfig | 89 +
20 drivers/video/omap2/dss/Makefile | 6 +
21 drivers/video/omap2/dss/core.c | 641 +++++
22 drivers/video/omap2/dss/dispc.c | 2968 +++++++++++++++++++++++
23 drivers/video/omap2/dss/display.c | 693 ++++++
24 drivers/video/omap2/dss/dpi.c | 393 +++
25 drivers/video/omap2/dss/dsi.c | 3752 +++++++++++++++++++++++++++++
26 drivers/video/omap2/dss/dss.c | 345 +++
27 drivers/video/omap2/dss/dss.h | 331 +++
28 drivers/video/omap2/dss/manager.c | 576 +++++
29 drivers/video/omap2/dss/overlay.c | 587 +++++
30 drivers/video/omap2/dss/rfbi.c | 1304 ++++++++++
31 drivers/video/omap2/dss/sdi.c | 245 ++
32 drivers/video/omap2/dss/venc.c | 600 +++++
33 25 files changed, 14225 insertions(+), 1 deletions(-)
34 create mode 100644 Documentation/arm/OMAP/DSS
35 create mode 100644 arch/arm/plat-omap/include/mach/display.h
36 create mode 100644 arch/arm/plat-omap/include/mach/vram.h
37 create mode 100644 arch/arm/plat-omap/include/mach/vrfb.h
38 create mode 100644 arch/arm/plat-omap/vram.c
39 create mode 100644 arch/arm/plat-omap/vrfb.c
40 create mode 100644 drivers/video/omap2/Kconfig
41 create mode 100644 drivers/video/omap2/Makefile
42 create mode 100644 drivers/video/omap2/dss/Kconfig
43 create mode 100644 drivers/video/omap2/dss/Makefile
44 create mode 100644 drivers/video/omap2/dss/core.c
45 create mode 100644 drivers/video/omap2/dss/dispc.c
46 create mode 100644 drivers/video/omap2/dss/display.c
47 create mode 100644 drivers/video/omap2/dss/dpi.c
48 create mode 100644 drivers/video/omap2/dss/dsi.c
49 create mode 100644 drivers/video/omap2/dss/dss.c
50 create mode 100644 drivers/video/omap2/dss/dss.h
51 create mode 100644 drivers/video/omap2/dss/manager.c
52 create mode 100644 drivers/video/omap2/dss/overlay.c
53 create mode 100644 drivers/video/omap2/dss/rfbi.c
54 create mode 100644 drivers/video/omap2/dss/sdi.c
55 create mode 100644 drivers/video/omap2/dss/venc.c
56
57diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
58new file mode 100644
59index 0000000..9e902a2
60--- /dev/null
61+++ b/Documentation/arm/OMAP/DSS
62@@ -0,0 +1,311 @@
63+OMAP2/3 Display Subsystem
64+-------------------------
65+
66+This is an almost total rewrite of the OMAP FB driver in drivers/video/omap
67+(let's call it DSS1). The main differences between DSS1 and DSS2 are DSI,
68+TV-out and multiple display support, but there are lots of small improvements
69+also.
70+
71+The DSS2 driver (omapdss module) is in arch/arm/plat-omap/dss/, and the FB,
72+panel and controller drivers are in drivers/video/omap2/. DSS1 and DSS2 live
73+currently side by side, you can choose which one to use.
74+
75+Features
76+--------
77+
78+Working and tested features include:
79+
80+- MIPI DPI (parallel) output
81+- MIPI DSI output in command mode
82+- MIPI DBI (RFBI) output
83+- SDI output
84+- TV output
85+- All pieces can be compiled as a module or inside kernel
86+- Use DISPC to update any of the outputs
87+- Use CPU to update RFBI or DSI output
88+- OMAP DISPC planes
89+- RGB16, RGB24 packed, RGB24 unpacked
90+- YUV2, UYVY
91+- Scaling
92+- Adjusting DSS FCK to find a good pixel clock
93+- Use DSI DPLL to create DSS FCK
94+
95+Tested boards include:
96+- OMAP3 SDP board
97+- Beagle board
98+- N810
99+
100+omapdss driver
101+--------------
102+
103+The DSS driver does not itself have any support for Linux framebuffer, V4L or
104+such like the current ones, but it has an internal kernel API that upper level
105+drivers can use.
106+
107+The DSS driver models OMAP's overlays, overlay managers and displays in a
108+flexible way to enable non-common multi-display configuration. In addition to
109+modelling the hardware overlays, omapdss supports virtual overlays and overlay
110+managers. These can be used when updating a display with CPU or system DMA.
111+
112+Panel and controller drivers
113+----------------------------
114+
115+The drivers implement panel or controller specific functionality and are not
116+usually visible to users except through omapfb driver. They register
117+themselves to the DSS driver.
118+
119+omapfb driver
120+-------------
121+
122+The omapfb driver implements arbitrary number of standard linux framebuffers.
123+These framebuffers can be routed flexibly to any overlays, thus allowing very
124+dynamic display architecture.
125+
126+The driver exports some omapfb specific ioctls, which are compatible with the
127+ioctls in the old driver.
128+
129+The rest of the non standard features are exported via sysfs. Whether the final
130+implementation will use sysfs, or ioctls, is still open.
131+
132+V4L2 drivers
133+------------
134+
135+V4L2 is being implemented in TI.
136+
137+From omapdss point of view the V4L2 drivers should be similar to framebuffer
138+driver.
139+
140+Architecture
141+--------------------
142+
143+Some clarification what the different components do:
144+
145+ - Framebuffer is a memory area inside OMAP's SRAM/SDRAM that contains the
146+ pixel data for the image. Framebuffer has width and height and color
147+ depth.
148+ - Overlay defines where the pixels are read from and where they go on the
149+ screen. The overlay may be smaller than framebuffer, thus displaying only
150+ part of the framebuffer. The position of the overlay may be changed if
151+ the overlay is smaller than the display.
152+ - Overlay manager combines the overlays in to one image and feeds them to
153+ display.
154+ - Display is the actual physical display device.
155+
156+A framebuffer can be connected to multiple overlays to show the same pixel data
157+on all of the overlays. Note that in this case the overlay input sizes must be
158+the same, but, in case of video overlays, the output size can be different. Any
159+framebuffer can be connected to any overlay.
160+
161+An overlay can be connected to one overlay manager. Also DISPC overlays can be
162+connected only to DISPC overlay managers, and virtual overlays can be only
163+connected to virtual overlays.
164+
165+An overlay manager can be connected to one display. There are certain
166+restrictions which kinds of displays an overlay manager can be connected:
167+
168+ - DISPC TV overlay manager can be only connected to TV display.
169+ - Virtual overlay managers can only be connected to DBI or DSI displays.
170+ - DISPC LCD overlay manager can be connected to all displays, except TV
171+ display.
172+
173+Sysfs
174+-----
175+The sysfs interface is mainly used for testing. I don't think sysfs
176+interface is the best for this in the final version, but I don't quite know
177+what would be the best interfaces for these things.
178+
179+The sysfs interface is divided to two parts: DSS and FB.
180+
181+/sys/class/graphics/fb? directory:
182+mirror 0=off, 1=on
183+rotate Rotation 0-3 for 0, 90, 180, 270 degrees
184+rotate_type 0 = DMA rotation, 1 = VRFB rotation
185+overlays List of overlay numbers to which framebuffer pixels go
186+phys_addr Physical address of the framebuffer
187+virt_addr Virtual address of the framebuffer
188+size Size of the framebuffer
189+
190+/sys/devices/platform/omapdss/overlay? directory:
191+enabled 0=off, 1=on
192+input_size width,height (ie. the framebuffer size)
193+manager Destination overlay manager name
194+name
195+output_size width,height
196+position x,y
197+screen_width width
198+
199+/sys/devices/platform/omapdss/manager? directory:
200+display Destination display
201+name
202+
203+/sys/devices/platform/omapdss/display? directory:
204+ctrl_name Controller name
205+mirror 0=off, 1=on
206+update_mode 0=off, 1=auto, 2=manual
207+enabled 0=off, 1=on
208+name
209+rotate Rotation 0-3 for 0, 90, 180, 270 degrees
210+timings Display timings (pixclock,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw)
211+ When writing, two special timings are accepted for tv-out:
212+ "pal" and "ntsc"
213+panel_name
214+tear_elim Tearing elimination 0=off, 1=on
215+
216+There are also some debugfs files at <debugfs>/omapdss/ which show information
217+about clocks and registers.
218+
219+Examples
220+--------
221+
222+The following definitions have been made for the examples below:
223+
224+ovl0=/sys/devices/platform/omapdss/overlay0
225+ovl1=/sys/devices/platform/omapdss/overlay1
226+ovl2=/sys/devices/platform/omapdss/overlay2
227+
228+mgr0=/sys/devices/platform/omapdss/manager0
229+mgr1=/sys/devices/platform/omapdss/manager1
230+
231+lcd=/sys/devices/platform/omapdss/display0
232+dvi=/sys/devices/platform/omapdss/display1
233+tv=/sys/devices/platform/omapdss/display2
234+
235+fb0=/sys/class/graphics/fb0
236+fb1=/sys/class/graphics/fb1
237+fb2=/sys/class/graphics/fb2
238+
239+Default setup on OMAP3 SDP
240+--------------------------
241+
242+Here's the default setup on OMAP3 SDP board. All planes go to LCD. DVI
243+and TV-out are not in use. The columns from left to right are:
244+framebuffers, overlays, overlay managers, displays. Framebuffers are
245+handled by omapfb, and the rest by the DSS.
246+
247+FB0 --- GFX -\ DVI
248+FB1 --- VID1 --+- LCD ---- LCD
249+FB2 --- VID2 -/ TV ----- TV
250+
251+Example: Switch from LCD to DVI
252+----------------------
253+
254+w=`cat $dvi/horizontal | cut -d "," -f 1`
255+h=`cat $dvi/vertical | cut -d "," -f 1`
256+
257+echo "0" > $lcd/enabled
258+echo "" > $mgr0/display
259+fbset -fb /dev/fb0 -xres $w -yres $h -vxres $w -vyres $h
260+# at this point you have to switch the dvi/lcd dip-switch from the omap board
261+echo "dvi" > $mgr0/display
262+echo "1" > $dvi/enabled
263+
264+After this the configuration looks like:
265+
266+FB0 --- GFX -\ -- DVI
267+FB1 --- VID1 --+- LCD -/ LCD
268+FB2 --- VID2 -/ TV ----- TV
269+
270+Example: Clone GFX overlay to LCD and TV
271+-------------------------------
272+
273+w=`cat $tv/horizontal | cut -d "," -f 1`
274+h=`cat $tv/vertical | cut -d "," -f 1`
275+
276+echo "0" > $ovl0/enabled
277+echo "0" > $ovl1/enabled
278+
279+echo "" > $fb1/overlays
280+echo "0,1" > $fb0/overlays
281+
282+echo "$w,$h" > $ovl1/output_size
283+echo "tv" > $ovl1/manager
284+
285+echo "1" > $ovl0/enabled
286+echo "1" > $ovl1/enabled
287+
288+echo "1" > $tv/enabled
289+
290+After this the configuration looks like (only relevant parts shown):
291+
292+FB0 +-- GFX ---- LCD ---- LCD
293+ \- VID1 ---- TV ---- TV
294+
295+Misc notes
296+----------
297+
298+OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator.
299+
300+Using DSI DPLL to generate pixel clock it is possible produce the pixel clock
301+of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI.
302+
303+Rotation and mirroring currently only supports RGB565 and RGB8888 modes. VRFB
304+does not support mirroring.
305+
306+VRFB rotation requires much more memory than non-rotated framebuffer, so you
307+probably need to increase your vram setting before using VRFB rotation. Also,
308+many applications may not work with VRFB if they do not pay attention to all
309+framebuffer parameters.
310+
311+Kernel boot arguments
312+---------------------
313+
314+vram=<size>
315+ - Amount of total VRAM to preallocate. For example, "10M". omapfb
316+ allocates memory for framebuffers from VRAM.
317+
318+omapfb.mode=<display>:<mode>[,...]
319+ - Default video mode for specified displays. For example,
320+ "dvi:800x400MR-24@60". See drivers/video/modedb.c.
321+ There are also two special modes: "pal" and "ntsc" that
322+ can be used to tv out.
323+
324+omapfb.vram=<fbnum>:<size>[@<physaddr>][,...]
325+ - VRAM allocated for a framebuffer. Normally omapfb allocates vram
326+ depending on the display size. With this you can manually allocate
327+ more or define the physical address of each framebuffer. For example,
328+ "1:4M" to allocate 4M for fb1.
329+
330+omapfb.debug=<y|n>
331+ - Enable debug printing. You have to have OMAPFB debug support enabled
332+ in kernel config.
333+
334+omapfb.test=<y|n>
335+ - Draw test pattern to framebuffer whenever framebuffer settings change.
336+ You need to have OMAPFB debug support enabled in kernel config.
337+
338+omapfb.vrfb=<y|n>
339+ - Use VRFB rotation for all framebuffers.
340+
341+omapfb.rotate=<angle>
342+ - Default rotation applied to all framebuffers.
343+ 0 - 0 degree rotation
344+ 1 - 90 degree rotation
345+ 2 - 180 degree rotation
346+ 3 - 270 degree rotation
347+
348+omapfb.mirror=<y|n>
349+ - Default mirror for all framebuffers. Only works with DMA rotation.
350+
351+omapdss.def_disp=<display>
352+ - Name of default display, to which all overlays will be connected.
353+ Common examples are "lcd" or "tv".
354+
355+omapdss.debug=<y|n>
356+ - Enable debug printing. You have to have DSS debug support enabled in
357+ kernel config.
358+
359+TODO
360+----
361+
362+DSS locking
363+
364+Error checking
365+- Lots of checks are missing or implemented just as BUG()
366+
367+System DMA update for DSI
368+- Can be used for RGB16 and RGB24P modes. Probably not for RGB24U (how
369+ to skip the empty byte?)
370+
371+OMAP1 support
372+- Not sure if needed
373+
374diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
375index 3ebc09e..e6146b2 100644
376--- a/arch/arm/plat-omap/Makefile
377+++ b/arch/arm/plat-omap/Makefile
378@@ -4,7 +4,7 @@
379
380 # Common support
381 obj-y := common.o sram.o clock.o devices.o dma.o mux.o gpio.o \
382- usb.o fb.o io.o
383+ usb.o fb.o vram.o vrfb.o io.o
384 obj-m :=
385 obj-n :=
386 obj- :=
387diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
388new file mode 100644
389index 0000000..6288353
390--- /dev/null
391+++ b/arch/arm/plat-omap/include/mach/display.h
392@@ -0,0 +1,520 @@
393+/*
394+ * linux/include/asm-arm/arch-omap/display.h
395+ *
396+ * Copyright (C) 2008 Nokia Corporation
397+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
398+ *
399+ * This program is free software; you can redistribute it and/or modify it
400+ * under the terms of the GNU General Public License version 2 as published by
401+ * the Free Software Foundation.
402+ *
403+ * This program is distributed in the hope that it will be useful, but WITHOUT
404+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
405+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
406+ * more details.
407+ *
408+ * You should have received a copy of the GNU General Public License along with
409+ * this program. If not, see <http://www.gnu.org/licenses/>.
410+ */
411+
412+#ifndef __ASM_ARCH_OMAP_DISPLAY_H
413+#define __ASM_ARCH_OMAP_DISPLAY_H
414+
415+#include <linux/list.h>
416+#include <linux/kobject.h>
417+#include <asm/atomic.h>
418+
419+#define DISPC_IRQ_FRAMEDONE (1 << 0)
420+#define DISPC_IRQ_VSYNC (1 << 1)
421+#define DISPC_IRQ_EVSYNC_EVEN (1 << 2)
422+#define DISPC_IRQ_EVSYNC_ODD (1 << 3)
423+#define DISPC_IRQ_ACBIAS_COUNT_STAT (1 << 4)
424+#define DISPC_IRQ_PROG_LINE_NUM (1 << 5)
425+#define DISPC_IRQ_GFX_FIFO_UNDERFLOW (1 << 6)
426+#define DISPC_IRQ_GFX_END_WIN (1 << 7)
427+#define DISPC_IRQ_PAL_GAMMA_MASK (1 << 8)
428+#define DISPC_IRQ_OCP_ERR (1 << 9)
429+#define DISPC_IRQ_VID1_FIFO_UNDERFLOW (1 << 10)
430+#define DISPC_IRQ_VID1_END_WIN (1 << 11)
431+#define DISPC_IRQ_VID2_FIFO_UNDERFLOW (1 << 12)
432+#define DISPC_IRQ_VID2_END_WIN (1 << 13)
433+#define DISPC_IRQ_SYNC_LOST (1 << 14)
434+#define DISPC_IRQ_SYNC_LOST_DIGIT (1 << 15)
435+#define DISPC_IRQ_WAKEUP (1 << 16)
436+
437+enum omap_display_type {
438+ OMAP_DISPLAY_TYPE_NONE = 0,
439+ OMAP_DISPLAY_TYPE_DPI = 1 << 0,
440+ OMAP_DISPLAY_TYPE_DBI = 1 << 1,
441+ OMAP_DISPLAY_TYPE_SDI = 1 << 2,
442+ OMAP_DISPLAY_TYPE_DSI = 1 << 3,
443+ OMAP_DISPLAY_TYPE_VENC = 1 << 4,
444+};
445+
446+enum omap_plane {
447+ OMAP_DSS_GFX = 0,
448+ OMAP_DSS_VIDEO1 = 1,
449+ OMAP_DSS_VIDEO2 = 2
450+};
451+
452+enum omap_channel {
453+ OMAP_DSS_CHANNEL_LCD = 0,
454+ OMAP_DSS_CHANNEL_DIGIT = 1,
455+};
456+
457+enum omap_color_mode {
458+ OMAP_DSS_COLOR_CLUT1 = 1 << 0, /* BITMAP 1 */
459+ OMAP_DSS_COLOR_CLUT2 = 1 << 1, /* BITMAP 2 */
460+ OMAP_DSS_COLOR_CLUT4 = 1 << 2, /* BITMAP 4 */
461+ OMAP_DSS_COLOR_CLUT8 = 1 << 3, /* BITMAP 8 */
462+ OMAP_DSS_COLOR_RGB12U = 1 << 4, /* RGB12, 16-bit container */
463+ OMAP_DSS_COLOR_ARGB16 = 1 << 5, /* ARGB16 */
464+ OMAP_DSS_COLOR_RGB16 = 1 << 6, /* RGB16 */
465+ OMAP_DSS_COLOR_RGB24U = 1 << 7, /* RGB24, 32-bit container */
466+ OMAP_DSS_COLOR_RGB24P = 1 << 8, /* RGB24, 24-bit container */
467+ OMAP_DSS_COLOR_YUV2 = 1 << 9, /* YUV2 4:2:2 co-sited */
468+ OMAP_DSS_COLOR_UYVY = 1 << 10, /* UYVY 4:2:2 co-sited */
469+ OMAP_DSS_COLOR_ARGB32 = 1 << 11, /* ARGB32 */
470+ OMAP_DSS_COLOR_RGBA32 = 1 << 12, /* RGBA32 */
471+ OMAP_DSS_COLOR_RGBX32 = 1 << 13, /* RGBx32 */
472+
473+ OMAP_DSS_COLOR_GFX_OMAP3 =
474+ OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
475+ OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
476+ OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
477+ OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
478+ OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
479+ OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
480+
481+ OMAP_DSS_COLOR_VID_OMAP3 =
482+ OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
483+ OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
484+ OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
485+ OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 |
486+ OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
487+};
488+
489+enum omap_lcd_display_type {
490+ OMAP_DSS_LCD_DISPLAY_STN,
491+ OMAP_DSS_LCD_DISPLAY_TFT,
492+};
493+
494+enum omap_dss_load_mode {
495+ OMAP_DSS_LOAD_CLUT_AND_FRAME = 0,
496+ OMAP_DSS_LOAD_CLUT_ONLY = 1,
497+ OMAP_DSS_LOAD_FRAME_ONLY = 2,
498+ OMAP_DSS_LOAD_CLUT_ONCE_FRAME = 3,
499+};
500+
501+enum omap_dss_color_key_type {
502+ OMAP_DSS_COLOR_KEY_GFX_DST = 0,
503+ OMAP_DSS_COLOR_KEY_VID_SRC = 1,
504+};
505+
506+enum omap_rfbi_te_mode {
507+ OMAP_DSS_RFBI_TE_MODE_1 = 1,
508+ OMAP_DSS_RFBI_TE_MODE_2 = 2,
509+};
510+
511+enum omap_panel_config {
512+ OMAP_DSS_LCD_IVS = 1<<0,
513+ OMAP_DSS_LCD_IHS = 1<<1,
514+ OMAP_DSS_LCD_IPC = 1<<2,
515+ OMAP_DSS_LCD_IEO = 1<<3,
516+ OMAP_DSS_LCD_RF = 1<<4,
517+ OMAP_DSS_LCD_ONOFF = 1<<5,
518+
519+ OMAP_DSS_LCD_TFT = 1<<20,
520+};
521+
522+enum omap_dss_venc_type {
523+ OMAP_DSS_VENC_TYPE_COMPOSITE,
524+ OMAP_DSS_VENC_TYPE_SVIDEO,
525+};
526+
527+struct omap_display;
528+struct omap_panel;
529+struct omap_ctrl;
530+
531+/* RFBI */
532+
533+struct rfbi_timings {
534+ int cs_on_time;
535+ int cs_off_time;
536+ int we_on_time;
537+ int we_off_time;
538+ int re_on_time;
539+ int re_off_time;
540+ int we_cycle_time;
541+ int re_cycle_time;
542+ int cs_pulse_width;
543+ int access_time;
544+
545+ int clk_div;
546+
547+ u32 tim[5]; /* set by rfbi_convert_timings() */
548+
549+ int converted;
550+};
551+
552+void omap_rfbi_write_command(const void *buf, u32 len);
553+void omap_rfbi_read_data(void *buf, u32 len);
554+void omap_rfbi_write_data(const void *buf, u32 len);
555+void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
556+ u16 x, u16 y,
557+ u16 w, u16 h);
558+int omap_rfbi_enable_te(bool enable, unsigned line);
559+int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
560+ unsigned hs_pulse_time, unsigned vs_pulse_time,
561+ int hs_pol_inv, int vs_pol_inv, int extif_div);
562+
563+/* DSI */
564+int dsi_vc_dcs_write(int channel, u8 *data, int len);
565+int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len);
566+int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen);
567+int dsi_vc_set_max_rx_packet_size(int channel, u16 len);
568+int dsi_vc_send_null(int channel);
569+
570+/* Board specific data */
571+struct omap_dss_display_config {
572+ enum omap_display_type type;
573+
574+ union {
575+ struct {
576+ u8 data_lines;
577+ } dpi;
578+
579+ struct {
580+ u8 channel;
581+ u8 data_lines;
582+ } rfbi;
583+
584+ struct {
585+ u8 datapairs;
586+ } sdi;
587+
588+ struct {
589+ u8 clk_lane;
590+ u8 clk_pol;
591+ u8 data1_lane;
592+ u8 data1_pol;
593+ u8 data2_lane;
594+ u8 data2_pol;
595+ unsigned long ddr_clk_hz;
596+ } dsi;
597+
598+ struct {
599+ enum omap_dss_venc_type type;
600+ } venc;
601+ } u;
602+
603+ int panel_reset_gpio;
604+ int ctrl_reset_gpio;
605+
606+ const char *name; /* for debug */
607+ const char *ctrl_name;
608+ const char *panel_name;
609+
610+ void *panel_data;
611+ void *ctrl_data;
612+
613+ /* platform specific enable/disable */
614+ int (*panel_enable)(struct omap_display *display);
615+ void (*panel_disable)(struct omap_display *display);
616+ int (*ctrl_enable)(struct omap_display *display);
617+ void (*ctrl_disable)(struct omap_display *display);
618+ int (*set_backlight)(struct omap_display *display,
619+ int level);
620+};
621+
622+struct device;
623+
624+/* Board specific data */
625+struct omap_dss_board_info {
626+ unsigned (*get_last_off_on_transaction_id)(struct device *dev);
627+ int (*dsi_power_up)(void);
628+ void (*dsi_power_down)(void);
629+ int num_displays;
630+ struct omap_dss_display_config *displays[];
631+};
632+
633+struct omap_ctrl {
634+ struct module *owner;
635+
636+ const char *name;
637+
638+ int (*init)(struct omap_display *display);
639+ void (*cleanup)(struct omap_display *display);
640+ int (*enable)(struct omap_display *display);
641+ void (*disable)(struct omap_display *display);
642+ int (*suspend)(struct omap_display *display);
643+ int (*resume)(struct omap_display *display);
644+ void (*setup_update)(struct omap_display *display,
645+ u16 x, u16 y, u16 w, u16 h);
646+
647+ int (*enable_te)(struct omap_display *display, bool enable);
648+
649+ u8 (*get_rotate)(struct omap_display *display);
650+ int (*set_rotate)(struct omap_display *display, u8 rotate);
651+
652+ bool (*get_mirror)(struct omap_display *display);
653+ int (*set_mirror)(struct omap_display *display, bool enable);
654+
655+ int (*run_test)(struct omap_display *display, int test);
656+ int (*memory_read)(struct omap_display *display,
657+ void *buf, size_t size,
658+ u16 x, u16 y, u16 w, u16 h);
659+
660+ u8 pixel_size;
661+
662+ struct rfbi_timings timings;
663+
664+ void *priv;
665+};
666+
667+struct omap_video_timings {
668+ /* Unit: pixels */
669+ u16 x_res;
670+ /* Unit: pixels */
671+ u16 y_res;
672+ /* Unit: KHz */
673+ u32 pixel_clock;
674+ /* Unit: pixel clocks */
675+ u16 hsw; /* Horizontal synchronization pulse width */
676+ /* Unit: pixel clocks */
677+ u16 hfp; /* Horizontal front porch */
678+ /* Unit: pixel clocks */
679+ u16 hbp; /* Horizontal back porch */
680+ /* Unit: line clocks */
681+ u16 vsw; /* Vertical synchronization pulse width */
682+ /* Unit: line clocks */
683+ u16 vfp; /* Vertical front porch */
684+ /* Unit: line clocks */
685+ u16 vbp; /* Vertical back porch */
686+
687+};
688+
689+#ifdef CONFIG_OMAP2_DSS_VENC
690+/* Hardcoded timings for tv modes. Venc only uses these to
691+ * identify the mode, and does not actually use the configs
692+ * itself. However, the configs should be something that
693+ * a normal monitor can also show */
694+const extern struct omap_video_timings omap_dss_pal_timings;
695+const extern struct omap_video_timings omap_dss_ntsc_timings;
696+#endif
697+
698+struct omap_panel {
699+ struct module *owner;
700+
701+ const char *name;
702+
703+ int (*init)(struct omap_display *display);
704+ void (*cleanup)(struct omap_display *display);
705+ int (*remove)(struct omap_display *display);
706+ int (*enable)(struct omap_display *display);
707+ void (*disable)(struct omap_display *display);
708+ int (*suspend)(struct omap_display *display);
709+ int (*resume)(struct omap_display *display);
710+ int (*run_test)(struct omap_display *display, int test);
711+
712+ struct omap_video_timings timings;
713+
714+ int acbi; /* ac-bias pin transitions per interrupt */
715+ /* Unit: line clocks */
716+ int acb; /* ac-bias pin frequency */
717+
718+ enum omap_panel_config config;
719+
720+ u8 recommended_bpp;
721+
722+ void *priv;
723+};
724+
725+/* XXX perhaps this should be removed */
726+enum omap_dss_overlay_managers {
727+ OMAP_DSS_OVL_MGR_LCD,
728+ OMAP_DSS_OVL_MGR_TV,
729+};
730+
731+struct omap_overlay_manager;
732+
733+struct omap_overlay_info {
734+ bool enabled;
735+
736+ u32 paddr;
737+ void __iomem *vaddr;
738+ u16 screen_width;
739+ u16 width;
740+ u16 height;
741+ enum omap_color_mode color_mode;
742+ u8 rotation;
743+ bool mirror;
744+
745+ u16 pos_x;
746+ u16 pos_y;
747+ u16 out_width; /* if 0, out_width == width */
748+ u16 out_height; /* if 0, out_height == height */
749+};
750+
751+enum omap_overlay_caps {
752+ OMAP_DSS_OVL_CAP_SCALE = 1 << 0,
753+ OMAP_DSS_OVL_CAP_DISPC = 1 << 1,
754+};
755+
756+struct omap_overlay {
757+ struct kobject kobj;
758+ struct list_head list;
759+
760+ const char *name;
761+ int id;
762+ struct omap_overlay_manager *manager;
763+ enum omap_color_mode supported_modes;
764+ struct omap_overlay_info info;
765+ enum omap_overlay_caps caps;
766+
767+ int (*set_manager)(struct omap_overlay *ovl,
768+ struct omap_overlay_manager *mgr);
769+ int (*unset_manager)(struct omap_overlay *ovl);
770+
771+ int (*set_overlay_info)(struct omap_overlay *ovl,
772+ struct omap_overlay_info *info);
773+ void (*get_overlay_info)(struct omap_overlay *ovl,
774+ struct omap_overlay_info *info);
775+};
776+
777+enum omap_overlay_manager_caps {
778+ OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0,
779+};
780+
781+struct omap_overlay_manager {
782+ struct kobject kobj;
783+ struct list_head list;
784+
785+ const char *name;
786+ int id;
787+ enum omap_overlay_manager_caps caps;
788+ struct omap_display *display;
789+ int num_overlays;
790+ struct omap_overlay **overlays;
791+ enum omap_display_type supported_displays;
792+
793+ int (*set_display)(struct omap_overlay_manager *mgr,
794+ struct omap_display *display);
795+ int (*unset_display)(struct omap_overlay_manager *mgr);
796+
797+ int (*apply)(struct omap_overlay_manager *mgr);
798+
799+ void (*set_default_color)(struct omap_overlay_manager *mgr, u32 color);
800+ void (*set_trans_key)(struct omap_overlay_manager *mgr,
801+ enum omap_dss_color_key_type type,
802+ u32 trans_key);
803+ void (*enable_trans_key)(struct omap_overlay_manager *mgr,
804+ bool enable);
805+};
806+
807+enum omap_display_caps {
808+ OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0,
809+};
810+
811+enum omap_dss_update_mode {
812+ OMAP_DSS_UPDATE_DISABLED = 0,
813+ OMAP_DSS_UPDATE_AUTO,
814+ OMAP_DSS_UPDATE_MANUAL,
815+};
816+
817+enum omap_dss_display_state {
818+ OMAP_DSS_DISPLAY_DISABLED = 0,
819+ OMAP_DSS_DISPLAY_ACTIVE,
820+ OMAP_DSS_DISPLAY_SUSPENDED,
821+};
822+
823+struct omap_display {
824+ struct kobject kobj;
825+ struct list_head list;
826+
827+ /*atomic_t ref_count;*/
828+ int ref_count;
829+ /* helper variable for driver suspend/resume */
830+ int activate_after_resume;
831+
832+ enum omap_display_type type;
833+ const char *name;
834+
835+ enum omap_display_caps caps;
836+
837+ struct omap_overlay_manager *manager;
838+
839+ enum omap_dss_display_state state;
840+
841+ struct omap_dss_display_config hw_config; /* board specific data */
842+ struct omap_ctrl *ctrl; /* static common data */
843+ struct omap_panel *panel; /* static common data */
844+
845+ int (*enable)(struct omap_display *display);
846+ void (*disable)(struct omap_display *display);
847+
848+ int (*suspend)(struct omap_display *display);
849+ int (*resume)(struct omap_display *display);
850+
851+ void (*get_resolution)(struct omap_display *display,
852+ u16 *xres, u16 *yres);
853+ int (*get_recommended_bpp)(struct omap_display *display);
854+
855+ int (*check_timings)(struct omap_display *display,
856+ struct omap_video_timings *timings);
857+ void (*set_timings)(struct omap_display *display,
858+ struct omap_video_timings *timings);
859+ void (*get_timings)(struct omap_display *display,
860+ struct omap_video_timings *timings);
861+ int (*update)(struct omap_display *display,
862+ u16 x, u16 y, u16 w, u16 h);
863+ int (*sync)(struct omap_display *display);
864+ int (*wait_vsync)(struct omap_display *display);
865+
866+ int (*set_update_mode)(struct omap_display *display,
867+ enum omap_dss_update_mode);
868+ enum omap_dss_update_mode (*get_update_mode)
869+ (struct omap_display *display);
870+
871+ int (*enable_te)(struct omap_display *display, bool enable);
872+ int (*get_te)(struct omap_display *display);
873+
874+ u8 (*get_rotate)(struct omap_display *display);
875+ int (*set_rotate)(struct omap_display *display, u8 rotate);
876+
877+ bool (*get_mirror)(struct omap_display *display);
878+ int (*set_mirror)(struct omap_display *display, bool enable);
879+
880+ int (*run_test)(struct omap_display *display, int test);
881+ int (*memory_read)(struct omap_display *display,
882+ void *buf, size_t size,
883+ u16 x, u16 y, u16 w, u16 h);
884+
885+ void (*configure_overlay)(struct omap_overlay *overlay);
886+};
887+
888+int omap_dss_get_num_displays(void);
889+struct omap_display *omap_dss_get_display(int no);
890+void omap_dss_put_display(struct omap_display *display);
891+
892+void omap_dss_register_ctrl(struct omap_ctrl *ctrl);
893+void omap_dss_unregister_ctrl(struct omap_ctrl *ctrl);
894+
895+void omap_dss_register_panel(struct omap_panel *panel);
896+void omap_dss_unregister_panel(struct omap_panel *panel);
897+
898+int omap_dss_get_num_overlay_managers(void);
899+struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
900+
901+int omap_dss_get_num_overlays(void);
902+struct omap_overlay *omap_dss_get_overlay(int num);
903+
904+typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
905+int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
906+int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
907+
908+int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout);
909+int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
910+ unsigned long timeout);
911+
912+#endif
913diff --git a/arch/arm/plat-omap/include/mach/vram.h b/arch/arm/plat-omap/include/mach/vram.h
914new file mode 100644
915index 0000000..f176562
916--- /dev/null
917+++ b/arch/arm/plat-omap/include/mach/vram.h
918@@ -0,0 +1,33 @@
919+/*
920+ * File: arch/arm/plat-omap/include/mach/vram.h
921+ *
922+ * Copyright (C) 2009 Nokia Corporation
923+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
924+ *
925+ * This program is free software; you can redistribute it and/or modify it
926+ * under the terms of the GNU General Public License as published by the
927+ * Free Software Foundation; either version 2 of the License, or (at your
928+ * option) any later version.
929+ *
930+ * This program is distributed in the hope that it will be useful, but
931+ * WITHOUT ANY WARRANTY; without even the implied warranty of
932+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
933+ * General Public License for more details.
934+ *
935+ * You should have received a copy of the GNU General Public License along
936+ * with this program; if not, write to the Free Software Foundation, Inc.,
937+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
938+ */
939+
940+#ifndef __OMAPVRAM_H
941+#define __OMAPVRAM_H
942+
943+#include <asm/types.h>
944+
945+extern int omap_vram_free(unsigned long paddr, size_t size);
946+extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr);
947+extern int omap_vram_reserve(unsigned long paddr, size_t size);
948+extern void omap2_set_sdram_vram(u32 size, u32 start);
949+extern void omap2_set_sram_vram(u32 size, u32 start);
950+
951+#endif
952diff --git a/arch/arm/plat-omap/include/mach/vrfb.h b/arch/arm/plat-omap/include/mach/vrfb.h
953new file mode 100644
954index 0000000..2047862
955--- /dev/null
956+++ b/arch/arm/plat-omap/include/mach/vrfb.h
957@@ -0,0 +1,47 @@
958+/*
959+ * File: arch/arm/plat-omap/include/mach/vrfb.h
960+ *
961+ * VRFB
962+ *
963+ * Copyright (C) 2009 Nokia Corporation
964+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
965+ *
966+ * This program is free software; you can redistribute it and/or modify it
967+ * under the terms of the GNU General Public License as published by the
968+ * Free Software Foundation; either version 2 of the License, or (at your
969+ * option) any later version.
970+ *
971+ * This program is distributed in the hope that it will be useful, but
972+ * WITHOUT ANY WARRANTY; without even the implied warranty of
973+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
974+ * General Public License for more details.
975+ *
976+ * You should have received a copy of the GNU General Public License along
977+ * with this program; if not, write to the Free Software Foundation, Inc.,
978+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
979+ */
980+
981+#ifndef __VRFB_H
982+#define __VRFB_H
983+
984+#define OMAP_VRFB_LINE_LEN 2048
985+
986+struct vrfb
987+{
988+ u8 context;
989+ void __iomem *vaddr[4];
990+ unsigned long paddr[4];
991+ u16 xoffset;
992+ u16 yoffset;
993+ u8 bytespp;
994+};
995+
996+extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
997+extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
998+extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
999+ u8 bytespp);
1000+extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
1001+ u16 width, u16 height,
1002+ u8 bytespp);
1003+
1004+#endif /* __VRFB_H */
1005diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c
1006new file mode 100644
1007index 0000000..f24a110
1008--- /dev/null
1009+++ b/arch/arm/plat-omap/vram.c
1010@@ -0,0 +1,615 @@
1011+/*
1012+ * linux/arch/arm/plat-omap/vram.c
1013+ *
1014+ * Copyright (C) 2008 Nokia Corporation
1015+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
1016+ *
1017+ * Some code and ideas taken from drivers/video/omap/ driver
1018+ * by Imre Deak.
1019+ *
1020+ * This program is free software; you can redistribute it and/or modify it
1021+ * under the terms of the GNU General Public License version 2 as published by
1022+ * the Free Software Foundation.
1023+ *
1024+ * This program is distributed in the hope that it will be useful, but WITHOUT
1025+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1026+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
1027+ * more details.
1028+ *
1029+ * You should have received a copy of the GNU General Public License along with
1030+ * this program. If not, see <http://www.gnu.org/licenses/>.
1031+ */
1032+
1033+/*#define DEBUG*/
1034+
1035+#include <linux/vmalloc.h>
1036+#include <linux/kernel.h>
1037+#include <linux/mm.h>
1038+#include <linux/list.h>
1039+#include <linux/dma-mapping.h>
1040+#include <linux/proc_fs.h>
1041+#include <linux/seq_file.h>
1042+#include <linux/bootmem.h>
1043+#include <linux/omapfb.h>
1044+
1045+#include <asm/setup.h>
1046+
1047+#include <mach/sram.h>
1048+#include <mach/vram.h>
1049+
1050+#ifdef DEBUG
1051+#define DBG(format, ...) printk(KERN_DEBUG "VRAM: " format, ## __VA_ARGS__)
1052+#else
1053+#define DBG(format, ...)
1054+#endif
1055+
1056+#define OMAP2_SRAM_START 0x40200000
1057+/* Maximum size, in reality this is smaller if SRAM is partially locked. */
1058+#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */
1059+
1060+#define REG_MAP_SIZE(_page_cnt) \
1061+ ((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8)
1062+#define REG_MAP_PTR(_rg, _page_nr) \
1063+ (((_rg)->map) + (_page_nr) / (sizeof(unsigned long) * 8))
1064+#define REG_MAP_MASK(_page_nr) \
1065+ (1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1)))
1066+
1067+#if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
1068+
1069+/* postponed regions are used to temporarily store region information at boot
1070+ * time when we cannot yet allocate the region list */
1071+#define MAX_POSTPONED_REGIONS 10
1072+
1073+static int postponed_cnt __initdata;
1074+static struct {
1075+ unsigned long paddr;
1076+ size_t size;
1077+} postponed_regions[MAX_POSTPONED_REGIONS] __initdata;
1078+
1079+struct vram_alloc {
1080+ struct list_head list;
1081+ unsigned long paddr;
1082+ unsigned pages;
1083+};
1084+
1085+struct vram_region {
1086+ struct list_head list;
1087+ struct list_head alloc_list;
1088+ unsigned long paddr;
1089+ unsigned pages;
1090+};
1091+
1092+static DEFINE_MUTEX(region_mutex);
1093+static LIST_HEAD(region_list);
1094+
1095+static inline int region_mem_type(unsigned long paddr)
1096+{
1097+ if (paddr >= OMAP2_SRAM_START &&
1098+ paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
1099+ return OMAPFB_MEMTYPE_SRAM;
1100+ else
1101+ return OMAPFB_MEMTYPE_SDRAM;
1102+}
1103+
1104+static struct vram_region *omap_vram_create_region(unsigned long paddr,
1105+ unsigned pages)
1106+{
1107+ struct vram_region *rm;
1108+
1109+ rm = kzalloc(sizeof(*rm), GFP_KERNEL);
1110+
1111+ if (rm) {
1112+ INIT_LIST_HEAD(&rm->alloc_list);
1113+ rm->paddr = paddr;
1114+ rm->pages = pages;
1115+ }
1116+
1117+ return rm;
1118+}
1119+
1120+#if 0
1121+static void omap_vram_free_region(struct vram_region *vr)
1122+{
1123+ list_del(&vr->list);
1124+ kfree(vr);
1125+}
1126+#endif
1127+
1128+static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr,
1129+ unsigned long paddr, unsigned pages)
1130+{
1131+ struct vram_alloc *va;
1132+ struct vram_alloc *new;
1133+
1134+ new = kzalloc(sizeof(*va), GFP_KERNEL);
1135+
1136+ if (!new)
1137+ return NULL;
1138+
1139+ new->paddr = paddr;
1140+ new->pages = pages;
1141+
1142+ list_for_each_entry(va, &vr->alloc_list, list) {
1143+ if (va->paddr > new->paddr)
1144+ break;
1145+ }
1146+
1147+ list_add_tail(&new->list, &va->list);
1148+
1149+ return new;
1150+}
1151+
1152+static void omap_vram_free_allocation(struct vram_alloc *va)
1153+{
1154+ list_del(&va->list);
1155+ kfree(va);
1156+}
1157+
1158+static __init int omap_vram_add_region_postponed(unsigned long paddr,
1159+ size_t size)
1160+{
1161+ if (postponed_cnt == MAX_POSTPONED_REGIONS)
1162+ return -ENOMEM;
1163+
1164+ postponed_regions[postponed_cnt].paddr = paddr;
1165+ postponed_regions[postponed_cnt].size = size;
1166+
1167+ ++postponed_cnt;
1168+
1169+ return 0;
1170+}
1171+
1172+/* add/remove_region can be exported if there's need to add/remove regions
1173+ * runtime */
1174+static int omap_vram_add_region(unsigned long paddr, size_t size)
1175+{
1176+ struct vram_region *rm;
1177+ unsigned pages;
1178+
1179+ DBG("adding region paddr %08lx size %d\n",
1180+ paddr, size);
1181+
1182+ size &= PAGE_MASK;
1183+ pages = size >> PAGE_SHIFT;
1184+
1185+ rm = omap_vram_create_region(paddr, pages);
1186+ if (rm == NULL)
1187+ return -ENOMEM;
1188+
1189+ list_add(&rm->list, &region_list);
1190+
1191+ return 0;
1192+}
1193+
1194+int omap_vram_free(unsigned long paddr, size_t size)
1195+{
1196+ struct vram_region *rm;
1197+ struct vram_alloc *alloc;
1198+ unsigned start, end;
1199+
1200+ DBG("free mem paddr %08lx size %d\n", paddr, size);
1201+
1202+ size = PAGE_ALIGN(size);
1203+
1204+ mutex_lock(&region_mutex);
1205+
1206+ list_for_each_entry(rm, &region_list, list) {
1207+ list_for_each_entry(alloc, &rm->alloc_list, list) {
1208+ start = alloc->paddr;
1209+ end = alloc->paddr + (alloc->pages >> PAGE_SHIFT);
1210+
1211+ if (start >= paddr && end < paddr + size)
1212+ goto found;
1213+ }
1214+ }
1215+
1216+ mutex_unlock(&region_mutex);
1217+ return -EINVAL;
1218+
1219+found:
1220+ omap_vram_free_allocation(alloc);
1221+
1222+ mutex_unlock(&region_mutex);
1223+ return 0;
1224+}
1225+EXPORT_SYMBOL(omap_vram_free);
1226+
1227+static int _omap_vram_reserve(unsigned long paddr, unsigned pages)
1228+{
1229+ struct vram_region *rm;
1230+ struct vram_alloc *alloc;
1231+ size_t size;
1232+
1233+ size = pages << PAGE_SHIFT;
1234+
1235+ list_for_each_entry(rm, &region_list, list) {
1236+ unsigned long start, end;
1237+
1238+ DBG("checking region %lx %d\n", rm->paddr, rm->pages);
1239+
1240+ if (region_mem_type(rm->paddr) != region_mem_type(paddr))
1241+ continue;
1242+
1243+ start = rm->paddr;
1244+ end = start + (rm->pages << PAGE_SHIFT) - 1;
1245+ if (start > paddr || end < paddr + size - 1)
1246+ continue;
1247+
1248+ DBG("block ok, checking allocs\n");
1249+
1250+ list_for_each_entry(alloc, &rm->alloc_list, list) {
1251+ end = alloc->paddr - 1;
1252+
1253+ if (start <= paddr && end >= paddr + size - 1)
1254+ goto found;
1255+
1256+ start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
1257+ }
1258+
1259+ end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1;
1260+
1261+ if (!(start <= paddr && end >= paddr + size - 1))
1262+ continue;
1263+found:
1264+ DBG("FOUND area start %lx, end %lx\n", start, end);
1265+
1266+ if (omap_vram_create_allocation(rm, paddr, pages) == NULL)
1267+ return -ENOMEM;
1268+
1269+ return 0;
1270+ }
1271+
1272+ return -ENOMEM;
1273+}
1274+
1275+int omap_vram_reserve(unsigned long paddr, size_t size)
1276+{
1277+ unsigned pages;
1278+ int r;
1279+
1280+ DBG("reserve mem paddr %08lx size %d\n", paddr, size);
1281+
1282+ size = PAGE_ALIGN(size);
1283+ pages = size >> PAGE_SHIFT;
1284+
1285+ mutex_lock(&region_mutex);
1286+
1287+ r = _omap_vram_reserve(paddr, pages);
1288+
1289+ mutex_unlock(&region_mutex);
1290+
1291+ return r;
1292+}
1293+EXPORT_SYMBOL(omap_vram_reserve);
1294+
1295+static int _omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr)
1296+{
1297+ struct vram_region *rm;
1298+ struct vram_alloc *alloc;
1299+
1300+ list_for_each_entry(rm, &region_list, list) {
1301+ unsigned long start, end;
1302+
1303+ DBG("checking region %lx %d\n", rm->paddr, rm->pages);
1304+
1305+ if (region_mem_type(rm->paddr) != mtype)
1306+ continue;
1307+
1308+ start = rm->paddr;
1309+
1310+ list_for_each_entry(alloc, &rm->alloc_list, list) {
1311+ end = alloc->paddr;
1312+
1313+ if (end - start >= pages << PAGE_SHIFT)
1314+ goto found;
1315+
1316+ start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
1317+ }
1318+
1319+ end = rm->paddr + (rm->pages << PAGE_SHIFT);
1320+found:
1321+ if (end - start < pages << PAGE_SHIFT)
1322+ continue;
1323+
1324+ DBG("FOUND %lx, end %lx\n", start, end);
1325+
1326+ alloc = omap_vram_create_allocation(rm, start, pages);
1327+ if (alloc == NULL)
1328+ return -ENOMEM;
1329+
1330+ *paddr = start;
1331+
1332+ return 0;
1333+ }
1334+
1335+ return -ENOMEM;
1336+}
1337+
1338+int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr)
1339+{
1340+ unsigned pages;
1341+ int r;
1342+
1343+ BUG_ON(mtype > OMAPFB_MEMTYPE_MAX || !size);
1344+
1345+ DBG("alloc mem type %d size %d\n", mtype, size);
1346+
1347+ size = PAGE_ALIGN(size);
1348+ pages = size >> PAGE_SHIFT;
1349+
1350+ mutex_lock(&region_mutex);
1351+
1352+ r = _omap_vram_alloc(mtype, pages, paddr);
1353+
1354+ mutex_unlock(&region_mutex);
1355+
1356+ return r;
1357+}
1358+EXPORT_SYMBOL(omap_vram_alloc);
1359+
1360+#ifdef CONFIG_PROC_FS
1361+static void *r_next(struct seq_file *m, void *v, loff_t *pos)
1362+{
1363+ struct list_head *l = v;
1364+
1365+ (*pos)++;
1366+
1367+ if (list_is_last(l, &region_list))
1368+ return NULL;
1369+
1370+ return l->next;
1371+}
1372+
1373+static void *r_start(struct seq_file *m, loff_t *pos)
1374+{
1375+ loff_t p = *pos;
1376+ struct list_head *l = &region_list;
1377+
1378+ mutex_lock(&region_mutex);
1379+
1380+ do {
1381+ l = l->next;
1382+ if (l == &region_list)
1383+ return NULL;
1384+ } while (p--);
1385+
1386+ return l;
1387+}
1388+
1389+static void r_stop(struct seq_file *m, void *v)
1390+{
1391+ mutex_unlock(&region_mutex);
1392+}
1393+
1394+static int r_show(struct seq_file *m, void *v)
1395+{
1396+ struct vram_region *vr;
1397+ struct vram_alloc *va;
1398+ unsigned size;
1399+
1400+ vr = list_entry(v, struct vram_region, list);
1401+
1402+ size = vr->pages << PAGE_SHIFT;
1403+
1404+ seq_printf(m, "%08lx-%08lx (%d bytes)\n",
1405+ vr->paddr, vr->paddr + size - 1,
1406+ size);
1407+
1408+ list_for_each_entry(va, &vr->alloc_list, list) {
1409+ size = va->pages << PAGE_SHIFT;
1410+ seq_printf(m, " %08lx-%08lx (%d bytes)\n",
1411+ va->paddr, va->paddr + size - 1,
1412+ size);
1413+ }
1414+
1415+
1416+
1417+ return 0;
1418+}
1419+
1420+static const struct seq_operations resource_op = {
1421+ .start = r_start,
1422+ .next = r_next,
1423+ .stop = r_stop,
1424+ .show = r_show,
1425+};
1426+
1427+static int vram_open(struct inode *inode, struct file *file)
1428+{
1429+ return seq_open(file, &resource_op);
1430+}
1431+
1432+static const struct file_operations proc_vram_operations = {
1433+ .open = vram_open,
1434+ .read = seq_read,
1435+ .llseek = seq_lseek,
1436+ .release = seq_release,
1437+};
1438+
1439+static int __init omap_vram_create_proc(void)
1440+{
1441+ proc_create("omap-vram", 0, NULL, &proc_vram_operations);
1442+
1443+ return 0;
1444+}
1445+#endif
1446+
1447+static __init int omap_vram_init(void)
1448+{
1449+ int i, r;
1450+
1451+ for (i = 0; i < postponed_cnt; i++)
1452+ omap_vram_add_region(postponed_regions[i].paddr,
1453+ postponed_regions[i].size);
1454+
1455+#ifdef CONFIG_PROC_FS
1456+ r = omap_vram_create_proc();
1457+ if (r)
1458+ return -ENOMEM;
1459+#endif
1460+
1461+ return 0;
1462+}
1463+
1464+arch_initcall(omap_vram_init);
1465+
1466+/* boottime vram alloc stuff */
1467+
1468+/* set from board file */
1469+static u32 omapfb_sram_vram_start __initdata;
1470+static u32 omapfb_sram_vram_size __initdata;
1471+
1472+/* set from board file */
1473+static u32 omapfb_sdram_vram_start __initdata;
1474+static u32 omapfb_sdram_vram_size __initdata;
1475+
1476+/* set from kernel cmdline */
1477+static u32 omapfb_def_sdram_vram_size __initdata;
1478+static u32 omapfb_def_sdram_vram_start __initdata;
1479+
1480+static void __init omapfb_early_vram(char **p)
1481+{
1482+ omapfb_def_sdram_vram_size = memparse(*p, p);
1483+ if (**p == ',')
1484+ omapfb_def_sdram_vram_start = simple_strtoul((*p) + 1, p, 16);
1485+
1486+ printk("omapfb_early_vram, %d, 0x%x\n",
1487+ omapfb_def_sdram_vram_size,
1488+ omapfb_def_sdram_vram_start);
1489+}
1490+__early_param("vram=", omapfb_early_vram);
1491+
1492+/*
1493+ * Called from map_io. We need to call to this early enough so that we
1494+ * can reserve the fixed SDRAM regions before VM could get hold of them.
1495+ */
1496+void __init omapfb_reserve_sdram(void)
1497+{
1498+ struct bootmem_data *bdata;
1499+ unsigned long sdram_start, sdram_size;
1500+ u32 paddr;
1501+ u32 size = 0;
1502+
1503+ /* cmdline arg overrides the board file definition */
1504+ if (omapfb_def_sdram_vram_size) {
1505+ size = omapfb_def_sdram_vram_size;
1506+ paddr = omapfb_def_sdram_vram_start;
1507+ }
1508+
1509+ if (!size) {
1510+ size = omapfb_sdram_vram_size;
1511+ paddr = omapfb_sdram_vram_start;
1512+ }
1513+
1514+#ifdef CONFIG_OMAP2_DSS_VRAM_SIZE
1515+ if (!size) {
1516+ size = CONFIG_OMAP2_DSS_VRAM_SIZE * 1024 * 1024;
1517+ paddr = 0;
1518+ }
1519+#endif
1520+
1521+ if (!size)
1522+ return;
1523+
1524+ size = PAGE_ALIGN(size);
1525+
1526+ bdata = NODE_DATA(0)->bdata;
1527+ sdram_start = bdata->node_min_pfn << PAGE_SHIFT;
1528+ sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start;
1529+
1530+ if (paddr) {
1531+ if ((paddr & ~PAGE_MASK) || paddr < sdram_start ||
1532+ paddr + size > sdram_start + sdram_size) {
1533+ printk(KERN_ERR "Illegal SDRAM region for VRAM\n");
1534+ return;
1535+ }
1536+
1537+ reserve_bootmem(paddr, size, BOOTMEM_DEFAULT);
1538+ } else {
1539+ if (size > sdram_size) {
1540+ printk(KERN_ERR "Illegal SDRAM size for VRAM\n");
1541+ return;
1542+ }
1543+
1544+ paddr = virt_to_phys(alloc_bootmem_pages(size));
1545+ BUG_ON(paddr & ~PAGE_MASK);
1546+ }
1547+
1548+ omap_vram_add_region_postponed(paddr, size);
1549+
1550+ pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
1551+}
1552+
1553+/*
1554+ * Called at sram init time, before anything is pushed to the SRAM stack.
1555+ * Because of the stack scheme, we will allocate everything from the
1556+ * start of the lowest address region to the end of SRAM. This will also
1557+ * include padding for page alignment and possible holes between regions.
1558+ *
1559+ * As opposed to the SDRAM case, we'll also do any dynamic allocations at
1560+ * this point, since the driver built as a module would have problem with
1561+ * freeing / reallocating the regions.
1562+ */
1563+unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
1564+ unsigned long sram_vstart,
1565+ unsigned long sram_size,
1566+ unsigned long pstart_avail,
1567+ unsigned long size_avail)
1568+{
1569+ unsigned long pend_avail;
1570+ unsigned long reserved;
1571+ u32 paddr;
1572+ u32 size;
1573+
1574+ paddr = omapfb_sram_vram_start;
1575+ size = omapfb_sram_vram_size;
1576+
1577+ if (!size)
1578+ return 0;
1579+
1580+ reserved = 0;
1581+ pend_avail = pstart_avail + size_avail;
1582+
1583+ if (!paddr) {
1584+ /* Dynamic allocation */
1585+ if ((size_avail & PAGE_MASK) < size) {
1586+ printk(KERN_ERR "Not enough SRAM for VRAM\n");
1587+ return 0;
1588+ }
1589+ size_avail = (size_avail - size) & PAGE_MASK;
1590+ paddr = pstart_avail + size_avail;
1591+ }
1592+
1593+ if (paddr < sram_pstart ||
1594+ paddr + size > sram_pstart + sram_size) {
1595+ printk(KERN_ERR "Illegal SRAM region for VRAM\n");
1596+ return 0;
1597+ }
1598+
1599+ /* Reserve everything above the start of the region. */
1600+ if (pend_avail - paddr > reserved)
1601+ reserved = pend_avail - paddr;
1602+ size_avail = pend_avail - reserved - pstart_avail;
1603+
1604+ omap_vram_add_region_postponed(paddr, size);
1605+
1606+ if (reserved)
1607+ pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved);
1608+
1609+ return reserved;
1610+}
1611+
1612+void __init omap2_set_sdram_vram(u32 size, u32 start)
1613+{
1614+ omapfb_sdram_vram_start = start;
1615+ omapfb_sdram_vram_size = size;
1616+}
1617+
1618+void __init omap2_set_sram_vram(u32 size, u32 start)
1619+{
1620+ omapfb_sram_vram_start = start;
1621+ omapfb_sram_vram_size = size;
1622+}
1623+
1624+#endif
1625+
1626diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
1627new file mode 100644
1628index 0000000..7e0f8fc
1629--- /dev/null
1630+++ b/arch/arm/plat-omap/vrfb.c
1631@@ -0,0 +1,159 @@
1632+#include <linux/kernel.h>
1633+#include <linux/module.h>
1634+#include <linux/ioport.h>
1635+#include <asm/io.h>
1636+
1637+#include <mach/io.h>
1638+#include <mach/vrfb.h>
1639+
1640+/*#define DEBUG*/
1641+
1642+#ifdef DEBUG
1643+#define DBG(format, ...) printk(KERN_DEBUG "VRFB: " format, ## __VA_ARGS__)
1644+#else
1645+#define DBG(format, ...)
1646+#endif
1647+
1648+#define SMS_ROT_VIRT_BASE(context, rot) \
1649+ (((context >= 4) ? 0xD0000000 : 0x70000000) \
1650+ | 0x4000000 * (context) \
1651+ | 0x1000000 * (rot))
1652+
1653+#define OMAP_VRFB_SIZE (2048 * 2048 * 4)
1654+
1655+#define VRFB_PAGE_WIDTH_EXP 5 /* Assuming SDRAM pagesize= 1024 */
1656+#define VRFB_PAGE_HEIGHT_EXP 5 /* 1024 = 2^5 * 2^5 */
1657+#define VRFB_PAGE_WIDTH (1 << VRFB_PAGE_WIDTH_EXP)
1658+#define VRFB_PAGE_HEIGHT (1 << VRFB_PAGE_HEIGHT_EXP)
1659+#define SMS_IMAGEHEIGHT_OFFSET 16
1660+#define SMS_IMAGEWIDTH_OFFSET 0
1661+#define SMS_PH_OFFSET 8
1662+#define SMS_PW_OFFSET 4
1663+#define SMS_PS_OFFSET 0
1664+
1665+#define OMAP_SMS_BASE 0x6C000000
1666+#define SMS_ROT_CONTROL(context) (OMAP_SMS_BASE + 0x180 + 0x10 * context)
1667+#define SMS_ROT_SIZE(context) (OMAP_SMS_BASE + 0x184 + 0x10 * context)
1668+#define SMS_ROT_PHYSICAL_BA(context) (OMAP_SMS_BASE + 0x188 + 0x10 * context)
1669+
1670+#define VRFB_NUM_CTXS 12
1671+/* bitmap of reserved contexts */
1672+static unsigned ctx_map;
1673+
1674+void omap_vrfb_adjust_size(u16 *width, u16 *height,
1675+ u8 bytespp)
1676+{
1677+ *width = ALIGN(*width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
1678+ *height = ALIGN(*height, VRFB_PAGE_HEIGHT);
1679+}
1680+EXPORT_SYMBOL(omap_vrfb_adjust_size);
1681+
1682+void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
1683+ u16 width, u16 height,
1684+ u8 bytespp)
1685+{
1686+ unsigned pixel_size_exp;
1687+ u16 vrfb_width;
1688+ u16 vrfb_height;
1689+ u8 ctx = vrfb->context;
1690+
1691+ DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d)\n", ctx, paddr,
1692+ width, height, bytespp);
1693+
1694+ if (bytespp == 4)
1695+ pixel_size_exp = 2;
1696+ else if (bytespp == 2)
1697+ pixel_size_exp = 1;
1698+ else
1699+ BUG();
1700+
1701+ vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
1702+ vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT);
1703+
1704+ DBG("vrfb w %u, h %u\n", vrfb_width, vrfb_height);
1705+
1706+ omap_writel(paddr, SMS_ROT_PHYSICAL_BA(ctx));
1707+ omap_writel((vrfb_width << SMS_IMAGEWIDTH_OFFSET) |
1708+ (vrfb_height << SMS_IMAGEHEIGHT_OFFSET),
1709+ SMS_ROT_SIZE(ctx));
1710+
1711+ omap_writel(pixel_size_exp << SMS_PS_OFFSET |
1712+ VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET |
1713+ VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET,
1714+ SMS_ROT_CONTROL(ctx));
1715+
1716+ DBG("vrfb offset pixels %d, %d\n",
1717+ vrfb_width - width, vrfb_height - height);
1718+
1719+ vrfb->xoffset = vrfb_width - width;
1720+ vrfb->yoffset = vrfb_height - height;
1721+ vrfb->bytespp = bytespp;
1722+}
1723+EXPORT_SYMBOL(omap_vrfb_setup);
1724+
1725+void omap_vrfb_release_ctx(struct vrfb *vrfb)
1726+{
1727+ int rot;
1728+
1729+ if (vrfb->context == 0xff)
1730+ return;
1731+
1732+ DBG("release ctx %d\n", vrfb->context);
1733+
1734+ ctx_map &= ~(1 << vrfb->context);
1735+
1736+ for (rot = 0; rot < 4; ++rot) {
1737+ if(vrfb->paddr[rot]) {
1738+ release_mem_region(vrfb->paddr[rot], OMAP_VRFB_SIZE);
1739+ vrfb->paddr[rot] = 0;
1740+ }
1741+ }
1742+
1743+ vrfb->context = 0xff;
1744+}
1745+EXPORT_SYMBOL(omap_vrfb_release_ctx);
1746+
1747+int omap_vrfb_request_ctx(struct vrfb *vrfb)
1748+{
1749+ int rot;
1750+ u32 paddr;
1751+ u8 ctx;
1752+
1753+ DBG("request ctx\n");
1754+
1755+ for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
1756+ if ((ctx_map & (1 << ctx)) == 0)
1757+ break;
1758+
1759+ if (ctx == VRFB_NUM_CTXS) {
1760+ printk(KERN_ERR "vrfb: no free contexts\n");
1761+ return -EBUSY;
1762+ }
1763+
1764+ DBG("found free ctx %d\n", ctx);
1765+
1766+ ctx_map |= 1 << ctx;
1767+
1768+ memset(vrfb, 0, sizeof(*vrfb));
1769+
1770+ vrfb->context = ctx;
1771+
1772+ for (rot = 0; rot < 4; ++rot) {
1773+ paddr = SMS_ROT_VIRT_BASE(ctx, rot);
1774+ if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
1775+ printk(KERN_ERR "vrfb: failed to reserve VRFB "
1776+ "area for ctx %d, rotation %d\n",
1777+ ctx, rot * 90);
1778+ omap_vrfb_release_ctx(vrfb);
1779+ return -ENOMEM;
1780+ }
1781+
1782+ vrfb->paddr[rot] = paddr;
1783+
1784+ DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]);
1785+ }
1786+
1787+ return 0;
1788+}
1789+EXPORT_SYMBOL(omap_vrfb_request_ctx);
1790+
1791diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
1792index fb19803..8b3752b 100644
1793--- a/drivers/video/Kconfig
1794+++ b/drivers/video/Kconfig
1795@@ -2132,6 +2132,7 @@ config FB_MX3
1796 an LCD display with your i.MX31 system, say Y here.
1797
1798 source "drivers/video/omap/Kconfig"
1799+source "drivers/video/omap2/Kconfig"
1800
1801 source "drivers/video/backlight/Kconfig"
1802 source "drivers/video/display/Kconfig"
1803diff --git a/drivers/video/Makefile b/drivers/video/Makefile
1804index 2a998ca..1db8dd4 100644
1805--- a/drivers/video/Makefile
1806+++ b/drivers/video/Makefile
1807@@ -120,6 +120,7 @@ obj-$(CONFIG_FB_SM501) += sm501fb.o
1808 obj-$(CONFIG_FB_XILINX) += xilinxfb.o
1809 obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
1810 obj-$(CONFIG_FB_OMAP) += omap/
1811+obj-$(CONFIG_OMAP2_DSS) += omap2/
1812 obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
1813 obj-$(CONFIG_FB_CARMINE) += carminefb.o
1814 obj-$(CONFIG_FB_MB862XX) += mb862xx/
1815diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
1816new file mode 100644
1817index 0000000..89bf210
1818--- /dev/null
1819+++ b/drivers/video/omap2/Kconfig
1820@@ -0,0 +1,3 @@
1821+source "drivers/video/omap2/dss/Kconfig"
1822+source "drivers/video/omap2/displays/Kconfig"
1823+source "drivers/video/omap2/omapfb/Kconfig"
1824diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
1825new file mode 100644
1826index 0000000..72134db
1827--- /dev/null
1828+++ b/drivers/video/omap2/Makefile
1829@@ -0,0 +1,4 @@
1830+# OMAP2/3 Display Subsystem
1831+obj-y += dss/
1832+obj-y += displays/
1833+obj-y += omapfb/
1834diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
1835new file mode 100644
1836index 0000000..f2ce068
1837--- /dev/null
1838+++ b/drivers/video/omap2/dss/Kconfig
1839@@ -0,0 +1,89 @@
1840+menuconfig OMAP2_DSS
1841+ tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)"
1842+ depends on ARCH_OMAP2 || ARCH_OMAP3
1843+ help
1844+ OMAP2/3 Display Subsystem support.
1845+
1846+if OMAP2_DSS
1847+
1848+config OMAP2_DSS_VRAM_SIZE
1849+ int "VRAM size (MB)"
1850+ range 0 32
1851+ default 4
1852+ help
1853+ The amount of SDRAM to reserve at boot time for video RAM use.
1854+ This VRAM will be used by omapfb and other drivers that need
1855+ large continuous RAM area for video use.
1856+
1857+ You can also set this with "vram=<bytes>" kernel argument, or
1858+ in the board file.
1859+
1860+config OMAP2_DSS_DEBUG_SUPPORT
1861+ bool "Debug support"
1862+ default y
1863+ help
1864+ This enables debug messages. You need to enable printing
1865+ with 'debug' module parameter.
1866+
1867+config OMAP2_DSS_RFBI
1868+ bool "RFBI support"
1869+ default n
1870+ help
1871+ MIPI DBI, or RFBI (Remote Framebuffer Interface), support.
1872+
1873+config OMAP2_DSS_VENC
1874+ bool "VENC support"
1875+ default y
1876+ help
1877+ OMAP Video Encoder support.
1878+
1879+config OMAP2_DSS_SDI
1880+ bool "SDI support"
1881+ depends on ARCH_OMAP3
1882+ default n
1883+ help
1884+ SDI (Serial Display Interface) support.
1885+
1886+config OMAP2_DSS_DSI
1887+ bool "DSI support"
1888+ depends on ARCH_OMAP3
1889+ default n
1890+ help
1891+ MIPI DSI support.
1892+
1893+config OMAP2_DSS_USE_DSI_PLL
1894+ bool "Use DSI PLL for PCLK (EXPERIMENTAL)"
1895+ default n
1896+ depends on OMAP2_DSS_DSI
1897+ help
1898+ Use DSI PLL to generate pixel clock. Currently only for DPI output.
1899+ DSI PLL can be used to generate higher and more precise pixel clocks.
1900+
1901+config OMAP2_DSS_FAKE_VSYNC
1902+ bool "Fake VSYNC irq from manual update displays"
1903+ default n
1904+ help
1905+ If this is selected, DSI will generate a fake DISPC VSYNC interrupt
1906+ when DSI has sent a frame. This is only needed with DSI or RFBI
1907+ displays using manual mode, and you want VSYNC to, for example,
1908+ time animation.
1909+
1910+config OMAP2_DSS_MIN_FCK_PER_PCK
1911+ int "Minimum FCK/PCK ratio (for scaling)"
1912+ range 0 32
1913+ default 0
1914+ help
1915+ This can be used to adjust the minimum FCK/PCK ratio.
1916+
1917+ With this you can make sure that DISPC FCK is at least
1918+ n x PCK. Video plane scaling requires higher FCK than
1919+ normally.
1920+
1921+ If this is set to 0, there's no extra constraint on the
1922+ DISPC FCK. However, the FCK will at minimum be
1923+ 2xPCK (if active matrix) or 3xPCK (if passive matrix).
1924+
1925+ Max FCK is 173MHz, so this doesn't work if your PCK
1926+ is very high.
1927+
1928+endif
1929diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
1930new file mode 100644
1931index 0000000..980c72c
1932--- /dev/null
1933+++ b/drivers/video/omap2/dss/Makefile
1934@@ -0,0 +1,6 @@
1935+obj-$(CONFIG_OMAP2_DSS) += omapdss.o
1936+omapdss-y := core.o dss.o dispc.o dpi.o display.o manager.o overlay.o
1937+omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
1938+omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
1939+omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
1940+omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
1941diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
1942new file mode 100644
1943index 0000000..ae7cd06
1944--- /dev/null
1945+++ b/drivers/video/omap2/dss/core.c
1946@@ -0,0 +1,641 @@
1947+/*
1948+ * linux/drivers/video/omap2/dss/core.c
1949+ *
1950+ * Copyright (C) 2009 Nokia Corporation
1951+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
1952+ *
1953+ * Some code and ideas taken from drivers/video/omap/ driver
1954+ * by Imre Deak.
1955+ *
1956+ * This program is free software; you can redistribute it and/or modify it
1957+ * under the terms of the GNU General Public License version 2 as published by
1958+ * the Free Software Foundation.
1959+ *
1960+ * This program is distributed in the hope that it will be useful, but WITHOUT
1961+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1962+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
1963+ * more details.
1964+ *
1965+ * You should have received a copy of the GNU General Public License along with
1966+ * this program. If not, see <http://www.gnu.org/licenses/>.
1967+ */
1968+
1969+#define DSS_SUBSYS_NAME "CORE"
1970+
1971+#include <linux/kernel.h>
1972+#include <linux/module.h>
1973+#include <linux/clk.h>
1974+#include <linux/err.h>
1975+#include <linux/platform_device.h>
1976+#include <linux/seq_file.h>
1977+#include <linux/debugfs.h>
1978+#include <linux/io.h>
1979+
1980+#include <mach/display.h>
1981+#include <mach/clock.h>
1982+
1983+#include "dss.h"
1984+
1985+static struct {
1986+ struct platform_device *pdev;
1987+ unsigned ctx_id;
1988+
1989+ struct clk *dss_ick;
1990+ struct clk *dss1_fck;
1991+ struct clk *dss2_fck;
1992+ struct clk *dss_54m_fck;
1993+ struct clk *dss_96m_fck;
1994+ unsigned num_clks_enabled;
1995+} core;
1996+
1997+static void dss_clk_enable_all_no_ctx(void);
1998+static void dss_clk_disable_all_no_ctx(void);
1999+static void dss_clk_enable_no_ctx(enum dss_clock clks);
2000+static void dss_clk_disable_no_ctx(enum dss_clock clks);
2001+
2002+static char *def_disp_name;
2003+module_param_named(def_disp, def_disp_name, charp, 0);
2004+MODULE_PARM_DESC(def_disp_name, "default display name");
2005+
2006+#ifdef DEBUG
2007+unsigned int dss_debug;
2008+module_param_named(debug, dss_debug, bool, 0644);
2009+#endif
2010+
2011+/* CONTEXT */
2012+static unsigned dss_get_ctx_id(void)
2013+{
2014+ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
2015+
2016+ if (!pdata->get_last_off_on_transaction_id)
2017+ return 0;
2018+
2019+ return pdata->get_last_off_on_transaction_id(&core.pdev->dev);
2020+}
2021+
2022+int dss_need_ctx_restore(void)
2023+{
2024+ int id = dss_get_ctx_id();
2025+
2026+ if (id != core.ctx_id) {
2027+ DSSDBG("ctx id %u -> id %u\n",
2028+ core.ctx_id, id);
2029+ core.ctx_id = id;
2030+ return 1;
2031+ } else {
2032+ return 0;
2033+ }
2034+}
2035+
2036+static void save_all_ctx(void)
2037+{
2038+ DSSDBG("save context\n");
2039+
2040+ dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
2041+
2042+ dss_save_context();
2043+ dispc_save_context();
2044+#ifdef CONFIG_OMAP2_DSS_DSI
2045+ dsi_save_context();
2046+#endif
2047+
2048+ dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
2049+}
2050+
2051+static void restore_all_ctx(void)
2052+{
2053+ DSSDBG("restore context\n");
2054+
2055+ dss_clk_enable_all_no_ctx();
2056+
2057+ dss_restore_context();
2058+ dispc_restore_context();
2059+#ifdef CONFIG_OMAP2_DSS_DSI
2060+ dsi_restore_context();
2061+#endif
2062+
2063+ dss_clk_disable_all_no_ctx();
2064+}
2065+
2066+/* CLOCKS */
2067+void dss_dump_clocks(struct seq_file *s)
2068+{
2069+ int i;
2070+ struct clk *clocks[5] = {
2071+ core.dss_ick,
2072+ core.dss1_fck,
2073+ core.dss2_fck,
2074+ core.dss_54m_fck,
2075+ core.dss_96m_fck
2076+ };
2077+
2078+ seq_printf(s, "- dss -\n");
2079+
2080+ seq_printf(s, "internal clk count\t%u\n", core.num_clks_enabled);
2081+
2082+ for (i = 0; i < 5; i++) {
2083+ if (!clocks[i])
2084+ continue;
2085+ seq_printf(s, "%-15s\t%lu\t%d\n",
2086+ clocks[i]->name,
2087+ clk_get_rate(clocks[i]),
2088+ clocks[i]->usecount);
2089+ }
2090+}
2091+
2092+static int dss_get_clocks(void)
2093+{
2094+ const struct {
2095+ struct clk **clock;
2096+ char *omap2_name;
2097+ char *omap3_name;
2098+ } clocks[5] = {
2099+ { &core.dss_ick, "dss_ick", "dss_ick" }, /* L3 & L4 ick */
2100+ { &core.dss1_fck, "dss1_fck", "dss1_alwon_fck" },
2101+ { &core.dss2_fck, "dss2_fck", "dss2_alwon_fck" },
2102+ { &core.dss_54m_fck, "dss_54m_fck", "dss_tv_fck" },
2103+ { &core.dss_96m_fck, NULL, "dss_96m_fck" },
2104+ };
2105+
2106+ int r = 0;
2107+ int i;
2108+ const int num_clocks = 5;
2109+
2110+ for (i = 0; i < num_clocks; i++)
2111+ *clocks[i].clock = NULL;
2112+
2113+ for (i = 0; i < num_clocks; i++) {
2114+ struct clk *clk;
2115+ const char *clk_name;
2116+
2117+ clk_name = cpu_is_omap34xx() ? clocks[i].omap3_name
2118+ : clocks[i].omap2_name;
2119+
2120+ if (!clk_name)
2121+ continue;
2122+
2123+ clk = clk_get(NULL, clk_name);
2124+
2125+ if (IS_ERR(clk)) {
2126+ DSSERR("can't get clock %s", clk_name);
2127+ r = PTR_ERR(clk);
2128+ goto err;
2129+ }
2130+
2131+ DSSDBG("clk %s, rate %ld\n",
2132+ clk_name, clk_get_rate(clk));
2133+
2134+ *clocks[i].clock = clk;
2135+ }
2136+
2137+ return 0;
2138+
2139+err:
2140+ for (i = 0; i < num_clocks; i++) {
2141+ if (!IS_ERR(*clocks[i].clock))
2142+ clk_put(*clocks[i].clock);
2143+ }
2144+
2145+ return r;
2146+}
2147+
2148+static void dss_put_clocks(void)
2149+{
2150+ if (core.dss_96m_fck)
2151+ clk_put(core.dss_96m_fck);
2152+ clk_put(core.dss_54m_fck);
2153+ clk_put(core.dss1_fck);
2154+ clk_put(core.dss2_fck);
2155+ clk_put(core.dss_ick);
2156+}
2157+
2158+unsigned long dss_clk_get_rate(enum dss_clock clk)
2159+{
2160+ switch (clk) {
2161+ case DSS_CLK_ICK:
2162+ return clk_get_rate(core.dss_ick);
2163+ case DSS_CLK_FCK1:
2164+ return clk_get_rate(core.dss1_fck);
2165+ case DSS_CLK_FCK2:
2166+ return clk_get_rate(core.dss2_fck);
2167+ case DSS_CLK_54M:
2168+ return clk_get_rate(core.dss_54m_fck);
2169+ case DSS_CLK_96M:
2170+ return clk_get_rate(core.dss_96m_fck);
2171+ }
2172+
2173+ BUG();
2174+ return 0;
2175+}
2176+
2177+static unsigned count_clk_bits(enum dss_clock clks)
2178+{
2179+ unsigned num_clks = 0;
2180+
2181+ if (clks & DSS_CLK_ICK)
2182+ ++num_clks;
2183+ if (clks & DSS_CLK_FCK1)
2184+ ++num_clks;
2185+ if (clks & DSS_CLK_FCK2)
2186+ ++num_clks;
2187+ if (clks & DSS_CLK_54M)
2188+ ++num_clks;
2189+ if (clks & DSS_CLK_96M)
2190+ ++num_clks;
2191+
2192+ return num_clks;
2193+}
2194+
2195+static void dss_clk_enable_no_ctx(enum dss_clock clks)
2196+{
2197+ unsigned num_clks = count_clk_bits(clks);
2198+
2199+ if (clks & DSS_CLK_ICK)
2200+ clk_enable(core.dss_ick);
2201+ if (clks & DSS_CLK_FCK1)
2202+ clk_enable(core.dss1_fck);
2203+ if (clks & DSS_CLK_FCK2)
2204+ clk_enable(core.dss2_fck);
2205+ if (clks & DSS_CLK_54M)
2206+ clk_enable(core.dss_54m_fck);
2207+ if (clks & DSS_CLK_96M)
2208+ clk_enable(core.dss_96m_fck);
2209+
2210+ core.num_clks_enabled += num_clks;
2211+}
2212+
2213+void dss_clk_enable(enum dss_clock clks)
2214+{
2215+ dss_clk_enable_no_ctx(clks);
2216+
2217+ if (cpu_is_omap34xx() && dss_need_ctx_restore())
2218+ restore_all_ctx();
2219+}
2220+
2221+static void dss_clk_disable_no_ctx(enum dss_clock clks)
2222+{
2223+ unsigned num_clks = count_clk_bits(clks);
2224+
2225+ if (clks & DSS_CLK_ICK)
2226+ clk_disable(core.dss_ick);
2227+ if (clks & DSS_CLK_FCK1)
2228+ clk_disable(core.dss1_fck);
2229+ if (clks & DSS_CLK_FCK2)
2230+ clk_disable(core.dss2_fck);
2231+ if (clks & DSS_CLK_54M)
2232+ clk_disable(core.dss_54m_fck);
2233+ if (clks & DSS_CLK_96M)
2234+ clk_disable(core.dss_96m_fck);
2235+
2236+ core.num_clks_enabled -= num_clks;
2237+}
2238+
2239+void dss_clk_disable(enum dss_clock clks)
2240+{
2241+ if (cpu_is_omap34xx()) {
2242+ unsigned num_clks = count_clk_bits(clks);
2243+
2244+ BUG_ON(core.num_clks_enabled < num_clks);
2245+
2246+ if (core.num_clks_enabled == num_clks)
2247+ save_all_ctx();
2248+ }
2249+
2250+ dss_clk_disable_no_ctx(clks);
2251+}
2252+
2253+static void dss_clk_enable_all_no_ctx(void)
2254+{
2255+ enum dss_clock clks;
2256+
2257+ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
2258+ if (cpu_is_omap34xx())
2259+ clks |= DSS_CLK_96M;
2260+ dss_clk_enable_no_ctx(clks);
2261+}
2262+
2263+static void dss_clk_disable_all_no_ctx(void)
2264+{
2265+ enum dss_clock clks;
2266+
2267+ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
2268+ if (cpu_is_omap34xx())
2269+ clks |= DSS_CLK_96M;
2270+ dss_clk_disable_no_ctx(clks);
2271+}
2272+
2273+static void dss_clk_disable_all(void)
2274+{
2275+ enum dss_clock clks;
2276+
2277+ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
2278+ if (cpu_is_omap34xx())
2279+ clks |= DSS_CLK_96M;
2280+ dss_clk_disable(clks);
2281+}
2282+
2283+/* DEBUGFS */
2284+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
2285+static void dss_debug_dump_clocks(struct seq_file *s)
2286+{
2287+ dss_dump_clocks(s);
2288+ dispc_dump_clocks(s);
2289+#ifdef CONFIG_OMAP2_DSS_DSI
2290+ dsi_dump_clocks(s);
2291+#endif
2292+}
2293+
2294+static int dss_debug_show(struct seq_file *s, void *unused)
2295+{
2296+ void (*func)(struct seq_file *) = s->private;
2297+ func(s);
2298+ return 0;
2299+}
2300+
2301+static int dss_debug_open(struct inode *inode, struct file *file)
2302+{
2303+ return single_open(file, dss_debug_show, inode->i_private);
2304+}
2305+
2306+static const struct file_operations dss_debug_fops = {
2307+ .open = dss_debug_open,
2308+ .read = seq_read,
2309+ .llseek = seq_lseek,
2310+ .release = single_release,
2311+};
2312+
2313+static struct dentry *dss_debugfs_dir;
2314+
2315+static int dss_initialize_debugfs(void)
2316+{
2317+ dss_debugfs_dir = debugfs_create_dir("omapdss", NULL);
2318+ if (IS_ERR(dss_debugfs_dir)) {
2319+ int err = PTR_ERR(dss_debugfs_dir);
2320+ dss_debugfs_dir = NULL;
2321+ return err;
2322+ }
2323+
2324+ debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
2325+ &dss_debug_dump_clocks, &dss_debug_fops);
2326+
2327+ debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir,
2328+ &dss_dump_regs, &dss_debug_fops);
2329+ debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir,
2330+ &dispc_dump_regs, &dss_debug_fops);
2331+#ifdef CONFIG_OMAP2_DSS_RFBI
2332+ debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir,
2333+ &rfbi_dump_regs, &dss_debug_fops);
2334+#endif
2335+#ifdef CONFIG_OMAP2_DSS_DSI
2336+ debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir,
2337+ &dsi_dump_regs, &dss_debug_fops);
2338+#endif
2339+ return 0;
2340+}
2341+
2342+static void dss_uninitialize_debugfs(void)
2343+{
2344+ if (dss_debugfs_dir)
2345+ debugfs_remove_recursive(dss_debugfs_dir);
2346+}
2347+#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
2348+
2349+
2350+/* DSI powers */
2351+int dss_dsi_power_up(void)
2352+{
2353+ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
2354+
2355+ if (!pdata->dsi_power_up)
2356+ return 0; /* presume power is always on then */
2357+
2358+ return pdata->dsi_power_up();
2359+}
2360+
2361+void dss_dsi_power_down(void)
2362+{
2363+ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
2364+
2365+ if (!pdata->dsi_power_down)
2366+ return;
2367+
2368+ pdata->dsi_power_down();
2369+}
2370+
2371+
2372+
2373+/* PLATFORM DEVICE */
2374+static int omap_dss_probe(struct platform_device *pdev)
2375+{
2376+ int skip_init = 0;
2377+ int r;
2378+
2379+ core.pdev = pdev;
2380+
2381+ r = dss_get_clocks();
2382+ if (r)
2383+ goto fail0;
2384+
2385+ dss_clk_enable_all_no_ctx();
2386+
2387+ core.ctx_id = dss_get_ctx_id();
2388+ DSSDBG("initial ctx id %u\n", core.ctx_id);
2389+
2390+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
2391+ /* DISPC_CONTROL */
2392+ if (omap_readl(0x48050440) & 1) /* LCD enabled? */
2393+ skip_init = 1;
2394+#endif
2395+
2396+ r = dss_init(skip_init);
2397+ if (r) {
2398+ DSSERR("Failed to initialize DSS\n");
2399+ goto fail0;
2400+ }
2401+
2402+#ifdef CONFIG_OMAP2_DSS_RFBI
2403+ r = rfbi_init();
2404+ if (r) {
2405+ DSSERR("Failed to initialize rfbi\n");
2406+ goto fail0;
2407+ }
2408+#endif
2409+
2410+ r = dpi_init();
2411+ if (r) {
2412+ DSSERR("Failed to initialize dpi\n");
2413+ goto fail0;
2414+ }
2415+
2416+ r = dispc_init();
2417+ if (r) {
2418+ DSSERR("Failed to initialize dispc\n");
2419+ goto fail0;
2420+ }
2421+#ifdef CONFIG_OMAP2_DSS_VENC
2422+ r = venc_init();
2423+ if (r) {
2424+ DSSERR("Failed to initialize venc\n");
2425+ goto fail0;
2426+ }
2427+#endif
2428+ if (cpu_is_omap34xx()) {
2429+#ifdef CONFIG_OMAP2_DSS_SDI
2430+ r = sdi_init(skip_init);
2431+ if (r) {
2432+ DSSERR("Failed to initialize SDI\n");
2433+ goto fail0;
2434+ }
2435+#endif
2436+#ifdef CONFIG_OMAP2_DSS_DSI
2437+ r = dsi_init();
2438+ if (r) {
2439+ DSSERR("Failed to initialize DSI\n");
2440+ goto fail0;
2441+ }
2442+#endif
2443+ }
2444+
2445+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
2446+ r = dss_initialize_debugfs();
2447+ if (r)
2448+ goto fail0;
2449+#endif
2450+
2451+ dss_init_displays(pdev);
2452+ dss_init_overlay_managers(pdev);
2453+ dss_init_overlays(pdev, def_disp_name);
2454+
2455+ dss_clk_disable_all();
2456+
2457+ return 0;
2458+
2459+ /* XXX fail correctly */
2460+fail0:
2461+ return r;
2462+}
2463+
2464+static int omap_dss_remove(struct platform_device *pdev)
2465+{
2466+ int c;
2467+
2468+ dss_uninit_overlays(pdev);
2469+ dss_uninit_overlay_managers(pdev);
2470+ dss_uninit_displays(pdev);
2471+
2472+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
2473+ dss_uninitialize_debugfs();
2474+#endif
2475+
2476+#ifdef CONFIG_OMAP2_DSS_VENC
2477+ venc_exit();
2478+#endif
2479+ dispc_exit();
2480+ dpi_exit();
2481+#ifdef CONFIG_OMAP2_DSS_RFBI
2482+ rfbi_exit();
2483+#endif
2484+ if (cpu_is_omap34xx()) {
2485+#ifdef CONFIG_OMAP2_DSS_DSI
2486+ dsi_exit();
2487+#endif
2488+#ifdef CONFIG_OMAP2_DSS_SDI
2489+ sdi_exit();
2490+#endif
2491+ }
2492+
2493+ dss_exit();
2494+
2495+ /* these should be removed at some point */
2496+ c = core.dss_ick->usecount;
2497+ if (c > 0) {
2498+ DSSERR("warning: dss_ick usecount %d, disabling\n", c);
2499+ while (c-- > 0)
2500+ clk_disable(core.dss_ick);
2501+ }
2502+
2503+ c = core.dss1_fck->usecount;
2504+ if (c > 0) {
2505+ DSSERR("warning: dss1_fck usecount %d, disabling\n", c);
2506+ while (c-- > 0)
2507+ clk_disable(core.dss1_fck);
2508+ }
2509+
2510+ c = core.dss2_fck->usecount;
2511+ if (c > 0) {
2512+ DSSERR("warning: dss2_fck usecount %d, disabling\n", c);
2513+ while (c-- > 0)
2514+ clk_disable(core.dss2_fck);
2515+ }
2516+
2517+ c = core.dss_54m_fck->usecount;
2518+ if (c > 0) {
2519+ DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c);
2520+ while (c-- > 0)
2521+ clk_disable(core.dss_54m_fck);
2522+ }
2523+
2524+ if (core.dss_96m_fck) {
2525+ c = core.dss_96m_fck->usecount;
2526+ if (c > 0) {
2527+ DSSERR("warning: dss_96m_fck usecount %d, disabling\n",
2528+ c);
2529+ while (c-- > 0)
2530+ clk_disable(core.dss_96m_fck);
2531+ }
2532+ }
2533+
2534+ dss_put_clocks();
2535+
2536+ return 0;
2537+}
2538+
2539+static void omap_dss_shutdown(struct platform_device *pdev)
2540+{
2541+ DSSDBG("shutdown\n");
2542+}
2543+
2544+static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state)
2545+{
2546+ DSSDBG("suspend %d\n", state.event);
2547+
2548+ return dss_suspend_all_displays();
2549+}
2550+
2551+static int omap_dss_resume(struct platform_device *pdev)
2552+{
2553+ DSSDBG("resume\n");
2554+
2555+ return dss_resume_all_displays();
2556+}
2557+
2558+static struct platform_driver omap_dss_driver = {
2559+ .probe = omap_dss_probe,
2560+ .remove = omap_dss_remove,
2561+ .shutdown = omap_dss_shutdown,
2562+ .suspend = omap_dss_suspend,
2563+ .resume = omap_dss_resume,
2564+ .driver = {
2565+ .name = "omapdss",
2566+ .owner = THIS_MODULE,
2567+ },
2568+};
2569+
2570+static int __init omap_dss_init(void)
2571+{
2572+ return platform_driver_register(&omap_dss_driver);
2573+}
2574+
2575+static void __exit omap_dss_exit(void)
2576+{
2577+ platform_driver_unregister(&omap_dss_driver);
2578+}
2579+
2580+subsys_initcall(omap_dss_init);
2581+module_exit(omap_dss_exit);
2582+
2583+
2584+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
2585+MODULE_DESCRIPTION("OMAP2/3 Display Subsystem");
2586+MODULE_LICENSE("GPL v2");
2587+
2588diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
2589new file mode 100644
2590index 0000000..ffb5648
2591--- /dev/null
2592+++ b/drivers/video/omap2/dss/dispc.c
2593@@ -0,0 +1,2968 @@
2594+/*
2595+ * linux/drivers/video/omap2/dss/dispc.c
2596+ *
2597+ * Copyright (C) 2009 Nokia Corporation
2598+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
2599+ *
2600+ * Some code and ideas taken from drivers/video/omap/ driver
2601+ * by Imre Deak.
2602+ *
2603+ * This program is free software; you can redistribute it and/or modify it
2604+ * under the terms of the GNU General Public License version 2 as published by
2605+ * the Free Software Foundation.
2606+ *
2607+ * This program is distributed in the hope that it will be useful, but WITHOUT
2608+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2609+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
2610+ * more details.
2611+ *
2612+ * You should have received a copy of the GNU General Public License along with
2613+ * this program. If not, see <http://www.gnu.org/licenses/>.
2614+ */
2615+
2616+#define DSS_SUBSYS_NAME "DISPC"
2617+
2618+#include <linux/kernel.h>
2619+#include <linux/dma-mapping.h>
2620+#include <linux/vmalloc.h>
2621+#include <linux/clk.h>
2622+#include <linux/io.h>
2623+#include <linux/jiffies.h>
2624+#include <linux/seq_file.h>
2625+#include <linux/delay.h>
2626+#include <linux/workqueue.h>
2627+
2628+#include <mach/sram.h>
2629+#include <mach/board.h>
2630+#include <mach/clock.h>
2631+
2632+#include <mach/display.h>
2633+
2634+#include "dss.h"
2635+
2636+/* DISPC */
2637+#define DISPC_BASE 0x48050400
2638+
2639+#define DISPC_SZ_REGS SZ_1K
2640+
2641+struct dispc_reg { u16 idx; };
2642+
2643+#define DISPC_REG(idx) ((const struct dispc_reg) { idx })
2644+
2645+/* DISPC common */
2646+#define DISPC_REVISION DISPC_REG(0x0000)
2647+#define DISPC_SYSCONFIG DISPC_REG(0x0010)
2648+#define DISPC_SYSSTATUS DISPC_REG(0x0014)
2649+#define DISPC_IRQSTATUS DISPC_REG(0x0018)
2650+#define DISPC_IRQENABLE DISPC_REG(0x001C)
2651+#define DISPC_CONTROL DISPC_REG(0x0040)
2652+#define DISPC_CONFIG DISPC_REG(0x0044)
2653+#define DISPC_CAPABLE DISPC_REG(0x0048)
2654+#define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C)
2655+#define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050)
2656+#define DISPC_TRANS_COLOR0 DISPC_REG(0x0054)
2657+#define DISPC_TRANS_COLOR1 DISPC_REG(0x0058)
2658+#define DISPC_LINE_STATUS DISPC_REG(0x005C)
2659+#define DISPC_LINE_NUMBER DISPC_REG(0x0060)
2660+#define DISPC_TIMING_H DISPC_REG(0x0064)
2661+#define DISPC_TIMING_V DISPC_REG(0x0068)
2662+#define DISPC_POL_FREQ DISPC_REG(0x006C)
2663+#define DISPC_DIVISOR DISPC_REG(0x0070)
2664+#define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074)
2665+#define DISPC_SIZE_DIG DISPC_REG(0x0078)
2666+#define DISPC_SIZE_LCD DISPC_REG(0x007C)
2667+
2668+/* DISPC GFX plane */
2669+#define DISPC_GFX_BA0 DISPC_REG(0x0080)
2670+#define DISPC_GFX_BA1 DISPC_REG(0x0084)
2671+#define DISPC_GFX_POSITION DISPC_REG(0x0088)
2672+#define DISPC_GFX_SIZE DISPC_REG(0x008C)
2673+#define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0)
2674+#define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4)
2675+#define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8)
2676+#define DISPC_GFX_ROW_INC DISPC_REG(0x00AC)
2677+#define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0)
2678+#define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4)
2679+#define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8)
2680+
2681+#define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4)
2682+#define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8)
2683+#define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC)
2684+
2685+#define DISPC_CPR_COEF_R DISPC_REG(0x0220)
2686+#define DISPC_CPR_COEF_G DISPC_REG(0x0224)
2687+#define DISPC_CPR_COEF_B DISPC_REG(0x0228)
2688+
2689+#define DISPC_GFX_PRELOAD DISPC_REG(0x022C)
2690+
2691+/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */
2692+#define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx)
2693+
2694+#define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000)
2695+#define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004)
2696+#define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008)
2697+#define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C)
2698+#define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010)
2699+#define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014)
2700+#define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018)
2701+#define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C)
2702+#define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020)
2703+#define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024)
2704+#define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028)
2705+#define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C)
2706+#define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030)
2707+
2708+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
2709+#define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8)
2710+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
2711+#define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8)
2712+/* coef index i = {0, 1, 2, 3, 4} */
2713+#define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4)
2714+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
2715+#define DISPC_VID_FIR_COEF_V(n, i) DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4)
2716+
2717+#define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04)
2718+
2719+
2720+#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
2721+ DISPC_IRQ_OCP_ERR | \
2722+ DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
2723+ DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
2724+ DISPC_IRQ_SYNC_LOST | \
2725+ DISPC_IRQ_SYNC_LOST_DIGIT)
2726+
2727+#define DISPC_MAX_NR_ISRS 8
2728+
2729+struct omap_dispc_isr_data {
2730+ omap_dispc_isr_t isr;
2731+ void *arg;
2732+ u32 mask;
2733+};
2734+
2735+#define REG_GET(idx, start, end) \
2736+ FLD_GET(dispc_read_reg(idx), start, end)
2737+
2738+#define REG_FLD_MOD(idx, val, start, end) \
2739+ dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
2740+
2741+static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES,
2742+ DISPC_VID_ATTRIBUTES(0),
2743+ DISPC_VID_ATTRIBUTES(1) };
2744+
2745+static struct {
2746+ void __iomem *base;
2747+
2748+ struct clk *dpll4_m4_ck;
2749+
2750+ spinlock_t irq_lock;
2751+
2752+ unsigned long cache_req_pck;
2753+ unsigned long cache_prate;
2754+ struct dispc_clock_info cache_cinfo;
2755+
2756+ u32 irq_error_mask;
2757+ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
2758+
2759+ spinlock_t error_lock;
2760+ u32 error_irqs;
2761+ struct work_struct error_work;
2762+
2763+ u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
2764+} dispc;
2765+
2766+static void omap_dispc_set_irqs(void);
2767+
2768+static inline void dispc_write_reg(const struct dispc_reg idx, u32 val)
2769+{
2770+ __raw_writel(val, dispc.base + idx.idx);
2771+}
2772+
2773+static inline u32 dispc_read_reg(const struct dispc_reg idx)
2774+{
2775+ return __raw_readl(dispc.base + idx.idx);
2776+}
2777+
2778+#define SR(reg) \
2779+ dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
2780+#define RR(reg) \
2781+ dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)])
2782+
2783+void dispc_save_context(void)
2784+{
2785+ if (cpu_is_omap24xx())
2786+ return;
2787+
2788+ SR(SYSCONFIG);
2789+ SR(IRQENABLE);
2790+ SR(CONTROL);
2791+ SR(CONFIG);
2792+ SR(DEFAULT_COLOR0);
2793+ SR(DEFAULT_COLOR1);
2794+ SR(TRANS_COLOR0);
2795+ SR(TRANS_COLOR1);
2796+ SR(LINE_NUMBER);
2797+ SR(TIMING_H);
2798+ SR(TIMING_V);
2799+ SR(POL_FREQ);
2800+ SR(DIVISOR);
2801+ SR(GLOBAL_ALPHA);
2802+ SR(SIZE_DIG);
2803+ SR(SIZE_LCD);
2804+
2805+ SR(GFX_BA0);
2806+ SR(GFX_BA1);
2807+ SR(GFX_POSITION);
2808+ SR(GFX_SIZE);
2809+ SR(GFX_ATTRIBUTES);
2810+ SR(GFX_FIFO_THRESHOLD);
2811+ SR(GFX_ROW_INC);
2812+ SR(GFX_PIXEL_INC);
2813+ SR(GFX_WINDOW_SKIP);
2814+ SR(GFX_TABLE_BA);
2815+
2816+ SR(DATA_CYCLE1);
2817+ SR(DATA_CYCLE2);
2818+ SR(DATA_CYCLE3);
2819+
2820+ SR(CPR_COEF_R);
2821+ SR(CPR_COEF_G);
2822+ SR(CPR_COEF_B);
2823+
2824+ SR(GFX_PRELOAD);
2825+
2826+ /* VID1 */
2827+ SR(VID_BA0(0));
2828+ SR(VID_BA1(0));
2829+ SR(VID_POSITION(0));
2830+ SR(VID_SIZE(0));
2831+ SR(VID_ATTRIBUTES(0));
2832+ SR(VID_FIFO_THRESHOLD(0));
2833+ SR(VID_ROW_INC(0));
2834+ SR(VID_PIXEL_INC(0));
2835+ SR(VID_FIR(0));
2836+ SR(VID_PICTURE_SIZE(0));
2837+ SR(VID_ACCU0(0));
2838+ SR(VID_ACCU1(0));
2839+
2840+ SR(VID_FIR_COEF_H(0, 0));
2841+ SR(VID_FIR_COEF_H(0, 1));
2842+ SR(VID_FIR_COEF_H(0, 2));
2843+ SR(VID_FIR_COEF_H(0, 3));
2844+ SR(VID_FIR_COEF_H(0, 4));
2845+ SR(VID_FIR_COEF_H(0, 5));
2846+ SR(VID_FIR_COEF_H(0, 6));
2847+ SR(VID_FIR_COEF_H(0, 7));
2848+
2849+ SR(VID_FIR_COEF_HV(0, 0));
2850+ SR(VID_FIR_COEF_HV(0, 1));
2851+ SR(VID_FIR_COEF_HV(0, 2));
2852+ SR(VID_FIR_COEF_HV(0, 3));
2853+ SR(VID_FIR_COEF_HV(0, 4));
2854+ SR(VID_FIR_COEF_HV(0, 5));
2855+ SR(VID_FIR_COEF_HV(0, 6));
2856+ SR(VID_FIR_COEF_HV(0, 7));
2857+
2858+ SR(VID_CONV_COEF(0, 0));
2859+ SR(VID_CONV_COEF(0, 1));
2860+ SR(VID_CONV_COEF(0, 2));
2861+ SR(VID_CONV_COEF(0, 3));
2862+ SR(VID_CONV_COEF(0, 4));
2863+
2864+ SR(VID_FIR_COEF_V(0, 0));
2865+ SR(VID_FIR_COEF_V(0, 1));
2866+ SR(VID_FIR_COEF_V(0, 2));
2867+ SR(VID_FIR_COEF_V(0, 3));
2868+ SR(VID_FIR_COEF_V(0, 4));
2869+ SR(VID_FIR_COEF_V(0, 5));
2870+ SR(VID_FIR_COEF_V(0, 6));
2871+ SR(VID_FIR_COEF_V(0, 7));
2872+
2873+ SR(VID_PRELOAD(0));
2874+
2875+ /* VID2 */
2876+ SR(VID_BA0(1));
2877+ SR(VID_BA1(1));
2878+ SR(VID_POSITION(1));
2879+ SR(VID_SIZE(1));
2880+ SR(VID_ATTRIBUTES(1));
2881+ SR(VID_FIFO_THRESHOLD(1));
2882+ SR(VID_ROW_INC(1));
2883+ SR(VID_PIXEL_INC(1));
2884+ SR(VID_FIR(1));
2885+ SR(VID_PICTURE_SIZE(1));
2886+ SR(VID_ACCU0(1));
2887+ SR(VID_ACCU1(1));
2888+
2889+ SR(VID_FIR_COEF_H(1, 0));
2890+ SR(VID_FIR_COEF_H(1, 1));
2891+ SR(VID_FIR_COEF_H(1, 2));
2892+ SR(VID_FIR_COEF_H(1, 3));
2893+ SR(VID_FIR_COEF_H(1, 4));
2894+ SR(VID_FIR_COEF_H(1, 5));
2895+ SR(VID_FIR_COEF_H(1, 6));
2896+ SR(VID_FIR_COEF_H(1, 7));
2897+
2898+ SR(VID_FIR_COEF_HV(1, 0));
2899+ SR(VID_FIR_COEF_HV(1, 1));
2900+ SR(VID_FIR_COEF_HV(1, 2));
2901+ SR(VID_FIR_COEF_HV(1, 3));
2902+ SR(VID_FIR_COEF_HV(1, 4));
2903+ SR(VID_FIR_COEF_HV(1, 5));
2904+ SR(VID_FIR_COEF_HV(1, 6));
2905+ SR(VID_FIR_COEF_HV(1, 7));
2906+
2907+ SR(VID_CONV_COEF(1, 0));
2908+ SR(VID_CONV_COEF(1, 1));
2909+ SR(VID_CONV_COEF(1, 2));
2910+ SR(VID_CONV_COEF(1, 3));
2911+ SR(VID_CONV_COEF(1, 4));
2912+
2913+ SR(VID_FIR_COEF_V(1, 0));
2914+ SR(VID_FIR_COEF_V(1, 1));
2915+ SR(VID_FIR_COEF_V(1, 2));
2916+ SR(VID_FIR_COEF_V(1, 3));
2917+ SR(VID_FIR_COEF_V(1, 4));
2918+ SR(VID_FIR_COEF_V(1, 5));
2919+ SR(VID_FIR_COEF_V(1, 6));
2920+ SR(VID_FIR_COEF_V(1, 7));
2921+
2922+ SR(VID_PRELOAD(1));
2923+}
2924+
2925+void dispc_restore_context(void)
2926+{
2927+ RR(SYSCONFIG);
2928+ RR(IRQENABLE);
2929+ /*RR(CONTROL);*/
2930+ RR(CONFIG);
2931+ RR(DEFAULT_COLOR0);
2932+ RR(DEFAULT_COLOR1);
2933+ RR(TRANS_COLOR0);
2934+ RR(TRANS_COLOR1);
2935+ RR(LINE_NUMBER);
2936+ RR(TIMING_H);
2937+ RR(TIMING_V);
2938+ RR(POL_FREQ);
2939+ RR(DIVISOR);
2940+ RR(GLOBAL_ALPHA);
2941+ RR(SIZE_DIG);
2942+ RR(SIZE_LCD);
2943+
2944+ RR(GFX_BA0);
2945+ RR(GFX_BA1);
2946+ RR(GFX_POSITION);
2947+ RR(GFX_SIZE);
2948+ RR(GFX_ATTRIBUTES);
2949+ RR(GFX_FIFO_THRESHOLD);
2950+ RR(GFX_ROW_INC);
2951+ RR(GFX_PIXEL_INC);
2952+ RR(GFX_WINDOW_SKIP);
2953+ RR(GFX_TABLE_BA);
2954+
2955+ RR(DATA_CYCLE1);
2956+ RR(DATA_CYCLE2);
2957+ RR(DATA_CYCLE3);
2958+
2959+ RR(CPR_COEF_R);
2960+ RR(CPR_COEF_G);
2961+ RR(CPR_COEF_B);
2962+
2963+ RR(GFX_PRELOAD);
2964+
2965+ /* VID1 */
2966+ RR(VID_BA0(0));
2967+ RR(VID_BA1(0));
2968+ RR(VID_POSITION(0));
2969+ RR(VID_SIZE(0));
2970+ RR(VID_ATTRIBUTES(0));
2971+ RR(VID_FIFO_THRESHOLD(0));
2972+ RR(VID_ROW_INC(0));
2973+ RR(VID_PIXEL_INC(0));
2974+ RR(VID_FIR(0));
2975+ RR(VID_PICTURE_SIZE(0));
2976+ RR(VID_ACCU0(0));
2977+ RR(VID_ACCU1(0));
2978+
2979+ RR(VID_FIR_COEF_H(0, 0));
2980+ RR(VID_FIR_COEF_H(0, 1));
2981+ RR(VID_FIR_COEF_H(0, 2));
2982+ RR(VID_FIR_COEF_H(0, 3));
2983+ RR(VID_FIR_COEF_H(0, 4));
2984+ RR(VID_FIR_COEF_H(0, 5));
2985+ RR(VID_FIR_COEF_H(0, 6));
2986+ RR(VID_FIR_COEF_H(0, 7));
2987+
2988+ RR(VID_FIR_COEF_HV(0, 0));
2989+ RR(VID_FIR_COEF_HV(0, 1));
2990+ RR(VID_FIR_COEF_HV(0, 2));
2991+ RR(VID_FIR_COEF_HV(0, 3));
2992+ RR(VID_FIR_COEF_HV(0, 4));
2993+ RR(VID_FIR_COEF_HV(0, 5));
2994+ RR(VID_FIR_COEF_HV(0, 6));
2995+ RR(VID_FIR_COEF_HV(0, 7));
2996+
2997+ RR(VID_CONV_COEF(0, 0));
2998+ RR(VID_CONV_COEF(0, 1));
2999+ RR(VID_CONV_COEF(0, 2));
3000+ RR(VID_CONV_COEF(0, 3));
3001+ RR(VID_CONV_COEF(0, 4));
3002+
3003+ RR(VID_FIR_COEF_V(0, 0));
3004+ RR(VID_FIR_COEF_V(0, 1));
3005+ RR(VID_FIR_COEF_V(0, 2));
3006+ RR(VID_FIR_COEF_V(0, 3));
3007+ RR(VID_FIR_COEF_V(0, 4));
3008+ RR(VID_FIR_COEF_V(0, 5));
3009+ RR(VID_FIR_COEF_V(0, 6));
3010+ RR(VID_FIR_COEF_V(0, 7));
3011+
3012+ RR(VID_PRELOAD(0));
3013+
3014+ /* VID2 */
3015+ RR(VID_BA0(1));
3016+ RR(VID_BA1(1));
3017+ RR(VID_POSITION(1));
3018+ RR(VID_SIZE(1));
3019+ RR(VID_ATTRIBUTES(1));
3020+ RR(VID_FIFO_THRESHOLD(1));
3021+ RR(VID_ROW_INC(1));
3022+ RR(VID_PIXEL_INC(1));
3023+ RR(VID_FIR(1));
3024+ RR(VID_PICTURE_SIZE(1));
3025+ RR(VID_ACCU0(1));
3026+ RR(VID_ACCU1(1));
3027+
3028+ RR(VID_FIR_COEF_H(1, 0));
3029+ RR(VID_FIR_COEF_H(1, 1));
3030+ RR(VID_FIR_COEF_H(1, 2));
3031+ RR(VID_FIR_COEF_H(1, 3));
3032+ RR(VID_FIR_COEF_H(1, 4));
3033+ RR(VID_FIR_COEF_H(1, 5));
3034+ RR(VID_FIR_COEF_H(1, 6));
3035+ RR(VID_FIR_COEF_H(1, 7));
3036+
3037+ RR(VID_FIR_COEF_HV(1, 0));
3038+ RR(VID_FIR_COEF_HV(1, 1));
3039+ RR(VID_FIR_COEF_HV(1, 2));
3040+ RR(VID_FIR_COEF_HV(1, 3));
3041+ RR(VID_FIR_COEF_HV(1, 4));
3042+ RR(VID_FIR_COEF_HV(1, 5));
3043+ RR(VID_FIR_COEF_HV(1, 6));
3044+ RR(VID_FIR_COEF_HV(1, 7));
3045+
3046+ RR(VID_CONV_COEF(1, 0));
3047+ RR(VID_CONV_COEF(1, 1));
3048+ RR(VID_CONV_COEF(1, 2));
3049+ RR(VID_CONV_COEF(1, 3));
3050+ RR(VID_CONV_COEF(1, 4));
3051+
3052+ RR(VID_FIR_COEF_V(1, 0));
3053+ RR(VID_FIR_COEF_V(1, 1));
3054+ RR(VID_FIR_COEF_V(1, 2));
3055+ RR(VID_FIR_COEF_V(1, 3));
3056+ RR(VID_FIR_COEF_V(1, 4));
3057+ RR(VID_FIR_COEF_V(1, 5));
3058+ RR(VID_FIR_COEF_V(1, 6));
3059+ RR(VID_FIR_COEF_V(1, 7));
3060+
3061+ RR(VID_PRELOAD(1));
3062+
3063+ /* enable last, because LCD & DIGIT enable are here */
3064+ RR(CONTROL);
3065+}
3066+
3067+#undef SR
3068+#undef RR
3069+
3070+static inline void enable_clocks(bool enable)
3071+{
3072+ if (enable)
3073+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
3074+ else
3075+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
3076+}
3077+
3078+void dispc_go(enum omap_channel channel)
3079+{
3080+ int bit;
3081+ unsigned long tmo;
3082+
3083+ enable_clocks(1);
3084+
3085+ if (channel == OMAP_DSS_CHANNEL_LCD)
3086+ bit = 0; /* LCDENABLE */
3087+ else
3088+ bit = 1; /* DIGITALENABLE */
3089+
3090+ /* if the channel is not enabled, we don't need GO */
3091+ if (REG_GET(DISPC_CONTROL, bit, bit) == 0)
3092+ goto end;
3093+
3094+ if (channel == OMAP_DSS_CHANNEL_LCD)
3095+ bit = 5; /* GOLCD */
3096+ else
3097+ bit = 6; /* GODIGIT */
3098+
3099+ tmo = jiffies + msecs_to_jiffies(200);
3100+ while (REG_GET(DISPC_CONTROL, bit, bit) == 1) {
3101+ if (time_after(jiffies, tmo)) {
3102+ DSSERR("timeout waiting GO flag\n");
3103+ goto end;
3104+ }
3105+ cpu_relax();
3106+ }
3107+
3108+ DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT");
3109+
3110+ REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
3111+end:
3112+ enable_clocks(0);
3113+}
3114+
3115+static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
3116+{
3117+ BUG_ON(plane == OMAP_DSS_GFX);
3118+
3119+ dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value);
3120+}
3121+
3122+static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
3123+{
3124+ BUG_ON(plane == OMAP_DSS_GFX);
3125+
3126+ dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value);
3127+}
3128+
3129+static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value)
3130+{
3131+ BUG_ON(plane == OMAP_DSS_GFX);
3132+
3133+ dispc_write_reg(DISPC_VID_FIR_COEF_V(plane-1, reg), value);
3134+}
3135+
3136+static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
3137+ int vscaleup, int five_taps)
3138+{
3139+ /* Coefficients for horizontal up-sampling */
3140+ static const u32 coef_hup[8] = {
3141+ 0x00800000,
3142+ 0x0D7CF800,
3143+ 0x1E70F5FF,
3144+ 0x335FF5FE,
3145+ 0xF74949F7,
3146+ 0xF55F33FB,
3147+ 0xF5701EFE,
3148+ 0xF87C0DFF,
3149+ };
3150+
3151+ /* Coefficients for horizontal down-sampling */
3152+ static const u32 coef_hdown[8] = {
3153+ 0x24382400,
3154+ 0x28371FFE,
3155+ 0x2C361BFB,
3156+ 0x303516F9,
3157+ 0x11343311,
3158+ 0x1635300C,
3159+ 0x1B362C08,
3160+ 0x1F372804,
3161+ };
3162+
3163+ /* Coefficients for horizontal and vertical up-sampling */
3164+ static const u32 coef_hvup[2][8] = {
3165+ {
3166+ 0x00800000,
3167+ 0x037B02FF,
3168+ 0x0C6F05FE,
3169+ 0x205907FB,
3170+ 0x00404000,
3171+ 0x075920FE,
3172+ 0x056F0CFF,
3173+ 0x027B0300,
3174+ },
3175+ {
3176+ 0x00800000,
3177+ 0x0D7CF8FF,
3178+ 0x1E70F5FE,
3179+ 0x335FF5FB,
3180+ 0xF7404000,
3181+ 0xF55F33FE,
3182+ 0xF5701EFF,
3183+ 0xF87C0D00,
3184+ },
3185+ };
3186+
3187+ /* Coefficients for horizontal and vertical down-sampling */
3188+ static const u32 coef_hvdown[2][8] = {
3189+ {
3190+ 0x24382400,
3191+ 0x28391F04,
3192+ 0x2D381B08,
3193+ 0x3237170C,
3194+ 0x123737F7,
3195+ 0x173732F9,
3196+ 0x1B382DFB,
3197+ 0x1F3928FE,
3198+ },
3199+ {
3200+ 0x24382400,
3201+ 0x28371F04,
3202+ 0x2C361B08,
3203+ 0x3035160C,
3204+ 0x113433F7,
3205+ 0x163530F9,
3206+ 0x1B362CFB,
3207+ 0x1F3728FE,
3208+ },
3209+ };
3210+
3211+ /* Coefficients for vertical up-sampling */
3212+ static const u32 coef_vup[8] = {
3213+ 0x00000000,
3214+ 0x0000FF00,
3215+ 0x0000FEFF,
3216+ 0x0000FBFE,
3217+ 0x000000F7,
3218+ 0x0000FEFB,
3219+ 0x0000FFFE,
3220+ 0x000000FF,
3221+ };
3222+
3223+
3224+ /* Coefficients for vertical down-sampling */
3225+ static const u32 coef_vdown[8] = {
3226+ 0x00000000,
3227+ 0x000004FE,
3228+ 0x000008FB,
3229+ 0x00000CF9,
3230+ 0x0000F711,
3231+ 0x0000F90C,
3232+ 0x0000FB08,
3233+ 0x0000FE04,
3234+ };
3235+
3236+ const u32 *h_coef;
3237+ const u32 *hv_coef;
3238+ const u32 *hv_coef_mod;
3239+ const u32 *v_coef;
3240+ int i;
3241+
3242+ if (hscaleup)
3243+ h_coef = coef_hup;
3244+ else
3245+ h_coef = coef_hdown;
3246+
3247+ if (vscaleup) {
3248+ hv_coef = coef_hvup[five_taps];
3249+ v_coef = coef_vup;
3250+
3251+ if (hscaleup)
3252+ hv_coef_mod = NULL;
3253+ else
3254+ hv_coef_mod = coef_hvdown[five_taps];
3255+ } else {
3256+ hv_coef = coef_hvdown[five_taps];
3257+ v_coef = coef_vdown;
3258+
3259+ if (hscaleup)
3260+ hv_coef_mod = coef_hvup[five_taps];
3261+ else
3262+ hv_coef_mod = NULL;
3263+ }
3264+
3265+ for (i = 0; i < 8; i++) {
3266+ u32 h, hv;
3267+
3268+ h = h_coef[i];
3269+
3270+ hv = hv_coef[i];
3271+
3272+ if (hv_coef_mod) {
3273+ hv &= 0xffffff00;
3274+ hv |= (hv_coef_mod[i] & 0xff);
3275+ }
3276+
3277+ _dispc_write_firh_reg(plane, i, h);
3278+ _dispc_write_firhv_reg(plane, i, hv);
3279+ }
3280+
3281+ if (!five_taps)
3282+ return;
3283+
3284+ for (i = 0; i < 8; i++) {
3285+ u32 v;
3286+ v = v_coef[i];
3287+ _dispc_write_firv_reg(plane, i, v);
3288+ }
3289+}
3290+
3291+static void _dispc_setup_color_conv_coef(void)
3292+{
3293+ const struct color_conv_coef {
3294+ int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
3295+ int full_range;
3296+ } ctbl_bt601_5 = {
3297+ 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
3298+ };
3299+
3300+ const struct color_conv_coef *ct;
3301+
3302+#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
3303+
3304+ ct = &ctbl_bt601_5;
3305+
3306+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry));
3307+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb));
3308+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr));
3309+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by));
3310+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb));
3311+
3312+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry));
3313+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb));
3314+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr));
3315+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by));
3316+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb));
3317+
3318+#undef CVAL
3319+
3320+ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11);
3321+ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11);
3322+}
3323+
3324+
3325+static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr)
3326+{
3327+ const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0,
3328+ DISPC_VID_BA0(0),
3329+ DISPC_VID_BA0(1) };
3330+
3331+ dispc_write_reg(ba0_reg[plane], paddr);
3332+}
3333+
3334+static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr)
3335+{
3336+ const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1,
3337+ DISPC_VID_BA1(0),
3338+ DISPC_VID_BA1(1) };
3339+
3340+ dispc_write_reg(ba1_reg[plane], paddr);
3341+}
3342+
3343+static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y)
3344+{
3345+ const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION,
3346+ DISPC_VID_POSITION(0),
3347+ DISPC_VID_POSITION(1) };
3348+
3349+ u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
3350+ dispc_write_reg(pos_reg[plane], val);
3351+}
3352+
3353+static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
3354+{
3355+ const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE,
3356+ DISPC_VID_PICTURE_SIZE(0),
3357+ DISPC_VID_PICTURE_SIZE(1) };
3358+ u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
3359+ dispc_write_reg(siz_reg[plane], val);
3360+}
3361+
3362+static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
3363+{
3364+ u32 val;
3365+ const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0),
3366+ DISPC_VID_SIZE(1) };
3367+
3368+ BUG_ON(plane == OMAP_DSS_GFX);
3369+
3370+ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
3371+ dispc_write_reg(vsi_reg[plane-1], val);
3372+}
3373+
3374+static void _dispc_set_pix_inc(enum omap_plane plane, u16 inc)
3375+{
3376+ const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC,
3377+ DISPC_VID_PIXEL_INC(0),
3378+ DISPC_VID_PIXEL_INC(1) };
3379+
3380+ dispc_write_reg(ri_reg[plane], inc);
3381+}
3382+
3383+static void _dispc_set_row_inc(enum omap_plane plane, u16 inc)
3384+{
3385+ const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC,
3386+ DISPC_VID_ROW_INC(0),
3387+ DISPC_VID_ROW_INC(1) };
3388+
3389+ dispc_write_reg(ri_reg[plane], inc);
3390+}
3391+
3392+static void _dispc_set_color_mode(enum omap_plane plane,
3393+ enum omap_color_mode color_mode)
3394+{
3395+ u32 m = 0;
3396+
3397+ switch (color_mode) {
3398+ case OMAP_DSS_COLOR_CLUT1:
3399+ m = 0x0; break;
3400+ case OMAP_DSS_COLOR_CLUT2:
3401+ m = 0x1; break;
3402+ case OMAP_DSS_COLOR_CLUT4:
3403+ m = 0x2; break;
3404+ case OMAP_DSS_COLOR_CLUT8:
3405+ m = 0x3; break;
3406+ case OMAP_DSS_COLOR_RGB12U:
3407+ m = 0x4; break;
3408+ case OMAP_DSS_COLOR_ARGB16:
3409+ m = 0x5; break;
3410+ case OMAP_DSS_COLOR_RGB16:
3411+ m = 0x6; break;
3412+ case OMAP_DSS_COLOR_RGB24U:
3413+ m = 0x8; break;
3414+ case OMAP_DSS_COLOR_RGB24P:
3415+ m = 0x9; break;
3416+ case OMAP_DSS_COLOR_YUV2:
3417+ m = 0xa; break;
3418+ case OMAP_DSS_COLOR_UYVY:
3419+ m = 0xb; break;
3420+ case OMAP_DSS_COLOR_ARGB32:
3421+ m = 0xc; break;
3422+ case OMAP_DSS_COLOR_RGBA32:
3423+ m = 0xd; break;
3424+ case OMAP_DSS_COLOR_RGBX32:
3425+ m = 0xe; break;
3426+ default:
3427+ BUG(); break;
3428+ }
3429+
3430+ REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1);
3431+}
3432+
3433+static void _dispc_set_channel_out(enum omap_plane plane,
3434+ enum omap_channel channel)
3435+{
3436+ int shift;
3437+ u32 val;
3438+
3439+ switch (plane) {
3440+ case OMAP_DSS_GFX:
3441+ shift = 8;
3442+ break;
3443+ case OMAP_DSS_VIDEO1:
3444+ case OMAP_DSS_VIDEO2:
3445+ shift = 16;
3446+ break;
3447+ default:
3448+ BUG();
3449+ return;
3450+ }
3451+
3452+ val = dispc_read_reg(dispc_reg_att[plane]);
3453+ val = FLD_MOD(val, channel, shift, shift);
3454+ dispc_write_reg(dispc_reg_att[plane], val);
3455+}
3456+
3457+void dispc_set_burst_size(enum omap_plane plane,
3458+ enum omap_burst_size burst_size)
3459+{
3460+ int shift;
3461+ u32 val;
3462+
3463+ enable_clocks(1);
3464+
3465+ switch (plane) {
3466+ case OMAP_DSS_GFX:
3467+ shift = 6;
3468+ break;
3469+ case OMAP_DSS_VIDEO1:
3470+ case OMAP_DSS_VIDEO2:
3471+ shift = 14;
3472+ break;
3473+ default:
3474+ BUG();
3475+ return;
3476+ }
3477+
3478+ val = dispc_read_reg(dispc_reg_att[plane]);
3479+ val = FLD_MOD(val, burst_size, shift+1, shift);
3480+ dispc_write_reg(dispc_reg_att[plane], val);
3481+
3482+ enable_clocks(0);
3483+}
3484+
3485+static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
3486+{
3487+ u32 val;
3488+
3489+ BUG_ON(plane == OMAP_DSS_GFX);
3490+
3491+ val = dispc_read_reg(dispc_reg_att[plane]);
3492+ val = FLD_MOD(val, enable, 9, 9);
3493+ dispc_write_reg(dispc_reg_att[plane], val);
3494+}
3495+
3496+void dispc_set_lcd_size(u16 width, u16 height)
3497+{
3498+ u32 val;
3499+ BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
3500+ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
3501+ enable_clocks(1);
3502+ dispc_write_reg(DISPC_SIZE_LCD, val);
3503+ enable_clocks(0);
3504+}
3505+
3506+void dispc_set_digit_size(u16 width, u16 height)
3507+{
3508+ u32 val;
3509+ BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
3510+ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
3511+ enable_clocks(1);
3512+ dispc_write_reg(DISPC_SIZE_DIG, val);
3513+ enable_clocks(0);
3514+}
3515+
3516+u32 dispc_get_plane_fifo_size(enum omap_plane plane)
3517+{
3518+ const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
3519+ DISPC_VID_FIFO_SIZE_STATUS(0),
3520+ DISPC_VID_FIFO_SIZE_STATUS(1) };
3521+ u32 size;
3522+
3523+ enable_clocks(1);
3524+
3525+ if (cpu_is_omap24xx())
3526+ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0);
3527+ else if (cpu_is_omap34xx())
3528+ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0);
3529+ else
3530+ BUG();
3531+
3532+ if (cpu_is_omap34xx()) {
3533+ /* FIFOMERGE */
3534+ if (REG_GET(DISPC_CONFIG, 14, 14))
3535+ size *= 3;
3536+ }
3537+
3538+ enable_clocks(0);
3539+
3540+ return size;
3541+}
3542+
3543+void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
3544+{
3545+ const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
3546+ DISPC_VID_FIFO_THRESHOLD(0),
3547+ DISPC_VID_FIFO_THRESHOLD(1) };
3548+ u32 size;
3549+
3550+ enable_clocks(1);
3551+
3552+ size = dispc_get_plane_fifo_size(plane);
3553+
3554+ BUG_ON(low > size || high > size);
3555+
3556+ DSSDBG("fifo(%d) size %d, low/high old %u/%u, new %u/%u\n",
3557+ plane, size,
3558+ REG_GET(ftrs_reg[plane], 11, 0),
3559+ REG_GET(ftrs_reg[plane], 27, 16),
3560+ low, high);
3561+
3562+ if (cpu_is_omap24xx())
3563+ dispc_write_reg(ftrs_reg[plane],
3564+ FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0));
3565+ else
3566+ dispc_write_reg(ftrs_reg[plane],
3567+ FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0));
3568+
3569+ enable_clocks(0);
3570+}
3571+
3572+void dispc_enable_fifomerge(bool enable)
3573+{
3574+ enable_clocks(1);
3575+
3576+ DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
3577+ REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
3578+
3579+ enable_clocks(0);
3580+}
3581+
3582+static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc)
3583+{
3584+ u32 val;
3585+ const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0),
3586+ DISPC_VID_FIR(1) };
3587+
3588+ BUG_ON(plane == OMAP_DSS_GFX);
3589+
3590+ val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0);
3591+ dispc_write_reg(fir_reg[plane-1], val);
3592+}
3593+
3594+static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
3595+{
3596+ u32 val;
3597+ const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0),
3598+ DISPC_VID_ACCU0(1) };
3599+
3600+ BUG_ON(plane == OMAP_DSS_GFX);
3601+
3602+ val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
3603+ dispc_write_reg(ac0_reg[plane-1], val);
3604+}
3605+
3606+static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
3607+{
3608+ u32 val;
3609+ const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0),
3610+ DISPC_VID_ACCU1(1) };
3611+
3612+ BUG_ON(plane == OMAP_DSS_GFX);
3613+
3614+ val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
3615+ dispc_write_reg(ac1_reg[plane-1], val);
3616+}
3617+
3618+
3619+static void _dispc_set_scaling(enum omap_plane plane,
3620+ u16 orig_width, u16 orig_height,
3621+ u16 out_width, u16 out_height,
3622+ bool ilace)
3623+{
3624+ int fir_hinc;
3625+ int fir_vinc;
3626+ int hscaleup, vscaleup, five_taps;
3627+ int fieldmode = 0;
3628+ int accu0 = 0;
3629+ int accu1 = 0;
3630+ u32 l;
3631+
3632+ BUG_ON(plane == OMAP_DSS_GFX);
3633+
3634+ hscaleup = orig_width <= out_width;
3635+ vscaleup = orig_height <= out_height;
3636+ five_taps = orig_height > out_height * 2;
3637+
3638+ _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps);
3639+
3640+ if (!orig_width || orig_width == out_width)
3641+ fir_hinc = 0;
3642+ else
3643+ fir_hinc = 1024 * orig_width / out_width;
3644+
3645+ if (!orig_height || orig_height == out_height)
3646+ fir_vinc = 0;
3647+ else
3648+ fir_vinc = 1024 * orig_height / out_height;
3649+
3650+ _dispc_set_fir(plane, fir_hinc, fir_vinc);
3651+
3652+ l = dispc_read_reg(dispc_reg_att[plane]);
3653+ l &= ~((0x0f << 5) | (0x3 << 21));
3654+
3655+ l |= fir_hinc ? (1 << 5) : 0;
3656+ l |= fir_vinc ? (1 << 6) : 0;
3657+
3658+ l |= hscaleup ? 0 : (1 << 7);
3659+ l |= vscaleup ? 0 : (1 << 8);
3660+
3661+ l |= five_taps ? (1 << 21) : 0;
3662+ l |= five_taps ? (1 << 22) : 0;
3663+
3664+ dispc_write_reg(dispc_reg_att[plane], l);
3665+
3666+ if (ilace) {
3667+ if (fieldmode) {
3668+ accu0 = fir_vinc / 2;
3669+ accu1 = 0;
3670+ } else {
3671+ accu0 = 0;
3672+ accu1 = fir_vinc / 2;
3673+ if (accu1 >= 1024/2) {
3674+ accu0 = 1024/2;
3675+ accu1 -= accu0;
3676+ }
3677+ }
3678+ }
3679+
3680+ _dispc_set_vid_accu0(plane, 0, accu0);
3681+ _dispc_set_vid_accu1(plane, 0, accu1);
3682+}
3683+
3684+static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
3685+ bool mirroring, enum omap_color_mode color_mode)
3686+{
3687+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
3688+ color_mode == OMAP_DSS_COLOR_UYVY) {
3689+ int vidrot = 0;
3690+
3691+ if (mirroring) {
3692+ switch (rotation) {
3693+ case 0: vidrot = 2; break;
3694+ case 1: vidrot = 3; break;
3695+ case 2: vidrot = 0; break;
3696+ case 3: vidrot = 1; break;
3697+ }
3698+ } else {
3699+ switch (rotation) {
3700+ case 0: vidrot = 0; break;
3701+ case 1: vidrot = 1; break;
3702+ case 2: vidrot = 2; break;
3703+ case 3: vidrot = 1; break;
3704+ }
3705+ }
3706+
3707+ REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12);
3708+
3709+ if (rotation == 1 || rotation == 3)
3710+ REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18);
3711+ else
3712+ REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18);
3713+ } else {
3714+ REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12);
3715+ REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18);
3716+ }
3717+}
3718+
3719+static int pixinc(int pixels, u8 ps)
3720+{
3721+ if (pixels == 1)
3722+ return 1;
3723+ else if (pixels > 1)
3724+ return 1 + (pixels - 1) * ps;
3725+ else if (pixels < 0)
3726+ return 1 - (-pixels + 1) * ps;
3727+ else
3728+ BUG();
3729+}
3730+
3731+static void calc_rotation_offset(u8 rotation, bool mirror,
3732+ u16 screen_width,
3733+ u16 width, u16 height,
3734+ enum omap_color_mode color_mode, bool fieldmode,
3735+ unsigned *offset0, unsigned *offset1,
3736+ u16 *row_inc, u16 *pix_inc)
3737+{
3738+ u8 ps;
3739+ u16 fbw, fbh;
3740+
3741+ switch (color_mode) {
3742+ case OMAP_DSS_COLOR_RGB16:
3743+ case OMAP_DSS_COLOR_ARGB16:
3744+ ps = 2;
3745+ break;
3746+
3747+ case OMAP_DSS_COLOR_RGB24P:
3748+ ps = 3;
3749+ break;
3750+
3751+ case OMAP_DSS_COLOR_RGB24U:
3752+ case OMAP_DSS_COLOR_ARGB32:
3753+ case OMAP_DSS_COLOR_RGBA32:
3754+ case OMAP_DSS_COLOR_RGBX32:
3755+ ps = 4;
3756+ break;
3757+
3758+ case OMAP_DSS_COLOR_YUV2:
3759+ case OMAP_DSS_COLOR_UYVY:
3760+ ps = 2;
3761+ break;
3762+ default:
3763+ BUG();
3764+ return;
3765+ }
3766+
3767+ DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
3768+ width, height);
3769+
3770+ /* width & height are overlay sizes, convert to fb sizes */
3771+
3772+ if (rotation == 0 || rotation == 2) {
3773+ fbw = width;
3774+ fbh = height;
3775+ } else {
3776+ fbw = height;
3777+ fbh = width;
3778+ }
3779+
3780+ switch (rotation + mirror * 4) {
3781+ case 0:
3782+ *offset0 = 0;
3783+ if (fieldmode)
3784+ *offset1 = screen_width * ps;
3785+ else
3786+ *offset1 = 0;
3787+ *row_inc = pixinc(1 + (screen_width - fbw) +
3788+ (fieldmode ? screen_width : 0),
3789+ ps);
3790+ *pix_inc = pixinc(1, ps);
3791+ break;
3792+ case 1:
3793+ *offset0 = screen_width * (fbh - 1) * ps;
3794+ if (fieldmode)
3795+ *offset1 = *offset0 + ps;
3796+ else
3797+ *offset1 = *offset0;
3798+ *row_inc = pixinc(screen_width * (fbh - 1) + 1 +
3799+ (fieldmode ? 1 : 0), ps);
3800+ *pix_inc = pixinc(-screen_width, ps);
3801+ break;
3802+ case 2:
3803+ *offset0 = (screen_width * (fbh - 1) + fbw - 1) * ps;
3804+ if (fieldmode)
3805+ *offset1 = *offset0 - screen_width * ps;
3806+ else
3807+ *offset1 = *offset0;
3808+ *row_inc = pixinc(-1 -
3809+ (screen_width - fbw) -
3810+ (fieldmode ? screen_width : 0),
3811+ ps);
3812+ *pix_inc = pixinc(-1, ps);
3813+ break;
3814+ case 3:
3815+ *offset0 = (fbw - 1) * ps;
3816+ if (fieldmode)
3817+ *offset1 = *offset0 - ps;
3818+ else
3819+ *offset1 = *offset0;
3820+ *row_inc = pixinc(-screen_width * (fbh - 1) - 1 -
3821+ (fieldmode ? 1 : 0), ps);
3822+ *pix_inc = pixinc(screen_width, ps);
3823+ break;
3824+
3825+ /* mirroring */
3826+ case 0 + 4:
3827+ *offset0 = (fbw - 1) * ps;
3828+ if (fieldmode)
3829+ *offset1 = *offset0 + screen_width * ps;
3830+ else
3831+ *offset1 = *offset0;
3832+ *row_inc = pixinc(screen_width * 2 - 1 +
3833+ (fieldmode ? screen_width : 0),
3834+ ps);
3835+ *pix_inc = pixinc(-1, ps);
3836+ break;
3837+
3838+ case 1 + 4:
3839+ *offset0 = 0;
3840+ if (fieldmode)
3841+ *offset1 = *offset0 + screen_width * ps;
3842+ else
3843+ *offset1 = *offset0;
3844+ *row_inc = pixinc(-screen_width * (fbh - 1) + 1 +
3845+ (fieldmode ? 1 : 0),
3846+ ps);
3847+ *pix_inc = pixinc(screen_width, ps);
3848+ break;
3849+
3850+ case 2 + 4:
3851+ *offset0 = screen_width * (fbh - 1) * ps;
3852+ if (fieldmode)
3853+ *offset1 = *offset0 + screen_width * ps;
3854+ else
3855+ *offset1 = *offset0;
3856+ *row_inc = pixinc(1 - screen_width * 2 -
3857+ (fieldmode ? screen_width : 0),
3858+ ps);
3859+ *pix_inc = pixinc(1, ps);
3860+ break;
3861+
3862+ case 3 + 4:
3863+ *offset0 = (screen_width * (fbh - 1) + fbw - 1) * ps;
3864+ if (fieldmode)
3865+ *offset1 = *offset0 + screen_width * ps;
3866+ else
3867+ *offset1 = *offset0;
3868+ *row_inc = pixinc(screen_width * (fbh - 1) - 1 -
3869+ (fieldmode ? 1 : 0),
3870+ ps);
3871+ *pix_inc = pixinc(-screen_width, ps);
3872+ break;
3873+
3874+ default:
3875+ BUG();
3876+ }
3877+}
3878+
3879+static int _dispc_setup_plane(enum omap_plane plane,
3880+ enum omap_channel channel_out,
3881+ u32 paddr, u16 screen_width,
3882+ u16 pos_x, u16 pos_y,
3883+ u16 width, u16 height,
3884+ u16 out_width, u16 out_height,
3885+ enum omap_color_mode color_mode,
3886+ bool ilace,
3887+ u8 rotation, int mirror)
3888+{
3889+ const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
3890+ bool five_taps = height > out_height * 2;
3891+ bool fieldmode = 0;
3892+ int cconv = 0;
3893+ unsigned offset0, offset1;
3894+ u16 row_inc;
3895+ u16 pix_inc;
3896+
3897+ if (plane == OMAP_DSS_GFX) {
3898+ if (width != out_width || height != out_height)
3899+ return -EINVAL;
3900+
3901+ switch (color_mode) {
3902+ case OMAP_DSS_COLOR_ARGB16:
3903+ case OMAP_DSS_COLOR_RGB16:
3904+ case OMAP_DSS_COLOR_RGB24P:
3905+ case OMAP_DSS_COLOR_RGB24U:
3906+ case OMAP_DSS_COLOR_ARGB32:
3907+ case OMAP_DSS_COLOR_RGBA32:
3908+ case OMAP_DSS_COLOR_RGBX32:
3909+ break;
3910+
3911+ default:
3912+ return -EINVAL;
3913+ }
3914+ } else {
3915+ /* video plane */
3916+ if (width > (2048 >> five_taps))
3917+ return -EINVAL;
3918+
3919+ if (out_width < width / maxdownscale ||
3920+ out_width > width * 8)
3921+ return -EINVAL;
3922+
3923+ if (out_height < height / maxdownscale ||
3924+ out_height > height * 8)
3925+ return -EINVAL;
3926+
3927+ switch (color_mode) {
3928+ case OMAP_DSS_COLOR_RGB16:
3929+ case OMAP_DSS_COLOR_RGB24P:
3930+ case OMAP_DSS_COLOR_RGB24U:
3931+ case OMAP_DSS_COLOR_RGBX32:
3932+ break;
3933+
3934+ case OMAP_DSS_COLOR_ARGB16:
3935+ case OMAP_DSS_COLOR_ARGB32:
3936+ case OMAP_DSS_COLOR_RGBA32:
3937+ if (plane == OMAP_DSS_VIDEO1)
3938+ return -EINVAL;
3939+ break;
3940+
3941+ case OMAP_DSS_COLOR_YUV2:
3942+ case OMAP_DSS_COLOR_UYVY:
3943+ cconv = 1;
3944+ break;
3945+
3946+ default:
3947+ return -EINVAL;
3948+ }
3949+ }
3950+
3951+ if (ilace && height >= out_height)
3952+ fieldmode = 1;
3953+
3954+ calc_rotation_offset(rotation, mirror,
3955+ screen_width, width, height, color_mode,
3956+ fieldmode,
3957+ &offset0, &offset1, &row_inc, &pix_inc);
3958+
3959+ DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
3960+ offset0, offset1, row_inc, pix_inc);
3961+
3962+ if (ilace) {
3963+ if (fieldmode)
3964+ height /= 2;
3965+ pos_y /= 2;
3966+ out_height /= 2;
3967+
3968+ DSSDBG("adjusting for ilace: height %d, pos_y %d, "
3969+ "out_height %d\n",
3970+ height, pos_y, out_height);
3971+ }
3972+
3973+ _dispc_set_channel_out(plane, channel_out);
3974+ _dispc_set_color_mode(plane, color_mode);
3975+
3976+ _dispc_set_plane_ba0(plane, paddr + offset0);
3977+ _dispc_set_plane_ba1(plane, paddr + offset1);
3978+
3979+ _dispc_set_row_inc(plane, row_inc);
3980+ _dispc_set_pix_inc(plane, pix_inc);
3981+
3982+ DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height,
3983+ out_width, out_height);
3984+
3985+ _dispc_set_plane_pos(plane, pos_x, pos_y);
3986+
3987+ _dispc_set_pic_size(plane, width, height);
3988+
3989+ if (plane != OMAP_DSS_GFX) {
3990+ _dispc_set_scaling(plane, width, height,
3991+ out_width, out_height,
3992+ ilace);
3993+ _dispc_set_vid_size(plane, out_width, out_height);
3994+ _dispc_set_vid_color_conv(plane, cconv);
3995+ }
3996+
3997+ _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
3998+
3999+ return 0;
4000+}
4001+
4002+static void _dispc_enable_plane(enum omap_plane plane, bool enable)
4003+{
4004+ REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0);
4005+}
4006+
4007+static void dispc_disable_isr(void *data, u32 mask)
4008+{
4009+ struct completion *compl = data;
4010+ complete(compl);
4011+}
4012+
4013+static void _enable_lcd_out(bool enable)
4014+{
4015+ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
4016+}
4017+
4018+void dispc_enable_lcd_out(bool enable)
4019+{
4020+ struct completion frame_done_completion;
4021+ bool is_on;
4022+ int r;
4023+
4024+ enable_clocks(1);
4025+
4026+ /* When we disable LCD output, we need to wait until frame is done.
4027+ * Otherwise the DSS is still working, and turning off the clocks
4028+ * prevents DSS from going to OFF mode */
4029+ is_on = REG_GET(DISPC_CONTROL, 0, 0);
4030+
4031+ if (!enable && is_on) {
4032+ init_completion(&frame_done_completion);
4033+
4034+ r = omap_dispc_register_isr(dispc_disable_isr,
4035+ &frame_done_completion,
4036+ DISPC_IRQ_FRAMEDONE);
4037+
4038+ if (r)
4039+ DSSERR("failed to register FRAMEDONE isr\n");
4040+ }
4041+
4042+ _enable_lcd_out(enable);
4043+
4044+ if (!enable && is_on) {
4045+ if (!wait_for_completion_timeout(&frame_done_completion,
4046+ msecs_to_jiffies(100)))
4047+ DSSERR("timeout waiting for FRAME DONE\n");
4048+
4049+ r = omap_dispc_unregister_isr(dispc_disable_isr,
4050+ &frame_done_completion,
4051+ DISPC_IRQ_FRAMEDONE);
4052+
4053+ if (r)
4054+ DSSERR("failed to unregister FRAMEDONE isr\n");
4055+ }
4056+
4057+ enable_clocks(0);
4058+}
4059+
4060+static void _enable_digit_out(bool enable)
4061+{
4062+ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
4063+}
4064+
4065+void dispc_enable_digit_out(bool enable)
4066+{
4067+ struct completion frame_done_completion;
4068+ int r;
4069+
4070+ enable_clocks(1);
4071+
4072+ if (REG_GET(DISPC_CONTROL, 1, 1) == enable) {
4073+ enable_clocks(0);
4074+ return;
4075+ }
4076+
4077+ if (enable) {
4078+ /* When we enable digit output, we'll get an extra digit
4079+ * sync lost interrupt, that we need to ignore */
4080+ dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
4081+ omap_dispc_set_irqs();
4082+ }
4083+
4084+ /* When we disable digit output, we need to wait until fields are done.
4085+ * Otherwise the DSS is still working, and turning off the clocks
4086+ * prevents DSS from going to OFF mode. And when enabling, we need to
4087+ * wait for the extra sync losts */
4088+ init_completion(&frame_done_completion);
4089+
4090+ r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
4091+ DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
4092+ if (r)
4093+ DSSERR("failed to register EVSYNC isr\n");
4094+
4095+ _enable_digit_out(enable);
4096+
4097+ /* XXX I understand from TRM that we should only wait for the
4098+ * current field to complete. But it seems we have to wait
4099+ * for both fields */
4100+ if (!wait_for_completion_timeout(&frame_done_completion,
4101+ msecs_to_jiffies(100)))
4102+ DSSERR("timeout waiting for EVSYNC\n");
4103+
4104+ if (!wait_for_completion_timeout(&frame_done_completion,
4105+ msecs_to_jiffies(100)))
4106+ DSSERR("timeout waiting for EVSYNC\n");
4107+
4108+ r = omap_dispc_unregister_isr(dispc_disable_isr,
4109+ &frame_done_completion,
4110+ DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
4111+ if (r)
4112+ DSSERR("failed to unregister EVSYNC isr\n");
4113+
4114+ if (enable) {
4115+ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
4116+ dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
4117+ omap_dispc_set_irqs();
4118+ }
4119+
4120+ enable_clocks(0);
4121+}
4122+
4123+void dispc_lcd_enable_signal_polarity(bool act_high)
4124+{
4125+ enable_clocks(1);
4126+ REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
4127+ enable_clocks(0);
4128+}
4129+
4130+void dispc_lcd_enable_signal(bool enable)
4131+{
4132+ enable_clocks(1);
4133+ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
4134+ enable_clocks(0);
4135+}
4136+
4137+void dispc_pck_free_enable(bool enable)
4138+{
4139+ enable_clocks(1);
4140+ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
4141+ enable_clocks(0);
4142+}
4143+
4144+void dispc_enable_fifohandcheck(bool enable)
4145+{
4146+ enable_clocks(1);
4147+ REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
4148+ enable_clocks(0);
4149+}
4150+
4151+
4152+void dispc_set_lcd_display_type(enum omap_lcd_display_type type)
4153+{
4154+ int mode;
4155+
4156+ switch (type) {
4157+ case OMAP_DSS_LCD_DISPLAY_STN:
4158+ mode = 0;
4159+ break;
4160+
4161+ case OMAP_DSS_LCD_DISPLAY_TFT:
4162+ mode = 1;
4163+ break;
4164+
4165+ default:
4166+ BUG();
4167+ return;
4168+ }
4169+
4170+ enable_clocks(1);
4171+ REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
4172+ enable_clocks(0);
4173+}
4174+
4175+void dispc_set_loadmode(enum omap_dss_load_mode mode)
4176+{
4177+ enable_clocks(1);
4178+ REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
4179+ enable_clocks(0);
4180+}
4181+
4182+
4183+void dispc_set_default_color(enum omap_channel channel, u32 color)
4184+{
4185+ const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
4186+ DISPC_DEFAULT_COLOR1 };
4187+
4188+ enable_clocks(1);
4189+ dispc_write_reg(def_reg[channel], color);
4190+ enable_clocks(0);
4191+}
4192+
4193+u32 dispc_get_default_color(enum omap_channel channel)
4194+{
4195+ const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
4196+ DISPC_DEFAULT_COLOR1 };
4197+ u32 l;
4198+
4199+ BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT &&
4200+ channel != OMAP_DSS_CHANNEL_LCD);
4201+
4202+ enable_clocks(1);
4203+ l = dispc_read_reg(def_reg[channel]);
4204+ enable_clocks(0);
4205+
4206+ return l;
4207+}
4208+
4209+void dispc_set_trans_key(enum omap_channel ch,
4210+ enum omap_dss_color_key_type type,
4211+ u32 trans_key)
4212+{
4213+ const struct dispc_reg tr_reg[] = {
4214+ DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
4215+
4216+ enable_clocks(1);
4217+ if (ch == OMAP_DSS_CHANNEL_LCD)
4218+ REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
4219+ else /* OMAP_DSS_CHANNEL_DIGIT */
4220+ REG_FLD_MOD(DISPC_CONFIG, type, 13, 13);
4221+
4222+ dispc_write_reg(tr_reg[ch], trans_key);
4223+ enable_clocks(0);
4224+}
4225+
4226+void dispc_get_trans_key(enum omap_channel ch,
4227+ enum omap_dss_color_key_type *type,
4228+ u32 *trans_key)
4229+{
4230+ const struct dispc_reg tr_reg[] = {
4231+ DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
4232+
4233+ enable_clocks(1);
4234+ if (type) {
4235+ if (ch == OMAP_DSS_CHANNEL_LCD)
4236+ *type = REG_GET(DISPC_CONFIG, 11, 11) >> 11;
4237+ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
4238+ *type = REG_GET(DISPC_CONFIG, 13, 13) >> 13;
4239+ else
4240+ BUG();
4241+ }
4242+
4243+ if (trans_key)
4244+ *trans_key = dispc_read_reg(tr_reg[ch]);
4245+ enable_clocks(0);
4246+}
4247+
4248+void dispc_enable_trans_key(enum omap_channel ch, bool enable)
4249+{
4250+ enable_clocks(1);
4251+ if (ch == OMAP_DSS_CHANNEL_LCD)
4252+ REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
4253+ else /* OMAP_DSS_CHANNEL_DIGIT */
4254+ REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
4255+ enable_clocks(0);
4256+}
4257+
4258+bool dispc_trans_key_enabled(enum omap_channel ch)
4259+{
4260+ bool enabled;
4261+
4262+ enable_clocks(1);
4263+ if (ch == OMAP_DSS_CHANNEL_LCD)
4264+ enabled = REG_GET(DISPC_CONFIG, 10, 10);
4265+ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
4266+ enabled = REG_GET(DISPC_CONFIG, 12, 12);
4267+ else BUG();
4268+ enable_clocks(0);
4269+
4270+ return enabled;
4271+}
4272+
4273+
4274+void dispc_set_tft_data_lines(u8 data_lines)
4275+{
4276+ int code;
4277+
4278+ switch (data_lines) {
4279+ case 12:
4280+ code = 0;
4281+ break;
4282+ case 16:
4283+ code = 1;
4284+ break;
4285+ case 18:
4286+ code = 2;
4287+ break;
4288+ case 24:
4289+ code = 3;
4290+ break;
4291+ default:
4292+ BUG();
4293+ return;
4294+ }
4295+
4296+ enable_clocks(1);
4297+ REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
4298+ enable_clocks(0);
4299+}
4300+
4301+void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode)
4302+{
4303+ u32 l;
4304+ int stallmode;
4305+ int gpout0 = 1;
4306+ int gpout1;
4307+
4308+ switch (mode) {
4309+ case OMAP_DSS_PARALLELMODE_BYPASS:
4310+ stallmode = 0;
4311+ gpout1 = 1;
4312+ break;
4313+
4314+ case OMAP_DSS_PARALLELMODE_RFBI:
4315+ stallmode = 1;
4316+ gpout1 = 0;
4317+ break;
4318+
4319+ case OMAP_DSS_PARALLELMODE_DSI:
4320+ stallmode = 1;
4321+ gpout1 = 1;
4322+ break;
4323+
4324+ default:
4325+ BUG();
4326+ return;
4327+ }
4328+
4329+ enable_clocks(1);
4330+
4331+ l = dispc_read_reg(DISPC_CONTROL);
4332+
4333+ l = FLD_MOD(l, stallmode, 11, 11);
4334+ l = FLD_MOD(l, gpout0, 15, 15);
4335+ l = FLD_MOD(l, gpout1, 16, 16);
4336+
4337+ dispc_write_reg(DISPC_CONTROL, l);
4338+
4339+ enable_clocks(0);
4340+}
4341+
4342+static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp,
4343+ int vsw, int vfp, int vbp)
4344+{
4345+ u32 timing_h, timing_v;
4346+
4347+ if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
4348+ BUG_ON(hsw < 1 || hsw > 64);
4349+ BUG_ON(hfp < 1 || hfp > 256);
4350+ BUG_ON(hbp < 1 || hbp > 256);
4351+
4352+ BUG_ON(vsw < 1 || vsw > 64);
4353+ BUG_ON(vfp < 0 || vfp > 255);
4354+ BUG_ON(vbp < 0 || vbp > 255);
4355+
4356+ timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) |
4357+ FLD_VAL(hbp-1, 27, 20);
4358+
4359+ timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) |
4360+ FLD_VAL(vbp, 27, 20);
4361+ } else {
4362+ BUG_ON(hsw < 1 || hsw > 256);
4363+ BUG_ON(hfp < 1 || hfp > 4096);
4364+ BUG_ON(hbp < 1 || hbp > 4096);
4365+
4366+ BUG_ON(vsw < 1 || vsw > 256);
4367+ BUG_ON(vfp < 0 || vfp > 4095);
4368+ BUG_ON(vbp < 0 || vbp > 4095);
4369+
4370+ timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
4371+ FLD_VAL(hbp-1, 31, 20);
4372+
4373+ timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
4374+ FLD_VAL(vbp, 31, 20);
4375+ }
4376+
4377+ enable_clocks(1);
4378+ dispc_write_reg(DISPC_TIMING_H, timing_h);
4379+ dispc_write_reg(DISPC_TIMING_V, timing_v);
4380+ enable_clocks(0);
4381+}
4382+
4383+/* change name to mode? */
4384+void dispc_set_lcd_timings(struct omap_video_timings *timings)
4385+{
4386+ unsigned xtot, ytot;
4387+ unsigned long ht, vt;
4388+
4389+ _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp,
4390+ timings->vsw, timings->vfp, timings->vbp);
4391+
4392+ dispc_set_lcd_size(timings->x_res, timings->y_res);
4393+
4394+ xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
4395+ ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
4396+
4397+ ht = (timings->pixel_clock * 1000) / xtot;
4398+ vt = (timings->pixel_clock * 1000) / xtot / ytot;
4399+
4400+ DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res);
4401+ DSSDBG("pck %u\n", timings->pixel_clock);
4402+ DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
4403+ timings->hsw, timings->hfp, timings->hbp,
4404+ timings->vsw, timings->vfp, timings->vbp);
4405+
4406+ DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
4407+}
4408+
4409+void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div)
4410+{
4411+ BUG_ON(lck_div < 1);
4412+ BUG_ON(pck_div < 2);
4413+
4414+ enable_clocks(1);
4415+ dispc_write_reg(DISPC_DIVISOR,
4416+ FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
4417+ enable_clocks(0);
4418+}
4419+
4420+static void dispc_get_lcd_divisor(int *lck_div, int *pck_div)
4421+{
4422+ u32 l;
4423+ l = dispc_read_reg(DISPC_DIVISOR);
4424+ *lck_div = FLD_GET(l, 23, 16);
4425+ *pck_div = FLD_GET(l, 7, 0);
4426+}
4427+
4428+unsigned long dispc_fclk_rate(void)
4429+{
4430+ unsigned long r = 0;
4431+
4432+ if (dss_get_dispc_clk_source() == 0)
4433+ r = dss_clk_get_rate(DSS_CLK_FCK1);
4434+ else
4435+#ifdef CONFIG_OMAP2_DSS_DSI
4436+ r = dsi_get_dsi1_pll_rate();
4437+#else
4438+ BUG();
4439+#endif
4440+ return r;
4441+}
4442+
4443+unsigned long dispc_pclk_rate(void)
4444+{
4445+ int lcd, pcd;
4446+ unsigned long r;
4447+ u32 l;
4448+
4449+ l = dispc_read_reg(DISPC_DIVISOR);
4450+
4451+ lcd = FLD_GET(l, 23, 16);
4452+ pcd = FLD_GET(l, 7, 0);
4453+
4454+ r = dispc_fclk_rate();
4455+
4456+ return r / lcd / pcd;
4457+}
4458+
4459+void dispc_dump_clocks(struct seq_file *s)
4460+{
4461+ int lcd, pcd;
4462+
4463+ enable_clocks(1);
4464+
4465+ dispc_get_lcd_divisor(&lcd, &pcd);
4466+
4467+ seq_printf(s, "- dispc -\n");
4468+
4469+ seq_printf(s, "dispc fclk source = %s\n",
4470+ dss_get_dispc_clk_source() == 0 ?
4471+ "dss1_alwon_fclk" : "dsi1_pll_fclk");
4472+
4473+ seq_printf(s, "pixel clk = %lu / %d / %d = %lu\n",
4474+ dispc_fclk_rate(),
4475+ lcd, pcd,
4476+ dispc_pclk_rate());
4477+
4478+ enable_clocks(0);
4479+}
4480+
4481+void dispc_dump_regs(struct seq_file *s)
4482+{
4483+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r))
4484+
4485+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
4486+
4487+ DUMPREG(DISPC_REVISION);
4488+ DUMPREG(DISPC_SYSCONFIG);
4489+ DUMPREG(DISPC_SYSSTATUS);
4490+ DUMPREG(DISPC_IRQSTATUS);
4491+ DUMPREG(DISPC_IRQENABLE);
4492+ DUMPREG(DISPC_CONTROL);
4493+ DUMPREG(DISPC_CONFIG);
4494+ DUMPREG(DISPC_CAPABLE);
4495+ DUMPREG(DISPC_DEFAULT_COLOR0);
4496+ DUMPREG(DISPC_DEFAULT_COLOR1);
4497+ DUMPREG(DISPC_TRANS_COLOR0);
4498+ DUMPREG(DISPC_TRANS_COLOR1);
4499+ DUMPREG(DISPC_LINE_STATUS);
4500+ DUMPREG(DISPC_LINE_NUMBER);
4501+ DUMPREG(DISPC_TIMING_H);
4502+ DUMPREG(DISPC_TIMING_V);
4503+ DUMPREG(DISPC_POL_FREQ);
4504+ DUMPREG(DISPC_DIVISOR);
4505+ DUMPREG(DISPC_GLOBAL_ALPHA);
4506+ DUMPREG(DISPC_SIZE_DIG);
4507+ DUMPREG(DISPC_SIZE_LCD);
4508+
4509+ DUMPREG(DISPC_GFX_BA0);
4510+ DUMPREG(DISPC_GFX_BA1);
4511+ DUMPREG(DISPC_GFX_POSITION);
4512+ DUMPREG(DISPC_GFX_SIZE);
4513+ DUMPREG(DISPC_GFX_ATTRIBUTES);
4514+ DUMPREG(DISPC_GFX_FIFO_THRESHOLD);
4515+ DUMPREG(DISPC_GFX_FIFO_SIZE_STATUS);
4516+ DUMPREG(DISPC_GFX_ROW_INC);
4517+ DUMPREG(DISPC_GFX_PIXEL_INC);
4518+ DUMPREG(DISPC_GFX_WINDOW_SKIP);
4519+ DUMPREG(DISPC_GFX_TABLE_BA);
4520+
4521+ DUMPREG(DISPC_DATA_CYCLE1);
4522+ DUMPREG(DISPC_DATA_CYCLE2);
4523+ DUMPREG(DISPC_DATA_CYCLE3);
4524+
4525+ DUMPREG(DISPC_CPR_COEF_R);
4526+ DUMPREG(DISPC_CPR_COEF_G);
4527+ DUMPREG(DISPC_CPR_COEF_B);
4528+
4529+ DUMPREG(DISPC_GFX_PRELOAD);
4530+
4531+ DUMPREG(DISPC_VID_BA0(0));
4532+ DUMPREG(DISPC_VID_BA1(0));
4533+ DUMPREG(DISPC_VID_POSITION(0));
4534+ DUMPREG(DISPC_VID_SIZE(0));
4535+ DUMPREG(DISPC_VID_ATTRIBUTES(0));
4536+ DUMPREG(DISPC_VID_FIFO_THRESHOLD(0));
4537+ DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(0));
4538+ DUMPREG(DISPC_VID_ROW_INC(0));
4539+ DUMPREG(DISPC_VID_PIXEL_INC(0));
4540+ DUMPREG(DISPC_VID_FIR(0));
4541+ DUMPREG(DISPC_VID_PICTURE_SIZE(0));
4542+ DUMPREG(DISPC_VID_ACCU0(0));
4543+ DUMPREG(DISPC_VID_ACCU1(0));
4544+
4545+ DUMPREG(DISPC_VID_BA0(1));
4546+ DUMPREG(DISPC_VID_BA1(1));
4547+ DUMPREG(DISPC_VID_POSITION(1));
4548+ DUMPREG(DISPC_VID_SIZE(1));
4549+ DUMPREG(DISPC_VID_ATTRIBUTES(1));
4550+ DUMPREG(DISPC_VID_FIFO_THRESHOLD(1));
4551+ DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1));
4552+ DUMPREG(DISPC_VID_ROW_INC(1));
4553+ DUMPREG(DISPC_VID_PIXEL_INC(1));
4554+ DUMPREG(DISPC_VID_FIR(1));
4555+ DUMPREG(DISPC_VID_PICTURE_SIZE(1));
4556+ DUMPREG(DISPC_VID_ACCU0(1));
4557+ DUMPREG(DISPC_VID_ACCU1(1));
4558+
4559+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 0));
4560+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 1));
4561+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 2));
4562+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 3));
4563+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 4));
4564+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 5));
4565+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 6));
4566+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 7));
4567+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 0));
4568+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 1));
4569+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 2));
4570+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 3));
4571+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 4));
4572+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 5));
4573+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 6));
4574+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 7));
4575+ DUMPREG(DISPC_VID_CONV_COEF(0, 0));
4576+ DUMPREG(DISPC_VID_CONV_COEF(0, 1));
4577+ DUMPREG(DISPC_VID_CONV_COEF(0, 2));
4578+ DUMPREG(DISPC_VID_CONV_COEF(0, 3));
4579+ DUMPREG(DISPC_VID_CONV_COEF(0, 4));
4580+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 0));
4581+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 1));
4582+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 2));
4583+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 3));
4584+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 4));
4585+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 5));
4586+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 6));
4587+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 7));
4588+
4589+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 0));
4590+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 1));
4591+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 2));
4592+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 3));
4593+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 4));
4594+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 5));
4595+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 6));
4596+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 7));
4597+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 0));
4598+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 1));
4599+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 2));
4600+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 3));
4601+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 4));
4602+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 5));
4603+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 6));
4604+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 7));
4605+ DUMPREG(DISPC_VID_CONV_COEF(1, 0));
4606+ DUMPREG(DISPC_VID_CONV_COEF(1, 1));
4607+ DUMPREG(DISPC_VID_CONV_COEF(1, 2));
4608+ DUMPREG(DISPC_VID_CONV_COEF(1, 3));
4609+ DUMPREG(DISPC_VID_CONV_COEF(1, 4));
4610+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 0));
4611+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 1));
4612+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 2));
4613+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 3));
4614+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 4));
4615+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 5));
4616+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 6));
4617+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 7));
4618+
4619+ DUMPREG(DISPC_VID_PRELOAD(0));
4620+ DUMPREG(DISPC_VID_PRELOAD(1));
4621+
4622+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
4623+#undef DUMPREG
4624+}
4625+
4626+static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc,
4627+ bool ihs, bool ivs, u8 acbi, u8 acb)
4628+{
4629+ u32 l = 0;
4630+
4631+ DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n",
4632+ onoff, rf, ieo, ipc, ihs, ivs, acbi, acb);
4633+
4634+ l |= FLD_VAL(onoff, 17, 17);
4635+ l |= FLD_VAL(rf, 16, 16);
4636+ l |= FLD_VAL(ieo, 15, 15);
4637+ l |= FLD_VAL(ipc, 14, 14);
4638+ l |= FLD_VAL(ihs, 13, 13);
4639+ l |= FLD_VAL(ivs, 12, 12);
4640+ l |= FLD_VAL(acbi, 11, 8);
4641+ l |= FLD_VAL(acb, 7, 0);
4642+
4643+ enable_clocks(1);
4644+ dispc_write_reg(DISPC_POL_FREQ, l);
4645+ enable_clocks(0);
4646+}
4647+
4648+void dispc_set_pol_freq(struct omap_panel *panel)
4649+{
4650+ _dispc_set_pol_freq((panel->config & OMAP_DSS_LCD_ONOFF) != 0,
4651+ (panel->config & OMAP_DSS_LCD_RF) != 0,
4652+ (panel->config & OMAP_DSS_LCD_IEO) != 0,
4653+ (panel->config & OMAP_DSS_LCD_IPC) != 0,
4654+ (panel->config & OMAP_DSS_LCD_IHS) != 0,
4655+ (panel->config & OMAP_DSS_LCD_IVS) != 0,
4656+ panel->acbi, panel->acb);
4657+}
4658+
4659+void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
4660+ u16 *lck_div, u16 *pck_div)
4661+{
4662+ u16 pcd_min = is_tft ? 2 : 3;
4663+ unsigned long best_pck;
4664+ u16 best_ld, cur_ld;
4665+ u16 best_pd, cur_pd;
4666+
4667+ best_pck = 0;
4668+ best_ld = 0;
4669+ best_pd = 0;
4670+
4671+ for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
4672+ unsigned long lck = fck / cur_ld;
4673+
4674+ for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) {
4675+ unsigned long pck = lck / cur_pd;
4676+ long old_delta = abs(best_pck - req_pck);
4677+ long new_delta = abs(pck - req_pck);
4678+
4679+ if (best_pck == 0 || new_delta < old_delta) {
4680+ best_pck = pck;
4681+ best_ld = cur_ld;
4682+ best_pd = cur_pd;
4683+
4684+ if (pck == req_pck)
4685+ goto found;
4686+ }
4687+
4688+ if (pck < req_pck)
4689+ break;
4690+ }
4691+
4692+ if (lck / pcd_min < req_pck)
4693+ break;
4694+ }
4695+
4696+found:
4697+ *lck_div = best_ld;
4698+ *pck_div = best_pd;
4699+}
4700+
4701+int dispc_calc_clock_div(bool is_tft, unsigned long req_pck,
4702+ struct dispc_clock_info *cinfo)
4703+{
4704+ unsigned long prate;
4705+ struct dispc_clock_info cur, best;
4706+ int match = 0;
4707+ int min_fck_per_pck;
4708+ unsigned long fck_rate = dss_clk_get_rate(DSS_CLK_FCK1);
4709+
4710+ if (cpu_is_omap34xx())
4711+ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
4712+ else
4713+ prate = 0;
4714+
4715+ if (req_pck == dispc.cache_req_pck &&
4716+ ((cpu_is_omap34xx() && prate == dispc.cache_prate) ||
4717+ dispc.cache_cinfo.fck == fck_rate)) {
4718+ DSSDBG("dispc clock info found from cache.\n");
4719+ *cinfo = dispc.cache_cinfo;
4720+ return 0;
4721+ }
4722+
4723+ min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
4724+
4725+ if (min_fck_per_pck &&
4726+ req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
4727+ DSSERR("Requested pixel clock not possible with the current "
4728+ "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
4729+ "the constraint off.\n");
4730+ min_fck_per_pck = 0;
4731+ }
4732+
4733+retry:
4734+ memset(&cur, 0, sizeof(cur));
4735+ memset(&best, 0, sizeof(best));
4736+
4737+ if (cpu_is_omap24xx()) {
4738+ /* XXX can we change the clock on omap2? */
4739+ cur.fck = dss_clk_get_rate(DSS_CLK_FCK1);
4740+ cur.fck_div = 1;
4741+
4742+ match = 1;
4743+
4744+ find_lck_pck_divs(is_tft, req_pck, cur.fck,
4745+ &cur.lck_div, &cur.pck_div);
4746+
4747+ cur.lck = cur.fck / cur.lck_div;
4748+ cur.pck = cur.lck / cur.pck_div;
4749+
4750+ best = cur;
4751+
4752+ goto found;
4753+ } else if (cpu_is_omap34xx()) {
4754+ for (cur.fck_div = 16; cur.fck_div > 0; --cur.fck_div) {
4755+ cur.fck = prate / cur.fck_div * 2;
4756+
4757+ if (cur.fck > DISPC_MAX_FCK)
4758+ continue;
4759+
4760+ if (min_fck_per_pck &&
4761+ cur.fck < req_pck * min_fck_per_pck)
4762+ continue;
4763+
4764+ match = 1;
4765+
4766+ find_lck_pck_divs(is_tft, req_pck, cur.fck,
4767+ &cur.lck_div, &cur.pck_div);
4768+
4769+ cur.lck = cur.fck / cur.lck_div;
4770+ cur.pck = cur.lck / cur.pck_div;
4771+
4772+ if (abs(cur.pck - req_pck) < abs(best.pck - req_pck)) {
4773+ best = cur;
4774+
4775+ if (cur.pck == req_pck)
4776+ goto found;
4777+ }
4778+ }
4779+ } else {
4780+ BUG();
4781+ }
4782+
4783+found:
4784+ if (!match) {
4785+ if (min_fck_per_pck) {
4786+ DSSERR("Could not find suitable clock settings.\n"
4787+ "Turning FCK/PCK constraint off and"
4788+ "trying again.\n");
4789+ min_fck_per_pck = 0;
4790+ goto retry;
4791+ }
4792+
4793+ DSSERR("Could not find suitable clock settings.\n");
4794+
4795+ return -EINVAL;
4796+ }
4797+
4798+ if (cinfo)
4799+ *cinfo = best;
4800+
4801+ dispc.cache_req_pck = req_pck;
4802+ dispc.cache_prate = prate;
4803+ dispc.cache_cinfo = best;
4804+
4805+ return 0;
4806+}
4807+
4808+int dispc_set_clock_div(struct dispc_clock_info *cinfo)
4809+{
4810+ unsigned long prate;
4811+ int r;
4812+
4813+ if (cpu_is_omap34xx()) {
4814+ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
4815+ DSSDBG("dpll4_m4 = %ld\n", prate);
4816+ }
4817+
4818+ DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
4819+ DSSDBG("lck = %ld (%d)\n", cinfo->lck, cinfo->lck_div);
4820+ DSSDBG("pck = %ld (%d)\n", cinfo->pck, cinfo->pck_div);
4821+
4822+ if (cpu_is_omap34xx()) {
4823+ r = clk_set_rate(dispc.dpll4_m4_ck, prate / cinfo->fck_div);
4824+ if (r)
4825+ return r;
4826+ }
4827+
4828+ dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div);
4829+
4830+ return 0;
4831+}
4832+
4833+int dispc_get_clock_div(struct dispc_clock_info *cinfo)
4834+{
4835+ cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1);
4836+
4837+ if (cpu_is_omap34xx()) {
4838+ unsigned long prate;
4839+ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
4840+ cinfo->fck_div = prate / (cinfo->fck / 2);
4841+ } else {
4842+ cinfo->fck_div = 0;
4843+ }
4844+
4845+ cinfo->lck_div = REG_GET(DISPC_DIVISOR, 23, 16);
4846+ cinfo->pck_div = REG_GET(DISPC_DIVISOR, 7, 0);
4847+
4848+ cinfo->lck = cinfo->fck / cinfo->lck_div;
4849+ cinfo->pck = cinfo->lck / cinfo->pck_div;
4850+
4851+ return 0;
4852+}
4853+
4854+static void omap_dispc_set_irqs(void)
4855+{
4856+ unsigned long flags;
4857+ u32 mask = dispc.irq_error_mask;
4858+ int i;
4859+ struct omap_dispc_isr_data *isr_data;
4860+
4861+ spin_lock_irqsave(&dispc.irq_lock, flags);
4862+
4863+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
4864+ isr_data = &dispc.registered_isr[i];
4865+
4866+ if (isr_data->isr == NULL)
4867+ continue;
4868+
4869+ mask |= isr_data->mask;
4870+ }
4871+
4872+ enable_clocks(1);
4873+ dispc_write_reg(DISPC_IRQENABLE, mask);
4874+ enable_clocks(0);
4875+
4876+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
4877+}
4878+
4879+int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
4880+{
4881+ int i;
4882+ int ret;
4883+ unsigned long flags;
4884+ struct omap_dispc_isr_data *isr_data;
4885+
4886+ if (isr == NULL)
4887+ return -EINVAL;
4888+
4889+ spin_lock_irqsave(&dispc.irq_lock, flags);
4890+
4891+ /* check for duplicate entry */
4892+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
4893+ isr_data = &dispc.registered_isr[i];
4894+ if (isr_data->isr == isr && isr_data->arg == arg &&
4895+ isr_data->mask == mask) {
4896+ ret = -EINVAL;
4897+ goto err;
4898+ }
4899+ }
4900+
4901+ isr_data = NULL;
4902+ ret = -EBUSY;
4903+
4904+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
4905+ isr_data = &dispc.registered_isr[i];
4906+
4907+ if (isr_data->isr != NULL)
4908+ continue;
4909+
4910+ isr_data->isr = isr;
4911+ isr_data->arg = arg;
4912+ isr_data->mask = mask;
4913+ ret = 0;
4914+
4915+ break;
4916+ }
4917+err:
4918+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
4919+
4920+ if (ret == 0)
4921+ omap_dispc_set_irqs();
4922+
4923+ return ret;
4924+}
4925+EXPORT_SYMBOL(omap_dispc_register_isr);
4926+
4927+int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
4928+{
4929+ int i;
4930+ unsigned long flags;
4931+ int ret = -EINVAL;
4932+ struct omap_dispc_isr_data *isr_data;
4933+
4934+ spin_lock_irqsave(&dispc.irq_lock, flags);
4935+
4936+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
4937+ isr_data = &dispc.registered_isr[i];
4938+ if (isr_data->isr != isr || isr_data->arg != arg ||
4939+ isr_data->mask != mask)
4940+ continue;
4941+
4942+ /* found the correct isr */
4943+
4944+ isr_data->isr = NULL;
4945+ isr_data->arg = NULL;
4946+ isr_data->mask = 0;
4947+
4948+ ret = 0;
4949+ break;
4950+ }
4951+
4952+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
4953+
4954+ if (ret == 0)
4955+ omap_dispc_set_irqs();
4956+
4957+ return ret;
4958+}
4959+EXPORT_SYMBOL(omap_dispc_unregister_isr);
4960+
4961+#ifdef DEBUG
4962+static void print_irq_status(u32 status)
4963+{
4964+ if ((status & dispc.irq_error_mask) == 0)
4965+ return;
4966+
4967+ printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status);
4968+
4969+#define PIS(x) \
4970+ if (status & DISPC_IRQ_##x) \
4971+ printk(#x " ");
4972+ PIS(GFX_FIFO_UNDERFLOW);
4973+ PIS(OCP_ERR);
4974+ PIS(VID1_FIFO_UNDERFLOW);
4975+ PIS(VID2_FIFO_UNDERFLOW);
4976+ PIS(SYNC_LOST);
4977+ PIS(SYNC_LOST_DIGIT);
4978+#undef PIS
4979+
4980+ printk("\n");
4981+}
4982+#endif
4983+
4984+/* Called from dss.c. Note that we don't touch clocks here,
4985+ * but we presume they are on because we got an IRQ. However,
4986+ * an irq handler may turn the clocks off, so we may not have
4987+ * clock later in the function. */
4988+void dispc_irq_handler(void)
4989+{
4990+ int i;
4991+ u32 irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
4992+ u32 handledirqs = 0;
4993+ u32 unhandled_errors;
4994+ struct omap_dispc_isr_data *isr_data;
4995+
4996+#ifdef DEBUG
4997+ if (dss_debug)
4998+ print_irq_status(irqstatus);
4999+#endif
5000+ /* Ack the interrupt. Do it here before clocks are possibly turned
5001+ * off */
5002+ dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
5003+
5004+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
5005+ isr_data = &dispc.registered_isr[i];
5006+
5007+ if (!isr_data->isr)
5008+ continue;
5009+
5010+ if (isr_data->mask & irqstatus) {
5011+ isr_data->isr(isr_data->arg, irqstatus);
5012+ handledirqs |= isr_data->mask;
5013+ }
5014+ }
5015+
5016+ unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
5017+
5018+ if (unhandled_errors) {
5019+ spin_lock(&dispc.error_lock);
5020+ dispc.error_irqs |= unhandled_errors;
5021+ spin_unlock(&dispc.error_lock);
5022+
5023+ dispc.irq_error_mask &= ~unhandled_errors;
5024+ omap_dispc_set_irqs();
5025+
5026+ schedule_work(&dispc.error_work);
5027+ }
5028+}
5029+
5030+static void dispc_error_worker(struct work_struct *work)
5031+{
5032+ int i;
5033+ u32 errors;
5034+ unsigned long flags;
5035+
5036+ spin_lock_irqsave(&dispc.error_lock, flags);
5037+ errors = dispc.error_irqs;
5038+ dispc.error_irqs = 0;
5039+ spin_unlock_irqrestore(&dispc.error_lock, flags);
5040+
5041+ if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) {
5042+ DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n");
5043+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
5044+ struct omap_overlay *ovl;
5045+ ovl = omap_dss_get_overlay(i);
5046+
5047+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
5048+ continue;
5049+
5050+ if (ovl->id == 0) {
5051+ dispc_enable_plane(ovl->id, 0);
5052+ dispc_go(ovl->manager->id);
5053+ mdelay(50);
5054+ break;
5055+ }
5056+ }
5057+ }
5058+
5059+ if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) {
5060+ DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n");
5061+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
5062+ struct omap_overlay *ovl;
5063+ ovl = omap_dss_get_overlay(i);
5064+
5065+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
5066+ continue;
5067+
5068+ if (ovl->id == 1) {
5069+ dispc_enable_plane(ovl->id, 0);
5070+ dispc_go(ovl->manager->id);
5071+ mdelay(50);
5072+ break;
5073+ }
5074+ }
5075+ }
5076+
5077+ if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) {
5078+ DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n");
5079+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
5080+ struct omap_overlay *ovl;
5081+ ovl = omap_dss_get_overlay(i);
5082+
5083+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
5084+ continue;
5085+
5086+ if (ovl->id == 2) {
5087+ dispc_enable_plane(ovl->id, 0);
5088+ dispc_go(ovl->manager->id);
5089+ mdelay(50);
5090+ break;
5091+ }
5092+ }
5093+ }
5094+
5095+ if (errors & DISPC_IRQ_SYNC_LOST) {
5096+ DSSERR("SYNC_LOST, disabling LCD\n");
5097+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
5098+ struct omap_overlay_manager *mgr;
5099+ mgr = omap_dss_get_overlay_manager(i);
5100+
5101+ if (mgr->id == OMAP_DSS_CHANNEL_LCD) {
5102+ mgr->display->disable(mgr->display);
5103+ break;
5104+ }
5105+ }
5106+ }
5107+
5108+ if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) {
5109+ DSSERR("SYNC_LOST_DIGIT, disabling TV\n");
5110+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
5111+ struct omap_overlay_manager *mgr;
5112+ mgr = omap_dss_get_overlay_manager(i);
5113+
5114+ if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) {
5115+ mgr->display->disable(mgr->display);
5116+ break;
5117+ }
5118+ }
5119+ }
5120+
5121+ if (errors & DISPC_IRQ_OCP_ERR) {
5122+ DSSERR("OCP_ERR\n");
5123+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
5124+ struct omap_overlay_manager *mgr;
5125+ mgr = omap_dss_get_overlay_manager(i);
5126+
5127+ if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC)
5128+ mgr->display->disable(mgr->display);
5129+ }
5130+ }
5131+
5132+ dispc.irq_error_mask |= errors;
5133+ omap_dispc_set_irqs();
5134+}
5135+
5136+int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
5137+{
5138+ void dispc_irq_wait_handler(void *data, u32 mask)
5139+ {
5140+ complete((struct completion *)data);
5141+ }
5142+
5143+ int r;
5144+ DECLARE_COMPLETION_ONSTACK(completion);
5145+
5146+ r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
5147+ irqmask);
5148+
5149+ if (r)
5150+ return r;
5151+
5152+ timeout = wait_for_completion_timeout(&completion, timeout);
5153+
5154+ omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
5155+
5156+ if (timeout == 0)
5157+ return -ETIMEDOUT;
5158+
5159+ if (timeout == -ERESTARTSYS)
5160+ return -ERESTARTSYS;
5161+
5162+ return 0;
5163+}
5164+
5165+int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
5166+ unsigned long timeout)
5167+{
5168+ void dispc_irq_wait_handler(void *data, u32 mask)
5169+ {
5170+ complete((struct completion *)data);
5171+ }
5172+
5173+ int r;
5174+ DECLARE_COMPLETION_ONSTACK(completion);
5175+
5176+ r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
5177+ irqmask);
5178+
5179+ if (r)
5180+ return r;
5181+
5182+ timeout = wait_for_completion_interruptible_timeout(&completion,
5183+ timeout);
5184+
5185+ omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
5186+
5187+ if (timeout == 0)
5188+ return -ETIMEDOUT;
5189+
5190+ if (timeout == -ERESTARTSYS)
5191+ return -ERESTARTSYS;
5192+
5193+ return 0;
5194+}
5195+
5196+#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
5197+void dispc_fake_vsync_irq(void)
5198+{
5199+ u32 irqstatus = DISPC_IRQ_VSYNC;
5200+ int i;
5201+
5202+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
5203+ struct omap_dispc_isr_data *isr_data;
5204+ isr_data = &dispc.registered_isr[i];
5205+
5206+ if (!isr_data->isr)
5207+ continue;
5208+
5209+ if (isr_data->mask & irqstatus)
5210+ isr_data->isr(isr_data->arg, irqstatus);
5211+ }
5212+}
5213+#endif
5214+
5215+static void _omap_dispc_initialize_irq(void)
5216+{
5217+ memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
5218+
5219+ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
5220+
5221+ /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
5222+ * so clear it */
5223+ dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
5224+
5225+ omap_dispc_set_irqs();
5226+}
5227+
5228+static void _omap_dispc_initial_config(void)
5229+{
5230+ u32 l;
5231+
5232+ l = dispc_read_reg(DISPC_SYSCONFIG);
5233+ l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */
5234+ l = FLD_MOD(l, 2, 4, 3); /* SIDLEMODE: smart idle */
5235+ l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */
5236+ l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */
5237+ dispc_write_reg(DISPC_SYSCONFIG, l);
5238+
5239+ /* FUNCGATED */
5240+ REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
5241+
5242+ /* L3 firewall setting: enable access to OCM RAM */
5243+ if (cpu_is_omap24xx())
5244+ __raw_writel(0x402000b0, IO_ADDRESS(0x680050a0));
5245+
5246+ _dispc_setup_color_conv_coef();
5247+
5248+ dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
5249+}
5250+
5251+int dispc_init(void)
5252+{
5253+ u32 rev;
5254+
5255+ spin_lock_init(&dispc.irq_lock);
5256+ spin_lock_init(&dispc.error_lock);
5257+
5258+ INIT_WORK(&dispc.error_work, dispc_error_worker);
5259+
5260+ dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS);
5261+ if (!dispc.base) {
5262+ DSSERR("can't ioremap DISPC\n");
5263+ return -ENOMEM;
5264+ }
5265+
5266+ if (cpu_is_omap34xx()) {
5267+ dispc.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
5268+ if (IS_ERR(dispc.dpll4_m4_ck)) {
5269+ DSSERR("Failed to get dpll4_m4_ck\n");
5270+ return -ENODEV;
5271+ }
5272+ }
5273+
5274+ enable_clocks(1);
5275+
5276+ _omap_dispc_initial_config();
5277+
5278+ _omap_dispc_initialize_irq();
5279+
5280+ dispc_save_context();
5281+
5282+ rev = dispc_read_reg(DISPC_REVISION);
5283+ printk(KERN_INFO "OMAP DISPC rev %d.%d\n",
5284+ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
5285+
5286+ enable_clocks(0);
5287+
5288+ return 0;
5289+}
5290+
5291+void dispc_exit(void)
5292+{
5293+ if (cpu_is_omap34xx())
5294+ clk_put(dispc.dpll4_m4_ck);
5295+ iounmap(dispc.base);
5296+}
5297+
5298+int dispc_enable_plane(enum omap_plane plane, bool enable)
5299+{
5300+ DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
5301+
5302+ enable_clocks(1);
5303+ _dispc_enable_plane(plane, enable);
5304+ enable_clocks(0);
5305+
5306+ return 0;
5307+}
5308+
5309+int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
5310+ u32 paddr, u16 screen_width,
5311+ u16 pos_x, u16 pos_y,
5312+ u16 width, u16 height,
5313+ u16 out_width, u16 out_height,
5314+ enum omap_color_mode color_mode,
5315+ bool ilace,
5316+ u8 rotation, bool mirror)
5317+{
5318+ int r = 0;
5319+
5320+ DSSDBG("dispc_setup_plane %d, ch %d, pa %x, sw %d, %d,%d, %dx%d -> "
5321+ "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n",
5322+ plane, channel_out, paddr, screen_width, pos_x, pos_y,
5323+ width, height,
5324+ out_width, out_height,
5325+ ilace, color_mode,
5326+ rotation, mirror);
5327+
5328+ enable_clocks(1);
5329+
5330+ r = _dispc_setup_plane(plane, channel_out,
5331+ paddr, screen_width,
5332+ pos_x, pos_y,
5333+ width, height,
5334+ out_width, out_height,
5335+ color_mode, ilace,
5336+ rotation, mirror);
5337+
5338+ enable_clocks(0);
5339+
5340+ return r;
5341+}
5342+
5343+static int dispc_is_intersecting(int x1, int y1, int w1, int h1,
5344+ int x2, int y2, int w2, int h2)
5345+{
5346+ if (x1 >= (x2+w2))
5347+ return 0;
5348+
5349+ if ((x1+w1) <= x2)
5350+ return 0;
5351+
5352+ if (y1 >= (y2+h2))
5353+ return 0;
5354+
5355+ if ((y1+h1) <= y2)
5356+ return 0;
5357+
5358+ return 1;
5359+}
5360+
5361+static int dispc_is_overlay_scaled(struct omap_overlay_info *pi)
5362+{
5363+ if (pi->width != pi->out_width)
5364+ return 1;
5365+
5366+ if (pi->height != pi->out_height)
5367+ return 1;
5368+
5369+ return 0;
5370+}
5371+
5372+/* returns the area that needs updating */
5373+void dispc_setup_partial_planes(struct omap_display *display,
5374+ u16 *xi, u16 *yi, u16 *wi, u16 *hi)
5375+{
5376+ struct omap_overlay_manager *mgr;
5377+ int i;
5378+
5379+ int x, y, w, h;
5380+
5381+ x = *xi;
5382+ y = *yi;
5383+ w = *wi;
5384+ h = *hi;
5385+
5386+ DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n",
5387+ *xi, *yi, *wi, *hi);
5388+
5389+
5390+ mgr = display->manager;
5391+
5392+ if (!mgr) {
5393+ DSSDBG("no manager\n");
5394+ return;
5395+ }
5396+
5397+ for (i = 0; i < mgr->num_overlays; i++) {
5398+ struct omap_overlay *ovl;
5399+ struct omap_overlay_info *pi;
5400+ ovl = mgr->overlays[i];
5401+
5402+ if (ovl->manager != mgr)
5403+ continue;
5404+
5405+ if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
5406+ continue;
5407+
5408+ pi = &ovl->info;
5409+
5410+ if (!pi->enabled)
5411+ continue;
5412+ /*
5413+ * If the plane is intersecting and scaled, we
5414+ * enlarge the update region to accomodate the
5415+ * whole area
5416+ */
5417+
5418+ if (dispc_is_intersecting(x, y, w, h,
5419+ pi->pos_x, pi->pos_y,
5420+ pi->out_width, pi->out_height)) {
5421+ if (dispc_is_overlay_scaled(pi)) {
5422+
5423+ int x1, y1, x2, y2;
5424+
5425+ if (x > pi->pos_x)
5426+ x1 = pi->pos_x;
5427+ else
5428+ x1 = x;
5429+
5430+ if (y > pi->pos_y)
5431+ y1 = pi->pos_y;
5432+ else
5433+ y1 = y;
5434+
5435+ if ((x + w) < (pi->pos_x + pi->out_width))
5436+ x2 = pi->pos_x + pi->out_width;
5437+ else
5438+ x2 = x + w;
5439+
5440+ if ((y + h) < (pi->pos_y + pi->out_height))
5441+ y2 = pi->pos_y + pi->out_height;
5442+ else
5443+ y2 = y + h;
5444+
5445+ x = x1;
5446+ y = y1;
5447+ w = x2 - x1;
5448+ h = y2 - y1;
5449+
5450+ DSSDBG("Update area after enlarge due to "
5451+ "scaling %d, %d %dx%d\n",
5452+ x, y, w, h);
5453+ }
5454+ }
5455+ }
5456+
5457+ for (i = 0; i < mgr->num_overlays; i++) {
5458+ struct omap_overlay *ovl = mgr->overlays[i];
5459+ struct omap_overlay_info *pi = &ovl->info;
5460+
5461+ int px = pi->pos_x;
5462+ int py = pi->pos_y;
5463+ int pw = pi->width;
5464+ int ph = pi->height;
5465+ int pow = pi->out_width;
5466+ int poh = pi->out_height;
5467+ u32 pa = pi->paddr;
5468+ int psw = pi->screen_width;
5469+ int bpp;
5470+
5471+ if (ovl->manager != mgr)
5472+ continue;
5473+
5474+ /*
5475+ * If plane is not enabled or the update region
5476+ * does not intersect with the plane in question,
5477+ * we really disable the plane from hardware
5478+ */
5479+
5480+ if (!pi->enabled ||
5481+ !dispc_is_intersecting(x, y, w, h,
5482+ px, py, pow, poh)) {
5483+ dispc_enable_plane(ovl->id, 0);
5484+ continue;
5485+ }
5486+
5487+ switch (pi->color_mode) {
5488+ case OMAP_DSS_COLOR_RGB16:
5489+ case OMAP_DSS_COLOR_ARGB16:
5490+ case OMAP_DSS_COLOR_YUV2:
5491+ case OMAP_DSS_COLOR_UYVY:
5492+ bpp = 16;
5493+ break;
5494+
5495+ case OMAP_DSS_COLOR_RGB24P:
5496+ bpp = 24;
5497+ break;
5498+
5499+ case OMAP_DSS_COLOR_RGB24U:
5500+ case OMAP_DSS_COLOR_ARGB32:
5501+ case OMAP_DSS_COLOR_RGBA32:
5502+ case OMAP_DSS_COLOR_RGBX32:
5503+ bpp = 32;
5504+ break;
5505+
5506+ default:
5507+ BUG();
5508+ return;
5509+ }
5510+
5511+ if (x > pi->pos_x) {
5512+ px = 0;
5513+ pw -= (x - pi->pos_x);
5514+ pa += (x - pi->pos_x) * bpp / 8;
5515+ } else {
5516+ px = pi->pos_x - x;
5517+ }
5518+
5519+ if (y > pi->pos_y) {
5520+ py = 0;
5521+ ph -= (y - pi->pos_y);
5522+ pa += (y - pi->pos_y) * psw * bpp / 8;
5523+ } else {
5524+ py = pi->pos_y - y;
5525+ }
5526+
5527+ if (w < (px+pw))
5528+ pw -= (px+pw) - (w);
5529+
5530+ if (h < (py+ph))
5531+ ph -= (py+ph) - (h);
5532+
5533+ /* Can't scale the GFX plane */
5534+ if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0 ||
5535+ dispc_is_overlay_scaled(pi) == 0) {
5536+ pow = pw;
5537+ poh = ph;
5538+ }
5539+
5540+ DSSDBG("calc plane %d, %x, sw %d, %d,%d, %dx%d -> %dx%d\n",
5541+ ovl->id, pa, psw, px, py, pw, ph, pow, poh);
5542+
5543+ dispc_setup_plane(ovl->id, mgr->id,
5544+ pa, psw,
5545+ px, py,
5546+ pw, ph,
5547+ pow, poh,
5548+ pi->color_mode, 0,
5549+ pi->rotation, // XXX rotation probably wrong
5550+ pi->mirror);
5551+
5552+ dispc_enable_plane(ovl->id, 1);
5553+ }
5554+
5555+ *xi = x;
5556+ *yi = y;
5557+ *wi = w;
5558+ *hi = h;
5559+
5560+}
5561+
5562diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
5563new file mode 100644
5564index 0000000..9aaf392
5565--- /dev/null
5566+++ b/drivers/video/omap2/dss/display.c
5567@@ -0,0 +1,693 @@
5568+/*
5569+ * linux/drivers/video/omap2/dss/display.c
5570+ *
5571+ * Copyright (C) 2009 Nokia Corporation
5572+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
5573+ *
5574+ * Some code and ideas taken from drivers/video/omap/ driver
5575+ * by Imre Deak.
5576+ *
5577+ * This program is free software; you can redistribute it and/or modify it
5578+ * under the terms of the GNU General Public License version 2 as published by
5579+ * the Free Software Foundation.
5580+ *
5581+ * This program is distributed in the hope that it will be useful, but WITHOUT
5582+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
5583+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
5584+ * more details.
5585+ *
5586+ * You should have received a copy of the GNU General Public License along with
5587+ * this program. If not, see <http://www.gnu.org/licenses/>.
5588+ */
5589+
5590+#define DSS_SUBSYS_NAME "DISPLAY"
5591+
5592+#include <linux/kernel.h>
5593+#include <linux/module.h>
5594+#include <linux/jiffies.h>
5595+#include <linux/list.h>
5596+#include <linux/platform_device.h>
5597+
5598+#include <mach/display.h>
5599+#include "dss.h"
5600+
5601+static int num_displays;
5602+static LIST_HEAD(display_list);
5603+
5604+static ssize_t display_name_show(struct omap_display *display, char *buf)
5605+{
5606+ return snprintf(buf, PAGE_SIZE, "%s\n", display->name);
5607+}
5608+
5609+static ssize_t display_enabled_show(struct omap_display *display, char *buf)
5610+{
5611+ bool enabled = display->state != OMAP_DSS_DISPLAY_DISABLED;
5612+
5613+ return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
5614+}
5615+
5616+static ssize_t display_enabled_store(struct omap_display *display,
5617+ const char *buf, size_t size)
5618+{
5619+ bool enabled, r;
5620+
5621+ enabled = simple_strtoul(buf, NULL, 10);
5622+
5623+ if (enabled != (display->state != OMAP_DSS_DISPLAY_DISABLED)) {
5624+ if (enabled) {
5625+ r = display->enable(display);
5626+ if (r)
5627+ return r;
5628+ } else {
5629+ display->disable(display);
5630+ }
5631+ }
5632+
5633+ return size;
5634+}
5635+
5636+static ssize_t display_upd_mode_show(struct omap_display *display, char *buf)
5637+{
5638+ enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO;
5639+ if (display->get_update_mode)
5640+ mode = display->get_update_mode(display);
5641+ return snprintf(buf, PAGE_SIZE, "%d\n", mode);
5642+}
5643+
5644+static ssize_t display_upd_mode_store(struct omap_display *display,
5645+ const char *buf, size_t size)
5646+{
5647+ int val, r;
5648+ enum omap_dss_update_mode mode;
5649+
5650+ val = simple_strtoul(buf, NULL, 10);
5651+
5652+ switch (val) {
5653+ case OMAP_DSS_UPDATE_DISABLED:
5654+ case OMAP_DSS_UPDATE_AUTO:
5655+ case OMAP_DSS_UPDATE_MANUAL:
5656+ mode = (enum omap_dss_update_mode)val;
5657+ break;
5658+ default:
5659+ return -EINVAL;
5660+ }
5661+
5662+ if ((r = display->set_update_mode(display, mode)))
5663+ return r;
5664+
5665+ return size;
5666+}
5667+
5668+static ssize_t display_tear_show(struct omap_display *display, char *buf)
5669+{
5670+ return snprintf(buf, PAGE_SIZE, "%d\n",
5671+ display->get_te ? display->get_te(display) : 0);
5672+}
5673+
5674+static ssize_t display_tear_store(struct omap_display *display,
5675+ const char *buf, size_t size)
5676+{
5677+ unsigned long te;
5678+ int r;
5679+
5680+ if (!display->enable_te || !display->get_te)
5681+ return -ENOENT;
5682+
5683+ te = simple_strtoul(buf, NULL, 0);
5684+
5685+ if ((r = display->enable_te(display, te)))
5686+ return r;
5687+
5688+ return size;
5689+}
5690+
5691+static ssize_t display_timings_show(struct omap_display *display, char *buf)
5692+{
5693+ struct omap_video_timings t;
5694+
5695+ if (!display->get_timings)
5696+ return -ENOENT;
5697+
5698+ display->get_timings(display, &t);
5699+
5700+ return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
5701+ t.pixel_clock,
5702+ t.x_res, t.hfp, t.hbp, t.hsw,
5703+ t.y_res, t.vfp, t.vbp, t.vsw);
5704+}
5705+
5706+static ssize_t display_timings_store(struct omap_display *display,
5707+ const char *buf, size_t size)
5708+{
5709+ struct omap_video_timings t;
5710+ int r, found;
5711+
5712+ if (!display->set_timings || !display->check_timings)
5713+ return -ENOENT;
5714+
5715+ found = 0;
5716+#ifdef CONFIG_OMAP2_DSS_VENC
5717+ if (strncmp("pal", buf, 3) == 0) {
5718+ t = omap_dss_pal_timings;
5719+ found = 1;
5720+ } else if (strncmp("ntsc", buf, 4) == 0) {
5721+ t = omap_dss_ntsc_timings;
5722+ found = 1;
5723+ }
5724+#endif
5725+ if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
5726+ &t.pixel_clock,
5727+ &t.x_res, &t.hfp, &t.hbp, &t.hsw,
5728+ &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
5729+ return -EINVAL;
5730+
5731+ if ((r = display->check_timings(display, &t)))
5732+ return r;
5733+
5734+ display->set_timings(display, &t);
5735+
5736+ return size;
5737+}
5738+
5739+static ssize_t display_rotate_show(struct omap_display *display, char *buf)
5740+{
5741+ int rotate;
5742+ if (!display->get_rotate)
5743+ return -ENOENT;
5744+ rotate = display->get_rotate(display);
5745+ return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
5746+}
5747+
5748+static ssize_t display_rotate_store(struct omap_display *display,
5749+ const char *buf, size_t size)
5750+{
5751+ unsigned long rot;
5752+ int r;
5753+
5754+ if (!display->set_rotate || !display->get_rotate)
5755+ return -ENOENT;
5756+
5757+ rot = simple_strtoul(buf, NULL, 0);
5758+
5759+ if ((r = display->set_rotate(display, rot)))
5760+ return r;
5761+
5762+ return size;
5763+}
5764+
5765+static ssize_t display_mirror_show(struct omap_display *display, char *buf)
5766+{
5767+ int mirror;
5768+ if (!display->get_mirror)
5769+ return -ENOENT;
5770+ mirror = display->get_mirror(display);
5771+ return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
5772+}
5773+
5774+static ssize_t display_mirror_store(struct omap_display *display,
5775+ const char *buf, size_t size)
5776+{
5777+ unsigned long mirror;
5778+ int r;
5779+
5780+ if (!display->set_mirror || !display->get_mirror)
5781+ return -ENOENT;
5782+
5783+ mirror = simple_strtoul(buf, NULL, 0);
5784+
5785+ if ((r = display->set_mirror(display, mirror)))
5786+ return r;
5787+
5788+ return size;
5789+}
5790+
5791+static ssize_t display_panel_name_show(struct omap_display *display, char *buf)
5792+{
5793+ return snprintf(buf, PAGE_SIZE, "%s\n",
5794+ display->panel ? display->panel->name : "");
5795+}
5796+
5797+static ssize_t display_ctrl_name_show(struct omap_display *display, char *buf)
5798+{
5799+ return snprintf(buf, PAGE_SIZE, "%s\n",
5800+ display->ctrl ? display->ctrl->name : "");
5801+}
5802+
5803+struct display_attribute {
5804+ struct attribute attr;
5805+ ssize_t (*show)(struct omap_display *, char *);
5806+ ssize_t (*store)(struct omap_display *, const char *, size_t);
5807+};
5808+
5809+#define DISPLAY_ATTR(_name, _mode, _show, _store) \
5810+ struct display_attribute display_attr_##_name = \
5811+ __ATTR(_name, _mode, _show, _store)
5812+
5813+static DISPLAY_ATTR(name, S_IRUGO, display_name_show, NULL);
5814+static DISPLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
5815+ display_enabled_show, display_enabled_store);
5816+static DISPLAY_ATTR(update_mode, S_IRUGO|S_IWUSR,
5817+ display_upd_mode_show, display_upd_mode_store);
5818+static DISPLAY_ATTR(tear_elim, S_IRUGO|S_IWUSR,
5819+ display_tear_show, display_tear_store);
5820+static DISPLAY_ATTR(timings, S_IRUGO|S_IWUSR,
5821+ display_timings_show, display_timings_store);
5822+static DISPLAY_ATTR(rotate, S_IRUGO|S_IWUSR,
5823+ display_rotate_show, display_rotate_store);
5824+static DISPLAY_ATTR(mirror, S_IRUGO|S_IWUSR,
5825+ display_mirror_show, display_mirror_store);
5826+static DISPLAY_ATTR(panel_name, S_IRUGO, display_panel_name_show, NULL);
5827+static DISPLAY_ATTR(ctrl_name, S_IRUGO, display_ctrl_name_show, NULL);
5828+
5829+static struct attribute *display_sysfs_attrs[] = {
5830+ &display_attr_name.attr,
5831+ &display_attr_enabled.attr,
5832+ &display_attr_update_mode.attr,
5833+ &display_attr_tear_elim.attr,
5834+ &display_attr_timings.attr,
5835+ &display_attr_rotate.attr,
5836+ &display_attr_mirror.attr,
5837+ &display_attr_panel_name.attr,
5838+ &display_attr_ctrl_name.attr,
5839+ NULL
5840+};
5841+
5842+static ssize_t display_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
5843+{
5844+ struct omap_display *display;
5845+ struct display_attribute *display_attr;
5846+
5847+ display = container_of(kobj, struct omap_display, kobj);
5848+ display_attr = container_of(attr, struct display_attribute, attr);
5849+
5850+ if (!display_attr->show)
5851+ return -ENOENT;
5852+
5853+ return display_attr->show(display, buf);
5854+}
5855+
5856+static ssize_t display_attr_store(struct kobject *kobj, struct attribute *attr,
5857+ const char *buf, size_t size)
5858+{
5859+ struct omap_display *display;
5860+ struct display_attribute *display_attr;
5861+
5862+ display = container_of(kobj, struct omap_display, kobj);
5863+ display_attr = container_of(attr, struct display_attribute, attr);
5864+
5865+ if (!display_attr->store)
5866+ return -ENOENT;
5867+
5868+ return display_attr->store(display, buf, size);
5869+}
5870+
5871+static struct sysfs_ops display_sysfs_ops = {
5872+ .show = display_attr_show,
5873+ .store = display_attr_store,
5874+};
5875+
5876+static struct kobj_type display_ktype = {
5877+ .sysfs_ops = &display_sysfs_ops,
5878+ .default_attrs = display_sysfs_attrs,
5879+};
5880+
5881+static void default_get_resolution(struct omap_display *display,
5882+ u16 *xres, u16 *yres)
5883+{
5884+ *xres = display->panel->timings.x_res;
5885+ *yres = display->panel->timings.y_res;
5886+}
5887+
5888+static void default_configure_overlay(struct omap_overlay *ovl)
5889+{
5890+ unsigned low, high, size;
5891+ enum omap_burst_size burst;
5892+ enum omap_plane plane = ovl->id;
5893+
5894+ burst = OMAP_DSS_BURST_16x32;
5895+ size = 16 * 32 / 8;
5896+
5897+ dispc_set_burst_size(plane, burst);
5898+
5899+ high = dispc_get_plane_fifo_size(plane) - 1;
5900+ low = dispc_get_plane_fifo_size(plane) - size;
5901+
5902+ dispc_setup_plane_fifo(plane, low, high);
5903+}
5904+
5905+static int default_wait_vsync(struct omap_display *display)
5906+{
5907+ unsigned long timeout = msecs_to_jiffies(500);
5908+ u32 irq;
5909+
5910+ if (display->type == OMAP_DISPLAY_TYPE_VENC)
5911+ irq = DISPC_IRQ_EVSYNC_ODD;
5912+ else
5913+ irq = DISPC_IRQ_VSYNC;
5914+
5915+ return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
5916+}
5917+
5918+static int default_get_recommended_bpp(struct omap_display *display)
5919+{
5920+ if (display->panel->recommended_bpp)
5921+ return display->panel->recommended_bpp;
5922+
5923+ switch (display->type) {
5924+ case OMAP_DISPLAY_TYPE_DPI:
5925+ if (display->hw_config.u.dpi.data_lines == 24)
5926+ return 24;
5927+ else
5928+ return 16;
5929+
5930+ case OMAP_DISPLAY_TYPE_DBI:
5931+ case OMAP_DISPLAY_TYPE_DSI:
5932+ if (display->ctrl->pixel_size == 24)
5933+ return 24;
5934+ else
5935+ return 16;
5936+ case OMAP_DISPLAY_TYPE_VENC:
5937+ case OMAP_DISPLAY_TYPE_SDI:
5938+ return 24;
5939+ return 24;
5940+ default:
5941+ BUG();
5942+ }
5943+}
5944+
5945+void dss_init_displays(struct platform_device *pdev)
5946+{
5947+ struct omap_dss_board_info *pdata = pdev->dev.platform_data;
5948+ int i, r;
5949+
5950+ INIT_LIST_HEAD(&display_list);
5951+
5952+ num_displays = 0;
5953+
5954+ for (i = 0; i < pdata->num_displays; ++i) {
5955+ struct omap_display *display;
5956+
5957+ switch (pdata->displays[i]->type) {
5958+ case OMAP_DISPLAY_TYPE_DPI:
5959+#ifdef CONFIG_OMAP2_DSS_RFBI
5960+ case OMAP_DISPLAY_TYPE_DBI:
5961+#endif
5962+#ifdef CONFIG_OMAP2_DSS_SDI
5963+ case OMAP_DISPLAY_TYPE_SDI:
5964+#endif
5965+#ifdef CONFIG_OMAP2_DSS_DSI
5966+ case OMAP_DISPLAY_TYPE_DSI:
5967+#endif
5968+#ifdef CONFIG_OMAP2_DSS_VENC
5969+ case OMAP_DISPLAY_TYPE_VENC:
5970+#endif
5971+ break;
5972+ default:
5973+ DSSERR("Support for display '%s' not compiled in.\n",
5974+ pdata->displays[i]->name);
5975+ continue;
5976+ }
5977+
5978+ display = kzalloc(sizeof(*display), GFP_KERNEL);
5979+
5980+ /*atomic_set(&display->ref_count, 0);*/
5981+ display->ref_count = 0;
5982+
5983+ display->hw_config = *pdata->displays[i];
5984+ display->type = pdata->displays[i]->type;
5985+ display->name = pdata->displays[i]->name;
5986+
5987+ display->get_resolution = default_get_resolution;
5988+ display->get_recommended_bpp = default_get_recommended_bpp;
5989+ display->configure_overlay = default_configure_overlay;
5990+ display->wait_vsync = default_wait_vsync;
5991+
5992+ switch (display->type) {
5993+ case OMAP_DISPLAY_TYPE_DPI:
5994+ dpi_init_display(display);
5995+ break;
5996+#ifdef CONFIG_OMAP2_DSS_RFBI
5997+ case OMAP_DISPLAY_TYPE_DBI:
5998+ rfbi_init_display(display);
5999+ break;
6000+#endif
6001+#ifdef CONFIG_OMAP2_DSS_VENC
6002+ case OMAP_DISPLAY_TYPE_VENC:
6003+ venc_init_display(display);
6004+ break;
6005+#endif
6006+#ifdef CONFIG_OMAP2_DSS_SDI
6007+ case OMAP_DISPLAY_TYPE_SDI:
6008+ sdi_init_display(display);
6009+ break;
6010+#endif
6011+#ifdef CONFIG_OMAP2_DSS_DSI
6012+ case OMAP_DISPLAY_TYPE_DSI:
6013+ dsi_init_display(display);
6014+ break;
6015+#endif
6016+ default:
6017+ BUG();
6018+ }
6019+
6020+ r = kobject_init_and_add(&display->kobj, &display_ktype,
6021+ &pdev->dev.kobj, "display%d", num_displays);
6022+
6023+ if (r) {
6024+ DSSERR("failed to create sysfs file\n");
6025+ continue;
6026+ }
6027+
6028+ num_displays++;
6029+
6030+ list_add_tail(&display->list, &display_list);
6031+ }
6032+}
6033+
6034+void dss_uninit_displays(struct platform_device *pdev)
6035+{
6036+ struct omap_display *display;
6037+
6038+ while (!list_empty(&display_list)) {
6039+ display = list_first_entry(&display_list,
6040+ struct omap_display, list);
6041+ list_del(&display->list);
6042+ kobject_del(&display->kobj);
6043+ kobject_put(&display->kobj);
6044+ kfree(display);
6045+ }
6046+
6047+ num_displays = 0;
6048+}
6049+
6050+int dss_suspend_all_displays(void)
6051+{
6052+ int r;
6053+ struct omap_display *display;
6054+
6055+ list_for_each_entry(display, &display_list, list) {
6056+ if (display->state != OMAP_DSS_DISPLAY_ACTIVE) {
6057+ display->activate_after_resume = 0;
6058+ continue;
6059+ }
6060+
6061+ if (!display->suspend) {
6062+ DSSERR("display '%s' doesn't implement suspend\n",
6063+ display->name);
6064+ r = -ENOSYS;
6065+ goto err;
6066+ }
6067+
6068+ r = display->suspend(display);
6069+
6070+ if (r)
6071+ goto err;
6072+
6073+ display->activate_after_resume = 1;
6074+ }
6075+
6076+ return 0;
6077+err:
6078+ /* resume all displays that were suspended */
6079+ dss_resume_all_displays();
6080+ return r;
6081+}
6082+
6083+int dss_resume_all_displays(void)
6084+{
6085+ int r;
6086+ struct omap_display *display;
6087+
6088+ list_for_each_entry(display, &display_list, list) {
6089+ if (display->activate_after_resume && display->resume) {
6090+ r = display->resume(display);
6091+ if (r)
6092+ return r;
6093+ }
6094+
6095+ display->activate_after_resume = 0;
6096+ }
6097+
6098+ return 0;
6099+}
6100+
6101+int omap_dss_get_num_displays(void)
6102+{
6103+ return num_displays;
6104+}
6105+EXPORT_SYMBOL(omap_dss_get_num_displays);
6106+
6107+struct omap_display *dss_get_display(int no)
6108+{
6109+ int i = 0;
6110+ struct omap_display *display;
6111+
6112+ list_for_each_entry(display, &display_list, list) {
6113+ if (i++ == no)
6114+ return display;
6115+ }
6116+
6117+ return NULL;
6118+}
6119+
6120+struct omap_display *omap_dss_get_display(int no)
6121+{
6122+ struct omap_display *display;
6123+
6124+ display = dss_get_display(no);
6125+
6126+ if (!display)
6127+ return NULL;
6128+
6129+ switch (display->type) {
6130+ case OMAP_DISPLAY_TYPE_VENC:
6131+ break;
6132+
6133+ case OMAP_DISPLAY_TYPE_DPI:
6134+ case OMAP_DISPLAY_TYPE_SDI:
6135+ if (display->panel == NULL)
6136+ return NULL;
6137+ break;
6138+
6139+ case OMAP_DISPLAY_TYPE_DBI:
6140+ case OMAP_DISPLAY_TYPE_DSI:
6141+ if (display->panel == NULL || display->ctrl == NULL)
6142+ return NULL;
6143+ break;
6144+
6145+ default:
6146+ return NULL;
6147+ }
6148+
6149+ if (display->ctrl) {
6150+ if (!try_module_get(display->ctrl->owner))
6151+ goto err0;
6152+
6153+ if (display->ctrl->init)
6154+ if (display->ctrl->init(display) != 0)
6155+ goto err1;
6156+ }
6157+
6158+ if (display->panel) {
6159+ if (!try_module_get(display->panel->owner))
6160+ goto err2;
6161+
6162+ if (display->panel->init)
6163+ if (display->panel->init(display) != 0)
6164+ goto err3;
6165+ }
6166+
6167+ display->ref_count++;
6168+ /*
6169+ if (atomic_cmpxchg(&display->ref_count, 0, 1) != 0)
6170+ return 0;
6171+*/
6172+
6173+ return display;
6174+err3:
6175+ if (display->panel)
6176+ module_put(display->panel->owner);
6177+err2:
6178+ if (display->ctrl && display->ctrl->cleanup)
6179+ display->ctrl->cleanup(display);
6180+err1:
6181+ if (display->ctrl)
6182+ module_put(display->ctrl->owner);
6183+err0:
6184+ return NULL;
6185+}
6186+EXPORT_SYMBOL(omap_dss_get_display);
6187+
6188+void omap_dss_put_display(struct omap_display *display)
6189+{
6190+ if (--display->ref_count > 0)
6191+ return;
6192+/*
6193+ if (atomic_cmpxchg(&display->ref_count, 1, 0) != 1)
6194+ return;
6195+*/
6196+ if (display->ctrl) {
6197+ if (display->ctrl->cleanup)
6198+ display->ctrl->cleanup(display);
6199+ module_put(display->ctrl->owner);
6200+ }
6201+
6202+ if (display->panel) {
6203+ if (display->panel->cleanup)
6204+ display->panel->cleanup(display);
6205+ module_put(display->panel->owner);
6206+ }
6207+}
6208+EXPORT_SYMBOL(omap_dss_put_display);
6209+
6210+void omap_dss_register_ctrl(struct omap_ctrl *ctrl)
6211+{
6212+ struct omap_display *display;
6213+
6214+ list_for_each_entry(display, &display_list, list) {
6215+ if (display->hw_config.ctrl_name &&
6216+ strcmp(display->hw_config.ctrl_name, ctrl->name) == 0) {
6217+ display->ctrl = ctrl;
6218+ DSSDBG("ctrl '%s' registered\n", ctrl->name);
6219+ }
6220+ }
6221+}
6222+EXPORT_SYMBOL(omap_dss_register_ctrl);
6223+
6224+void omap_dss_register_panel(struct omap_panel *panel)
6225+{
6226+ struct omap_display *display;
6227+
6228+ list_for_each_entry(display, &display_list, list) {
6229+ if (display->hw_config.panel_name &&
6230+ strcmp(display->hw_config.panel_name, panel->name) == 0) {
6231+ display->panel = panel;
6232+ DSSDBG("panel '%s' registered\n", panel->name);
6233+ }
6234+ }
6235+}
6236+EXPORT_SYMBOL(omap_dss_register_panel);
6237+
6238+void omap_dss_unregister_ctrl(struct omap_ctrl *ctrl)
6239+{
6240+ struct omap_display *display;
6241+
6242+ list_for_each_entry(display, &display_list, list) {
6243+ if (display->hw_config.ctrl_name &&
6244+ strcmp(display->hw_config.ctrl_name, ctrl->name) == 0)
6245+ display->ctrl = NULL;
6246+ }
6247+}
6248+EXPORT_SYMBOL(omap_dss_unregister_ctrl);
6249+
6250+void omap_dss_unregister_panel(struct omap_panel *panel)
6251+{
6252+ struct omap_display *display;
6253+
6254+ list_for_each_entry(display, &display_list, list) {
6255+ if (display->hw_config.panel_name &&
6256+ strcmp(display->hw_config.panel_name, panel->name) == 0)
6257+ display->panel = NULL;
6258+ }
6259+}
6260+EXPORT_SYMBOL(omap_dss_unregister_panel);
6261diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
6262new file mode 100644
6263index 0000000..71fffca
6264--- /dev/null
6265+++ b/drivers/video/omap2/dss/dpi.c
6266@@ -0,0 +1,393 @@
6267+/*
6268+ * linux/drivers/video/omap2/dss/dpi.c
6269+ *
6270+ * Copyright (C) 2009 Nokia Corporation
6271+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6272+ *
6273+ * Some code and ideas taken from drivers/video/omap/ driver
6274+ * by Imre Deak.
6275+ *
6276+ * This program is free software; you can redistribute it and/or modify it
6277+ * under the terms of the GNU General Public License version 2 as published by
6278+ * the Free Software Foundation.
6279+ *
6280+ * This program is distributed in the hope that it will be useful, but WITHOUT
6281+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6282+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
6283+ * more details.
6284+ *
6285+ * You should have received a copy of the GNU General Public License along with
6286+ * this program. If not, see <http://www.gnu.org/licenses/>.
6287+ */
6288+
6289+#include <linux/kernel.h>
6290+#include <linux/clk.h>
6291+#include <linux/delay.h>
6292+#include <linux/errno.h>
6293+
6294+#include <mach/board.h>
6295+#include <mach/display.h>
6296+#include <mach/cpu.h>
6297+
6298+#include "dss.h"
6299+
6300+static struct {
6301+ int update_enabled;
6302+} dpi;
6303+
6304+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
6305+static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req,
6306+ unsigned long *fck, int *lck_div, int *pck_div)
6307+{
6308+ struct dsi_clock_info cinfo;
6309+ int r;
6310+
6311+ r = dsi_pll_calc_pck(is_tft, pck_req, &cinfo);
6312+ if (r)
6313+ return r;
6314+
6315+ r = dsi_pll_program(&cinfo);
6316+ if (r)
6317+ return r;
6318+
6319+ dss_select_clk_source(0, 1);
6320+
6321+ dispc_set_lcd_divisor(cinfo.lck_div, cinfo.pck_div);
6322+
6323+ *fck = cinfo.dsi1_pll_fclk;
6324+ *lck_div = cinfo.lck_div;
6325+ *pck_div = cinfo.pck_div;
6326+
6327+ return 0;
6328+}
6329+#else
6330+static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req,
6331+ unsigned long *fck, int *lck_div, int *pck_div)
6332+{
6333+ struct dispc_clock_info cinfo;
6334+ int r;
6335+
6336+ r = dispc_calc_clock_div(is_tft, pck_req, &cinfo);
6337+ if (r)
6338+ return r;
6339+
6340+ r = dispc_set_clock_div(&cinfo);
6341+ if (r)
6342+ return r;
6343+
6344+ *fck = cinfo.fck;
6345+ *lck_div = cinfo.lck_div;
6346+ *pck_div = cinfo.pck_div;
6347+
6348+ return 0;
6349+}
6350+#endif
6351+
6352+static int dpi_set_mode(struct omap_display *display)
6353+{
6354+ struct omap_panel *panel = display->panel;
6355+ int lck_div, pck_div;
6356+ unsigned long fck;
6357+ unsigned long pck;
6358+ bool is_tft;
6359+ int r = 0;
6360+
6361+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
6362+
6363+ dispc_set_pol_freq(panel);
6364+
6365+ is_tft = (display->panel->config & OMAP_DSS_LCD_TFT) != 0;
6366+
6367+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
6368+ r = dpi_set_dsi_clk(is_tft, panel->timings.pixel_clock * 1000,
6369+ &fck, &lck_div, &pck_div);
6370+#else
6371+ r = dpi_set_dispc_clk(is_tft, panel->timings.pixel_clock * 1000,
6372+ &fck, &lck_div, &pck_div);
6373+#endif
6374+ if (r)
6375+ goto err0;
6376+
6377+ pck = fck / lck_div / pck_div / 1000;
6378+
6379+ if (pck != panel->timings.pixel_clock) {
6380+ DSSWARN("Could not find exact pixel clock. "
6381+ "Requested %d kHz, got %lu kHz\n",
6382+ panel->timings.pixel_clock, pck);
6383+
6384+ panel->timings.pixel_clock = pck;
6385+ }
6386+
6387+ dispc_set_lcd_timings(&panel->timings);
6388+
6389+err0:
6390+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
6391+ return r;
6392+}
6393+
6394+static int dpi_basic_init(struct omap_display *display)
6395+{
6396+ bool is_tft;
6397+
6398+ is_tft = (display->panel->config & OMAP_DSS_LCD_TFT) != 0;
6399+
6400+ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
6401+ dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT :
6402+ OMAP_DSS_LCD_DISPLAY_STN);
6403+ dispc_set_tft_data_lines(display->hw_config.u.dpi.data_lines);
6404+
6405+ return 0;
6406+}
6407+
6408+static int dpi_display_enable(struct omap_display *display)
6409+{
6410+ struct omap_panel *panel = display->panel;
6411+ int r;
6412+
6413+ if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
6414+ DSSERR("display already enabled\n");
6415+ return -EINVAL;
6416+ }
6417+
6418+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
6419+
6420+ r = dpi_basic_init(display);
6421+ if (r)
6422+ goto err0;
6423+
6424+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
6425+ dss_clk_enable(DSS_CLK_FCK2);
6426+ r = dsi_pll_init(0, 1);
6427+ if (r)
6428+ goto err1;
6429+#endif
6430+ r = dpi_set_mode(display);
6431+ if (r)
6432+ goto err2;
6433+
6434+ mdelay(2);
6435+
6436+ dispc_enable_lcd_out(1);
6437+
6438+ r = panel->enable(display);
6439+ if (r)
6440+ goto err3;
6441+
6442+ display->state = OMAP_DSS_DISPLAY_ACTIVE;
6443+
6444+ return 0;
6445+
6446+err3:
6447+ dispc_enable_lcd_out(0);
6448+err2:
6449+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
6450+ dsi_pll_uninit();
6451+err1:
6452+ dss_clk_disable(DSS_CLK_FCK2);
6453+#endif
6454+err0:
6455+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
6456+ return r;
6457+}
6458+
6459+static int dpi_display_resume(struct omap_display *display);
6460+
6461+static void dpi_display_disable(struct omap_display *display)
6462+{
6463+ if (display->state == OMAP_DSS_DISPLAY_DISABLED)
6464+ return;
6465+
6466+ if (display->state == OMAP_DSS_DISPLAY_SUSPENDED)
6467+ dpi_display_resume(display);
6468+
6469+ display->panel->disable(display);
6470+
6471+ dispc_enable_lcd_out(0);
6472+
6473+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
6474+ dss_select_clk_source(0, 0);
6475+ dsi_pll_uninit();
6476+ dss_clk_disable(DSS_CLK_FCK2);
6477+#endif
6478+
6479+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
6480+
6481+ display->state = OMAP_DSS_DISPLAY_DISABLED;
6482+}
6483+
6484+static int dpi_display_suspend(struct omap_display *display)
6485+{
6486+ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
6487+ return -EINVAL;
6488+
6489+ DSSDBG("dpi_display_suspend\n");
6490+
6491+ if (display->panel->suspend)
6492+ display->panel->suspend(display);
6493+
6494+ dispc_enable_lcd_out(0);
6495+
6496+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
6497+
6498+ display->state = OMAP_DSS_DISPLAY_SUSPENDED;
6499+
6500+ return 0;
6501+}
6502+
6503+static int dpi_display_resume(struct omap_display *display)
6504+{
6505+ if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
6506+ return -EINVAL;
6507+
6508+ DSSDBG("dpi_display_resume\n");
6509+
6510+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
6511+
6512+ dispc_enable_lcd_out(1);
6513+
6514+ if (display->panel->resume)
6515+ display->panel->resume(display);
6516+
6517+ display->state = OMAP_DSS_DISPLAY_ACTIVE;
6518+
6519+ return 0;
6520+}
6521+
6522+static void dpi_set_timings(struct omap_display *display,
6523+ struct omap_video_timings *timings)
6524+{
6525+ DSSDBG("dpi_set_timings\n");
6526+ display->panel->timings = *timings;
6527+ if (display->state == OMAP_DSS_DISPLAY_ACTIVE) {
6528+ dpi_set_mode(display);
6529+ dispc_go(OMAP_DSS_CHANNEL_LCD);
6530+ }
6531+}
6532+
6533+static int dpi_check_timings(struct omap_display *display,
6534+ struct omap_video_timings *timings)
6535+{
6536+ bool is_tft;
6537+ int r;
6538+ int lck_div, pck_div;
6539+ unsigned long fck;
6540+ unsigned long pck;
6541+
6542+ if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
6543+ if (timings->hsw < 1 || timings->hsw > 64 ||
6544+ timings->hfp < 1 || timings->hfp > 256 ||
6545+ timings->hbp < 1 || timings->hbp > 256) {
6546+ return -EINVAL;
6547+ }
6548+
6549+ if (timings->vsw < 1 || timings->vsw > 64 ||
6550+ timings->vfp > 255 || timings->vbp > 255) {
6551+ return -EINVAL;
6552+ }
6553+ } else {
6554+ if (timings->hsw < 1 || timings->hsw > 256 ||
6555+ timings->hfp < 1 || timings->hfp > 4096 ||
6556+ timings->hbp < 1 || timings->hbp > 4096) {
6557+ return -EINVAL;
6558+ }
6559+
6560+ if (timings->vsw < 1 || timings->vsw > 64 ||
6561+ timings->vfp > 4095 || timings->vbp > 4095) {
6562+ return -EINVAL;
6563+ }
6564+ }
6565+
6566+ if (timings->pixel_clock == 0)
6567+ return -EINVAL;
6568+
6569+ is_tft = (display->panel->config & OMAP_DSS_LCD_TFT) != 0;
6570+
6571+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
6572+ {
6573+ struct dsi_clock_info cinfo;
6574+ r = dsi_pll_calc_pck(is_tft, timings->pixel_clock * 1000,
6575+ &cinfo);
6576+
6577+ if (r)
6578+ return r;
6579+
6580+ fck = cinfo.dsi1_pll_fclk;
6581+ lck_div = cinfo.lck_div;
6582+ pck_div = cinfo.pck_div;
6583+ }
6584+#else
6585+ {
6586+ struct dispc_clock_info cinfo;
6587+ r = dispc_calc_clock_div(is_tft, timings->pixel_clock * 1000,
6588+ &cinfo);
6589+
6590+ if (r)
6591+ return r;
6592+
6593+ fck = cinfo.fck;
6594+ lck_div = cinfo.lck_div;
6595+ pck_div = cinfo.pck_div;
6596+ }
6597+#endif
6598+
6599+ pck = fck / lck_div / pck_div / 1000;
6600+
6601+ timings->pixel_clock = pck;
6602+
6603+ return 0;
6604+}
6605+
6606+static void dpi_get_timings(struct omap_display *display,
6607+ struct omap_video_timings *timings)
6608+{
6609+ *timings = display->panel->timings;
6610+}
6611+
6612+static int dpi_display_set_update_mode(struct omap_display *display,
6613+ enum omap_dss_update_mode mode)
6614+{
6615+ if (mode == OMAP_DSS_UPDATE_MANUAL)
6616+ return -EINVAL;
6617+
6618+ if (mode == OMAP_DSS_UPDATE_DISABLED) {
6619+ dispc_enable_lcd_out(0);
6620+ dpi.update_enabled = 0;
6621+ } else {
6622+ dispc_enable_lcd_out(1);
6623+ dpi.update_enabled = 1;
6624+ }
6625+
6626+ return 0;
6627+}
6628+
6629+static enum omap_dss_update_mode dpi_display_get_update_mode(
6630+ struct omap_display *display)
6631+{
6632+ return dpi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
6633+ OMAP_DSS_UPDATE_DISABLED;
6634+}
6635+
6636+void dpi_init_display(struct omap_display *display)
6637+{
6638+ DSSDBG("DPI init_display\n");
6639+
6640+ display->enable = dpi_display_enable;
6641+ display->disable = dpi_display_disable;
6642+ display->suspend = dpi_display_suspend;
6643+ display->resume = dpi_display_resume;
6644+ display->set_timings = dpi_set_timings;
6645+ display->check_timings = dpi_check_timings;
6646+ display->get_timings = dpi_get_timings;
6647+ display->set_update_mode = dpi_display_set_update_mode;
6648+ display->get_update_mode = dpi_display_get_update_mode;
6649+}
6650+
6651+int dpi_init(void)
6652+{
6653+ return 0;
6654+}
6655+
6656+void dpi_exit(void)
6657+{
6658+}
6659+
6660diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
6661new file mode 100644
6662index 0000000..4442931
6663--- /dev/null
6664+++ b/drivers/video/omap2/dss/dsi.c
6665@@ -0,0 +1,3752 @@
6666+/*
6667+ * linux/drivers/video/omap2/dss/dsi.c
6668+ *
6669+ * Copyright (C) 2009 Nokia Corporation
6670+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6671+ *
6672+ * This program is free software; you can redistribute it and/or modify it
6673+ * under the terms of the GNU General Public License version 2 as published by
6674+ * the Free Software Foundation.
6675+ *
6676+ * This program is distributed in the hope that it will be useful, but WITHOUT
6677+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6678+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
6679+ * more details.
6680+ *
6681+ * You should have received a copy of the GNU General Public License along with
6682+ * this program. If not, see <http://www.gnu.org/licenses/>.
6683+ */
6684+
6685+#define DSS_SUBSYS_NAME "DSI"
6686+
6687+#include <linux/kernel.h>
6688+#include <linux/io.h>
6689+#include <linux/clk.h>
6690+#include <linux/device.h>
6691+#include <linux/err.h>
6692+#include <linux/interrupt.h>
6693+#include <linux/delay.h>
6694+#include <linux/workqueue.h>
6695+#include <linux/mutex.h>
6696+#include <linux/seq_file.h>
6697+#include <linux/kfifo.h>
6698+
6699+#include <mach/board.h>
6700+#include <mach/display.h>
6701+#include <mach/clock.h>
6702+
6703+#include "dss.h"
6704+
6705+/*#define VERBOSE_IRQ*/
6706+
6707+#define DSI_BASE 0x4804FC00
6708+
6709+struct dsi_reg { u16 idx; };
6710+
6711+#define DSI_REG(idx) ((const struct dsi_reg) { idx })
6712+
6713+#define DSI_SZ_REGS SZ_1K
6714+/* DSI Protocol Engine */
6715+
6716+#define DSI_REVISION DSI_REG(0x0000)
6717+#define DSI_SYSCONFIG DSI_REG(0x0010)
6718+#define DSI_SYSSTATUS DSI_REG(0x0014)
6719+#define DSI_IRQSTATUS DSI_REG(0x0018)
6720+#define DSI_IRQENABLE DSI_REG(0x001C)
6721+#define DSI_CTRL DSI_REG(0x0040)
6722+#define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048)
6723+#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C)
6724+#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050)
6725+#define DSI_CLK_CTRL DSI_REG(0x0054)
6726+#define DSI_TIMING1 DSI_REG(0x0058)
6727+#define DSI_TIMING2 DSI_REG(0x005C)
6728+#define DSI_VM_TIMING1 DSI_REG(0x0060)
6729+#define DSI_VM_TIMING2 DSI_REG(0x0064)
6730+#define DSI_VM_TIMING3 DSI_REG(0x0068)
6731+#define DSI_CLK_TIMING DSI_REG(0x006C)
6732+#define DSI_TX_FIFO_VC_SIZE DSI_REG(0x0070)
6733+#define DSI_RX_FIFO_VC_SIZE DSI_REG(0x0074)
6734+#define DSI_COMPLEXIO_CFG2 DSI_REG(0x0078)
6735+#define DSI_RX_FIFO_VC_FULLNESS DSI_REG(0x007C)
6736+#define DSI_VM_TIMING4 DSI_REG(0x0080)
6737+#define DSI_TX_FIFO_VC_EMPTINESS DSI_REG(0x0084)
6738+#define DSI_VM_TIMING5 DSI_REG(0x0088)
6739+#define DSI_VM_TIMING6 DSI_REG(0x008C)
6740+#define DSI_VM_TIMING7 DSI_REG(0x0090)
6741+#define DSI_STOPCLK_TIMING DSI_REG(0x0094)
6742+#define DSI_VC_CTRL(n) DSI_REG(0x0100 + (n * 0x20))
6743+#define DSI_VC_TE(n) DSI_REG(0x0104 + (n * 0x20))
6744+#define DSI_VC_LONG_PACKET_HEADER(n) DSI_REG(0x0108 + (n * 0x20))
6745+#define DSI_VC_LONG_PACKET_PAYLOAD(n) DSI_REG(0x010C + (n * 0x20))
6746+#define DSI_VC_SHORT_PACKET_HEADER(n) DSI_REG(0x0110 + (n * 0x20))
6747+#define DSI_VC_IRQSTATUS(n) DSI_REG(0x0118 + (n * 0x20))
6748+#define DSI_VC_IRQENABLE(n) DSI_REG(0x011C + (n * 0x20))
6749+
6750+/* DSIPHY_SCP */
6751+
6752+#define DSI_DSIPHY_CFG0 DSI_REG(0x200 + 0x0000)
6753+#define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004)
6754+#define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008)
6755+#define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014)
6756+
6757+/* DSI_PLL_CTRL_SCP */
6758+
6759+#define DSI_PLL_CONTROL DSI_REG(0x300 + 0x0000)
6760+#define DSI_PLL_STATUS DSI_REG(0x300 + 0x0004)
6761+#define DSI_PLL_GO DSI_REG(0x300 + 0x0008)
6762+#define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C)
6763+#define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010)
6764+
6765+#define REG_GET(idx, start, end) \
6766+ FLD_GET(dsi_read_reg(idx), start, end)
6767+
6768+#define REG_FLD_MOD(idx, val, start, end) \
6769+ dsi_write_reg(idx, FLD_MOD(dsi_read_reg(idx), val, start, end))
6770+
6771+/* Global interrupts */
6772+#define DSI_IRQ_VC0 (1 << 0)
6773+#define DSI_IRQ_VC1 (1 << 1)
6774+#define DSI_IRQ_VC2 (1 << 2)
6775+#define DSI_IRQ_VC3 (1 << 3)
6776+#define DSI_IRQ_WAKEUP (1 << 4)
6777+#define DSI_IRQ_RESYNC (1 << 5)
6778+#define DSI_IRQ_PLL_LOCK (1 << 7)
6779+#define DSI_IRQ_PLL_UNLOCK (1 << 8)
6780+#define DSI_IRQ_PLL_RECALL (1 << 9)
6781+#define DSI_IRQ_COMPLEXIO_ERR (1 << 10)
6782+#define DSI_IRQ_HS_TX_TIMEOUT (1 << 14)
6783+#define DSI_IRQ_LP_RX_TIMEOUT (1 << 15)
6784+#define DSI_IRQ_TE_TRIGGER (1 << 16)
6785+#define DSI_IRQ_ACK_TRIGGER (1 << 17)
6786+#define DSI_IRQ_SYNC_LOST (1 << 18)
6787+#define DSI_IRQ_LDO_POWER_GOOD (1 << 19)
6788+#define DSI_IRQ_TA_TIMEOUT (1 << 20)
6789+#define DSI_IRQ_ERROR_MASK \
6790+ (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
6791+ DSI_IRQ_TA_TIMEOUT)
6792+#define DSI_IRQ_CHANNEL_MASK 0xf
6793+
6794+/* Virtual channel interrupts */
6795+#define DSI_VC_IRQ_CS (1 << 0)
6796+#define DSI_VC_IRQ_ECC_CORR (1 << 1)
6797+#define DSI_VC_IRQ_PACKET_SENT (1 << 2)
6798+#define DSI_VC_IRQ_FIFO_TX_OVF (1 << 3)
6799+#define DSI_VC_IRQ_FIFO_RX_OVF (1 << 4)
6800+#define DSI_VC_IRQ_BTA (1 << 5)
6801+#define DSI_VC_IRQ_ECC_NO_CORR (1 << 6)
6802+#define DSI_VC_IRQ_FIFO_TX_UDF (1 << 7)
6803+#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8)
6804+#define DSI_VC_IRQ_ERROR_MASK \
6805+ (DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \
6806+ DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \
6807+ DSI_VC_IRQ_FIFO_TX_UDF)
6808+
6809+/* ComplexIO interrupts */
6810+#define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0)
6811+#define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1)
6812+#define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2)
6813+#define DSI_CIO_IRQ_ERRESC1 (1 << 5)
6814+#define DSI_CIO_IRQ_ERRESC2 (1 << 6)
6815+#define DSI_CIO_IRQ_ERRESC3 (1 << 7)
6816+#define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10)
6817+#define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11)
6818+#define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12)
6819+#define DSI_CIO_IRQ_STATEULPS1 (1 << 15)
6820+#define DSI_CIO_IRQ_STATEULPS2 (1 << 16)
6821+#define DSI_CIO_IRQ_STATEULPS3 (1 << 17)
6822+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20)
6823+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21)
6824+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22)
6825+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23)
6826+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24)
6827+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25)
6828+#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30)
6829+#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31)
6830+
6831+#define DSI_DT_DCS_SHORT_WRITE_0 0x05
6832+#define DSI_DT_DCS_SHORT_WRITE_1 0x15
6833+#define DSI_DT_DCS_READ 0x06
6834+#define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37
6835+#define DSI_DT_NULL_PACKET 0x09
6836+#define DSI_DT_DCS_LONG_WRITE 0x39
6837+
6838+#define DSI_DT_RX_ACK_WITH_ERR 0x02
6839+#define DSI_DT_RX_DCS_LONG_READ 0x1c
6840+#define DSI_DT_RX_SHORT_READ_1 0x21
6841+#define DSI_DT_RX_SHORT_READ_2 0x22
6842+
6843+#define FINT_MAX 2100000
6844+#define FINT_MIN 750000
6845+#define REGN_MAX (1 << 7)
6846+#define REGM_MAX ((1 << 11) - 1)
6847+#define REGM3_MAX (1 << 4)
6848+#define REGM4_MAX (1 << 4)
6849+
6850+enum fifo_size {
6851+ DSI_FIFO_SIZE_0 = 0,
6852+ DSI_FIFO_SIZE_32 = 1,
6853+ DSI_FIFO_SIZE_64 = 2,
6854+ DSI_FIFO_SIZE_96 = 3,
6855+ DSI_FIFO_SIZE_128 = 4,
6856+};
6857+
6858+#define DSI_CMD_FIFO_LEN 16
6859+
6860+struct dsi_cmd_update {
6861+ int bytespp;
6862+ u16 x;
6863+ u16 y;
6864+ u16 w;
6865+ u16 h;
6866+};
6867+
6868+struct dsi_cmd_mem_read {
6869+ void *buf;
6870+ size_t size;
6871+ u16 x;
6872+ u16 y;
6873+ u16 w;
6874+ u16 h;
6875+ size_t *ret_size;
6876+ struct completion *completion;
6877+};
6878+
6879+struct dsi_cmd_test {
6880+ int test_num;
6881+ int *result;
6882+ struct completion *completion;
6883+};
6884+
6885+enum dsi_cmd {
6886+ DSI_CMD_UPDATE,
6887+ DSI_CMD_AUTOUPDATE,
6888+ DSI_CMD_SYNC,
6889+ DSI_CMD_MEM_READ,
6890+ DSI_CMD_TEST,
6891+ DSI_CMD_SET_TE,
6892+ DSI_CMD_SET_UPDATE_MODE,
6893+ DSI_CMD_SET_ROTATE,
6894+ DSI_CMD_SET_MIRROR,
6895+};
6896+
6897+struct dsi_cmd_item {
6898+ struct omap_display *display;
6899+
6900+ enum dsi_cmd cmd;
6901+
6902+ union {
6903+ struct dsi_cmd_update r;
6904+ struct completion *sync;
6905+ struct dsi_cmd_mem_read mem_read;
6906+ struct dsi_cmd_test test;
6907+ int te;
6908+ enum omap_dss_update_mode update_mode;
6909+ int rotate;
6910+ int mirror;
6911+ } u;
6912+};
6913+
6914+static struct
6915+{
6916+ void __iomem *base;
6917+
6918+ unsigned long dsi1_pll_fclk; /* Hz */
6919+ unsigned long dsi2_pll_fclk; /* Hz */
6920+ unsigned long dsiphy; /* Hz */
6921+ unsigned long ddr_clk; /* Hz */
6922+
6923+ struct {
6924+ struct omap_display *display;
6925+ enum fifo_size fifo_size;
6926+ int dest_per; /* destination peripheral 0-3 */
6927+ } vc[4];
6928+
6929+ struct mutex lock;
6930+
6931+ unsigned pll_locked;
6932+
6933+ struct completion bta_completion;
6934+
6935+ struct work_struct framedone_work;
6936+ struct work_struct process_work;
6937+ struct workqueue_struct *workqueue;
6938+
6939+ enum omap_dss_update_mode user_update_mode;
6940+ enum omap_dss_update_mode target_update_mode;
6941+ enum omap_dss_update_mode update_mode;
6942+ int use_te;
6943+ int framedone_scheduled; /* helps to catch strange framedone bugs */
6944+
6945+ unsigned long cache_req_pck;
6946+ unsigned long cache_clk_freq;
6947+ struct dsi_clock_info cache_cinfo;
6948+
6949+ struct kfifo *cmd_fifo;
6950+ spinlock_t cmd_lock;
6951+ struct completion cmd_done;
6952+ atomic_t cmd_fifo_full;
6953+ atomic_t cmd_pending;
6954+
6955+ bool autoupdate_setup;
6956+
6957+#ifdef DEBUG
6958+ ktime_t perf_setup_time;
6959+ ktime_t perf_start_time;
6960+ int perf_measure_frames;
6961+
6962+ struct {
6963+ int x, y, w, h;
6964+ int bytespp;
6965+ } update_region;
6966+
6967+#endif
6968+ int debug_process;
6969+ int debug_read;
6970+ int debug_write;
6971+} dsi;
6972+
6973+#ifdef DEBUG
6974+static unsigned int dsi_perf;
6975+module_param_named(dsi_perf, dsi_perf, bool, 0644);
6976+#endif
6977+
6978+static void dsi_process_cmd_fifo(struct work_struct *work);
6979+static void dsi_push_update(struct omap_display *display,
6980+ int x, int y, int w, int h);
6981+static void dsi_push_autoupdate(struct omap_display *display);
6982+
6983+static inline void dsi_write_reg(const struct dsi_reg idx, u32 val)
6984+{
6985+ __raw_writel(val, dsi.base + idx.idx);
6986+}
6987+
6988+static inline u32 dsi_read_reg(const struct dsi_reg idx)
6989+{
6990+ return __raw_readl(dsi.base + idx.idx);
6991+}
6992+
6993+
6994+void dsi_save_context(void)
6995+{
6996+}
6997+
6998+void dsi_restore_context(void)
6999+{
7000+}
7001+
7002+static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
7003+ int value)
7004+{
7005+ int t = 100000;
7006+
7007+ while (REG_GET(idx, bitnum, bitnum) != value) {
7008+ if (--t == 0)
7009+ return !value;
7010+ }
7011+
7012+ return value;
7013+}
7014+
7015+#ifdef DEBUG
7016+static void perf_mark_setup(void)
7017+{
7018+ dsi.perf_setup_time = ktime_get();
7019+}
7020+
7021+static void perf_mark_start(void)
7022+{
7023+ dsi.perf_start_time = ktime_get();
7024+}
7025+
7026+static void perf_show(const char *name)
7027+{
7028+ ktime_t t, setup_time, trans_time;
7029+ u32 total_bytes;
7030+ u32 setup_us, trans_us, total_us;
7031+ const int numframes = 100;
7032+ static u32 s_trans_us, s_min_us = 0xffffffff, s_max_us;
7033+
7034+ if (!dsi_perf)
7035+ return;
7036+
7037+ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED)
7038+ return;
7039+
7040+ t = ktime_get();
7041+
7042+ setup_time = ktime_sub(dsi.perf_start_time, dsi.perf_setup_time);
7043+ setup_us = (u32)ktime_to_us(setup_time);
7044+ if (setup_us == 0)
7045+ setup_us = 1;
7046+
7047+ trans_time = ktime_sub(t, dsi.perf_start_time);
7048+ trans_us = (u32)ktime_to_us(trans_time);
7049+ if (trans_us == 0)
7050+ trans_us = 1;
7051+
7052+ total_us = setup_us + trans_us;
7053+
7054+ total_bytes = dsi.update_region.w *
7055+ dsi.update_region.h *
7056+ dsi.update_region.bytespp;
7057+
7058+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
7059+ dsi.perf_measure_frames++;
7060+
7061+ if (trans_us < s_min_us)
7062+ s_min_us = trans_us;
7063+
7064+ if (trans_us > s_max_us)
7065+ s_max_us = trans_us;
7066+
7067+ s_trans_us += trans_us;
7068+
7069+ if (dsi.perf_measure_frames < numframes)
7070+ return;
7071+
7072+ DSSINFO("%s update: %d frames in %u us "
7073+ "(min/max/avg %u/%u/%u), %u fps\n",
7074+ name, numframes,
7075+ s_trans_us,
7076+ s_min_us,
7077+ s_max_us,
7078+ s_trans_us / numframes,
7079+ 1000*1000 / (s_trans_us / numframes));
7080+
7081+ dsi.perf_measure_frames = 0;
7082+ s_trans_us = 0;
7083+ s_min_us = 0xffffffff;
7084+ s_max_us = 0;
7085+ } else {
7086+ DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, "
7087+ "%u kbytes/sec\n",
7088+ name,
7089+ setup_us,
7090+ trans_us,
7091+ total_us,
7092+ 1000*1000 / total_us,
7093+ total_bytes,
7094+ total_bytes * 1000 / total_us);
7095+ }
7096+}
7097+#else
7098+#define perf_mark_setup()
7099+#define perf_mark_start()
7100+#define perf_show(x)
7101+#endif
7102+
7103+static void print_irq_status(u32 status)
7104+{
7105+#ifndef VERBOSE_IRQ
7106+ if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
7107+ return;
7108+#endif
7109+ printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status);
7110+
7111+#define PIS(x) \
7112+ if (status & DSI_IRQ_##x) \
7113+ printk(#x " ");
7114+#ifdef VERBOSE_IRQ
7115+ PIS(VC0);
7116+ PIS(VC1);
7117+ PIS(VC2);
7118+ PIS(VC3);
7119+#endif
7120+ PIS(WAKEUP);
7121+ PIS(RESYNC);
7122+ PIS(PLL_LOCK);
7123+ PIS(PLL_UNLOCK);
7124+ PIS(PLL_RECALL);
7125+ PIS(COMPLEXIO_ERR);
7126+ PIS(HS_TX_TIMEOUT);
7127+ PIS(LP_RX_TIMEOUT);
7128+ PIS(TE_TRIGGER);
7129+ PIS(ACK_TRIGGER);
7130+ PIS(SYNC_LOST);
7131+ PIS(LDO_POWER_GOOD);
7132+ PIS(TA_TIMEOUT);
7133+#undef PIS
7134+
7135+ printk("\n");
7136+}
7137+
7138+static void print_irq_status_vc(int channel, u32 status)
7139+{
7140+#ifndef VERBOSE_IRQ
7141+ if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
7142+ return;
7143+#endif
7144+ printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status);
7145+
7146+#define PIS(x) \
7147+ if (status & DSI_VC_IRQ_##x) \
7148+ printk(#x " ");
7149+ PIS(CS);
7150+ PIS(ECC_CORR);
7151+#ifdef VERBOSE_IRQ
7152+ PIS(PACKET_SENT);
7153+#endif
7154+ PIS(FIFO_TX_OVF);
7155+ PIS(FIFO_RX_OVF);
7156+ PIS(BTA);
7157+ PIS(ECC_NO_CORR);
7158+ PIS(FIFO_TX_UDF);
7159+ PIS(PP_BUSY_CHANGE);
7160+#undef PIS
7161+ printk("\n");
7162+}
7163+
7164+static void print_irq_status_cio(u32 status)
7165+{
7166+ printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
7167+
7168+#define PIS(x) \
7169+ if (status & DSI_CIO_IRQ_##x) \
7170+ printk(#x " ");
7171+ PIS(ERRSYNCESC1);
7172+ PIS(ERRSYNCESC2);
7173+ PIS(ERRSYNCESC3);
7174+ PIS(ERRESC1);
7175+ PIS(ERRESC2);
7176+ PIS(ERRESC3);
7177+ PIS(ERRCONTROL1);
7178+ PIS(ERRCONTROL2);
7179+ PIS(ERRCONTROL3);
7180+ PIS(STATEULPS1);
7181+ PIS(STATEULPS2);
7182+ PIS(STATEULPS3);
7183+ PIS(ERRCONTENTIONLP0_1);
7184+ PIS(ERRCONTENTIONLP1_1);
7185+ PIS(ERRCONTENTIONLP0_2);
7186+ PIS(ERRCONTENTIONLP1_2);
7187+ PIS(ERRCONTENTIONLP0_3);
7188+ PIS(ERRCONTENTIONLP1_3);
7189+ PIS(ULPSACTIVENOT_ALL0);
7190+ PIS(ULPSACTIVENOT_ALL1);
7191+#undef PIS
7192+
7193+ printk("\n");
7194+}
7195+
7196+static int debug_irq;
7197+
7198+/* called from dss */
7199+void dsi_irq_handler(void)
7200+{
7201+ u32 irqstatus, vcstatus, ciostatus;
7202+ int i;
7203+
7204+ irqstatus = dsi_read_reg(DSI_IRQSTATUS);
7205+
7206+ if (irqstatus & DSI_IRQ_ERROR_MASK) {
7207+ DSSERR("DSI error, irqstatus %x\n", irqstatus);
7208+ print_irq_status(irqstatus);
7209+ } else if (debug_irq) {
7210+ print_irq_status(irqstatus);
7211+ }
7212+
7213+ for (i = 0; i < 4; ++i) {
7214+ if ((irqstatus & (1<<i)) == 0)
7215+ continue;
7216+
7217+ vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i));
7218+
7219+ if (vcstatus & DSI_VC_IRQ_BTA)
7220+ complete(&dsi.bta_completion);
7221+
7222+ if (vcstatus & DSI_VC_IRQ_ERROR_MASK) {
7223+ DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
7224+ i, vcstatus);
7225+ print_irq_status_vc(i, vcstatus);
7226+ } else if (debug_irq) {
7227+ print_irq_status_vc(i, vcstatus);
7228+ }
7229+
7230+ dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus);
7231+ }
7232+
7233+ if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
7234+ ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
7235+
7236+ dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
7237+
7238+ DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
7239+ print_irq_status_cio(ciostatus);
7240+ }
7241+
7242+ dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
7243+}
7244+
7245+
7246+static void _dsi_initialize_irq(void)
7247+{
7248+ u32 l;
7249+ int i;
7250+
7251+ /* disable all interrupts */
7252+ dsi_write_reg(DSI_IRQENABLE, 0);
7253+ for (i = 0; i < 4; ++i)
7254+ dsi_write_reg(DSI_VC_IRQENABLE(i), 0);
7255+ dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0);
7256+
7257+ /* clear interrupt status */
7258+ l = dsi_read_reg(DSI_IRQSTATUS);
7259+ dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK);
7260+
7261+ for (i = 0; i < 4; ++i) {
7262+ l = dsi_read_reg(DSI_VC_IRQSTATUS(i));
7263+ dsi_write_reg(DSI_VC_IRQSTATUS(i), l);
7264+ }
7265+
7266+ l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
7267+ dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l);
7268+
7269+ /* enable error irqs */
7270+ l = DSI_IRQ_ERROR_MASK;
7271+ dsi_write_reg(DSI_IRQENABLE, l);
7272+
7273+ l = DSI_VC_IRQ_ERROR_MASK;
7274+ for (i = 0; i < 4; ++i)
7275+ dsi_write_reg(DSI_VC_IRQENABLE(i), l);
7276+
7277+ /* XXX zonda responds incorrectly, causing control error:
7278+ Exit from LP-ESC mode to LP11 uses wrong transition states on the
7279+ data lines LP0 and LN0. */
7280+ dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE,
7281+ -1 & (~DSI_CIO_IRQ_ERRCONTROL2));
7282+}
7283+
7284+static void dsi_vc_enable_bta_irq(int channel)
7285+{
7286+ u32 l;
7287+
7288+ l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
7289+ l |= DSI_VC_IRQ_BTA;
7290+ dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
7291+}
7292+
7293+static void dsi_vc_disable_bta_irq(int channel)
7294+{
7295+ u32 l;
7296+
7297+ l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
7298+ l &= ~DSI_VC_IRQ_BTA;
7299+ dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
7300+}
7301+
7302+/* DSI func clock. this could also be DSI2_PLL_FCLK */
7303+static inline void enable_clocks(bool enable)
7304+{
7305+ if (enable)
7306+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
7307+ else
7308+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
7309+}
7310+
7311+/* source clock for DSI PLL. this could also be PCLKFREE */
7312+static inline void dsi_enable_pll_clock(bool enable)
7313+{
7314+ if (enable)
7315+ dss_clk_enable(DSS_CLK_FCK2);
7316+ else
7317+ dss_clk_disable(DSS_CLK_FCK2);
7318+
7319+ if (enable && dsi.pll_locked) {
7320+ if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1)
7321+ DSSERR("cannot lock PLL when enabling clocks\n");
7322+ }
7323+}
7324+
7325+#ifdef DEBUG
7326+static void _dsi_print_reset_status(void)
7327+{
7328+ u32 l;
7329+
7330+ if (!dss_debug)
7331+ return;
7332+
7333+ /* A dummy read using the SCP interface to any DSIPHY register is
7334+ * required after DSIPHY reset to complete the reset of the DSI complex
7335+ * I/O. */
7336+ l = dsi_read_reg(DSI_DSIPHY_CFG5);
7337+
7338+ printk(KERN_DEBUG "DSI resets: ");
7339+
7340+ l = dsi_read_reg(DSI_PLL_STATUS);
7341+ printk("PLL (%d) ", FLD_GET(l, 0, 0));
7342+
7343+ l = dsi_read_reg(DSI_COMPLEXIO_CFG1);
7344+ printk("CIO (%d) ", FLD_GET(l, 29, 29));
7345+
7346+ l = dsi_read_reg(DSI_DSIPHY_CFG5);
7347+ printk("PHY (%x, %d, %d, %d)\n",
7348+ FLD_GET(l, 28, 26),
7349+ FLD_GET(l, 29, 29),
7350+ FLD_GET(l, 30, 30),
7351+ FLD_GET(l, 31, 31));
7352+}
7353+#else
7354+#define _dsi_print_reset_status()
7355+#endif
7356+
7357+static inline int dsi_if_enable(bool enable)
7358+{
7359+ DSSDBG("dsi_if_enable(%d)\n", enable);
7360+
7361+ enable = enable ? 1 : 0;
7362+ REG_FLD_MOD(DSI_CTRL, enable, 0, 0); /* IF_EN */
7363+
7364+ if (wait_for_bit_change(DSI_CTRL, 0, enable) != enable) {
7365+ DSSERR("Failed to set dsi_if_enable to %d\n", enable);
7366+ return -EIO;
7367+ }
7368+
7369+ return 0;
7370+}
7371+
7372+static unsigned long dsi_fclk_rate(void)
7373+{
7374+ unsigned long r;
7375+
7376+ if (dss_get_dsi_clk_source() == 0) {
7377+ /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */
7378+ r = dss_clk_get_rate(DSS_CLK_FCK1);
7379+ } else {
7380+ /* DSI FCLK source is DSI2_PLL_FCLK */
7381+ r = dsi.dsi2_pll_fclk;
7382+ }
7383+
7384+ return r;
7385+}
7386+
7387+static int dsi_set_lp_clk_divisor(void)
7388+{
7389+ int n;
7390+ unsigned long dsi_fclk;
7391+ unsigned long mhz;
7392+
7393+ /* LP_CLK_DIVISOR, DSI fclk/n, should be 20MHz - 32kHz */
7394+
7395+ dsi_fclk = dsi_fclk_rate();
7396+
7397+ for (n = 1; n < (1 << 13) - 1; ++n) {
7398+ mhz = dsi_fclk / n;
7399+ if (mhz <= 20*1000*1000)
7400+ break;
7401+ }
7402+
7403+ if (n == (1 << 13) - 1) {
7404+ DSSERR("Failed to find LP_CLK_DIVISOR\n");
7405+ return -EINVAL;
7406+ }
7407+
7408+ DSSDBG("LP_CLK_DIV %d, LP_CLK %ld\n", n, mhz);
7409+
7410+ REG_FLD_MOD(DSI_CLK_CTRL, n, 12, 0); /* LP_CLK_DIVISOR */
7411+ if (dsi_fclk > 30*1000*1000)
7412+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 21, 21); /* LP_RX_SYNCHRO_ENABLE */
7413+
7414+ return 0;
7415+}
7416+
7417+
7418+enum dsi_pll_power_state {
7419+ DSI_PLL_POWER_OFF = 0x0,
7420+ DSI_PLL_POWER_ON_HSCLK = 0x1,
7421+ DSI_PLL_POWER_ON_ALL = 0x2,
7422+ DSI_PLL_POWER_ON_DIV = 0x3,
7423+};
7424+
7425+static int dsi_pll_power(enum dsi_pll_power_state state)
7426+{
7427+ int t = 0;
7428+
7429+ REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30); /* PLL_PWR_CMD */
7430+
7431+ /* PLL_PWR_STATUS */
7432+ while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) {
7433+ udelay(1);
7434+ if (t++ > 1000) {
7435+ DSSERR("Failed to set DSI PLL power mode to %d\n",
7436+ state);
7437+ return -ENODEV;
7438+ }
7439+ }
7440+
7441+ return 0;
7442+}
7443+
7444+int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck,
7445+ struct dsi_clock_info *cinfo)
7446+{
7447+ struct dsi_clock_info cur, best;
7448+ int min_fck_per_pck;
7449+ int match = 0;
7450+
7451+ if (req_pck == dsi.cache_req_pck &&
7452+ dsi.cache_cinfo.clkin == dss_clk_get_rate(DSS_CLK_FCK2)) {
7453+ DSSDBG("DSI clock info found from cache\n");
7454+ *cinfo = dsi.cache_cinfo;
7455+ return 0;
7456+ }
7457+
7458+ min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
7459+
7460+ if (min_fck_per_pck &&
7461+ req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
7462+ DSSERR("Requested pixel clock not possible with the current "
7463+ "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
7464+ "the constraint off.\n");
7465+ min_fck_per_pck = 0;
7466+ }
7467+
7468+ DSSDBG("dsi_pll_calc\n");
7469+
7470+retry:
7471+ memset(&best, 0, sizeof(best));
7472+
7473+ memset(&cur, 0, sizeof(cur));
7474+ cur.clkin = dss_clk_get_rate(DSS_CLK_FCK2);
7475+ cur.use_dss2_fck = 1;
7476+ cur.highfreq = 0;
7477+
7478+ /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
7479+ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
7480+ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
7481+ for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
7482+ if (cur.highfreq == 0)
7483+ cur.fint = cur.clkin / cur.regn;
7484+ else
7485+ cur.fint = cur.clkin / (2 * cur.regn);
7486+
7487+ if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
7488+ continue;
7489+
7490+ /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
7491+ for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
7492+ unsigned long a, b;
7493+
7494+ a = 2 * cur.regm * (cur.clkin/1000);
7495+ b = cur.regn * (cur.highfreq + 1);
7496+ cur.dsiphy = a / b * 1000;
7497+
7498+ if (cur.dsiphy > 1800 * 1000 * 1000)
7499+ break;
7500+
7501+ /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */
7502+ for (cur.regm3 = 1; cur.regm3 < REGM3_MAX;
7503+ ++cur.regm3) {
7504+ cur.dsi1_pll_fclk = cur.dsiphy / cur.regm3;
7505+
7506+ /* this will narrow down the search a bit,
7507+ * but still give pixclocks below what was
7508+ * requested */
7509+ if (cur.dsi1_pll_fclk < req_pck)
7510+ break;
7511+
7512+ if (cur.dsi1_pll_fclk > DISPC_MAX_FCK)
7513+ continue;
7514+
7515+ if (min_fck_per_pck &&
7516+ cur.dsi1_pll_fclk <
7517+ req_pck * min_fck_per_pck)
7518+ continue;
7519+
7520+ match = 1;
7521+
7522+ find_lck_pck_divs(is_tft, req_pck,
7523+ cur.dsi1_pll_fclk,
7524+ &cur.lck_div,
7525+ &cur.pck_div);
7526+
7527+ cur.lck = cur.dsi1_pll_fclk / cur.lck_div;
7528+ cur.pck = cur.lck / cur.pck_div;
7529+
7530+ if (abs(cur.pck - req_pck) <
7531+ abs(best.pck - req_pck)) {
7532+ best = cur;
7533+
7534+ if (cur.pck == req_pck)
7535+ goto found;
7536+ }
7537+ }
7538+ }
7539+ }
7540+found:
7541+ if (!match) {
7542+ if (min_fck_per_pck) {
7543+ DSSERR("Could not find suitable clock settings.\n"
7544+ "Turning FCK/PCK constraint off and"
7545+ "trying again.\n");
7546+ min_fck_per_pck = 0;
7547+ goto retry;
7548+ }
7549+
7550+ DSSERR("Could not find suitable clock settings.\n");
7551+
7552+ return -EINVAL;
7553+ }
7554+
7555+ /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */
7556+ best.regm4 = best.dsiphy / 48000000;
7557+ if (best.regm4 > REGM4_MAX)
7558+ best.regm4 = REGM4_MAX;
7559+ else if (best.regm4 == 0)
7560+ best.regm4 = 1;
7561+ best.dsi2_pll_fclk = best.dsiphy / best.regm4;
7562+
7563+ if (cinfo)
7564+ *cinfo = best;
7565+
7566+ dsi.cache_req_pck = req_pck;
7567+ dsi.cache_clk_freq = 0;
7568+ dsi.cache_cinfo = best;
7569+
7570+ return 0;
7571+}
7572+
7573+static int dsi_pll_calc_ddrfreq(unsigned long clk_freq,
7574+ struct dsi_clock_info *cinfo)
7575+{
7576+ struct dsi_clock_info cur, best;
7577+ const bool use_dss2_fck = 1;
7578+ unsigned long datafreq;
7579+
7580+ DSSDBG("dsi_pll_calc_ddrfreq\n");
7581+
7582+ if (clk_freq == dsi.cache_clk_freq &&
7583+ dsi.cache_cinfo.clkin == dss_clk_get_rate(DSS_CLK_FCK2)) {
7584+ DSSDBG("DSI clock info found from cache\n");
7585+ *cinfo = dsi.cache_cinfo;
7586+ return 0;
7587+ }
7588+
7589+ datafreq = clk_freq * 4;
7590+
7591+ memset(&best, 0, sizeof(best));
7592+
7593+ memset(&cur, 0, sizeof(cur));
7594+ cur.use_dss2_fck = use_dss2_fck;
7595+ if (use_dss2_fck) {
7596+ cur.clkin = dss_clk_get_rate(DSS_CLK_FCK2);
7597+ cur.highfreq = 0;
7598+ } else {
7599+ cur.clkin = dispc_pclk_rate();
7600+ if (cur.clkin < 32000000)
7601+ cur.highfreq = 0;
7602+ else
7603+ cur.highfreq = 1;
7604+ }
7605+
7606+ /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
7607+ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
7608+ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
7609+ for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
7610+ if (cur.highfreq == 0)
7611+ cur.fint = cur.clkin / cur.regn;
7612+ else
7613+ cur.fint = cur.clkin / (2 * cur.regn);
7614+
7615+ if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
7616+ continue;
7617+
7618+ /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
7619+ for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
7620+ unsigned long a, b;
7621+
7622+ a = 2 * cur.regm * (cur.clkin/1000);
7623+ b = cur.regn * (cur.highfreq + 1);
7624+ cur.dsiphy = a / b * 1000;
7625+
7626+ if (cur.dsiphy > 1800 * 1000 * 1000)
7627+ break;
7628+
7629+ if (abs(cur.dsiphy - datafreq) <
7630+ abs(best.dsiphy - datafreq)) {
7631+ best = cur;
7632+ /* DSSDBG("best %ld\n", best.dsiphy); */
7633+ }
7634+
7635+ if (cur.dsiphy == datafreq)
7636+ goto found;
7637+ }
7638+ }
7639+found:
7640+ /* DSI1_PLL_FCLK (regm3) is not used. Set it to something sane. */
7641+ best.regm3 = best.dsiphy / 48000000;
7642+ if (best.regm3 > REGM3_MAX)
7643+ best.regm3 = REGM3_MAX;
7644+ else if (best.regm3 == 0)
7645+ best.regm3 = 1;
7646+ best.dsi1_pll_fclk = best.dsiphy / best.regm3;
7647+
7648+ /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */
7649+ best.regm4 = best.dsiphy / 48000000;
7650+ if (best.regm4 > REGM4_MAX)
7651+ best.regm4 = REGM4_MAX;
7652+ else if (best.regm4 == 0)
7653+ best.regm4 = 1;
7654+ best.dsi2_pll_fclk = best.dsiphy / best.regm4;
7655+
7656+ if (cinfo)
7657+ *cinfo = best;
7658+
7659+ dsi.cache_clk_freq = clk_freq;
7660+ dsi.cache_req_pck = 0;
7661+ dsi.cache_cinfo = best;
7662+
7663+ return 0;
7664+}
7665+
7666+int dsi_pll_program(struct dsi_clock_info *cinfo)
7667+{
7668+ int r = 0;
7669+ u32 l;
7670+
7671+ DSSDBG("dsi_pll_program\n");
7672+
7673+ dsi.dsiphy = cinfo->dsiphy;
7674+ dsi.ddr_clk = dsi.dsiphy / 4;
7675+ dsi.dsi1_pll_fclk = cinfo->dsi1_pll_fclk;
7676+ dsi.dsi2_pll_fclk = cinfo->dsi2_pll_fclk;
7677+
7678+ DSSDBG("DSI Fint %ld\n", cinfo->fint);
7679+
7680+ DSSDBG("clkin (%s) rate %ld, highfreq %d\n",
7681+ cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree",
7682+ cinfo->clkin,
7683+ cinfo->highfreq);
7684+
7685+ /* DSIPHY == CLKIN4DDR */
7686+ DSSDBG("DSIPHY = 2 * %d / %d * %lu / %d = %lu\n",
7687+ cinfo->regm,
7688+ cinfo->regn,
7689+ cinfo->clkin,
7690+ cinfo->highfreq + 1,
7691+ cinfo->dsiphy);
7692+
7693+ DSSDBG("Data rate on 1 DSI lane %ld Mbps\n",
7694+ dsi.dsiphy / 1000 / 1000 / 2);
7695+
7696+ DSSDBG("Clock lane freq %ld Hz\n", dsi.ddr_clk);
7697+
7698+ DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n",
7699+ cinfo->regm3, cinfo->dsi1_pll_fclk);
7700+ DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n",
7701+ cinfo->regm4, cinfo->dsi2_pll_fclk);
7702+
7703+ REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */
7704+
7705+ l = dsi_read_reg(DSI_PLL_CONFIGURATION1);
7706+ l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */
7707+ l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */
7708+ l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */
7709+ l = FLD_MOD(l, cinfo->regm3 - 1, 22, 19); /* DSI_CLOCK_DIV */
7710+ l = FLD_MOD(l, cinfo->regm4 - 1, 26, 23); /* DSIPROTO_CLOCK_DIV */
7711+ dsi_write_reg(DSI_PLL_CONFIGURATION1, l);
7712+
7713+ l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
7714+ l = FLD_MOD(l, 7, 4, 1); /* DSI_PLL_FREQSEL */
7715+ /* DSI_PLL_CLKSEL */
7716+ l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1, 11, 11);
7717+ l = FLD_MOD(l, cinfo->highfreq, 12, 12); /* DSI_PLL_HIGHFREQ */
7718+ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
7719+ l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
7720+ l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
7721+ dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
7722+
7723+ REG_FLD_MOD(DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
7724+
7725+ if (wait_for_bit_change(DSI_PLL_GO, 0, 0) != 0) {
7726+ DSSERR("dsi pll go bit not going down.\n");
7727+ r = -EIO;
7728+ goto err;
7729+ }
7730+
7731+ if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) {
7732+ DSSERR("cannot lock PLL\n");
7733+ r = -EIO;
7734+ goto err;
7735+ }
7736+
7737+ dsi.pll_locked = 1;
7738+
7739+ l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
7740+ l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */
7741+ l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */
7742+ l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */
7743+ l = FLD_MOD(l, 0, 7, 7); /* DSI_PLL_TIGHTPHASELOCK */
7744+ l = FLD_MOD(l, 0, 8, 8); /* DSI_PLL_DRIFTGUARDEN */
7745+ l = FLD_MOD(l, 0, 10, 9); /* DSI_PLL_LOCKSEL */
7746+ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
7747+ l = FLD_MOD(l, 1, 14, 14); /* DSIPHY_CLKINEN */
7748+ l = FLD_MOD(l, 0, 15, 15); /* DSI_BYPASSEN */
7749+ l = FLD_MOD(l, 1, 16, 16); /* DSS_CLOCK_EN */
7750+ l = FLD_MOD(l, 0, 17, 17); /* DSS_CLOCK_PWDN */
7751+ l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */
7752+ l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */
7753+ l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */
7754+ dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
7755+
7756+ DSSDBG("PLL config done\n");
7757+err:
7758+ return r;
7759+}
7760+
7761+int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv)
7762+{
7763+ int r = 0;
7764+ enum dsi_pll_power_state pwstate;
7765+ struct dispc_clock_info cinfo;
7766+
7767+ DSSDBG("PLL init\n");
7768+
7769+ enable_clocks(1);
7770+ dsi_enable_pll_clock(1);
7771+
7772+ /* configure dispc fck and pixel clock to something sane */
7773+ r = dispc_calc_clock_div(1, 48 * 1000 * 1000, &cinfo);
7774+ if (r)
7775+ goto err0;
7776+
7777+ r = dispc_set_clock_div(&cinfo);
7778+ if (r) {
7779+ DSSERR("Failed to set basic clocks\n");
7780+ goto err0;
7781+ }
7782+
7783+ r = dss_dsi_power_up();
7784+ if (r)
7785+ goto err0;
7786+
7787+ /* PLL does not come out of reset without this... */
7788+ dispc_pck_free_enable(1);
7789+
7790+ if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) {
7791+ DSSERR("PLL not coming out of reset.\n");
7792+ r = -ENODEV;
7793+ goto err1;
7794+ }
7795+
7796+ /* ... but if left on, we get problems when planes do not
7797+ * fill the whole display. No idea about this XXX */
7798+ dispc_pck_free_enable(0);
7799+
7800+ if (enable_hsclk && enable_hsdiv)
7801+ pwstate = DSI_PLL_POWER_ON_ALL;
7802+ else if (enable_hsclk)
7803+ pwstate = DSI_PLL_POWER_ON_HSCLK;
7804+ else if (enable_hsdiv)
7805+ pwstate = DSI_PLL_POWER_ON_DIV;
7806+ else
7807+ pwstate = DSI_PLL_POWER_OFF;
7808+
7809+ r = dsi_pll_power(pwstate);
7810+
7811+ if (r)
7812+ goto err1;
7813+
7814+ DSSDBG("PLL init done\n");
7815+
7816+ return 0;
7817+err1:
7818+ dss_dsi_power_down();
7819+err0:
7820+ enable_clocks(0);
7821+ dsi_enable_pll_clock(0);
7822+ return r;
7823+}
7824+
7825+void dsi_pll_uninit(void)
7826+{
7827+ enable_clocks(0);
7828+ dsi_enable_pll_clock(0);
7829+
7830+ dsi.pll_locked = 0;
7831+ dsi_pll_power(DSI_PLL_POWER_OFF);
7832+ dss_dsi_power_down();
7833+ DSSDBG("PLL uninit done\n");
7834+}
7835+
7836+unsigned long dsi_get_dsi1_pll_rate(void)
7837+{
7838+ return dsi.dsi1_pll_fclk;
7839+}
7840+
7841+unsigned long dsi_get_dsi2_pll_rate(void)
7842+{
7843+ return dsi.dsi2_pll_fclk;
7844+}
7845+
7846+void dsi_dump_clocks(struct seq_file *s)
7847+{
7848+ int clksel;
7849+
7850+ enable_clocks(1);
7851+
7852+ clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11);
7853+
7854+ seq_printf(s, "- dsi -\n");
7855+
7856+ seq_printf(s, "dsi fclk source = %s\n",
7857+ dss_get_dsi_clk_source() == 0 ?
7858+ "dss1_alwon_fclk" : "dsi2_pll_fclk");
7859+
7860+ seq_printf(s, "dsi pll source = %s\n",
7861+ clksel == 0 ?
7862+ "dss2_alwon_fclk" : "pclkfree");
7863+
7864+ seq_printf(s, "DSIPHY\t\t%lu\nDDR_CLK\t\t%lu\n",
7865+ dsi.dsiphy, dsi.ddr_clk);
7866+
7867+ seq_printf(s, "dsi1_pll_fck\t%lu (%s)\n"
7868+ "dsi2_pll_fck\t%lu (%s)\n",
7869+ dsi.dsi1_pll_fclk,
7870+ dss_get_dispc_clk_source() == 0 ? "off" : "on",
7871+ dsi.dsi2_pll_fclk,
7872+ dss_get_dsi_clk_source() == 0 ? "off" : "on");
7873+
7874+ enable_clocks(0);
7875+}
7876+
7877+void dsi_dump_regs(struct seq_file *s)
7878+{
7879+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r))
7880+
7881+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
7882+
7883+ DUMPREG(DSI_REVISION);
7884+ DUMPREG(DSI_SYSCONFIG);
7885+ DUMPREG(DSI_SYSSTATUS);
7886+ DUMPREG(DSI_IRQSTATUS);
7887+ DUMPREG(DSI_IRQENABLE);
7888+ DUMPREG(DSI_CTRL);
7889+ DUMPREG(DSI_COMPLEXIO_CFG1);
7890+ DUMPREG(DSI_COMPLEXIO_IRQ_STATUS);
7891+ DUMPREG(DSI_COMPLEXIO_IRQ_ENABLE);
7892+ DUMPREG(DSI_CLK_CTRL);
7893+ DUMPREG(DSI_TIMING1);
7894+ DUMPREG(DSI_TIMING2);
7895+ DUMPREG(DSI_VM_TIMING1);
7896+ DUMPREG(DSI_VM_TIMING2);
7897+ DUMPREG(DSI_VM_TIMING3);
7898+ DUMPREG(DSI_CLK_TIMING);
7899+ DUMPREG(DSI_TX_FIFO_VC_SIZE);
7900+ DUMPREG(DSI_RX_FIFO_VC_SIZE);
7901+ DUMPREG(DSI_COMPLEXIO_CFG2);
7902+ DUMPREG(DSI_RX_FIFO_VC_FULLNESS);
7903+ DUMPREG(DSI_VM_TIMING4);
7904+ DUMPREG(DSI_TX_FIFO_VC_EMPTINESS);
7905+ DUMPREG(DSI_VM_TIMING5);
7906+ DUMPREG(DSI_VM_TIMING6);
7907+ DUMPREG(DSI_VM_TIMING7);
7908+ DUMPREG(DSI_STOPCLK_TIMING);
7909+
7910+ DUMPREG(DSI_VC_CTRL(0));
7911+ DUMPREG(DSI_VC_TE(0));
7912+ DUMPREG(DSI_VC_LONG_PACKET_HEADER(0));
7913+ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(0));
7914+ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(0));
7915+ DUMPREG(DSI_VC_IRQSTATUS(0));
7916+ DUMPREG(DSI_VC_IRQENABLE(0));
7917+
7918+ DUMPREG(DSI_VC_CTRL(1));
7919+ DUMPREG(DSI_VC_TE(1));
7920+ DUMPREG(DSI_VC_LONG_PACKET_HEADER(1));
7921+ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(1));
7922+ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(1));
7923+ DUMPREG(DSI_VC_IRQSTATUS(1));
7924+ DUMPREG(DSI_VC_IRQENABLE(1));
7925+
7926+ DUMPREG(DSI_VC_CTRL(2));
7927+ DUMPREG(DSI_VC_TE(2));
7928+ DUMPREG(DSI_VC_LONG_PACKET_HEADER(2));
7929+ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(2));
7930+ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(2));
7931+ DUMPREG(DSI_VC_IRQSTATUS(2));
7932+ DUMPREG(DSI_VC_IRQENABLE(2));
7933+
7934+ DUMPREG(DSI_VC_CTRL(3));
7935+ DUMPREG(DSI_VC_TE(3));
7936+ DUMPREG(DSI_VC_LONG_PACKET_HEADER(3));
7937+ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(3));
7938+ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(3));
7939+ DUMPREG(DSI_VC_IRQSTATUS(3));
7940+ DUMPREG(DSI_VC_IRQENABLE(3));
7941+
7942+ DUMPREG(DSI_DSIPHY_CFG0);
7943+ DUMPREG(DSI_DSIPHY_CFG1);
7944+ DUMPREG(DSI_DSIPHY_CFG2);
7945+ DUMPREG(DSI_DSIPHY_CFG5);
7946+
7947+ DUMPREG(DSI_PLL_CONTROL);
7948+ DUMPREG(DSI_PLL_STATUS);
7949+ DUMPREG(DSI_PLL_GO);
7950+ DUMPREG(DSI_PLL_CONFIGURATION1);
7951+ DUMPREG(DSI_PLL_CONFIGURATION2);
7952+
7953+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
7954+#undef DUMPREG
7955+}
7956+
7957+enum dsi_complexio_power_state {
7958+ DSI_COMPLEXIO_POWER_OFF = 0x0,
7959+ DSI_COMPLEXIO_POWER_ON = 0x1,
7960+ DSI_COMPLEXIO_POWER_ULPS = 0x2,
7961+};
7962+
7963+static int dsi_complexio_power(enum dsi_complexio_power_state state)
7964+{
7965+ int t = 0;
7966+
7967+ /* PWR_CMD */
7968+ REG_FLD_MOD(DSI_COMPLEXIO_CFG1, state, 28, 27);
7969+
7970+ /* PWR_STATUS */
7971+ while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) {
7972+ udelay(1);
7973+ if (t++ > 1000) {
7974+ DSSERR("failed to set complexio power state to "
7975+ "%d\n", state);
7976+ return -ENODEV;
7977+ }
7978+ }
7979+
7980+ return 0;
7981+}
7982+
7983+static void dsi_complexio_config(struct omap_display *display)
7984+{
7985+ u32 r;
7986+
7987+ int clk_lane = display->hw_config.u.dsi.clk_lane;
7988+ int data1_lane = display->hw_config.u.dsi.data1_lane;
7989+ int data2_lane = display->hw_config.u.dsi.data2_lane;
7990+ int clk_pol = display->hw_config.u.dsi.clk_pol;
7991+ int data1_pol = display->hw_config.u.dsi.data1_pol;
7992+ int data2_pol = display->hw_config.u.dsi.data2_pol;
7993+
7994+ r = dsi_read_reg(DSI_COMPLEXIO_CFG1);
7995+ r = FLD_MOD(r, clk_lane, 2, 0);
7996+ r = FLD_MOD(r, clk_pol, 3, 3);
7997+ r = FLD_MOD(r, data1_lane, 6, 4);
7998+ r = FLD_MOD(r, data1_pol, 7, 7);
7999+ r = FLD_MOD(r, data2_lane, 10, 8);
8000+ r = FLD_MOD(r, data2_pol, 11, 11);
8001+ dsi_write_reg(DSI_COMPLEXIO_CFG1, r);
8002+
8003+ /* The configuration of the DSI complex I/O (number of data lanes,
8004+ position, differential order) should not be changed while
8005+ DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for
8006+ the hardware to take into account a new configuration of the complex
8007+ I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to
8008+ follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1,
8009+ then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set
8010+ DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the
8011+ DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the
8012+ DSI complex I/O configuration is unknown. */
8013+
8014+ /*
8015+ REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
8016+ REG_FLD_MOD(DSI_CTRL, 0, 0, 0);
8017+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20);
8018+ REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
8019+ */
8020+}
8021+
8022+static inline unsigned ns2ddr(unsigned ns)
8023+{
8024+ /* convert time in ns to ddr ticks, rounding up */
8025+ return (ns * (dsi.ddr_clk/1000/1000) + 999) / 1000;
8026+}
8027+
8028+static inline unsigned ddr2ns(unsigned ddr)
8029+{
8030+ return ddr * 1000 * 1000 / (dsi.ddr_clk / 1000);
8031+}
8032+
8033+static void dsi_complexio_timings(void)
8034+{
8035+ u32 r;
8036+ u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
8037+ u32 tlpx_half, tclk_trail, tclk_zero;
8038+ u32 tclk_prepare;
8039+
8040+ /* calculate timings */
8041+
8042+ /* 1 * DDR_CLK = 2 * UI */
8043+
8044+ /* min 40ns + 4*UI max 85ns + 6*UI */
8045+ ths_prepare = ns2ddr(59) + 2;
8046+
8047+ /* min 145ns + 10*UI */
8048+ ths_prepare_ths_zero = ns2ddr(145) + 5;
8049+
8050+ /* min max(8*UI, 60ns+4*UI) */
8051+ ths_trail = max((unsigned)4, ns2ddr(60) + 2);
8052+
8053+ /* min 100ns */
8054+ ths_exit = ns2ddr(100);
8055+
8056+ /* tlpx min 50n */
8057+ tlpx_half = ns2ddr(25);
8058+
8059+ /* min 60ns */
8060+ tclk_trail = ns2ddr(60);
8061+
8062+ /* min 38ns, max 95ns */
8063+ tclk_prepare = ns2ddr(38);
8064+
8065+ /* min tclk-prepare + tclk-zero = 300ns */
8066+ tclk_zero = ns2ddr(300 - 38);
8067+
8068+ DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n",
8069+ ths_prepare, ddr2ns(ths_prepare),
8070+ ths_prepare_ths_zero, ddr2ns(ths_prepare_ths_zero));
8071+ DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n",
8072+ ths_trail, ddr2ns(ths_trail),
8073+ ths_exit, ddr2ns(ths_exit));
8074+
8075+ DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), "
8076+ "tclk_zero %u (%uns)\n",
8077+ tlpx_half, ddr2ns(tlpx_half),
8078+ tclk_trail, ddr2ns(tclk_trail),
8079+ tclk_zero, ddr2ns(tclk_zero));
8080+ DSSDBG("tclk_prepare %u (%uns)\n",
8081+ tclk_prepare, ddr2ns(tclk_prepare));
8082+
8083+ /* program timings */
8084+
8085+ r = dsi_read_reg(DSI_DSIPHY_CFG0);
8086+ r = FLD_MOD(r, ths_prepare, 31, 24);
8087+ r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16);
8088+ r = FLD_MOD(r, ths_trail, 15, 8);
8089+ r = FLD_MOD(r, ths_exit, 7, 0);
8090+ dsi_write_reg(DSI_DSIPHY_CFG0, r);
8091+
8092+ r = dsi_read_reg(DSI_DSIPHY_CFG1);
8093+ r = FLD_MOD(r, tlpx_half, 22, 16);
8094+ r = FLD_MOD(r, tclk_trail, 15, 8);
8095+ r = FLD_MOD(r, tclk_zero, 7, 0);
8096+ dsi_write_reg(DSI_DSIPHY_CFG1, r);
8097+
8098+ r = dsi_read_reg(DSI_DSIPHY_CFG2);
8099+ r = FLD_MOD(r, tclk_prepare, 7, 0);
8100+ dsi_write_reg(DSI_DSIPHY_CFG2, r);
8101+}
8102+
8103+
8104+static int dsi_complexio_init(struct omap_display *display)
8105+{
8106+ int r = 0;
8107+
8108+ DSSDBG("dsi_complexio_init\n");
8109+
8110+ /* CIO_CLK_ICG, enable L3 clk to CIO */
8111+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
8112+
8113+ /* A dummy read using the SCP interface to any DSIPHY register is
8114+ * required after DSIPHY reset to complete the reset of the DSI complex
8115+ * I/O. */
8116+ dsi_read_reg(DSI_DSIPHY_CFG5);
8117+
8118+ if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) {
8119+ DSSERR("ComplexIO PHY not coming out of reset.\n");
8120+ r = -ENODEV;
8121+ goto err;
8122+ }
8123+
8124+ dsi_complexio_config(display);
8125+
8126+ r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON);
8127+
8128+ if (r)
8129+ goto err;
8130+
8131+ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
8132+ DSSERR("ComplexIO not coming out of reset.\n");
8133+ r = -ENODEV;
8134+ goto err;
8135+ }
8136+
8137+ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
8138+ DSSERR("ComplexIO LDO power down.\n");
8139+ r = -ENODEV;
8140+ goto err;
8141+ }
8142+
8143+ dsi_complexio_timings();
8144+
8145+ /*
8146+ The configuration of the DSI complex I/O (number of data lanes,
8147+ position, differential order) should not be changed while
8148+ DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the
8149+ hardware to recognize a new configuration of the complex I/O (done
8150+ in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow
8151+ this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next
8152+ reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20]
8153+ LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN
8154+ bit to 1. If the sequence is not followed, the DSi complex I/O
8155+ configuration is undetermined.
8156+ */
8157+ dsi_if_enable(1);
8158+ dsi_if_enable(0);
8159+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
8160+ dsi_if_enable(1);
8161+ dsi_if_enable(0);
8162+
8163+ DSSDBG("CIO init done\n");
8164+err:
8165+ return r;
8166+}
8167+
8168+static void dsi_complexio_uninit(void)
8169+{
8170+ dsi_complexio_power(DSI_COMPLEXIO_POWER_OFF);
8171+}
8172+
8173+static int _dsi_wait_reset(void)
8174+{
8175+ int i = 0;
8176+
8177+ while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) {
8178+ if (i++ > 5) {
8179+ DSSERR("soft reset failed\n");
8180+ return -ENODEV;
8181+ }
8182+ udelay(1);
8183+ }
8184+
8185+ return 0;
8186+}
8187+
8188+static int _dsi_reset(void)
8189+{
8190+ /* Soft reset */
8191+ REG_FLD_MOD(DSI_SYSCONFIG, 1, 1, 1);
8192+ return _dsi_wait_reset();
8193+}
8194+
8195+
8196+static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2,
8197+ enum fifo_size size3, enum fifo_size size4)
8198+{
8199+ u32 r = 0;
8200+ int add = 0;
8201+ int i;
8202+
8203+ dsi.vc[0].fifo_size = size1;
8204+ dsi.vc[1].fifo_size = size2;
8205+ dsi.vc[2].fifo_size = size3;
8206+ dsi.vc[3].fifo_size = size4;
8207+
8208+ for (i = 0; i < 4; i++) {
8209+ u8 v;
8210+ int size = dsi.vc[i].fifo_size;
8211+
8212+ if (add + size > 4) {
8213+ DSSERR("Illegal FIFO configuration\n");
8214+ BUG();
8215+ }
8216+
8217+ v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
8218+ r |= v << (8 * i);
8219+ /*DSSDBG("TX FIFO vc %d: size %d, add %d\n", i, size, add); */
8220+ add += size;
8221+ }
8222+
8223+ dsi_write_reg(DSI_TX_FIFO_VC_SIZE, r);
8224+}
8225+
8226+static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2,
8227+ enum fifo_size size3, enum fifo_size size4)
8228+{
8229+ u32 r = 0;
8230+ int add = 0;
8231+ int i;
8232+
8233+ dsi.vc[0].fifo_size = size1;
8234+ dsi.vc[1].fifo_size = size2;
8235+ dsi.vc[2].fifo_size = size3;
8236+ dsi.vc[3].fifo_size = size4;
8237+
8238+ for (i = 0; i < 4; i++) {
8239+ u8 v;
8240+ int size = dsi.vc[i].fifo_size;
8241+
8242+ if (add + size > 4) {
8243+ DSSERR("Illegal FIFO configuration\n");
8244+ BUG();
8245+ }
8246+
8247+ v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
8248+ r |= v << (8 * i);
8249+ /*DSSDBG("RX FIFO vc %d: size %d, add %d\n", i, size, add); */
8250+ add += size;
8251+ }
8252+
8253+ dsi_write_reg(DSI_RX_FIFO_VC_SIZE, r);
8254+}
8255+
8256+static int dsi_force_tx_stop_mode_io(void)
8257+{
8258+ u32 r;
8259+
8260+ r = dsi_read_reg(DSI_TIMING1);
8261+ r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
8262+ dsi_write_reg(DSI_TIMING1, r);
8263+
8264+ if (wait_for_bit_change(DSI_TIMING1, 15, 0) != 0) {
8265+ DSSERR("TX_STOP bit not going down\n");
8266+ return -EIO;
8267+ }
8268+
8269+ return 0;
8270+}
8271+
8272+static void dsi_vc_print_status(int channel)
8273+{
8274+ u32 r;
8275+
8276+ r = dsi_read_reg(DSI_VC_CTRL(channel));
8277+ DSSDBG("vc %d: TX_FIFO_NOT_EMPTY %d, BTA_EN %d, VC_BUSY %d, "
8278+ "TX_FIFO_FULL %d, RX_FIFO_NOT_EMPTY %d, ",
8279+ channel,
8280+ FLD_GET(r, 5, 5),
8281+ FLD_GET(r, 6, 6),
8282+ FLD_GET(r, 15, 15),
8283+ FLD_GET(r, 16, 16),
8284+ FLD_GET(r, 20, 20));
8285+
8286+ r = dsi_read_reg(DSI_TX_FIFO_VC_EMPTINESS);
8287+ DSSDBG("EMPTINESS %d\n", (r >> (8 * channel)) & 0xff);
8288+}
8289+
8290+static void dsi_vc_config(int channel)
8291+{
8292+ u32 r;
8293+
8294+ DSSDBG("dsi_vc_config %d\n", channel);
8295+
8296+ r = dsi_read_reg(DSI_VC_CTRL(channel));
8297+
8298+ r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */
8299+ r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */
8300+ r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
8301+ r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
8302+ r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
8303+ r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
8304+ r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
8305+
8306+ r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
8307+ r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
8308+
8309+ dsi_write_reg(DSI_VC_CTRL(channel), r);
8310+}
8311+
8312+static void dsi_vc_config_vp(int channel)
8313+{
8314+ u32 r;
8315+
8316+ DSSDBG("dsi_vc_config_vp\n");
8317+
8318+ r = dsi_read_reg(DSI_VC_CTRL(channel));
8319+
8320+ r = FLD_MOD(r, 1, 1, 1); /* SOURCE, 1 = video port */
8321+ r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */
8322+ r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
8323+ r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
8324+ r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
8325+ r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
8326+ r = FLD_MOD(r, 1, 9, 9); /* MODE_SPEED, high speed on/off */
8327+
8328+ r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
8329+ r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
8330+
8331+ dsi_write_reg(DSI_VC_CTRL(channel), r);
8332+}
8333+
8334+
8335+static int dsi_vc_enable(int channel, bool enable)
8336+{
8337+ DSSDBG("dsi_vc_enable channel %d, enable %d\n", channel, enable);
8338+
8339+ enable = enable ? 1 : 0;
8340+
8341+ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0);
8342+
8343+ if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) {
8344+ DSSERR("Failed to set dsi_vc_enable to %d\n", enable);
8345+ return -EIO;
8346+ }
8347+
8348+ return 0;
8349+}
8350+
8351+static void dsi_vc_enable_hs(int channel, bool enable)
8352+{
8353+ DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
8354+
8355+ dsi_vc_enable(channel, 0);
8356+ dsi_if_enable(0);
8357+
8358+ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 9, 9);
8359+
8360+ dsi_vc_enable(channel, 1);
8361+ dsi_if_enable(1);
8362+
8363+ dsi_force_tx_stop_mode_io();
8364+}
8365+
8366+static void dsi_vc_flush_long_data(int channel)
8367+{
8368+ while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
8369+ u32 val;
8370+ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
8371+ DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n",
8372+ (val >> 0) & 0xff,
8373+ (val >> 8) & 0xff,
8374+ (val >> 16) & 0xff,
8375+ (val >> 24) & 0xff);
8376+ }
8377+}
8378+
8379+static void dsi_show_rx_ack_with_err(u16 err)
8380+{
8381+ DSSERR("\tACK with ERROR (%#x):\n", err);
8382+ if (err & (1 << 0))
8383+ DSSERR("\t\tSoT Error\n");
8384+ if (err & (1 << 1))
8385+ DSSERR("\t\tSoT Sync Error\n");
8386+ if (err & (1 << 2))
8387+ DSSERR("\t\tEoT Sync Error\n");
8388+ if (err & (1 << 3))
8389+ DSSERR("\t\tEscape Mode Entry Command Error\n");
8390+ if (err & (1 << 4))
8391+ DSSERR("\t\tLP Transmit Sync Error\n");
8392+ if (err & (1 << 5))
8393+ DSSERR("\t\tHS Receive Timeout Error\n");
8394+ if (err & (1 << 6))
8395+ DSSERR("\t\tFalse Control Error\n");
8396+ if (err & (1 << 7))
8397+ DSSERR("\t\t(reserved7)\n");
8398+ if (err & (1 << 8))
8399+ DSSERR("\t\tECC Error, single-bit (corrected)\n");
8400+ if (err & (1 << 9))
8401+ DSSERR("\t\tECC Error, multi-bit (not corrected)\n");
8402+ if (err & (1 << 10))
8403+ DSSERR("\t\tChecksum Error\n");
8404+ if (err & (1 << 11))
8405+ DSSERR("\t\tData type not recognized\n");
8406+ if (err & (1 << 12))
8407+ DSSERR("\t\tInvalid VC ID\n");
8408+ if (err & (1 << 13))
8409+ DSSERR("\t\tInvalid Transmission Length\n");
8410+ if (err & (1 << 14))
8411+ DSSERR("\t\t(reserved14)\n");
8412+ if (err & (1 << 15))
8413+ DSSERR("\t\tDSI Protocol Violation\n");
8414+}
8415+
8416+static u16 dsi_vc_flush_receive_data(int channel)
8417+{
8418+ /* RX_FIFO_NOT_EMPTY */
8419+ while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
8420+ u32 val;
8421+ u8 dt;
8422+ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
8423+ DSSDBG("\trawval %#08x\n", val);
8424+ dt = FLD_GET(val, 5, 0);
8425+ if (dt == DSI_DT_RX_ACK_WITH_ERR) {
8426+ u16 err = FLD_GET(val, 23, 8);
8427+ dsi_show_rx_ack_with_err(err);
8428+ } else if (dt == DSI_DT_RX_SHORT_READ_1) {
8429+ DSSDBG("\tDCS short response, 1 byte: %#x\n",
8430+ FLD_GET(val, 23, 8));
8431+ } else if (dt == DSI_DT_RX_SHORT_READ_2) {
8432+ DSSDBG("\tDCS short response, 2 byte: %#x\n",
8433+ FLD_GET(val, 23, 8));
8434+ } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
8435+ DSSDBG("\tDCS long response, len %d\n",
8436+ FLD_GET(val, 23, 8));
8437+ dsi_vc_flush_long_data(channel);
8438+ } else {
8439+ DSSERR("\tunknown datatype 0x%02x\n", dt);
8440+ }
8441+ }
8442+ return 0;
8443+}
8444+
8445+static int dsi_vc_send_bta(int channel)
8446+{
8447+ unsigned long tmo;
8448+
8449+ /*DSSDBG("dsi_vc_send_bta_sync %d\n", channel); */
8450+
8451+ if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */
8452+ DSSERR("rx fifo not empty when sending BTA, dumping data:\n");
8453+ dsi_vc_flush_receive_data(channel);
8454+ }
8455+
8456+ REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
8457+
8458+ tmo = jiffies + msecs_to_jiffies(10);
8459+ while (REG_GET(DSI_VC_CTRL(channel), 6, 6) == 1) {
8460+ if (time_after(jiffies, tmo)) {
8461+ DSSERR("Failed to send BTA\n");
8462+ return -EIO;
8463+ }
8464+ }
8465+
8466+ return 0;
8467+}
8468+
8469+static int dsi_vc_send_bta_sync(int channel)
8470+{
8471+ int r = 0;
8472+
8473+ init_completion(&dsi.bta_completion);
8474+
8475+ dsi_vc_enable_bta_irq(channel);
8476+
8477+ r = dsi_vc_send_bta(channel);
8478+ if (r)
8479+ goto err;
8480+
8481+ if (wait_for_completion_timeout(&dsi.bta_completion,
8482+ msecs_to_jiffies(500)) == 0) {
8483+ DSSERR("Failed to receive BTA\n");
8484+ r = -EIO;
8485+ goto err;
8486+ }
8487+err:
8488+ dsi_vc_disable_bta_irq(channel);
8489+
8490+ return r;
8491+}
8492+
8493+static inline void dsi_vc_write_long_header(int channel, u8 data_type,
8494+ u16 len, u8 ecc)
8495+{
8496+ u32 val;
8497+ u8 data_id;
8498+
8499+ /*data_id = data_type | channel << 6; */
8500+ data_id = data_type | dsi.vc[channel].dest_per << 6;
8501+
8502+ val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
8503+ FLD_VAL(ecc, 31, 24);
8504+
8505+ dsi_write_reg(DSI_VC_LONG_PACKET_HEADER(channel), val);
8506+}
8507+
8508+static inline void dsi_vc_write_long_payload(int channel,
8509+ u8 b1, u8 b2, u8 b3, u8 b4)
8510+{
8511+ u32 val;
8512+
8513+ val = b4 << 24 | b3 << 16 | b2 << 8 | b1 << 0;
8514+
8515+/* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n",
8516+ b1, b2, b3, b4, val); */
8517+
8518+ dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(channel), val);
8519+}
8520+
8521+static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len,
8522+ u8 ecc)
8523+{
8524+ /*u32 val; */
8525+ int i;
8526+ u8 *p;
8527+ int r = 0;
8528+ u8 b1, b2, b3, b4;
8529+
8530+ if (dsi.debug_write)
8531+ DSSDBG("dsi_vc_send_long, %d bytes\n", len);
8532+
8533+ /* len + header */
8534+ if (dsi.vc[channel].fifo_size * 32 * 4 < len + 4) {
8535+ DSSERR("unable to send long packet: packet too long.\n");
8536+ return -EINVAL;
8537+ }
8538+
8539+ dsi_vc_write_long_header(channel, data_type, len, ecc);
8540+
8541+ /*dsi_vc_print_status(0); */
8542+
8543+ p = data;
8544+ for (i = 0; i < len >> 2; i++) {
8545+ if (dsi.debug_write)
8546+ DSSDBG("\tsending full packet %d\n", i);
8547+ /*dsi_vc_print_status(0); */
8548+
8549+ b1 = *p++;
8550+ b2 = *p++;
8551+ b3 = *p++;
8552+ b4 = *p++;
8553+
8554+ dsi_vc_write_long_payload(channel, b1, b2, b3, b4);
8555+ }
8556+
8557+ i = len % 4;
8558+ if (i) {
8559+ b1 = 0; b2 = 0; b3 = 0;
8560+
8561+ if (dsi.debug_write)
8562+ DSSDBG("\tsending remainder bytes %d\n", i);
8563+
8564+ switch (i) {
8565+ case 3:
8566+ b1 = *p++;
8567+ b2 = *p++;
8568+ b3 = *p++;
8569+ break;
8570+ case 2:
8571+ b1 = *p++;
8572+ b2 = *p++;
8573+ break;
8574+ case 1:
8575+ b1 = *p++;
8576+ break;
8577+ }
8578+
8579+ dsi_vc_write_long_payload(channel, b1, b2, b3, 0);
8580+ }
8581+
8582+ return r;
8583+}
8584+
8585+static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc)
8586+{
8587+ u32 r;
8588+ u8 data_id;
8589+
8590+ if (dsi.debug_write)
8591+ DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
8592+ channel,
8593+ data_type, data & 0xff, (data >> 8) & 0xff);
8594+
8595+ if (FLD_GET(dsi_read_reg(DSI_VC_CTRL(channel)), 16, 16)) {
8596+ DSSERR("ERROR FIFO FULL, aborting transfer\n");
8597+ return -EINVAL;
8598+ }
8599+
8600+ data_id = data_type | channel << 6;
8601+
8602+ r = (data_id << 0) | (data << 8) | (ecc << 24);
8603+
8604+ dsi_write_reg(DSI_VC_SHORT_PACKET_HEADER(channel), r);
8605+
8606+ return 0;
8607+}
8608+
8609+int dsi_vc_send_null(int channel)
8610+{
8611+ u8 nullpkg[] = {0, 0, 0, 0};
8612+ return dsi_vc_send_long(0, DSI_DT_NULL_PACKET, nullpkg, 4, 0);
8613+}
8614+EXPORT_SYMBOL(dsi_vc_send_null);
8615+
8616+int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len)
8617+{
8618+ int r;
8619+
8620+ BUG_ON(len == 0);
8621+
8622+ if (len == 1) {
8623+ r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_0,
8624+ data[0], 0);
8625+ } else if (len == 2) {
8626+ r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_1,
8627+ data[0] | (data[1] << 8), 0);
8628+ } else {
8629+ /* 0x39 = DCS Long Write */
8630+ r = dsi_vc_send_long(channel, DSI_DT_DCS_LONG_WRITE,
8631+ data, len, 0);
8632+ }
8633+
8634+ return r;
8635+}
8636+EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
8637+
8638+int dsi_vc_dcs_write(int channel, u8 *data, int len)
8639+{
8640+ int r;
8641+
8642+ r = dsi_vc_dcs_write_nosync(channel, data, len);
8643+ if (r)
8644+ return r;
8645+
8646+ /* Some devices need time to process the msg in low power mode.
8647+ This also makes the write synchronous, and checks that
8648+ the peripheral is still alive */
8649+ r = dsi_vc_send_bta_sync(channel);
8650+
8651+ return r;
8652+}
8653+EXPORT_SYMBOL(dsi_vc_dcs_write);
8654+
8655+int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
8656+{
8657+ u32 val;
8658+ u8 dt;
8659+ int r;
8660+
8661+ if (dsi.debug_read)
8662+ DSSDBG("dsi_vc_dcs_read\n");
8663+
8664+ r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0);
8665+ if (r)
8666+ return r;
8667+
8668+ r = dsi_vc_send_bta_sync(channel);
8669+ if (r)
8670+ return r;
8671+
8672+ if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) { /* RX_FIFO_NOT_EMPTY */
8673+ DSSERR("RX fifo empty when trying to read.\n");
8674+ return -EIO;
8675+ }
8676+
8677+ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
8678+ if (dsi.debug_read)
8679+ DSSDBG("\theader: %08x\n", val);
8680+ dt = FLD_GET(val, 5, 0);
8681+ if (dt == DSI_DT_RX_ACK_WITH_ERR) {
8682+ u16 err = FLD_GET(val, 23, 8);
8683+ dsi_show_rx_ack_with_err(err);
8684+ return -1;
8685+
8686+ } else if (dt == DSI_DT_RX_SHORT_READ_1) {
8687+ u8 data = FLD_GET(val, 15, 8);
8688+ if (dsi.debug_read)
8689+ DSSDBG("\tDCS short response, 1 byte: %02x\n", data);
8690+
8691+ if (buflen < 1)
8692+ return -1;
8693+
8694+ buf[0] = data;
8695+
8696+ return 1;
8697+ } else if (dt == DSI_DT_RX_SHORT_READ_2) {
8698+ u16 data = FLD_GET(val, 23, 8);
8699+ if (dsi.debug_read)
8700+ DSSDBG("\tDCS short response, 2 byte: %04x\n", data);
8701+
8702+ if (buflen < 2)
8703+ return -1;
8704+
8705+ buf[0] = data & 0xff;
8706+ buf[1] = (data >> 8) & 0xff;
8707+
8708+ return 2;
8709+ } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
8710+ int w;
8711+ int len = FLD_GET(val, 23, 8);
8712+ if (dsi.debug_read)
8713+ DSSDBG("\tDCS long response, len %d\n", len);
8714+
8715+ if (len > buflen)
8716+ return -1;
8717+
8718+ /* two byte checksum ends the packet, not included in len */
8719+ for (w = 0; w < len + 2;) {
8720+ int b;
8721+ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
8722+ if (dsi.debug_read)
8723+ DSSDBG("\t\t%02x %02x %02x %02x\n",
8724+ (val >> 0) & 0xff,
8725+ (val >> 8) & 0xff,
8726+ (val >> 16) & 0xff,
8727+ (val >> 24) & 0xff);
8728+
8729+ for (b = 0; b < 4; ++b) {
8730+ if (w < len)
8731+ buf[w] = (val >> (b * 8)) & 0xff;
8732+ /* we discard the 2 byte checksum */
8733+ ++w;
8734+ }
8735+ }
8736+
8737+ return len;
8738+
8739+ } else {
8740+ DSSERR("\tunknown datatype 0x%02x\n", dt);
8741+ return -1;
8742+ }
8743+}
8744+EXPORT_SYMBOL(dsi_vc_dcs_read);
8745+
8746+
8747+int dsi_vc_set_max_rx_packet_size(int channel, u16 len)
8748+{
8749+ return dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
8750+ len, 0);
8751+}
8752+EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
8753+
8754+
8755+static int dsi_set_lp_rx_timeout(int ns, int x4, int x16)
8756+{
8757+ u32 r;
8758+ unsigned long fck;
8759+ int ticks;
8760+
8761+ /* ticks in DSI_FCK */
8762+
8763+ fck = dsi_fclk_rate();
8764+ ticks = (fck / 1000 / 1000) * ns / 1000;
8765+
8766+ if (ticks > 0x1fff) {
8767+ DSSERR("LP_TX_TO too high\n");
8768+ return -EINVAL;
8769+ }
8770+
8771+ r = dsi_read_reg(DSI_TIMING2);
8772+ r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */
8773+ r = FLD_MOD(r, x16, 14, 14); /* LP_RX_TO_X16 */
8774+ r = FLD_MOD(r, x4, 13, 13); /* LP_RX_TO_X4 */
8775+ r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */
8776+ dsi_write_reg(DSI_TIMING2, r);
8777+
8778+ DSSDBG("LP_RX_TO %ld ns (%#x ticks)\n",
8779+ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
8780+ (fck / 1000 / 1000),
8781+ ticks);
8782+
8783+ return 0;
8784+}
8785+
8786+static int dsi_set_ta_timeout(int ns, int x8, int x16)
8787+{
8788+ u32 r;
8789+ unsigned long fck;
8790+ int ticks;
8791+
8792+ /* ticks in DSI_FCK */
8793+
8794+ fck = dsi_fclk_rate();
8795+ ticks = (fck / 1000 / 1000) * ns / 1000;
8796+
8797+ if (ticks > 0x1fff) {
8798+ DSSERR("TA_TO too high\n");
8799+ return -EINVAL;
8800+ }
8801+
8802+ r = dsi_read_reg(DSI_TIMING1);
8803+ r = FLD_MOD(r, 1, 31, 31); /* TA_TO */
8804+ r = FLD_MOD(r, x16, 30, 30); /* TA_TO_X16 */
8805+ r = FLD_MOD(r, x8, 29, 29); /* TA_TO_X8 */
8806+ r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */
8807+ dsi_write_reg(DSI_TIMING1, r);
8808+
8809+ DSSDBG("TA_TO %ld ns (%#x ticks)\n",
8810+ (ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1) * 1000) /
8811+ (fck / 1000 / 1000),
8812+ ticks);
8813+
8814+ return 0;
8815+}
8816+
8817+static int dsi_set_stop_state_counter(int ns, int x4, int x16)
8818+{
8819+ u32 r;
8820+ unsigned long fck;
8821+ int ticks;
8822+
8823+ /* ticks in DSI_FCK */
8824+
8825+ fck = dsi_fclk_rate();
8826+ ticks = (fck / 1000 / 1000) * ns / 1000;
8827+
8828+ if (ticks > 0x1fff) {
8829+ DSSERR("STOP_STATE_COUNTER_IO too high\n");
8830+ return -EINVAL;
8831+ }
8832+
8833+ r = dsi_read_reg(DSI_TIMING1);
8834+ r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
8835+ r = FLD_MOD(r, x16, 14, 14); /* STOP_STATE_X16_IO */
8836+ r = FLD_MOD(r, x4, 13, 13); /* STOP_STATE_X4_IO */
8837+ r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */
8838+ dsi_write_reg(DSI_TIMING1, r);
8839+
8840+ DSSDBG("STOP_STATE_COUNTER %ld ns (%#x ticks)\n",
8841+ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
8842+ (fck / 1000 / 1000),
8843+ ticks);
8844+
8845+ return 0;
8846+}
8847+
8848+static int dsi_set_hs_tx_timeout(int ns, int x4, int x16)
8849+{
8850+ u32 r;
8851+ unsigned long fck;
8852+ int ticks;
8853+
8854+ /* ticks in TxByteClkHS */
8855+
8856+ fck = dsi.ddr_clk / 4;
8857+ ticks = (fck / 1000 / 1000) * ns / 1000;
8858+
8859+ if (ticks > 0x1fff) {
8860+ DSSERR("HS_TX_TO too high\n");
8861+ return -EINVAL;
8862+ }
8863+
8864+ r = dsi_read_reg(DSI_TIMING2);
8865+ r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */
8866+ r = FLD_MOD(r, x16, 30, 30); /* HS_TX_TO_X16 */
8867+ r = FLD_MOD(r, x4, 29, 29); /* HS_TX_TO_X8 (4 really) */
8868+ r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */
8869+ dsi_write_reg(DSI_TIMING2, r);
8870+
8871+ DSSDBG("HS_TX_TO %ld ns (%#x ticks)\n",
8872+ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
8873+ (fck / 1000 / 1000),
8874+ ticks);
8875+
8876+ return 0;
8877+}
8878+static int dsi_proto_config(struct omap_display *display)
8879+{
8880+ u32 r;
8881+ int buswidth = 0;
8882+
8883+ dsi_config_tx_fifo(DSI_FIFO_SIZE_128,
8884+ DSI_FIFO_SIZE_0,
8885+ DSI_FIFO_SIZE_0,
8886+ DSI_FIFO_SIZE_0);
8887+
8888+ dsi_config_rx_fifo(DSI_FIFO_SIZE_128,
8889+ DSI_FIFO_SIZE_0,
8890+ DSI_FIFO_SIZE_0,
8891+ DSI_FIFO_SIZE_0);
8892+
8893+ /* XXX what values for the timeouts? */
8894+ dsi_set_stop_state_counter(1000, 0, 0);
8895+
8896+ dsi_set_ta_timeout(50000, 1, 1);
8897+
8898+ /* 3000ns * 16 */
8899+ dsi_set_lp_rx_timeout(3000, 0, 1);
8900+
8901+ /* 10000ns * 4 */
8902+ dsi_set_hs_tx_timeout(10000, 1, 0);
8903+
8904+ switch (display->ctrl->pixel_size) {
8905+ case 16:
8906+ buswidth = 0;
8907+ break;
8908+ case 18:
8909+ buswidth = 1;
8910+ break;
8911+ case 24:
8912+ buswidth = 2;
8913+ break;
8914+ default:
8915+ BUG();
8916+ }
8917+
8918+ r = dsi_read_reg(DSI_CTRL);
8919+ r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */
8920+ r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */
8921+ r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */
8922+ /* XXX what should the ratio be */
8923+ r = FLD_MOD(r, 0, 4, 4); /* VP_CLK_RATIO, VP_PCLK = VP_CLK/2 */
8924+ r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
8925+ r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */
8926+ r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */
8927+ r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */
8928+ r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */
8929+ r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */
8930+ r = FLD_MOD(r, 0, 25, 25); /* DCS_CMD_CODE, 1=start, 0=continue */
8931+
8932+ dsi_write_reg(DSI_CTRL, r);
8933+
8934+ /* we configure vc0 for L4 communication, and
8935+ * vc1 for dispc */
8936+ dsi_vc_config(0);
8937+ dsi_vc_config_vp(1);
8938+
8939+ /* set all vc targets to peripheral 0 */
8940+ dsi.vc[0].dest_per = 0;
8941+ dsi.vc[1].dest_per = 0;
8942+ dsi.vc[2].dest_per = 0;
8943+ dsi.vc[3].dest_per = 0;
8944+
8945+ return 0;
8946+}
8947+
8948+static void dsi_proto_timings(void)
8949+{
8950+ int tlpx_half, tclk_zero, tclk_prepare, tclk_trail;
8951+ int tclk_pre, tclk_post;
8952+ int ddr_clk_pre, ddr_clk_post;
8953+ u32 r;
8954+
8955+ r = dsi_read_reg(DSI_DSIPHY_CFG1);
8956+ tlpx_half = FLD_GET(r, 22, 16);
8957+ tclk_trail = FLD_GET(r, 15, 8);
8958+ tclk_zero = FLD_GET(r, 7, 0);
8959+
8960+ r = dsi_read_reg(DSI_DSIPHY_CFG2);
8961+ tclk_prepare = FLD_GET(r, 7, 0);
8962+
8963+ /* min 8*UI */
8964+ tclk_pre = 20;
8965+ /* min 60ns + 52*UI */
8966+ tclk_post = ns2ddr(60) + 26;
8967+
8968+ ddr_clk_pre = (tclk_pre + tlpx_half*2 + tclk_zero + tclk_prepare) / 4;
8969+ ddr_clk_post = (tclk_post + tclk_trail) / 4;
8970+
8971+ r = dsi_read_reg(DSI_CLK_TIMING);
8972+ r = FLD_MOD(r, ddr_clk_pre, 15, 8);
8973+ r = FLD_MOD(r, ddr_clk_post, 7, 0);
8974+ dsi_write_reg(DSI_CLK_TIMING, r);
8975+
8976+ DSSDBG("ddr_clk_pre %d, ddr_clk_post %d\n",
8977+ ddr_clk_pre,
8978+ ddr_clk_post);
8979+}
8980+
8981+
8982+#define DSI_DECL_VARS \
8983+ int __dsi_cb = 0; u32 __dsi_cv = 0;
8984+
8985+#define DSI_FLUSH(ch) \
8986+ if (__dsi_cb > 0) { \
8987+ /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \
8988+ dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \
8989+ __dsi_cb = __dsi_cv = 0; \
8990+ }
8991+
8992+#define DSI_PUSH(ch, data) \
8993+ do { \
8994+ __dsi_cv |= (data) << (__dsi_cb * 8); \
8995+ /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \
8996+ if (++__dsi_cb > 3) \
8997+ DSI_FLUSH(ch); \
8998+ } while (0)
8999+
9000+static int dsi_update_screen_l4(struct omap_display *display,
9001+ int x, int y, int w, int h)
9002+{
9003+ /* Note: supports only 24bit colors in 32bit container */
9004+ int first = 1;
9005+ int fifo_stalls = 0;
9006+ int max_dsi_packet_size;
9007+ int max_data_per_packet;
9008+ int max_pixels_per_packet;
9009+ int pixels_left;
9010+ int bytespp = 3;
9011+ int scr_width;
9012+ u32 __iomem *data;
9013+ int start_offset;
9014+ int horiz_inc;
9015+ int current_x;
9016+ struct omap_overlay *ovl;
9017+
9018+ debug_irq = 0;
9019+
9020+ DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n",
9021+ x, y, w, h);
9022+
9023+ ovl = display->manager->overlays[0];
9024+
9025+ if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U)
9026+ return -EINVAL;
9027+
9028+ if (display->ctrl->pixel_size != 24)
9029+ return -EINVAL;
9030+
9031+ scr_width = ovl->info.screen_width;
9032+ data = ovl->info.vaddr;
9033+
9034+ start_offset = scr_width * y + x;
9035+ horiz_inc = scr_width - w;
9036+ current_x = x;
9037+
9038+ /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes
9039+ * in fifo */
9040+
9041+ /* When using CPU, max long packet size is TX buffer size */
9042+ max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4;
9043+
9044+ /* we seem to get better perf if we divide the tx fifo to half,
9045+ and while the other half is being sent, we fill the other half
9046+ max_dsi_packet_size /= 2; */
9047+
9048+ max_data_per_packet = max_dsi_packet_size - 4 - 1;
9049+
9050+ max_pixels_per_packet = max_data_per_packet / bytespp;
9051+
9052+ DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet);
9053+
9054+ display->ctrl->setup_update(display, x, y, w, h);
9055+
9056+ pixels_left = w * h;
9057+
9058+ DSSDBG("total pixels %d\n", pixels_left);
9059+
9060+ data += start_offset;
9061+
9062+#ifdef DEBUG
9063+ dsi.update_region.x = x;
9064+ dsi.update_region.y = y;
9065+ dsi.update_region.w = w;
9066+ dsi.update_region.h = h;
9067+ dsi.update_region.bytespp = bytespp;
9068+#endif
9069+
9070+ perf_mark_start();
9071+
9072+ while (pixels_left > 0) {
9073+ /* 0x2c = write_memory_start */
9074+ /* 0x3c = write_memory_continue */
9075+ u8 dcs_cmd = first ? 0x2c : 0x3c;
9076+ int pixels;
9077+ DSI_DECL_VARS;
9078+ first = 0;
9079+
9080+#if 1
9081+ /* using fifo not empty */
9082+ /* TX_FIFO_NOT_EMPTY */
9083+ while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) {
9084+ udelay(1);
9085+ fifo_stalls++;
9086+ if (fifo_stalls > 0xfffff) {
9087+ DSSERR("fifo stalls overflow, pixels left %d\n",
9088+ pixels_left);
9089+ dsi_if_enable(0);
9090+ return -EIO;
9091+ }
9092+ }
9093+#elif 1
9094+ /* using fifo emptiness */
9095+ while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 <
9096+ max_dsi_packet_size) {
9097+ fifo_stalls++;
9098+ if (fifo_stalls > 0xfffff) {
9099+ DSSERR("fifo stalls overflow, pixels left %d\n",
9100+ pixels_left);
9101+ dsi_if_enable(0);
9102+ return -EIO;
9103+ }
9104+ }
9105+#else
9106+ while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 == 0) {
9107+ fifo_stalls++;
9108+ if (fifo_stalls > 0xfffff) {
9109+ DSSERR("fifo stalls overflow, pixels left %d\n",
9110+ pixels_left);
9111+ dsi_if_enable(0);
9112+ return -EIO;
9113+ }
9114+ }
9115+#endif
9116+ pixels = min(max_pixels_per_packet, pixels_left);
9117+
9118+ pixels_left -= pixels;
9119+
9120+ dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE,
9121+ 1 + pixels * bytespp, 0);
9122+
9123+ DSI_PUSH(0, dcs_cmd);
9124+
9125+ while (pixels-- > 0) {
9126+ u32 pix = __raw_readl(data++);
9127+
9128+ DSI_PUSH(0, (pix >> 16) & 0xff);
9129+ DSI_PUSH(0, (pix >> 8) & 0xff);
9130+ DSI_PUSH(0, (pix >> 0) & 0xff);
9131+
9132+ current_x++;
9133+ if (current_x == x+w) {
9134+ current_x = x;
9135+ data += horiz_inc;
9136+ }
9137+ }
9138+
9139+ DSI_FLUSH(0);
9140+ }
9141+
9142+ perf_show("L4");
9143+
9144+ return 0;
9145+}
9146+
9147+#if 0
9148+static void dsi_clear_screen_l4(struct omap_display *display,
9149+ int x, int y, int w, int h)
9150+{
9151+ int first = 1;
9152+ int fifo_stalls = 0;
9153+ int max_dsi_packet_size;
9154+ int max_data_per_packet;
9155+ int max_pixels_per_packet;
9156+ int pixels_left;
9157+ int bytespp = 3;
9158+ int pixnum;
9159+
9160+ debug_irq = 0;
9161+
9162+ DSSDBG("dsi_clear_screen_l4 (%d,%d %dx%d)\n",
9163+ x, y, w, h);
9164+
9165+ if (display->ctrl->bpp != 24)
9166+ return -EINVAL;
9167+
9168+ /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp)
9169+ * bytes in fifo */
9170+
9171+ /* When using CPU, max long packet size is TX buffer size */
9172+ max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4;
9173+
9174+ max_data_per_packet = max_dsi_packet_size - 4 - 1;
9175+
9176+ max_pixels_per_packet = max_data_per_packet / bytespp;
9177+
9178+ enable_clocks(1);
9179+
9180+ display->ctrl->setup_update(display, x, y, w, h);
9181+
9182+ pixels_left = w * h;
9183+
9184+ dsi.update_region.x = x;
9185+ dsi.update_region.y = y;
9186+ dsi.update_region.w = w;
9187+ dsi.update_region.h = h;
9188+ dsi.update_region.bytespp = bytespp;
9189+
9190+ start_measuring();
9191+
9192+ pixnum = 0;
9193+
9194+ while (pixels_left > 0) {
9195+ /* 0x2c = write_memory_start */
9196+ /* 0x3c = write_memory_continue */
9197+ u8 dcs_cmd = first ? 0x2c : 0x3c;
9198+ int pixels;
9199+ DSI_DECL_VARS;
9200+ first = 0;
9201+
9202+ /* TX_FIFO_NOT_EMPTY */
9203+ while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) {
9204+ fifo_stalls++;
9205+ if (fifo_stalls > 0xfffff) {
9206+ DSSERR("fifo stalls overflow\n");
9207+ dsi_if_enable(0);
9208+ enable_clocks(0);
9209+ return;
9210+ }
9211+ }
9212+
9213+ pixels = min(max_pixels_per_packet, pixels_left);
9214+
9215+ pixels_left -= pixels;
9216+
9217+ dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE,
9218+ 1 + pixels * bytespp, 0);
9219+
9220+ DSI_PUSH(0, dcs_cmd);
9221+
9222+ while (pixels-- > 0) {
9223+ u32 pix;
9224+
9225+ pix = 0x000000;
9226+
9227+ DSI_PUSH(0, (pix >> 16) & 0xff);
9228+ DSI_PUSH(0, (pix >> 8) & 0xff);
9229+ DSI_PUSH(0, (pix >> 0) & 0xff);
9230+ }
9231+
9232+ DSI_FLUSH(0);
9233+ }
9234+
9235+ enable_clocks(0);
9236+
9237+ end_measuring("L4 CLEAR");
9238+}
9239+#endif
9240+
9241+static void dsi_setup_update_dispc(struct omap_display *display,
9242+ u16 x, u16 y, u16 w, u16 h)
9243+{
9244+ DSSDBG("dsi_setup_update_dispc(%d,%d %dx%d)\n",
9245+ x, y, w, h);
9246+
9247+#ifdef DEBUG
9248+ dsi.update_region.x = x;
9249+ dsi.update_region.y = y;
9250+ dsi.update_region.w = w;
9251+ dsi.update_region.h = h;
9252+ dsi.update_region.bytespp = 3; // XXX
9253+#endif
9254+
9255+ dispc_setup_partial_planes(display, &x, &y, &w, &h);
9256+
9257+ dispc_set_lcd_size(w, h);
9258+}
9259+
9260+static void dsi_setup_autoupdate_dispc(struct omap_display *display)
9261+{
9262+ u16 w, h;
9263+
9264+ display->get_resolution(display, &w, &h);
9265+
9266+#ifdef DEBUG
9267+ dsi.update_region.x = 0;
9268+ dsi.update_region.y = 0;
9269+ dsi.update_region.w = w;
9270+ dsi.update_region.h = h;
9271+ dsi.update_region.bytespp = 3; // XXX
9272+#endif
9273+
9274+ /* the overlay settings may not have been applied, if we were in manual
9275+ * mode earlier, so do it here */
9276+ display->manager->apply(display->manager);
9277+
9278+ dispc_set_lcd_size(w, h);
9279+
9280+ dsi.autoupdate_setup = 0;
9281+}
9282+
9283+static void dsi_update_screen_dispc(struct omap_display *display,
9284+ u16 x, u16 y, u16 w, u16 h)
9285+{
9286+ int bytespp = 3;
9287+ int total_len;
9288+ int line_packet_len;
9289+ u32 l;
9290+
9291+ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
9292+ DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
9293+ x, y, w, h);
9294+
9295+ /* TODO: one packet could be longer, I think? Max is the line buffer */
9296+ line_packet_len = w * bytespp + 1; /* 1 byte for DCS cmd */
9297+ total_len = line_packet_len * h;
9298+
9299+ display->ctrl->setup_update(display, x, y, w, h);
9300+
9301+ if (0)
9302+ dsi_vc_print_status(1);
9303+
9304+ perf_mark_start();
9305+
9306+ l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
9307+ dsi_write_reg(DSI_VC_TE(1), l);
9308+
9309+ dsi_vc_write_long_header(1, DSI_DT_DCS_LONG_WRITE, line_packet_len, 0);
9310+
9311+ if (dsi.use_te)
9312+ l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
9313+ else
9314+ l = FLD_MOD(l, 1, 31, 31); /* TE_START */
9315+ dsi_write_reg(DSI_VC_TE(1), l);
9316+
9317+ dispc_enable_lcd_out(1);
9318+
9319+ if (dsi.use_te)
9320+ dsi_vc_send_bta(1);
9321+}
9322+
9323+static void framedone_callback(void *data, u32 mask)
9324+{
9325+ if (dsi.framedone_scheduled) {
9326+ DSSERR("Framedone already scheduled. Bogus FRAMEDONE IRQ?\n");
9327+ return;
9328+ }
9329+
9330+ dsi.framedone_scheduled = 1;
9331+
9332+ /* We get FRAMEDONE when DISPC has finished sending pixels and turns
9333+ * itself off. However, DSI still has the pixels in its buffers, and
9334+ * is sending the data. Thus we have to wait until we can do a new
9335+ * transfer or turn the clocks off. We do that in a separate work
9336+ * func. */
9337+ queue_work(dsi.workqueue, &dsi.framedone_work);
9338+}
9339+
9340+static void framedone_worker(struct work_struct *work)
9341+{
9342+ u32 l;
9343+ unsigned long tmo;
9344+ int i = 0;
9345+
9346+ l = REG_GET(DSI_VC_TE(1), 23, 0); /* TE_SIZE */
9347+
9348+ /* There shouldn't be much stuff in DSI buffers, if any, so we'll
9349+ * just busyloop */
9350+ if (l > 0) {
9351+ tmo = jiffies + msecs_to_jiffies(50);
9352+ while (REG_GET(DSI_VC_TE(1), 23, 0) > 0) { /* TE_SIZE */
9353+ i++;
9354+ if (time_after(jiffies, tmo)) {
9355+ DSSERR("timeout waiting TE_SIZE to zero\n");
9356+ break;
9357+ }
9358+ cpu_relax();
9359+ }
9360+ }
9361+
9362+ if (REG_GET(DSI_VC_TE(1), 30, 30))
9363+ DSSERR("TE_EN not zero\n");
9364+
9365+ if (REG_GET(DSI_VC_TE(1), 31, 31))
9366+ DSSERR("TE_START not zero\n");
9367+
9368+ perf_show("DISPC");
9369+
9370+ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
9371+ DSSDBG("FRAMEDONE\n");
9372+
9373+#if 0
9374+ if (l)
9375+ DSSWARN("FRAMEDONE irq too early, %d bytes, %d loops\n", l, i);
9376+#else
9377+ if (l > 1024*3)
9378+ DSSWARN("FRAMEDONE irq too early, %d bytes, %d loops\n", l, i);
9379+#endif
9380+
9381+#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
9382+ dispc_fake_vsync_irq();
9383+#endif
9384+ dsi.framedone_scheduled = 0;
9385+
9386+ /* XXX check that fifo is not full. otherwise we would sleep and never
9387+ * get to process_cmd_fifo below */
9388+ /* We check for target_update_mode, not update_mode. No reason to push
9389+ * new updates if we're turning auto update off */
9390+ if (dsi.target_update_mode == OMAP_DSS_UPDATE_AUTO)
9391+ dsi_push_autoupdate(dsi.vc[1].display);
9392+
9393+ atomic_set(&dsi.cmd_pending, 0);
9394+ dsi_process_cmd_fifo(NULL);
9395+}
9396+
9397+static void dsi_start_auto_update(struct omap_display *display)
9398+{
9399+ DSSDBG("starting auto update\n");
9400+
9401+ dsi.autoupdate_setup = 1;
9402+
9403+ dsi_push_autoupdate(display);
9404+}
9405+
9406+
9407+
9408+
9409+
9410+
9411+
9412+
9413+
9414+
9415+
9416+
9417+
9418+/* FIFO functions */
9419+
9420+static void dsi_signal_fifo_waiters(void)
9421+{
9422+ if (atomic_read(&dsi.cmd_fifo_full) > 0) {
9423+ DSSDBG("SIGNALING: Fifo not full for waiter!\n");
9424+ complete(&dsi.cmd_done);
9425+ atomic_dec(&dsi.cmd_fifo_full);
9426+ }
9427+}
9428+
9429+/* returns 1 for async op, and 0 for sync op */
9430+static int dsi_do_update(struct omap_display *display,
9431+ struct dsi_cmd_update *upd)
9432+{
9433+ int r;
9434+ u16 x = upd->x, y = upd->y, w = upd->w, h = upd->h;
9435+ u16 dw, dh;
9436+
9437+ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED)
9438+ return 0;
9439+
9440+ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
9441+ return 0;
9442+
9443+ display->get_resolution(display, &dw, &dh);
9444+ if (x > dw || y > dh)
9445+ return 0;
9446+
9447+ if (x + w > dw)
9448+ w = dw - x;
9449+
9450+ if (y + h > dh)
9451+ h = dh - y;
9452+
9453+ DSSDBGF("%d,%d %dx%d", x, y, w, h);
9454+
9455+ perf_mark_setup();
9456+
9457+ if (display->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
9458+ dsi_setup_update_dispc(display, x, y, w, h);
9459+ dsi_update_screen_dispc(display, x, y, w, h);
9460+ return 1;
9461+ } else {
9462+ r = dsi_update_screen_l4(display, x, y, w, h);
9463+ if (r)
9464+ DSSERR("L4 update failed\n");
9465+ return 0;
9466+ }
9467+}
9468+
9469+/* returns 1 for async op, and 0 for sync op */
9470+static int dsi_do_autoupdate(struct omap_display *display)
9471+{
9472+ int r;
9473+ u16 w, h;
9474+
9475+ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED)
9476+ return 0;
9477+
9478+ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
9479+ return 0;
9480+
9481+ display->get_resolution(display, &w, &h);
9482+
9483+ perf_mark_setup();
9484+
9485+ if (display->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
9486+ if (dsi.autoupdate_setup)
9487+ dsi_setup_autoupdate_dispc(display);
9488+ dsi_update_screen_dispc(display, 0, 0, w, h);
9489+ return 1;
9490+ } else {
9491+ r = dsi_update_screen_l4(display, 0, 0, w, h);
9492+ if (r)
9493+ DSSERR("L4 update failed\n");
9494+ return 0;
9495+ }
9496+}
9497+
9498+static void dsi_do_cmd_mem_read(struct omap_display *display,
9499+ struct dsi_cmd_mem_read *mem_read)
9500+{
9501+ int r;
9502+ r = display->ctrl->memory_read(display,
9503+ mem_read->buf,
9504+ mem_read->size,
9505+ mem_read->x,
9506+ mem_read->y,
9507+ mem_read->w,
9508+ mem_read->h);
9509+
9510+ *mem_read->ret_size = (size_t)r;
9511+ complete(mem_read->completion);
9512+}
9513+
9514+static void dsi_do_cmd_test(struct omap_display *display,
9515+ struct dsi_cmd_test *test)
9516+{
9517+ int r = 0;
9518+
9519+ DSSDBGF("");
9520+
9521+ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
9522+ return;
9523+
9524+ /* run test first in low speed mode */
9525+ dsi_vc_enable_hs(0, 0);
9526+
9527+ if (display->ctrl->run_test) {
9528+ r = display->ctrl->run_test(display, test->test_num);
9529+ if (r)
9530+ goto end;
9531+ }
9532+
9533+ if (display->panel->run_test) {
9534+ r = display->panel->run_test(display, test->test_num);
9535+ if (r)
9536+ goto end;
9537+ }
9538+
9539+ /* then in high speed */
9540+ dsi_vc_enable_hs(0, 1);
9541+
9542+ if (display->ctrl->run_test) {
9543+ r = display->ctrl->run_test(display, test->test_num);
9544+ if (r)
9545+ goto end;
9546+ }
9547+
9548+ if (display->panel->run_test)
9549+ r = display->panel->run_test(display, test->test_num);
9550+
9551+end:
9552+ dsi_vc_enable_hs(0, 1);
9553+
9554+ *test->result = r;
9555+ complete(test->completion);
9556+
9557+ DSSDBG("test end\n");
9558+}
9559+
9560+static void dsi_do_cmd_set_te(struct omap_display *display, bool enable)
9561+{
9562+ dsi.use_te = enable;
9563+
9564+ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
9565+ return;
9566+
9567+ display->ctrl->enable_te(display, enable);
9568+
9569+ if (enable) {
9570+ /* disable LP_RX_TO, so that we can receive TE.
9571+ * Time to wait for TE is longer than the timer allows */
9572+ REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
9573+ } else {
9574+ REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
9575+ }
9576+}
9577+
9578+static void dsi_do_cmd_set_update_mode(struct omap_display *display,
9579+ enum omap_dss_update_mode mode)
9580+{
9581+ dsi.update_mode = mode;
9582+
9583+ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
9584+ return;
9585+
9586+ if (mode == OMAP_DSS_UPDATE_AUTO)
9587+ dsi_start_auto_update(display);
9588+}
9589+
9590+static void dsi_process_cmd_fifo(struct work_struct *work)
9591+{
9592+ int len;
9593+ struct dsi_cmd_item p;
9594+ unsigned long flags;
9595+ struct omap_display *display;
9596+ int exit = 0;
9597+
9598+ if (dsi.debug_process)
9599+ DSSDBGF("");
9600+
9601+ if (atomic_cmpxchg(&dsi.cmd_pending, 0, 1) == 1) {
9602+ if (dsi.debug_process)
9603+ DSSDBG("cmd pending, skip process\n");
9604+ return;
9605+ }
9606+
9607+ while (!exit) {
9608+ spin_lock_irqsave(dsi.cmd_fifo->lock, flags);
9609+
9610+ len = __kfifo_get(dsi.cmd_fifo, (unsigned char *)&p,
9611+ sizeof(p));
9612+ if (len == 0) {
9613+ if (dsi.debug_process)
9614+ DSSDBG("nothing more in fifo, atomic clear\n");
9615+ atomic_set(&dsi.cmd_pending, 0);
9616+ spin_unlock_irqrestore(dsi.cmd_fifo->lock, flags);
9617+ break;
9618+ }
9619+
9620+ spin_unlock_irqrestore(dsi.cmd_fifo->lock, flags);
9621+
9622+ BUG_ON(len != sizeof(p));
9623+
9624+ display = p.display;
9625+
9626+ if (dsi.debug_process)
9627+ DSSDBG("processing cmd %d\n", p.cmd);
9628+
9629+ switch (p.cmd) {
9630+ case DSI_CMD_UPDATE:
9631+ if (dsi_do_update(display, &p.u.r)) {
9632+ if (dsi.debug_process)
9633+ DSSDBG("async update\n");
9634+ exit = 1;
9635+ } else {
9636+ if (dsi.debug_process)
9637+ DSSDBG("sync update\n");
9638+ }
9639+ break;
9640+
9641+ case DSI_CMD_AUTOUPDATE:
9642+ if (dsi_do_autoupdate(display)) {
9643+ if (dsi.debug_process)
9644+ DSSDBG("async autoupdate\n");
9645+ exit = 1;
9646+ } else {
9647+ if (dsi.debug_process)
9648+ DSSDBG("sync autoupdate\n");
9649+ }
9650+ break;
9651+
9652+ case DSI_CMD_SYNC:
9653+ if (dsi.debug_process)
9654+ DSSDBG("Signaling SYNC done!\n");
9655+ complete(p.u.sync);
9656+ break;
9657+
9658+ case DSI_CMD_MEM_READ:
9659+ dsi_do_cmd_mem_read(display, &p.u.mem_read);
9660+ break;
9661+
9662+ case DSI_CMD_TEST:
9663+ dsi_do_cmd_test(display, &p.u.test);
9664+ break;
9665+
9666+ case DSI_CMD_SET_TE:
9667+ dsi_do_cmd_set_te(display, p.u.te);
9668+ break;
9669+
9670+ case DSI_CMD_SET_UPDATE_MODE:
9671+ dsi_do_cmd_set_update_mode(display, p.u.update_mode);
9672+ break;
9673+
9674+ case DSI_CMD_SET_ROTATE:
9675+ display->ctrl->set_rotate(display, p.u.rotate);
9676+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
9677+ dsi.autoupdate_setup = 1;
9678+ break;
9679+
9680+ case DSI_CMD_SET_MIRROR:
9681+ display->ctrl->set_mirror(display, p.u.mirror);
9682+ break;
9683+
9684+ default:
9685+ BUG();
9686+ }
9687+ }
9688+
9689+ if (dsi.debug_process)
9690+ DSSDBG("exit dsi_process_cmd_fifo\n");
9691+
9692+ dsi_signal_fifo_waiters();
9693+}
9694+
9695+static void dsi_push_cmd(struct dsi_cmd_item *p)
9696+{
9697+ int ret;
9698+
9699+ if (dsi.debug_process)
9700+ DSSDBGF("");
9701+
9702+ while (1) {
9703+ unsigned long flags;
9704+ unsigned avail, used;
9705+
9706+ spin_lock_irqsave(dsi.cmd_fifo->lock, flags);
9707+ used = __kfifo_len(dsi.cmd_fifo) / sizeof(struct dsi_cmd_item);
9708+ avail = DSI_CMD_FIFO_LEN - used;
9709+
9710+ if (dsi.debug_process)
9711+ DSSDBG("%u/%u items left in fifo\n", avail, used);
9712+
9713+ if (avail == 0) {
9714+ if (dsi.debug_process)
9715+ DSSDBG("cmd fifo full, waiting...\n");
9716+ spin_unlock_irqrestore(dsi.cmd_fifo->lock, flags);
9717+ atomic_inc(&dsi.cmd_fifo_full);
9718+ wait_for_completion(&dsi.cmd_done);
9719+ if (dsi.debug_process)
9720+ DSSDBG("cmd fifo not full, woke up\n");
9721+ continue;
9722+ }
9723+
9724+ ret = __kfifo_put(dsi.cmd_fifo, (unsigned char *)p,
9725+ sizeof(*p));
9726+
9727+ spin_unlock_irqrestore(dsi.cmd_fifo->lock, flags);
9728+
9729+ BUG_ON(ret != sizeof(*p));
9730+
9731+ break;
9732+ }
9733+
9734+ queue_work(dsi.workqueue, &dsi.process_work);
9735+}
9736+
9737+static void dsi_push_update(struct omap_display *display,
9738+ int x, int y, int w, int h)
9739+{
9740+ struct dsi_cmd_item p;
9741+
9742+ p.display = display;
9743+ p.cmd = DSI_CMD_UPDATE;
9744+
9745+ p.u.r.x = x;
9746+ p.u.r.y = y;
9747+ p.u.r.w = w;
9748+ p.u.r.h = h;
9749+
9750+ DSSDBG("pushing UPDATE %d,%d %dx%d\n", x, y, w, h);
9751+
9752+ dsi_push_cmd(&p);
9753+}
9754+
9755+static void dsi_push_autoupdate(struct omap_display *display)
9756+{
9757+ struct dsi_cmd_item p;
9758+
9759+ p.display = display;
9760+ p.cmd = DSI_CMD_AUTOUPDATE;
9761+
9762+ dsi_push_cmd(&p);
9763+}
9764+
9765+static void dsi_push_sync(struct omap_display *display,
9766+ struct completion *sync_comp)
9767+{
9768+ struct dsi_cmd_item p;
9769+
9770+ p.display = display;
9771+ p.cmd = DSI_CMD_SYNC;
9772+ p.u.sync = sync_comp;
9773+
9774+ DSSDBG("pushing SYNC\n");
9775+
9776+ dsi_push_cmd(&p);
9777+}
9778+
9779+static void dsi_push_mem_read(struct omap_display *display,
9780+ struct dsi_cmd_mem_read *mem_read)
9781+{
9782+ struct dsi_cmd_item p;
9783+
9784+ p.display = display;
9785+ p.cmd = DSI_CMD_MEM_READ;
9786+ p.u.mem_read = *mem_read;
9787+
9788+ DSSDBG("pushing MEM_READ\n");
9789+
9790+ dsi_push_cmd(&p);
9791+}
9792+
9793+static void dsi_push_test(struct omap_display *display, int test_num,
9794+ int *result, struct completion *completion)
9795+{
9796+ struct dsi_cmd_item p;
9797+
9798+ p.display = display;
9799+ p.cmd = DSI_CMD_TEST;
9800+ p.u.test.test_num = test_num;
9801+ p.u.test.result = result;
9802+ p.u.test.completion = completion;
9803+
9804+ DSSDBG("pushing TEST\n");
9805+
9806+ dsi_push_cmd(&p);
9807+}
9808+
9809+static void dsi_push_set_te(struct omap_display *display, bool enable)
9810+{
9811+ struct dsi_cmd_item p;
9812+
9813+ p.display = display;
9814+ p.cmd = DSI_CMD_SET_TE;
9815+ p.u.te = enable;
9816+
9817+ DSSDBG("pushing SET_TE\n");
9818+
9819+ dsi_push_cmd(&p);
9820+}
9821+
9822+static void dsi_push_set_update_mode(struct omap_display *display,
9823+ enum omap_dss_update_mode mode)
9824+{
9825+ struct dsi_cmd_item p;
9826+
9827+ p.display = display;
9828+ p.cmd = DSI_CMD_SET_UPDATE_MODE;
9829+ p.u.update_mode = mode;
9830+
9831+ DSSDBG("pushing SET_UPDATE_MODE\n");
9832+
9833+ dsi_push_cmd(&p);
9834+}
9835+
9836+static void dsi_push_set_rotate(struct omap_display *display, int rotate)
9837+{
9838+ struct dsi_cmd_item p;
9839+
9840+ p.display = display;
9841+ p.cmd = DSI_CMD_SET_ROTATE;
9842+ p.u.rotate = rotate;
9843+
9844+ DSSDBG("pushing SET_ROTATE\n");
9845+
9846+ dsi_push_cmd(&p);
9847+}
9848+
9849+static void dsi_push_set_mirror(struct omap_display *display, int mirror)
9850+{
9851+ struct dsi_cmd_item p;
9852+
9853+ p.display = display;
9854+ p.cmd = DSI_CMD_SET_MIRROR;
9855+ p.u.mirror = mirror;
9856+
9857+ DSSDBG("pushing SET_MIRROR\n");
9858+
9859+ dsi_push_cmd(&p);
9860+}
9861+
9862+static int dsi_wait_sync(struct omap_display *display)
9863+{
9864+ long wait = msecs_to_jiffies(60000);
9865+ struct completion compl;
9866+
9867+ DSSDBGF("");
9868+
9869+ init_completion(&compl);
9870+ dsi_push_sync(display, &compl);
9871+
9872+ DSSDBG("Waiting for SYNC to happen...\n");
9873+ wait = wait_for_completion_timeout(&compl, wait);
9874+ DSSDBG("Released from SYNC\n");
9875+
9876+ if (wait == 0) {
9877+ DSSERR("timeout waiting sync\n");
9878+ return -ETIME;
9879+ }
9880+
9881+ return 0;
9882+}
9883+
9884+
9885+
9886+
9887+
9888+
9889+
9890+
9891+
9892+
9893+
9894+
9895+/* Display funcs */
9896+
9897+static int dsi_display_init_dispc(struct omap_display *display)
9898+{
9899+ int r;
9900+
9901+ r = omap_dispc_register_isr(framedone_callback, NULL,
9902+ DISPC_IRQ_FRAMEDONE);
9903+ if (r) {
9904+ DSSERR("can't get FRAMEDONE irq\n");
9905+ return r;
9906+ }
9907+
9908+ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
9909+
9910+ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_DSI);
9911+ dispc_enable_fifohandcheck(1);
9912+
9913+ dispc_set_tft_data_lines(display->ctrl->pixel_size);
9914+
9915+ {
9916+ struct omap_video_timings timings = {
9917+ .hsw = 1,
9918+ .hfp = 1,
9919+ .hbp = 1,
9920+ .vsw = 1,
9921+ .vfp = 0,
9922+ .vbp = 0,
9923+ };
9924+
9925+ dispc_set_lcd_timings(&timings);
9926+ }
9927+
9928+ return 0;
9929+}
9930+
9931+static void dsi_display_uninit_dispc(struct omap_display *display)
9932+{
9933+ omap_dispc_unregister_isr(framedone_callback, NULL,
9934+ DISPC_IRQ_FRAMEDONE);
9935+}
9936+
9937+static int dsi_display_init_dsi(struct omap_display *display)
9938+{
9939+ struct dsi_clock_info cinfo;
9940+ int r;
9941+
9942+ _dsi_print_reset_status();
9943+
9944+ r = dsi_pll_init(1, 0);
9945+ if (r)
9946+ goto err0;
9947+
9948+ r = dsi_pll_calc_ddrfreq(display->hw_config.u.dsi.ddr_clk_hz, &cinfo);
9949+ if (r)
9950+ goto err1;
9951+
9952+ r = dsi_pll_program(&cinfo);
9953+ if (r)
9954+ goto err1;
9955+
9956+ DSSDBG("PLL OK\n");
9957+
9958+ r = dsi_complexio_init(display);
9959+ if (r)
9960+ goto err1;
9961+
9962+ _dsi_print_reset_status();
9963+
9964+ dsi_proto_timings();
9965+ dsi_set_lp_clk_divisor();
9966+
9967+ if (1)
9968+ _dsi_print_reset_status();
9969+
9970+ r = dsi_proto_config(display);
9971+ if (r)
9972+ goto err2;
9973+
9974+ /* enable interface */
9975+ dsi_vc_enable(0, 1);
9976+ dsi_vc_enable(1, 1);
9977+ dsi_if_enable(1);
9978+ dsi_force_tx_stop_mode_io();
9979+
9980+ if (display->ctrl && display->ctrl->enable) {
9981+ r = display->ctrl->enable(display);
9982+ if (r)
9983+ goto err3;
9984+ }
9985+
9986+ if (display->panel && display->panel->enable) {
9987+ r = display->panel->enable(display);
9988+ if (r)
9989+ goto err4;
9990+ }
9991+
9992+ /* enable high-speed after initial config */
9993+ dsi_vc_enable_hs(0, 1);
9994+
9995+ return 0;
9996+err4:
9997+ if (display->ctrl && display->ctrl->disable)
9998+ display->ctrl->disable(display);
9999+err3:
10000+ dsi_if_enable(0);
10001+err2:
10002+ dsi_complexio_uninit();
10003+err1:
10004+ dsi_pll_uninit();
10005+err0:
10006+ return r;
10007+}
10008+
10009+static void dsi_display_uninit_dsi(struct omap_display *display)
10010+{
10011+ if (display->panel && display->panel->disable)
10012+ display->panel->disable(display);
10013+ if (display->ctrl && display->ctrl->disable)
10014+ display->ctrl->disable(display);
10015+
10016+ dsi_complexio_uninit();
10017+ dsi_pll_uninit();
10018+}
10019+
10020+static int dsi_core_init(void)
10021+{
10022+ /* Autoidle */
10023+ REG_FLD_MOD(DSI_SYSCONFIG, 1, 0, 0);
10024+
10025+ /* ENWAKEUP */
10026+ REG_FLD_MOD(DSI_SYSCONFIG, 1, 2, 2);
10027+
10028+ /* SIDLEMODE smart-idle */
10029+ REG_FLD_MOD(DSI_SYSCONFIG, 2, 4, 3);
10030+
10031+ _dsi_initialize_irq();
10032+
10033+ return 0;
10034+}
10035+
10036+static int dsi_display_enable(struct omap_display *display)
10037+{
10038+ int r = 0;
10039+
10040+ DSSDBG("dsi_display_enable\n");
10041+
10042+ mutex_lock(&dsi.lock);
10043+
10044+ if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
10045+ DSSERR("display already enabled\n");
10046+ r = -EINVAL;
10047+ goto err0;
10048+ }
10049+
10050+ enable_clocks(1);
10051+ dsi_enable_pll_clock(1);
10052+
10053+ r = _dsi_reset();
10054+ if (r)
10055+ return r;
10056+
10057+ dsi_core_init();
10058+
10059+ r = dsi_display_init_dispc(display);
10060+ if (r)
10061+ goto err1;
10062+
10063+ r = dsi_display_init_dsi(display);
10064+ if (r)
10065+ goto err2;
10066+
10067+ display->state = OMAP_DSS_DISPLAY_ACTIVE;
10068+
10069+ if (dsi.use_te)
10070+ dsi_push_set_te(display, 1);
10071+
10072+ dsi_push_set_update_mode(display, dsi.user_update_mode);
10073+ dsi.target_update_mode = dsi.user_update_mode;
10074+
10075+ mutex_unlock(&dsi.lock);
10076+
10077+ return dsi_wait_sync(display);
10078+
10079+err2:
10080+ dsi_display_uninit_dispc(display);
10081+err1:
10082+ enable_clocks(0);
10083+ dsi_enable_pll_clock(0);
10084+err0:
10085+ mutex_unlock(&dsi.lock);
10086+ DSSDBG("dsi_display_enable FAILED\n");
10087+ return r;
10088+}
10089+
10090+static void dsi_display_disable(struct omap_display *display)
10091+{
10092+ DSSDBG("dsi_display_disable\n");
10093+
10094+ mutex_lock(&dsi.lock);
10095+
10096+ if (display->state == OMAP_DSS_DISPLAY_DISABLED ||
10097+ display->state == OMAP_DSS_DISPLAY_SUSPENDED)
10098+ goto end;
10099+
10100+ if (dsi.target_update_mode != OMAP_DSS_UPDATE_DISABLED) {
10101+ dsi_push_set_update_mode(display, OMAP_DSS_UPDATE_DISABLED);
10102+ dsi.target_update_mode = OMAP_DSS_UPDATE_DISABLED;
10103+ }
10104+
10105+ dsi_wait_sync(display);
10106+
10107+ display->state = OMAP_DSS_DISPLAY_DISABLED;
10108+
10109+ dsi_display_uninit_dispc(display);
10110+
10111+ dsi_display_uninit_dsi(display);
10112+
10113+ enable_clocks(0);
10114+ dsi_enable_pll_clock(0);
10115+end:
10116+ mutex_unlock(&dsi.lock);
10117+}
10118+
10119+static int dsi_display_suspend(struct omap_display *display)
10120+{
10121+ DSSDBG("dsi_display_suspend\n");
10122+
10123+ dsi_display_disable(display);
10124+
10125+ display->state = OMAP_DSS_DISPLAY_SUSPENDED;
10126+
10127+ return 0;
10128+}
10129+
10130+static int dsi_display_resume(struct omap_display *display)
10131+{
10132+ DSSDBG("dsi_display_resume\n");
10133+
10134+ display->state = OMAP_DSS_DISPLAY_DISABLED;
10135+ return dsi_display_enable(display);
10136+}
10137+
10138+static int dsi_display_update(struct omap_display *display,
10139+ u16 x, u16 y, u16 w, u16 h)
10140+{
10141+ DSSDBG("dsi_display_update(%d,%d %dx%d)\n", x, y, w, h);
10142+
10143+ if (w == 0 || h == 0)
10144+ return 0;
10145+
10146+ mutex_lock(&dsi.lock);
10147+
10148+ if (dsi.target_update_mode == OMAP_DSS_UPDATE_MANUAL)
10149+ dsi_push_update(display, x, y, w, h);
10150+ /* XXX else return error? */
10151+
10152+ mutex_unlock(&dsi.lock);
10153+
10154+ return 0;
10155+}
10156+
10157+static int dsi_display_sync(struct omap_display *display)
10158+{
10159+ DSSDBGF("");
10160+ return dsi_wait_sync(display);
10161+}
10162+
10163+static int dsi_display_set_update_mode(struct omap_display *display,
10164+ enum omap_dss_update_mode mode)
10165+{
10166+ DSSDBGF("%d", mode);
10167+
10168+ mutex_lock(&dsi.lock);
10169+
10170+ if (dsi.target_update_mode != mode) {
10171+ dsi_push_set_update_mode(display, mode);
10172+
10173+ dsi.target_update_mode = mode;
10174+ dsi.user_update_mode = mode;
10175+ }
10176+
10177+ mutex_unlock(&dsi.lock);
10178+
10179+ return dsi_wait_sync(display);
10180+}
10181+
10182+static enum omap_dss_update_mode dsi_display_get_update_mode(
10183+ struct omap_display *display)
10184+{
10185+ return dsi.update_mode;
10186+}
10187+
10188+static int dsi_display_enable_te(struct omap_display *display, bool enable)
10189+{
10190+ DSSDBGF("%d", enable);
10191+
10192+ if (!display->ctrl->enable_te)
10193+ return -ENOENT;
10194+
10195+ dsi_push_set_te(display, enable);
10196+
10197+ return dsi_wait_sync(display);
10198+}
10199+
10200+static int dsi_display_get_te(struct omap_display *display)
10201+{
10202+ return dsi.use_te;
10203+}
10204+
10205+
10206+
10207+static int dsi_display_set_rotate(struct omap_display *display, u8 rotate)
10208+{
10209+ DSSDBGF("%d", rotate);
10210+
10211+ if (!display->ctrl->set_rotate || !display->ctrl->get_rotate)
10212+ return -EINVAL;
10213+
10214+ dsi_push_set_rotate(display, rotate);
10215+
10216+ return dsi_wait_sync(display);
10217+}
10218+
10219+static u8 dsi_display_get_rotate(struct omap_display *display)
10220+{
10221+ if (!display->ctrl->set_rotate || !display->ctrl->get_rotate)
10222+ return 0;
10223+
10224+ return display->ctrl->get_rotate(display);
10225+}
10226+
10227+static int dsi_display_set_mirror(struct omap_display *display, bool mirror)
10228+{
10229+ DSSDBGF("%d", mirror);
10230+
10231+ if (!display->ctrl->set_mirror || !display->ctrl->get_mirror)
10232+ return -EINVAL;
10233+
10234+ dsi_push_set_mirror(display, mirror);
10235+
10236+ return dsi_wait_sync(display);
10237+}
10238+
10239+static bool dsi_display_get_mirror(struct omap_display *display)
10240+{
10241+ if (!display->ctrl->set_mirror || !display->ctrl->get_mirror)
10242+ return 0;
10243+
10244+ return display->ctrl->get_mirror(display);
10245+}
10246+
10247+static int dsi_display_run_test(struct omap_display *display, int test_num)
10248+{
10249+ long wait = msecs_to_jiffies(60000);
10250+ struct completion compl;
10251+ int result;
10252+
10253+ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
10254+ return -EIO;
10255+
10256+ DSSDBGF("%d", test_num);
10257+
10258+ init_completion(&compl);
10259+
10260+ dsi_push_test(display, test_num, &result, &compl);
10261+
10262+ DSSDBG("Waiting for SYNC to happen...\n");
10263+ wait = wait_for_completion_timeout(&compl, wait);
10264+ DSSDBG("Released from SYNC\n");
10265+
10266+ if (wait == 0) {
10267+ DSSERR("timeout waiting test sync\n");
10268+ return -ETIME;
10269+ }
10270+
10271+ return result;
10272+}
10273+
10274+static int dsi_display_memory_read(struct omap_display *display,
10275+ void *buf, size_t size,
10276+ u16 x, u16 y, u16 w, u16 h)
10277+{
10278+ long wait = msecs_to_jiffies(60000);
10279+ struct completion compl;
10280+ struct dsi_cmd_mem_read mem_read;
10281+ size_t ret_size;
10282+
10283+ DSSDBGF("");
10284+
10285+ if (!display->ctrl->memory_read)
10286+ return -EINVAL;
10287+
10288+ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
10289+ return -EIO;
10290+
10291+ init_completion(&compl);
10292+
10293+ mem_read.x = x;
10294+ mem_read.y = y;
10295+ mem_read.w = w;
10296+ mem_read.h = h;
10297+ mem_read.buf = buf;
10298+ mem_read.size = size;
10299+ mem_read.ret_size = &ret_size;
10300+ mem_read.completion = &compl;
10301+
10302+ dsi_push_mem_read(display, &mem_read);
10303+
10304+ DSSDBG("Waiting for SYNC to happen...\n");
10305+ wait = wait_for_completion_timeout(&compl, wait);
10306+ DSSDBG("Released from SYNC\n");
10307+
10308+ if (wait == 0) {
10309+ DSSERR("timeout waiting mem read sync\n");
10310+ return -ETIME;
10311+ }
10312+
10313+ return ret_size;
10314+}
10315+
10316+static void dsi_configure_overlay(struct omap_overlay *ovl)
10317+{
10318+ unsigned low, high, size;
10319+ enum omap_burst_size burst;
10320+ enum omap_plane plane = ovl->id;
10321+
10322+ burst = OMAP_DSS_BURST_16x32;
10323+ size = 16 * 32 / 8;
10324+
10325+ dispc_set_burst_size(plane, burst);
10326+
10327+ high = dispc_get_plane_fifo_size(plane) - size;
10328+ low = 0;
10329+ dispc_setup_plane_fifo(plane, low, high);
10330+}
10331+
10332+void dsi_init_display(struct omap_display *display)
10333+{
10334+ DSSDBG("DSI init\n");
10335+
10336+ display->enable = dsi_display_enable;
10337+ display->disable = dsi_display_disable;
10338+ display->suspend = dsi_display_suspend;
10339+ display->resume = dsi_display_resume;
10340+ display->update = dsi_display_update;
10341+ display->sync = dsi_display_sync;
10342+ display->set_update_mode = dsi_display_set_update_mode;
10343+ display->get_update_mode = dsi_display_get_update_mode;
10344+ display->enable_te = dsi_display_enable_te;
10345+ display->get_te = dsi_display_get_te;
10346+
10347+ display->get_rotate = dsi_display_get_rotate;
10348+ display->set_rotate = dsi_display_set_rotate;
10349+
10350+ display->get_mirror = dsi_display_get_mirror;
10351+ display->set_mirror = dsi_display_set_mirror;
10352+
10353+ display->run_test = dsi_display_run_test;
10354+ display->memory_read = dsi_display_memory_read;
10355+
10356+ display->configure_overlay = dsi_configure_overlay;
10357+
10358+ display->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
10359+
10360+ dsi.vc[0].display = display;
10361+ dsi.vc[1].display = display;
10362+}
10363+
10364+int dsi_init(void)
10365+{
10366+ u32 rev;
10367+
10368+ spin_lock_init(&dsi.cmd_lock);
10369+ dsi.cmd_fifo = kfifo_alloc(
10370+ DSI_CMD_FIFO_LEN * sizeof(struct dsi_cmd_item),
10371+ GFP_KERNEL,
10372+ &dsi.cmd_lock);
10373+
10374+ init_completion(&dsi.cmd_done);
10375+ atomic_set(&dsi.cmd_fifo_full, 0);
10376+ atomic_set(&dsi.cmd_pending, 0);
10377+
10378+ init_completion(&dsi.bta_completion);
10379+
10380+ dsi.workqueue = create_singlethread_workqueue("dsi");
10381+ INIT_WORK(&dsi.framedone_work, framedone_worker);
10382+ INIT_WORK(&dsi.process_work, dsi_process_cmd_fifo);
10383+
10384+ mutex_init(&dsi.lock);
10385+
10386+ dsi.target_update_mode = OMAP_DSS_UPDATE_DISABLED;
10387+ dsi.user_update_mode = OMAP_DSS_UPDATE_DISABLED;
10388+
10389+ dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS);
10390+ if (!dsi.base) {
10391+ DSSERR("can't ioremap DSI\n");
10392+ return -ENOMEM;
10393+ }
10394+
10395+ enable_clocks(1);
10396+
10397+ rev = dsi_read_reg(DSI_REVISION);
10398+ printk(KERN_INFO "OMAP DSI rev %d.%d\n",
10399+ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
10400+
10401+ enable_clocks(0);
10402+
10403+ return 0;
10404+}
10405+
10406+void dsi_exit(void)
10407+{
10408+ flush_workqueue(dsi.workqueue);
10409+ destroy_workqueue(dsi.workqueue);
10410+
10411+ iounmap(dsi.base);
10412+
10413+ kfifo_free(dsi.cmd_fifo);
10414+
10415+ DSSDBG("omap_dsi_exit\n");
10416+}
10417+
10418diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
10419new file mode 100644
10420index 0000000..adc1f34
10421--- /dev/null
10422+++ b/drivers/video/omap2/dss/dss.c
10423@@ -0,0 +1,345 @@
10424+/*
10425+ * linux/drivers/video/omap2/dss/dss.c
10426+ *
10427+ * Copyright (C) 2009 Nokia Corporation
10428+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
10429+ *
10430+ * Some code and ideas taken from drivers/video/omap/ driver
10431+ * by Imre Deak.
10432+ *
10433+ * This program is free software; you can redistribute it and/or modify it
10434+ * under the terms of the GNU General Public License version 2 as published by
10435+ * the Free Software Foundation.
10436+ *
10437+ * This program is distributed in the hope that it will be useful, but WITHOUT
10438+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10439+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
10440+ * more details.
10441+ *
10442+ * You should have received a copy of the GNU General Public License along with
10443+ * this program. If not, see <http://www.gnu.org/licenses/>.
10444+ */
10445+
10446+#define DSS_SUBSYS_NAME "DSS"
10447+
10448+#include <linux/kernel.h>
10449+#include <linux/io.h>
10450+#include <linux/err.h>
10451+#include <linux/delay.h>
10452+#include <linux/interrupt.h>
10453+#include <linux/seq_file.h>
10454+
10455+#include <mach/display.h>
10456+#include "dss.h"
10457+
10458+#define DSS_BASE 0x48050000
10459+
10460+#define DSS_SZ_REGS SZ_512
10461+
10462+struct dss_reg {
10463+ u16 idx;
10464+};
10465+
10466+#define DSS_REG(idx) ((const struct dss_reg) { idx })
10467+
10468+#define DSS_REVISION DSS_REG(0x0000)
10469+#define DSS_SYSCONFIG DSS_REG(0x0010)
10470+#define DSS_SYSSTATUS DSS_REG(0x0014)
10471+#define DSS_IRQSTATUS DSS_REG(0x0018)
10472+#define DSS_CONTROL DSS_REG(0x0040)
10473+#define DSS_SDI_CONTROL DSS_REG(0x0044)
10474+#define DSS_PLL_CONTROL DSS_REG(0x0048)
10475+#define DSS_SDI_STATUS DSS_REG(0x005C)
10476+
10477+#define REG_GET(idx, start, end) \
10478+ FLD_GET(dss_read_reg(idx), start, end)
10479+
10480+#define REG_FLD_MOD(idx, val, start, end) \
10481+ dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
10482+
10483+static struct {
10484+ void __iomem *base;
10485+
10486+ u32 ctx[DSS_SZ_REGS / sizeof(u32)];
10487+} dss;
10488+
10489+static int _omap_dss_wait_reset(void);
10490+
10491+static inline void dss_write_reg(const struct dss_reg idx, u32 val)
10492+{
10493+ __raw_writel(val, dss.base + idx.idx);
10494+}
10495+
10496+static inline u32 dss_read_reg(const struct dss_reg idx)
10497+{
10498+ return __raw_readl(dss.base + idx.idx);
10499+}
10500+
10501+#define SR(reg) \
10502+ dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
10503+#define RR(reg) \
10504+ dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
10505+
10506+void dss_save_context(void)
10507+{
10508+ if (cpu_is_omap24xx())
10509+ return;
10510+
10511+ SR(SYSCONFIG);
10512+ SR(CONTROL);
10513+
10514+#ifdef CONFIG_OMAP2_DSS_SDI
10515+ SR(SDI_CONTROL);
10516+ SR(PLL_CONTROL);
10517+#endif
10518+}
10519+
10520+void dss_restore_context(void)
10521+{
10522+ if (_omap_dss_wait_reset())
10523+ DSSERR("DSS not coming out of reset after sleep\n");
10524+
10525+ RR(SYSCONFIG);
10526+ RR(CONTROL);
10527+
10528+#ifdef CONFIG_OMAP2_DSS_SDI
10529+ RR(SDI_CONTROL);
10530+ RR(PLL_CONTROL);
10531+#endif
10532+}
10533+
10534+#undef SR
10535+#undef RR
10536+
10537+void dss_sdi_init(u8 datapairs)
10538+{
10539+ u32 l;
10540+
10541+ BUG_ON(datapairs > 3 || datapairs < 1);
10542+
10543+ l = dss_read_reg(DSS_SDI_CONTROL);
10544+ l = FLD_MOD(l, 0xf, 19, 15); /* SDI_PDIV */
10545+ l = FLD_MOD(l, datapairs-1, 3, 2); /* SDI_PRSEL */
10546+ l = FLD_MOD(l, 2, 1, 0); /* SDI_BWSEL */
10547+ dss_write_reg(DSS_SDI_CONTROL, l);
10548+
10549+ l = dss_read_reg(DSS_PLL_CONTROL);
10550+ l = FLD_MOD(l, 0x7, 25, 22); /* SDI_PLL_FREQSEL */
10551+ l = FLD_MOD(l, 0xb, 16, 11); /* SDI_PLL_REGN */
10552+ l = FLD_MOD(l, 0xb4, 10, 1); /* SDI_PLL_REGM */
10553+ dss_write_reg(DSS_PLL_CONTROL, l);
10554+}
10555+
10556+void dss_sdi_enable(void)
10557+{
10558+ dispc_pck_free_enable(1);
10559+
10560+ /* Reset SDI PLL */
10561+ REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
10562+ udelay(1); /* wait 2x PCLK */
10563+
10564+ /* Lock SDI PLL */
10565+ REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
10566+
10567+ /* Waiting for PLL lock request to complete */
10568+ while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6))
10569+ ;
10570+
10571+ /* Clearing PLL_GO bit */
10572+ REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
10573+
10574+ /* Waiting for PLL to lock */
10575+ while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5)))
10576+ ;
10577+
10578+ dispc_lcd_enable_signal(1);
10579+
10580+ /* Waiting for SDI reset to complete */
10581+ while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2)))
10582+ ;
10583+}
10584+
10585+void dss_sdi_disable(void)
10586+{
10587+ dispc_lcd_enable_signal(0);
10588+
10589+ dispc_pck_free_enable(0);
10590+
10591+ /* Reset SDI PLL */
10592+ REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
10593+}
10594+
10595+void dss_dump_regs(struct seq_file *s)
10596+{
10597+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
10598+
10599+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
10600+
10601+ DUMPREG(DSS_REVISION);
10602+ DUMPREG(DSS_SYSCONFIG);
10603+ DUMPREG(DSS_SYSSTATUS);
10604+ DUMPREG(DSS_IRQSTATUS);
10605+ DUMPREG(DSS_CONTROL);
10606+ DUMPREG(DSS_SDI_CONTROL);
10607+ DUMPREG(DSS_PLL_CONTROL);
10608+ DUMPREG(DSS_SDI_STATUS);
10609+
10610+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
10611+#undef DUMPREG
10612+}
10613+
10614+void dss_select_clk_source(bool dsi, bool dispc)
10615+{
10616+ u32 r;
10617+ r = dss_read_reg(DSS_CONTROL);
10618+ r = FLD_MOD(r, dsi, 1, 1); /* DSI_CLK_SWITCH */
10619+ r = FLD_MOD(r, dispc, 0, 0); /* DISPC_CLK_SWITCH */
10620+ dss_write_reg(DSS_CONTROL, r);
10621+}
10622+
10623+int dss_get_dsi_clk_source(void)
10624+{
10625+ return FLD_GET(dss_read_reg(DSS_CONTROL), 1, 1);
10626+}
10627+
10628+int dss_get_dispc_clk_source(void)
10629+{
10630+ return FLD_GET(dss_read_reg(DSS_CONTROL), 0, 0);
10631+}
10632+
10633+static irqreturn_t dss_irq_handler_omap2(int irq, void *arg)
10634+{
10635+ dispc_irq_handler();
10636+
10637+ return IRQ_HANDLED;
10638+}
10639+
10640+static irqreturn_t dss_irq_handler_omap3(int irq, void *arg)
10641+{
10642+ u32 irqstatus;
10643+
10644+ irqstatus = dss_read_reg(DSS_IRQSTATUS);
10645+
10646+ if (irqstatus & (1<<0)) /* DISPC_IRQ */
10647+ dispc_irq_handler();
10648+#ifdef CONFIG_OMAP2_DSS_DSI
10649+ if (irqstatus & (1<<1)) /* DSI_IRQ */
10650+ dsi_irq_handler();
10651+#endif
10652+
10653+ return IRQ_HANDLED;
10654+}
10655+
10656+static int _omap_dss_wait_reset(void)
10657+{
10658+ unsigned timeout = 1000;
10659+
10660+ while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
10661+ udelay(1);
10662+ if (!--timeout) {
10663+ DSSERR("soft reset failed\n");
10664+ return -ENODEV;
10665+ }
10666+ }
10667+
10668+ return 0;
10669+}
10670+
10671+static int _omap_dss_reset(void)
10672+{
10673+ /* Soft reset */
10674+ REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
10675+ return _omap_dss_wait_reset();
10676+}
10677+
10678+void dss_set_venc_output(enum omap_dss_venc_type type)
10679+{
10680+ int l = 0;
10681+
10682+ if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
10683+ l = 0;
10684+ else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
10685+ l = 1;
10686+ else
10687+ BUG();
10688+
10689+ /* venc out selection. 0 = comp, 1 = svideo */
10690+ REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
10691+}
10692+
10693+void dss_set_dac_pwrdn_bgz(bool enable)
10694+{
10695+ REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
10696+}
10697+
10698+int dss_init(bool skip_init)
10699+{
10700+ int r;
10701+ u32 rev;
10702+
10703+ dss.base = ioremap(DSS_BASE, DSS_SZ_REGS);
10704+ if (!dss.base) {
10705+ DSSERR("can't ioremap DSS\n");
10706+ r = -ENOMEM;
10707+ goto fail0;
10708+ }
10709+
10710+ if (!skip_init) {
10711+ /* We need to wait here a bit, otherwise we sometimes start to
10712+ * get synclost errors, and after that only power cycle will
10713+ * restore DSS functionality. I have no idea why this happens.
10714+ * And we have to wait _before_ resetting the DSS, but after
10715+ * enabling clocks.
10716+ */
10717+ msleep(50);
10718+
10719+ _omap_dss_reset();
10720+
10721+ }
10722+ else
10723+ printk("DSS SKIP RESET\n");
10724+
10725+ /* autoidle */
10726+ REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
10727+
10728+ /* Select DPLL */
10729+ REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
10730+
10731+#ifdef CONFIG_OMAP2_DSS_VENC
10732+ REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
10733+ REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
10734+ REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
10735+#endif
10736+
10737+ r = request_irq(INT_24XX_DSS_IRQ,
10738+ cpu_is_omap24xx()
10739+ ? dss_irq_handler_omap2
10740+ : dss_irq_handler_omap3,
10741+ 0, "OMAP DSS", NULL);
10742+
10743+ if (r < 0) {
10744+ DSSERR("omap2 dss: request_irq failed\n");
10745+ goto fail1;
10746+ }
10747+
10748+ dss_save_context();
10749+
10750+ rev = dss_read_reg(DSS_REVISION);
10751+ printk(KERN_INFO "OMAP DSS rev %d.%d\n",
10752+ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
10753+
10754+ return 0;
10755+
10756+fail1:
10757+ iounmap(dss.base);
10758+fail0:
10759+ return r;
10760+}
10761+
10762+void dss_exit(void)
10763+{
10764+ free_irq(INT_24XX_DSS_IRQ, NULL);
10765+
10766+ iounmap(dss.base);
10767+}
10768+
10769diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
10770new file mode 100644
10771index 0000000..bac5ece
10772--- /dev/null
10773+++ b/drivers/video/omap2/dss/dss.h
10774@@ -0,0 +1,331 @@
10775+/*
10776+ * linux/drivers/video/omap2/dss/dss.h
10777+ *
10778+ * Copyright (C) 2009 Nokia Corporation
10779+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
10780+ *
10781+ * Some code and ideas taken from drivers/video/omap/ driver
10782+ * by Imre Deak.
10783+ *
10784+ * This program is free software; you can redistribute it and/or modify it
10785+ * under the terms of the GNU General Public License version 2 as published by
10786+ * the Free Software Foundation.
10787+ *
10788+ * This program is distributed in the hope that it will be useful, but WITHOUT
10789+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10790+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
10791+ * more details.
10792+ *
10793+ * You should have received a copy of the GNU General Public License along with
10794+ * this program. If not, see <http://www.gnu.org/licenses/>.
10795+ */
10796+
10797+#ifndef __OMAP2_DSS_H
10798+#define __OMAP2_DSS_H
10799+
10800+#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT
10801+#define DEBUG
10802+#endif
10803+
10804+#ifdef DEBUG
10805+extern unsigned int dss_debug;
10806+#ifdef DSS_SUBSYS_NAME
10807+#define DSSDBG(format, ...) \
10808+ if (dss_debug) \
10809+ printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \
10810+ ## __VA_ARGS__)
10811+#else
10812+#define DSSDBG(format, ...) \
10813+ if (dss_debug) \
10814+ printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__)
10815+#endif
10816+
10817+#ifdef DSS_SUBSYS_NAME
10818+#define DSSDBGF(format, ...) \
10819+ if (dss_debug) \
10820+ printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \
10821+ ": %s(" format ")\n", \
10822+ __func__, \
10823+ ## __VA_ARGS__)
10824+#else
10825+#define DSSDBGF(format, ...) \
10826+ if (dss_debug) \
10827+ printk(KERN_DEBUG "omapdss: " \
10828+ ": %s(" format ")\n", \
10829+ __func__, \
10830+ ## __VA_ARGS__)
10831+#endif
10832+
10833+#else /* DEBUG */
10834+#define DSSDBG(format, ...)
10835+#define DSSDBGF(format, ...)
10836+#endif
10837+
10838+
10839+#ifdef DSS_SUBSYS_NAME
10840+#define DSSERR(format, ...) \
10841+ printk(KERN_ERR "omapdss " DSS_SUBSYS_NAME " error: " format, \
10842+ ## __VA_ARGS__)
10843+#else
10844+#define DSSERR(format, ...) \
10845+ printk(KERN_ERR "omapdss error: " format, ## __VA_ARGS__)
10846+#endif
10847+
10848+#ifdef DSS_SUBSYS_NAME
10849+#define DSSINFO(format, ...) \
10850+ printk(KERN_INFO "omapdss " DSS_SUBSYS_NAME ": " format, \
10851+ ## __VA_ARGS__)
10852+#else
10853+#define DSSINFO(format, ...) \
10854+ printk(KERN_INFO "omapdss: " format, ## __VA_ARGS__)
10855+#endif
10856+
10857+#ifdef DSS_SUBSYS_NAME
10858+#define DSSWARN(format, ...) \
10859+ printk(KERN_WARNING "omapdss " DSS_SUBSYS_NAME ": " format, \
10860+ ## __VA_ARGS__)
10861+#else
10862+#define DSSWARN(format, ...) \
10863+ printk(KERN_WARNING "omapdss: " format, ## __VA_ARGS__)
10864+#endif
10865+
10866+/* OMAP TRM gives bitfields as start:end, where start is the higher bit
10867+ number. For example 7:0 */
10868+#define FLD_MASK(start, end) (((1 << (start - end + 1)) - 1) << (end))
10869+#define FLD_VAL(val, start, end) (((val) << end) & FLD_MASK(start, end))
10870+#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
10871+#define FLD_MOD(orig, val, start, end) \
10872+ (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
10873+
10874+#define DISPC_MAX_FCK 173000000
10875+
10876+enum omap_burst_size {
10877+ OMAP_DSS_BURST_4x32 = 0,
10878+ OMAP_DSS_BURST_8x32 = 1,
10879+ OMAP_DSS_BURST_16x32 = 2,
10880+};
10881+
10882+enum omap_parallel_interface_mode {
10883+ OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */
10884+ OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */
10885+ OMAP_DSS_PARALLELMODE_DSI,
10886+};
10887+
10888+enum dss_clock {
10889+ DSS_CLK_ICK = 1 << 0,
10890+ DSS_CLK_FCK1 = 1 << 1,
10891+ DSS_CLK_FCK2 = 1 << 2,
10892+ DSS_CLK_54M = 1 << 3,
10893+ DSS_CLK_96M = 1 << 4,
10894+};
10895+
10896+struct dispc_clock_info {
10897+ /* rates that we get with dividers below */
10898+ unsigned long fck;
10899+ unsigned long lck;
10900+ unsigned long pck;
10901+
10902+ /* dividers */
10903+ u16 fck_div;
10904+ u16 lck_div;
10905+ u16 pck_div;
10906+};
10907+
10908+struct dsi_clock_info {
10909+ /* rates that we get with dividers below */
10910+ unsigned long fint;
10911+ unsigned long dsiphy;
10912+ unsigned long clkin;
10913+ unsigned long dsi1_pll_fclk;
10914+ unsigned long dsi2_pll_fclk;
10915+ unsigned long lck;
10916+ unsigned long pck;
10917+
10918+ /* dividers */
10919+ u16 regn;
10920+ u16 regm;
10921+ u16 regm3;
10922+ u16 regm4;
10923+
10924+ u16 lck_div;
10925+ u16 pck_div;
10926+
10927+ u8 highfreq;
10928+ bool use_dss2_fck;
10929+};
10930+
10931+struct seq_file;
10932+struct platform_device;
10933+
10934+/* core */
10935+void dss_clk_enable(enum dss_clock clks);
10936+void dss_clk_disable(enum dss_clock clks);
10937+unsigned long dss_clk_get_rate(enum dss_clock clk);
10938+int dss_need_ctx_restore(void);
10939+void dss_dump_clocks(struct seq_file *s);
10940+
10941+int dss_dsi_power_up(void);
10942+void dss_dsi_power_down(void);
10943+
10944+/* display */
10945+void dss_init_displays(struct platform_device *pdev);
10946+void dss_uninit_displays(struct platform_device *pdev);
10947+int dss_suspend_all_displays(void);
10948+int dss_resume_all_displays(void);
10949+struct omap_display *dss_get_display(int no);
10950+
10951+/* manager */
10952+int dss_init_overlay_managers(struct platform_device *pdev);
10953+void dss_uninit_overlay_managers(struct platform_device *pdev);
10954+
10955+/* overlay */
10956+void dss_init_overlays(struct platform_device *pdev, const char *def_disp_name);
10957+void dss_uninit_overlays(struct platform_device *pdev);
10958+int dss_check_overlay(struct omap_overlay *ovl, struct omap_display *display);
10959+void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
10960+
10961+/* DSS */
10962+int dss_init(bool skip_init);
10963+void dss_exit(void);
10964+
10965+void dss_save_context(void);
10966+void dss_restore_context(void);
10967+
10968+void dss_dump_regs(struct seq_file *s);
10969+
10970+void dss_sdi_init(u8 datapairs);
10971+void dss_sdi_enable(void);
10972+void dss_sdi_disable(void);
10973+
10974+void dss_select_clk_source(bool dsi, bool dispc);
10975+int dss_get_dsi_clk_source(void);
10976+int dss_get_dispc_clk_source(void);
10977+void dss_set_venc_output(enum omap_dss_venc_type type);
10978+void dss_set_dac_pwrdn_bgz(bool enable);
10979+
10980+/* SDI */
10981+int sdi_init(bool skip_init);
10982+void sdi_exit(void);
10983+void sdi_init_display(struct omap_display *display);
10984+
10985+/* DSI */
10986+int dsi_init(void);
10987+void dsi_exit(void);
10988+
10989+void dsi_dump_clocks(struct seq_file *s);
10990+void dsi_dump_regs(struct seq_file *s);
10991+
10992+void dsi_save_context(void);
10993+void dsi_restore_context(void);
10994+
10995+void dsi_init_display(struct omap_display *display);
10996+void dsi_irq_handler(void);
10997+unsigned long dsi_get_dsi1_pll_rate(void);
10998+unsigned long dsi_get_dsi2_pll_rate(void);
10999+int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck,
11000+ struct dsi_clock_info *cinfo);
11001+int dsi_pll_program(struct dsi_clock_info *cinfo);
11002+int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv);
11003+void dsi_pll_uninit(void);
11004+
11005+/* DPI */
11006+int dpi_init(void);
11007+void dpi_exit(void);
11008+void dpi_init_display(struct omap_display *display);
11009+
11010+/* DISPC */
11011+int dispc_init(void);
11012+void dispc_exit(void);
11013+void dispc_dump_clocks(struct seq_file *s);
11014+void dispc_dump_regs(struct seq_file *s);
11015+void dispc_irq_handler(void);
11016+void dispc_fake_vsync_irq(void);
11017+
11018+void dispc_save_context(void);
11019+void dispc_restore_context(void);
11020+
11021+void dispc_lcd_enable_signal_polarity(bool act_high);
11022+void dispc_lcd_enable_signal(bool enable);
11023+void dispc_pck_free_enable(bool enable);
11024+void dispc_enable_fifohandcheck(bool enable);
11025+
11026+void dispc_set_lcd_size(u16 width, u16 height);
11027+void dispc_set_digit_size(u16 width, u16 height);
11028+u32 dispc_get_plane_fifo_size(enum omap_plane plane);
11029+void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high);
11030+void dispc_enable_fifomerge(bool enable);
11031+void dispc_set_burst_size(enum omap_plane plane,
11032+ enum omap_burst_size burst_size);
11033+
11034+void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
11035+void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
11036+void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y);
11037+void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
11038+
11039+int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
11040+ u32 paddr, u16 screen_width,
11041+ u16 pos_x, u16 pos_y,
11042+ u16 width, u16 height,
11043+ u16 out_width, u16 out_height,
11044+ enum omap_color_mode color_mode,
11045+ bool ilace,
11046+ u8 rotation, bool mirror);
11047+
11048+void dispc_go(enum omap_channel channel);
11049+void dispc_enable_lcd_out(bool enable);
11050+void dispc_enable_digit_out(bool enable);
11051+int dispc_enable_plane(enum omap_plane plane, bool enable);
11052+
11053+void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode);
11054+void dispc_set_tft_data_lines(u8 data_lines);
11055+void dispc_set_lcd_display_type(enum omap_lcd_display_type type);
11056+void dispc_set_loadmode(enum omap_dss_load_mode mode);
11057+
11058+void dispc_set_default_color(enum omap_channel channel, u32 color);
11059+u32 dispc_get_default_color(enum omap_channel channel);
11060+void dispc_set_trans_key(enum omap_channel ch,
11061+ enum omap_dss_color_key_type type,
11062+ u32 trans_key);
11063+void dispc_get_trans_key(enum omap_channel ch,
11064+ enum omap_dss_color_key_type *type,
11065+ u32 *trans_key);
11066+void dispc_enable_trans_key(enum omap_channel ch, bool enable);
11067+bool dispc_trans_key_enabled(enum omap_channel ch);
11068+
11069+void dispc_set_lcd_timings(struct omap_video_timings *timings);
11070+unsigned long dispc_fclk_rate(void);
11071+unsigned long dispc_pclk_rate(void);
11072+void dispc_set_pol_freq(struct omap_panel *panel);
11073+void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
11074+ u16 *lck_div, u16 *pck_div);
11075+int dispc_calc_clock_div(bool is_tft, unsigned long req_pck,
11076+ struct dispc_clock_info *cinfo);
11077+int dispc_set_clock_div(struct dispc_clock_info *cinfo);
11078+int dispc_get_clock_div(struct dispc_clock_info *cinfo);
11079+void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div);
11080+
11081+void dispc_setup_partial_planes(struct omap_display *display,
11082+ u16 *x, u16 *y, u16 *w, u16 *h);
11083+void dispc_draw_partial_planes(struct omap_display *display);
11084+
11085+
11086+/* VENC */
11087+int venc_init(void);
11088+void venc_exit(void);
11089+void venc_dump_regs(struct seq_file *s);
11090+void venc_init_display(struct omap_display *display);
11091+
11092+/* RFBI */
11093+int rfbi_init(void);
11094+void rfbi_exit(void);
11095+void rfbi_dump_regs(struct seq_file *s);
11096+
11097+int rfbi_configure(int rfbi_module, int bpp, int lines);
11098+void rfbi_enable_rfbi(bool enable);
11099+void rfbi_transfer_area(u16 width, u16 height,
11100+ void (callback)(void *data), void *data);
11101+void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
11102+unsigned long rfbi_get_max_tx_rate(void);
11103+void rfbi_init_display(struct omap_display *display);
11104+
11105+#endif
11106diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
11107new file mode 100644
11108index 0000000..b0fee80
11109--- /dev/null
11110+++ b/drivers/video/omap2/dss/manager.c
11111@@ -0,0 +1,576 @@
11112+/*
11113+ * linux/drivers/video/omap2/dss/manager.c
11114+ *
11115+ * Copyright (C) 2009 Nokia Corporation
11116+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
11117+ *
11118+ * Some code and ideas taken from drivers/video/omap/ driver
11119+ * by Imre Deak.
11120+ *
11121+ * This program is free software; you can redistribute it and/or modify it
11122+ * under the terms of the GNU General Public License version 2 as published by
11123+ * the Free Software Foundation.
11124+ *
11125+ * This program is distributed in the hope that it will be useful, but WITHOUT
11126+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11127+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11128+ * more details.
11129+ *
11130+ * You should have received a copy of the GNU General Public License along with
11131+ * this program. If not, see <http://www.gnu.org/licenses/>.
11132+ */
11133+
11134+#define DSS_SUBSYS_NAME "MANAGER"
11135+
11136+#include <linux/kernel.h>
11137+#include <linux/module.h>
11138+#include <linux/platform_device.h>
11139+
11140+#include <mach/display.h>
11141+
11142+#include "dss.h"
11143+
11144+static int num_managers;
11145+static struct list_head manager_list;
11146+
11147+static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
11148+{
11149+ return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
11150+}
11151+
11152+static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
11153+{
11154+ return snprintf(buf, PAGE_SIZE, "%s\n",
11155+ mgr->display ? mgr->display->name : "<none>");
11156+}
11157+
11158+static ssize_t manager_display_store(struct omap_overlay_manager *mgr, const char *buf, size_t size)
11159+{
11160+ int r, i;
11161+ int len = size;
11162+ struct omap_display *display = NULL;
11163+
11164+ if (buf[size-1] == '\n')
11165+ --len;
11166+
11167+ if (len > 0) {
11168+ for (i = 0; i < omap_dss_get_num_displays(); ++i) {
11169+ display = dss_get_display(i);
11170+
11171+ if (strncmp(buf, display->name, len) == 0)
11172+ break;
11173+
11174+ display = NULL;
11175+ }
11176+ }
11177+
11178+ if (len > 0 && display == NULL)
11179+ return -EINVAL;
11180+
11181+ if (display)
11182+ DSSDBG("display %s found\n", display->name);
11183+
11184+ if (mgr->display) {
11185+ r = mgr->unset_display(mgr);
11186+ if (r) {
11187+ DSSERR("failed to unset display\n");
11188+ return r;
11189+ }
11190+ }
11191+
11192+ if (display) {
11193+ r = mgr->set_display(mgr, display);
11194+ if (r) {
11195+ DSSERR("failed to set manager\n");
11196+ return r;
11197+ }
11198+
11199+ r = mgr->apply(mgr);
11200+ if (r) {
11201+ DSSERR("failed to apply dispc config\n");
11202+ return r;
11203+ }
11204+ }
11205+
11206+ return size;
11207+}
11208+
11209+static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
11210+ char *buf)
11211+{
11212+ u32 default_color;
11213+
11214+ default_color = dispc_get_default_color(mgr->id);
11215+ return snprintf(buf, PAGE_SIZE, "%d", default_color);
11216+}
11217+
11218+static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
11219+ const char *buf, size_t size)
11220+{
11221+ u32 default_color;
11222+
11223+ if (sscanf(buf, "%d", &default_color) != 1)
11224+ return -EINVAL;
11225+ dispc_set_default_color(mgr->id, default_color);
11226+
11227+ return size;
11228+}
11229+
11230+static const char *color_key_type_str[] = {
11231+ "gfx-destination",
11232+ "video-source",
11233+};
11234+
11235+static ssize_t manager_color_key_type_show(struct omap_overlay_manager *mgr,
11236+ char *buf)
11237+{
11238+ enum omap_dss_color_key_type key_type;
11239+
11240+ dispc_get_trans_key(mgr->id, &key_type, NULL);
11241+ BUG_ON(key_type >= ARRAY_SIZE(color_key_type_str));
11242+
11243+ return snprintf(buf, PAGE_SIZE, "%s\n", color_key_type_str[key_type]);
11244+}
11245+
11246+static ssize_t manager_color_key_type_store(struct omap_overlay_manager *mgr,
11247+ const char *buf, size_t size)
11248+{
11249+ enum omap_dss_color_key_type key_type;
11250+ u32 key_value;
11251+
11252+ for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
11253+ key_type < ARRAY_SIZE(color_key_type_str); key_type++) {
11254+ if (sysfs_streq(buf, color_key_type_str[key_type]))
11255+ break;
11256+ }
11257+ if (key_type == ARRAY_SIZE(color_key_type_str))
11258+ return -EINVAL;
11259+ dispc_get_trans_key(mgr->id, NULL, &key_value);
11260+ dispc_set_trans_key(mgr->id, key_type, key_value);
11261+
11262+ return size;
11263+}
11264+
11265+static ssize_t manager_color_key_value_show(struct omap_overlay_manager *mgr,
11266+ char *buf)
11267+{
11268+ u32 key_value;
11269+
11270+ dispc_get_trans_key(mgr->id, NULL, &key_value);
11271+
11272+ return snprintf(buf, PAGE_SIZE, "%d\n", key_value);
11273+}
11274+
11275+static ssize_t manager_color_key_value_store(struct omap_overlay_manager *mgr,
11276+ const char *buf, size_t size)
11277+{
11278+ enum omap_dss_color_key_type key_type;
11279+ u32 key_value;
11280+
11281+ if (sscanf(buf, "%d", &key_value) != 1)
11282+ return -EINVAL;
11283+ dispc_get_trans_key(mgr->id, &key_type, NULL);
11284+ dispc_set_trans_key(mgr->id, key_type, key_value);
11285+
11286+ return size;
11287+}
11288+
11289+static ssize_t manager_color_key_enabled_show(struct omap_overlay_manager *mgr,
11290+ char *buf)
11291+{
11292+ return snprintf(buf, PAGE_SIZE, "%d\n",
11293+ dispc_trans_key_enabled(mgr->id));
11294+}
11295+
11296+static ssize_t manager_color_key_enabled_store(struct omap_overlay_manager *mgr,
11297+ const char *buf, size_t size)
11298+{
11299+ int enable;
11300+
11301+ if (sscanf(buf, "%d", &enable) != 1)
11302+ return -EINVAL;
11303+
11304+ dispc_enable_trans_key(mgr->id, enable);
11305+
11306+ return size;
11307+}
11308+
11309+
11310+struct manager_attribute {
11311+ struct attribute attr;
11312+ ssize_t (*show)(struct omap_overlay_manager *, char *);
11313+ ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
11314+};
11315+
11316+#define MANAGER_ATTR(_name, _mode, _show, _store) \
11317+ struct manager_attribute manager_attr_##_name = \
11318+ __ATTR(_name, _mode, _show, _store)
11319+
11320+static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
11321+static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
11322+ manager_display_show, manager_display_store);
11323+static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
11324+ manager_default_color_show, manager_default_color_store);
11325+static MANAGER_ATTR(color_key_type, S_IRUGO|S_IWUSR,
11326+ manager_color_key_type_show, manager_color_key_type_store);
11327+static MANAGER_ATTR(color_key_value, S_IRUGO|S_IWUSR,
11328+ manager_color_key_value_show, manager_color_key_value_store);
11329+static MANAGER_ATTR(color_key_enabled, S_IRUGO|S_IWUSR,
11330+ manager_color_key_enabled_show, manager_color_key_enabled_store);
11331+
11332+static struct attribute *manager_sysfs_attrs[] = {
11333+ &manager_attr_name.attr,
11334+ &manager_attr_display.attr,
11335+ &manager_attr_default_color.attr,
11336+ &manager_attr_color_key_type.attr,
11337+ &manager_attr_color_key_value.attr,
11338+ &manager_attr_color_key_enabled.attr,
11339+ NULL
11340+};
11341+
11342+static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
11343+{
11344+ struct omap_overlay_manager *manager;
11345+ struct manager_attribute *manager_attr;
11346+
11347+ manager = container_of(kobj, struct omap_overlay_manager, kobj);
11348+ manager_attr = container_of(attr, struct manager_attribute, attr);
11349+
11350+ if (!manager_attr->show)
11351+ return -ENOENT;
11352+
11353+ return manager_attr->show(manager, buf);
11354+}
11355+
11356+static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
11357+ const char *buf, size_t size)
11358+{
11359+ struct omap_overlay_manager *manager;
11360+ struct manager_attribute *manager_attr;
11361+
11362+ manager = container_of(kobj, struct omap_overlay_manager, kobj);
11363+ manager_attr = container_of(attr, struct manager_attribute, attr);
11364+
11365+ if (!manager_attr->store)
11366+ return -ENOENT;
11367+
11368+ return manager_attr->store(manager, buf, size);
11369+}
11370+
11371+static struct sysfs_ops manager_sysfs_ops = {
11372+ .show = manager_attr_show,
11373+ .store = manager_attr_store,
11374+};
11375+
11376+static struct kobj_type manager_ktype = {
11377+ .sysfs_ops = &manager_sysfs_ops,
11378+ .default_attrs = manager_sysfs_attrs,
11379+};
11380+
11381+static int omap_dss_set_display(struct omap_overlay_manager *mgr,
11382+ struct omap_display *display)
11383+{
11384+ int i;
11385+ int r;
11386+
11387+ if (display->manager) {
11388+ DSSERR("display '%s' already has a manager '%s'\n",
11389+ display->name, display->manager->name);
11390+ return -EINVAL;
11391+ }
11392+
11393+ if ((mgr->supported_displays & display->type) == 0) {
11394+ DSSERR("display '%s' does not support manager '%s'\n",
11395+ display->name, mgr->name);
11396+ return -EINVAL;
11397+ }
11398+
11399+ for (i = 0; i < mgr->num_overlays; i++) {
11400+ struct omap_overlay *ovl = mgr->overlays[i];
11401+
11402+ if (ovl->manager != mgr || !ovl->info.enabled)
11403+ continue;
11404+
11405+ r = dss_check_overlay(ovl, display);
11406+ if (r)
11407+ return r;
11408+ }
11409+
11410+ display->manager = mgr;
11411+ mgr->display = display;
11412+
11413+ return 0;
11414+}
11415+
11416+static int omap_dss_unset_display(struct omap_overlay_manager *mgr)
11417+{
11418+ if (!mgr->display) {
11419+ DSSERR("failed to unset display, display not set.\n");
11420+ return -EINVAL;
11421+ }
11422+
11423+ mgr->display->manager = NULL;
11424+ mgr->display = NULL;
11425+
11426+ return 0;
11427+}
11428+
11429+
11430+static int overlay_enabled(struct omap_overlay *ovl)
11431+{
11432+ return ovl->info.enabled && ovl->manager && ovl->manager->display;
11433+}
11434+
11435+/* We apply settings to both managers here so that we can use optimizations
11436+ * like fifomerge. Shadow registers can be changed first and the non-shadowed
11437+ * should be changed last, at the same time with GO */
11438+static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
11439+{
11440+ int i;
11441+ int ret = 0;
11442+ enum omap_dss_update_mode mode;
11443+ struct omap_display *display;
11444+ struct omap_overlay *ovl;
11445+ bool ilace = 0;
11446+ int outw, outh;
11447+ int r;
11448+ int num_planes_enabled = 0;
11449+
11450+ DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
11451+
11452+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
11453+
11454+ /* Configure normal overlay parameters and disable unused overlays */
11455+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
11456+ ovl = omap_dss_get_overlay(i);
11457+
11458+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
11459+ continue;
11460+
11461+ if (!overlay_enabled(ovl)) {
11462+ dispc_enable_plane(ovl->id, 0);
11463+ continue;
11464+ }
11465+
11466+ display = ovl->manager->display;
11467+
11468+ if (dss_check_overlay(ovl, display)) {
11469+ dispc_enable_plane(ovl->id, 0);
11470+ continue;
11471+ }
11472+
11473+ ++num_planes_enabled;
11474+
11475+ /* On a manual update display, in manual update mode, update()
11476+ * handles configuring planes */
11477+ mode = OMAP_DSS_UPDATE_AUTO;
11478+ if (display->get_update_mode)
11479+ mode = display->get_update_mode(mgr->display);
11480+
11481+ if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
11482+ mode != OMAP_DSS_UPDATE_AUTO)
11483+ continue;
11484+
11485+ if (display->type == OMAP_DISPLAY_TYPE_VENC)
11486+ ilace = 1;
11487+
11488+ if (ovl->info.out_width == 0)
11489+ outw = ovl->info.width;
11490+ else
11491+ outw = ovl->info.out_width;
11492+
11493+ if (ovl->info.out_height == 0)
11494+ outh = ovl->info.height;
11495+ else
11496+ outh = ovl->info.out_height;
11497+
11498+ r = dispc_setup_plane(ovl->id, ovl->manager->id,
11499+ ovl->info.paddr,
11500+ ovl->info.screen_width,
11501+ ovl->info.pos_x,
11502+ ovl->info.pos_y,
11503+ ovl->info.width,
11504+ ovl->info.height,
11505+ outw,
11506+ outh,
11507+ ovl->info.color_mode,
11508+ ilace,
11509+ ovl->info.rotation,
11510+ ovl->info.mirror);
11511+
11512+ if (r) {
11513+ DSSERR("dispc_setup_plane failed for ovl %d\n",
11514+ ovl->id);
11515+ dispc_enable_plane(ovl->id, 0);
11516+ continue;
11517+ }
11518+
11519+ dispc_enable_plane(ovl->id, 1);
11520+ }
11521+
11522+ /* Enable fifo merge if possible */
11523+ dispc_enable_fifomerge(num_planes_enabled == 1);
11524+
11525+ /* Go through overlays again. This time we configure fifos. We have to
11526+ * do this after enabling/disabling fifomerge so that we have correct
11527+ * knowledge of fifo sizes */
11528+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
11529+ ovl = omap_dss_get_overlay(i);
11530+
11531+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
11532+ continue;
11533+
11534+ if (!overlay_enabled(ovl)) {
11535+ continue;
11536+ }
11537+
11538+ ovl->manager->display->configure_overlay(ovl);
11539+ }
11540+
11541+ /* Issue GO for managers */
11542+ list_for_each_entry(mgr, &manager_list, list) {
11543+ if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
11544+ continue;
11545+
11546+ display = mgr->display;
11547+
11548+ if (!display)
11549+ continue;
11550+
11551+ /* We don't need GO with manual update display. LCD iface will
11552+ * always be turned off after frame, and new settings will
11553+ * be taken in to use at next update */
11554+ if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
11555+ continue;
11556+
11557+ dispc_go(mgr->id);
11558+ }
11559+
11560+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
11561+
11562+ return ret;
11563+}
11564+
11565+static void omap_dss_mgr_set_def_color(struct omap_overlay_manager *mgr,
11566+ u32 color)
11567+{
11568+ dispc_set_default_color(mgr->id, color);
11569+}
11570+
11571+static void omap_dss_mgr_set_trans_key(struct omap_overlay_manager *mgr,
11572+ enum omap_dss_color_key_type type,
11573+ u32 trans_key)
11574+{
11575+ dispc_set_trans_key(mgr->id, type, trans_key);
11576+}
11577+
11578+static void omap_dss_mgr_enable_trans_key(struct omap_overlay_manager *mgr,
11579+ bool enable)
11580+{
11581+ dispc_enable_trans_key(mgr->id, enable);
11582+}
11583+
11584+static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
11585+{
11586+ ++num_managers;
11587+ list_add_tail(&manager->list, &manager_list);
11588+}
11589+
11590+int dss_init_overlay_managers(struct platform_device *pdev)
11591+{
11592+ int i, r;
11593+
11594+ INIT_LIST_HEAD(&manager_list);
11595+
11596+ num_managers = 0;
11597+
11598+ for (i = 0; i < 2; ++i) {
11599+ struct omap_overlay_manager *mgr;
11600+ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
11601+
11602+ BUG_ON(mgr == NULL);
11603+
11604+ switch (i) {
11605+ case 0:
11606+ mgr->name = "lcd";
11607+ mgr->id = OMAP_DSS_CHANNEL_LCD;
11608+ mgr->supported_displays =
11609+ OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
11610+ OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI;
11611+ break;
11612+ case 1:
11613+ mgr->name = "tv";
11614+ mgr->id = OMAP_DSS_CHANNEL_DIGIT;
11615+ mgr->supported_displays = OMAP_DISPLAY_TYPE_VENC;
11616+ break;
11617+ }
11618+
11619+ mgr->set_display = &omap_dss_set_display,
11620+ mgr->unset_display = &omap_dss_unset_display,
11621+ mgr->apply = &omap_dss_mgr_apply,
11622+ mgr->set_default_color = &omap_dss_mgr_set_def_color,
11623+ mgr->set_trans_key = &omap_dss_mgr_set_trans_key,
11624+ mgr->enable_trans_key = &omap_dss_mgr_enable_trans_key,
11625+ mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC,
11626+
11627+ dss_overlay_setup_dispc_manager(mgr);
11628+
11629+ omap_dss_add_overlay_manager(mgr);
11630+
11631+ r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
11632+ &pdev->dev.kobj, "manager%d", i);
11633+
11634+ if (r) {
11635+ DSSERR("failed to create sysfs file\n");
11636+ continue;
11637+ }
11638+ }
11639+
11640+ return 0;
11641+}
11642+
11643+void dss_uninit_overlay_managers(struct platform_device *pdev)
11644+{
11645+ struct omap_overlay_manager *mgr;
11646+
11647+ while (!list_empty(&manager_list)) {
11648+ mgr = list_first_entry(&manager_list,
11649+ struct omap_overlay_manager, list);
11650+ list_del(&mgr->list);
11651+ kobject_del(&mgr->kobj);
11652+ kobject_put(&mgr->kobj);
11653+ kfree(mgr);
11654+ }
11655+
11656+ num_managers = 0;
11657+}
11658+
11659+int omap_dss_get_num_overlay_managers(void)
11660+{
11661+ return num_managers;
11662+}
11663+EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
11664+
11665+struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
11666+{
11667+ int i = 0;
11668+ struct omap_overlay_manager *mgr;
11669+
11670+ list_for_each_entry(mgr, &manager_list, list) {
11671+ if (i++ == num)
11672+ return mgr;
11673+ }
11674+
11675+ return NULL;
11676+}
11677+EXPORT_SYMBOL(omap_dss_get_overlay_manager);
11678+
11679+#ifdef L4_EXAMPLE
11680+static int ovl_mgr_apply_l4(struct omap_overlay_manager *mgr)
11681+{
11682+ DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);
11683+
11684+ return 0;
11685+}
11686+#endif
11687+
11688diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
11689new file mode 100644
11690index 0000000..968edbe
11691--- /dev/null
11692+++ b/drivers/video/omap2/dss/overlay.c
11693@@ -0,0 +1,587 @@
11694+/*
11695+ * linux/drivers/video/omap2/dss/overlay.c
11696+ *
11697+ * Copyright (C) 2009 Nokia Corporation
11698+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
11699+ *
11700+ * Some code and ideas taken from drivers/video/omap/ driver
11701+ * by Imre Deak.
11702+ *
11703+ * This program is free software; you can redistribute it and/or modify it
11704+ * under the terms of the GNU General Public License version 2 as published by
11705+ * the Free Software Foundation.
11706+ *
11707+ * This program is distributed in the hope that it will be useful, but WITHOUT
11708+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11709+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11710+ * more details.
11711+ *
11712+ * You should have received a copy of the GNU General Public License along with
11713+ * this program. If not, see <http://www.gnu.org/licenses/>.
11714+ */
11715+
11716+#define DSS_SUBSYS_NAME "OVERLAY"
11717+
11718+#include <linux/kernel.h>
11719+#include <linux/module.h>
11720+#include <linux/err.h>
11721+#include <linux/sysfs.h>
11722+#include <linux/kobject.h>
11723+#include <linux/platform_device.h>
11724+
11725+#include <mach/display.h>
11726+
11727+#include "dss.h"
11728+
11729+static int num_overlays;
11730+static struct list_head overlay_list;
11731+
11732+static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
11733+{
11734+ return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
11735+}
11736+
11737+static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
11738+{
11739+ return snprintf(buf, PAGE_SIZE, "%s\n",
11740+ ovl->manager ? ovl->manager->name : "<none>");
11741+}
11742+
11743+static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf, size_t size)
11744+{
11745+ int i, r;
11746+ struct omap_overlay_manager *mgr = NULL;
11747+ int len = size;
11748+
11749+ if (buf[size-1] == '\n')
11750+ --len;
11751+
11752+ if (len > 0) {
11753+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
11754+ mgr = omap_dss_get_overlay_manager(i);
11755+
11756+ if (strncmp(buf, mgr->name, len) == 0)
11757+ break;
11758+
11759+ mgr = NULL;
11760+ }
11761+ }
11762+
11763+ if (len > 0 && mgr == NULL)
11764+ return -EINVAL;
11765+
11766+ if (mgr)
11767+ DSSDBG("manager %s found\n", mgr->name);
11768+
11769+ if (mgr != ovl->manager) {
11770+ /* detach old manager */
11771+ if (ovl->manager) {
11772+ r = ovl->unset_manager(ovl);
11773+ if (r) {
11774+ DSSERR("detach failed\n");
11775+ return r;
11776+ }
11777+ }
11778+
11779+ if (mgr) {
11780+ r = ovl->set_manager(ovl, mgr);
11781+ if (r) {
11782+ DSSERR("Failed to attach overlay\n");
11783+ return r;
11784+ }
11785+ }
11786+ }
11787+
11788+ if (ovl->manager && (r = ovl->manager->apply(ovl->manager)))
11789+ return r;
11790+
11791+ return size;
11792+}
11793+
11794+static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
11795+{
11796+ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
11797+ ovl->info.width, ovl->info.height);
11798+}
11799+
11800+static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
11801+{
11802+ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.screen_width);
11803+}
11804+
11805+static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
11806+{
11807+ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
11808+ ovl->info.pos_x, ovl->info.pos_y);
11809+}
11810+
11811+static ssize_t overlay_position_store(struct omap_overlay *ovl,
11812+ const char *buf, size_t size)
11813+{
11814+ int r;
11815+ char *last;
11816+ struct omap_overlay_info info;
11817+
11818+ ovl->get_overlay_info(ovl, &info);
11819+
11820+ info.pos_x = simple_strtoul(buf, &last, 10);
11821+ ++last;
11822+ if (last - buf >= size)
11823+ return -EINVAL;
11824+
11825+ info.pos_y = simple_strtoul(last, &last, 10);
11826+
11827+ if ((r = ovl->set_overlay_info(ovl, &info)))
11828+ return r;
11829+
11830+ if (ovl->manager && (r = ovl->manager->apply(ovl->manager)))
11831+ return r;
11832+
11833+ return size;
11834+}
11835+
11836+static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
11837+{
11838+ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
11839+ ovl->info.out_width, ovl->info.out_height);
11840+}
11841+
11842+static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
11843+ const char *buf, size_t size)
11844+{
11845+ int r;
11846+ char *last;
11847+ struct omap_overlay_info info;
11848+
11849+ ovl->get_overlay_info(ovl, &info);
11850+
11851+ info.out_width = simple_strtoul(buf, &last, 10);
11852+ ++last;
11853+ if (last - buf >= size)
11854+ return -EINVAL;
11855+
11856+ info.out_height = simple_strtoul(last, &last, 10);
11857+
11858+ if ((r = ovl->set_overlay_info(ovl, &info)))
11859+ return r;
11860+
11861+ if (ovl->manager && (r = ovl->manager->apply(ovl->manager)))
11862+ return r;
11863+
11864+ return size;
11865+}
11866+
11867+static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
11868+{
11869+ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled);
11870+}
11871+
11872+static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, size_t size)
11873+{
11874+ int r;
11875+ struct omap_overlay_info info;
11876+
11877+ ovl->get_overlay_info(ovl, &info);
11878+
11879+ info.enabled = simple_strtoul(buf, NULL, 10);
11880+
11881+ if ((r = ovl->set_overlay_info(ovl, &info)))
11882+ return r;
11883+
11884+ if (ovl->manager && (r = ovl->manager->apply(ovl->manager)))
11885+ return r;
11886+
11887+ return size;
11888+}
11889+
11890+struct overlay_attribute {
11891+ struct attribute attr;
11892+ ssize_t (*show)(struct omap_overlay *, char *);
11893+ ssize_t (*store)(struct omap_overlay *, const char *, size_t);
11894+};
11895+
11896+#define OVERLAY_ATTR(_name, _mode, _show, _store) \
11897+ struct overlay_attribute overlay_attr_##_name = \
11898+ __ATTR(_name, _mode, _show, _store)
11899+
11900+static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
11901+static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
11902+ overlay_manager_show, overlay_manager_store);
11903+static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
11904+static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
11905+static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
11906+ overlay_position_show, overlay_position_store);
11907+static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
11908+ overlay_output_size_show, overlay_output_size_store);
11909+static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
11910+ overlay_enabled_show, overlay_enabled_store);
11911+
11912+static struct attribute *overlay_sysfs_attrs[] = {
11913+ &overlay_attr_name.attr,
11914+ &overlay_attr_manager.attr,
11915+ &overlay_attr_input_size.attr,
11916+ &overlay_attr_screen_width.attr,
11917+ &overlay_attr_position.attr,
11918+ &overlay_attr_output_size.attr,
11919+ &overlay_attr_enabled.attr,
11920+ NULL
11921+};
11922+
11923+static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
11924+{
11925+ struct omap_overlay *overlay;
11926+ struct overlay_attribute *overlay_attr;
11927+
11928+ overlay = container_of(kobj, struct omap_overlay, kobj);
11929+ overlay_attr = container_of(attr, struct overlay_attribute, attr);
11930+
11931+ if (!overlay_attr->show)
11932+ return -ENOENT;
11933+
11934+ return overlay_attr->show(overlay, buf);
11935+}
11936+
11937+static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
11938+ const char *buf, size_t size)
11939+{
11940+ struct omap_overlay *overlay;
11941+ struct overlay_attribute *overlay_attr;
11942+
11943+ overlay = container_of(kobj, struct omap_overlay, kobj);
11944+ overlay_attr = container_of(attr, struct overlay_attribute, attr);
11945+
11946+ if (!overlay_attr->store)
11947+ return -ENOENT;
11948+
11949+ return overlay_attr->store(overlay, buf, size);
11950+}
11951+
11952+static struct sysfs_ops overlay_sysfs_ops = {
11953+ .show = overlay_attr_show,
11954+ .store = overlay_attr_store,
11955+};
11956+
11957+static struct kobj_type overlay_ktype = {
11958+ .sysfs_ops = &overlay_sysfs_ops,
11959+ .default_attrs = overlay_sysfs_attrs,
11960+};
11961+
11962+/* Check if overlay parameters are compatible with display */
11963+int dss_check_overlay(struct omap_overlay *ovl, struct omap_display *display)
11964+{
11965+ struct omap_overlay_info *info;
11966+ u16 outw, outh;
11967+ u16 dw, dh;
11968+
11969+ if (!display)
11970+ return 0;
11971+
11972+ if (!ovl->info.enabled)
11973+ return 0;
11974+
11975+ info = &ovl->info;
11976+
11977+ display->get_resolution(display, &dw, &dh);
11978+
11979+ DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n",
11980+ ovl->id,
11981+ info->pos_x, info->pos_y,
11982+ info->width, info->height,
11983+ info->out_width, info->out_height,
11984+ dw, dh);
11985+
11986+ if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
11987+ outw = info->width;
11988+ outh = info->height;
11989+ } else {
11990+ if (info->out_width == 0)
11991+ outw = info->width;
11992+ else
11993+ outw = info->out_width;
11994+
11995+ if (info->out_height == 0)
11996+ outh = info->height;
11997+ else
11998+ outh = info->out_height;
11999+ }
12000+
12001+ if (dw < info->pos_x + outw) {
12002+ DSSDBG("check_overlay failed 1: %d < %d + %d\n",
12003+ dw, info->pos_x, outw);
12004+ return -EINVAL;
12005+ }
12006+
12007+ if (dh < info->pos_y + outh) {
12008+ DSSDBG("check_overlay failed 2: %d < %d + %d\n",
12009+ dh, info->pos_y, outh);
12010+ return -EINVAL;
12011+ }
12012+
12013+ if ((ovl->supported_modes & info->color_mode) == 0) {
12014+ DSSERR("overlay doesn't support mode %d\n", info->color_mode);
12015+ return -EINVAL;
12016+ }
12017+
12018+ return 0;
12019+}
12020+
12021+static int dss_ovl_set_overlay_info(struct omap_overlay *ovl,
12022+ struct omap_overlay_info *info)
12023+{
12024+ int r;
12025+ struct omap_overlay_info old_info;
12026+
12027+ old_info = ovl->info;
12028+ ovl->info = *info;
12029+
12030+ if (ovl->manager) {
12031+ r = dss_check_overlay(ovl, ovl->manager->display);
12032+ if (r) {
12033+ ovl->info = old_info;
12034+ return r;
12035+ }
12036+ }
12037+
12038+ return 0;
12039+}
12040+
12041+static void dss_ovl_get_overlay_info(struct omap_overlay *ovl,
12042+ struct omap_overlay_info *info)
12043+{
12044+ *info = ovl->info;
12045+}
12046+
12047+static int omap_dss_set_manager(struct omap_overlay *ovl,
12048+ struct omap_overlay_manager *mgr)
12049+{
12050+ int r;
12051+
12052+ if (ovl->manager) {
12053+ DSSERR("overlay '%s' already has a manager '%s'\n",
12054+ ovl->name, ovl->manager->name);
12055+ }
12056+
12057+ r = dss_check_overlay(ovl, mgr->display);
12058+ if (r)
12059+ return r;
12060+
12061+ ovl->manager = mgr;
12062+
12063+ return 0;
12064+}
12065+
12066+static int omap_dss_unset_manager(struct omap_overlay *ovl)
12067+{
12068+ if (!ovl->manager) {
12069+ DSSERR("failed to detach overlay: manager not set\n");
12070+ return -EINVAL;
12071+ }
12072+
12073+ ovl->manager = NULL;
12074+
12075+ return 0;
12076+}
12077+
12078+int omap_dss_get_num_overlays(void)
12079+{
12080+ return num_overlays;
12081+}
12082+EXPORT_SYMBOL(omap_dss_get_num_overlays);
12083+
12084+struct omap_overlay *omap_dss_get_overlay(int num)
12085+{
12086+ int i = 0;
12087+ struct omap_overlay *ovl;
12088+
12089+ list_for_each_entry(ovl, &overlay_list, list) {
12090+ if (i++ == num)
12091+ return ovl;
12092+ }
12093+
12094+ return NULL;
12095+}
12096+EXPORT_SYMBOL(omap_dss_get_overlay);
12097+
12098+static void omap_dss_add_overlay(struct omap_overlay *overlay)
12099+{
12100+ ++num_overlays;
12101+ list_add_tail(&overlay->list, &overlay_list);
12102+}
12103+
12104+static struct omap_overlay *dispc_overlays[3];
12105+
12106+void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
12107+{
12108+ mgr->num_overlays = 3;
12109+ mgr->overlays = dispc_overlays;
12110+}
12111+
12112+void dss_init_overlays(struct platform_device *pdev, const char *def_disp_name)
12113+{
12114+ int i, r;
12115+ struct omap_overlay_manager *lcd_mgr;
12116+ struct omap_overlay_manager *tv_mgr;
12117+ struct omap_overlay_manager *def_mgr = NULL;
12118+
12119+ INIT_LIST_HEAD(&overlay_list);
12120+
12121+ num_overlays = 0;
12122+
12123+ for (i = 0; i < 3; ++i) {
12124+ struct omap_overlay *ovl;
12125+ ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
12126+
12127+ BUG_ON(ovl == NULL);
12128+
12129+ switch (i) {
12130+ case 0:
12131+ ovl->name = "gfx";
12132+ ovl->id = OMAP_DSS_GFX;
12133+ ovl->supported_modes = OMAP_DSS_COLOR_GFX_OMAP3;
12134+ ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
12135+ break;
12136+ case 1:
12137+ ovl->name = "vid1";
12138+ ovl->id = OMAP_DSS_VIDEO1;
12139+ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3;
12140+ ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
12141+ OMAP_DSS_OVL_CAP_DISPC;
12142+ break;
12143+ case 2:
12144+ ovl->name = "vid2";
12145+ ovl->id = OMAP_DSS_VIDEO2;
12146+ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3;
12147+ ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
12148+ OMAP_DSS_OVL_CAP_DISPC;
12149+ break;
12150+ }
12151+
12152+ ovl->set_manager = &omap_dss_set_manager;
12153+ ovl->unset_manager = &omap_dss_unset_manager;
12154+ ovl->set_overlay_info = &dss_ovl_set_overlay_info;
12155+ ovl->get_overlay_info = &dss_ovl_get_overlay_info;
12156+
12157+ omap_dss_add_overlay(ovl);
12158+
12159+ r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
12160+ &pdev->dev.kobj, "overlay%d", i);
12161+
12162+ if (r) {
12163+ DSSERR("failed to create sysfs file\n");
12164+ continue;
12165+ }
12166+
12167+ dispc_overlays[i] = ovl;
12168+ }
12169+
12170+ lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD);
12171+ tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV);
12172+
12173+ if (def_disp_name) {
12174+ for (i = 0; i < omap_dss_get_num_displays() ; i++) {
12175+ struct omap_display *display = dss_get_display(i);
12176+
12177+ if (strcmp(display->name, def_disp_name) == 0) {
12178+ if (display->type != OMAP_DISPLAY_TYPE_VENC) {
12179+ lcd_mgr->set_display(lcd_mgr, display);
12180+ def_mgr = lcd_mgr;
12181+ } else {
12182+ lcd_mgr->set_display(tv_mgr, display);
12183+ def_mgr = tv_mgr;
12184+ }
12185+
12186+ break;
12187+ }
12188+ }
12189+
12190+ if (!def_mgr)
12191+ DSSWARN("default display %s not found\n",
12192+ def_disp_name);
12193+ }
12194+
12195+ if (def_mgr != lcd_mgr) {
12196+ /* connect lcd manager to first non-VENC display found */
12197+ for (i = 0; i < omap_dss_get_num_displays(); i++) {
12198+ struct omap_display *display = dss_get_display(i);
12199+ if (display->type != OMAP_DISPLAY_TYPE_VENC) {
12200+ lcd_mgr->set_display(lcd_mgr, display);
12201+
12202+ if (!def_mgr)
12203+ def_mgr = lcd_mgr;
12204+
12205+ break;
12206+ }
12207+ }
12208+ }
12209+
12210+ if (def_mgr != tv_mgr) {
12211+ /* connect tv manager to first VENC display found */
12212+ for (i = 0; i < omap_dss_get_num_displays(); i++) {
12213+ struct omap_display *display = dss_get_display(i);
12214+ if (display->type == OMAP_DISPLAY_TYPE_VENC) {
12215+ tv_mgr->set_display(tv_mgr, display);
12216+
12217+ if (!def_mgr)
12218+ def_mgr = tv_mgr;
12219+
12220+ break;
12221+ }
12222+ }
12223+ }
12224+
12225+ /* connect all dispc overlays to def_mgr */
12226+ if (def_mgr) {
12227+ for (i = 0; i < 3; i++) {
12228+ struct omap_overlay *ovl;
12229+ ovl = omap_dss_get_overlay(i);
12230+ omap_dss_set_manager(ovl, def_mgr);
12231+ }
12232+ }
12233+
12234+#ifdef L4_EXAMPLE
12235+ /* setup L4 overlay as an example */
12236+ {
12237+ static struct omap_overlay ovl = {
12238+ .name = "l4-ovl",
12239+ .supported_modes = OMAP_DSS_COLOR_RGB24U,
12240+ .set_manager = &omap_dss_set_manager,
12241+ .unset_manager = &omap_dss_unset_manager,
12242+ .setup_input = &omap_dss_setup_overlay_input,
12243+ .setup_output = &omap_dss_setup_overlay_output,
12244+ .enable = &omap_dss_enable_overlay,
12245+ };
12246+
12247+ static struct omap_overlay_manager mgr = {
12248+ .name = "l4",
12249+ .num_overlays = 1,
12250+ .overlays = &ovl,
12251+ .set_display = &omap_dss_set_display,
12252+ .unset_display = &omap_dss_unset_display,
12253+ .apply = &ovl_mgr_apply_l4,
12254+ .supported_displays =
12255+ OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI,
12256+ };
12257+
12258+ omap_dss_add_overlay(&ovl);
12259+ omap_dss_add_overlay_manager(&mgr);
12260+ omap_dss_set_manager(&ovl, &mgr);
12261+ }
12262+#endif
12263+}
12264+
12265+void dss_uninit_overlays(struct platform_device *pdev)
12266+{
12267+ struct omap_overlay *ovl;
12268+
12269+ while (!list_empty(&overlay_list)) {
12270+ ovl = list_first_entry(&overlay_list,
12271+ struct omap_overlay, list);
12272+ list_del(&ovl->list);
12273+ kobject_del(&ovl->kobj);
12274+ kobject_put(&ovl->kobj);
12275+ kfree(ovl);
12276+ }
12277+
12278+ num_overlays = 0;
12279+}
12280+
12281diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
12282new file mode 100644
12283index 0000000..3e9ae1e
12284--- /dev/null
12285+++ b/drivers/video/omap2/dss/rfbi.c
12286@@ -0,0 +1,1304 @@
12287+/*
12288+ * linux/drivers/video/omap2/dss/rfbi.c
12289+ *
12290+ * Copyright (C) 2009 Nokia Corporation
12291+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
12292+ *
12293+ * Some code and ideas taken from drivers/video/omap/ driver
12294+ * by Imre Deak.
12295+ *
12296+ * This program is free software; you can redistribute it and/or modify it
12297+ * under the terms of the GNU General Public License version 2 as published by
12298+ * the Free Software Foundation.
12299+ *
12300+ * This program is distributed in the hope that it will be useful, but WITHOUT
12301+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12302+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12303+ * more details.
12304+ *
12305+ * You should have received a copy of the GNU General Public License along with
12306+ * this program. If not, see <http://www.gnu.org/licenses/>.
12307+ */
12308+
12309+#define DSS_SUBSYS_NAME "RFBI"
12310+
12311+#include <linux/kernel.h>
12312+#include <linux/dma-mapping.h>
12313+#include <linux/vmalloc.h>
12314+#include <linux/clk.h>
12315+#include <linux/io.h>
12316+#include <linux/delay.h>
12317+#include <linux/kfifo.h>
12318+#include <linux/ktime.h>
12319+#include <linux/hrtimer.h>
12320+#include <linux/seq_file.h>
12321+
12322+#include <mach/board.h>
12323+#include <mach/display.h>
12324+#include "dss.h"
12325+
12326+/*#define MEASURE_PERF*/
12327+
12328+#define RFBI_BASE 0x48050800
12329+
12330+struct rfbi_reg { u16 idx; };
12331+
12332+#define RFBI_REG(idx) ((const struct rfbi_reg) { idx })
12333+
12334+#define RFBI_REVISION RFBI_REG(0x0000)
12335+#define RFBI_SYSCONFIG RFBI_REG(0x0010)
12336+#define RFBI_SYSSTATUS RFBI_REG(0x0014)
12337+#define RFBI_CONTROL RFBI_REG(0x0040)
12338+#define RFBI_PIXEL_CNT RFBI_REG(0x0044)
12339+#define RFBI_LINE_NUMBER RFBI_REG(0x0048)
12340+#define RFBI_CMD RFBI_REG(0x004c)
12341+#define RFBI_PARAM RFBI_REG(0x0050)
12342+#define RFBI_DATA RFBI_REG(0x0054)
12343+#define RFBI_READ RFBI_REG(0x0058)
12344+#define RFBI_STATUS RFBI_REG(0x005c)
12345+
12346+#define RFBI_CONFIG(n) RFBI_REG(0x0060 + (n)*0x18)
12347+#define RFBI_ONOFF_TIME(n) RFBI_REG(0x0064 + (n)*0x18)
12348+#define RFBI_CYCLE_TIME(n) RFBI_REG(0x0068 + (n)*0x18)
12349+#define RFBI_DATA_CYCLE1(n) RFBI_REG(0x006c + (n)*0x18)
12350+#define RFBI_DATA_CYCLE2(n) RFBI_REG(0x0070 + (n)*0x18)
12351+#define RFBI_DATA_CYCLE3(n) RFBI_REG(0x0074 + (n)*0x18)
12352+
12353+#define RFBI_VSYNC_WIDTH RFBI_REG(0x0090)
12354+#define RFBI_HSYNC_WIDTH RFBI_REG(0x0094)
12355+
12356+#define RFBI_CMD_FIFO_LEN_BYTES (16 * sizeof(struct update_param))
12357+
12358+#define REG_FLD_MOD(idx, val, start, end) \
12359+ rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
12360+
12361+/* To work around an RFBI transfer rate limitation */
12362+#define OMAP_RFBI_RATE_LIMIT 1
12363+
12364+enum omap_rfbi_cycleformat {
12365+ OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0,
12366+ OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1,
12367+ OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2,
12368+ OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3,
12369+};
12370+
12371+enum omap_rfbi_datatype {
12372+ OMAP_DSS_RFBI_DATATYPE_12 = 0,
12373+ OMAP_DSS_RFBI_DATATYPE_16 = 1,
12374+ OMAP_DSS_RFBI_DATATYPE_18 = 2,
12375+ OMAP_DSS_RFBI_DATATYPE_24 = 3,
12376+};
12377+
12378+enum omap_rfbi_parallelmode {
12379+ OMAP_DSS_RFBI_PARALLELMODE_8 = 0,
12380+ OMAP_DSS_RFBI_PARALLELMODE_9 = 1,
12381+ OMAP_DSS_RFBI_PARALLELMODE_12 = 2,
12382+ OMAP_DSS_RFBI_PARALLELMODE_16 = 3,
12383+};
12384+
12385+enum update_cmd {
12386+ RFBI_CMD_UPDATE = 0,
12387+ RFBI_CMD_SYNC = 1,
12388+};
12389+
12390+static int rfbi_convert_timings(struct rfbi_timings *t);
12391+static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
12392+static void process_cmd_fifo(void);
12393+
12394+static struct {
12395+ void __iomem *base;
12396+
12397+ unsigned long l4_khz;
12398+
12399+ enum omap_rfbi_datatype datatype;
12400+ enum omap_rfbi_parallelmode parallelmode;
12401+
12402+ enum omap_rfbi_te_mode te_mode;
12403+ int te_enabled;
12404+
12405+ void (*framedone_callback)(void *data);
12406+ void *framedone_callback_data;
12407+
12408+ struct omap_display *display[2];
12409+
12410+ struct kfifo *cmd_fifo;
12411+ spinlock_t cmd_lock;
12412+ struct completion cmd_done;
12413+ atomic_t cmd_fifo_full;
12414+ atomic_t cmd_pending;
12415+#ifdef MEASURE_PERF
12416+ unsigned perf_bytes;
12417+ ktime_t perf_setup_time;
12418+ ktime_t perf_start_time;
12419+#endif
12420+} rfbi;
12421+
12422+struct update_region {
12423+ u16 x;
12424+ u16 y;
12425+ u16 w;
12426+ u16 h;
12427+};
12428+
12429+struct update_param {
12430+ u8 rfbi_module;
12431+ u8 cmd;
12432+
12433+ union {
12434+ struct update_region r;
12435+ struct completion *sync;
12436+ } par;
12437+};
12438+
12439+static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
12440+{
12441+ __raw_writel(val, rfbi.base + idx.idx);
12442+}
12443+
12444+static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
12445+{
12446+ return __raw_readl(rfbi.base + idx.idx);
12447+}
12448+
12449+static void rfbi_enable_clocks(bool enable)
12450+{
12451+ if (enable)
12452+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
12453+ else
12454+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
12455+}
12456+
12457+void omap_rfbi_write_command(const void *buf, u32 len)
12458+{
12459+ rfbi_enable_clocks(1);
12460+ switch (rfbi.parallelmode) {
12461+ case OMAP_DSS_RFBI_PARALLELMODE_8:
12462+ {
12463+ const u8 *b = buf;
12464+ for (; len; len--)
12465+ rfbi_write_reg(RFBI_CMD, *b++);
12466+ break;
12467+ }
12468+
12469+ case OMAP_DSS_RFBI_PARALLELMODE_16:
12470+ {
12471+ const u16 *w = buf;
12472+ BUG_ON(len & 1);
12473+ for (; len; len -= 2)
12474+ rfbi_write_reg(RFBI_CMD, *w++);
12475+ break;
12476+ }
12477+
12478+ case OMAP_DSS_RFBI_PARALLELMODE_9:
12479+ case OMAP_DSS_RFBI_PARALLELMODE_12:
12480+ default:
12481+ BUG();
12482+ }
12483+ rfbi_enable_clocks(0);
12484+}
12485+EXPORT_SYMBOL(omap_rfbi_write_command);
12486+
12487+void omap_rfbi_read_data(void *buf, u32 len)
12488+{
12489+ rfbi_enable_clocks(1);
12490+ switch (rfbi.parallelmode) {
12491+ case OMAP_DSS_RFBI_PARALLELMODE_8:
12492+ {
12493+ u8 *b = buf;
12494+ for (; len; len--) {
12495+ rfbi_write_reg(RFBI_READ, 0);
12496+ *b++ = rfbi_read_reg(RFBI_READ);
12497+ }
12498+ break;
12499+ }
12500+
12501+ case OMAP_DSS_RFBI_PARALLELMODE_16:
12502+ {
12503+ u16 *w = buf;
12504+ BUG_ON(len & ~1);
12505+ for (; len; len -= 2) {
12506+ rfbi_write_reg(RFBI_READ, 0);
12507+ *w++ = rfbi_read_reg(RFBI_READ);
12508+ }
12509+ break;
12510+ }
12511+
12512+ case OMAP_DSS_RFBI_PARALLELMODE_9:
12513+ case OMAP_DSS_RFBI_PARALLELMODE_12:
12514+ default:
12515+ BUG();
12516+ }
12517+ rfbi_enable_clocks(0);
12518+}
12519+EXPORT_SYMBOL(omap_rfbi_read_data);
12520+
12521+void omap_rfbi_write_data(const void *buf, u32 len)
12522+{
12523+ rfbi_enable_clocks(1);
12524+ switch (rfbi.parallelmode) {
12525+ case OMAP_DSS_RFBI_PARALLELMODE_8:
12526+ {
12527+ const u8 *b = buf;
12528+ for (; len; len--)
12529+ rfbi_write_reg(RFBI_PARAM, *b++);
12530+ break;
12531+ }
12532+
12533+ case OMAP_DSS_RFBI_PARALLELMODE_16:
12534+ {
12535+ const u16 *w = buf;
12536+ BUG_ON(len & 1);
12537+ for (; len; len -= 2)
12538+ rfbi_write_reg(RFBI_PARAM, *w++);
12539+ break;
12540+ }
12541+
12542+ case OMAP_DSS_RFBI_PARALLELMODE_9:
12543+ case OMAP_DSS_RFBI_PARALLELMODE_12:
12544+ default:
12545+ BUG();
12546+
12547+ }
12548+ rfbi_enable_clocks(0);
12549+}
12550+EXPORT_SYMBOL(omap_rfbi_write_data);
12551+
12552+void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
12553+ u16 x, u16 y,
12554+ u16 w, u16 h)
12555+{
12556+ int start_offset = scr_width * y + x;
12557+ int horiz_offset = scr_width - w;
12558+ int i;
12559+
12560+ rfbi_enable_clocks(1);
12561+
12562+ if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
12563+ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
12564+ const u16 __iomem *pd = buf;
12565+ pd += start_offset;
12566+
12567+ for (; h; --h) {
12568+ for (i = 0; i < w; ++i) {
12569+ const u8 __iomem *b = (const u8 __iomem *)pd;
12570+ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
12571+ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
12572+ ++pd;
12573+ }
12574+ pd += horiz_offset;
12575+ }
12576+ } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 &&
12577+ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
12578+ const u32 __iomem *pd = buf;
12579+ pd += start_offset;
12580+
12581+ for (; h; --h) {
12582+ for (i = 0; i < w; ++i) {
12583+ const u8 __iomem *b = (const u8 __iomem *)pd;
12584+ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+2));
12585+ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
12586+ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
12587+ ++pd;
12588+ }
12589+ pd += horiz_offset;
12590+ }
12591+ } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
12592+ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) {
12593+ const u16 __iomem *pd = buf;
12594+ pd += start_offset;
12595+
12596+ for (; h; --h) {
12597+ for (i = 0; i < w; ++i) {
12598+ rfbi_write_reg(RFBI_PARAM, __raw_readw(pd));
12599+ ++pd;
12600+ }
12601+ pd += horiz_offset;
12602+ }
12603+ } else {
12604+ BUG();
12605+ }
12606+
12607+ rfbi_enable_clocks(0);
12608+}
12609+EXPORT_SYMBOL(omap_rfbi_write_pixels);
12610+
12611+#ifdef MEASURE_PERF
12612+static void perf_mark_setup(void)
12613+{
12614+ rfbi.perf_setup_time = ktime_get();
12615+}
12616+
12617+static void perf_mark_start(void)
12618+{
12619+ rfbi.perf_start_time = ktime_get();
12620+}
12621+
12622+static void perf_show(const char *name)
12623+{
12624+ ktime_t t, setup_time, trans_time;
12625+ u32 total_bytes;
12626+ u32 setup_us, trans_us, total_us;
12627+
12628+ t = ktime_get();
12629+
12630+ setup_time = ktime_sub(rfbi.perf_start_time, rfbi.perf_setup_time);
12631+ setup_us = (u32)ktime_to_us(setup_time);
12632+ if (setup_us == 0)
12633+ setup_us = 1;
12634+
12635+ trans_time = ktime_sub(t, rfbi.perf_start_time);
12636+ trans_us = (u32)ktime_to_us(trans_time);
12637+ if (trans_us == 0)
12638+ trans_us = 1;
12639+
12640+ total_us = setup_us + trans_us;
12641+
12642+ total_bytes = rfbi.perf_bytes;
12643+
12644+ DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, "
12645+ "%u kbytes/sec\n",
12646+ name,
12647+ setup_us,
12648+ trans_us,
12649+ total_us,
12650+ 1000*1000 / total_us,
12651+ total_bytes,
12652+ total_bytes * 1000 / total_us);
12653+}
12654+#else
12655+#define perf_mark_setup()
12656+#define perf_mark_start()
12657+#define perf_show(x)
12658+#endif
12659+
12660+void rfbi_transfer_area(u16 width, u16 height,
12661+ void (callback)(void *data), void *data)
12662+{
12663+ u32 l;
12664+
12665+ /*BUG_ON(callback == 0);*/
12666+ BUG_ON(rfbi.framedone_callback != NULL);
12667+
12668+ DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
12669+
12670+ dispc_set_lcd_size(width, height);
12671+
12672+ dispc_enable_lcd_out(1);
12673+
12674+ rfbi.framedone_callback = callback;
12675+ rfbi.framedone_callback_data = data;
12676+
12677+ rfbi_enable_clocks(1);
12678+
12679+ rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
12680+
12681+ l = rfbi_read_reg(RFBI_CONTROL);
12682+ l = FLD_MOD(l, 1, 0, 0); /* enable */
12683+ if (!rfbi.te_enabled)
12684+ l = FLD_MOD(l, 1, 4, 4); /* ITE */
12685+
12686+ perf_mark_start();
12687+
12688+ rfbi_write_reg(RFBI_CONTROL, l);
12689+}
12690+
12691+static void framedone_callback(void *data, u32 mask)
12692+{
12693+ void (*callback)(void *data);
12694+
12695+ DSSDBG("FRAMEDONE\n");
12696+
12697+ perf_show("DISPC");
12698+
12699+ REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0);
12700+
12701+ rfbi_enable_clocks(0);
12702+
12703+ callback = rfbi.framedone_callback;
12704+ rfbi.framedone_callback = NULL;
12705+
12706+ /*callback(rfbi.framedone_callback_data);*/
12707+
12708+ atomic_set(&rfbi.cmd_pending, 0);
12709+
12710+ process_cmd_fifo();
12711+}
12712+
12713+#if 1 /* VERBOSE */
12714+static void rfbi_print_timings(void)
12715+{
12716+ u32 l;
12717+ u32 time;
12718+
12719+ l = rfbi_read_reg(RFBI_CONFIG(0));
12720+ time = 1000000000 / rfbi.l4_khz;
12721+ if (l & (1 << 4))
12722+ time *= 2;
12723+
12724+ DSSDBG("Tick time %u ps\n", time);
12725+ l = rfbi_read_reg(RFBI_ONOFF_TIME(0));
12726+ DSSDBG("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
12727+ "REONTIME %d, REOFFTIME %d\n",
12728+ l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
12729+ (l >> 20) & 0x0f, (l >> 24) & 0x3f);
12730+
12731+ l = rfbi_read_reg(RFBI_CYCLE_TIME(0));
12732+ DSSDBG("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
12733+ "ACCESSTIME %d\n",
12734+ (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
12735+ (l >> 22) & 0x3f);
12736+}
12737+#else
12738+static void rfbi_print_timings(void) {}
12739+#endif
12740+
12741+
12742+
12743+
12744+static u32 extif_clk_period;
12745+
12746+static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
12747+{
12748+ int bus_tick = extif_clk_period * div;
12749+ return (ps + bus_tick - 1) / bus_tick * bus_tick;
12750+}
12751+
12752+static int calc_reg_timing(struct rfbi_timings *t, int div)
12753+{
12754+ t->clk_div = div;
12755+
12756+ t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div);
12757+
12758+ t->we_on_time = round_to_extif_ticks(t->we_on_time, div);
12759+ t->we_off_time = round_to_extif_ticks(t->we_off_time, div);
12760+ t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div);
12761+
12762+ t->re_on_time = round_to_extif_ticks(t->re_on_time, div);
12763+ t->re_off_time = round_to_extif_ticks(t->re_off_time, div);
12764+ t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div);
12765+
12766+ t->access_time = round_to_extif_ticks(t->access_time, div);
12767+ t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div);
12768+ t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div);
12769+
12770+ DSSDBG("[reg]cson %d csoff %d reon %d reoff %d\n",
12771+ t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
12772+ DSSDBG("[reg]weon %d weoff %d recyc %d wecyc %d\n",
12773+ t->we_on_time, t->we_off_time, t->re_cycle_time,
12774+ t->we_cycle_time);
12775+ DSSDBG("[reg]rdaccess %d cspulse %d\n",
12776+ t->access_time, t->cs_pulse_width);
12777+
12778+ return rfbi_convert_timings(t);
12779+}
12780+
12781+static int calc_extif_timings(struct rfbi_timings *t)
12782+{
12783+ u32 max_clk_div;
12784+ int div;
12785+
12786+ rfbi_get_clk_info(&extif_clk_period, &max_clk_div);
12787+ for (div = 1; div <= max_clk_div; div++) {
12788+ if (calc_reg_timing(t, div) == 0)
12789+ break;
12790+ }
12791+
12792+ if (div <= max_clk_div)
12793+ return 0;
12794+
12795+ DSSERR("can't setup timings\n");
12796+ return -1;
12797+}
12798+
12799+
12800+void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
12801+{
12802+ int r;
12803+
12804+ if (!t->converted) {
12805+ r = calc_extif_timings(t);
12806+ if (r < 0)
12807+ DSSERR("Failed to calc timings\n");
12808+ }
12809+
12810+ BUG_ON(!t->converted);
12811+
12812+ rfbi_enable_clocks(1);
12813+ rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]);
12814+ rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]);
12815+
12816+ /* TIMEGRANULARITY */
12817+ REG_FLD_MOD(RFBI_CONFIG(rfbi_module),
12818+ (t->tim[2] ? 1 : 0), 4, 4);
12819+
12820+ rfbi_print_timings();
12821+ rfbi_enable_clocks(0);
12822+}
12823+
12824+static int ps_to_rfbi_ticks(int time, int div)
12825+{
12826+ unsigned long tick_ps;
12827+ int ret;
12828+
12829+ /* Calculate in picosecs to yield more exact results */
12830+ tick_ps = 1000000000 / (rfbi.l4_khz) * div;
12831+
12832+ ret = (time + tick_ps - 1) / tick_ps;
12833+
12834+ return ret;
12835+}
12836+
12837+#ifdef OMAP_RFBI_RATE_LIMIT
12838+unsigned long rfbi_get_max_tx_rate(void)
12839+{
12840+ unsigned long l4_rate, dss1_rate;
12841+ int min_l4_ticks = 0;
12842+ int i;
12843+
12844+ /* According to TI this can't be calculated so make the
12845+ * adjustments for a couple of known frequencies and warn for
12846+ * others.
12847+ */
12848+ static const struct {
12849+ unsigned long l4_clk; /* HZ */
12850+ unsigned long dss1_clk; /* HZ */
12851+ unsigned long min_l4_ticks;
12852+ } ftab[] = {
12853+ { 55, 132, 7, }, /* 7.86 MPix/s */
12854+ { 110, 110, 12, }, /* 9.16 MPix/s */
12855+ { 110, 132, 10, }, /* 11 Mpix/s */
12856+ { 120, 120, 10, }, /* 12 Mpix/s */
12857+ { 133, 133, 10, }, /* 13.3 Mpix/s */
12858+ };
12859+
12860+ l4_rate = rfbi.l4_khz / 1000;
12861+ dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000;
12862+
12863+ for (i = 0; i < ARRAY_SIZE(ftab); i++) {
12864+ /* Use a window instead of an exact match, to account
12865+ * for different DPLL multiplier / divider pairs.
12866+ */
12867+ if (abs(ftab[i].l4_clk - l4_rate) < 3 &&
12868+ abs(ftab[i].dss1_clk - dss1_rate) < 3) {
12869+ min_l4_ticks = ftab[i].min_l4_ticks;
12870+ break;
12871+ }
12872+ }
12873+ if (i == ARRAY_SIZE(ftab)) {
12874+ /* Can't be sure, return anyway the maximum not
12875+ * rate-limited. This might cause a problem only for the
12876+ * tearing synchronisation.
12877+ */
12878+ DSSERR("can't determine maximum RFBI transfer rate\n");
12879+ return rfbi.l4_khz * 1000;
12880+ }
12881+ return rfbi.l4_khz * 1000 / min_l4_ticks;
12882+}
12883+#else
12884+int rfbi_get_max_tx_rate(void)
12885+{
12886+ return rfbi.l4_khz * 1000;
12887+}
12888+#endif
12889+
12890+static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
12891+{
12892+ *clk_period = 1000000000 / rfbi.l4_khz;
12893+ *max_clk_div = 2;
12894+}
12895+
12896+static int rfbi_convert_timings(struct rfbi_timings *t)
12897+{
12898+ u32 l;
12899+ int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
12900+ int actim, recyc, wecyc;
12901+ int div = t->clk_div;
12902+
12903+ if (div <= 0 || div > 2)
12904+ return -1;
12905+
12906+ /* Make sure that after conversion it still holds that:
12907+ * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
12908+ * csoff > cson, csoff >= max(weoff, reoff), actim > reon
12909+ */
12910+ weon = ps_to_rfbi_ticks(t->we_on_time, div);
12911+ weoff = ps_to_rfbi_ticks(t->we_off_time, div);
12912+ if (weoff <= weon)
12913+ weoff = weon + 1;
12914+ if (weon > 0x0f)
12915+ return -1;
12916+ if (weoff > 0x3f)
12917+ return -1;
12918+
12919+ reon = ps_to_rfbi_ticks(t->re_on_time, div);
12920+ reoff = ps_to_rfbi_ticks(t->re_off_time, div);
12921+ if (reoff <= reon)
12922+ reoff = reon + 1;
12923+ if (reon > 0x0f)
12924+ return -1;
12925+ if (reoff > 0x3f)
12926+ return -1;
12927+
12928+ cson = ps_to_rfbi_ticks(t->cs_on_time, div);
12929+ csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
12930+ if (csoff <= cson)
12931+ csoff = cson + 1;
12932+ if (csoff < max(weoff, reoff))
12933+ csoff = max(weoff, reoff);
12934+ if (cson > 0x0f)
12935+ return -1;
12936+ if (csoff > 0x3f)
12937+ return -1;
12938+
12939+ l = cson;
12940+ l |= csoff << 4;
12941+ l |= weon << 10;
12942+ l |= weoff << 14;
12943+ l |= reon << 20;
12944+ l |= reoff << 24;
12945+
12946+ t->tim[0] = l;
12947+
12948+ actim = ps_to_rfbi_ticks(t->access_time, div);
12949+ if (actim <= reon)
12950+ actim = reon + 1;
12951+ if (actim > 0x3f)
12952+ return -1;
12953+
12954+ wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
12955+ if (wecyc < weoff)
12956+ wecyc = weoff;
12957+ if (wecyc > 0x3f)
12958+ return -1;
12959+
12960+ recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
12961+ if (recyc < reoff)
12962+ recyc = reoff;
12963+ if (recyc > 0x3f)
12964+ return -1;
12965+
12966+ cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
12967+ if (cs_pulse > 0x3f)
12968+ return -1;
12969+
12970+ l = wecyc;
12971+ l |= recyc << 6;
12972+ l |= cs_pulse << 12;
12973+ l |= actim << 22;
12974+
12975+ t->tim[1] = l;
12976+
12977+ t->tim[2] = div - 1;
12978+
12979+ t->converted = 1;
12980+
12981+ return 0;
12982+}
12983+
12984+/* xxx FIX module selection missing */
12985+int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
12986+ unsigned hs_pulse_time, unsigned vs_pulse_time,
12987+ int hs_pol_inv, int vs_pol_inv, int extif_div)
12988+{
12989+ int hs, vs;
12990+ int min;
12991+ u32 l;
12992+
12993+ hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
12994+ vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
12995+ if (hs < 2)
12996+ return -EDOM;
12997+ if (mode == OMAP_DSS_RFBI_TE_MODE_2)
12998+ min = 2;
12999+ else /* OMAP_DSS_RFBI_TE_MODE_1 */
13000+ min = 4;
13001+ if (vs < min)
13002+ return -EDOM;
13003+ if (vs == hs)
13004+ return -EINVAL;
13005+ rfbi.te_mode = mode;
13006+ DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n",
13007+ mode, hs, vs, hs_pol_inv, vs_pol_inv);
13008+
13009+ rfbi_enable_clocks(1);
13010+ rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
13011+ rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
13012+
13013+ l = rfbi_read_reg(RFBI_CONFIG(0));
13014+ if (hs_pol_inv)
13015+ l &= ~(1 << 21);
13016+ else
13017+ l |= 1 << 21;
13018+ if (vs_pol_inv)
13019+ l &= ~(1 << 20);
13020+ else
13021+ l |= 1 << 20;
13022+ rfbi_enable_clocks(0);
13023+
13024+ return 0;
13025+}
13026+EXPORT_SYMBOL(omap_rfbi_setup_te);
13027+
13028+/* xxx FIX module selection missing */
13029+int omap_rfbi_enable_te(bool enable, unsigned line)
13030+{
13031+ u32 l;
13032+
13033+ DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode);
13034+ if (line > (1 << 11) - 1)
13035+ return -EINVAL;
13036+
13037+ rfbi_enable_clocks(1);
13038+ l = rfbi_read_reg(RFBI_CONFIG(0));
13039+ l &= ~(0x3 << 2);
13040+ if (enable) {
13041+ rfbi.te_enabled = 1;
13042+ l |= rfbi.te_mode << 2;
13043+ } else
13044+ rfbi.te_enabled = 0;
13045+ rfbi_write_reg(RFBI_CONFIG(0), l);
13046+ rfbi_write_reg(RFBI_LINE_NUMBER, line);
13047+ rfbi_enable_clocks(0);
13048+
13049+ return 0;
13050+}
13051+EXPORT_SYMBOL(omap_rfbi_enable_te);
13052+
13053+#if 0
13054+static void rfbi_enable_config(int enable1, int enable2)
13055+{
13056+ u32 l;
13057+ int cs = 0;
13058+
13059+ if (enable1)
13060+ cs |= 1<<0;
13061+ if (enable2)
13062+ cs |= 1<<1;
13063+
13064+ rfbi_enable_clocks(1);
13065+
13066+ l = rfbi_read_reg(RFBI_CONTROL);
13067+
13068+ l = FLD_MOD(l, cs, 3, 2);
13069+ l = FLD_MOD(l, 0, 1, 1);
13070+
13071+ rfbi_write_reg(RFBI_CONTROL, l);
13072+
13073+
13074+ l = rfbi_read_reg(RFBI_CONFIG(0));
13075+ l = FLD_MOD(l, 0, 3, 2); /* TRIGGERMODE: ITE */
13076+ /*l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
13077+ /*l |= FLD_VAL(0, 8, 7); */ /* L4FORMAT, 1pix/L4 */
13078+
13079+ l = FLD_MOD(l, 0, 16, 16); /* A0POLARITY */
13080+ l = FLD_MOD(l, 1, 20, 20); /* TE_VSYNC_POLARITY */
13081+ l = FLD_MOD(l, 1, 21, 21); /* HSYNCPOLARITY */
13082+
13083+ l = FLD_MOD(l, OMAP_DSS_RFBI_PARALLELMODE_8, 1, 0);
13084+ rfbi_write_reg(RFBI_CONFIG(0), l);
13085+
13086+ rfbi_enable_clocks(0);
13087+}
13088+#endif
13089+
13090+int rfbi_configure(int rfbi_module, int bpp, int lines)
13091+{
13092+ u32 l;
13093+ int cycle1 = 0, cycle2 = 0, cycle3 = 0;
13094+ enum omap_rfbi_cycleformat cycleformat;
13095+ enum omap_rfbi_datatype datatype;
13096+ enum omap_rfbi_parallelmode parallelmode;
13097+
13098+ switch (bpp) {
13099+ case 12:
13100+ datatype = OMAP_DSS_RFBI_DATATYPE_12;
13101+ break;
13102+ case 16:
13103+ datatype = OMAP_DSS_RFBI_DATATYPE_16;
13104+ break;
13105+ case 18:
13106+ datatype = OMAP_DSS_RFBI_DATATYPE_18;
13107+ break;
13108+ case 24:
13109+ datatype = OMAP_DSS_RFBI_DATATYPE_24;
13110+ break;
13111+ default:
13112+ BUG();
13113+ return 1;
13114+ }
13115+ rfbi.datatype = datatype;
13116+
13117+ switch (lines) {
13118+ case 8:
13119+ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8;
13120+ break;
13121+ case 9:
13122+ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9;
13123+ break;
13124+ case 12:
13125+ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12;
13126+ break;
13127+ case 16:
13128+ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16;
13129+ break;
13130+ default:
13131+ BUG();
13132+ return 1;
13133+ }
13134+ rfbi.parallelmode = parallelmode;
13135+
13136+ if ((bpp % lines) == 0) {
13137+ switch (bpp / lines) {
13138+ case 1:
13139+ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1;
13140+ break;
13141+ case 2:
13142+ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1;
13143+ break;
13144+ case 3:
13145+ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1;
13146+ break;
13147+ default:
13148+ BUG();
13149+ return 1;
13150+ }
13151+ } else if ((2 * bpp % lines) == 0) {
13152+ if ((2 * bpp / lines) == 3)
13153+ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2;
13154+ else {
13155+ BUG();
13156+ return 1;
13157+ }
13158+ } else {
13159+ BUG();
13160+ return 1;
13161+ }
13162+
13163+ switch (cycleformat) {
13164+ case OMAP_DSS_RFBI_CYCLEFORMAT_1_1:
13165+ cycle1 = lines;
13166+ break;
13167+
13168+ case OMAP_DSS_RFBI_CYCLEFORMAT_2_1:
13169+ cycle1 = lines;
13170+ cycle2 = lines;
13171+ break;
13172+
13173+ case OMAP_DSS_RFBI_CYCLEFORMAT_3_1:
13174+ cycle1 = lines;
13175+ cycle2 = lines;
13176+ cycle3 = lines;
13177+ break;
13178+
13179+ case OMAP_DSS_RFBI_CYCLEFORMAT_3_2:
13180+ cycle1 = lines;
13181+ cycle2 = (lines / 2) | ((lines / 2) << 16);
13182+ cycle3 = (lines << 16);
13183+ break;
13184+ }
13185+
13186+ rfbi_enable_clocks(1);
13187+
13188+ REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */
13189+
13190+ l = 0;
13191+ l |= FLD_VAL(parallelmode, 1, 0);
13192+ l |= FLD_VAL(0, 3, 2); /* TRIGGERMODE: ITE */
13193+ l |= FLD_VAL(0, 4, 4); /* TIMEGRANULARITY */
13194+ l |= FLD_VAL(datatype, 6, 5);
13195+ /* l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
13196+ l |= FLD_VAL(0, 8, 7); /* L4FORMAT, 1pix/L4 */
13197+ l |= FLD_VAL(cycleformat, 10, 9);
13198+ l |= FLD_VAL(0, 12, 11); /* UNUSEDBITS */
13199+ l |= FLD_VAL(0, 16, 16); /* A0POLARITY */
13200+ l |= FLD_VAL(0, 17, 17); /* REPOLARITY */
13201+ l |= FLD_VAL(0, 18, 18); /* WEPOLARITY */
13202+ l |= FLD_VAL(0, 19, 19); /* CSPOLARITY */
13203+ l |= FLD_VAL(1, 20, 20); /* TE_VSYNC_POLARITY */
13204+ l |= FLD_VAL(1, 21, 21); /* HSYNCPOLARITY */
13205+ rfbi_write_reg(RFBI_CONFIG(rfbi_module), l);
13206+
13207+ rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1);
13208+ rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2);
13209+ rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3);
13210+
13211+
13212+ l = rfbi_read_reg(RFBI_CONTROL);
13213+ l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */
13214+ l = FLD_MOD(l, 0, 1, 1); /* clear bypass */
13215+ rfbi_write_reg(RFBI_CONTROL, l);
13216+
13217+
13218+ DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n",
13219+ bpp, lines, cycle1, cycle2, cycle3);
13220+
13221+ rfbi_enable_clocks(0);
13222+
13223+ return 0;
13224+}
13225+EXPORT_SYMBOL(rfbi_configure);
13226+
13227+static int rfbi_find_display(struct omap_display *disp)
13228+{
13229+ if (disp == rfbi.display[0])
13230+ return 0;
13231+
13232+ if (disp == rfbi.display[1])
13233+ return 1;
13234+
13235+ BUG();
13236+ return -1;
13237+}
13238+
13239+
13240+static void signal_fifo_waiters(void)
13241+{
13242+ if (atomic_read(&rfbi.cmd_fifo_full) > 0) {
13243+ /* DSSDBG("SIGNALING: Fifo not full for waiter!\n"); */
13244+ complete(&rfbi.cmd_done);
13245+ atomic_dec(&rfbi.cmd_fifo_full);
13246+ }
13247+}
13248+
13249+/* returns 1 for async op, and 0 for sync op */
13250+static int do_update(struct omap_display *display, struct update_region *upd)
13251+{
13252+ u16 x = upd->x;
13253+ u16 y = upd->y;
13254+ u16 w = upd->w;
13255+ u16 h = upd->h;
13256+
13257+ perf_mark_setup();
13258+
13259+ if (display->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
13260+ /*display->ctrl->enable_te(display, 1); */
13261+ dispc_setup_partial_planes(display, &x, &y, &w, &h);
13262+ }
13263+
13264+#ifdef MEASURE_PERF
13265+ rfbi.perf_bytes = w * h * 2; /* XXX always 16bit */
13266+#endif
13267+
13268+ display->ctrl->setup_update(display, x, y, w, h);
13269+
13270+ if (display->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
13271+ rfbi_transfer_area(w, h, NULL, NULL);
13272+ return 1;
13273+ } else {
13274+ struct omap_overlay *ovl;
13275+ void __iomem *addr;
13276+ int scr_width;
13277+
13278+ ovl = display->manager->overlays[0];
13279+ scr_width = ovl->info.screen_width;
13280+ addr = ovl->info.vaddr;
13281+
13282+ omap_rfbi_write_pixels(addr, scr_width, x, y, w, h);
13283+
13284+ perf_show("L4");
13285+
13286+ return 0;
13287+ }
13288+}
13289+
13290+static void process_cmd_fifo(void)
13291+{
13292+ int len;
13293+ struct update_param p;
13294+ struct omap_display *display;
13295+ unsigned long flags;
13296+
13297+ if (atomic_inc_return(&rfbi.cmd_pending) != 1)
13298+ return;
13299+
13300+ while (true) {
13301+ spin_lock_irqsave(rfbi.cmd_fifo->lock, flags);
13302+
13303+ len = __kfifo_get(rfbi.cmd_fifo, (unsigned char *)&p,
13304+ sizeof(struct update_param));
13305+ if (len == 0) {
13306+ DSSDBG("nothing more in fifo\n");
13307+ atomic_set(&rfbi.cmd_pending, 0);
13308+ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
13309+ break;
13310+ }
13311+
13312+ /* DSSDBG("fifo full %d\n", rfbi.cmd_fifo_full.counter);*/
13313+
13314+ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
13315+
13316+ BUG_ON(len != sizeof(struct update_param));
13317+ BUG_ON(p.rfbi_module > 1);
13318+
13319+ display = rfbi.display[p.rfbi_module];
13320+
13321+ if (p.cmd == RFBI_CMD_UPDATE) {
13322+ if (do_update(display, &p.par.r))
13323+ break; /* async op */
13324+ } else if (p.cmd == RFBI_CMD_SYNC) {
13325+ DSSDBG("Signaling SYNC done!\n");
13326+ complete(p.par.sync);
13327+ } else
13328+ BUG();
13329+ }
13330+
13331+ signal_fifo_waiters();
13332+}
13333+
13334+static void rfbi_push_cmd(struct update_param *p)
13335+{
13336+ int ret;
13337+
13338+ while (1) {
13339+ unsigned long flags;
13340+ int available;
13341+
13342+ spin_lock_irqsave(rfbi.cmd_fifo->lock, flags);
13343+ available = RFBI_CMD_FIFO_LEN_BYTES -
13344+ __kfifo_len(rfbi.cmd_fifo);
13345+
13346+/* DSSDBG("%d bytes left in fifo\n", available); */
13347+ if (available < sizeof(struct update_param)) {
13348+ DSSDBG("Going to wait because FIFO FULL..\n");
13349+ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
13350+ atomic_inc(&rfbi.cmd_fifo_full);
13351+ wait_for_completion(&rfbi.cmd_done);
13352+ /*DSSDBG("Woke up because fifo not full anymore\n");*/
13353+ continue;
13354+ }
13355+
13356+ ret = __kfifo_put(rfbi.cmd_fifo, (unsigned char *)p,
13357+ sizeof(struct update_param));
13358+/* DSSDBG("pushed %d bytes\n", ret);*/
13359+
13360+ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
13361+
13362+ BUG_ON(ret != sizeof(struct update_param));
13363+
13364+ break;
13365+ }
13366+}
13367+
13368+static void rfbi_push_update(int rfbi_module, int x, int y, int w, int h)
13369+{
13370+ struct update_param p;
13371+
13372+ p.rfbi_module = rfbi_module;
13373+ p.cmd = RFBI_CMD_UPDATE;
13374+
13375+ p.par.r.x = x;
13376+ p.par.r.y = y;
13377+ p.par.r.w = w;
13378+ p.par.r.h = h;
13379+
13380+ DSSDBG("RFBI pushed %d,%d %dx%d\n", x, y, w, h);
13381+
13382+ rfbi_push_cmd(&p);
13383+
13384+ process_cmd_fifo();
13385+}
13386+
13387+static void rfbi_push_sync(int rfbi_module, struct completion *sync_comp)
13388+{
13389+ struct update_param p;
13390+
13391+ p.rfbi_module = rfbi_module;
13392+ p.cmd = RFBI_CMD_SYNC;
13393+ p.par.sync = sync_comp;
13394+
13395+ rfbi_push_cmd(&p);
13396+
13397+ DSSDBG("RFBI sync pushed to cmd fifo\n");
13398+
13399+ process_cmd_fifo();
13400+}
13401+
13402+void rfbi_dump_regs(struct seq_file *s)
13403+{
13404+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
13405+
13406+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
13407+
13408+ DUMPREG(RFBI_REVISION);
13409+ DUMPREG(RFBI_SYSCONFIG);
13410+ DUMPREG(RFBI_SYSSTATUS);
13411+ DUMPREG(RFBI_CONTROL);
13412+ DUMPREG(RFBI_PIXEL_CNT);
13413+ DUMPREG(RFBI_LINE_NUMBER);
13414+ DUMPREG(RFBI_CMD);
13415+ DUMPREG(RFBI_PARAM);
13416+ DUMPREG(RFBI_DATA);
13417+ DUMPREG(RFBI_READ);
13418+ DUMPREG(RFBI_STATUS);
13419+
13420+ DUMPREG(RFBI_CONFIG(0));
13421+ DUMPREG(RFBI_ONOFF_TIME(0));
13422+ DUMPREG(RFBI_CYCLE_TIME(0));
13423+ DUMPREG(RFBI_DATA_CYCLE1(0));
13424+ DUMPREG(RFBI_DATA_CYCLE2(0));
13425+ DUMPREG(RFBI_DATA_CYCLE3(0));
13426+
13427+ DUMPREG(RFBI_CONFIG(1));
13428+ DUMPREG(RFBI_ONOFF_TIME(1));
13429+ DUMPREG(RFBI_CYCLE_TIME(1));
13430+ DUMPREG(RFBI_DATA_CYCLE1(1));
13431+ DUMPREG(RFBI_DATA_CYCLE2(1));
13432+ DUMPREG(RFBI_DATA_CYCLE3(1));
13433+
13434+ DUMPREG(RFBI_VSYNC_WIDTH);
13435+ DUMPREG(RFBI_HSYNC_WIDTH);
13436+
13437+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
13438+#undef DUMPREG
13439+}
13440+
13441+int rfbi_init(void)
13442+{
13443+ u32 rev;
13444+ u32 l;
13445+
13446+ spin_lock_init(&rfbi.cmd_lock);
13447+ rfbi.cmd_fifo = kfifo_alloc(RFBI_CMD_FIFO_LEN_BYTES, GFP_KERNEL,
13448+ &rfbi.cmd_lock);
13449+ if (IS_ERR(rfbi.cmd_fifo))
13450+ return -ENOMEM;
13451+
13452+ init_completion(&rfbi.cmd_done);
13453+ atomic_set(&rfbi.cmd_fifo_full, 0);
13454+ atomic_set(&rfbi.cmd_pending, 0);
13455+
13456+ rfbi.base = ioremap(RFBI_BASE, SZ_256);
13457+ if (!rfbi.base) {
13458+ DSSERR("can't ioremap RFBI\n");
13459+ return -ENOMEM;
13460+ }
13461+
13462+ rfbi_enable_clocks(1);
13463+
13464+ msleep(10);
13465+
13466+ rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
13467+
13468+ /* Enable autoidle and smart-idle */
13469+ l = rfbi_read_reg(RFBI_SYSCONFIG);
13470+ l |= (1 << 0) | (2 << 3);
13471+ rfbi_write_reg(RFBI_SYSCONFIG, l);
13472+
13473+ rev = rfbi_read_reg(RFBI_REVISION);
13474+ printk(KERN_INFO "OMAP RFBI rev %d.%d\n",
13475+ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
13476+
13477+ rfbi_enable_clocks(0);
13478+
13479+ return 0;
13480+}
13481+
13482+void rfbi_exit(void)
13483+{
13484+ DSSDBG("rfbi_exit\n");
13485+
13486+ kfifo_free(rfbi.cmd_fifo);
13487+
13488+ iounmap(rfbi.base);
13489+}
13490+
13491+/* struct omap_display support */
13492+static int rfbi_display_update(struct omap_display *display,
13493+ u16 x, u16 y, u16 w, u16 h)
13494+{
13495+ int rfbi_module;
13496+
13497+ if (w == 0 || h == 0)
13498+ return 0;
13499+
13500+ rfbi_module = rfbi_find_display(display);
13501+
13502+ rfbi_push_update(rfbi_module, x, y, w, h);
13503+
13504+ return 0;
13505+}
13506+
13507+static int rfbi_display_sync(struct omap_display *display)
13508+{
13509+ struct completion sync_comp;
13510+ int rfbi_module;
13511+
13512+ rfbi_module = rfbi_find_display(display);
13513+
13514+ init_completion(&sync_comp);
13515+ rfbi_push_sync(rfbi_module, &sync_comp);
13516+ DSSDBG("Waiting for SYNC to happen...\n");
13517+ wait_for_completion(&sync_comp);
13518+ DSSDBG("Released from SYNC\n");
13519+ return 0;
13520+}
13521+
13522+static int rfbi_display_enable_te(struct omap_display *display, bool enable)
13523+{
13524+ display->ctrl->enable_te(display, enable);
13525+ return 0;
13526+}
13527+
13528+static int rfbi_display_enable(struct omap_display *display)
13529+{
13530+ int r;
13531+
13532+ BUG_ON(display->panel == NULL || display->ctrl == NULL);
13533+
13534+ r = omap_dispc_register_isr(framedone_callback, NULL,
13535+ DISPC_IRQ_FRAMEDONE);
13536+ if (r) {
13537+ DSSERR("can't get FRAMEDONE irq\n");
13538+ return r;
13539+ }
13540+
13541+ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
13542+
13543+ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_RFBI);
13544+
13545+ dispc_set_tft_data_lines(display->ctrl->pixel_size);
13546+
13547+ rfbi_configure(display->hw_config.u.rfbi.channel,
13548+ display->ctrl->pixel_size,
13549+ display->hw_config.u.rfbi.data_lines);
13550+
13551+ rfbi_set_timings(display->hw_config.u.rfbi.channel,
13552+ &display->ctrl->timings);
13553+
13554+
13555+ if (display->ctrl && display->ctrl->enable) {
13556+ r = display->ctrl->enable(display);
13557+ if (r)
13558+ goto err;
13559+ }
13560+
13561+ if (display->panel && display->panel->enable) {
13562+ r = display->panel->enable(display);
13563+ if (r)
13564+ goto err;
13565+ }
13566+
13567+ return 0;
13568+err:
13569+ return -ENODEV;
13570+}
13571+
13572+static void rfbi_display_disable(struct omap_display *display)
13573+{
13574+ display->ctrl->disable(display);
13575+ omap_dispc_unregister_isr(framedone_callback, NULL,
13576+ DISPC_IRQ_FRAMEDONE);
13577+}
13578+
13579+void rfbi_init_display(struct omap_display *display)
13580+{
13581+ display->enable = rfbi_display_enable;
13582+ display->disable = rfbi_display_disable;
13583+ display->update = rfbi_display_update;
13584+ display->sync = rfbi_display_sync;
13585+ display->enable_te = rfbi_display_enable_te;
13586+
13587+ rfbi.display[display->hw_config.u.rfbi.channel] = display;
13588+
13589+ display->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
13590+}
13591diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
13592new file mode 100644
13593index 0000000..fbff2b2
13594--- /dev/null
13595+++ b/drivers/video/omap2/dss/sdi.c
13596@@ -0,0 +1,245 @@
13597+/*
13598+ * linux/drivers/video/omap2/dss/sdi.c
13599+ *
13600+ * Copyright (C) 2009 Nokia Corporation
13601+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
13602+ *
13603+ * This program is free software; you can redistribute it and/or modify it
13604+ * under the terms of the GNU General Public License version 2 as published by
13605+ * the Free Software Foundation.
13606+ *
13607+ * This program is distributed in the hope that it will be useful, but WITHOUT
13608+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13609+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13610+ * more details.
13611+ *
13612+ * You should have received a copy of the GNU General Public License along with
13613+ * this program. If not, see <http://www.gnu.org/licenses/>.
13614+ */
13615+
13616+#define DSS_SUBSYS_NAME "SDI"
13617+
13618+#include <linux/kernel.h>
13619+#include <linux/clk.h>
13620+#include <linux/delay.h>
13621+#include <linux/err.h>
13622+
13623+#include <mach/board.h>
13624+#include <mach/display.h>
13625+#include "dss.h"
13626+
13627+
13628+static struct {
13629+ bool skip_init;
13630+ bool update_enabled;
13631+} sdi;
13632+
13633+static void sdi_basic_init(void)
13634+{
13635+ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
13636+
13637+ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
13638+ dispc_set_tft_data_lines(24);
13639+ dispc_lcd_enable_signal_polarity(1);
13640+}
13641+
13642+static int sdi_display_enable(struct omap_display *display)
13643+{
13644+ struct dispc_clock_info cinfo;
13645+ u16 lck_div, pck_div;
13646+ unsigned long fck;
13647+ struct omap_panel *panel = display->panel;
13648+ unsigned long pck;
13649+ int r;
13650+
13651+ if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
13652+ DSSERR("display already enabled\n");
13653+ return -EINVAL;
13654+ }
13655+
13656+ /* In case of skip_init sdi_init has already enabled the clocks */
13657+ if (!sdi.skip_init)
13658+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
13659+
13660+ sdi_basic_init();
13661+
13662+ /* 15.5.9.1.2 */
13663+ panel->config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
13664+
13665+ dispc_set_pol_freq(panel);
13666+
13667+ if (!sdi.skip_init)
13668+ r = dispc_calc_clock_div(1, panel->timings.pixel_clock * 1000,
13669+ &cinfo);
13670+ else
13671+ r = dispc_get_clock_div(&cinfo);
13672+
13673+ if (r)
13674+ goto err0;
13675+
13676+ fck = cinfo.fck;
13677+ lck_div = cinfo.lck_div;
13678+ pck_div = cinfo.pck_div;
13679+
13680+ pck = fck / lck_div / pck_div / 1000;
13681+
13682+ if (pck != panel->timings.pixel_clock) {
13683+ DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
13684+ "got %lu kHz\n",
13685+ panel->timings.pixel_clock, pck);
13686+
13687+ panel->timings.pixel_clock = pck;
13688+ }
13689+
13690+
13691+ dispc_set_lcd_timings(&panel->timings);
13692+
13693+ r = dispc_set_clock_div(&cinfo);
13694+ if (r)
13695+ goto err1;
13696+
13697+ if (!sdi.skip_init) {
13698+ dss_sdi_init(display->hw_config.u.sdi.datapairs);
13699+ dss_sdi_enable();
13700+ mdelay(2);
13701+ }
13702+
13703+ dispc_enable_lcd_out(1);
13704+
13705+ r = panel->enable(display);
13706+ if (r)
13707+ goto err2;
13708+
13709+ display->state = OMAP_DSS_DISPLAY_ACTIVE;
13710+
13711+ sdi.skip_init = 0;
13712+
13713+ return 0;
13714+err2:
13715+ dispc_enable_lcd_out(0);
13716+err1:
13717+err0:
13718+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
13719+ return r;
13720+}
13721+
13722+static int sdi_display_resume(struct omap_display *display);
13723+
13724+static void sdi_display_disable(struct omap_display *display)
13725+{
13726+ if (display->state == OMAP_DSS_DISPLAY_DISABLED)
13727+ return;
13728+
13729+ if (display->state == OMAP_DSS_DISPLAY_SUSPENDED)
13730+ sdi_display_resume(display);
13731+
13732+ display->panel->disable(display);
13733+
13734+ dispc_enable_lcd_out(0);
13735+
13736+ dss_sdi_disable();
13737+
13738+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
13739+
13740+ display->state = OMAP_DSS_DISPLAY_DISABLED;
13741+}
13742+
13743+static int sdi_display_suspend(struct omap_display *display)
13744+{
13745+ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
13746+ return -EINVAL;
13747+
13748+ if (display->panel->suspend)
13749+ display->panel->suspend(display);
13750+
13751+ dispc_enable_lcd_out(0);
13752+
13753+ dss_sdi_disable();
13754+
13755+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
13756+
13757+ display->state = OMAP_DSS_DISPLAY_SUSPENDED;
13758+
13759+ return 0;
13760+}
13761+
13762+static int sdi_display_resume(struct omap_display *display)
13763+{
13764+ if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
13765+ return -EINVAL;
13766+
13767+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
13768+
13769+ dss_sdi_enable();
13770+ mdelay(2);
13771+
13772+ dispc_enable_lcd_out(1);
13773+
13774+ if (display->panel->resume)
13775+ display->panel->resume(display);
13776+
13777+ display->state = OMAP_DSS_DISPLAY_ACTIVE;
13778+
13779+ return 0;
13780+}
13781+
13782+static int sdi_display_set_update_mode(struct omap_display *display,
13783+ enum omap_dss_update_mode mode)
13784+{
13785+ if (mode == OMAP_DSS_UPDATE_MANUAL)
13786+ return -EINVAL;
13787+
13788+ if (mode == OMAP_DSS_UPDATE_DISABLED) {
13789+ dispc_enable_lcd_out(0);
13790+ sdi.update_enabled = 0;
13791+ } else {
13792+ dispc_enable_lcd_out(1);
13793+ sdi.update_enabled = 1;
13794+ }
13795+
13796+ return 0;
13797+}
13798+
13799+static enum omap_dss_update_mode sdi_display_get_update_mode(
13800+ struct omap_display *display)
13801+{
13802+ return sdi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
13803+ OMAP_DSS_UPDATE_DISABLED;
13804+}
13805+
13806+static void sdi_get_timings(struct omap_display *display,
13807+ struct omap_video_timings *timings)
13808+{
13809+ *timings = display->panel->timings;
13810+}
13811+
13812+void sdi_init_display(struct omap_display *display)
13813+{
13814+ DSSDBG("SDI init\n");
13815+
13816+ display->enable = sdi_display_enable;
13817+ display->disable = sdi_display_disable;
13818+ display->suspend = sdi_display_suspend;
13819+ display->resume = sdi_display_resume;
13820+ display->set_update_mode = sdi_display_set_update_mode;
13821+ display->get_update_mode = sdi_display_get_update_mode;
13822+ display->get_timings = sdi_get_timings;
13823+}
13824+
13825+int sdi_init(bool skip_init)
13826+{
13827+ /* we store this for first display enable, then clear it */
13828+ sdi.skip_init = skip_init;
13829+
13830+ /*
13831+ * Enable clocks already here, otherwise there would be a toggle
13832+ * of them until sdi_display_enable is called.
13833+ */
13834+ if (skip_init)
13835+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
13836+ return 0;
13837+}
13838+
13839+void sdi_exit(void)
13840+{
13841+}
13842diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
13843new file mode 100644
13844index 0000000..aceed9f
13845--- /dev/null
13846+++ b/drivers/video/omap2/dss/venc.c
13847@@ -0,0 +1,600 @@
13848+/*
13849+ * linux/drivers/video/omap2/dss/venc.c
13850+ *
13851+ * Copyright (C) 2009 Nokia Corporation
13852+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
13853+ *
13854+ * VENC settings from TI's DSS driver
13855+ *
13856+ * This program is free software; you can redistribute it and/or modify it
13857+ * under the terms of the GNU General Public License version 2 as published by
13858+ * the Free Software Foundation.
13859+ *
13860+ * This program is distributed in the hope that it will be useful, but WITHOUT
13861+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13862+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13863+ * more details.
13864+ *
13865+ * You should have received a copy of the GNU General Public License along with
13866+ * this program. If not, see <http://www.gnu.org/licenses/>.
13867+ */
13868+
13869+#define DSS_SUBSYS_NAME "VENC"
13870+
13871+#include <linux/kernel.h>
13872+#include <linux/module.h>
13873+#include <linux/clk.h>
13874+#include <linux/err.h>
13875+#include <linux/io.h>
13876+#include <linux/mutex.h>
13877+#include <linux/completion.h>
13878+#include <linux/delay.h>
13879+#include <linux/string.h>
13880+
13881+#include <mach/display.h>
13882+#include <mach/cpu.h>
13883+
13884+#include "dss.h"
13885+
13886+#define VENC_BASE 0x48050C00
13887+
13888+/* Venc registers */
13889+#define VENC_REV_ID 0x00
13890+#define VENC_STATUS 0x04
13891+#define VENC_F_CONTROL 0x08
13892+#define VENC_VIDOUT_CTRL 0x10
13893+#define VENC_SYNC_CTRL 0x14
13894+#define VENC_LLEN 0x1C
13895+#define VENC_FLENS 0x20
13896+#define VENC_HFLTR_CTRL 0x24
13897+#define VENC_CC_CARR_WSS_CARR 0x28
13898+#define VENC_C_PHASE 0x2C
13899+#define VENC_GAIN_U 0x30
13900+#define VENC_GAIN_V 0x34
13901+#define VENC_GAIN_Y 0x38
13902+#define VENC_BLACK_LEVEL 0x3C
13903+#define VENC_BLANK_LEVEL 0x40
13904+#define VENC_X_COLOR 0x44
13905+#define VENC_M_CONTROL 0x48
13906+#define VENC_BSTAMP_WSS_DATA 0x4C
13907+#define VENC_S_CARR 0x50
13908+#define VENC_LINE21 0x54
13909+#define VENC_LN_SEL 0x58
13910+#define VENC_L21__WC_CTL 0x5C
13911+#define VENC_HTRIGGER_VTRIGGER 0x60
13912+#define VENC_SAVID__EAVID 0x64
13913+#define VENC_FLEN__FAL 0x68
13914+#define VENC_LAL__PHASE_RESET 0x6C
13915+#define VENC_HS_INT_START_STOP_X 0x70
13916+#define VENC_HS_EXT_START_STOP_X 0x74
13917+#define VENC_VS_INT_START_X 0x78
13918+#define VENC_VS_INT_STOP_X__VS_INT_START_Y 0x7C
13919+#define VENC_VS_INT_STOP_Y__VS_EXT_START_X 0x80
13920+#define VENC_VS_EXT_STOP_X__VS_EXT_START_Y 0x84
13921+#define VENC_VS_EXT_STOP_Y 0x88
13922+#define VENC_AVID_START_STOP_X 0x90
13923+#define VENC_AVID_START_STOP_Y 0x94
13924+#define VENC_FID_INT_START_X__FID_INT_START_Y 0xA0
13925+#define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X 0xA4
13926+#define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y 0xA8
13927+#define VENC_TVDETGP_INT_START_STOP_X 0xB0
13928+#define VENC_TVDETGP_INT_START_STOP_Y 0xB4
13929+#define VENC_GEN_CTRL 0xB8
13930+#define VENC_OUTPUT_CONTROL 0xC4
13931+#define VENC_DAC_B__DAC_C 0xC8
13932+
13933+struct venc_config {
13934+ u32 f_control;
13935+ u32 vidout_ctrl;
13936+ u32 sync_ctrl;
13937+ u32 llen;
13938+ u32 flens;
13939+ u32 hfltr_ctrl;
13940+ u32 cc_carr_wss_carr;
13941+ u32 c_phase;
13942+ u32 gain_u;
13943+ u32 gain_v;
13944+ u32 gain_y;
13945+ u32 black_level;
13946+ u32 blank_level;
13947+ u32 x_color;
13948+ u32 m_control;
13949+ u32 bstamp_wss_data;
13950+ u32 s_carr;
13951+ u32 line21;
13952+ u32 ln_sel;
13953+ u32 l21__wc_ctl;
13954+ u32 htrigger_vtrigger;
13955+ u32 savid__eavid;
13956+ u32 flen__fal;
13957+ u32 lal__phase_reset;
13958+ u32 hs_int_start_stop_x;
13959+ u32 hs_ext_start_stop_x;
13960+ u32 vs_int_start_x;
13961+ u32 vs_int_stop_x__vs_int_start_y;
13962+ u32 vs_int_stop_y__vs_ext_start_x;
13963+ u32 vs_ext_stop_x__vs_ext_start_y;
13964+ u32 vs_ext_stop_y;
13965+ u32 avid_start_stop_x;
13966+ u32 avid_start_stop_y;
13967+ u32 fid_int_start_x__fid_int_start_y;
13968+ u32 fid_int_offset_y__fid_ext_start_x;
13969+ u32 fid_ext_start_y__fid_ext_offset_y;
13970+ u32 tvdetgp_int_start_stop_x;
13971+ u32 tvdetgp_int_start_stop_y;
13972+ u32 gen_ctrl;
13973+};
13974+
13975+/* from TRM */
13976+static const struct venc_config venc_config_pal_trm = {
13977+ .f_control = 0,
13978+ .vidout_ctrl = 1,
13979+ .sync_ctrl = 0x40,
13980+ .llen = 0x35F, /* 863 */
13981+ .flens = 0x270, /* 624 */
13982+ .hfltr_ctrl = 0,
13983+ .cc_carr_wss_carr = 0x2F7225ED,
13984+ .c_phase = 0,
13985+ .gain_u = 0x111,
13986+ .gain_v = 0x181,
13987+ .gain_y = 0x140,
13988+ .black_level = 0x3B,
13989+ .blank_level = 0x3B,
13990+ .x_color = 0x7,
13991+ .m_control = 0x2,
13992+ .bstamp_wss_data = 0x3F,
13993+ .s_carr = 0x2A098ACB,
13994+ .line21 = 0,
13995+ .ln_sel = 0x01290015,
13996+ .l21__wc_ctl = 0x0000F603,
13997+ .htrigger_vtrigger = 0,
13998+
13999+ .savid__eavid = 0x06A70108,
14000+ .flen__fal = 0x00180270,
14001+ .lal__phase_reset = 0x00040135,
14002+ .hs_int_start_stop_x = 0x00880358,
14003+ .hs_ext_start_stop_x = 0x000F035F,
14004+ .vs_int_start_x = 0x01A70000,
14005+ .vs_int_stop_x__vs_int_start_y = 0x000001A7,
14006+ .vs_int_stop_y__vs_ext_start_x = 0x01AF0000,
14007+ .vs_ext_stop_x__vs_ext_start_y = 0x000101AF,
14008+ .vs_ext_stop_y = 0x00000025,
14009+ .avid_start_stop_x = 0x03530083,
14010+ .avid_start_stop_y = 0x026C002E,
14011+ .fid_int_start_x__fid_int_start_y = 0x0001008A,
14012+ .fid_int_offset_y__fid_ext_start_x = 0x002E0138,
14013+ .fid_ext_start_y__fid_ext_offset_y = 0x01380001,
14014+
14015+ .tvdetgp_int_start_stop_x = 0x00140001,
14016+ .tvdetgp_int_start_stop_y = 0x00010001,
14017+ .gen_ctrl = 0x00FF0000,
14018+};
14019+
14020+/* from TRM */
14021+static const struct venc_config venc_config_ntsc_trm = {
14022+ .f_control = 0,
14023+ .vidout_ctrl = 1,
14024+ .sync_ctrl = 0x8040,
14025+ .llen = 0x359,
14026+ .flens = 0x20C,
14027+ .hfltr_ctrl = 0,
14028+ .cc_carr_wss_carr = 0x043F2631,
14029+ .c_phase = 0,
14030+ .gain_u = 0x102,
14031+ .gain_v = 0x16C,
14032+ .gain_y = 0x12F,
14033+ .black_level = 0x43,
14034+ .blank_level = 0x38,
14035+ .x_color = 0x7,
14036+ .m_control = 0x1,
14037+ .bstamp_wss_data = 0x38,
14038+ .s_carr = 0x21F07C1F,
14039+ .line21 = 0,
14040+ .ln_sel = 0x01310011,
14041+ .l21__wc_ctl = 0x0000F003,
14042+ .htrigger_vtrigger = 0,
14043+
14044+ .savid__eavid = 0x069300F4,
14045+ .flen__fal = 0x0016020C,
14046+ .lal__phase_reset = 0x00060107,
14047+ .hs_int_start_stop_x = 0x008E0350,
14048+ .hs_ext_start_stop_x = 0x000F0359,
14049+ .vs_int_start_x = 0x01A00000,
14050+ .vs_int_stop_x__vs_int_start_y = 0x020701A0,
14051+ .vs_int_stop_y__vs_ext_start_x = 0x01AC0024,
14052+ .vs_ext_stop_x__vs_ext_start_y = 0x020D01AC,
14053+ .vs_ext_stop_y = 0x00000006,
14054+ .avid_start_stop_x = 0x03480078,
14055+ .avid_start_stop_y = 0x02060024,
14056+ .fid_int_start_x__fid_int_start_y = 0x0001008A,
14057+ .fid_int_offset_y__fid_ext_start_x = 0x01AC0106,
14058+ .fid_ext_start_y__fid_ext_offset_y = 0x01060006,
14059+
14060+ .tvdetgp_int_start_stop_x = 0x00140001,
14061+ .tvdetgp_int_start_stop_y = 0x00010001,
14062+ .gen_ctrl = 0x00F90000,
14063+};
14064+
14065+static const struct venc_config venc_config_pal_bdghi = {
14066+ .f_control = 0,
14067+ .vidout_ctrl = 0,
14068+ .sync_ctrl = 0,
14069+ .hfltr_ctrl = 0,
14070+ .x_color = 0,
14071+ .line21 = 0,
14072+ .ln_sel = 21,
14073+ .htrigger_vtrigger = 0,
14074+ .tvdetgp_int_start_stop_x = 0x00140001,
14075+ .tvdetgp_int_start_stop_y = 0x00010001,
14076+ .gen_ctrl = 0x00FB0000,
14077+
14078+ .llen = 864-1,
14079+ .flens = 625-1,
14080+ .cc_carr_wss_carr = 0x2F7625ED,
14081+ .c_phase = 0xDF,
14082+ .gain_u = 0x111,
14083+ .gain_v = 0x181,
14084+ .gain_y = 0x140,
14085+ .black_level = 0x3e,
14086+ .blank_level = 0x3e,
14087+ .m_control = 0<<2 | 1<<1,
14088+ .bstamp_wss_data = 0x42,
14089+ .s_carr = 0x2a098acb,
14090+ .l21__wc_ctl = 0<<13 | 0x16<<8 | 0<<0,
14091+ .savid__eavid = 0x06A70108,
14092+ .flen__fal = 23<<16 | 624<<0,
14093+ .lal__phase_reset = 2<<17 | 310<<0,
14094+ .hs_int_start_stop_x = 0x00920358,
14095+ .hs_ext_start_stop_x = 0x000F035F,
14096+ .vs_int_start_x = 0x1a7<<16,
14097+ .vs_int_stop_x__vs_int_start_y = 0x000601A7,
14098+ .vs_int_stop_y__vs_ext_start_x = 0x01AF0036,
14099+ .vs_ext_stop_x__vs_ext_start_y = 0x27101af,
14100+ .vs_ext_stop_y = 0x05,
14101+ .avid_start_stop_x = 0x03530082,
14102+ .avid_start_stop_y = 0x0270002E,
14103+ .fid_int_start_x__fid_int_start_y = 0x0005008A,
14104+ .fid_int_offset_y__fid_ext_start_x = 0x002E0138,
14105+ .fid_ext_start_y__fid_ext_offset_y = 0x01380005,
14106+};
14107+
14108+const struct omap_video_timings omap_dss_pal_timings = {
14109+ .x_res = 720,
14110+ .y_res = 574,
14111+ .pixel_clock = 26181,
14112+ .hsw = 32,
14113+ .hfp = 80,
14114+ .hbp = 48,
14115+ .vsw = 7,
14116+ .vfp = 3,
14117+ .vbp = 6,
14118+};
14119+EXPORT_SYMBOL(omap_dss_pal_timings);
14120+
14121+const struct omap_video_timings omap_dss_ntsc_timings = {
14122+ .x_res = 720,
14123+ .y_res = 482,
14124+ .pixel_clock = 22153,
14125+ .hsw = 32,
14126+ .hfp = 80,
14127+ .hbp = 48,
14128+ .vsw = 10,
14129+ .vfp = 3,
14130+ .vbp = 6,
14131+};
14132+EXPORT_SYMBOL(omap_dss_ntsc_timings);
14133+
14134+static struct {
14135+ void __iomem *base;
14136+ struct mutex venc_lock;
14137+} venc;
14138+
14139+static struct omap_panel venc_panel = {
14140+ .name = "tv-out",
14141+};
14142+
14143+static inline void venc_write_reg(int idx, u32 val)
14144+{
14145+ __raw_writel(val, venc.base + idx);
14146+}
14147+
14148+static inline u32 venc_read_reg(int idx)
14149+{
14150+ u32 l = __raw_readl(venc.base + idx);
14151+ return l;
14152+}
14153+
14154+static void venc_write_config(const struct venc_config *config)
14155+{
14156+ DSSDBG("write venc conf\n");
14157+
14158+ venc_write_reg(VENC_LLEN, config->llen);
14159+ venc_write_reg(VENC_FLENS, config->flens);
14160+ venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr);
14161+ venc_write_reg(VENC_C_PHASE, config->c_phase);
14162+ venc_write_reg(VENC_GAIN_U, config->gain_u);
14163+ venc_write_reg(VENC_GAIN_V, config->gain_v);
14164+ venc_write_reg(VENC_GAIN_Y, config->gain_y);
14165+ venc_write_reg(VENC_BLACK_LEVEL, config->black_level);
14166+ venc_write_reg(VENC_BLANK_LEVEL, config->blank_level);
14167+ venc_write_reg(VENC_M_CONTROL, config->m_control);
14168+ venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data);
14169+ venc_write_reg(VENC_S_CARR, config->s_carr);
14170+ venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl);
14171+ venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid);
14172+ venc_write_reg(VENC_FLEN__FAL, config->flen__fal);
14173+ venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset);
14174+ venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x);
14175+ venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x);
14176+ venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x);
14177+ venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y,
14178+ config->vs_int_stop_x__vs_int_start_y);
14179+ venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X,
14180+ config->vs_int_stop_y__vs_ext_start_x);
14181+ venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y,
14182+ config->vs_ext_stop_x__vs_ext_start_y);
14183+ venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y);
14184+ venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x);
14185+ venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y);
14186+ venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y,
14187+ config->fid_int_start_x__fid_int_start_y);
14188+ venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X,
14189+ config->fid_int_offset_y__fid_ext_start_x);
14190+ venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y,
14191+ config->fid_ext_start_y__fid_ext_offset_y);
14192+
14193+ venc_write_reg(VENC_DAC_B__DAC_C, venc_read_reg(VENC_DAC_B__DAC_C));
14194+ venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl);
14195+ venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl);
14196+ venc_write_reg(VENC_X_COLOR, config->x_color);
14197+ venc_write_reg(VENC_LINE21, config->line21);
14198+ venc_write_reg(VENC_LN_SEL, config->ln_sel);
14199+ venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger);
14200+ venc_write_reg(VENC_TVDETGP_INT_START_STOP_X,
14201+ config->tvdetgp_int_start_stop_x);
14202+ venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y,
14203+ config->tvdetgp_int_start_stop_y);
14204+ venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl);
14205+ venc_write_reg(VENC_F_CONTROL, config->f_control);
14206+ venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl);
14207+}
14208+
14209+static void venc_reset(void)
14210+{
14211+ int t = 1000;
14212+
14213+ venc_write_reg(VENC_F_CONTROL, 1<<8);
14214+ while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) {
14215+ if (--t == 0) {
14216+ DSSERR("Failed to reset venc\n");
14217+ return;
14218+ }
14219+ }
14220+
14221+ /* the magical sleep that makes things work */
14222+ msleep(20);
14223+}
14224+
14225+static void venc_enable_clocks(int enable)
14226+{
14227+ if (enable)
14228+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
14229+ DSS_CLK_96M);
14230+ else
14231+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
14232+ DSS_CLK_96M);
14233+}
14234+
14235+static const struct venc_config *venc_timings_to_config(
14236+ struct omap_video_timings *timings)
14237+{
14238+ if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
14239+ return &venc_config_pal_trm;
14240+
14241+ if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
14242+ return &venc_config_ntsc_trm;
14243+
14244+ BUG();
14245+}
14246+
14247+int venc_init(void)
14248+{
14249+ u8 rev_id;
14250+
14251+ mutex_init(&venc.venc_lock);
14252+
14253+ venc_panel.timings = omap_dss_pal_timings;
14254+
14255+ venc.base = ioremap(VENC_BASE, SZ_1K);
14256+ if (!venc.base) {
14257+ DSSERR("can't ioremap VENC\n");
14258+ return -ENOMEM;
14259+ }
14260+
14261+ venc_enable_clocks(1);
14262+
14263+ rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
14264+ printk(KERN_INFO "OMAP VENC rev %d\n", rev_id);
14265+
14266+ venc_enable_clocks(0);
14267+
14268+ return 0;
14269+}
14270+
14271+void venc_exit(void)
14272+{
14273+ iounmap(venc.base);
14274+}
14275+
14276+static void venc_power_on(struct omap_display *display)
14277+{
14278+ venc_enable_clocks(1);
14279+
14280+ venc_reset();
14281+ venc_write_config(venc_timings_to_config(&display->panel->timings));
14282+
14283+ dss_set_venc_output(display->hw_config.u.venc.type);
14284+ dss_set_dac_pwrdn_bgz(1);
14285+
14286+ if (display->hw_config.u.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE) {
14287+ if (cpu_is_omap24xx())
14288+ venc_write_reg(VENC_OUTPUT_CONTROL, 0x2);
14289+ else
14290+ venc_write_reg(VENC_OUTPUT_CONTROL, 0xa);
14291+ } else { /* S-Video */
14292+ venc_write_reg(VENC_OUTPUT_CONTROL, 0xd);
14293+ }
14294+
14295+ dispc_set_digit_size(display->panel->timings.x_res,
14296+ display->panel->timings.y_res/2);
14297+
14298+ if (display->hw_config.panel_enable)
14299+ display->hw_config.panel_enable(display);
14300+
14301+ dispc_enable_digit_out(1);
14302+}
14303+
14304+static void venc_power_off(struct omap_display *display)
14305+{
14306+ venc_write_reg(VENC_OUTPUT_CONTROL, 0);
14307+ dss_set_dac_pwrdn_bgz(0);
14308+
14309+ dispc_enable_digit_out(0);
14310+
14311+ if (display->hw_config.panel_disable)
14312+ display->hw_config.panel_disable(display);
14313+
14314+ venc_enable_clocks(0);
14315+}
14316+
14317+static int venc_enable_display(struct omap_display *display)
14318+{
14319+ int r = 0;
14320+
14321+ DSSDBG("venc_enable_display\n");
14322+
14323+ mutex_lock(&venc.venc_lock);
14324+
14325+ if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
14326+ r = -EINVAL;
14327+ goto err;
14328+ }
14329+
14330+ venc_power_on(display);
14331+
14332+ display->state = OMAP_DSS_DISPLAY_ACTIVE;
14333+err:
14334+ mutex_unlock(&venc.venc_lock);
14335+
14336+ return r;
14337+}
14338+
14339+static void venc_disable_display(struct omap_display *display)
14340+{
14341+ DSSDBG("venc_disable_display\n");
14342+
14343+ mutex_lock(&venc.venc_lock);
14344+
14345+ if (display->state == OMAP_DSS_DISPLAY_DISABLED)
14346+ goto end;
14347+
14348+ if (display->state == OMAP_DSS_DISPLAY_SUSPENDED) {
14349+ /* suspended is the same as disabled with venc */
14350+ display->state = OMAP_DSS_DISPLAY_DISABLED;
14351+ goto end;
14352+ }
14353+
14354+ venc_power_off(display);
14355+
14356+ display->state = OMAP_DSS_DISPLAY_DISABLED;
14357+end:
14358+ mutex_unlock(&venc.venc_lock);
14359+}
14360+
14361+static int venc_display_suspend(struct omap_display *display)
14362+{
14363+ int r = 0;
14364+
14365+ DSSDBG("venc_display_suspend\n");
14366+
14367+ mutex_lock(&venc.venc_lock);
14368+
14369+ if (display->state != OMAP_DSS_DISPLAY_ACTIVE) {
14370+ r = -EINVAL;
14371+ goto err;
14372+ }
14373+
14374+ venc_power_off(display);
14375+
14376+ display->state = OMAP_DSS_DISPLAY_SUSPENDED;
14377+err:
14378+ mutex_unlock(&venc.venc_lock);
14379+
14380+ return r;
14381+}
14382+
14383+static int venc_display_resume(struct omap_display *display)
14384+{
14385+ int r = 0;
14386+
14387+ DSSDBG("venc_display_resume\n");
14388+
14389+ mutex_lock(&venc.venc_lock);
14390+
14391+ if (display->state != OMAP_DSS_DISPLAY_SUSPENDED) {
14392+ r = -EINVAL;
14393+ goto err;
14394+ }
14395+
14396+ venc_power_on(display);
14397+
14398+ display->state = OMAP_DSS_DISPLAY_ACTIVE;
14399+err:
14400+ mutex_unlock(&venc.venc_lock);
14401+
14402+ return r;
14403+}
14404+
14405+static void venc_get_timings(struct omap_display *display,
14406+ struct omap_video_timings *timings)
14407+{
14408+ *timings = venc_panel.timings;
14409+}
14410+
14411+static void venc_set_timings(struct omap_display *display,
14412+ struct omap_video_timings *timings)
14413+{
14414+ DSSDBG("venc_set_timings\n");
14415+ display->panel->timings = *timings;
14416+ if (display->state == OMAP_DSS_DISPLAY_ACTIVE) {
14417+ /* turn the venc off and on to get new timings to use */
14418+ venc_disable_display(display);
14419+ venc_enable_display(display);
14420+ }
14421+}
14422+
14423+static int venc_check_timings(struct omap_display *display,
14424+ struct omap_video_timings *timings)
14425+{
14426+ DSSDBG("venc_check_timings\n");
14427+
14428+ if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
14429+ return 0;
14430+
14431+ if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
14432+ return 0;
14433+
14434+ return -EINVAL;
14435+}
14436+
14437+void venc_init_display(struct omap_display *display)
14438+{
14439+ display->panel = &venc_panel;
14440+ display->enable = venc_enable_display;
14441+ display->disable = venc_disable_display;
14442+ display->suspend = venc_display_suspend;
14443+ display->resume = venc_display_resume;
14444+ display->get_timings = venc_get_timings;
14445+ display->set_timings = venc_set_timings;
14446+ display->check_timings = venc_check_timings;
14447+}
14448--
144491.5.6.5
14450