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:
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