Root/target/linux/omap35xx/patches-2.6.32/001-DSS2.patch

1--- /dev/null
2+++ b/Documentation/arm/OMAP/DSS
3@@ -0,0 +1,317 @@
4+OMAP2/3 Display Subsystem
5+-------------------------
6+
7+This is an almost total rewrite of the OMAP FB driver in drivers/video/omap
8+(let's call it DSS1). The main differences between DSS1 and DSS2 are DSI,
9+TV-out and multiple display support, but there are lots of small improvements
10+also.
11+
12+The DSS2 driver (omapdss module) is in arch/arm/plat-omap/dss/, and the FB,
13+panel and controller drivers are in drivers/video/omap2/. DSS1 and DSS2 live
14+currently side by side, you can choose which one to use.
15+
16+Features
17+--------
18+
19+Working and tested features include:
20+
21+- MIPI DPI (parallel) output
22+- MIPI DSI output in command mode
23+- MIPI DBI (RFBI) output
24+- SDI output
25+- TV output
26+- All pieces can be compiled as a module or inside kernel
27+- Use DISPC to update any of the outputs
28+- Use CPU to update RFBI or DSI output
29+- OMAP DISPC planes
30+- RGB16, RGB24 packed, RGB24 unpacked
31+- YUV2, UYVY
32+- Scaling
33+- Adjusting DSS FCK to find a good pixel clock
34+- Use DSI DPLL to create DSS FCK
35+
36+Tested boards include:
37+- OMAP3 SDP board
38+- Beagle board
39+- N810
40+
41+omapdss driver
42+--------------
43+
44+The DSS driver does not itself have any support for Linux framebuffer, V4L or
45+such like the current ones, but it has an internal kernel API that upper level
46+drivers can use.
47+
48+The DSS driver models OMAP's overlays, overlay managers and displays in a
49+flexible way to enable non-common multi-display configuration. In addition to
50+modelling the hardware overlays, omapdss supports virtual overlays and overlay
51+managers. These can be used when updating a display with CPU or system DMA.
52+
53+Panel and controller drivers
54+----------------------------
55+
56+The drivers implement panel or controller specific functionality and are not
57+usually visible to users except through omapfb driver. They register
58+themselves to the DSS driver.
59+
60+omapfb driver
61+-------------
62+
63+The omapfb driver implements arbitrary number of standard linux framebuffers.
64+These framebuffers can be routed flexibly to any overlays, thus allowing very
65+dynamic display architecture.
66+
67+The driver exports some omapfb specific ioctls, which are compatible with the
68+ioctls in the old driver.
69+
70+The rest of the non standard features are exported via sysfs. Whether the final
71+implementation will use sysfs, or ioctls, is still open.
72+
73+V4L2 drivers
74+------------
75+
76+V4L2 is being implemented in TI.
77+
78+From omapdss point of view the V4L2 drivers should be similar to framebuffer
79+driver.
80+
81+Architecture
82+--------------------
83+
84+Some clarification what the different components do:
85+
86+ - Framebuffer is a memory area inside OMAP's SRAM/SDRAM that contains the
87+ pixel data for the image. Framebuffer has width and height and color
88+ depth.
89+ - Overlay defines where the pixels are read from and where they go on the
90+ screen. The overlay may be smaller than framebuffer, thus displaying only
91+ part of the framebuffer. The position of the overlay may be changed if
92+ the overlay is smaller than the display.
93+ - Overlay manager combines the overlays in to one image and feeds them to
94+ display.
95+ - Display is the actual physical display device.
96+
97+A framebuffer can be connected to multiple overlays to show the same pixel data
98+on all of the overlays. Note that in this case the overlay input sizes must be
99+the same, but, in case of video overlays, the output size can be different. Any
100+framebuffer can be connected to any overlay.
101+
102+An overlay can be connected to one overlay manager. Also DISPC overlays can be
103+connected only to DISPC overlay managers, and virtual overlays can be only
104+connected to virtual overlays.
105+
106+An overlay manager can be connected to one display. There are certain
107+restrictions which kinds of displays an overlay manager can be connected:
108+
109+ - DISPC TV overlay manager can be only connected to TV display.
110+ - Virtual overlay managers can only be connected to DBI or DSI displays.
111+ - DISPC LCD overlay manager can be connected to all displays, except TV
112+ display.
113+
114+Sysfs
115+-----
116+The sysfs interface is mainly used for testing. I don't think sysfs
117+interface is the best for this in the final version, but I don't quite know
118+what would be the best interfaces for these things.
119+
120+The sysfs interface is divided to two parts: DSS and FB.
121+
122+/sys/class/graphics/fb? directory:
123+mirror 0=off, 1=on
124+rotate Rotation 0-3 for 0, 90, 180, 270 degrees
125+rotate_type 0 = DMA rotation, 1 = VRFB rotation
126+overlays List of overlay numbers to which framebuffer pixels go
127+phys_addr Physical address of the framebuffer
128+virt_addr Virtual address of the framebuffer
129+size Size of the framebuffer
130+
131+/sys/devices/platform/omapdss/overlay? directory:
132+enabled 0=off, 1=on
133+input_size width,height (ie. the framebuffer size)
134+manager Destination overlay manager name
135+name
136+output_size width,height
137+position x,y
138+screen_width width
139+global_alpha global alpha 0-255 0=transparent 255=opaque
140+
141+/sys/devices/platform/omapdss/manager? directory:
142+display Destination display
143+name
144+alpha_blending_enabled 0=off, 1=on
145+trans_key_enabled 0=off, 1=on
146+trans_key_type gfx-destination, video-source
147+trans_key_value transparency color key (RGB24)
148+default_color default background color (RGB24)
149+
150+/sys/devices/platform/omapdss/display? directory:
151+ctrl_name Controller name
152+mirror 0=off, 1=on
153+update_mode 0=off, 1=auto, 2=manual
154+enabled 0=off, 1=on
155+name
156+rotate Rotation 0-3 for 0, 90, 180, 270 degrees
157+timings Display timings (pixclock,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw)
158+ When writing, two special timings are accepted for tv-out:
159+ "pal" and "ntsc"
160+panel_name
161+tear_elim Tearing elimination 0=off, 1=on
162+
163+There are also some debugfs files at <debugfs>/omapdss/ which show information
164+about clocks and registers.
165+
166+Examples
167+--------
168+
169+The following definitions have been made for the examples below:
170+
171+ovl0=/sys/devices/platform/omapdss/overlay0
172+ovl1=/sys/devices/platform/omapdss/overlay1
173+ovl2=/sys/devices/platform/omapdss/overlay2
174+
175+mgr0=/sys/devices/platform/omapdss/manager0
176+mgr1=/sys/devices/platform/omapdss/manager1
177+
178+lcd=/sys/devices/platform/omapdss/display0
179+dvi=/sys/devices/platform/omapdss/display1
180+tv=/sys/devices/platform/omapdss/display2
181+
182+fb0=/sys/class/graphics/fb0
183+fb1=/sys/class/graphics/fb1
184+fb2=/sys/class/graphics/fb2
185+
186+Default setup on OMAP3 SDP
187+--------------------------
188+
189+Here's the default setup on OMAP3 SDP board. All planes go to LCD. DVI
190+and TV-out are not in use. The columns from left to right are:
191+framebuffers, overlays, overlay managers, displays. Framebuffers are
192+handled by omapfb, and the rest by the DSS.
193+
194+FB0 --- GFX -\ DVI
195+FB1 --- VID1 --+- LCD ---- LCD
196+FB2 --- VID2 -/ TV ----- TV
197+
198+Example: Switch from LCD to DVI
199+----------------------
200+
201+w=`cat $dvi/timings | cut -d "," -f 2 | cut -d "/" -f 1`
202+h=`cat $dvi/timings | cut -d "," -f 3 | cut -d "/" -f 1`
203+
204+echo "0" > $lcd/enabled
205+echo "" > $mgr0/display
206+fbset -fb /dev/fb0 -xres $w -yres $h -vxres $w -vyres $h
207+# at this point you have to switch the dvi/lcd dip-switch from the omap board
208+echo "dvi" > $mgr0/display
209+echo "1" > $dvi/enabled
210+
211+After this the configuration looks like:
212+
213+FB0 --- GFX -\ -- DVI
214+FB1 --- VID1 --+- LCD -/ LCD
215+FB2 --- VID2 -/ TV ----- TV
216+
217+Example: Clone GFX overlay to LCD and TV
218+-------------------------------
219+
220+w=`cat $tv/timings | cut -d "," -f 2 | cut -d "/" -f 1`
221+h=`cat $tv/timings | cut -d "," -f 3 | cut -d "/" -f 1`
222+
223+echo "0" > $ovl0/enabled
224+echo "0" > $ovl1/enabled
225+
226+echo "" > $fb1/overlays
227+echo "0,1" > $fb0/overlays
228+
229+echo "$w,$h" > $ovl1/output_size
230+echo "tv" > $ovl1/manager
231+
232+echo "1" > $ovl0/enabled
233+echo "1" > $ovl1/enabled
234+
235+echo "1" > $tv/enabled
236+
237+After this the configuration looks like (only relevant parts shown):
238+
239+FB0 +-- GFX ---- LCD ---- LCD
240+ \- VID1 ---- TV ---- TV
241+
242+Misc notes
243+----------
244+
245+OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator.
246+
247+Using DSI DPLL to generate pixel clock it is possible produce the pixel clock
248+of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI.
249+
250+Rotation and mirroring currently only supports RGB565 and RGB8888 modes. VRFB
251+does not support mirroring.
252+
253+VRFB rotation requires much more memory than non-rotated framebuffer, so you
254+probably need to increase your vram setting before using VRFB rotation. Also,
255+many applications may not work with VRFB if they do not pay attention to all
256+framebuffer parameters.
257+
258+Kernel boot arguments
259+---------------------
260+
261+vram=<size>
262+ - Amount of total VRAM to preallocate. For example, "10M". omapfb
263+ allocates memory for framebuffers from VRAM.
264+
265+omapfb.mode=<display>:<mode>[,...]
266+ - Default video mode for specified displays. For example,
267+ "dvi:800x400MR-24@60". See drivers/video/modedb.c.
268+ There are also two special modes: "pal" and "ntsc" that
269+ can be used to tv out.
270+
271+omapfb.vram=<fbnum>:<size>[@<physaddr>][,...]
272+ - VRAM allocated for a framebuffer. Normally omapfb allocates vram
273+ depending on the display size. With this you can manually allocate
274+ more or define the physical address of each framebuffer. For example,
275+ "1:4M" to allocate 4M for fb1.
276+
277+omapfb.debug=<y|n>
278+ - Enable debug printing. You have to have OMAPFB debug support enabled
279+ in kernel config.
280+
281+omapfb.test=<y|n>
282+ - Draw test pattern to framebuffer whenever framebuffer settings change.
283+ You need to have OMAPFB debug support enabled in kernel config.
284+
285+omapfb.vrfb=<y|n>
286+ - Use VRFB rotation for all framebuffers.
287+
288+omapfb.rotate=<angle>
289+ - Default rotation applied to all framebuffers.
290+ 0 - 0 degree rotation
291+ 1 - 90 degree rotation
292+ 2 - 180 degree rotation
293+ 3 - 270 degree rotation
294+
295+omapfb.mirror=<y|n>
296+ - Default mirror for all framebuffers. Only works with DMA rotation.
297+
298+omapdss.def_disp=<display>
299+ - Name of default display, to which all overlays will be connected.
300+ Common examples are "lcd" or "tv".
301+
302+omapdss.debug=<y|n>
303+ - Enable debug printing. You have to have DSS debug support enabled in
304+ kernel config.
305+
306+TODO
307+----
308+
309+DSS locking
310+
311+Error checking
312+- Lots of checks are missing or implemented just as BUG()
313+
314+System DMA update for DSI
315+- Can be used for RGB16 and RGB24P modes. Probably not for RGB24U (how
316+ to skip the empty byte?)
317+
318+OMAP1 support
319+- Not sure if needed
320+
321--- a/MAINTAINERS
322+++ b/MAINTAINERS
323@@ -3848,6 +3848,23 @@ L: linux-omap@vger.kernel.org
324 S: Maintained
325 F: drivers/video/omap/
326 
327+OMAP DISPLAY SUBSYSTEM SUPPORT (DSS2)
328+M: Tomi Valkeinen <tomi.valkeinen@nokia.com>
329+L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
330+L: linux-omap@vger.kernel.org
331+S: Maintained
332+F: drivers/video/omap2/dss/
333+F: drivers/video/omap2/vrfb.c
334+F: drivers/video/omap2/vram.c
335+F: Documentation/arm/OMAP/DSS
336+
337+OMAP FRAMEBUFFER SUPPORT (FOR DSS2)
338+M: Tomi Valkeinen <tomi.valkeinen@nokia.com>
339+L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
340+L: linux-omap@vger.kernel.org
341+S: Maintained
342+F: drivers/video/omap2/omapfb/
343+
344 OMAP MMC SUPPORT
345 M: Jarkko Lavinen <jarkko.lavinen@nokia.com>
346 L: linux-omap@vger.kernel.org
347--- a/arch/arm/configs/omap_3430sdp_defconfig
348+++ b/arch/arm/configs/omap_3430sdp_defconfig
349@@ -1336,10 +1336,33 @@ CONFIG_FB_CFB_IMAGEBLIT=y
350 #
351 # CONFIG_FB_S1D13XXX is not set
352 # CONFIG_FB_VIRTUAL is not set
353-CONFIG_FB_OMAP=y
354-# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
355+# CONFIG_FB_METRONOME is not set
356+# CONFIG_FB_MB862XX is not set
357+# CONFIG_FB_BROADSHEET is not set
358+# CONFIG_FB_OMAP_LCD_VGA is not set
359 # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
360-CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2
361+CONFIG_OMAP2_VRAM=y
362+CONFIG_OMAP2_VRFB=y
363+CONFIG_OMAP2_DSS=y
364+CONFIG_OMAP2_VRAM_SIZE=4
365+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
366+# CONFIG_OMAP2_DSS_RFBI is not set
367+CONFIG_OMAP2_DSS_VENC=y
368+# CONFIG_OMAP2_DSS_SDI is not set
369+# CONFIG_OMAP2_DSS_DSI is not set
370+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
371+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
372+CONFIG_FB_OMAP2=y
373+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
374+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
375+CONFIG_FB_OMAP2_NUM_FBS=3
376+
377+#
378+# OMAP2/3 Display Device Drivers
379+#
380+CONFIG_PANEL_GENERIC=y
381+# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set
382+CONFIG_PANEL_SHARP_LS037V7DW01=y
383 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
384 
385 #
386--- a/arch/arm/mach-omap1/board-nokia770.c
387+++ b/arch/arm/mach-omap1/board-nokia770.c
388@@ -14,6 +14,7 @@
389 #include <linux/platform_device.h>
390 #include <linux/input.h>
391 #include <linux/clk.h>
392+#include <linux/omapfb.h>
393 
394 #include <linux/spi/spi.h>
395 #include <linux/spi/ads7846.h>
396@@ -32,7 +33,6 @@
397 #include <mach/keypad.h>
398 #include <mach/common.h>
399 #include <mach/dsp_common.h>
400-#include <mach/omapfb.h>
401 #include <mach/hwa742.h>
402 #include <mach/lcd_mipid.h>
403 #include <mach/mmc.h>
404--- a/arch/arm/mach-omap2/board-3430sdp.c
405+++ b/arch/arm/mach-omap2/board-3430sdp.c
406@@ -37,6 +37,7 @@
407 #include <mach/common.h>
408 #include <mach/dma.h>
409 #include <mach/gpmc.h>
410+#include <mach/display.h>
411 
412 #include <mach/control.h>
413 #include <mach/gpmc-smc91x.h>
414@@ -152,31 +153,152 @@ static struct spi_board_info sdp3430_spi
415     },
416 };
417 
418-static struct platform_device sdp3430_lcd_device = {
419- .name = "sdp2430_lcd",
420- .id = -1,
421+
422+#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 8
423+#define SDP3430_LCD_PANEL_ENABLE_GPIO 5
424+
425+static unsigned backlight_gpio;
426+static unsigned enable_gpio;
427+static int lcd_enabled;
428+static int dvi_enabled;
429+
430+static void __init sdp3430_display_init(void)
431+{
432+ int r;
433+
434+ enable_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO;
435+ backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO;
436+
437+ r = gpio_request(enable_gpio, "LCD reset");
438+ if (r) {
439+ printk(KERN_ERR "failed to get LCD reset GPIO\n");
440+ goto err0;
441+ }
442+
443+ r = gpio_request(backlight_gpio, "LCD Backlight");
444+ if (r) {
445+ printk(KERN_ERR "failed to get LCD backlight GPIO\n");
446+ goto err1;
447+ }
448+
449+ gpio_direction_output(enable_gpio, 0);
450+ gpio_direction_output(backlight_gpio, 0);
451+
452+ return;
453+err1:
454+ gpio_free(enable_gpio);
455+err0:
456+ return;
457+}
458+
459+static int sdp3430_panel_enable_lcd(struct omap_dss_device *dssdev)
460+{
461+ if (dvi_enabled) {
462+ printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
463+ return -EINVAL;
464+ }
465+
466+ gpio_direction_output(enable_gpio, 1);
467+ gpio_direction_output(backlight_gpio, 1);
468+
469+ lcd_enabled = 1;
470+
471+ return 0;
472+}
473+
474+static void sdp3430_panel_disable_lcd(struct omap_dss_device *dssdev)
475+{
476+ lcd_enabled = 0;
477+
478+ gpio_direction_output(enable_gpio, 0);
479+ gpio_direction_output(backlight_gpio, 0);
480+}
481+
482+static int sdp3430_panel_enable_dvi(struct omap_dss_device *dssdev)
483+{
484+ if (lcd_enabled) {
485+ printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
486+ return -EINVAL;
487+ }
488+
489+ dvi_enabled = 1;
490+
491+ return 0;
492+}
493+
494+static void sdp3430_panel_disable_dvi(struct omap_dss_device *dssdev)
495+{
496+ dvi_enabled = 0;
497+}
498+
499+static int sdp3430_panel_enable_tv(struct omap_dss_device *dssdev)
500+{
501+ return 0;
502+}
503+
504+static void sdp3430_panel_disable_tv(struct omap_dss_device *dssdev)
505+{
506+}
507+
508+
509+static struct omap_dss_device sdp3430_lcd_device = {
510+ .name = "lcd",
511+ .driver_name = "sharp_ls_panel",
512+ .type = OMAP_DISPLAY_TYPE_DPI,
513+ .phy.dpi.data_lines = 16,
514+ .platform_enable = sdp3430_panel_enable_lcd,
515+ .platform_disable = sdp3430_panel_disable_lcd,
516+};
517+
518+static struct omap_dss_device sdp3430_dvi_device = {
519+ .name = "dvi",
520+ .driver_name = "generic_panel",
521+ .type = OMAP_DISPLAY_TYPE_DPI,
522+ .phy.dpi.data_lines = 24,
523+ .platform_enable = sdp3430_panel_enable_dvi,
524+ .platform_disable = sdp3430_panel_disable_dvi,
525+};
526+
527+static struct omap_dss_device sdp3430_tv_device = {
528+ .name = "tv",
529+ .driver_name = "venc",
530+ .type = OMAP_DISPLAY_TYPE_VENC,
531+ .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
532+ .platform_enable = sdp3430_panel_enable_tv,
533+ .platform_disable = sdp3430_panel_disable_tv,
534+};
535+
536+
537+static struct omap_dss_device *sdp3430_dss_devices[] = {
538+ &sdp3430_lcd_device,
539+ &sdp3430_dvi_device,
540+ &sdp3430_tv_device,
541 };
542 
543-static struct regulator_consumer_supply sdp3430_vdac_supply = {
544- .supply = "vdac",
545- .dev = &sdp3430_lcd_device.dev,
546+static struct omap_dss_board_info sdp3430_dss_data = {
547+ .num_devices = ARRAY_SIZE(sdp3430_dss_devices),
548+ .devices = sdp3430_dss_devices,
549+ .default_device = &sdp3430_lcd_device,
550 };
551 
552-static struct regulator_consumer_supply sdp3430_vdvi_supply = {
553- .supply = "vdvi",
554- .dev = &sdp3430_lcd_device.dev,
555+static struct platform_device sdp3430_dss_device = {
556+ .name = "omapdss",
557+ .id = -1,
558+ .dev = {
559+ .platform_data = &sdp3430_dss_data,
560+ },
561 };
562 
563-static struct platform_device *sdp3430_devices[] __initdata = {
564- &sdp3430_lcd_device,
565+static struct regulator_consumer_supply sdp3430_vdda_dac_supply = {
566+ .supply = "vdda_dac",
567+ .dev = &sdp3430_dss_device.dev,
568 };
569 
570-static struct omap_lcd_config sdp3430_lcd_config __initdata = {
571- .ctrl_name = "internal",
572+static struct platform_device *sdp3430_devices[] __initdata = {
573+ &sdp3430_dss_device,
574 };
575 
576 static struct omap_board_config_kernel sdp3430_config[] __initdata = {
577- { OMAP_TAG_LCD, &sdp3430_lcd_config },
578 };
579 
580 static void __init omap_3430sdp_init_irq(void)
581@@ -392,22 +514,34 @@ static struct regulator_init_data sdp343
582                     | REGULATOR_CHANGE_STATUS,
583     },
584     .num_consumer_supplies = 1,
585- .consumer_supplies = &sdp3430_vdac_supply,
586+ .consumer_supplies = &sdp3430_vdda_dac_supply,
587 };
588 
589 /* VPLL2 for digital video outputs */
590+static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = {
591+ {
592+ .supply = "vdvi",
593+ .dev = &sdp3430_lcd_device.dev,
594+ },
595+ {
596+ .supply = "vdds_dsi",
597+ .dev = &sdp3430_dss_device.dev,
598+ }
599+};
600+
601 static struct regulator_init_data sdp3430_vpll2 = {
602     .constraints = {
603         .name = "VDVI",
604         .min_uV = 1800000,
605         .max_uV = 1800000,
606+ .apply_uV = true,
607         .valid_modes_mask = REGULATOR_MODE_NORMAL
608                     | REGULATOR_MODE_STANDBY,
609         .valid_ops_mask = REGULATOR_CHANGE_MODE
610                     | REGULATOR_CHANGE_STATUS,
611     },
612- .num_consumer_supplies = 1,
613- .consumer_supplies = &sdp3430_vdvi_supply,
614+ .num_consumer_supplies = ARRAY_SIZE(sdp3430_vpll2_supplies),
615+ .consumer_supplies = sdp3430_vpll2_supplies,
616 };
617 
618 static struct twl4030_platform_data sdp3430_twldata = {
619@@ -499,6 +633,7 @@ static void __init omap_3430sdp_init(voi
620     omap_serial_init();
621     usb_musb_init();
622     board_smc91x_init();
623+ sdp3430_display_init();
624     enable_board_wakeup_source();
625 }
626 
627--- a/arch/arm/mach-omap2/clock24xx.c
628+++ b/arch/arm/mach-omap2/clock24xx.c
629@@ -116,10 +116,10 @@ static struct omap_clk omap24xx_clks[] =
630     CLK(NULL, "mdm_ick", &mdm_ick, CK_243X),
631     CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X),
632     /* DSS domain clocks */
633- CLK("omapfb", "ick", &dss_ick, CK_243X | CK_242X),
634- CLK("omapfb", "dss1_fck", &dss1_fck, CK_243X | CK_242X),
635- CLK("omapfb", "dss2_fck", &dss2_fck, CK_243X | CK_242X),
636- CLK("omapfb", "tv_fck", &dss_54m_fck, CK_243X | CK_242X),
637+ CLK("omapdss", "ick", &dss_ick, CK_243X | CK_242X),
638+ CLK("omapdss", "dss1_fck", &dss1_fck, CK_243X | CK_242X),
639+ CLK("omapdss", "dss2_fck", &dss2_fck, CK_243X | CK_242X),
640+ CLK("omapdss", "tv_fck", &dss_54m_fck, CK_243X | CK_242X),
641     /* L3 domain clocks */
642     CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X | CK_242X),
643     CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X | CK_242X),
644--- a/arch/arm/mach-omap2/clock34xx.c
645+++ b/arch/arm/mach-omap2/clock34xx.c
646@@ -236,13 +236,13 @@ static struct omap_clk omap34xx_clks[] =
647     CLK("omap_rng", "ick", &rng_ick, CK_343X),
648     CLK(NULL, "sha11_ick", &sha11_ick, CK_343X),
649     CLK(NULL, "des1_ick", &des1_ick, CK_343X),
650- CLK("omapfb", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1),
651- CLK("omapfb", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2),
652- CLK("omapfb", "tv_fck", &dss_tv_fck, CK_343X),
653- CLK("omapfb", "video_fck", &dss_96m_fck, CK_343X),
654- CLK("omapfb", "dss2_fck", &dss2_alwon_fck, CK_343X),
655- CLK("omapfb", "ick", &dss_ick_3430es1, CK_3430ES1),
656- CLK("omapfb", "ick", &dss_ick_3430es2, CK_3430ES2),
657+ CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1),
658+ CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2),
659+ CLK("omapdss", "tv_fck", &dss_tv_fck, CK_343X),
660+ CLK("omapdss", "video_fck", &dss_96m_fck, CK_343X),
661+ CLK("omapdss", "dss2_fck", &dss2_alwon_fck, CK_343X),
662+ CLK("omapdss", "ick", &dss_ick_3430es1, CK_3430ES1),
663+ CLK("omapdss", "ick", &dss_ick_3430es2, CK_3430ES2),
664     CLK(NULL, "cam_mclk", &cam_mclk, CK_343X),
665     CLK(NULL, "cam_ick", &cam_ick, CK_343X),
666     CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_343X),
667--- a/arch/arm/mach-omap2/io.c
668+++ b/arch/arm/mach-omap2/io.c
669@@ -22,17 +22,18 @@
670 #include <linux/init.h>
671 #include <linux/io.h>
672 #include <linux/clk.h>
673+#include <linux/omapfb.h>
674 
675 #include <asm/tlb.h>
676 
677 #include <asm/mach/map.h>
678 
679 #include <mach/mux.h>
680-#include <mach/omapfb.h>
681 #include <mach/sram.h>
682 #include <mach/sdrc.h>
683 #include <mach/gpmc.h>
684 #include <mach/serial.h>
685+#include <mach/vram.h>
686 
687 #ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdev is ready */
688 #include "clock.h"
689@@ -246,6 +247,7 @@ void __init omap2_map_common_io(void)
690     omap2_check_revision();
691     omap_sram_init();
692     omapfb_reserve_sdram();
693+ omap_vram_reserve_sdram();
694 }
695 
696 /*
697--- a/arch/arm/mach-omap2/sdrc.c
698+++ b/arch/arm/mach-omap2/sdrc.c
699@@ -133,3 +133,19 @@ void __init omap2_sdrc_init(struct omap_
700         (1 << SDRC_POWER_PAGEPOLICY_SHIFT);
701     sdrc_write_reg(l, SDRC_POWER);
702 }
703+
704+void omap2_sms_write_rot_control(u32 val, unsigned ctx)
705+{
706+ sms_write_reg(val, SMS_ROT_CONTROL(ctx));
707+}
708+
709+void omap2_sms_write_rot_size(u32 val, unsigned ctx)
710+{
711+ sms_write_reg(val, SMS_ROT_SIZE(ctx));
712+}
713+
714+void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
715+{
716+ sms_write_reg(val, SMS_ROT_PHYSICAL_BA(ctx));
717+}
718+
719--- a/arch/arm/plat-omap/fb.c
720+++ b/arch/arm/plat-omap/fb.c
721@@ -28,13 +28,13 @@
722 #include <linux/platform_device.h>
723 #include <linux/bootmem.h>
724 #include <linux/io.h>
725+#include <linux/omapfb.h>
726 
727 #include <mach/hardware.h>
728 #include <asm/mach/map.h>
729 
730 #include <mach/board.h>
731 #include <mach/sram.h>
732-#include <mach/omapfb.h>
733 
734 #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
735 
736@@ -327,7 +327,33 @@ static inline int omap_init_fb(void)
737 
738 arch_initcall(omap_init_fb);
739 
740-#else
741+#elif defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
742+
743+static u64 omap_fb_dma_mask = ~(u32)0;
744+static struct omapfb_platform_data omapfb_config;
745+
746+static struct platform_device omap_fb_device = {
747+ .name = "omapfb",
748+ .id = -1,
749+ .dev = {
750+ .dma_mask = &omap_fb_dma_mask,
751+ .coherent_dma_mask = ~(u32)0,
752+ .platform_data = &omapfb_config,
753+ },
754+ .num_resources = 0,
755+};
756+
757+void omapfb_set_platform_data(struct omapfb_platform_data *data)
758+{
759+ omapfb_config = *data;
760+}
761+
762+static inline int omap_init_fb(void)
763+{
764+ return platform_device_register(&omap_fb_device);
765+}
766+
767+arch_initcall(omap_init_fb);
768 
769 void omapfb_reserve_sdram(void) {}
770 unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
771@@ -339,5 +365,16 @@ unsigned long omapfb_reserve_sram(unsign
772     return 0;
773 }
774 
775+#else
776+
777+void omapfb_reserve_sdram(void) {}
778+unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
779+ unsigned long sram_vstart,
780+ unsigned long sram_size,
781+ unsigned long start_avail,
782+ unsigned long size_avail)
783+{
784+ return 0;
785+}
786 
787 #endif
788--- /dev/null
789+++ b/arch/arm/plat-omap/include/mach/display.h
790@@ -0,0 +1,540 @@
791+/*
792+ * linux/include/asm-arm/arch-omap/display.h
793+ *
794+ * Copyright (C) 2008 Nokia Corporation
795+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
796+ *
797+ * This program is free software; you can redistribute it and/or modify it
798+ * under the terms of the GNU General Public License version 2 as published by
799+ * the Free Software Foundation.
800+ *
801+ * This program is distributed in the hope that it will be useful, but WITHOUT
802+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
803+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
804+ * more details.
805+ *
806+ * You should have received a copy of the GNU General Public License along with
807+ * this program. If not, see <http://www.gnu.org/licenses/>.
808+ */
809+
810+#ifndef __ASM_ARCH_OMAP_DISPLAY_H
811+#define __ASM_ARCH_OMAP_DISPLAY_H
812+
813+#include <linux/list.h>
814+#include <linux/kobject.h>
815+#include <linux/device.h>
816+#include <asm/atomic.h>
817+
818+#define DISPC_IRQ_FRAMEDONE (1 << 0)
819+#define DISPC_IRQ_VSYNC (1 << 1)
820+#define DISPC_IRQ_EVSYNC_EVEN (1 << 2)
821+#define DISPC_IRQ_EVSYNC_ODD (1 << 3)
822+#define DISPC_IRQ_ACBIAS_COUNT_STAT (1 << 4)
823+#define DISPC_IRQ_PROG_LINE_NUM (1 << 5)
824+#define DISPC_IRQ_GFX_FIFO_UNDERFLOW (1 << 6)
825+#define DISPC_IRQ_GFX_END_WIN (1 << 7)
826+#define DISPC_IRQ_PAL_GAMMA_MASK (1 << 8)
827+#define DISPC_IRQ_OCP_ERR (1 << 9)
828+#define DISPC_IRQ_VID1_FIFO_UNDERFLOW (1 << 10)
829+#define DISPC_IRQ_VID1_END_WIN (1 << 11)
830+#define DISPC_IRQ_VID2_FIFO_UNDERFLOW (1 << 12)
831+#define DISPC_IRQ_VID2_END_WIN (1 << 13)
832+#define DISPC_IRQ_SYNC_LOST (1 << 14)
833+#define DISPC_IRQ_SYNC_LOST_DIGIT (1 << 15)
834+#define DISPC_IRQ_WAKEUP (1 << 16)
835+
836+struct omap_dss_device;
837+struct omap_overlay_manager;
838+
839+enum omap_display_type {
840+ OMAP_DISPLAY_TYPE_NONE = 0,
841+ OMAP_DISPLAY_TYPE_DPI = 1 << 0,
842+ OMAP_DISPLAY_TYPE_DBI = 1 << 1,
843+ OMAP_DISPLAY_TYPE_SDI = 1 << 2,
844+ OMAP_DISPLAY_TYPE_DSI = 1 << 3,
845+ OMAP_DISPLAY_TYPE_VENC = 1 << 4,
846+};
847+
848+enum omap_plane {
849+ OMAP_DSS_GFX = 0,
850+ OMAP_DSS_VIDEO1 = 1,
851+ OMAP_DSS_VIDEO2 = 2
852+};
853+
854+enum omap_channel {
855+ OMAP_DSS_CHANNEL_LCD = 0,
856+ OMAP_DSS_CHANNEL_DIGIT = 1,
857+};
858+
859+enum omap_color_mode {
860+ OMAP_DSS_COLOR_CLUT1 = 1 << 0, /* BITMAP 1 */
861+ OMAP_DSS_COLOR_CLUT2 = 1 << 1, /* BITMAP 2 */
862+ OMAP_DSS_COLOR_CLUT4 = 1 << 2, /* BITMAP 4 */
863+ OMAP_DSS_COLOR_CLUT8 = 1 << 3, /* BITMAP 8 */
864+ OMAP_DSS_COLOR_RGB12U = 1 << 4, /* RGB12, 16-bit container */
865+ OMAP_DSS_COLOR_ARGB16 = 1 << 5, /* ARGB16 */
866+ OMAP_DSS_COLOR_RGB16 = 1 << 6, /* RGB16 */
867+ OMAP_DSS_COLOR_RGB24U = 1 << 7, /* RGB24, 32-bit container */
868+ OMAP_DSS_COLOR_RGB24P = 1 << 8, /* RGB24, 24-bit container */
869+ OMAP_DSS_COLOR_YUV2 = 1 << 9, /* YUV2 4:2:2 co-sited */
870+ OMAP_DSS_COLOR_UYVY = 1 << 10, /* UYVY 4:2:2 co-sited */
871+ OMAP_DSS_COLOR_ARGB32 = 1 << 11, /* ARGB32 */
872+ OMAP_DSS_COLOR_RGBA32 = 1 << 12, /* RGBA32 */
873+ OMAP_DSS_COLOR_RGBX32 = 1 << 13, /* RGBx32 */
874+
875+ OMAP_DSS_COLOR_GFX_OMAP3 =
876+ OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
877+ OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
878+ OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
879+ OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
880+ OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
881+ OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
882+
883+ OMAP_DSS_COLOR_VID_OMAP3 =
884+ OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
885+ OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
886+ OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
887+ OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 |
888+ OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
889+};
890+
891+enum omap_lcd_display_type {
892+ OMAP_DSS_LCD_DISPLAY_STN,
893+ OMAP_DSS_LCD_DISPLAY_TFT,
894+};
895+
896+enum omap_dss_load_mode {
897+ OMAP_DSS_LOAD_CLUT_AND_FRAME = 0,
898+ OMAP_DSS_LOAD_CLUT_ONLY = 1,
899+ OMAP_DSS_LOAD_FRAME_ONLY = 2,
900+ OMAP_DSS_LOAD_CLUT_ONCE_FRAME = 3,
901+};
902+
903+enum omap_dss_trans_key_type {
904+ OMAP_DSS_COLOR_KEY_GFX_DST = 0,
905+ OMAP_DSS_COLOR_KEY_VID_SRC = 1,
906+};
907+
908+enum omap_rfbi_te_mode {
909+ OMAP_DSS_RFBI_TE_MODE_1 = 1,
910+ OMAP_DSS_RFBI_TE_MODE_2 = 2,
911+};
912+
913+enum omap_panel_config {
914+ OMAP_DSS_LCD_IVS = 1<<0,
915+ OMAP_DSS_LCD_IHS = 1<<1,
916+ OMAP_DSS_LCD_IPC = 1<<2,
917+ OMAP_DSS_LCD_IEO = 1<<3,
918+ OMAP_DSS_LCD_RF = 1<<4,
919+ OMAP_DSS_LCD_ONOFF = 1<<5,
920+
921+ OMAP_DSS_LCD_TFT = 1<<20,
922+};
923+
924+enum omap_dss_venc_type {
925+ OMAP_DSS_VENC_TYPE_COMPOSITE,
926+ OMAP_DSS_VENC_TYPE_SVIDEO,
927+};
928+
929+enum omap_display_caps {
930+ OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0,
931+};
932+
933+enum omap_dss_update_mode {
934+ OMAP_DSS_UPDATE_DISABLED = 0,
935+ OMAP_DSS_UPDATE_AUTO,
936+ OMAP_DSS_UPDATE_MANUAL,
937+};
938+
939+enum omap_dss_display_state {
940+ OMAP_DSS_DISPLAY_DISABLED = 0,
941+ OMAP_DSS_DISPLAY_ACTIVE,
942+ OMAP_DSS_DISPLAY_SUSPENDED,
943+};
944+
945+/* XXX perhaps this should be removed */
946+enum omap_dss_overlay_managers {
947+ OMAP_DSS_OVL_MGR_LCD,
948+ OMAP_DSS_OVL_MGR_TV,
949+};
950+
951+enum omap_dss_rotation_type {
952+ OMAP_DSS_ROT_DMA = 0,
953+ OMAP_DSS_ROT_VRFB = 1,
954+};
955+
956+enum omap_overlay_caps {
957+ OMAP_DSS_OVL_CAP_SCALE = 1 << 0,
958+ OMAP_DSS_OVL_CAP_DISPC = 1 << 1,
959+};
960+
961+enum omap_overlay_manager_caps {
962+ OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0,
963+};
964+
965+/* RFBI */
966+
967+struct rfbi_timings {
968+ int cs_on_time;
969+ int cs_off_time;
970+ int we_on_time;
971+ int we_off_time;
972+ int re_on_time;
973+ int re_off_time;
974+ int we_cycle_time;
975+ int re_cycle_time;
976+ int cs_pulse_width;
977+ int access_time;
978+
979+ int clk_div;
980+
981+ u32 tim[5]; /* set by rfbi_convert_timings() */
982+
983+ int converted;
984+};
985+
986+void omap_rfbi_write_command(const void *buf, u32 len);
987+void omap_rfbi_read_data(void *buf, u32 len);
988+void omap_rfbi_write_data(const void *buf, u32 len);
989+void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
990+ u16 x, u16 y,
991+ u16 w, u16 h);
992+int omap_rfbi_enable_te(bool enable, unsigned line);
993+int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
994+ unsigned hs_pulse_time, unsigned vs_pulse_time,
995+ int hs_pol_inv, int vs_pol_inv, int extif_div);
996+
997+/* DSI */
998+void dsi_bus_lock(void);
999+void dsi_bus_unlock(void);
1000+int dsi_vc_dcs_write(int channel, u8 *data, int len);
1001+int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len);
1002+int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen);
1003+int dsi_vc_set_max_rx_packet_size(int channel, u16 len);
1004+int dsi_vc_send_null(int channel);
1005+int dsi_vc_send_bta_sync(int channel);
1006+
1007+/* Board specific data */
1008+struct omap_dss_board_info {
1009+ int (*get_last_off_on_transaction_id)(struct device *dev);
1010+ int num_devices;
1011+ struct omap_dss_device **devices;
1012+ struct omap_dss_device *default_device;
1013+};
1014+
1015+struct omap_video_timings {
1016+ /* Unit: pixels */
1017+ u16 x_res;
1018+ /* Unit: pixels */
1019+ u16 y_res;
1020+ /* Unit: KHz */
1021+ u32 pixel_clock;
1022+ /* Unit: pixel clocks */
1023+ u16 hsw; /* Horizontal synchronization pulse width */
1024+ /* Unit: pixel clocks */
1025+ u16 hfp; /* Horizontal front porch */
1026+ /* Unit: pixel clocks */
1027+ u16 hbp; /* Horizontal back porch */
1028+ /* Unit: line clocks */
1029+ u16 vsw; /* Vertical synchronization pulse width */
1030+ /* Unit: line clocks */
1031+ u16 vfp; /* Vertical front porch */
1032+ /* Unit: line clocks */
1033+ u16 vbp; /* Vertical back porch */
1034+};
1035+
1036+#ifdef CONFIG_OMAP2_DSS_VENC
1037+/* Hardcoded timings for tv modes. Venc only uses these to
1038+ * identify the mode, and does not actually use the configs
1039+ * itself. However, the configs should be something that
1040+ * a normal monitor can also show */
1041+const extern struct omap_video_timings omap_dss_pal_timings;
1042+const extern struct omap_video_timings omap_dss_ntsc_timings;
1043+#endif
1044+
1045+struct omap_overlay_info {
1046+ bool enabled;
1047+
1048+ u32 paddr;
1049+ void __iomem *vaddr;
1050+ u16 screen_width;
1051+ u16 width;
1052+ u16 height;
1053+ enum omap_color_mode color_mode;
1054+ u8 rotation;
1055+ enum omap_dss_rotation_type rotation_type;
1056+ bool mirror;
1057+
1058+ u16 pos_x;
1059+ u16 pos_y;
1060+ u16 out_width; /* if 0, out_width == width */
1061+ u16 out_height; /* if 0, out_height == height */
1062+ u8 global_alpha;
1063+};
1064+
1065+struct omap_overlay {
1066+ struct kobject kobj;
1067+ struct list_head list;
1068+
1069+ /* static fields */
1070+ const char *name;
1071+ int id;
1072+ enum omap_color_mode supported_modes;
1073+ enum omap_overlay_caps caps;
1074+
1075+ /* dynamic fields */
1076+ struct omap_overlay_manager *manager;
1077+ struct omap_overlay_info info;
1078+
1079+ /* if true, info has been changed, but not applied() yet */
1080+ bool info_dirty;
1081+
1082+ int (*set_manager)(struct omap_overlay *ovl,
1083+ struct omap_overlay_manager *mgr);
1084+ int (*unset_manager)(struct omap_overlay *ovl);
1085+
1086+ int (*set_overlay_info)(struct omap_overlay *ovl,
1087+ struct omap_overlay_info *info);
1088+ void (*get_overlay_info)(struct omap_overlay *ovl,
1089+ struct omap_overlay_info *info);
1090+
1091+ int (*wait_for_go)(struct omap_overlay *ovl);
1092+};
1093+
1094+struct omap_overlay_manager_info {
1095+ u32 default_color;
1096+
1097+ enum omap_dss_trans_key_type trans_key_type;
1098+ u32 trans_key;
1099+ bool trans_enabled;
1100+
1101+ bool alpha_enabled;
1102+};
1103+
1104+struct omap_overlay_manager {
1105+ struct kobject kobj;
1106+ struct list_head list;
1107+
1108+ /* static fields */
1109+ const char *name;
1110+ int id;
1111+ enum omap_overlay_manager_caps caps;
1112+ int num_overlays;
1113+ struct omap_overlay **overlays;
1114+ enum omap_display_type supported_displays;
1115+
1116+ /* dynamic fields */
1117+ struct omap_dss_device *device;
1118+ struct omap_overlay_manager_info info;
1119+
1120+ bool device_changed;
1121+ /* if true, info has been changed but not applied() yet */
1122+ bool info_dirty;
1123+
1124+ int (*set_device)(struct omap_overlay_manager *mgr,
1125+ struct omap_dss_device *dssdev);
1126+ int (*unset_device)(struct omap_overlay_manager *mgr);
1127+
1128+ int (*set_manager_info)(struct omap_overlay_manager *mgr,
1129+ struct omap_overlay_manager_info *info);
1130+ void (*get_manager_info)(struct omap_overlay_manager *mgr,
1131+ struct omap_overlay_manager_info *info);
1132+
1133+ int (*apply)(struct omap_overlay_manager *mgr);
1134+ int (*wait_for_go)(struct omap_overlay_manager *mgr);
1135+};
1136+
1137+struct omap_dss_device {
1138+ struct device dev;
1139+
1140+ enum omap_display_type type;
1141+
1142+ union {
1143+ struct {
1144+ u8 data_lines;
1145+ } dpi;
1146+
1147+ struct {
1148+ u8 channel;
1149+ u8 data_lines;
1150+ } rfbi;
1151+
1152+ struct {
1153+ u8 datapairs;
1154+ } sdi;
1155+
1156+ struct {
1157+ u8 clk_lane;
1158+ u8 clk_pol;
1159+ u8 data1_lane;
1160+ u8 data1_pol;
1161+ u8 data2_lane;
1162+ u8 data2_pol;
1163+ unsigned long lp_clk_hz;
1164+ unsigned long ddr_clk_hz;
1165+
1166+ bool ext_te;
1167+ u8 ext_te_gpio;
1168+ } dsi;
1169+
1170+ struct {
1171+ enum omap_dss_venc_type type;
1172+ bool invert_polarity;
1173+ } venc;
1174+ } phy;
1175+
1176+ struct {
1177+ struct omap_video_timings timings;
1178+
1179+ int acbi; /* ac-bias pin transitions per interrupt */
1180+ /* Unit: line clocks */
1181+ int acb; /* ac-bias pin frequency */
1182+
1183+ enum omap_panel_config config;
1184+
1185+ u8 recommended_bpp;
1186+
1187+ struct omap_dss_device *ctrl;
1188+ } panel;
1189+
1190+ struct {
1191+ u8 pixel_size;
1192+ struct rfbi_timings rfbi_timings;
1193+ struct omap_dss_device *panel;
1194+ } ctrl;
1195+
1196+ int reset_gpio;
1197+
1198+ int max_backlight_level;
1199+
1200+ const char *name;
1201+
1202+ /* used to match device to driver */
1203+ const char *driver_name;
1204+
1205+ void *data;
1206+
1207+ struct omap_dss_driver *driver;
1208+
1209+ /* helper variable for driver suspend/resume */
1210+ bool activate_after_resume;
1211+
1212+ enum omap_display_caps caps;
1213+
1214+ struct omap_overlay_manager *manager;
1215+
1216+ enum omap_dss_display_state state;
1217+
1218+ int (*enable)(struct omap_dss_device *dssdev);
1219+ void (*disable)(struct omap_dss_device *dssdev);
1220+
1221+ int (*suspend)(struct omap_dss_device *dssdev);
1222+ int (*resume)(struct omap_dss_device *dssdev);
1223+
1224+ void (*get_resolution)(struct omap_dss_device *dssdev,
1225+ u16 *xres, u16 *yres);
1226+ int (*get_recommended_bpp)(struct omap_dss_device *dssdev);
1227+
1228+ int (*check_timings)(struct omap_dss_device *dssdev,
1229+ struct omap_video_timings *timings);
1230+ void (*set_timings)(struct omap_dss_device *dssdev,
1231+ struct omap_video_timings *timings);
1232+ void (*get_timings)(struct omap_dss_device *dssdev,
1233+ struct omap_video_timings *timings);
1234+ int (*update)(struct omap_dss_device *dssdev,
1235+ u16 x, u16 y, u16 w, u16 h);
1236+ int (*sync)(struct omap_dss_device *dssdev);
1237+ int (*wait_vsync)(struct omap_dss_device *dssdev);
1238+
1239+ int (*set_update_mode)(struct omap_dss_device *dssdev,
1240+ enum omap_dss_update_mode);
1241+ enum omap_dss_update_mode (*get_update_mode)
1242+ (struct omap_dss_device *dssdev);
1243+
1244+ int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
1245+ int (*get_te)(struct omap_dss_device *dssdev);
1246+
1247+ u8 (*get_rotate)(struct omap_dss_device *dssdev);
1248+ int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
1249+
1250+ bool (*get_mirror)(struct omap_dss_device *dssdev);
1251+ int (*set_mirror)(struct omap_dss_device *dssdev, bool enable);
1252+
1253+ int (*run_test)(struct omap_dss_device *dssdev, int test);
1254+ int (*memory_read)(struct omap_dss_device *dssdev,
1255+ void *buf, size_t size,
1256+ u16 x, u16 y, u16 w, u16 h);
1257+
1258+ int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
1259+ u32 (*get_wss)(struct omap_dss_device *dssdev);
1260+
1261+ /* platform specific */
1262+ int (*platform_enable)(struct omap_dss_device *dssdev);
1263+ void (*platform_disable)(struct omap_dss_device *dssdev);
1264+ int (*set_backlight)(struct omap_dss_device *dssdev, int level);
1265+ int (*get_backlight)(struct omap_dss_device *dssdev);
1266+};
1267+
1268+struct omap_dss_driver {
1269+ struct device_driver driver;
1270+
1271+ int (*probe)(struct omap_dss_device *);
1272+ void (*remove)(struct omap_dss_device *);
1273+
1274+ int (*enable)(struct omap_dss_device *display);
1275+ void (*disable)(struct omap_dss_device *display);
1276+ int (*suspend)(struct omap_dss_device *display);
1277+ int (*resume)(struct omap_dss_device *display);
1278+ int (*run_test)(struct omap_dss_device *display, int test);
1279+
1280+ void (*setup_update)(struct omap_dss_device *dssdev,
1281+ u16 x, u16 y, u16 w, u16 h);
1282+
1283+ int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
1284+ int (*wait_for_te)(struct omap_dss_device *dssdev);
1285+
1286+ u8 (*get_rotate)(struct omap_dss_device *dssdev);
1287+ int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
1288+
1289+ bool (*get_mirror)(struct omap_dss_device *dssdev);
1290+ int (*set_mirror)(struct omap_dss_device *dssdev, bool enable);
1291+
1292+ int (*memory_read)(struct omap_dss_device *dssdev,
1293+ void *buf, size_t size,
1294+ u16 x, u16 y, u16 w, u16 h);
1295+};
1296+
1297+int omap_dss_register_driver(struct omap_dss_driver *);
1298+void omap_dss_unregister_driver(struct omap_dss_driver *);
1299+
1300+int omap_dss_register_device(struct omap_dss_device *);
1301+void omap_dss_unregister_device(struct omap_dss_device *);
1302+
1303+void omap_dss_get_device(struct omap_dss_device *dssdev);
1304+void omap_dss_put_device(struct omap_dss_device *dssdev);
1305+#define for_each_dss_dev(d) while ((d = omap_dss_get_next_device(d)) != NULL)
1306+struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from);
1307+struct omap_dss_device *omap_dss_find_device(void *data,
1308+ int (*match)(struct omap_dss_device *dssdev, void *data));
1309+
1310+int omap_dss_start_device(struct omap_dss_device *dssdev);
1311+void omap_dss_stop_device(struct omap_dss_device *dssdev);
1312+
1313+int omap_dss_get_num_overlay_managers(void);
1314+struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
1315+
1316+int omap_dss_get_num_overlays(void);
1317+struct omap_overlay *omap_dss_get_overlay(int num);
1318+
1319+typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
1320+int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
1321+int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
1322+
1323+int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout);
1324+int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
1325+ unsigned long timeout);
1326+
1327+#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
1328+#define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
1329+
1330+#endif
1331--- a/arch/arm/plat-omap/include/mach/omapfb.h
1332+++ /dev/null
1333@@ -1,398 +0,0 @@
1334-/*
1335- * File: arch/arm/plat-omap/include/mach/omapfb.h
1336- *
1337- * Framebuffer driver for TI OMAP boards
1338- *
1339- * Copyright (C) 2004 Nokia Corporation
1340- * Author: Imre Deak <imre.deak@nokia.com>
1341- *
1342- * This program is free software; you can redistribute it and/or modify it
1343- * under the terms of the GNU General Public License as published by the
1344- * Free Software Foundation; either version 2 of the License, or (at your
1345- * option) any later version.
1346- *
1347- * This program is distributed in the hope that it will be useful, but
1348- * WITHOUT ANY WARRANTY; without even the implied warranty of
1349- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1350- * General Public License for more details.
1351- *
1352- * You should have received a copy of the GNU General Public License along
1353- * with this program; if not, write to the Free Software Foundation, Inc.,
1354- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1355- */
1356-
1357-#ifndef __OMAPFB_H
1358-#define __OMAPFB_H
1359-
1360-#include <asm/ioctl.h>
1361-#include <asm/types.h>
1362-
1363-/* IOCTL commands. */
1364-
1365-#define OMAP_IOW(num, dtype) _IOW('O', num, dtype)
1366-#define OMAP_IOR(num, dtype) _IOR('O', num, dtype)
1367-#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype)
1368-#define OMAP_IO(num) _IO('O', num)
1369-
1370-#define OMAPFB_MIRROR OMAP_IOW(31, int)
1371-#define OMAPFB_SYNC_GFX OMAP_IO(37)
1372-#define OMAPFB_VSYNC OMAP_IO(38)
1373-#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int)
1374-#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps)
1375-#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int)
1376-#define OMAPFB_LCD_TEST OMAP_IOW(45, int)
1377-#define OMAPFB_CTRL_TEST OMAP_IOW(46, int)
1378-#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old)
1379-#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key)
1380-#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key)
1381-#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info)
1382-#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info)
1383-#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window)
1384-#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info)
1385-#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info)
1386-
1387-#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff
1388-#define OMAPFB_CAPS_LCDC_MASK 0x00fff000
1389-#define OMAPFB_CAPS_PANEL_MASK 0xff000000
1390-
1391-#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000
1392-#define OMAPFB_CAPS_TEARSYNC 0x00002000
1393-#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000
1394-#define OMAPFB_CAPS_PLANE_SCALE 0x00008000
1395-#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000
1396-#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000
1397-#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000
1398-#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000
1399-#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000
1400-
1401-/* Values from DSP must map to lower 16-bits */
1402-#define OMAPFB_FORMAT_MASK 0x00ff
1403-#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100
1404-#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200
1405-#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400
1406-#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800
1407-#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000
1408-
1409-#define OMAPFB_EVENT_READY 1
1410-#define OMAPFB_EVENT_DISABLED 2
1411-
1412-#define OMAPFB_MEMTYPE_SDRAM 0
1413-#define OMAPFB_MEMTYPE_SRAM 1
1414-#define OMAPFB_MEMTYPE_MAX 1
1415-
1416-enum omapfb_color_format {
1417- OMAPFB_COLOR_RGB565 = 0,
1418- OMAPFB_COLOR_YUV422,
1419- OMAPFB_COLOR_YUV420,
1420- OMAPFB_COLOR_CLUT_8BPP,
1421- OMAPFB_COLOR_CLUT_4BPP,
1422- OMAPFB_COLOR_CLUT_2BPP,
1423- OMAPFB_COLOR_CLUT_1BPP,
1424- OMAPFB_COLOR_RGB444,
1425- OMAPFB_COLOR_YUY422,
1426-};
1427-
1428-struct omapfb_update_window {
1429- __u32 x, y;
1430- __u32 width, height;
1431- __u32 format;
1432- __u32 out_x, out_y;
1433- __u32 out_width, out_height;
1434- __u32 reserved[8];
1435-};
1436-
1437-struct omapfb_update_window_old {
1438- __u32 x, y;
1439- __u32 width, height;
1440- __u32 format;
1441-};
1442-
1443-enum omapfb_plane {
1444- OMAPFB_PLANE_GFX = 0,
1445- OMAPFB_PLANE_VID1,
1446- OMAPFB_PLANE_VID2,
1447-};
1448-
1449-enum omapfb_channel_out {
1450- OMAPFB_CHANNEL_OUT_LCD = 0,
1451- OMAPFB_CHANNEL_OUT_DIGIT,
1452-};
1453-
1454-struct omapfb_plane_info {
1455- __u32 pos_x;
1456- __u32 pos_y;
1457- __u8 enabled;
1458- __u8 channel_out;
1459- __u8 mirror;
1460- __u8 reserved1;
1461- __u32 out_width;
1462- __u32 out_height;
1463- __u32 reserved2[12];
1464-};
1465-
1466-struct omapfb_mem_info {
1467- __u32 size;
1468- __u8 type;
1469- __u8 reserved[3];
1470-};
1471-
1472-struct omapfb_caps {
1473- __u32 ctrl;
1474- __u32 plane_color;
1475- __u32 wnd_color;
1476-};
1477-
1478-enum omapfb_color_key_type {
1479- OMAPFB_COLOR_KEY_DISABLED = 0,
1480- OMAPFB_COLOR_KEY_GFX_DST,
1481- OMAPFB_COLOR_KEY_VID_SRC,
1482-};
1483-
1484-struct omapfb_color_key {
1485- __u8 channel_out;
1486- __u32 background;
1487- __u32 trans_key;
1488- __u8 key_type;
1489-};
1490-
1491-enum omapfb_update_mode {
1492- OMAPFB_UPDATE_DISABLED = 0,
1493- OMAPFB_AUTO_UPDATE,
1494- OMAPFB_MANUAL_UPDATE
1495-};
1496-
1497-#ifdef __KERNEL__
1498-
1499-#include <linux/completion.h>
1500-#include <linux/interrupt.h>
1501-#include <linux/fb.h>
1502-#include <linux/mutex.h>
1503-
1504-#include <mach/board.h>
1505-
1506-#define OMAP_LCDC_INV_VSYNC 0x0001
1507-#define OMAP_LCDC_INV_HSYNC 0x0002
1508-#define OMAP_LCDC_INV_PIX_CLOCK 0x0004
1509-#define OMAP_LCDC_INV_OUTPUT_EN 0x0008
1510-#define OMAP_LCDC_HSVS_RISING_EDGE 0x0010
1511-#define OMAP_LCDC_HSVS_OPPOSITE 0x0020
1512-
1513-#define OMAP_LCDC_SIGNAL_MASK 0x003f
1514-
1515-#define OMAP_LCDC_PANEL_TFT 0x0100
1516-
1517-#define OMAPFB_PLANE_XRES_MIN 8
1518-#define OMAPFB_PLANE_YRES_MIN 8
1519-
1520-#ifdef CONFIG_ARCH_OMAP1
1521-#define OMAPFB_PLANE_NUM 1
1522-#else
1523-#define OMAPFB_PLANE_NUM 3
1524-#endif
1525-
1526-struct omapfb_device;
1527-
1528-struct lcd_panel {
1529- const char *name;
1530- int config; /* TFT/STN, signal inversion */
1531- int bpp; /* Pixel format in fb mem */
1532- int data_lines; /* Lines on LCD HW interface */
1533-
1534- int x_res, y_res;
1535- int pixel_clock; /* In kHz */
1536- int hsw; /* Horizontal synchronization
1537- pulse width */
1538- int hfp; /* Horizontal front porch */
1539- int hbp; /* Horizontal back porch */
1540- int vsw; /* Vertical synchronization
1541- pulse width */
1542- int vfp; /* Vertical front porch */
1543- int vbp; /* Vertical back porch */
1544- int acb; /* ac-bias pin frequency */
1545- int pcd; /* pixel clock divider.
1546- Obsolete use pixel_clock instead */
1547-
1548- int (*init) (struct lcd_panel *panel,
1549- struct omapfb_device *fbdev);
1550- void (*cleanup) (struct lcd_panel *panel);
1551- int (*enable) (struct lcd_panel *panel);
1552- void (*disable) (struct lcd_panel *panel);
1553- unsigned long (*get_caps) (struct lcd_panel *panel);
1554- int (*set_bklight_level)(struct lcd_panel *panel,
1555- unsigned int level);
1556- unsigned int (*get_bklight_level)(struct lcd_panel *panel);
1557- unsigned int (*get_bklight_max) (struct lcd_panel *panel);
1558- int (*run_test) (struct lcd_panel *panel, int test_num);
1559-};
1560-
1561-struct extif_timings {
1562- int cs_on_time;
1563- int cs_off_time;
1564- int we_on_time;
1565- int we_off_time;
1566- int re_on_time;
1567- int re_off_time;
1568- int we_cycle_time;
1569- int re_cycle_time;
1570- int cs_pulse_width;
1571- int access_time;
1572-
1573- int clk_div;
1574-
1575- u32 tim[5]; /* set by extif->convert_timings */
1576-
1577- int converted;
1578-};
1579-
1580-struct lcd_ctrl_extif {
1581- int (*init) (struct omapfb_device *fbdev);
1582- void (*cleanup) (void);
1583- void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div);
1584- unsigned long (*get_max_tx_rate)(void);
1585- int (*convert_timings) (struct extif_timings *timings);
1586- void (*set_timings) (const struct extif_timings *timings);
1587- void (*set_bits_per_cycle)(int bpc);
1588- void (*write_command) (const void *buf, unsigned int len);
1589- void (*read_data) (void *buf, unsigned int len);
1590- void (*write_data) (const void *buf, unsigned int len);
1591- void (*transfer_area) (int width, int height,
1592- void (callback)(void * data), void *data);
1593- int (*setup_tearsync) (unsigned pin_cnt,
1594- unsigned hs_pulse_time, unsigned vs_pulse_time,
1595- int hs_pol_inv, int vs_pol_inv, int div);
1596- int (*enable_tearsync) (int enable, unsigned line);
1597-
1598- unsigned long max_transmit_size;
1599-};
1600-
1601-struct omapfb_notifier_block {
1602- struct notifier_block nb;
1603- void *data;
1604- int plane_idx;
1605-};
1606-
1607-typedef int (*omapfb_notifier_callback_t)(struct notifier_block *,
1608- unsigned long event,
1609- void *fbi);
1610-
1611-struct omapfb_mem_region {
1612- u32 paddr;
1613- void __iomem *vaddr;
1614- unsigned long size;
1615- u8 type; /* OMAPFB_PLANE_MEM_* */
1616- unsigned alloc:1; /* allocated by the driver */
1617- unsigned map:1; /* kernel mapped by the driver */
1618-};
1619-
1620-struct omapfb_mem_desc {
1621- int region_cnt;
1622- struct omapfb_mem_region region[OMAPFB_PLANE_NUM];
1623-};
1624-
1625-struct lcd_ctrl {
1626- const char *name;
1627- void *data;
1628-
1629- int (*init) (struct omapfb_device *fbdev,
1630- int ext_mode,
1631- struct omapfb_mem_desc *req_md);
1632- void (*cleanup) (void);
1633- void (*bind_client) (struct omapfb_notifier_block *nb);
1634- void (*get_caps) (int plane, struct omapfb_caps *caps);
1635- int (*set_update_mode)(enum omapfb_update_mode mode);
1636- enum omapfb_update_mode (*get_update_mode)(void);
1637- int (*setup_plane) (int plane, int channel_out,
1638- unsigned long offset,
1639- int screen_width,
1640- int pos_x, int pos_y, int width,
1641- int height, int color_mode);
1642- int (*set_rotate) (int angle);
1643- int (*setup_mem) (int plane, size_t size,
1644- int mem_type, unsigned long *paddr);
1645- int (*mmap) (struct fb_info *info,
1646- struct vm_area_struct *vma);
1647- int (*set_scale) (int plane,
1648- int orig_width, int orig_height,
1649- int out_width, int out_height);
1650- int (*enable_plane) (int plane, int enable);
1651- int (*update_window) (struct fb_info *fbi,
1652- struct omapfb_update_window *win,
1653- void (*callback)(void *),
1654- void *callback_data);
1655- void (*sync) (void);
1656- void (*suspend) (void);
1657- void (*resume) (void);
1658- int (*run_test) (int test_num);
1659- int (*setcolreg) (u_int regno, u16 red, u16 green,
1660- u16 blue, u16 transp,
1661- int update_hw_mem);
1662- int (*set_color_key) (struct omapfb_color_key *ck);
1663- int (*get_color_key) (struct omapfb_color_key *ck);
1664-};
1665-
1666-enum omapfb_state {
1667- OMAPFB_DISABLED = 0,
1668- OMAPFB_SUSPENDED= 99,
1669- OMAPFB_ACTIVE = 100
1670-};
1671-
1672-struct omapfb_plane_struct {
1673- int idx;
1674- struct omapfb_plane_info info;
1675- enum omapfb_color_format color_mode;
1676- struct omapfb_device *fbdev;
1677-};
1678-
1679-struct omapfb_device {
1680- int state;
1681- int ext_lcdc; /* Using external
1682- LCD controller */
1683- struct mutex rqueue_mutex;
1684-
1685- int palette_size;
1686- u32 pseudo_palette[17];
1687-
1688- struct lcd_panel *panel; /* LCD panel */
1689- const struct lcd_ctrl *ctrl; /* LCD controller */
1690- const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */
1691- struct lcd_ctrl_extif *ext_if; /* LCD ctrl external
1692- interface */
1693- struct device *dev;
1694- struct fb_var_screeninfo new_var; /* for mode changes */
1695-
1696- struct omapfb_mem_desc mem_desc;
1697- struct fb_info *fb_info[OMAPFB_PLANE_NUM];
1698-};
1699-
1700-struct omapfb_platform_data {
1701- struct omap_lcd_config lcd;
1702- struct omapfb_mem_desc mem_desc;
1703- void *ctrl_platform_data;
1704-};
1705-
1706-#ifdef CONFIG_ARCH_OMAP1
1707-extern struct lcd_ctrl omap1_lcd_ctrl;
1708-#else
1709-extern struct lcd_ctrl omap2_disp_ctrl;
1710-#endif
1711-
1712-extern void omapfb_reserve_sdram(void);
1713-extern void omapfb_register_panel(struct lcd_panel *panel);
1714-extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
1715-extern void omapfb_notify_clients(struct omapfb_device *fbdev,
1716- unsigned long event);
1717-extern int omapfb_register_client(struct omapfb_notifier_block *nb,
1718- omapfb_notifier_callback_t callback,
1719- void *callback_data);
1720-extern int omapfb_unregister_client(struct omapfb_notifier_block *nb);
1721-extern int omapfb_update_window_async(struct fb_info *fbi,
1722- struct omapfb_update_window *win,
1723- void (*callback)(void *),
1724- void *callback_data);
1725-
1726-/* in arch/arm/plat-omap/fb.c */
1727-extern void omapfb_set_ctrl_platform_data(void *pdata);
1728-
1729-#endif /* __KERNEL__ */
1730-
1731-#endif /* __OMAPFB_H */
1732--- a/arch/arm/plat-omap/include/mach/sdrc.h
1733+++ b/arch/arm/plat-omap/include/mach/sdrc.h
1734@@ -88,7 +88,10 @@
1735 
1736 /* SMS register offsets - read/write with sms_{read,write}_reg() */
1737 
1738-#define SMS_SYSCONFIG 0x010
1739+#define SMS_SYSCONFIG 0x010
1740+#define SMS_ROT_CONTROL(context) (0x180 + 0x10 * context)
1741+#define SMS_ROT_SIZE(context) (0x184 + 0x10 * context)
1742+#define SMS_ROT_PHYSICAL_BA(context) (0x188 + 0x10 * context)
1743 /* REVISIT: fill in other SMS registers here */
1744 
1745 
1746@@ -121,6 +124,10 @@ int omap2_sdrc_get_params(unsigned long
1747               struct omap_sdrc_params **sdrc_cs0,
1748               struct omap_sdrc_params **sdrc_cs1);
1749 
1750+void omap2_sms_write_rot_control(u32 val, unsigned ctx);
1751+void omap2_sms_write_rot_size(u32 val, unsigned ctx);
1752+void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx);
1753+
1754 #ifdef CONFIG_ARCH_OMAP2
1755 
1756 struct memory_timings {
1757--- /dev/null
1758+++ b/arch/arm/plat-omap/include/mach/vram.h
1759@@ -0,0 +1,63 @@
1760+/*
1761+ * VRAM manager for OMAP
1762+ *
1763+ * Copyright (C) 2009 Nokia Corporation
1764+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
1765+ *
1766+ * This program is free software; you can redistribute it and/or modify
1767+ * it under the terms of the GNU General Public License version 2 as
1768+ * published by the Free Software Foundation.
1769+ *
1770+ * This program is distributed in the hope that it will be useful, but
1771+ * WITHOUT ANY WARRANTY; without even the implied warranty of
1772+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1773+ * General Public License for more details.
1774+ *
1775+ * You should have received a copy of the GNU General Public License along
1776+ * with this program; if not, write to the Free Software Foundation, Inc.,
1777+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1778+ */
1779+
1780+#ifndef __OMAP_VRAM_H__
1781+#define __OMAP_VRAM_H__
1782+
1783+#include <linux/autoconf.h>
1784+#include <linux/types.h>
1785+
1786+#define OMAP_VRAM_MEMTYPE_SDRAM 0
1787+#define OMAP_VRAM_MEMTYPE_SRAM 1
1788+#define OMAP_VRAM_MEMTYPE_MAX 1
1789+
1790+extern int omap_vram_add_region(unsigned long paddr, size_t size);
1791+extern int omap_vram_free(unsigned long paddr, size_t size);
1792+extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr);
1793+extern int omap_vram_reserve(unsigned long paddr, size_t size);
1794+extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram,
1795+ unsigned long *largest_free_block);
1796+
1797+#ifdef CONFIG_OMAP2_VRAM
1798+extern void omap_vram_set_sdram_vram(u32 size, u32 start);
1799+extern void omap_vram_set_sram_vram(u32 size, u32 start);
1800+
1801+extern void omap_vram_reserve_sdram(void);
1802+extern unsigned long omap_vram_reserve_sram(unsigned long sram_pstart,
1803+ unsigned long sram_vstart,
1804+ unsigned long sram_size,
1805+ unsigned long pstart_avail,
1806+ unsigned long size_avail);
1807+#else
1808+static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { }
1809+static inline void omap_vram_set_sram_vram(u32 size, u32 start) { }
1810+
1811+static inline void omap_vram_reserve_sdram(void) { }
1812+static inline unsigned long omap_vram_reserve_sram(unsigned long sram_pstart,
1813+ unsigned long sram_vstart,
1814+ unsigned long sram_size,
1815+ unsigned long pstart_avail,
1816+ unsigned long size_avail)
1817+{
1818+ return 0;
1819+}
1820+#endif
1821+
1822+#endif
1823--- /dev/null
1824+++ b/arch/arm/plat-omap/include/mach/vrfb.h
1825@@ -0,0 +1,46 @@
1826+/*
1827+ * VRFB Rotation Engine
1828+ *
1829+ * Copyright (C) 2009 Nokia Corporation
1830+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
1831+ *
1832+ * This program is free software; you can redistribute it and/or modify
1833+ * it under the terms of the GNU General Public License version 2 as
1834+ * published by the Free Software Foundation.
1835+ *
1836+ * This program is distributed in the hope that it will be useful, but
1837+ * WITHOUT ANY WARRANTY; without even the implied warranty of
1838+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1839+ * General Public License for more details.
1840+ *
1841+ * You should have received a copy of the GNU General Public License along
1842+ * with this program; if not, write to the Free Software Foundation, Inc.,
1843+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1844+ */
1845+
1846+#ifndef __OMAP_VRFB_H__
1847+#define __OMAP_VRFB_H__
1848+
1849+#define OMAP_VRFB_LINE_LEN 2048
1850+
1851+struct vrfb {
1852+ u8 context;
1853+ void __iomem *vaddr[4];
1854+ unsigned long paddr[4];
1855+ u16 xoffset;
1856+ u16 yoffset;
1857+ u8 bytespp;
1858+};
1859+
1860+extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
1861+extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
1862+extern void omap_vrfb_suspend_ctx(struct vrfb *vrfb);
1863+extern void omap_vrfb_resume_ctx(struct vrfb *vrfb);
1864+extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
1865+ u8 bytespp);
1866+extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
1867+ u16 width, u16 height,
1868+ unsigned bytespp, bool yuv_mode);
1869+extern void omap_vrfb_restore_context(void);
1870+
1871+#endif /* __VRFB_H */
1872--- a/arch/arm/plat-omap/sram.c
1873+++ b/arch/arm/plat-omap/sram.c
1874@@ -28,6 +28,7 @@
1875 #include <mach/sram.h>
1876 #include <mach/board.h>
1877 #include <mach/cpu.h>
1878+#include <mach/vram.h>
1879 
1880 #include <mach/control.h>
1881 
1882@@ -185,6 +186,13 @@ void __init omap_detect_sram(void)
1883                        omap_sram_start + SRAM_BOOTLOADER_SZ,
1884                        omap_sram_size - SRAM_BOOTLOADER_SZ);
1885     omap_sram_size -= reserved;
1886+
1887+ reserved = omap_vram_reserve_sram(omap_sram_start, omap_sram_base,
1888+ omap_sram_size,
1889+ omap_sram_start + SRAM_BOOTLOADER_SZ,
1890+ omap_sram_size - SRAM_BOOTLOADER_SZ);
1891+ omap_sram_size -= reserved;
1892+
1893     omap_sram_ceil = omap_sram_base + omap_sram_size;
1894 }
1895 
1896--- a/drivers/video/Kconfig
1897+++ b/drivers/video/Kconfig
1898@@ -2161,6 +2161,7 @@ config FB_BROADSHEET
1899       a bridge adapter.
1900 
1901 source "drivers/video/omap/Kconfig"
1902+source "drivers/video/omap2/Kconfig"
1903 
1904 source "drivers/video/backlight/Kconfig"
1905 source "drivers/video/display/Kconfig"
1906--- a/drivers/video/Makefile
1907+++ b/drivers/video/Makefile
1908@@ -124,6 +124,7 @@ obj-$(CONFIG_FB_SM501) += sm5
1909 obj-$(CONFIG_FB_XILINX) += xilinxfb.o
1910 obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
1911 obj-$(CONFIG_FB_OMAP) += omap/
1912+obj-y += omap2/
1913 obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
1914 obj-$(CONFIG_FB_CARMINE) += carminefb.o
1915 obj-$(CONFIG_FB_MB862XX) += mb862xx/
1916--- a/drivers/video/omap/Kconfig
1917+++ b/drivers/video/omap/Kconfig
1918@@ -1,6 +1,7 @@
1919 config FB_OMAP
1920     tristate "OMAP frame buffer support (EXPERIMENTAL)"
1921- depends on FB && ARCH_OMAP
1922+ depends on FB && ARCH_OMAP && (OMAP2_DSS = "n")
1923+
1924     select FB_CFB_FILLRECT
1925     select FB_CFB_COPYAREA
1926     select FB_CFB_IMAGEBLIT
1927@@ -72,7 +73,7 @@ config FB_OMAP_LCD_MIPID
1928 
1929 config FB_OMAP_BOOTLOADER_INIT
1930     bool "Check bootloader initialization"
1931- depends on FB_OMAP
1932+ depends on FB_OMAP || FB_OMAP2
1933     help
1934       Say Y here if you want to enable checking if the bootloader has
1935       already initialized the display controller. In this case the
1936--- a/drivers/video/omap/blizzard.c
1937+++ b/drivers/video/omap/blizzard.c
1938@@ -27,9 +27,9 @@
1939 #include <linux/clk.h>
1940 
1941 #include <mach/dma.h>
1942-#include <mach/omapfb.h>
1943 #include <mach/blizzard.h>
1944 
1945+#include "omapfb.h"
1946 #include "dispc.h"
1947 
1948 #define MODULE_NAME "blizzard"
1949--- a/drivers/video/omap/dispc.c
1950+++ b/drivers/video/omap/dispc.c
1951@@ -24,11 +24,12 @@
1952 #include <linux/vmalloc.h>
1953 #include <linux/clk.h>
1954 #include <linux/io.h>
1955+#include <linux/platform_device.h>
1956 
1957 #include <mach/sram.h>
1958-#include <mach/omapfb.h>
1959 #include <mach/board.h>
1960 
1961+#include "omapfb.h"
1962 #include "dispc.h"
1963 
1964 #define MODULE_NAME "dispc"
1965@@ -188,6 +189,11 @@ static struct {
1966     struct omapfb_color_key color_key;
1967 } dispc;
1968 
1969+static struct platform_device omapdss_device = {
1970+ .name = "omapdss",
1971+ .id = -1,
1972+};
1973+
1974 static void enable_lcd_clocks(int enable);
1975 
1976 static void inline dispc_write_reg(int idx, u32 val)
1977@@ -907,20 +913,20 @@ static irqreturn_t omap_dispc_irq_handle
1978 
1979 static int get_dss_clocks(void)
1980 {
1981- dispc.dss_ick = clk_get(dispc.fbdev->dev, "ick");
1982+ dispc.dss_ick = clk_get(&omapdss_device.dev, "ick");
1983     if (IS_ERR(dispc.dss_ick)) {
1984         dev_err(dispc.fbdev->dev, "can't get ick\n");
1985         return PTR_ERR(dispc.dss_ick);
1986     }
1987 
1988- dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck");
1989+ dispc.dss1_fck = clk_get(&omapdss_device.dev, "dss1_fck");
1990     if (IS_ERR(dispc.dss1_fck)) {
1991         dev_err(dispc.fbdev->dev, "can't get dss1_fck\n");
1992         clk_put(dispc.dss_ick);
1993         return PTR_ERR(dispc.dss1_fck);
1994     }
1995 
1996- dispc.dss_54m_fck = clk_get(dispc.fbdev->dev, "tv_fck");
1997+ dispc.dss_54m_fck = clk_get(&omapdss_device.dev, "tv_fck");
1998     if (IS_ERR(dispc.dss_54m_fck)) {
1999         dev_err(dispc.fbdev->dev, "can't get tv_fck\n");
2000         clk_put(dispc.dss_ick);
2001@@ -1371,6 +1377,12 @@ static int omap_dispc_init(struct omapfb
2002     int skip_init = 0;
2003     int i;
2004 
2005+ r = platform_device_register(&omapdss_device);
2006+ if (r) {
2007+ dev_err(fbdev->dev, "can't register omapdss device\n");
2008+ return r;
2009+ }
2010+
2011     memset(&dispc, 0, sizeof(dispc));
2012 
2013     dispc.base = ioremap(DISPC_BASE, SZ_1K);
2014@@ -1508,6 +1520,7 @@ static void omap_dispc_cleanup(void)
2015     free_irq(INT_24XX_DSS_IRQ, dispc.fbdev);
2016     put_dss_clocks();
2017     iounmap(dispc.base);
2018+ platform_device_unregister(&omapdss_device);
2019 }
2020 
2021 const struct lcd_ctrl omap2_int_ctrl = {
2022--- a/drivers/video/omap/hwa742.c
2023+++ b/drivers/video/omap/hwa742.c
2024@@ -27,8 +27,8 @@
2025 #include <linux/clk.h>
2026 
2027 #include <mach/dma.h>
2028-#include <mach/omapfb.h>
2029 #include <mach/hwa742.h>
2030+#include "omapfb.h"
2031 
2032 #define HWA742_REV_CODE_REG 0x0
2033 #define HWA742_CONFIG_REG 0x2
2034--- a/drivers/video/omap/lcd_2430sdp.c
2035+++ b/drivers/video/omap/lcd_2430sdp.c
2036@@ -28,9 +28,10 @@
2037 #include <linux/i2c/twl4030.h>
2038 
2039 #include <mach/mux.h>
2040-#include <mach/omapfb.h>
2041 #include <asm/mach-types.h>
2042 
2043+#include "omapfb.h"
2044+
2045 #define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91
2046 #define SDP2430_LCD_PANEL_ENABLE_GPIO 154
2047 #define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 24
2048--- a/drivers/video/omap/lcd_ams_delta.c
2049+++ b/drivers/video/omap/lcd_ams_delta.c
2050@@ -27,7 +27,8 @@
2051 
2052 #include <mach/board-ams-delta.h>
2053 #include <mach/hardware.h>
2054-#include <mach/omapfb.h>
2055+
2056+#include "omapfb.h"
2057 
2058 #define AMS_DELTA_DEFAULT_CONTRAST 112
2059 
2060--- a/drivers/video/omap/lcd_apollon.c
2061+++ b/drivers/video/omap/lcd_apollon.c
2062@@ -26,7 +26,8 @@
2063 
2064 #include <mach/gpio.h>
2065 #include <mach/mux.h>
2066-#include <mach/omapfb.h>
2067+
2068+#include "omapfb.h"
2069 
2070 /* #define USE_35INCH_LCD 1 */
2071 
2072--- a/drivers/video/omap/lcd_h3.c
2073+++ b/drivers/video/omap/lcd_h3.c
2074@@ -24,7 +24,7 @@
2075 #include <linux/i2c/tps65010.h>
2076 
2077 #include <mach/gpio.h>
2078-#include <mach/omapfb.h>
2079+#include "omapfb.h"
2080 
2081 #define MODULE_NAME "omapfb-lcd_h3"
2082 
2083--- a/drivers/video/omap/lcd_h4.c
2084+++ b/drivers/video/omap/lcd_h4.c
2085@@ -22,7 +22,7 @@
2086 #include <linux/module.h>
2087 #include <linux/platform_device.h>
2088 
2089-#include <mach/omapfb.h>
2090+#include "omapfb.h"
2091 
2092 static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
2093 {
2094--- a/drivers/video/omap/lcd_inn1510.c
2095+++ b/drivers/video/omap/lcd_inn1510.c
2096@@ -24,7 +24,7 @@
2097 #include <linux/io.h>
2098 
2099 #include <mach/fpga.h>
2100-#include <mach/omapfb.h>
2101+#include "omapfb.h"
2102 
2103 static int innovator1510_panel_init(struct lcd_panel *panel,
2104                     struct omapfb_device *fbdev)
2105--- a/drivers/video/omap/lcd_inn1610.c
2106+++ b/drivers/video/omap/lcd_inn1610.c
2107@@ -23,7 +23,7 @@
2108 #include <linux/platform_device.h>
2109 
2110 #include <mach/gpio.h>
2111-#include <mach/omapfb.h>
2112+#include "omapfb.h"
2113 
2114 #define MODULE_NAME "omapfb-lcd_h3"
2115 
2116--- a/drivers/video/omap/lcd_ldp.c
2117+++ b/drivers/video/omap/lcd_ldp.c
2118@@ -28,9 +28,10 @@
2119 
2120 #include <mach/gpio.h>
2121 #include <mach/mux.h>
2122-#include <mach/omapfb.h>
2123 #include <asm/mach-types.h>
2124 
2125+#include "omapfb.h"
2126+
2127 #define LCD_PANEL_BACKLIGHT_GPIO (15 + OMAP_MAX_GPIO_LINES)
2128 #define LCD_PANEL_ENABLE_GPIO (7 + OMAP_MAX_GPIO_LINES)
2129 
2130--- a/drivers/video/omap/lcd_mipid.c
2131+++ b/drivers/video/omap/lcd_mipid.c
2132@@ -23,9 +23,10 @@
2133 #include <linux/workqueue.h>
2134 #include <linux/spi/spi.h>
2135 
2136-#include <mach/omapfb.h>
2137 #include <mach/lcd_mipid.h>
2138 
2139+#include "omapfb.h"
2140+
2141 #define MIPID_MODULE_NAME "lcd_mipid"
2142 
2143 #define MIPID_CMD_READ_DISP_ID 0x04
2144--- a/drivers/video/omap/lcd_omap2evm.c
2145+++ b/drivers/video/omap/lcd_omap2evm.c
2146@@ -27,9 +27,10 @@
2147 #include <linux/i2c/twl4030.h>
2148 
2149 #include <mach/mux.h>
2150-#include <mach/omapfb.h>
2151 #include <asm/mach-types.h>
2152 
2153+#include "omapfb.h"
2154+
2155 #define LCD_PANEL_ENABLE_GPIO 154
2156 #define LCD_PANEL_LR 128
2157 #define LCD_PANEL_UD 129
2158--- a/drivers/video/omap/lcd_omap3beagle.c
2159+++ b/drivers/video/omap/lcd_omap3beagle.c
2160@@ -26,9 +26,10 @@
2161 #include <linux/i2c/twl4030.h>
2162 
2163 #include <mach/mux.h>
2164-#include <mach/omapfb.h>
2165 #include <asm/mach-types.h>
2166 
2167+#include "omapfb.h"
2168+
2169 #define LCD_PANEL_ENABLE_GPIO 170
2170 
2171 static int omap3beagle_panel_init(struct lcd_panel *panel,
2172--- a/drivers/video/omap/lcd_omap3evm.c
2173+++ b/drivers/video/omap/lcd_omap3evm.c
2174@@ -26,9 +26,10 @@
2175 #include <linux/i2c/twl4030.h>
2176 
2177 #include <mach/mux.h>
2178-#include <mach/omapfb.h>
2179 #include <asm/mach-types.h>
2180 
2181+#include "omapfb.h"
2182+
2183 #define LCD_PANEL_ENABLE_GPIO 153
2184 #define LCD_PANEL_LR 2
2185 #define LCD_PANEL_UD 3
2186--- a/drivers/video/omap/lcd_osk.c
2187+++ b/drivers/video/omap/lcd_osk.c
2188@@ -25,7 +25,7 @@
2189 
2190 #include <mach/gpio.h>
2191 #include <mach/mux.h>
2192-#include <mach/omapfb.h>
2193+#include "omapfb.h"
2194 
2195 static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
2196 {
2197--- a/drivers/video/omap/lcd_overo.c
2198+++ b/drivers/video/omap/lcd_overo.c
2199@@ -25,9 +25,10 @@
2200 
2201 #include <mach/gpio.h>
2202 #include <mach/mux.h>
2203-#include <mach/omapfb.h>
2204 #include <asm/mach-types.h>
2205 
2206+#include "omapfb.h"
2207+
2208 #define LCD_ENABLE 144
2209 
2210 static int overo_panel_init(struct lcd_panel *panel,
2211--- a/drivers/video/omap/lcd_palmte.c
2212+++ b/drivers/video/omap/lcd_palmte.c
2213@@ -24,7 +24,7 @@
2214 #include <linux/io.h>
2215 
2216 #include <mach/fpga.h>
2217-#include <mach/omapfb.h>
2218+#include "omapfb.h"
2219 
2220 static int palmte_panel_init(struct lcd_panel *panel,
2221                 struct omapfb_device *fbdev)
2222--- a/drivers/video/omap/lcd_palmtt.c
2223+++ b/drivers/video/omap/lcd_palmtt.c
2224@@ -30,7 +30,7 @@ GPIO13 - screen blanking
2225 #include <linux/io.h>
2226 
2227 #include <mach/gpio.h>
2228-#include <mach/omapfb.h>
2229+#include "omapfb.h"
2230 
2231 static int palmtt_panel_init(struct lcd_panel *panel,
2232     struct omapfb_device *fbdev)
2233--- a/drivers/video/omap/lcd_palmz71.c
2234+++ b/drivers/video/omap/lcd_palmz71.c
2235@@ -24,7 +24,7 @@
2236 #include <linux/platform_device.h>
2237 #include <linux/io.h>
2238 
2239-#include <mach/omapfb.h>
2240+#include "omapfb.h"
2241 
2242 static int palmz71_panel_init(struct lcd_panel *panel,
2243                   struct omapfb_device *fbdev)
2244--- a/drivers/video/omap/lcdc.c
2245+++ b/drivers/video/omap/lcdc.c
2246@@ -30,10 +30,11 @@
2247 #include <linux/clk.h>
2248 
2249 #include <mach/dma.h>
2250-#include <mach/omapfb.h>
2251 
2252 #include <asm/mach-types.h>
2253 
2254+#include "omapfb.h"
2255+
2256 #include "lcdc.h"
2257 
2258 #define MODULE_NAME "lcdc"
2259--- /dev/null
2260+++ b/drivers/video/omap/omapfb.h
2261@@ -0,0 +1,227 @@
2262+/*
2263+ * File: drivers/video/omap/omapfb.h
2264+ *
2265+ * Framebuffer driver for TI OMAP boards
2266+ *
2267+ * Copyright (C) 2004 Nokia Corporation
2268+ * Author: Imre Deak <imre.deak@nokia.com>
2269+ *
2270+ * This program is free software; you can redistribute it and/or modify it
2271+ * under the terms of the GNU General Public License as published by the
2272+ * Free Software Foundation; either version 2 of the License, or (at your
2273+ * option) any later version.
2274+ *
2275+ * This program is distributed in the hope that it will be useful, but
2276+ * WITHOUT ANY WARRANTY; without even the implied warranty of
2277+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2278+ * General Public License for more details.
2279+ *
2280+ * You should have received a copy of the GNU General Public License along
2281+ * with this program; if not, write to the Free Software Foundation, Inc.,
2282+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2283+ */
2284+
2285+#ifndef __OMAPFB_H
2286+#define __OMAPFB_H
2287+
2288+#include <linux/fb.h>
2289+#include <linux/mutex.h>
2290+#include <linux/omapfb.h>
2291+
2292+#define OMAPFB_EVENT_READY 1
2293+#define OMAPFB_EVENT_DISABLED 2
2294+
2295+#define OMAP_LCDC_INV_VSYNC 0x0001
2296+#define OMAP_LCDC_INV_HSYNC 0x0002
2297+#define OMAP_LCDC_INV_PIX_CLOCK 0x0004
2298+#define OMAP_LCDC_INV_OUTPUT_EN 0x0008
2299+#define OMAP_LCDC_HSVS_RISING_EDGE 0x0010
2300+#define OMAP_LCDC_HSVS_OPPOSITE 0x0020
2301+
2302+#define OMAP_LCDC_SIGNAL_MASK 0x003f
2303+
2304+#define OMAP_LCDC_PANEL_TFT 0x0100
2305+
2306+#define OMAPFB_PLANE_XRES_MIN 8
2307+#define OMAPFB_PLANE_YRES_MIN 8
2308+
2309+struct omapfb_device;
2310+
2311+struct lcd_panel {
2312+ const char *name;
2313+ int config; /* TFT/STN, signal inversion */
2314+ int bpp; /* Pixel format in fb mem */
2315+ int data_lines; /* Lines on LCD HW interface */
2316+
2317+ int x_res, y_res;
2318+ int pixel_clock; /* In kHz */
2319+ int hsw; /* Horizontal synchronization
2320+ pulse width */
2321+ int hfp; /* Horizontal front porch */
2322+ int hbp; /* Horizontal back porch */
2323+ int vsw; /* Vertical synchronization
2324+ pulse width */
2325+ int vfp; /* Vertical front porch */
2326+ int vbp; /* Vertical back porch */
2327+ int acb; /* ac-bias pin frequency */
2328+ int pcd; /* pixel clock divider.
2329+ Obsolete use pixel_clock instead */
2330+
2331+ int (*init) (struct lcd_panel *panel,
2332+ struct omapfb_device *fbdev);
2333+ void (*cleanup) (struct lcd_panel *panel);
2334+ int (*enable) (struct lcd_panel *panel);
2335+ void (*disable) (struct lcd_panel *panel);
2336+ unsigned long (*get_caps) (struct lcd_panel *panel);
2337+ int (*set_bklight_level)(struct lcd_panel *panel,
2338+ unsigned int level);
2339+ unsigned int (*get_bklight_level)(struct lcd_panel *panel);
2340+ unsigned int (*get_bklight_max) (struct lcd_panel *panel);
2341+ int (*run_test) (struct lcd_panel *panel, int test_num);
2342+};
2343+
2344+struct extif_timings {
2345+ int cs_on_time;
2346+ int cs_off_time;
2347+ int we_on_time;
2348+ int we_off_time;
2349+ int re_on_time;
2350+ int re_off_time;
2351+ int we_cycle_time;
2352+ int re_cycle_time;
2353+ int cs_pulse_width;
2354+ int access_time;
2355+
2356+ int clk_div;
2357+
2358+ u32 tim[5]; /* set by extif->convert_timings */
2359+
2360+ int converted;
2361+};
2362+
2363+struct lcd_ctrl_extif {
2364+ int (*init) (struct omapfb_device *fbdev);
2365+ void (*cleanup) (void);
2366+ void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div);
2367+ unsigned long (*get_max_tx_rate)(void);
2368+ int (*convert_timings) (struct extif_timings *timings);
2369+ void (*set_timings) (const struct extif_timings *timings);
2370+ void (*set_bits_per_cycle)(int bpc);
2371+ void (*write_command) (const void *buf, unsigned int len);
2372+ void (*read_data) (void *buf, unsigned int len);
2373+ void (*write_data) (const void *buf, unsigned int len);
2374+ void (*transfer_area) (int width, int height,
2375+ void (callback)(void *data), void *data);
2376+ int (*setup_tearsync) (unsigned pin_cnt,
2377+ unsigned hs_pulse_time, unsigned vs_pulse_time,
2378+ int hs_pol_inv, int vs_pol_inv, int div);
2379+ int (*enable_tearsync) (int enable, unsigned line);
2380+
2381+ unsigned long max_transmit_size;
2382+};
2383+
2384+struct omapfb_notifier_block {
2385+ struct notifier_block nb;
2386+ void *data;
2387+ int plane_idx;
2388+};
2389+
2390+typedef int (*omapfb_notifier_callback_t)(struct notifier_block *,
2391+ unsigned long event,
2392+ void *fbi);
2393+
2394+struct lcd_ctrl {
2395+ const char *name;
2396+ void *data;
2397+
2398+ int (*init) (struct omapfb_device *fbdev,
2399+ int ext_mode,
2400+ struct omapfb_mem_desc *req_md);
2401+ void (*cleanup) (void);
2402+ void (*bind_client) (struct omapfb_notifier_block *nb);
2403+ void (*get_caps) (int plane, struct omapfb_caps *caps);
2404+ int (*set_update_mode)(enum omapfb_update_mode mode);
2405+ enum omapfb_update_mode (*get_update_mode)(void);
2406+ int (*setup_plane) (int plane, int channel_out,
2407+ unsigned long offset,
2408+ int screen_width,
2409+ int pos_x, int pos_y, int width,
2410+ int height, int color_mode);
2411+ int (*set_rotate) (int angle);
2412+ int (*setup_mem) (int plane, size_t size,
2413+ int mem_type, unsigned long *paddr);
2414+ int (*mmap) (struct fb_info *info,
2415+ struct vm_area_struct *vma);
2416+ int (*set_scale) (int plane,
2417+ int orig_width, int orig_height,
2418+ int out_width, int out_height);
2419+ int (*enable_plane) (int plane, int enable);
2420+ int (*update_window) (struct fb_info *fbi,
2421+ struct omapfb_update_window *win,
2422+ void (*callback)(void *),
2423+ void *callback_data);
2424+ void (*sync) (void);
2425+ void (*suspend) (void);
2426+ void (*resume) (void);
2427+ int (*run_test) (int test_num);
2428+ int (*setcolreg) (u_int regno, u16 red, u16 green,
2429+ u16 blue, u16 transp,
2430+ int update_hw_mem);
2431+ int (*set_color_key) (struct omapfb_color_key *ck);
2432+ int (*get_color_key) (struct omapfb_color_key *ck);
2433+};
2434+
2435+enum omapfb_state {
2436+ OMAPFB_DISABLED = 0,
2437+ OMAPFB_SUSPENDED = 99,
2438+ OMAPFB_ACTIVE = 100
2439+};
2440+
2441+struct omapfb_plane_struct {
2442+ int idx;
2443+ struct omapfb_plane_info info;
2444+ enum omapfb_color_format color_mode;
2445+ struct omapfb_device *fbdev;
2446+};
2447+
2448+struct omapfb_device {
2449+ int state;
2450+ int ext_lcdc; /* Using external
2451+ LCD controller */
2452+ struct mutex rqueue_mutex;
2453+
2454+ int palette_size;
2455+ u32 pseudo_palette[17];
2456+
2457+ struct lcd_panel *panel; /* LCD panel */
2458+ const struct lcd_ctrl *ctrl; /* LCD controller */
2459+ const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */
2460+ struct lcd_ctrl_extif *ext_if; /* LCD ctrl external
2461+ interface */
2462+ struct device *dev;
2463+ struct fb_var_screeninfo new_var; /* for mode changes */
2464+
2465+ struct omapfb_mem_desc mem_desc;
2466+ struct fb_info *fb_info[OMAPFB_PLANE_NUM];
2467+};
2468+
2469+#ifdef CONFIG_ARCH_OMAP1
2470+extern struct lcd_ctrl omap1_lcd_ctrl;
2471+#else
2472+extern struct lcd_ctrl omap2_disp_ctrl;
2473+#endif
2474+
2475+extern void omapfb_register_panel(struct lcd_panel *panel);
2476+extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
2477+extern void omapfb_notify_clients(struct omapfb_device *fbdev,
2478+ unsigned long event);
2479+extern int omapfb_register_client(struct omapfb_notifier_block *nb,
2480+ omapfb_notifier_callback_t callback,
2481+ void *callback_data);
2482+extern int omapfb_unregister_client(struct omapfb_notifier_block *nb);
2483+extern int omapfb_update_window_async(struct fb_info *fbi,
2484+ struct omapfb_update_window *win,
2485+ void (*callback)(void *),
2486+ void *callback_data);
2487+
2488+#endif /* __OMAPFB_H */
2489--- a/drivers/video/omap/omapfb_main.c
2490+++ b/drivers/video/omap/omapfb_main.c
2491@@ -29,8 +29,8 @@
2492 #include <linux/uaccess.h>
2493 
2494 #include <mach/dma.h>
2495-#include <mach/omapfb.h>
2496 
2497+#include "omapfb.h"
2498 #include "lcdc.h"
2499 #include "dispc.h"
2500 
2501--- a/drivers/video/omap/rfbi.c
2502+++ b/drivers/video/omap/rfbi.c
2503@@ -27,8 +27,7 @@
2504 #include <linux/clk.h>
2505 #include <linux/io.h>
2506 
2507-#include <mach/omapfb.h>
2508-
2509+#include "omapfb.h"
2510 #include "dispc.h"
2511 
2512 /* To work around an RFBI transfer rate limitation */
2513--- a/drivers/video/omap/sossi.c
2514+++ b/drivers/video/omap/sossi.c
2515@@ -25,8 +25,8 @@
2516 #include <linux/io.h>
2517 
2518 #include <mach/dma.h>
2519-#include <mach/omapfb.h>
2520 
2521+#include "omapfb.h"
2522 #include "lcdc.h"
2523 
2524 #define MODULE_NAME "omapfb-sossi"
2525--- /dev/null
2526+++ b/drivers/video/omap2/Kconfig
2527@@ -0,0 +1,9 @@
2528+config OMAP2_VRAM
2529+ bool
2530+
2531+config OMAP2_VRFB
2532+ bool
2533+
2534+source "drivers/video/omap2/dss/Kconfig"
2535+source "drivers/video/omap2/omapfb/Kconfig"
2536+source "drivers/video/omap2/displays/Kconfig"
2537--- /dev/null
2538+++ b/drivers/video/omap2/Makefile
2539@@ -0,0 +1,6 @@
2540+obj-$(CONFIG_OMAP2_VRAM) += vram.o
2541+obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
2542+
2543+obj-y += dss/
2544+obj-y += omapfb/
2545+obj-y += displays/
2546--- /dev/null
2547+++ b/drivers/video/omap2/displays/Kconfig
2548@@ -0,0 +1,28 @@
2549+menu "OMAP2/3 Display Device Drivers"
2550+ depends on OMAP2_DSS
2551+
2552+config PANEL_GENERIC
2553+ tristate "Generic Panel"
2554+ help
2555+ Generic panel driver.
2556+ Used for DVI output for Beagle and OMAP3 SDP.
2557+
2558+config PANEL_SAMSUNG_LTE430WQ_F0C
2559+ tristate "Samsung LTE430WQ-F0C LCD Panel"
2560+ depends on OMAP2_DSS
2561+ help
2562+ LCD Panel used on Overo Palo43
2563+
2564+config PANEL_SHARP_LS037V7DW01
2565+ tristate "Sharp LS037V7DW01 LCD Panel"
2566+ depends on OMAP2_DSS
2567+ help
2568+ LCD Panel used in TI's SDP3430 and EVM boards
2569+
2570+config PANEL_TAAL
2571+ tristate "Taal DSI Panel"
2572+ depends on OMAP2_DSS_DSI
2573+ help
2574+ Taal DSI command mode panel from TPO.
2575+
2576+endmenu
2577--- /dev/null
2578+++ b/drivers/video/omap2/displays/Makefile
2579@@ -0,0 +1,5 @@
2580+obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o
2581+obj-$(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) += panel-samsung-lte430wq-f0c.o
2582+obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
2583+
2584+obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
2585--- /dev/null
2586+++ b/drivers/video/omap2/displays/panel-generic.c
2587@@ -0,0 +1,104 @@
2588+/*
2589+ * Generic panel support
2590+ *
2591+ * Copyright (C) 2008 Nokia Corporation
2592+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
2593+ *
2594+ * This program is free software; you can redistribute it and/or modify it
2595+ * under the terms of the GNU General Public License version 2 as published by
2596+ * the Free Software Foundation.
2597+ *
2598+ * This program is distributed in the hope that it will be useful, but WITHOUT
2599+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2600+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
2601+ * more details.
2602+ *
2603+ * You should have received a copy of the GNU General Public License along with
2604+ * this program. If not, see <http://www.gnu.org/licenses/>.
2605+ */
2606+
2607+#include <linux/module.h>
2608+#include <linux/delay.h>
2609+
2610+#include <mach/display.h>
2611+
2612+static struct omap_video_timings generic_panel_timings = {
2613+ /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
2614+ .x_res = 640,
2615+ .y_res = 480,
2616+ .pixel_clock = 23500,
2617+ .hfp = 48,
2618+ .hsw = 32,
2619+ .hbp = 80,
2620+ .vfp = 3,
2621+ .vsw = 4,
2622+ .vbp = 7,
2623+};
2624+
2625+static int generic_panel_probe(struct omap_dss_device *dssdev)
2626+{
2627+ dssdev->panel.config = OMAP_DSS_LCD_TFT;
2628+ dssdev->panel.timings = generic_panel_timings;
2629+
2630+ return 0;
2631+}
2632+
2633+static void generic_panel_remove(struct omap_dss_device *dssdev)
2634+{
2635+}
2636+
2637+static int generic_panel_enable(struct omap_dss_device *dssdev)
2638+{
2639+ int r = 0;
2640+
2641+ if (dssdev->platform_enable)
2642+ r = dssdev->platform_enable(dssdev);
2643+
2644+ return r;
2645+}
2646+
2647+static void generic_panel_disable(struct omap_dss_device *dssdev)
2648+{
2649+ if (dssdev->platform_disable)
2650+ dssdev->platform_disable(dssdev);
2651+}
2652+
2653+static int generic_panel_suspend(struct omap_dss_device *dssdev)
2654+{
2655+ generic_panel_disable(dssdev);
2656+ return 0;
2657+}
2658+
2659+static int generic_panel_resume(struct omap_dss_device *dssdev)
2660+{
2661+ return generic_panel_enable(dssdev);
2662+}
2663+
2664+static struct omap_dss_driver generic_driver = {
2665+ .probe = generic_panel_probe,
2666+ .remove = generic_panel_remove,
2667+
2668+ .enable = generic_panel_enable,
2669+ .disable = generic_panel_disable,
2670+ .suspend = generic_panel_suspend,
2671+ .resume = generic_panel_resume,
2672+
2673+ .driver = {
2674+ .name = "generic_panel",
2675+ .owner = THIS_MODULE,
2676+ },
2677+};
2678+
2679+static int __init generic_panel_drv_init(void)
2680+{
2681+ return omap_dss_register_driver(&generic_driver);
2682+}
2683+
2684+static void __exit generic_panel_drv_exit(void)
2685+{
2686+ omap_dss_unregister_driver(&generic_driver);
2687+}
2688+
2689+module_init(generic_panel_drv_init);
2690+module_exit(generic_panel_drv_exit);
2691+MODULE_LICENSE("GPL");
2692--- /dev/null
2693+++ b/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c
2694@@ -0,0 +1,113 @@
2695+/*
2696+ * LCD panel driver for Samsung LTE430WQ-F0C
2697+ *
2698+ * Author: Steve Sakoman <steve@sakoman.com>
2699+ *
2700+ * This program is free software; you can redistribute it and/or modify it
2701+ * under the terms of the GNU General Public License version 2 as published by
2702+ * the Free Software Foundation.
2703+ *
2704+ * This program is distributed in the hope that it will be useful, but WITHOUT
2705+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2706+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
2707+ * more details.
2708+ *
2709+ * You should have received a copy of the GNU General Public License along with
2710+ * this program. If not, see <http://www.gnu.org/licenses/>.
2711+ */
2712+
2713+#include <linux/module.h>
2714+#include <linux/delay.h>
2715+
2716+#include <mach/display.h>
2717+
2718+static struct omap_video_timings samsung_lte_timings = {
2719+ .x_res = 480,
2720+ .y_res = 272,
2721+
2722+ .pixel_clock = 9200,
2723+
2724+ .hsw = 41,
2725+ .hfp = 8,
2726+ .hbp = 45-41,
2727+
2728+ .vsw = 10,
2729+ .vfp = 4,
2730+ .vbp = 12-10,
2731+};
2732+
2733+static int samsung_lte_panel_probe(struct omap_dss_device *dssdev)
2734+{
2735+ dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
2736+ OMAP_DSS_LCD_IHS;
2737+ dssdev->panel.timings = samsung_lte_timings;
2738+
2739+ return 0;
2740+}
2741+
2742+static void samsung_lte_panel_remove(struct omap_dss_device *dssdev)
2743+{
2744+}
2745+
2746+static int samsung_lte_panel_enable(struct omap_dss_device *dssdev)
2747+{
2748+ int r = 0;
2749+
2750+ /* wait couple of vsyncs until enabling the LCD */
2751+ msleep(50);
2752+
2753+ if (dssdev->platform_enable)
2754+ r = dssdev->platform_enable(dssdev);
2755+
2756+ return r;
2757+}
2758+
2759+static void samsung_lte_panel_disable(struct omap_dss_device *dssdev)
2760+{
2761+ if (dssdev->platform_disable)
2762+ dssdev->platform_disable(dssdev);
2763+
2764+ /* wait at least 5 vsyncs after disabling the LCD */
2765+
2766+ msleep(100);
2767+}
2768+
2769+static int samsung_lte_panel_suspend(struct omap_dss_device *dssdev)
2770+{
2771+ samsung_lte_panel_disable(dssdev);
2772+ return 0;
2773+}
2774+
2775+static int samsung_lte_panel_resume(struct omap_dss_device *dssdev)
2776+{
2777+ return samsung_lte_panel_enable(dssdev);
2778+}
2779+
2780+static struct omap_dss_driver samsung_lte_driver = {
2781+ .probe = samsung_lte_panel_probe,
2782+ .remove = samsung_lte_panel_remove,
2783+
2784+ .enable = samsung_lte_panel_enable,
2785+ .disable = samsung_lte_panel_disable,
2786+ .suspend = samsung_lte_panel_suspend,
2787+ .resume = samsung_lte_panel_resume,
2788+
2789+ .driver = {
2790+ .name = "samsung_lte_panel",
2791+ .owner = THIS_MODULE,
2792+ },
2793+};
2794+
2795+static int __init samsung_lte_panel_drv_init(void)
2796+{
2797+ return omap_dss_register_driver(&samsung_lte_driver);
2798+}
2799+
2800+static void __exit samsung_lte_panel_drv_exit(void)
2801+{
2802+ omap_dss_unregister_driver(&samsung_lte_driver);
2803+}
2804+
2805+module_init(samsung_lte_panel_drv_init);
2806+module_exit(samsung_lte_panel_drv_exit);
2807+MODULE_LICENSE("GPL");
2808--- /dev/null
2809+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
2810@@ -0,0 +1,153 @@
2811+/*
2812+ * LCD panel driver for Sharp LS037V7DW01
2813+ *
2814+ * Copyright (C) 2008 Nokia Corporation
2815+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
2816+ *
2817+ * This program is free software; you can redistribute it and/or modify it
2818+ * under the terms of the GNU General Public License version 2 as published by
2819+ * the Free Software Foundation.
2820+ *
2821+ * This program is distributed in the hope that it will be useful, but WITHOUT
2822+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2823+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
2824+ * more details.
2825+ *
2826+ * You should have received a copy of the GNU General Public License along with
2827+ * this program. If not, see <http://www.gnu.org/licenses/>.
2828+ */
2829+
2830+#include <linux/module.h>
2831+#include <linux/delay.h>
2832+#include <linux/device.h>
2833+#include <linux/regulator/consumer.h>
2834+#include <linux/err.h>
2835+
2836+#include <mach/display.h>
2837+
2838+struct sharp_data {
2839+ /* XXX This regulator should actually be in SDP board file, not here,
2840+ * as it doesn't actually power the LCD, but something else that
2841+ * affects the output to LCD (I think. Somebody clarify). It doesn't do
2842+ * harm here, as SDP is the only board using this currently */
2843+ struct regulator *vdvi_reg;
2844+};
2845+
2846+static struct omap_video_timings sharp_ls_timings = {
2847+ .x_res = 480,
2848+ .y_res = 640,
2849+
2850+ .pixel_clock = 19200,
2851+
2852+ .hsw = 2,
2853+ .hfp = 1,
2854+ .hbp = 28,
2855+
2856+ .vsw = 1,
2857+ .vfp = 1,
2858+ .vbp = 1,
2859+};
2860+
2861+static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
2862+{
2863+ struct sharp_data *sd;
2864+
2865+ dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
2866+ OMAP_DSS_LCD_IHS;
2867+ dssdev->panel.acb = 0x28;
2868+ dssdev->panel.timings = sharp_ls_timings;
2869+
2870+ sd = kzalloc(sizeof(*sd), GFP_KERNEL);
2871+ if (!sd)
2872+ return -ENOMEM;
2873+
2874+ dev_set_drvdata(&dssdev->dev, sd);
2875+
2876+ sd->vdvi_reg = regulator_get(&dssdev->dev, "vdvi");
2877+ if (IS_ERR(sd->vdvi_reg)) {
2878+ kfree(sd);
2879+ pr_err("failed to get VDVI regulator\n");
2880+ return PTR_ERR(sd->vdvi_reg);
2881+ }
2882+
2883+ return 0;
2884+}
2885+
2886+static void sharp_ls_panel_remove(struct omap_dss_device *dssdev)
2887+{
2888+ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
2889+
2890+ regulator_put(sd->vdvi_reg);
2891+
2892+ kfree(sd);
2893+}
2894+
2895+static int sharp_ls_panel_enable(struct omap_dss_device *dssdev)
2896+{
2897+ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
2898+ int r = 0;
2899+
2900+ /* wait couple of vsyncs until enabling the LCD */
2901+ msleep(50);
2902+
2903+ regulator_enable(sd->vdvi_reg);
2904+
2905+ if (dssdev->platform_enable)
2906+ r = dssdev->platform_enable(dssdev);
2907+
2908+ return r;
2909+}
2910+
2911+static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
2912+{
2913+ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
2914+
2915+ if (dssdev->platform_disable)
2916+ dssdev->platform_disable(dssdev);
2917+
2918+ regulator_disable(sd->vdvi_reg);
2919+
2920+ /* wait at least 5 vsyncs after disabling the LCD */
2921+
2922+ msleep(100);
2923+}
2924+
2925+static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev)
2926+{
2927+ sharp_ls_panel_disable(dssdev);
2928+ return 0;
2929+}
2930+
2931+static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
2932+{
2933+ return sharp_ls_panel_enable(dssdev);
2934+}
2935+
2936+static struct omap_dss_driver sharp_ls_driver = {
2937+ .probe = sharp_ls_panel_probe,
2938+ .remove = sharp_ls_panel_remove,
2939+
2940+ .enable = sharp_ls_panel_enable,
2941+ .disable = sharp_ls_panel_disable,
2942+ .suspend = sharp_ls_panel_suspend,
2943+ .resume = sharp_ls_panel_resume,
2944+
2945+ .driver = {
2946+ .name = "sharp_ls_panel",
2947+ .owner = THIS_MODULE,
2948+ },
2949+};
2950+
2951+static int __init sharp_ls_panel_drv_init(void)
2952+{
2953+ return omap_dss_register_driver(&sharp_ls_driver);
2954+}
2955+
2956+static void __exit sharp_ls_panel_drv_exit(void)
2957+{
2958+ omap_dss_unregister_driver(&sharp_ls_driver);
2959+}
2960+
2961+module_init(sharp_ls_panel_drv_init);
2962+module_exit(sharp_ls_panel_drv_exit);
2963+MODULE_LICENSE("GPL");
2964--- /dev/null
2965+++ b/drivers/video/omap2/displays/panel-taal.c
2966@@ -0,0 +1,900 @@
2967+/*
2968+ * Taal DSI command mode panel
2969+ *
2970+ * Copyright (C) 2009 Nokia Corporation
2971+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
2972+ *
2973+ * This program is free software; you can redistribute it and/or modify it
2974+ * under the terms of the GNU General Public License version 2 as published by
2975+ * the Free Software Foundation.
2976+ *
2977+ * This program is distributed in the hope that it will be useful, but WITHOUT
2978+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2979+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
2980+ * more details.
2981+ *
2982+ * You should have received a copy of the GNU General Public License along with
2983+ * this program. If not, see <http://www.gnu.org/licenses/>.
2984+ */
2985+
2986+/*#define DEBUG*/
2987+
2988+#include <linux/module.h>
2989+#include <linux/delay.h>
2990+#include <linux/err.h>
2991+#include <linux/jiffies.h>
2992+#include <linux/sched.h>
2993+#include <linux/backlight.h>
2994+#include <linux/fb.h>
2995+#include <linux/interrupt.h>
2996+#include <linux/gpio.h>
2997+#include <linux/completion.h>
2998+
2999+#include <mach/display.h>
3000+
3001+/* DSI Virtual channel. Hardcoded for now. */
3002+#define TCH 0
3003+
3004+#define DCS_READ_NUM_ERRORS 0x05
3005+#define DCS_READ_POWER_MODE 0x0a
3006+#define DCS_READ_MADCTL 0x0b
3007+#define DCS_READ_PIXEL_FORMAT 0x0c
3008+#define DCS_SLEEP_IN 0x10
3009+#define DCS_SLEEP_OUT 0x11
3010+#define DCS_DISPLAY_OFF 0x28
3011+#define DCS_DISPLAY_ON 0x29
3012+#define DCS_COLUMN_ADDR 0x2a
3013+#define DCS_PAGE_ADDR 0x2b
3014+#define DCS_MEMORY_WRITE 0x2c
3015+#define DCS_TEAR_OFF 0x34
3016+#define DCS_TEAR_ON 0x35
3017+#define DCS_MEM_ACC_CTRL 0x36
3018+#define DCS_PIXEL_FORMAT 0x3a
3019+#define DCS_BRIGHTNESS 0x51
3020+#define DCS_CTRL_DISPLAY 0x53
3021+#define DCS_WRITE_CABC 0x55
3022+#define DCS_READ_CABC 0x56
3023+#define DCS_GET_ID1 0xda
3024+#define DCS_GET_ID2 0xdb
3025+#define DCS_GET_ID3 0xdc
3026+
3027+struct taal_data {
3028+ struct backlight_device *bldev;
3029+
3030+ unsigned long hw_guard_end; /* next value of jiffies when we can
3031+ * issue the next sleep in/out command
3032+ */
3033+ unsigned long hw_guard_wait; /* max guard time in jiffies */
3034+
3035+ struct omap_dss_device *dssdev;
3036+
3037+ bool enabled;
3038+ u8 rotate;
3039+ bool mirror;
3040+
3041+ bool te_enabled;
3042+ bool use_ext_te;
3043+ struct completion te_completion;
3044+
3045+ bool use_dsi_bl;
3046+
3047+ bool cabc_broken;
3048+ unsigned cabc_mode;
3049+
3050+ bool intro_printed;
3051+};
3052+
3053+static void hw_guard_start(struct taal_data *td, int guard_msec)
3054+{
3055+ td->hw_guard_wait = msecs_to_jiffies(guard_msec);
3056+ td->hw_guard_end = jiffies + td->hw_guard_wait;
3057+}
3058+
3059+static void hw_guard_wait(struct taal_data *td)
3060+{
3061+ unsigned long wait = td->hw_guard_end - jiffies;
3062+
3063+ if ((long)wait > 0 && wait <= td->hw_guard_wait) {
3064+ set_current_state(TASK_UNINTERRUPTIBLE);
3065+ schedule_timeout(wait);
3066+ }
3067+}
3068+
3069+static int taal_dcs_read_1(u8 dcs_cmd, u8 *data)
3070+{
3071+ int r;
3072+ u8 buf[1];
3073+
3074+ r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1);
3075+
3076+ if (r < 0)
3077+ return r;
3078+
3079+ *data = buf[0];
3080+
3081+ return 0;
3082+}
3083+
3084+static int taal_dcs_write_0(u8 dcs_cmd)
3085+{
3086+ return dsi_vc_dcs_write(TCH, &dcs_cmd, 1);
3087+}
3088+
3089+static int taal_dcs_write_1(u8 dcs_cmd, u8 param)
3090+{
3091+ u8 buf[2];
3092+ buf[0] = dcs_cmd;
3093+ buf[1] = param;
3094+ return dsi_vc_dcs_write(TCH, buf, 2);
3095+}
3096+
3097+static int taal_sleep_in(struct taal_data *td)
3098+
3099+{
3100+ u8 cmd;
3101+ int r;
3102+
3103+ hw_guard_wait(td);
3104+
3105+ cmd = DCS_SLEEP_IN;
3106+ r = dsi_vc_dcs_write_nosync(TCH, &cmd, 1);
3107+ if (r)
3108+ return r;
3109+
3110+ hw_guard_start(td, 120);
3111+
3112+ msleep(5);
3113+
3114+ return 0;
3115+}
3116+
3117+static int taal_sleep_out(struct taal_data *td)
3118+{
3119+ int r;
3120+
3121+ hw_guard_wait(td);
3122+
3123+ r = taal_dcs_write_0(DCS_SLEEP_OUT);
3124+ if (r)
3125+ return r;
3126+
3127+ hw_guard_start(td, 120);
3128+
3129+ msleep(5);
3130+
3131+ return 0;
3132+}
3133+
3134+static int taal_get_id(u8 *id1, u8 *id2, u8 *id3)
3135+{
3136+ int r;
3137+
3138+ r = taal_dcs_read_1(DCS_GET_ID1, id1);
3139+ if (r)
3140+ return r;
3141+ r = taal_dcs_read_1(DCS_GET_ID2, id2);
3142+ if (r)
3143+ return r;
3144+ r = taal_dcs_read_1(DCS_GET_ID3, id3);
3145+ if (r)
3146+ return r;
3147+
3148+ return 0;
3149+}
3150+
3151+static int taal_set_addr_mode(u8 rotate, bool mirror)
3152+{
3153+ int r;
3154+ u8 mode;
3155+ int b5, b6, b7;
3156+
3157+ r = taal_dcs_read_1(DCS_READ_MADCTL, &mode);
3158+ if (r)
3159+ return r;
3160+
3161+ switch (rotate) {
3162+ default:
3163+ case 0:
3164+ b7 = 0;
3165+ b6 = 0;
3166+ b5 = 0;
3167+ break;
3168+ case 1:
3169+ b7 = 0;
3170+ b6 = 1;
3171+ b5 = 1;
3172+ break;
3173+ case 2:
3174+ b7 = 1;
3175+ b6 = 1;
3176+ b5 = 0;
3177+ break;
3178+ case 3:
3179+ b7 = 1;
3180+ b6 = 0;
3181+ b5 = 1;
3182+ break;
3183+ }
3184+
3185+ if (mirror)
3186+ b6 = !b6;
3187+
3188+ mode &= ~((1<<7) | (1<<6) | (1<<5));
3189+ mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
3190+
3191+ return taal_dcs_write_1(DCS_MEM_ACC_CTRL, mode);
3192+}
3193+
3194+static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h)
3195+{
3196+ int r;
3197+ u16 x1 = x;
3198+ u16 x2 = x + w - 1;
3199+ u16 y1 = y;
3200+ u16 y2 = y + h - 1;
3201+
3202+ u8 buf[5];
3203+ buf[0] = DCS_COLUMN_ADDR;
3204+ buf[1] = (x1 >> 8) & 0xff;
3205+ buf[2] = (x1 >> 0) & 0xff;
3206+ buf[3] = (x2 >> 8) & 0xff;
3207+ buf[4] = (x2 >> 0) & 0xff;
3208+
3209+ r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf));
3210+ if (r)
3211+ return r;
3212+
3213+ buf[0] = DCS_PAGE_ADDR;
3214+ buf[1] = (y1 >> 8) & 0xff;
3215+ buf[2] = (y1 >> 0) & 0xff;
3216+ buf[3] = (y2 >> 8) & 0xff;
3217+ buf[4] = (y2 >> 0) & 0xff;
3218+
3219+ r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf));
3220+ if (r)
3221+ return r;
3222+
3223+ dsi_vc_send_bta_sync(TCH);
3224+
3225+ return r;
3226+}
3227+
3228+static int taal_bl_update_status(struct backlight_device *dev)
3229+{
3230+ struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
3231+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3232+ int r;
3233+ int level;
3234+
3235+ if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
3236+ dev->props.power == FB_BLANK_UNBLANK)
3237+ level = dev->props.brightness;
3238+ else
3239+ level = 0;
3240+
3241+ dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
3242+
3243+ if (td->use_dsi_bl) {
3244+ if (td->enabled) {
3245+ dsi_bus_lock();
3246+ r = taal_dcs_write_1(DCS_BRIGHTNESS, level);
3247+ dsi_bus_unlock();
3248+ if (r)
3249+ return r;
3250+ }
3251+ } else {
3252+ if (!dssdev->set_backlight)
3253+ return -EINVAL;
3254+
3255+ r = dssdev->set_backlight(dssdev, level);
3256+ if (r)
3257+ return r;
3258+ }
3259+
3260+ return 0;
3261+}
3262+
3263+static int taal_bl_get_intensity(struct backlight_device *dev)
3264+{
3265+ if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
3266+ dev->props.power == FB_BLANK_UNBLANK)
3267+ return dev->props.brightness;
3268+
3269+ return 0;
3270+}
3271+
3272+static struct backlight_ops taal_bl_ops = {
3273+ .get_brightness = taal_bl_get_intensity,
3274+ .update_status = taal_bl_update_status,
3275+};
3276+
3277+static void taal_get_timings(struct omap_dss_device *dssdev,
3278+ struct omap_video_timings *timings)
3279+{
3280+ *timings = dssdev->panel.timings;
3281+}
3282+
3283+static void taal_get_resolution(struct omap_dss_device *dssdev,
3284+ u16 *xres, u16 *yres)
3285+{
3286+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3287+
3288+ if (td->rotate == 0 || td->rotate == 2) {
3289+ *xres = dssdev->panel.timings.x_res;
3290+ *yres = dssdev->panel.timings.y_res;
3291+ } else {
3292+ *yres = dssdev->panel.timings.x_res;
3293+ *xres = dssdev->panel.timings.y_res;
3294+ }
3295+}
3296+
3297+static irqreturn_t taal_te_isr(int irq, void *data)
3298+{
3299+ struct omap_dss_device *dssdev = data;
3300+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3301+
3302+ complete_all(&td->te_completion);
3303+
3304+ return IRQ_HANDLED;
3305+}
3306+
3307+static ssize_t taal_num_errors_show(struct device *dev,
3308+ struct device_attribute *attr, char *buf)
3309+{
3310+ struct omap_dss_device *dssdev = to_dss_device(dev);
3311+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3312+ u8 errors;
3313+ int r;
3314+
3315+ if (td->enabled) {
3316+ dsi_bus_lock();
3317+ r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors);
3318+ dsi_bus_unlock();
3319+ } else {
3320+ r = -ENODEV;
3321+ }
3322+
3323+ if (r)
3324+ return r;
3325+
3326+ return snprintf(buf, PAGE_SIZE, "%d\n", errors);
3327+}
3328+
3329+static ssize_t taal_hw_revision_show(struct device *dev,
3330+ struct device_attribute *attr, char *buf)
3331+{
3332+ struct omap_dss_device *dssdev = to_dss_device(dev);
3333+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3334+ u8 id1, id2, id3;
3335+ int r;
3336+
3337+ if (td->enabled) {
3338+ dsi_bus_lock();
3339+ r = taal_get_id(&id1, &id2, &id3);
3340+ dsi_bus_unlock();
3341+ } else {
3342+ r = -ENODEV;
3343+ }
3344+
3345+ if (r)
3346+ return r;
3347+
3348+ return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3);
3349+}
3350+
3351+static const char *cabc_modes[] = {
3352+ "off", /* used also always when CABC is not supported */
3353+ "ui",
3354+ "still-image",
3355+ "moving-image",
3356+};
3357+
3358+static ssize_t show_cabc_mode(struct device *dev,
3359+ struct device_attribute *attr,
3360+ char *buf)
3361+{
3362+ struct omap_dss_device *dssdev = to_dss_device(dev);
3363+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3364+ const char *mode_str;
3365+ int mode;
3366+ int len;
3367+
3368+ mode = td->cabc_mode;
3369+
3370+ mode_str = "unknown";
3371+ if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
3372+ mode_str = cabc_modes[mode];
3373+ len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
3374+
3375+ return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
3376+}
3377+
3378+static ssize_t store_cabc_mode(struct device *dev,
3379+ struct device_attribute *attr,
3380+ const char *buf, size_t count)
3381+{
3382+ struct omap_dss_device *dssdev = to_dss_device(dev);
3383+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3384+ int i;
3385+
3386+ for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
3387+ if (sysfs_streq(cabc_modes[i], buf))
3388+ break;
3389+ }
3390+
3391+ if (i == ARRAY_SIZE(cabc_modes))
3392+ return -EINVAL;
3393+
3394+ if (td->enabled) {
3395+ dsi_bus_lock();
3396+ if (!td->cabc_broken)
3397+ taal_dcs_write_1(DCS_WRITE_CABC, i);
3398+ dsi_bus_unlock();
3399+ }
3400+
3401+ td->cabc_mode = i;
3402+
3403+ return count;
3404+}
3405+
3406+static ssize_t show_cabc_available_modes(struct device *dev,
3407+ struct device_attribute *attr,
3408+ char *buf)
3409+{
3410+ int len;
3411+ int i;
3412+
3413+ for (i = 0, len = 0;
3414+ len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
3415+ len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
3416+ i ? " " : "", cabc_modes[i],
3417+ i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
3418+
3419+ return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
3420+}
3421+
3422+static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL);
3423+static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL);
3424+static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
3425+ show_cabc_mode, store_cabc_mode);
3426+static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
3427+ show_cabc_available_modes, NULL);
3428+
3429+static struct attribute *taal_attrs[] = {
3430+ &dev_attr_num_dsi_errors.attr,
3431+ &dev_attr_hw_revision.attr,
3432+ &dev_attr_cabc_mode.attr,
3433+ &dev_attr_cabc_available_modes.attr,
3434+ NULL,
3435+};
3436+
3437+static struct attribute_group taal_attr_group = {
3438+ .attrs = taal_attrs,
3439+};
3440+
3441+static int taal_probe(struct omap_dss_device *dssdev)
3442+{
3443+ struct taal_data *td;
3444+ struct backlight_device *bldev;
3445+ int r;
3446+
3447+ const struct omap_video_timings taal_panel_timings = {
3448+ .x_res = 864,
3449+ .y_res = 480,
3450+ };
3451+
3452+ dev_dbg(&dssdev->dev, "probe\n");
3453+
3454+ dssdev->panel.config = OMAP_DSS_LCD_TFT;
3455+ dssdev->panel.timings = taal_panel_timings;
3456+ dssdev->ctrl.pixel_size = 24;
3457+
3458+ td = kzalloc(sizeof(*td), GFP_KERNEL);
3459+ if (!td) {
3460+ r = -ENOMEM;
3461+ goto err0;
3462+ }
3463+
3464+ dev_set_drvdata(&dssdev->dev, td);
3465+
3466+ dssdev->get_timings = taal_get_timings;
3467+ dssdev->get_resolution = taal_get_resolution;
3468+
3469+ /* if no platform set_backlight() defined, presume DSI backlight
3470+ * control */
3471+ if (!dssdev->set_backlight)
3472+ td->use_dsi_bl = true;
3473+
3474+ bldev = backlight_device_register("taal", &dssdev->dev, dssdev,
3475+ &taal_bl_ops);
3476+ if (IS_ERR(bldev)) {
3477+ r = PTR_ERR(bldev);
3478+ goto err1;
3479+ }
3480+
3481+ td->bldev = bldev;
3482+
3483+ bldev->props.fb_blank = FB_BLANK_UNBLANK;
3484+ bldev->props.power = FB_BLANK_UNBLANK;
3485+ if (td->use_dsi_bl) {
3486+ bldev->props.max_brightness = 255;
3487+ bldev->props.brightness = 255;
3488+ } else {
3489+ bldev->props.max_brightness = 127;
3490+ bldev->props.brightness = 127;
3491+ }
3492+
3493+ taal_bl_update_status(bldev);
3494+
3495+ if (dssdev->phy.dsi.ext_te) {
3496+ int gpio = dssdev->phy.dsi.ext_te_gpio;
3497+
3498+ r = gpio_request(gpio, "taal irq");
3499+ if (r) {
3500+ dev_err(&dssdev->dev, "GPIO request failed\n");
3501+ goto err2;
3502+ }
3503+
3504+ gpio_direction_input(gpio);
3505+
3506+ r = request_irq(gpio_to_irq(gpio), taal_te_isr,
3507+ IRQF_DISABLED | IRQF_TRIGGER_RISING,
3508+ "taal vsync", dssdev);
3509+
3510+ if (r) {
3511+ dev_err(&dssdev->dev, "IRQ request failed\n");
3512+ gpio_free(gpio);
3513+ goto err2;
3514+ }
3515+
3516+ init_completion(&td->te_completion);
3517+
3518+ td->use_ext_te = true;
3519+ }
3520+
3521+ r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group);
3522+ if (r) {
3523+ dev_err(&dssdev->dev, "failed to create sysfs files\n");
3524+ goto err3;
3525+ }
3526+
3527+ return 0;
3528+err3:
3529+ if (td->use_ext_te) {
3530+ int gpio = dssdev->phy.dsi.ext_te_gpio;
3531+ free_irq(gpio_to_irq(gpio), dssdev);
3532+ gpio_free(gpio);
3533+ }
3534+err2:
3535+ backlight_device_unregister(bldev);
3536+err1:
3537+ kfree(td);
3538+err0:
3539+ return r;
3540+}
3541+
3542+static void taal_remove(struct omap_dss_device *dssdev)
3543+{
3544+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3545+ struct backlight_device *bldev;
3546+
3547+ dev_dbg(&dssdev->dev, "remove\n");
3548+
3549+ sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);
3550+
3551+ if (td->use_ext_te) {
3552+ int gpio = dssdev->phy.dsi.ext_te_gpio;
3553+ free_irq(gpio_to_irq(gpio), dssdev);
3554+ gpio_free(gpio);
3555+ }
3556+
3557+ bldev = td->bldev;
3558+ bldev->props.power = FB_BLANK_POWERDOWN;
3559+ taal_bl_update_status(bldev);
3560+ backlight_device_unregister(bldev);
3561+
3562+ kfree(td);
3563+}
3564+
3565+static int taal_enable(struct omap_dss_device *dssdev)
3566+{
3567+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3568+ u8 id1, id2, id3;
3569+ int r;
3570+
3571+ dev_dbg(&dssdev->dev, "enable\n");
3572+
3573+ if (dssdev->platform_enable) {
3574+ r = dssdev->platform_enable(dssdev);
3575+ if (r)
3576+ return r;
3577+ }
3578+
3579+ /* it seems we have to wait a bit until taal is ready */
3580+ msleep(5);
3581+
3582+ r = taal_sleep_out(td);
3583+ if (r)
3584+ return r;
3585+
3586+ r = taal_get_id(&id1, &id2, &id3);
3587+ if (r)
3588+ return r;
3589+
3590+ /* on early revisions CABC is broken */
3591+ if (id2 == 0x00 || id2 == 0xff || id2 == 0x81)
3592+ td->cabc_broken = true;
3593+
3594+ taal_dcs_write_1(DCS_BRIGHTNESS, 0xff);
3595+ taal_dcs_write_1(DCS_CTRL_DISPLAY, (1<<2) | (1<<5)); /* BL | BCTRL */
3596+
3597+ taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
3598+
3599+ taal_set_addr_mode(td->rotate, td->mirror);
3600+ if (!td->cabc_broken)
3601+ taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode);
3602+
3603+ taal_dcs_write_0(DCS_DISPLAY_ON);
3604+
3605+ td->enabled = 1;
3606+
3607+ if (!td->intro_printed) {
3608+ dev_info(&dssdev->dev, "revision %02x.%02x.%02x\n",
3609+ id1, id2, id3);
3610+ if (td->cabc_broken)
3611+ dev_info(&dssdev->dev,
3612+ "old Taal version, CABC disabled\n");
3613+ td->intro_printed = true;
3614+ }
3615+
3616+ return 0;
3617+}
3618+
3619+static void taal_disable(struct omap_dss_device *dssdev)
3620+{
3621+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3622+
3623+ dev_dbg(&dssdev->dev, "disable\n");
3624+
3625+ taal_dcs_write_0(DCS_DISPLAY_OFF);
3626+ taal_sleep_in(td);
3627+
3628+ /* wait a bit so that the message goes through */
3629+ msleep(10);
3630+
3631+ if (dssdev->platform_disable)
3632+ dssdev->platform_disable(dssdev);
3633+
3634+ td->enabled = 0;
3635+}
3636+
3637+static int taal_suspend(struct omap_dss_device *dssdev)
3638+{
3639+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3640+ struct backlight_device *bldev = td->bldev;
3641+
3642+ bldev->props.power = FB_BLANK_POWERDOWN;
3643+ taal_bl_update_status(bldev);
3644+
3645+ return 0;
3646+}
3647+
3648+static int taal_resume(struct omap_dss_device *dssdev)
3649+{
3650+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3651+ struct backlight_device *bldev = td->bldev;
3652+
3653+ bldev->props.power = FB_BLANK_UNBLANK;
3654+ taal_bl_update_status(bldev);
3655+
3656+ return 0;
3657+}
3658+
3659+static void taal_setup_update(struct omap_dss_device *dssdev,
3660+ u16 x, u16 y, u16 w, u16 h)
3661+{
3662+ taal_set_update_window(x, y, w, h);
3663+}
3664+
3665+static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
3666+{
3667+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3668+ int r;
3669+
3670+ td->te_enabled = enable;
3671+
3672+ if (enable)
3673+ r = taal_dcs_write_1(DCS_TEAR_ON, 0);
3674+ else
3675+ r = taal_dcs_write_0(DCS_TEAR_OFF);
3676+
3677+ return r;
3678+}
3679+
3680+static int taal_wait_te(struct omap_dss_device *dssdev)
3681+{
3682+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3683+ long wait = msecs_to_jiffies(500);
3684+
3685+ if (!td->use_ext_te || !td->te_enabled)
3686+ return 0;
3687+
3688+ INIT_COMPLETION(td->te_completion);
3689+ wait = wait_for_completion_timeout(&td->te_completion, wait);
3690+ if (wait == 0) {
3691+ dev_err(&dssdev->dev, "timeout waiting TE\n");
3692+ return -ETIME;
3693+ }
3694+
3695+ return 0;
3696+}
3697+
3698+static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
3699+{
3700+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3701+ int r;
3702+
3703+ dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
3704+
3705+ if (td->enabled) {
3706+ r = taal_set_addr_mode(rotate, td->mirror);
3707+
3708+ if (r)
3709+ return r;
3710+ }
3711+
3712+ td->rotate = rotate;
3713+
3714+ return 0;
3715+}
3716+
3717+static u8 taal_get_rotate(struct omap_dss_device *dssdev)
3718+{
3719+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3720+ return td->rotate;
3721+}
3722+
3723+static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
3724+{
3725+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3726+ int r;
3727+
3728+ dev_dbg(&dssdev->dev, "mirror %d\n", enable);
3729+
3730+ if (td->enabled) {
3731+ r = taal_set_addr_mode(td->rotate, enable);
3732+
3733+ if (r)
3734+ return r;
3735+ }
3736+
3737+ td->mirror = enable;
3738+
3739+ return 0;
3740+}
3741+
3742+static bool taal_get_mirror(struct omap_dss_device *dssdev)
3743+{
3744+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3745+ return td->mirror;
3746+}
3747+
3748+static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
3749+{
3750+ u8 id1, id2, id3;
3751+ int r;
3752+
3753+ r = taal_dcs_read_1(DCS_GET_ID1, &id1);
3754+ if (r)
3755+ return r;
3756+ r = taal_dcs_read_1(DCS_GET_ID2, &id2);
3757+ if (r)
3758+ return r;
3759+ r = taal_dcs_read_1(DCS_GET_ID3, &id3);
3760+ if (r)
3761+ return r;
3762+
3763+ return 0;
3764+}
3765+
3766+static int taal_memory_read(struct omap_dss_device *dssdev,
3767+ void *buf, size_t size,
3768+ u16 x, u16 y, u16 w, u16 h)
3769+{
3770+ int r;
3771+ int first = 1;
3772+ int plen;
3773+ unsigned buf_used = 0;
3774+
3775+ if (size < w * h * 3)
3776+ return -ENOMEM;
3777+
3778+ size = min(w * h * 3,
3779+ dssdev->panel.timings.x_res *
3780+ dssdev->panel.timings.y_res * 3);
3781+
3782+ /* plen 1 or 2 goes into short packet. until checksum error is fixed,
3783+ * use short packets. plen 32 works, but bigger packets seem to cause
3784+ * an error. */
3785+ if (size % 2)
3786+ plen = 1;
3787+ else
3788+ plen = 2;
3789+
3790+ taal_setup_update(dssdev, x, y, w, h);
3791+
3792+ r = dsi_vc_set_max_rx_packet_size(TCH, plen);
3793+ if (r)
3794+ return r;
3795+
3796+ while (buf_used < size) {
3797+ u8 dcs_cmd = first ? 0x2e : 0x3e;
3798+ first = 0;
3799+
3800+ r = dsi_vc_dcs_read(TCH, dcs_cmd,
3801+ buf + buf_used, size - buf_used);
3802+
3803+ if (r < 0) {
3804+ dev_err(&dssdev->dev, "read error\n");
3805+ goto err;
3806+ }
3807+
3808+ buf_used += r;
3809+
3810+ if (r < plen) {
3811+ dev_err(&dssdev->dev, "short read\n");
3812+ break;
3813+ }
3814+ }
3815+
3816+ r = buf_used;
3817+
3818+err:
3819+ dsi_vc_set_max_rx_packet_size(TCH, 1);
3820+
3821+ return r;
3822+}
3823+
3824+static struct omap_dss_driver taal_driver = {
3825+ .probe = taal_probe,
3826+ .remove = taal_remove,
3827+
3828+ .enable = taal_enable,
3829+ .disable = taal_disable,
3830+ .suspend = taal_suspend,
3831+ .resume = taal_resume,
3832+
3833+ .setup_update = taal_setup_update,
3834+ .enable_te = taal_enable_te,
3835+ .wait_for_te = taal_wait_te,
3836+ .set_rotate = taal_rotate,
3837+ .get_rotate = taal_get_rotate,
3838+ .set_mirror = taal_mirror,
3839+ .get_mirror = taal_get_mirror,
3840+ .run_test = taal_run_test,
3841+ .memory_read = taal_memory_read,
3842+
3843+ .driver = {
3844+ .name = "taal",
3845+ .owner = THIS_MODULE,
3846+ },
3847+};
3848+
3849+static int __init taal_init(void)
3850+{
3851+ omap_dss_register_driver(&taal_driver);
3852+
3853+ return 0;
3854+}
3855+
3856+static void __exit taal_exit(void)
3857+{
3858+ omap_dss_unregister_driver(&taal_driver);
3859+}
3860+
3861+module_init(taal_init);
3862+module_exit(taal_exit);
3863+
3864+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
3865+MODULE_DESCRIPTION("Taal Driver");
3866+MODULE_LICENSE("GPL");
3867--- /dev/null
3868+++ b/drivers/video/omap2/dss/Kconfig
3869@@ -0,0 +1,89 @@
3870+menuconfig OMAP2_DSS
3871+ tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)"
3872+ depends on ARCH_OMAP2 || ARCH_OMAP3
3873+ help
3874+ OMAP2/3 Display Subsystem support.
3875+
3876+if OMAP2_DSS
3877+
3878+config OMAP2_VRAM_SIZE
3879+ int "VRAM size (MB)"
3880+ range 0 32
3881+ default 0
3882+ help
3883+ The amount of SDRAM to reserve at boot time for video RAM use.
3884+ This VRAM will be used by omapfb and other drivers that need
3885+ large continuous RAM area for video use.
3886+
3887+ You can also set this with "vram=<bytes>" kernel argument, or
3888+ in the board file.
3889+
3890+config OMAP2_DSS_DEBUG_SUPPORT
3891+ bool "Debug support"
3892+ default y
3893+ help
3894+ This enables debug messages. You need to enable printing
3895+ with 'debug' module parameter.
3896+
3897+config OMAP2_DSS_RFBI
3898+ bool "RFBI support"
3899+ default n
3900+ help
3901+ MIPI DBI, or RFBI (Remote Framebuffer Interface), support.
3902+
3903+config OMAP2_DSS_VENC
3904+ bool "VENC support"
3905+ default y
3906+ help
3907+ OMAP Video Encoder support.
3908+
3909+config OMAP2_DSS_SDI
3910+ bool "SDI support"
3911+ depends on ARCH_OMAP3
3912+ default n
3913+ help
3914+ SDI (Serial Display Interface) support.
3915+
3916+config OMAP2_DSS_DSI
3917+ bool "DSI support"
3918+ depends on ARCH_OMAP3
3919+ default n
3920+ help
3921+ MIPI DSI support.
3922+
3923+config OMAP2_DSS_USE_DSI_PLL
3924+ bool "Use DSI PLL for PCLK (EXPERIMENTAL)"
3925+ default n
3926+ depends on OMAP2_DSS_DSI
3927+ help
3928+ Use DSI PLL to generate pixel clock. Currently only for DPI output.
3929+ DSI PLL can be used to generate higher and more precise pixel clocks.
3930+
3931+config OMAP2_DSS_FAKE_VSYNC
3932+ bool "Fake VSYNC irq from manual update displays"
3933+ default n
3934+ help
3935+ If this is selected, DSI will generate a fake DISPC VSYNC interrupt
3936+ when DSI has sent a frame. This is only needed with DSI or RFBI
3937+ displays using manual mode, and you want VSYNC to, for example,
3938+ time animation.
3939+
3940+config OMAP2_DSS_MIN_FCK_PER_PCK
3941+ int "Minimum FCK/PCK ratio (for scaling)"
3942+ range 0 32
3943+ default 0
3944+ help
3945+ This can be used to adjust the minimum FCK/PCK ratio.
3946+
3947+ With this you can make sure that DISPC FCK is at least
3948+ n x PCK. Video plane scaling requires higher FCK than
3949+ normally.
3950+
3951+ If this is set to 0, there's no extra constraint on the
3952+ DISPC FCK. However, the FCK will at minimum be
3953+ 2xPCK (if active matrix) or 3xPCK (if passive matrix).
3954+
3955+ Max FCK is 173MHz, so this doesn't work if your PCK
3956+ is very high.
3957+
3958+endif
3959--- /dev/null
3960+++ b/drivers/video/omap2/dss/Makefile
3961@@ -0,0 +1,6 @@
3962+obj-$(CONFIG_OMAP2_DSS) += omapdss.o
3963+omapdss-y := core.o dss.o dispc.o dpi.o display.o manager.o overlay.o
3964+omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
3965+omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
3966+omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
3967+omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
3968--- /dev/null
3969+++ b/drivers/video/omap2/dss/core.c
3970@@ -0,0 +1,917 @@
3971+/*
3972+ * linux/drivers/video/omap2/dss/core.c
3973+ *
3974+ * Copyright (C) 2009 Nokia Corporation
3975+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
3976+ *
3977+ * Some code and ideas taken from drivers/video/omap/ driver
3978+ * by Imre Deak.
3979+ *
3980+ * This program is free software; you can redistribute it and/or modify it
3981+ * under the terms of the GNU General Public License version 2 as published by
3982+ * the Free Software Foundation.
3983+ *
3984+ * This program is distributed in the hope that it will be useful, but WITHOUT
3985+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3986+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
3987+ * more details.
3988+ *
3989+ * You should have received a copy of the GNU General Public License along with
3990+ * this program. If not, see <http://www.gnu.org/licenses/>.
3991+ */
3992+
3993+#define DSS_SUBSYS_NAME "CORE"
3994+
3995+#include <linux/kernel.h>
3996+#include <linux/module.h>
3997+#include <linux/clk.h>
3998+#include <linux/err.h>
3999+#include <linux/platform_device.h>
4000+#include <linux/seq_file.h>
4001+#include <linux/debugfs.h>
4002+#include <linux/io.h>
4003+#include <linux/device.h>
4004+
4005+#include <mach/display.h>
4006+#include <mach/clock.h>
4007+
4008+#include "dss.h"
4009+
4010+static struct {
4011+ struct platform_device *pdev;
4012+ int ctx_id;
4013+
4014+ struct clk *dss_ick;
4015+ struct clk *dss1_fck;
4016+ struct clk *dss2_fck;
4017+ struct clk *dss_54m_fck;
4018+ struct clk *dss_96m_fck;
4019+ unsigned num_clks_enabled;
4020+} core;
4021+
4022+static void dss_clk_enable_all_no_ctx(void);
4023+static void dss_clk_disable_all_no_ctx(void);
4024+static void dss_clk_enable_no_ctx(enum dss_clock clks);
4025+static void dss_clk_disable_no_ctx(enum dss_clock clks);
4026+
4027+static char *def_disp_name;
4028+module_param_named(def_disp, def_disp_name, charp, 0);
4029+MODULE_PARM_DESC(def_disp_name, "default display name");
4030+
4031+#ifdef DEBUG
4032+unsigned int dss_debug;
4033+module_param_named(debug, dss_debug, bool, 0644);
4034+#endif
4035+
4036+/* CONTEXT */
4037+static int dss_get_ctx_id(void)
4038+{
4039+ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
4040+ int r;
4041+
4042+ if (!pdata->get_last_off_on_transaction_id)
4043+ return 0;
4044+ r = pdata->get_last_off_on_transaction_id(&core.pdev->dev);
4045+ if (r < 0) {
4046+ dev_err(&core.pdev->dev, "getting transaction ID failed, "
4047+ "will force context restore\n");
4048+ r = -1;
4049+ }
4050+ return r;
4051+}
4052+
4053+int dss_need_ctx_restore(void)
4054+{
4055+ int id = dss_get_ctx_id();
4056+
4057+ if (id < 0 || id != core.ctx_id) {
4058+ DSSDBG("ctx id %d -> id %d\n",
4059+ core.ctx_id, id);
4060+ core.ctx_id = id;
4061+ return 1;
4062+ } else {
4063+ return 0;
4064+ }
4065+}
4066+
4067+static void save_all_ctx(void)
4068+{
4069+ DSSDBG("save context\n");
4070+
4071+ dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
4072+
4073+ dss_save_context();
4074+ dispc_save_context();
4075+#ifdef CONFIG_OMAP2_DSS_DSI
4076+ dsi_save_context();
4077+#endif
4078+
4079+ dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
4080+}
4081+
4082+static void restore_all_ctx(void)
4083+{
4084+ DSSDBG("restore context\n");
4085+
4086+ dss_clk_enable_all_no_ctx();
4087+
4088+ dss_restore_context();
4089+ dispc_restore_context();
4090+#ifdef CONFIG_OMAP2_DSS_DSI
4091+ dsi_restore_context();
4092+#endif
4093+
4094+ dss_clk_disable_all_no_ctx();
4095+}
4096+
4097+/* CLOCKS */
4098+void dss_dump_clocks(struct seq_file *s)
4099+{
4100+ int i;
4101+ struct clk *clocks[5] = {
4102+ core.dss_ick,
4103+ core.dss1_fck,
4104+ core.dss2_fck,
4105+ core.dss_54m_fck,
4106+ core.dss_96m_fck
4107+ };
4108+
4109+ seq_printf(s, "- dss -\n");
4110+
4111+ seq_printf(s, "internal clk count\t%u\n", core.num_clks_enabled);
4112+
4113+ for (i = 0; i < 5; i++) {
4114+ if (!clocks[i])
4115+ continue;
4116+ seq_printf(s, "%-15s\t%lu\t%d\n",
4117+ clocks[i]->name,
4118+ clk_get_rate(clocks[i]),
4119+ clocks[i]->usecount);
4120+ }
4121+}
4122+
4123+static int dss_get_clock(struct clk **clock, const char *clk_name)
4124+{
4125+ struct clk *clk;
4126+
4127+ clk = clk_get(&core.pdev->dev, clk_name);
4128+
4129+ if (IS_ERR(clk)) {
4130+ DSSERR("can't get clock %s", clk_name);
4131+ return PTR_ERR(clk);
4132+ }
4133+
4134+ *clock = clk;
4135+
4136+ DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
4137+
4138+ return 0;
4139+}
4140+
4141+static int dss_get_clocks(void)
4142+{
4143+ int r;
4144+
4145+ core.dss_ick = NULL;
4146+ core.dss1_fck = NULL;
4147+ core.dss2_fck = NULL;
4148+ core.dss_54m_fck = NULL;
4149+ core.dss_96m_fck = NULL;
4150+
4151+ r = dss_get_clock(&core.dss_ick, "ick");
4152+ if (r)
4153+ goto err;
4154+
4155+ r = dss_get_clock(&core.dss1_fck, "dss1_fck");
4156+ if (r)
4157+ goto err;
4158+
4159+ r = dss_get_clock(&core.dss2_fck, "dss2_fck");
4160+ if (r)
4161+ goto err;
4162+
4163+ r = dss_get_clock(&core.dss_54m_fck, "tv_fck");
4164+ if (r)
4165+ goto err;
4166+
4167+ r = dss_get_clock(&core.dss_96m_fck, "video_fck");
4168+ if (r)
4169+ goto err;
4170+
4171+ return 0;
4172+
4173+err:
4174+ if (core.dss_ick)
4175+ clk_put(core.dss_ick);
4176+ if (core.dss1_fck)
4177+ clk_put(core.dss1_fck);
4178+ if (core.dss2_fck)
4179+ clk_put(core.dss2_fck);
4180+ if (core.dss_54m_fck)
4181+ clk_put(core.dss_54m_fck);
4182+ if (core.dss_96m_fck)
4183+ clk_put(core.dss_96m_fck);
4184+
4185+ return r;
4186+}
4187+
4188+static void dss_put_clocks(void)
4189+{
4190+ if (core.dss_96m_fck)
4191+ clk_put(core.dss_96m_fck);
4192+ clk_put(core.dss_54m_fck);
4193+ clk_put(core.dss1_fck);
4194+ clk_put(core.dss2_fck);
4195+ clk_put(core.dss_ick);
4196+}
4197+
4198+unsigned long dss_clk_get_rate(enum dss_clock clk)
4199+{
4200+ switch (clk) {
4201+ case DSS_CLK_ICK:
4202+ return clk_get_rate(core.dss_ick);
4203+ case DSS_CLK_FCK1:
4204+ return clk_get_rate(core.dss1_fck);
4205+ case DSS_CLK_FCK2:
4206+ return clk_get_rate(core.dss2_fck);
4207+ case DSS_CLK_54M:
4208+ return clk_get_rate(core.dss_54m_fck);
4209+ case DSS_CLK_96M:
4210+ return clk_get_rate(core.dss_96m_fck);
4211+ }
4212+
4213+ BUG();
4214+ return 0;
4215+}
4216+
4217+static unsigned count_clk_bits(enum dss_clock clks)
4218+{
4219+ unsigned num_clks = 0;
4220+
4221+ if (clks & DSS_CLK_ICK)
4222+ ++num_clks;
4223+ if (clks & DSS_CLK_FCK1)
4224+ ++num_clks;
4225+ if (clks & DSS_CLK_FCK2)
4226+ ++num_clks;
4227+ if (clks & DSS_CLK_54M)
4228+ ++num_clks;
4229+ if (clks & DSS_CLK_96M)
4230+ ++num_clks;
4231+
4232+ return num_clks;
4233+}
4234+
4235+static void dss_clk_enable_no_ctx(enum dss_clock clks)
4236+{
4237+ unsigned num_clks = count_clk_bits(clks);
4238+
4239+ if (clks & DSS_CLK_ICK)
4240+ clk_enable(core.dss_ick);
4241+ if (clks & DSS_CLK_FCK1)
4242+ clk_enable(core.dss1_fck);
4243+ if (clks & DSS_CLK_FCK2)
4244+ clk_enable(core.dss2_fck);
4245+ if (clks & DSS_CLK_54M)
4246+ clk_enable(core.dss_54m_fck);
4247+ if (clks & DSS_CLK_96M)
4248+ clk_enable(core.dss_96m_fck);
4249+
4250+ core.num_clks_enabled += num_clks;
4251+}
4252+
4253+void dss_clk_enable(enum dss_clock clks)
4254+{
4255+ dss_clk_enable_no_ctx(clks);
4256+
4257+ if (cpu_is_omap34xx() && dss_need_ctx_restore())
4258+ restore_all_ctx();
4259+}
4260+
4261+static void dss_clk_disable_no_ctx(enum dss_clock clks)
4262+{
4263+ unsigned num_clks = count_clk_bits(clks);
4264+
4265+ if (clks & DSS_CLK_ICK)
4266+ clk_disable(core.dss_ick);
4267+ if (clks & DSS_CLK_FCK1)
4268+ clk_disable(core.dss1_fck);
4269+ if (clks & DSS_CLK_FCK2)
4270+ clk_disable(core.dss2_fck);
4271+ if (clks & DSS_CLK_54M)
4272+ clk_disable(core.dss_54m_fck);
4273+ if (clks & DSS_CLK_96M)
4274+ clk_disable(core.dss_96m_fck);
4275+
4276+ core.num_clks_enabled -= num_clks;
4277+}
4278+
4279+void dss_clk_disable(enum dss_clock clks)
4280+{
4281+ if (cpu_is_omap34xx()) {
4282+ unsigned num_clks = count_clk_bits(clks);
4283+
4284+ BUG_ON(core.num_clks_enabled < num_clks);
4285+
4286+ if (core.num_clks_enabled == num_clks)
4287+ save_all_ctx();
4288+ }
4289+
4290+ dss_clk_disable_no_ctx(clks);
4291+}
4292+
4293+static void dss_clk_enable_all_no_ctx(void)
4294+{
4295+ enum dss_clock clks;
4296+
4297+ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
4298+ if (cpu_is_omap34xx())
4299+ clks |= DSS_CLK_96M;
4300+ dss_clk_enable_no_ctx(clks);
4301+}
4302+
4303+static void dss_clk_disable_all_no_ctx(void)
4304+{
4305+ enum dss_clock clks;
4306+
4307+ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
4308+ if (cpu_is_omap34xx())
4309+ clks |= DSS_CLK_96M;
4310+ dss_clk_disable_no_ctx(clks);
4311+}
4312+
4313+static void dss_clk_disable_all(void)
4314+{
4315+ enum dss_clock clks;
4316+
4317+ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
4318+ if (cpu_is_omap34xx())
4319+ clks |= DSS_CLK_96M;
4320+ dss_clk_disable(clks);
4321+}
4322+
4323+/* DEBUGFS */
4324+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
4325+static void dss_debug_dump_clocks(struct seq_file *s)
4326+{
4327+ dss_dump_clocks(s);
4328+ dispc_dump_clocks(s);
4329+#ifdef CONFIG_OMAP2_DSS_DSI
4330+ dsi_dump_clocks(s);
4331+#endif
4332+}
4333+
4334+static int dss_debug_show(struct seq_file *s, void *unused)
4335+{
4336+ void (*func)(struct seq_file *) = s->private;
4337+ func(s);
4338+ return 0;
4339+}
4340+
4341+static int dss_debug_open(struct inode *inode, struct file *file)
4342+{
4343+ return single_open(file, dss_debug_show, inode->i_private);
4344+}
4345+
4346+static const struct file_operations dss_debug_fops = {
4347+ .open = dss_debug_open,
4348+ .read = seq_read,
4349+ .llseek = seq_lseek,
4350+ .release = single_release,
4351+};
4352+
4353+static struct dentry *dss_debugfs_dir;
4354+
4355+static int dss_initialize_debugfs(void)
4356+{
4357+ dss_debugfs_dir = debugfs_create_dir("omapdss", NULL);
4358+ if (IS_ERR(dss_debugfs_dir)) {
4359+ int err = PTR_ERR(dss_debugfs_dir);
4360+ dss_debugfs_dir = NULL;
4361+ return err;
4362+ }
4363+
4364+ debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
4365+ &dss_debug_dump_clocks, &dss_debug_fops);
4366+
4367+ debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir,
4368+ &dss_dump_regs, &dss_debug_fops);
4369+ debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir,
4370+ &dispc_dump_regs, &dss_debug_fops);
4371+#ifdef CONFIG_OMAP2_DSS_RFBI
4372+ debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir,
4373+ &rfbi_dump_regs, &dss_debug_fops);
4374+#endif
4375+#ifdef CONFIG_OMAP2_DSS_DSI
4376+ debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir,
4377+ &dsi_dump_regs, &dss_debug_fops);
4378+#endif
4379+#ifdef CONFIG_OMAP2_DSS_VENC
4380+ debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir,
4381+ &venc_dump_regs, &dss_debug_fops);
4382+#endif
4383+ return 0;
4384+}
4385+
4386+static void dss_uninitialize_debugfs(void)
4387+{
4388+ if (dss_debugfs_dir)
4389+ debugfs_remove_recursive(dss_debugfs_dir);
4390+}
4391+#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
4392+
4393+/* PLATFORM DEVICE */
4394+static int omap_dss_probe(struct platform_device *pdev)
4395+{
4396+ struct omap_dss_board_info *pdata = pdev->dev.platform_data;
4397+ int skip_init = 0;
4398+ int r;
4399+ int i;
4400+
4401+ core.pdev = pdev;
4402+
4403+ dss_init_overlay_managers(pdev);
4404+ dss_init_overlays(pdev);
4405+
4406+ r = dss_get_clocks();
4407+ if (r)
4408+ goto fail0;
4409+
4410+ dss_clk_enable_all_no_ctx();
4411+
4412+ core.ctx_id = dss_get_ctx_id();
4413+ DSSDBG("initial ctx id %u\n", core.ctx_id);
4414+
4415+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
4416+ /* DISPC_CONTROL */
4417+ if (omap_readl(0x48050440) & 1) /* LCD enabled? */
4418+ skip_init = 1;
4419+#endif
4420+
4421+ r = dss_init(skip_init);
4422+ if (r) {
4423+ DSSERR("Failed to initialize DSS\n");
4424+ goto fail0;
4425+ }
4426+
4427+#ifdef CONFIG_OMAP2_DSS_RFBI
4428+ r = rfbi_init();
4429+ if (r) {
4430+ DSSERR("Failed to initialize rfbi\n");
4431+ goto fail0;
4432+ }
4433+#endif
4434+
4435+ r = dpi_init();
4436+ if (r) {
4437+ DSSERR("Failed to initialize dpi\n");
4438+ goto fail0;
4439+ }
4440+
4441+ r = dispc_init();
4442+ if (r) {
4443+ DSSERR("Failed to initialize dispc\n");
4444+ goto fail0;
4445+ }
4446+#ifdef CONFIG_OMAP2_DSS_VENC
4447+ r = venc_init(pdev);
4448+ if (r) {
4449+ DSSERR("Failed to initialize venc\n");
4450+ goto fail0;
4451+ }
4452+#endif
4453+ if (cpu_is_omap34xx()) {
4454+#ifdef CONFIG_OMAP2_DSS_SDI
4455+ r = sdi_init(skip_init);
4456+ if (r) {
4457+ DSSERR("Failed to initialize SDI\n");
4458+ goto fail0;
4459+ }
4460+#endif
4461+#ifdef CONFIG_OMAP2_DSS_DSI
4462+ r = dsi_init(pdev);
4463+ if (r) {
4464+ DSSERR("Failed to initialize DSI\n");
4465+ goto fail0;
4466+ }
4467+#endif
4468+ }
4469+
4470+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
4471+ r = dss_initialize_debugfs();
4472+ if (r)
4473+ goto fail0;
4474+#endif
4475+
4476+ for (i = 0; i < pdata->num_devices; ++i) {
4477+ struct omap_dss_device *dssdev = pdata->devices[i];
4478+
4479+ r = omap_dss_register_device(dssdev);
4480+ if (r)
4481+ DSSERR("device reg failed %d\n", i);
4482+
4483+ if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0)
4484+ pdata->default_device = dssdev;
4485+ }
4486+
4487+ dss_clk_disable_all();
4488+
4489+ return 0;
4490+
4491+ /* XXX fail correctly */
4492+fail0:
4493+ return r;
4494+}
4495+
4496+static int omap_dss_remove(struct platform_device *pdev)
4497+{
4498+ struct omap_dss_board_info *pdata = pdev->dev.platform_data;
4499+ int i;
4500+ int c;
4501+
4502+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
4503+ dss_uninitialize_debugfs();
4504+#endif
4505+
4506+#ifdef CONFIG_OMAP2_DSS_VENC
4507+ venc_exit();
4508+#endif
4509+ dispc_exit();
4510+ dpi_exit();
4511+#ifdef CONFIG_OMAP2_DSS_RFBI
4512+ rfbi_exit();
4513+#endif
4514+ if (cpu_is_omap34xx()) {
4515+#ifdef CONFIG_OMAP2_DSS_DSI
4516+ dsi_exit();
4517+#endif
4518+#ifdef CONFIG_OMAP2_DSS_SDI
4519+ sdi_exit();
4520+#endif
4521+ }
4522+
4523+ dss_exit();
4524+
4525+ /* these should be removed at some point */
4526+ c = core.dss_ick->usecount;
4527+ if (c > 0) {
4528+ DSSERR("warning: dss_ick usecount %d, disabling\n", c);
4529+ while (c-- > 0)
4530+ clk_disable(core.dss_ick);
4531+ }
4532+
4533+ c = core.dss1_fck->usecount;
4534+ if (c > 0) {
4535+ DSSERR("warning: dss1_fck usecount %d, disabling\n", c);
4536+ while (c-- > 0)
4537+ clk_disable(core.dss1_fck);
4538+ }
4539+
4540+ c = core.dss2_fck->usecount;
4541+ if (c > 0) {
4542+ DSSERR("warning: dss2_fck usecount %d, disabling\n", c);
4543+ while (c-- > 0)
4544+ clk_disable(core.dss2_fck);
4545+ }
4546+
4547+ c = core.dss_54m_fck->usecount;
4548+ if (c > 0) {
4549+ DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c);
4550+ while (c-- > 0)
4551+ clk_disable(core.dss_54m_fck);
4552+ }
4553+
4554+ if (core.dss_96m_fck) {
4555+ c = core.dss_96m_fck->usecount;
4556+ if (c > 0) {
4557+ DSSERR("warning: dss_96m_fck usecount %d, disabling\n",
4558+ c);
4559+ while (c-- > 0)
4560+ clk_disable(core.dss_96m_fck);
4561+ }
4562+ }
4563+
4564+ dss_put_clocks();
4565+
4566+ dss_uninit_overlays(pdev);
4567+ dss_uninit_overlay_managers(pdev);
4568+
4569+ for (i = 0; i < pdata->num_devices; ++i)
4570+ omap_dss_unregister_device(pdata->devices[i]);
4571+
4572+ return 0;
4573+}
4574+
4575+static void omap_dss_shutdown(struct platform_device *pdev)
4576+{
4577+ DSSDBG("shutdown\n");
4578+}
4579+
4580+static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state)
4581+{
4582+ DSSDBG("suspend %d\n", state.event);
4583+
4584+ return dss_suspend_all_devices();
4585+}
4586+
4587+static int omap_dss_resume(struct platform_device *pdev)
4588+{
4589+ DSSDBG("resume\n");
4590+
4591+ return dss_resume_all_devices();
4592+}
4593+
4594+static struct platform_driver omap_dss_driver = {
4595+ .probe = omap_dss_probe,
4596+ .remove = omap_dss_remove,
4597+ .shutdown = omap_dss_shutdown,
4598+ .suspend = omap_dss_suspend,
4599+ .resume = omap_dss_resume,
4600+ .driver = {
4601+ .name = "omapdss",
4602+ .owner = THIS_MODULE,
4603+ },
4604+};
4605+
4606+/* BUS */
4607+static int dss_bus_match(struct device *dev, struct device_driver *driver)
4608+{
4609+ struct omap_dss_device *dssdev = to_dss_device(dev);
4610+
4611+ DSSDBG("bus_match. dev %s/%s, drv %s\n",
4612+ dev_name(dev), dssdev->driver_name, driver->name);
4613+
4614+ return strcmp(dssdev->driver_name, driver->name) == 0;
4615+}
4616+
4617+static ssize_t device_name_show(struct device *dev,
4618+ struct device_attribute *attr, char *buf)
4619+{
4620+ struct omap_dss_device *dssdev = to_dss_device(dev);
4621+ return snprintf(buf, PAGE_SIZE, "%s\n",
4622+ dssdev->name ?
4623+ dssdev->name : "");
4624+}
4625+
4626+static struct device_attribute default_dev_attrs[] = {
4627+ __ATTR(name, S_IRUGO, device_name_show, NULL),
4628+ __ATTR_NULL,
4629+};
4630+
4631+static ssize_t driver_name_show(struct device_driver *drv, char *buf)
4632+{
4633+ struct omap_dss_driver *dssdrv = to_dss_driver(drv);
4634+ return snprintf(buf, PAGE_SIZE, "%s\n",
4635+ dssdrv->driver.name ?
4636+ dssdrv->driver.name : "");
4637+}
4638+static struct driver_attribute default_drv_attrs[] = {
4639+ __ATTR(name, S_IRUGO, driver_name_show, NULL),
4640+ __ATTR_NULL,
4641+};
4642+
4643+static struct bus_type dss_bus_type = {
4644+ .name = "omapdss",
4645+ .match = dss_bus_match,
4646+ .dev_attrs = default_dev_attrs,
4647+ .drv_attrs = default_drv_attrs,
4648+};
4649+
4650+static void dss_bus_release(struct device *dev)
4651+{
4652+ DSSDBG("bus_release\n");
4653+}
4654+
4655+static struct device dss_bus = {
4656+ .release = dss_bus_release,
4657+};
4658+
4659+struct bus_type *dss_get_bus(void)
4660+{
4661+ return &dss_bus_type;
4662+}
4663+
4664+/* DRIVER */
4665+static int dss_driver_probe(struct device *dev)
4666+{
4667+ int r;
4668+ struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
4669+ struct omap_dss_device *dssdev = to_dss_device(dev);
4670+ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
4671+ bool force;
4672+
4673+ DSSDBG("driver_probe: dev %s/%s, drv %s\n",
4674+ dev_name(dev), dssdev->driver_name,
4675+ dssdrv->driver.name);
4676+
4677+ dss_init_device(core.pdev, dssdev);
4678+
4679+ /* skip this if the device is behind a ctrl */
4680+ if (!dssdev->panel.ctrl) {
4681+ force = pdata->default_device == dssdev;
4682+ dss_recheck_connections(dssdev, force);
4683+ }
4684+
4685+ r = dssdrv->probe(dssdev);
4686+
4687+ if (r) {
4688+ DSSERR("driver probe failed: %d\n", r);
4689+ return r;
4690+ }
4691+
4692+ DSSDBG("probe done for device %s\n", dev_name(dev));
4693+
4694+ dssdev->driver = dssdrv;
4695+
4696+ return 0;
4697+}
4698+
4699+static int dss_driver_remove(struct device *dev)
4700+{
4701+ struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
4702+ struct omap_dss_device *dssdev = to_dss_device(dev);
4703+
4704+ DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev),
4705+ dssdev->driver_name);
4706+
4707+ dssdrv->remove(dssdev);
4708+
4709+ dss_uninit_device(core.pdev, dssdev);
4710+
4711+ dssdev->driver = NULL;
4712+
4713+ return 0;
4714+}
4715+
4716+int omap_dss_register_driver(struct omap_dss_driver *dssdriver)
4717+{
4718+ dssdriver->driver.bus = &dss_bus_type;
4719+ dssdriver->driver.probe = dss_driver_probe;
4720+ dssdriver->driver.remove = dss_driver_remove;
4721+ return driver_register(&dssdriver->driver);
4722+}
4723+EXPORT_SYMBOL(omap_dss_register_driver);
4724+
4725+void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)
4726+{
4727+ driver_unregister(&dssdriver->driver);
4728+}
4729+EXPORT_SYMBOL(omap_dss_unregister_driver);
4730+
4731+/* DEVICE */
4732+static void reset_device(struct device *dev, int check)
4733+{
4734+ u8 *dev_p = (u8 *)dev;
4735+ u8 *dev_end = dev_p + sizeof(*dev);
4736+ void *saved_pdata;
4737+
4738+ saved_pdata = dev->platform_data;
4739+ if (check) {
4740+ /*
4741+ * Check if there is any other setting than platform_data
4742+ * in struct device; warn that these will be reset by our
4743+ * init.
4744+ */
4745+ dev->platform_data = NULL;
4746+ while (dev_p < dev_end) {
4747+ if (*dev_p) {
4748+ WARN("%s: struct device fields will be "
4749+ "discarded\n",
4750+ __func__);
4751+ break;
4752+ }
4753+ dev_p++;
4754+ }
4755+ }
4756+ memset(dev, 0, sizeof(*dev));
4757+ dev->platform_data = saved_pdata;
4758+}
4759+
4760+
4761+static void omap_dss_dev_release(struct device *dev)
4762+{
4763+ reset_device(dev, 0);
4764+}
4765+
4766+int omap_dss_register_device(struct omap_dss_device *dssdev)
4767+{
4768+ static int dev_num;
4769+ static int panel_num;
4770+ int r;
4771+
4772+ WARN_ON(!dssdev->driver_name);
4773+
4774+ reset_device(&dssdev->dev, 1);
4775+ dssdev->dev.bus = &dss_bus_type;
4776+ dssdev->dev.parent = &dss_bus;
4777+ dssdev->dev.release = omap_dss_dev_release;
4778+ dev_set_name(&dssdev->dev, "display%d", dev_num++);
4779+ r = device_register(&dssdev->dev);
4780+ if (r)
4781+ return r;
4782+
4783+ if (dssdev->ctrl.panel) {
4784+ struct omap_dss_device *panel = dssdev->ctrl.panel;
4785+
4786+ panel->panel.ctrl = dssdev;
4787+
4788+ reset_device(&panel->dev, 1);
4789+ panel->dev.bus = &dss_bus_type;
4790+ panel->dev.parent = &dssdev->dev;
4791+ panel->dev.release = omap_dss_dev_release;
4792+ dev_set_name(&panel->dev, "panel%d", panel_num++);
4793+ r = device_register(&panel->dev);
4794+ if (r)
4795+ return r;
4796+ }
4797+
4798+ return 0;
4799+}
4800+
4801+void omap_dss_unregister_device(struct omap_dss_device *dssdev)
4802+{
4803+ device_unregister(&dssdev->dev);
4804+
4805+ if (dssdev->ctrl.panel) {
4806+ struct omap_dss_device *panel = dssdev->ctrl.panel;
4807+ device_unregister(&panel->dev);
4808+ }
4809+}
4810+
4811+/* BUS */
4812+static int omap_dss_bus_register(void)
4813+{
4814+ int r;
4815+
4816+ r = bus_register(&dss_bus_type);
4817+ if (r) {
4818+ DSSERR("bus register failed\n");
4819+ return r;
4820+ }
4821+
4822+ dev_set_name(&dss_bus, "omapdss");
4823+ r = device_register(&dss_bus);
4824+ if (r) {
4825+ DSSERR("bus driver register failed\n");
4826+ bus_unregister(&dss_bus_type);
4827+ return r;
4828+ }
4829+
4830+ return 0;
4831+}
4832+
4833+/* INIT */
4834+
4835+#ifdef CONFIG_OMAP2_DSS_MODULE
4836+static void omap_dss_bus_unregister(void)
4837+{
4838+ device_unregister(&dss_bus);
4839+
4840+ bus_unregister(&dss_bus_type);
4841+}
4842+
4843+static int __init omap_dss_init(void)
4844+{
4845+ int r;
4846+
4847+ r = omap_dss_bus_register();
4848+ if (r)
4849+ return r;
4850+
4851+ r = platform_driver_register(&omap_dss_driver);
4852+ if (r) {
4853+ omap_dss_bus_unregister();
4854+ return r;
4855+ }
4856+
4857+ return 0;
4858+}
4859+
4860+static void __exit omap_dss_exit(void)
4861+{
4862+ platform_driver_unregister(&omap_dss_driver);
4863+
4864+ omap_dss_bus_unregister();
4865+}
4866+
4867+module_init(omap_dss_init);
4868+module_exit(omap_dss_exit);
4869+#else
4870+static int __init omap_dss_init(void)
4871+{
4872+ return omap_dss_bus_register();
4873+}
4874+
4875+static int __init omap_dss_init2(void)
4876+{
4877+ return platform_driver_register(&omap_dss_driver);
4878+}
4879+
4880+core_initcall(omap_dss_init);
4881+device_initcall(omap_dss_init2);
4882+#endif
4883+
4884+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
4885+MODULE_DESCRIPTION("OMAP2/3 Display Subsystem");
4886+MODULE_LICENSE("GPL v2");
4887+
4888--- /dev/null
4889+++ b/drivers/video/omap2/dss/dispc.c
4890@@ -0,0 +1,3182 @@
4891+/*
4892+ * linux/drivers/video/omap2/dss/dispc.c
4893+ *
4894+ * Copyright (C) 2009 Nokia Corporation
4895+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4896+ *
4897+ * Some code and ideas taken from drivers/video/omap/ driver
4898+ * by Imre Deak.
4899+ *
4900+ * This program is free software; you can redistribute it and/or modify it
4901+ * under the terms of the GNU General Public License version 2 as published by
4902+ * the Free Software Foundation.
4903+ *
4904+ * This program is distributed in the hope that it will be useful, but WITHOUT
4905+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4906+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
4907+ * more details.
4908+ *
4909+ * You should have received a copy of the GNU General Public License along with
4910+ * this program. If not, see <http://www.gnu.org/licenses/>.
4911+ */
4912+
4913+#define DSS_SUBSYS_NAME "DISPC"
4914+
4915+#include <linux/kernel.h>
4916+#include <linux/dma-mapping.h>
4917+#include <linux/vmalloc.h>
4918+#include <linux/clk.h>
4919+#include <linux/io.h>
4920+#include <linux/jiffies.h>
4921+#include <linux/seq_file.h>
4922+#include <linux/delay.h>
4923+#include <linux/workqueue.h>
4924+
4925+#include <mach/sram.h>
4926+#include <mach/board.h>
4927+#include <mach/clock.h>
4928+
4929+#include <mach/display.h>
4930+
4931+#include "dss.h"
4932+
4933+/* DISPC */
4934+#define DISPC_BASE 0x48050400
4935+
4936+#define DISPC_SZ_REGS SZ_1K
4937+
4938+struct dispc_reg { u16 idx; };
4939+
4940+#define DISPC_REG(idx) ((const struct dispc_reg) { idx })
4941+
4942+/* DISPC common */
4943+#define DISPC_REVISION DISPC_REG(0x0000)
4944+#define DISPC_SYSCONFIG DISPC_REG(0x0010)
4945+#define DISPC_SYSSTATUS DISPC_REG(0x0014)
4946+#define DISPC_IRQSTATUS DISPC_REG(0x0018)
4947+#define DISPC_IRQENABLE DISPC_REG(0x001C)
4948+#define DISPC_CONTROL DISPC_REG(0x0040)
4949+#define DISPC_CONFIG DISPC_REG(0x0044)
4950+#define DISPC_CAPABLE DISPC_REG(0x0048)
4951+#define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C)
4952+#define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050)
4953+#define DISPC_TRANS_COLOR0 DISPC_REG(0x0054)
4954+#define DISPC_TRANS_COLOR1 DISPC_REG(0x0058)
4955+#define DISPC_LINE_STATUS DISPC_REG(0x005C)
4956+#define DISPC_LINE_NUMBER DISPC_REG(0x0060)
4957+#define DISPC_TIMING_H DISPC_REG(0x0064)
4958+#define DISPC_TIMING_V DISPC_REG(0x0068)
4959+#define DISPC_POL_FREQ DISPC_REG(0x006C)
4960+#define DISPC_DIVISOR DISPC_REG(0x0070)
4961+#define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074)
4962+#define DISPC_SIZE_DIG DISPC_REG(0x0078)
4963+#define DISPC_SIZE_LCD DISPC_REG(0x007C)
4964+
4965+/* DISPC GFX plane */
4966+#define DISPC_GFX_BA0 DISPC_REG(0x0080)
4967+#define DISPC_GFX_BA1 DISPC_REG(0x0084)
4968+#define DISPC_GFX_POSITION DISPC_REG(0x0088)
4969+#define DISPC_GFX_SIZE DISPC_REG(0x008C)
4970+#define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0)
4971+#define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4)
4972+#define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8)
4973+#define DISPC_GFX_ROW_INC DISPC_REG(0x00AC)
4974+#define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0)
4975+#define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4)
4976+#define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8)
4977+
4978+#define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4)
4979+#define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8)
4980+#define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC)
4981+
4982+#define DISPC_CPR_COEF_R DISPC_REG(0x0220)
4983+#define DISPC_CPR_COEF_G DISPC_REG(0x0224)
4984+#define DISPC_CPR_COEF_B DISPC_REG(0x0228)
4985+
4986+#define DISPC_GFX_PRELOAD DISPC_REG(0x022C)
4987+
4988+/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */
4989+#define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx)
4990+
4991+#define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000)
4992+#define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004)
4993+#define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008)
4994+#define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C)
4995+#define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010)
4996+#define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014)
4997+#define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018)
4998+#define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C)
4999+#define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020)
5000+#define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024)
5001+#define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028)
5002+#define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C)
5003+#define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030)
5004+
5005+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
5006+#define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8)
5007+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
5008+#define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8)
5009+/* coef index i = {0, 1, 2, 3, 4} */
5010+#define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4)
5011+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
5012+#define DISPC_VID_FIR_COEF_V(n, i) DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4)
5013+
5014+#define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04)
5015+
5016+
5017+#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
5018+ DISPC_IRQ_OCP_ERR | \
5019+ DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
5020+ DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
5021+ DISPC_IRQ_SYNC_LOST | \
5022+ DISPC_IRQ_SYNC_LOST_DIGIT)
5023+
5024+#define DISPC_MAX_NR_ISRS 8
5025+
5026+struct omap_dispc_isr_data {
5027+ omap_dispc_isr_t isr;
5028+ void *arg;
5029+ u32 mask;
5030+};
5031+
5032+#define REG_GET(idx, start, end) \
5033+ FLD_GET(dispc_read_reg(idx), start, end)
5034+
5035+#define REG_FLD_MOD(idx, val, start, end) \
5036+ dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
5037+
5038+static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES,
5039+ DISPC_VID_ATTRIBUTES(0),
5040+ DISPC_VID_ATTRIBUTES(1) };
5041+
5042+static struct {
5043+ void __iomem *base;
5044+
5045+ struct clk *dpll4_m4_ck;
5046+
5047+ unsigned long cache_req_pck;
5048+ unsigned long cache_prate;
5049+ struct dispc_clock_info cache_cinfo;
5050+
5051+ u32 fifo_size[3];
5052+
5053+ spinlock_t irq_lock;
5054+ u32 irq_error_mask;
5055+ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
5056+ u32 error_irqs;
5057+ struct work_struct error_work;
5058+
5059+ u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
5060+} dispc;
5061+
5062+static void _omap_dispc_set_irqs(void);
5063+
5064+static inline void dispc_write_reg(const struct dispc_reg idx, u32 val)
5065+{
5066+ __raw_writel(val, dispc.base + idx.idx);
5067+}
5068+
5069+static inline u32 dispc_read_reg(const struct dispc_reg idx)
5070+{
5071+ return __raw_readl(dispc.base + idx.idx);
5072+}
5073+
5074+#define SR(reg) \
5075+ dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
5076+#define RR(reg) \
5077+ dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)])
5078+
5079+void dispc_save_context(void)
5080+{
5081+ if (cpu_is_omap24xx())
5082+ return;
5083+
5084+ SR(SYSCONFIG);
5085+ SR(IRQENABLE);
5086+ SR(CONTROL);
5087+ SR(CONFIG);
5088+ SR(DEFAULT_COLOR0);
5089+ SR(DEFAULT_COLOR1);
5090+ SR(TRANS_COLOR0);
5091+ SR(TRANS_COLOR1);
5092+ SR(LINE_NUMBER);
5093+ SR(TIMING_H);
5094+ SR(TIMING_V);
5095+ SR(POL_FREQ);
5096+ SR(DIVISOR);
5097+ SR(GLOBAL_ALPHA);
5098+ SR(SIZE_DIG);
5099+ SR(SIZE_LCD);
5100+
5101+ SR(GFX_BA0);
5102+ SR(GFX_BA1);
5103+ SR(GFX_POSITION);
5104+ SR(GFX_SIZE);
5105+ SR(GFX_ATTRIBUTES);
5106+ SR(GFX_FIFO_THRESHOLD);
5107+ SR(GFX_ROW_INC);
5108+ SR(GFX_PIXEL_INC);
5109+ SR(GFX_WINDOW_SKIP);
5110+ SR(GFX_TABLE_BA);
5111+
5112+ SR(DATA_CYCLE1);
5113+ SR(DATA_CYCLE2);
5114+ SR(DATA_CYCLE3);
5115+
5116+ SR(CPR_COEF_R);
5117+ SR(CPR_COEF_G);
5118+ SR(CPR_COEF_B);
5119+
5120+ SR(GFX_PRELOAD);
5121+
5122+ /* VID1 */
5123+ SR(VID_BA0(0));
5124+ SR(VID_BA1(0));
5125+ SR(VID_POSITION(0));
5126+ SR(VID_SIZE(0));
5127+ SR(VID_ATTRIBUTES(0));
5128+ SR(VID_FIFO_THRESHOLD(0));
5129+ SR(VID_ROW_INC(0));
5130+ SR(VID_PIXEL_INC(0));
5131+ SR(VID_FIR(0));
5132+ SR(VID_PICTURE_SIZE(0));
5133+ SR(VID_ACCU0(0));
5134+ SR(VID_ACCU1(0));
5135+
5136+ SR(VID_FIR_COEF_H(0, 0));
5137+ SR(VID_FIR_COEF_H(0, 1));
5138+ SR(VID_FIR_COEF_H(0, 2));
5139+ SR(VID_FIR_COEF_H(0, 3));
5140+ SR(VID_FIR_COEF_H(0, 4));
5141+ SR(VID_FIR_COEF_H(0, 5));
5142+ SR(VID_FIR_COEF_H(0, 6));
5143+ SR(VID_FIR_COEF_H(0, 7));
5144+
5145+ SR(VID_FIR_COEF_HV(0, 0));
5146+ SR(VID_FIR_COEF_HV(0, 1));
5147+ SR(VID_FIR_COEF_HV(0, 2));
5148+ SR(VID_FIR_COEF_HV(0, 3));
5149+ SR(VID_FIR_COEF_HV(0, 4));
5150+ SR(VID_FIR_COEF_HV(0, 5));
5151+ SR(VID_FIR_COEF_HV(0, 6));
5152+ SR(VID_FIR_COEF_HV(0, 7));
5153+
5154+ SR(VID_CONV_COEF(0, 0));
5155+ SR(VID_CONV_COEF(0, 1));
5156+ SR(VID_CONV_COEF(0, 2));
5157+ SR(VID_CONV_COEF(0, 3));
5158+ SR(VID_CONV_COEF(0, 4));
5159+
5160+ SR(VID_FIR_COEF_V(0, 0));
5161+ SR(VID_FIR_COEF_V(0, 1));
5162+ SR(VID_FIR_COEF_V(0, 2));
5163+ SR(VID_FIR_COEF_V(0, 3));
5164+ SR(VID_FIR_COEF_V(0, 4));
5165+ SR(VID_FIR_COEF_V(0, 5));
5166+ SR(VID_FIR_COEF_V(0, 6));
5167+ SR(VID_FIR_COEF_V(0, 7));
5168+
5169+ SR(VID_PRELOAD(0));
5170+
5171+ /* VID2 */
5172+ SR(VID_BA0(1));
5173+ SR(VID_BA1(1));
5174+ SR(VID_POSITION(1));
5175+ SR(VID_SIZE(1));
5176+ SR(VID_ATTRIBUTES(1));
5177+ SR(VID_FIFO_THRESHOLD(1));
5178+ SR(VID_ROW_INC(1));
5179+ SR(VID_PIXEL_INC(1));
5180+ SR(VID_FIR(1));
5181+ SR(VID_PICTURE_SIZE(1));
5182+ SR(VID_ACCU0(1));
5183+ SR(VID_ACCU1(1));
5184+
5185+ SR(VID_FIR_COEF_H(1, 0));
5186+ SR(VID_FIR_COEF_H(1, 1));
5187+ SR(VID_FIR_COEF_H(1, 2));
5188+ SR(VID_FIR_COEF_H(1, 3));
5189+ SR(VID_FIR_COEF_H(1, 4));
5190+ SR(VID_FIR_COEF_H(1, 5));
5191+ SR(VID_FIR_COEF_H(1, 6));
5192+ SR(VID_FIR_COEF_H(1, 7));
5193+
5194+ SR(VID_FIR_COEF_HV(1, 0));
5195+ SR(VID_FIR_COEF_HV(1, 1));
5196+ SR(VID_FIR_COEF_HV(1, 2));
5197+ SR(VID_FIR_COEF_HV(1, 3));
5198+ SR(VID_FIR_COEF_HV(1, 4));
5199+ SR(VID_FIR_COEF_HV(1, 5));
5200+ SR(VID_FIR_COEF_HV(1, 6));
5201+ SR(VID_FIR_COEF_HV(1, 7));
5202+
5203+ SR(VID_CONV_COEF(1, 0));
5204+ SR(VID_CONV_COEF(1, 1));
5205+ SR(VID_CONV_COEF(1, 2));
5206+ SR(VID_CONV_COEF(1, 3));
5207+ SR(VID_CONV_COEF(1, 4));
5208+
5209+ SR(VID_FIR_COEF_V(1, 0));
5210+ SR(VID_FIR_COEF_V(1, 1));
5211+ SR(VID_FIR_COEF_V(1, 2));
5212+ SR(VID_FIR_COEF_V(1, 3));
5213+ SR(VID_FIR_COEF_V(1, 4));
5214+ SR(VID_FIR_COEF_V(1, 5));
5215+ SR(VID_FIR_COEF_V(1, 6));
5216+ SR(VID_FIR_COEF_V(1, 7));
5217+
5218+ SR(VID_PRELOAD(1));
5219+}
5220+
5221+void dispc_restore_context(void)
5222+{
5223+ RR(SYSCONFIG);
5224+ RR(IRQENABLE);
5225+ /*RR(CONTROL);*/
5226+ RR(CONFIG);
5227+ RR(DEFAULT_COLOR0);
5228+ RR(DEFAULT_COLOR1);
5229+ RR(TRANS_COLOR0);
5230+ RR(TRANS_COLOR1);
5231+ RR(LINE_NUMBER);
5232+ RR(TIMING_H);
5233+ RR(TIMING_V);
5234+ RR(POL_FREQ);
5235+ RR(DIVISOR);
5236+ RR(GLOBAL_ALPHA);
5237+ RR(SIZE_DIG);
5238+ RR(SIZE_LCD);
5239+
5240+ RR(GFX_BA0);
5241+ RR(GFX_BA1);
5242+ RR(GFX_POSITION);
5243+ RR(GFX_SIZE);
5244+ RR(GFX_ATTRIBUTES);
5245+ RR(GFX_FIFO_THRESHOLD);
5246+ RR(GFX_ROW_INC);
5247+ RR(GFX_PIXEL_INC);
5248+ RR(GFX_WINDOW_SKIP);
5249+ RR(GFX_TABLE_BA);
5250+
5251+ RR(DATA_CYCLE1);
5252+ RR(DATA_CYCLE2);
5253+ RR(DATA_CYCLE3);
5254+
5255+ RR(CPR_COEF_R);
5256+ RR(CPR_COEF_G);
5257+ RR(CPR_COEF_B);
5258+
5259+ RR(GFX_PRELOAD);
5260+
5261+ /* VID1 */
5262+ RR(VID_BA0(0));
5263+ RR(VID_BA1(0));
5264+ RR(VID_POSITION(0));
5265+ RR(VID_SIZE(0));
5266+ RR(VID_ATTRIBUTES(0));
5267+ RR(VID_FIFO_THRESHOLD(0));
5268+ RR(VID_ROW_INC(0));
5269+ RR(VID_PIXEL_INC(0));
5270+ RR(VID_FIR(0));
5271+ RR(VID_PICTURE_SIZE(0));
5272+ RR(VID_ACCU0(0));
5273+ RR(VID_ACCU1(0));
5274+
5275+ RR(VID_FIR_COEF_H(0, 0));
5276+ RR(VID_FIR_COEF_H(0, 1));
5277+ RR(VID_FIR_COEF_H(0, 2));
5278+ RR(VID_FIR_COEF_H(0, 3));
5279+ RR(VID_FIR_COEF_H(0, 4));
5280+ RR(VID_FIR_COEF_H(0, 5));
5281+ RR(VID_FIR_COEF_H(0, 6));
5282+ RR(VID_FIR_COEF_H(0, 7));
5283+
5284+ RR(VID_FIR_COEF_HV(0, 0));
5285+ RR(VID_FIR_COEF_HV(0, 1));
5286+ RR(VID_FIR_COEF_HV(0, 2));
5287+ RR(VID_FIR_COEF_HV(0, 3));
5288+ RR(VID_FIR_COEF_HV(0, 4));
5289+ RR(VID_FIR_COEF_HV(0, 5));
5290+ RR(VID_FIR_COEF_HV(0, 6));
5291+ RR(VID_FIR_COEF_HV(0, 7));
5292+
5293+ RR(VID_CONV_COEF(0, 0));
5294+ RR(VID_CONV_COEF(0, 1));
5295+ RR(VID_CONV_COEF(0, 2));
5296+ RR(VID_CONV_COEF(0, 3));
5297+ RR(VID_CONV_COEF(0, 4));
5298+
5299+ RR(VID_FIR_COEF_V(0, 0));
5300+ RR(VID_FIR_COEF_V(0, 1));
5301+ RR(VID_FIR_COEF_V(0, 2));
5302+ RR(VID_FIR_COEF_V(0, 3));
5303+ RR(VID_FIR_COEF_V(0, 4));
5304+ RR(VID_FIR_COEF_V(0, 5));
5305+ RR(VID_FIR_COEF_V(0, 6));
5306+ RR(VID_FIR_COEF_V(0, 7));
5307+
5308+ RR(VID_PRELOAD(0));
5309+
5310+ /* VID2 */
5311+ RR(VID_BA0(1));
5312+ RR(VID_BA1(1));
5313+ RR(VID_POSITION(1));
5314+ RR(VID_SIZE(1));
5315+ RR(VID_ATTRIBUTES(1));
5316+ RR(VID_FIFO_THRESHOLD(1));
5317+ RR(VID_ROW_INC(1));
5318+ RR(VID_PIXEL_INC(1));
5319+ RR(VID_FIR(1));
5320+ RR(VID_PICTURE_SIZE(1));
5321+ RR(VID_ACCU0(1));
5322+ RR(VID_ACCU1(1));
5323+
5324+ RR(VID_FIR_COEF_H(1, 0));
5325+ RR(VID_FIR_COEF_H(1, 1));
5326+ RR(VID_FIR_COEF_H(1, 2));
5327+ RR(VID_FIR_COEF_H(1, 3));
5328+ RR(VID_FIR_COEF_H(1, 4));
5329+ RR(VID_FIR_COEF_H(1, 5));
5330+ RR(VID_FIR_COEF_H(1, 6));
5331+ RR(VID_FIR_COEF_H(1, 7));
5332+
5333+ RR(VID_FIR_COEF_HV(1, 0));
5334+ RR(VID_FIR_COEF_HV(1, 1));
5335+ RR(VID_FIR_COEF_HV(1, 2));
5336+ RR(VID_FIR_COEF_HV(1, 3));
5337+ RR(VID_FIR_COEF_HV(1, 4));
5338+ RR(VID_FIR_COEF_HV(1, 5));
5339+ RR(VID_FIR_COEF_HV(1, 6));
5340+ RR(VID_FIR_COEF_HV(1, 7));
5341+
5342+ RR(VID_CONV_COEF(1, 0));
5343+ RR(VID_CONV_COEF(1, 1));
5344+ RR(VID_CONV_COEF(1, 2));
5345+ RR(VID_CONV_COEF(1, 3));
5346+ RR(VID_CONV_COEF(1, 4));
5347+
5348+ RR(VID_FIR_COEF_V(1, 0));
5349+ RR(VID_FIR_COEF_V(1, 1));
5350+ RR(VID_FIR_COEF_V(1, 2));
5351+ RR(VID_FIR_COEF_V(1, 3));
5352+ RR(VID_FIR_COEF_V(1, 4));
5353+ RR(VID_FIR_COEF_V(1, 5));
5354+ RR(VID_FIR_COEF_V(1, 6));
5355+ RR(VID_FIR_COEF_V(1, 7));
5356+
5357+ RR(VID_PRELOAD(1));
5358+
5359+ /* enable last, because LCD & DIGIT enable are here */
5360+ RR(CONTROL);
5361+}
5362+
5363+#undef SR
5364+#undef RR
5365+
5366+static inline void enable_clocks(bool enable)
5367+{
5368+ if (enable)
5369+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
5370+ else
5371+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
5372+}
5373+
5374+bool dispc_go_busy(enum omap_channel channel)
5375+{
5376+ int bit;
5377+
5378+ if (channel == OMAP_DSS_CHANNEL_LCD)
5379+ bit = 5; /* GOLCD */
5380+ else
5381+ bit = 6; /* GODIGIT */
5382+
5383+ return REG_GET(DISPC_CONTROL, bit, bit) == 1;
5384+}
5385+
5386+void dispc_go(enum omap_channel channel)
5387+{
5388+ int bit;
5389+
5390+ enable_clocks(1);
5391+
5392+ if (channel == OMAP_DSS_CHANNEL_LCD)
5393+ bit = 0; /* LCDENABLE */
5394+ else
5395+ bit = 1; /* DIGITALENABLE */
5396+
5397+ /* if the channel is not enabled, we don't need GO */
5398+ if (REG_GET(DISPC_CONTROL, bit, bit) == 0)
5399+ goto end;
5400+
5401+ if (channel == OMAP_DSS_CHANNEL_LCD)
5402+ bit = 5; /* GOLCD */
5403+ else
5404+ bit = 6; /* GODIGIT */
5405+
5406+ if (REG_GET(DISPC_CONTROL, bit, bit) == 1) {
5407+ DSSERR("GO bit not down for channel %d\n", channel);
5408+ goto end;
5409+ }
5410+
5411+ DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT");
5412+
5413+ REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
5414+end:
5415+ enable_clocks(0);
5416+}
5417+
5418+static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
5419+{
5420+ BUG_ON(plane == OMAP_DSS_GFX);
5421+
5422+ dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value);
5423+}
5424+
5425+static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
5426+{
5427+ BUG_ON(plane == OMAP_DSS_GFX);
5428+
5429+ dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value);
5430+}
5431+
5432+static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value)
5433+{
5434+ BUG_ON(plane == OMAP_DSS_GFX);
5435+
5436+ dispc_write_reg(DISPC_VID_FIR_COEF_V(plane-1, reg), value);
5437+}
5438+
5439+static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
5440+ int vscaleup, int five_taps)
5441+{
5442+ /* Coefficients for horizontal up-sampling */
5443+ static const u32 coef_hup[8] = {
5444+ 0x00800000,
5445+ 0x0D7CF800,
5446+ 0x1E70F5FF,
5447+ 0x335FF5FE,
5448+ 0xF74949F7,
5449+ 0xF55F33FB,
5450+ 0xF5701EFE,
5451+ 0xF87C0DFF,
5452+ };
5453+
5454+ /* Coefficients for horizontal down-sampling */
5455+ static const u32 coef_hdown[8] = {
5456+ 0x24382400,
5457+ 0x28371FFE,
5458+ 0x2C361BFB,
5459+ 0x303516F9,
5460+ 0x11343311,
5461+ 0x1635300C,
5462+ 0x1B362C08,
5463+ 0x1F372804,
5464+ };
5465+
5466+ /* Coefficients for horizontal and vertical up-sampling */
5467+ static const u32 coef_hvup[2][8] = {
5468+ {
5469+ 0x00800000,
5470+ 0x037B02FF,
5471+ 0x0C6F05FE,
5472+ 0x205907FB,
5473+ 0x00404000,
5474+ 0x075920FE,
5475+ 0x056F0CFF,
5476+ 0x027B0300,
5477+ },
5478+ {
5479+ 0x00800000,
5480+ 0x0D7CF8FF,
5481+ 0x1E70F5FE,
5482+ 0x335FF5FB,
5483+ 0xF7404000,
5484+ 0xF55F33FE,
5485+ 0xF5701EFF,
5486+ 0xF87C0D00,
5487+ },
5488+ };
5489+
5490+ /* Coefficients for horizontal and vertical down-sampling */
5491+ static const u32 coef_hvdown[2][8] = {
5492+ {
5493+ 0x24382400,
5494+ 0x28391F04,
5495+ 0x2D381B08,
5496+ 0x3237170C,
5497+ 0x123737F7,
5498+ 0x173732F9,
5499+ 0x1B382DFB,
5500+ 0x1F3928FE,
5501+ },
5502+ {
5503+ 0x24382400,
5504+ 0x28371F04,
5505+ 0x2C361B08,
5506+ 0x3035160C,
5507+ 0x113433F7,
5508+ 0x163530F9,
5509+ 0x1B362CFB,
5510+ 0x1F3728FE,
5511+ },
5512+ };
5513+
5514+ /* Coefficients for vertical up-sampling */
5515+ static const u32 coef_vup[8] = {
5516+ 0x00000000,
5517+ 0x0000FF00,
5518+ 0x0000FEFF,
5519+ 0x0000FBFE,
5520+ 0x000000F7,
5521+ 0x0000FEFB,
5522+ 0x0000FFFE,
5523+ 0x000000FF,
5524+ };
5525+
5526+
5527+ /* Coefficients for vertical down-sampling */
5528+ static const u32 coef_vdown[8] = {
5529+ 0x00000000,
5530+ 0x000004FE,
5531+ 0x000008FB,
5532+ 0x00000CF9,
5533+ 0x0000F711,
5534+ 0x0000F90C,
5535+ 0x0000FB08,
5536+ 0x0000FE04,
5537+ };
5538+
5539+ const u32 *h_coef;
5540+ const u32 *hv_coef;
5541+ const u32 *hv_coef_mod;
5542+ const u32 *v_coef;
5543+ int i;
5544+
5545+ if (hscaleup)
5546+ h_coef = coef_hup;
5547+ else
5548+ h_coef = coef_hdown;
5549+
5550+ if (vscaleup) {
5551+ hv_coef = coef_hvup[five_taps];
5552+ v_coef = coef_vup;
5553+
5554+ if (hscaleup)
5555+ hv_coef_mod = NULL;
5556+ else
5557+ hv_coef_mod = coef_hvdown[five_taps];
5558+ } else {
5559+ hv_coef = coef_hvdown[five_taps];
5560+ v_coef = coef_vdown;
5561+
5562+ if (hscaleup)
5563+ hv_coef_mod = coef_hvup[five_taps];
5564+ else
5565+ hv_coef_mod = NULL;
5566+ }
5567+
5568+ for (i = 0; i < 8; i++) {
5569+ u32 h, hv;
5570+
5571+ h = h_coef[i];
5572+
5573+ hv = hv_coef[i];
5574+
5575+ if (hv_coef_mod) {
5576+ hv &= 0xffffff00;
5577+ hv |= (hv_coef_mod[i] & 0xff);
5578+ }
5579+
5580+ _dispc_write_firh_reg(plane, i, h);
5581+ _dispc_write_firhv_reg(plane, i, hv);
5582+ }
5583+
5584+ if (!five_taps)
5585+ return;
5586+
5587+ for (i = 0; i < 8; i++) {
5588+ u32 v;
5589+ v = v_coef[i];
5590+ _dispc_write_firv_reg(plane, i, v);
5591+ }
5592+}
5593+
5594+static void _dispc_setup_color_conv_coef(void)
5595+{
5596+ const struct color_conv_coef {
5597+ int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
5598+ int full_range;
5599+ } ctbl_bt601_5 = {
5600+ 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
5601+ };
5602+
5603+ const struct color_conv_coef *ct;
5604+
5605+#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
5606+
5607+ ct = &ctbl_bt601_5;
5608+
5609+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry));
5610+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb));
5611+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr));
5612+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by));
5613+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb));
5614+
5615+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry));
5616+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb));
5617+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr));
5618+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by));
5619+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb));
5620+
5621+#undef CVAL
5622+
5623+ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11);
5624+ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11);
5625+}
5626+
5627+
5628+static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr)
5629+{
5630+ const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0,
5631+ DISPC_VID_BA0(0),
5632+ DISPC_VID_BA0(1) };
5633+
5634+ dispc_write_reg(ba0_reg[plane], paddr);
5635+}
5636+
5637+static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr)
5638+{
5639+ const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1,
5640+ DISPC_VID_BA1(0),
5641+ DISPC_VID_BA1(1) };
5642+
5643+ dispc_write_reg(ba1_reg[plane], paddr);
5644+}
5645+
5646+static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y)
5647+{
5648+ const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION,
5649+ DISPC_VID_POSITION(0),
5650+ DISPC_VID_POSITION(1) };
5651+
5652+ u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
5653+ dispc_write_reg(pos_reg[plane], val);
5654+}
5655+
5656+static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
5657+{
5658+ const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE,
5659+ DISPC_VID_PICTURE_SIZE(0),
5660+ DISPC_VID_PICTURE_SIZE(1) };
5661+ u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
5662+ dispc_write_reg(siz_reg[plane], val);
5663+}
5664+
5665+static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
5666+{
5667+ u32 val;
5668+ const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0),
5669+ DISPC_VID_SIZE(1) };
5670+
5671+ BUG_ON(plane == OMAP_DSS_GFX);
5672+
5673+ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
5674+ dispc_write_reg(vsi_reg[plane-1], val);
5675+}
5676+
5677+static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
5678+{
5679+
5680+ BUG_ON(plane == OMAP_DSS_VIDEO1);
5681+
5682+ if (plane == OMAP_DSS_GFX)
5683+ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
5684+ else if (plane == OMAP_DSS_VIDEO2)
5685+ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16);
5686+}
5687+
5688+static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc)
5689+{
5690+ const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC,
5691+ DISPC_VID_PIXEL_INC(0),
5692+ DISPC_VID_PIXEL_INC(1) };
5693+
5694+ dispc_write_reg(ri_reg[plane], inc);
5695+}
5696+
5697+static void _dispc_set_row_inc(enum omap_plane plane, s32 inc)
5698+{
5699+ const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC,
5700+ DISPC_VID_ROW_INC(0),
5701+ DISPC_VID_ROW_INC(1) };
5702+
5703+ dispc_write_reg(ri_reg[plane], inc);
5704+}
5705+
5706+static void _dispc_set_color_mode(enum omap_plane plane,
5707+ enum omap_color_mode color_mode)
5708+{
5709+ u32 m = 0;
5710+
5711+ switch (color_mode) {
5712+ case OMAP_DSS_COLOR_CLUT1:
5713+ m = 0x0; break;
5714+ case OMAP_DSS_COLOR_CLUT2:
5715+ m = 0x1; break;
5716+ case OMAP_DSS_COLOR_CLUT4:
5717+ m = 0x2; break;
5718+ case OMAP_DSS_COLOR_CLUT8:
5719+ m = 0x3; break;
5720+ case OMAP_DSS_COLOR_RGB12U:
5721+ m = 0x4; break;
5722+ case OMAP_DSS_COLOR_ARGB16:
5723+ m = 0x5; break;
5724+ case OMAP_DSS_COLOR_RGB16:
5725+ m = 0x6; break;
5726+ case OMAP_DSS_COLOR_RGB24U:
5727+ m = 0x8; break;
5728+ case OMAP_DSS_COLOR_RGB24P:
5729+ m = 0x9; break;
5730+ case OMAP_DSS_COLOR_YUV2:
5731+ m = 0xa; break;
5732+ case OMAP_DSS_COLOR_UYVY:
5733+ m = 0xb; break;
5734+ case OMAP_DSS_COLOR_ARGB32:
5735+ m = 0xc; break;
5736+ case OMAP_DSS_COLOR_RGBA32:
5737+ m = 0xd; break;
5738+ case OMAP_DSS_COLOR_RGBX32:
5739+ m = 0xe; break;
5740+ default:
5741+ BUG(); break;
5742+ }
5743+
5744+ REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1);
5745+}
5746+
5747+static void _dispc_set_channel_out(enum omap_plane plane,
5748+ enum omap_channel channel)
5749+{
5750+ int shift;
5751+ u32 val;
5752+
5753+ switch (plane) {
5754+ case OMAP_DSS_GFX:
5755+ shift = 8;
5756+ break;
5757+ case OMAP_DSS_VIDEO1:
5758+ case OMAP_DSS_VIDEO2:
5759+ shift = 16;
5760+ break;
5761+ default:
5762+ BUG();
5763+ return;
5764+ }
5765+
5766+ val = dispc_read_reg(dispc_reg_att[plane]);
5767+ val = FLD_MOD(val, channel, shift, shift);
5768+ dispc_write_reg(dispc_reg_att[plane], val);
5769+}
5770+
5771+void dispc_set_burst_size(enum omap_plane plane,
5772+ enum omap_burst_size burst_size)
5773+{
5774+ int shift;
5775+ u32 val;
5776+
5777+ enable_clocks(1);
5778+
5779+ switch (plane) {
5780+ case OMAP_DSS_GFX:
5781+ shift = 6;
5782+ break;
5783+ case OMAP_DSS_VIDEO1:
5784+ case OMAP_DSS_VIDEO2:
5785+ shift = 14;
5786+ break;
5787+ default:
5788+ BUG();
5789+ return;
5790+ }
5791+
5792+ val = dispc_read_reg(dispc_reg_att[plane]);
5793+ val = FLD_MOD(val, burst_size, shift+1, shift);
5794+ dispc_write_reg(dispc_reg_att[plane], val);
5795+
5796+ enable_clocks(0);
5797+}
5798+
5799+static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
5800+{
5801+ u32 val;
5802+
5803+ BUG_ON(plane == OMAP_DSS_GFX);
5804+
5805+ val = dispc_read_reg(dispc_reg_att[plane]);
5806+ val = FLD_MOD(val, enable, 9, 9);
5807+ dispc_write_reg(dispc_reg_att[plane], val);
5808+}
5809+
5810+void dispc_enable_replication(enum omap_plane plane, bool enable)
5811+{
5812+ int bit;
5813+
5814+ if (plane == OMAP_DSS_GFX)
5815+ bit = 5;
5816+ else
5817+ bit = 10;
5818+
5819+ enable_clocks(1);
5820+ REG_FLD_MOD(dispc_reg_att[plane], enable, bit, bit);
5821+ enable_clocks(0);
5822+}
5823+
5824+void dispc_set_lcd_size(u16 width, u16 height)
5825+{
5826+ u32 val;
5827+ BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
5828+ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
5829+ enable_clocks(1);
5830+ dispc_write_reg(DISPC_SIZE_LCD, val);
5831+ enable_clocks(0);
5832+}
5833+
5834+void dispc_set_digit_size(u16 width, u16 height)
5835+{
5836+ u32 val;
5837+ BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
5838+ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
5839+ enable_clocks(1);
5840+ dispc_write_reg(DISPC_SIZE_DIG, val);
5841+ enable_clocks(0);
5842+}
5843+
5844+static void dispc_read_plane_fifo_sizes(void)
5845+{
5846+ const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
5847+ DISPC_VID_FIFO_SIZE_STATUS(0),
5848+ DISPC_VID_FIFO_SIZE_STATUS(1) };
5849+ u32 size;
5850+ int plane;
5851+
5852+ enable_clocks(1);
5853+
5854+ for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
5855+ if (cpu_is_omap24xx())
5856+ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0);
5857+ else if (cpu_is_omap34xx())
5858+ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0);
5859+ else
5860+ BUG();
5861+
5862+ dispc.fifo_size[plane] = size;
5863+ }
5864+
5865+ enable_clocks(0);
5866+}
5867+
5868+u32 dispc_get_plane_fifo_size(enum omap_plane plane)
5869+{
5870+ return dispc.fifo_size[plane];
5871+}
5872+
5873+void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
5874+{
5875+ const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
5876+ DISPC_VID_FIFO_THRESHOLD(0),
5877+ DISPC_VID_FIFO_THRESHOLD(1) };
5878+ enable_clocks(1);
5879+
5880+ DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
5881+ plane,
5882+ REG_GET(ftrs_reg[plane], 11, 0),
5883+ REG_GET(ftrs_reg[plane], 27, 16),
5884+ low, high);
5885+
5886+ if (cpu_is_omap24xx())
5887+ dispc_write_reg(ftrs_reg[plane],
5888+ FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0));
5889+ else
5890+ dispc_write_reg(ftrs_reg[plane],
5891+ FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0));
5892+
5893+ enable_clocks(0);
5894+}
5895+
5896+void dispc_enable_fifomerge(bool enable)
5897+{
5898+ enable_clocks(1);
5899+
5900+ DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
5901+ REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
5902+
5903+ enable_clocks(0);
5904+}
5905+
5906+static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc)
5907+{
5908+ u32 val;
5909+ const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0),
5910+ DISPC_VID_FIR(1) };
5911+
5912+ BUG_ON(plane == OMAP_DSS_GFX);
5913+
5914+ if (cpu_is_omap24xx())
5915+ val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0);
5916+ else
5917+ val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
5918+ dispc_write_reg(fir_reg[plane-1], val);
5919+}
5920+
5921+static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
5922+{
5923+ u32 val;
5924+ const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0),
5925+ DISPC_VID_ACCU0(1) };
5926+
5927+ BUG_ON(plane == OMAP_DSS_GFX);
5928+
5929+ val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
5930+ dispc_write_reg(ac0_reg[plane-1], val);
5931+}
5932+
5933+static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
5934+{
5935+ u32 val;
5936+ const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0),
5937+ DISPC_VID_ACCU1(1) };
5938+
5939+ BUG_ON(plane == OMAP_DSS_GFX);
5940+
5941+ val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
5942+ dispc_write_reg(ac1_reg[plane-1], val);
5943+}
5944+
5945+
5946+static void _dispc_set_scaling(enum omap_plane plane,
5947+ u16 orig_width, u16 orig_height,
5948+ u16 out_width, u16 out_height,
5949+ bool ilace, bool five_taps,
5950+ bool fieldmode)
5951+{
5952+ int fir_hinc;
5953+ int fir_vinc;
5954+ int hscaleup, vscaleup;
5955+ int accu0 = 0;
5956+ int accu1 = 0;
5957+ u32 l;
5958+
5959+ BUG_ON(plane == OMAP_DSS_GFX);
5960+
5961+ hscaleup = orig_width <= out_width;
5962+ vscaleup = orig_height <= out_height;
5963+
5964+ _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps);
5965+
5966+ if (!orig_width || orig_width == out_width)
5967+ fir_hinc = 0;
5968+ else
5969+ fir_hinc = 1024 * orig_width / out_width;
5970+
5971+ if (!orig_height || orig_height == out_height)
5972+ fir_vinc = 0;
5973+ else
5974+ fir_vinc = 1024 * orig_height / out_height;
5975+
5976+ _dispc_set_fir(plane, fir_hinc, fir_vinc);
5977+
5978+ l = dispc_read_reg(dispc_reg_att[plane]);
5979+ l &= ~((0x0f << 5) | (0x3 << 21));
5980+
5981+ l |= fir_hinc ? (1 << 5) : 0;
5982+ l |= fir_vinc ? (1 << 6) : 0;
5983+
5984+ l |= hscaleup ? 0 : (1 << 7);
5985+ l |= vscaleup ? 0 : (1 << 8);
5986+
5987+ l |= five_taps ? (1 << 21) : 0;
5988+ l |= five_taps ? (1 << 22) : 0;
5989+
5990+ dispc_write_reg(dispc_reg_att[plane], l);
5991+
5992+ /*
5993+ * field 0 = even field = bottom field
5994+ * field 1 = odd field = top field
5995+ */
5996+ if (ilace && !fieldmode) {
5997+ accu1 = 0;
5998+ accu0 = (fir_vinc / 2) & 0x3ff;
5999+ if (accu0 >= 1024/2) {
6000+ accu1 = 1024/2;
6001+ accu0 -= accu1;
6002+ }
6003+ }
6004+
6005+ _dispc_set_vid_accu0(plane, 0, accu0);
6006+ _dispc_set_vid_accu1(plane, 0, accu1);
6007+}
6008+
6009+static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
6010+ bool mirroring, enum omap_color_mode color_mode)
6011+{
6012+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
6013+ color_mode == OMAP_DSS_COLOR_UYVY) {
6014+ int vidrot = 0;
6015+
6016+ if (mirroring) {
6017+ switch (rotation) {
6018+ case 0:
6019+ vidrot = 2;
6020+ break;
6021+ case 1:
6022+ vidrot = 1;
6023+ break;
6024+ case 2:
6025+ vidrot = 0;
6026+ break;
6027+ case 3:
6028+ vidrot = 3;
6029+ break;
6030+ }
6031+ } else {
6032+ switch (rotation) {
6033+ case 0:
6034+ vidrot = 0;
6035+ break;
6036+ case 1:
6037+ vidrot = 1;
6038+ break;
6039+ case 2:
6040+ vidrot = 2;
6041+ break;
6042+ case 3:
6043+ vidrot = 3;
6044+ break;
6045+ }
6046+ }
6047+
6048+ REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12);
6049+
6050+ if (rotation == 1 || rotation == 3)
6051+ REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18);
6052+ else
6053+ REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18);
6054+ } else {
6055+ REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12);
6056+ REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18);
6057+ }
6058+}
6059+
6060+static s32 pixinc(int pixels, u8 ps)
6061+{
6062+ if (pixels == 1)
6063+ return 1;
6064+ else if (pixels > 1)
6065+ return 1 + (pixels - 1) * ps;
6066+ else if (pixels < 0)
6067+ return 1 - (-pixels + 1) * ps;
6068+ else
6069+ BUG();
6070+}
6071+
6072+static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
6073+ u16 screen_width,
6074+ u16 width, u16 height,
6075+ enum omap_color_mode color_mode, bool fieldmode,
6076+ unsigned int field_offset,
6077+ unsigned *offset0, unsigned *offset1,
6078+ s32 *row_inc, s32 *pix_inc)
6079+{
6080+ u8 ps;
6081+
6082+ switch (color_mode) {
6083+ case OMAP_DSS_COLOR_RGB16:
6084+ case OMAP_DSS_COLOR_ARGB16:
6085+ ps = 2;
6086+ break;
6087+
6088+ case OMAP_DSS_COLOR_RGB24P:
6089+ ps = 3;
6090+ break;
6091+
6092+ case OMAP_DSS_COLOR_RGB24U:
6093+ case OMAP_DSS_COLOR_ARGB32:
6094+ case OMAP_DSS_COLOR_RGBA32:
6095+ case OMAP_DSS_COLOR_RGBX32:
6096+ case OMAP_DSS_COLOR_YUV2:
6097+ case OMAP_DSS_COLOR_UYVY:
6098+ ps = 4;
6099+ break;
6100+
6101+ default:
6102+ BUG();
6103+ return;
6104+ }
6105+
6106+ DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
6107+ width, height);
6108+
6109+ /*
6110+ * field 0 = even field = bottom field
6111+ * field 1 = odd field = top field
6112+ */
6113+ switch (rotation + mirror * 4) {
6114+ case 0:
6115+ case 2:
6116+ /*
6117+ * If the pixel format is YUV or UYVY divide the width
6118+ * of the image by 2 for 0 and 180 degree rotation.
6119+ */
6120+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
6121+ color_mode == OMAP_DSS_COLOR_UYVY)
6122+ width = width >> 1;
6123+ case 1:
6124+ case 3:
6125+ *offset1 = 0;
6126+ if (field_offset)
6127+ *offset0 = field_offset * screen_width * ps;
6128+ else
6129+ *offset0 = 0;
6130+
6131+ *row_inc = pixinc(1 + (screen_width - width) +
6132+ (fieldmode ? screen_width : 0),
6133+ ps);
6134+ *pix_inc = pixinc(1, ps);
6135+ break;
6136+
6137+ case 4:
6138+ case 6:
6139+ /* If the pixel format is YUV or UYVY divide the width
6140+ * of the image by 2 for 0 degree and 180 degree
6141+ */
6142+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
6143+ color_mode == OMAP_DSS_COLOR_UYVY)
6144+ width = width >> 1;
6145+ case 5:
6146+ case 7:
6147+ *offset1 = 0;
6148+ if (field_offset)
6149+ *offset0 = field_offset * screen_width * ps;
6150+ else
6151+ *offset0 = 0;
6152+ *row_inc = pixinc(1 - (screen_width + width) -
6153+ (fieldmode ? screen_width : 0),
6154+ ps);
6155+ *pix_inc = pixinc(1, ps);
6156+ break;
6157+
6158+ default:
6159+ BUG();
6160+ }
6161+}
6162+
6163+static void calc_dma_rotation_offset(u8 rotation, bool mirror,
6164+ u16 screen_width,
6165+ u16 width, u16 height,
6166+ enum omap_color_mode color_mode, bool fieldmode,
6167+ unsigned int field_offset,
6168+ unsigned *offset0, unsigned *offset1,
6169+ s32 *row_inc, s32 *pix_inc)
6170+{
6171+ u8 ps;
6172+ u16 fbw, fbh;
6173+
6174+ switch (color_mode) {
6175+ case OMAP_DSS_COLOR_RGB16:
6176+ case OMAP_DSS_COLOR_ARGB16:
6177+ ps = 2;
6178+ break;
6179+
6180+ case OMAP_DSS_COLOR_RGB24P:
6181+ ps = 3;
6182+ break;
6183+
6184+ case OMAP_DSS_COLOR_RGB24U:
6185+ case OMAP_DSS_COLOR_ARGB32:
6186+ case OMAP_DSS_COLOR_RGBA32:
6187+ case OMAP_DSS_COLOR_RGBX32:
6188+ ps = 4;
6189+ break;
6190+
6191+ case OMAP_DSS_COLOR_YUV2:
6192+ case OMAP_DSS_COLOR_UYVY:
6193+ ps = 2;
6194+ break;
6195+ default:
6196+ BUG();
6197+ return;
6198+ }
6199+
6200+ DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
6201+ width, height);
6202+
6203+ /* width & height are overlay sizes, convert to fb sizes */
6204+
6205+ if (rotation == 0 || rotation == 2) {
6206+ fbw = width;
6207+ fbh = height;
6208+ } else {
6209+ fbw = height;
6210+ fbh = width;
6211+ }
6212+
6213+ /*
6214+ * field 0 = even field = bottom field
6215+ * field 1 = odd field = top field
6216+ */
6217+ switch (rotation + mirror * 4) {
6218+ case 0:
6219+ *offset1 = 0;
6220+ if (field_offset)
6221+ *offset0 = *offset1 + field_offset * screen_width * ps;
6222+ else
6223+ *offset0 = *offset1;
6224+ *row_inc = pixinc(1 + (screen_width - fbw) +
6225+ (fieldmode ? screen_width : 0),
6226+ ps);
6227+ *pix_inc = pixinc(1, ps);
6228+ break;
6229+ case 1:
6230+ *offset1 = screen_width * (fbh - 1) * ps;
6231+ if (field_offset)
6232+ *offset0 = *offset1 + field_offset * ps;
6233+ else
6234+ *offset0 = *offset1;
6235+ *row_inc = pixinc(screen_width * (fbh - 1) + 1 +
6236+ (fieldmode ? 1 : 0), ps);
6237+ *pix_inc = pixinc(-screen_width, ps);
6238+ break;
6239+ case 2:
6240+ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
6241+ if (field_offset)
6242+ *offset0 = *offset1 - field_offset * screen_width * ps;
6243+ else
6244+ *offset0 = *offset1;
6245+ *row_inc = pixinc(-1 -
6246+ (screen_width - fbw) -
6247+ (fieldmode ? screen_width : 0),
6248+ ps);
6249+ *pix_inc = pixinc(-1, ps);
6250+ break;
6251+ case 3:
6252+ *offset1 = (fbw - 1) * ps;
6253+ if (field_offset)
6254+ *offset0 = *offset1 - field_offset * ps;
6255+ else
6256+ *offset0 = *offset1;
6257+ *row_inc = pixinc(-screen_width * (fbh - 1) - 1 -
6258+ (fieldmode ? 1 : 0), ps);
6259+ *pix_inc = pixinc(screen_width, ps);
6260+ break;
6261+
6262+ /* mirroring */
6263+ case 0 + 4:
6264+ *offset1 = (fbw - 1) * ps;
6265+ if (field_offset)
6266+ *offset0 = *offset1 + field_offset * screen_width * ps;
6267+ else
6268+ *offset0 = *offset1;
6269+ *row_inc = pixinc(screen_width * 2 - 1 +
6270+ (fieldmode ? screen_width : 0),
6271+ ps);
6272+ *pix_inc = pixinc(-1, ps);
6273+ break;
6274+
6275+ case 1 + 4:
6276+ *offset1 = 0;
6277+ if (field_offset)
6278+ *offset0 = *offset1 + field_offset * ps;
6279+ else
6280+ *offset0 = *offset1;
6281+ *row_inc = pixinc(-screen_width * (fbh - 1) + 1 +
6282+ (fieldmode ? 1 : 0),
6283+ ps);
6284+ *pix_inc = pixinc(screen_width, ps);
6285+ break;
6286+
6287+ case 2 + 4:
6288+ *offset1 = screen_width * (fbh - 1) * ps;
6289+ if (field_offset)
6290+ *offset0 = *offset1 - field_offset * screen_width * ps;
6291+ else
6292+ *offset0 = *offset1;
6293+ *row_inc = pixinc(1 - screen_width * 2 -
6294+ (fieldmode ? screen_width : 0),
6295+ ps);
6296+ *pix_inc = pixinc(1, ps);
6297+ break;
6298+
6299+ case 3 + 4:
6300+ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
6301+ if (field_offset)
6302+ *offset0 = *offset1 - field_offset * ps;
6303+ else
6304+ *offset0 = *offset1;
6305+ *row_inc = pixinc(screen_width * (fbh - 1) - 1 -
6306+ (fieldmode ? 1 : 0),
6307+ ps);
6308+ *pix_inc = pixinc(-screen_width, ps);
6309+ break;
6310+
6311+ default:
6312+ BUG();
6313+ }
6314+}
6315+
6316+static unsigned long calc_fclk_five_taps(u16 width, u16 height,
6317+ u16 out_width, u16 out_height, enum omap_color_mode color_mode)
6318+{
6319+ u32 fclk = 0;
6320+ /* FIXME venc pclk? */
6321+ u64 tmp, pclk = dispc_pclk_rate();
6322+
6323+ if (height > out_height) {
6324+ /* FIXME get real display PPL */
6325+ unsigned int ppl = 800;
6326+
6327+ tmp = pclk * height * out_width;
6328+ do_div(tmp, 2 * out_height * ppl);
6329+ fclk = tmp;
6330+
6331+ if (height > 2 * out_height && ppl != out_width) {
6332+ tmp = pclk * (height - 2 * out_height) * out_width;
6333+ do_div(tmp, 2 * out_height * (ppl - out_width));
6334+ fclk = max(fclk, (u32) tmp);
6335+ }
6336+ }
6337+
6338+ if (width > out_width) {
6339+ tmp = pclk * width;
6340+ do_div(tmp, out_width);
6341+ fclk = max(fclk, (u32) tmp);
6342+
6343+ if (color_mode == OMAP_DSS_COLOR_RGB24U)
6344+ fclk <<= 1;
6345+ }
6346+
6347+ return fclk;
6348+}
6349+
6350+static unsigned long calc_fclk(u16 width, u16 height,
6351+ u16 out_width, u16 out_height)
6352+{
6353+ unsigned int hf, vf;
6354+
6355+ /*
6356+ * FIXME how to determine the 'A' factor
6357+ * for the no downscaling case ?
6358+ */
6359+
6360+ if (width > 3 * out_width)
6361+ hf = 4;
6362+ else if (width > 2 * out_width)
6363+ hf = 3;
6364+ else if (width > out_width)
6365+ hf = 2;
6366+ else
6367+ hf = 1;
6368+
6369+ if (height > out_height)
6370+ vf = 2;
6371+ else
6372+ vf = 1;
6373+
6374+ /* FIXME venc pclk? */
6375+ return dispc_pclk_rate() * vf * hf;
6376+}
6377+
6378+void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
6379+{
6380+ enable_clocks(1);
6381+ _dispc_set_channel_out(plane, channel_out);
6382+ enable_clocks(0);
6383+}
6384+
6385+static int _dispc_setup_plane(enum omap_plane plane,
6386+ u32 paddr, u16 screen_width,
6387+ u16 pos_x, u16 pos_y,
6388+ u16 width, u16 height,
6389+ u16 out_width, u16 out_height,
6390+ enum omap_color_mode color_mode,
6391+ bool ilace,
6392+ enum omap_dss_rotation_type rotation_type,
6393+ u8 rotation, int mirror,
6394+ u8 global_alpha)
6395+{
6396+ const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
6397+ bool five_taps = 0;
6398+ bool fieldmode = 0;
6399+ int cconv = 0;
6400+ unsigned offset0, offset1;
6401+ s32 row_inc;
6402+ s32 pix_inc;
6403+ u16 frame_height = height;
6404+ unsigned int field_offset = 0;
6405+
6406+ if (paddr == 0)
6407+ return -EINVAL;
6408+
6409+ if (ilace && height == out_height)
6410+ fieldmode = 1;
6411+
6412+ if (ilace) {
6413+ if (fieldmode)
6414+ height /= 2;
6415+ pos_y /= 2;
6416+ out_height /= 2;
6417+
6418+ DSSDBG("adjusting for ilace: height %d, pos_y %d, "
6419+ "out_height %d\n",
6420+ height, pos_y, out_height);
6421+ }
6422+
6423+ if (plane == OMAP_DSS_GFX) {
6424+ if (width != out_width || height != out_height)
6425+ return -EINVAL;
6426+
6427+ switch (color_mode) {
6428+ case OMAP_DSS_COLOR_ARGB16:
6429+ case OMAP_DSS_COLOR_RGB16:
6430+ case OMAP_DSS_COLOR_RGB24P:
6431+ case OMAP_DSS_COLOR_RGB24U:
6432+ case OMAP_DSS_COLOR_ARGB32:
6433+ case OMAP_DSS_COLOR_RGBA32:
6434+ case OMAP_DSS_COLOR_RGBX32:
6435+ break;
6436+
6437+ default:
6438+ return -EINVAL;
6439+ }
6440+ } else {
6441+ /* video plane */
6442+
6443+ unsigned long fclk = 0;
6444+
6445+ if (out_width < width / maxdownscale ||
6446+ out_width > width * 8)
6447+ return -EINVAL;
6448+
6449+ if (out_height < height / maxdownscale ||
6450+ out_height > height * 8)
6451+ return -EINVAL;
6452+
6453+ switch (color_mode) {
6454+ case OMAP_DSS_COLOR_RGB16:
6455+ case OMAP_DSS_COLOR_RGB24P:
6456+ case OMAP_DSS_COLOR_RGB24U:
6457+ case OMAP_DSS_COLOR_RGBX32:
6458+ break;
6459+
6460+ case OMAP_DSS_COLOR_ARGB16:
6461+ case OMAP_DSS_COLOR_ARGB32:
6462+ case OMAP_DSS_COLOR_RGBA32:
6463+ if (plane == OMAP_DSS_VIDEO1)
6464+ return -EINVAL;
6465+ break;
6466+
6467+ case OMAP_DSS_COLOR_YUV2:
6468+ case OMAP_DSS_COLOR_UYVY:
6469+ cconv = 1;
6470+ break;
6471+
6472+ default:
6473+ return -EINVAL;
6474+ }
6475+
6476+ /* Must use 5-tap filter? */
6477+ five_taps = height > out_height * 2;
6478+
6479+ if (!five_taps) {
6480+ fclk = calc_fclk(width, height,
6481+ out_width, out_height);
6482+
6483+ /* Try 5-tap filter if 3-tap fclk is too high */
6484+ if (cpu_is_omap34xx() && height > out_height &&
6485+ fclk > dispc_fclk_rate())
6486+ five_taps = true;
6487+ }
6488+
6489+ if (width > (2048 >> five_taps))
6490+ return -EINVAL;
6491+
6492+ if (five_taps)
6493+ fclk = calc_fclk_five_taps(width, height,
6494+ out_width, out_height, color_mode);
6495+
6496+ DSSDBG("required fclk rate = %lu Hz\n", fclk);
6497+ DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
6498+
6499+ if (fclk > dispc_fclk_rate()) {
6500+ DSSERR("failed to set up scaling, "
6501+ "required fclk rate = %lu Hz, "
6502+ "current fclk rate = %lu Hz\n",
6503+ fclk, dispc_fclk_rate());
6504+ return -EINVAL;
6505+ }
6506+ }
6507+
6508+ if (ilace && !fieldmode) {
6509+ /*
6510+ * when downscaling the bottom field may have to start several
6511+ * source lines below the top field. Unfortunately ACCUI
6512+ * registers will only hold the fractional part of the offset
6513+ * so the integer part must be added to the base address of the
6514+ * bottom field.
6515+ */
6516+ if (!height || height == out_height)
6517+ field_offset = 0;
6518+ else
6519+ field_offset = height / out_height / 2;
6520+ }
6521+
6522+ /* Fields are independent but interleaved in memory. */
6523+ if (fieldmode)
6524+ field_offset = 1;
6525+
6526+ if (rotation_type == OMAP_DSS_ROT_DMA)
6527+ calc_dma_rotation_offset(rotation, mirror,
6528+ screen_width, width, frame_height, color_mode,
6529+ fieldmode, field_offset,
6530+ &offset0, &offset1, &row_inc, &pix_inc);
6531+ else
6532+ calc_vrfb_rotation_offset(rotation, mirror,
6533+ screen_width, width, frame_height, color_mode,
6534+ fieldmode, field_offset,
6535+ &offset0, &offset1, &row_inc, &pix_inc);
6536+
6537+ DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
6538+ offset0, offset1, row_inc, pix_inc);
6539+
6540+ _dispc_set_color_mode(plane, color_mode);
6541+
6542+ _dispc_set_plane_ba0(plane, paddr + offset0);
6543+ _dispc_set_plane_ba1(plane, paddr + offset1);
6544+
6545+ _dispc_set_row_inc(plane, row_inc);
6546+ _dispc_set_pix_inc(plane, pix_inc);
6547+
6548+ DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height,
6549+ out_width, out_height);
6550+
6551+ _dispc_set_plane_pos(plane, pos_x, pos_y);
6552+
6553+ _dispc_set_pic_size(plane, width, height);
6554+
6555+ if (plane != OMAP_DSS_GFX) {
6556+ _dispc_set_scaling(plane, width, height,
6557+ out_width, out_height,
6558+ ilace, five_taps, fieldmode);
6559+ _dispc_set_vid_size(plane, out_width, out_height);
6560+ _dispc_set_vid_color_conv(plane, cconv);
6561+ }
6562+
6563+ _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
6564+
6565+ if (plane != OMAP_DSS_VIDEO1)
6566+ _dispc_setup_global_alpha(plane, global_alpha);
6567+
6568+ return 0;
6569+}
6570+
6571+static void _dispc_enable_plane(enum omap_plane plane, bool enable)
6572+{
6573+ REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0);
6574+}
6575+
6576+static void dispc_disable_isr(void *data, u32 mask)
6577+{
6578+ struct completion *compl = data;
6579+ complete(compl);
6580+}
6581+
6582+static void _enable_lcd_out(bool enable)
6583+{
6584+ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
6585+}
6586+
6587+void dispc_enable_lcd_out(bool enable)
6588+{
6589+ struct completion frame_done_completion;
6590+ bool is_on;
6591+ int r;
6592+
6593+ enable_clocks(1);
6594+
6595+ /* When we disable LCD output, we need to wait until frame is done.
6596+ * Otherwise the DSS is still working, and turning off the clocks
6597+ * prevents DSS from going to OFF mode */
6598+ is_on = REG_GET(DISPC_CONTROL, 0, 0);
6599+
6600+ if (!enable && is_on) {
6601+ init_completion(&frame_done_completion);
6602+
6603+ r = omap_dispc_register_isr(dispc_disable_isr,
6604+ &frame_done_completion,
6605+ DISPC_IRQ_FRAMEDONE);
6606+
6607+ if (r)
6608+ DSSERR("failed to register FRAMEDONE isr\n");
6609+ }
6610+
6611+ _enable_lcd_out(enable);
6612+
6613+ if (!enable && is_on) {
6614+ if (!wait_for_completion_timeout(&frame_done_completion,
6615+ msecs_to_jiffies(100)))
6616+ DSSERR("timeout waiting for FRAME DONE\n");
6617+
6618+ r = omap_dispc_unregister_isr(dispc_disable_isr,
6619+ &frame_done_completion,
6620+ DISPC_IRQ_FRAMEDONE);
6621+
6622+ if (r)
6623+ DSSERR("failed to unregister FRAMEDONE isr\n");
6624+ }
6625+
6626+ enable_clocks(0);
6627+}
6628+
6629+static void _enable_digit_out(bool enable)
6630+{
6631+ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
6632+}
6633+
6634+void dispc_enable_digit_out(bool enable)
6635+{
6636+ struct completion frame_done_completion;
6637+ int r;
6638+
6639+ enable_clocks(1);
6640+
6641+ if (REG_GET(DISPC_CONTROL, 1, 1) == enable) {
6642+ enable_clocks(0);
6643+ return;
6644+ }
6645+
6646+ if (enable) {
6647+ unsigned long flags;
6648+ /* When we enable digit output, we'll get an extra digit
6649+ * sync lost interrupt, that we need to ignore */
6650+ spin_lock_irqsave(&dispc.irq_lock, flags);
6651+ dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
6652+ _omap_dispc_set_irqs();
6653+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
6654+ }
6655+
6656+ /* When we disable digit output, we need to wait until fields are done.
6657+ * Otherwise the DSS is still working, and turning off the clocks
6658+ * prevents DSS from going to OFF mode. And when enabling, we need to
6659+ * wait for the extra sync losts */
6660+ init_completion(&frame_done_completion);
6661+
6662+ r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
6663+ DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
6664+ if (r)
6665+ DSSERR("failed to register EVSYNC isr\n");
6666+
6667+ _enable_digit_out(enable);
6668+
6669+ /* XXX I understand from TRM that we should only wait for the
6670+ * current field to complete. But it seems we have to wait
6671+ * for both fields */
6672+ if (!wait_for_completion_timeout(&frame_done_completion,
6673+ msecs_to_jiffies(100)))
6674+ DSSERR("timeout waiting for EVSYNC\n");
6675+
6676+ if (!wait_for_completion_timeout(&frame_done_completion,
6677+ msecs_to_jiffies(100)))
6678+ DSSERR("timeout waiting for EVSYNC\n");
6679+
6680+ r = omap_dispc_unregister_isr(dispc_disable_isr,
6681+ &frame_done_completion,
6682+ DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
6683+ if (r)
6684+ DSSERR("failed to unregister EVSYNC isr\n");
6685+
6686+ if (enable) {
6687+ unsigned long flags;
6688+ spin_lock_irqsave(&dispc.irq_lock, flags);
6689+ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
6690+ dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
6691+ _omap_dispc_set_irqs();
6692+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
6693+ }
6694+
6695+ enable_clocks(0);
6696+}
6697+
6698+void dispc_lcd_enable_signal_polarity(bool act_high)
6699+{
6700+ enable_clocks(1);
6701+ REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
6702+ enable_clocks(0);
6703+}
6704+
6705+void dispc_lcd_enable_signal(bool enable)
6706+{
6707+ enable_clocks(1);
6708+ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
6709+ enable_clocks(0);
6710+}
6711+
6712+void dispc_pck_free_enable(bool enable)
6713+{
6714+ enable_clocks(1);
6715+ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
6716+ enable_clocks(0);
6717+}
6718+
6719+void dispc_enable_fifohandcheck(bool enable)
6720+{
6721+ enable_clocks(1);
6722+ REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
6723+ enable_clocks(0);
6724+}
6725+
6726+
6727+void dispc_set_lcd_display_type(enum omap_lcd_display_type type)
6728+{
6729+ int mode;
6730+
6731+ switch (type) {
6732+ case OMAP_DSS_LCD_DISPLAY_STN:
6733+ mode = 0;
6734+ break;
6735+
6736+ case OMAP_DSS_LCD_DISPLAY_TFT:
6737+ mode = 1;
6738+ break;
6739+
6740+ default:
6741+ BUG();
6742+ return;
6743+ }
6744+
6745+ enable_clocks(1);
6746+ REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
6747+ enable_clocks(0);
6748+}
6749+
6750+void dispc_set_loadmode(enum omap_dss_load_mode mode)
6751+{
6752+ enable_clocks(1);
6753+ REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
6754+ enable_clocks(0);
6755+}
6756+
6757+
6758+void dispc_set_default_color(enum omap_channel channel, u32 color)
6759+{
6760+ const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
6761+ DISPC_DEFAULT_COLOR1 };
6762+
6763+ enable_clocks(1);
6764+ dispc_write_reg(def_reg[channel], color);
6765+ enable_clocks(0);
6766+}
6767+
6768+u32 dispc_get_default_color(enum omap_channel channel)
6769+{
6770+ const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
6771+ DISPC_DEFAULT_COLOR1 };
6772+ u32 l;
6773+
6774+ BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT &&
6775+ channel != OMAP_DSS_CHANNEL_LCD);
6776+
6777+ enable_clocks(1);
6778+ l = dispc_read_reg(def_reg[channel]);
6779+ enable_clocks(0);
6780+
6781+ return l;
6782+}
6783+
6784+void dispc_set_trans_key(enum omap_channel ch,
6785+ enum omap_dss_trans_key_type type,
6786+ u32 trans_key)
6787+{
6788+ const struct dispc_reg tr_reg[] = {
6789+ DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
6790+
6791+ enable_clocks(1);
6792+ if (ch == OMAP_DSS_CHANNEL_LCD)
6793+ REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
6794+ else /* OMAP_DSS_CHANNEL_DIGIT */
6795+ REG_FLD_MOD(DISPC_CONFIG, type, 13, 13);
6796+
6797+ dispc_write_reg(tr_reg[ch], trans_key);
6798+ enable_clocks(0);
6799+}
6800+
6801+void dispc_get_trans_key(enum omap_channel ch,
6802+ enum omap_dss_trans_key_type *type,
6803+ u32 *trans_key)
6804+{
6805+ const struct dispc_reg tr_reg[] = {
6806+ DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
6807+
6808+ enable_clocks(1);
6809+ if (type) {
6810+ if (ch == OMAP_DSS_CHANNEL_LCD)
6811+ *type = REG_GET(DISPC_CONFIG, 11, 11);
6812+ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
6813+ *type = REG_GET(DISPC_CONFIG, 13, 13);
6814+ else
6815+ BUG();
6816+ }
6817+
6818+ if (trans_key)
6819+ *trans_key = dispc_read_reg(tr_reg[ch]);
6820+ enable_clocks(0);
6821+}
6822+
6823+void dispc_enable_trans_key(enum omap_channel ch, bool enable)
6824+{
6825+ enable_clocks(1);
6826+ if (ch == OMAP_DSS_CHANNEL_LCD)
6827+ REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
6828+ else /* OMAP_DSS_CHANNEL_DIGIT */
6829+ REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
6830+ enable_clocks(0);
6831+}
6832+void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
6833+{
6834+ enable_clocks(1);
6835+ if (ch == OMAP_DSS_CHANNEL_LCD)
6836+ REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
6837+ else /* OMAP_DSS_CHANNEL_DIGIT */
6838+ REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
6839+ enable_clocks(0);
6840+}
6841+bool dispc_alpha_blending_enabled(enum omap_channel ch)
6842+{
6843+ bool enabled;
6844+
6845+ enable_clocks(1);
6846+ if (ch == OMAP_DSS_CHANNEL_LCD)
6847+ enabled = REG_GET(DISPC_CONFIG, 18, 18);
6848+ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
6849+ enabled = REG_GET(DISPC_CONFIG, 18, 18);
6850+ else
6851+ BUG();
6852+ enable_clocks(0);
6853+
6854+ return enabled;
6855+
6856+}
6857+
6858+
6859+bool dispc_trans_key_enabled(enum omap_channel ch)
6860+{
6861+ bool enabled;
6862+
6863+ enable_clocks(1);
6864+ if (ch == OMAP_DSS_CHANNEL_LCD)
6865+ enabled = REG_GET(DISPC_CONFIG, 10, 10);
6866+ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
6867+ enabled = REG_GET(DISPC_CONFIG, 12, 12);
6868+ else
6869+ BUG();
6870+ enable_clocks(0);
6871+
6872+ return enabled;
6873+}
6874+
6875+
6876+void dispc_set_tft_data_lines(u8 data_lines)
6877+{
6878+ int code;
6879+
6880+ switch (data_lines) {
6881+ case 12:
6882+ code = 0;
6883+ break;
6884+ case 16:
6885+ code = 1;
6886+ break;
6887+ case 18:
6888+ code = 2;
6889+ break;
6890+ case 24:
6891+ code = 3;
6892+ break;
6893+ default:
6894+ BUG();
6895+ return;
6896+ }
6897+
6898+ enable_clocks(1);
6899+ REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
6900+ enable_clocks(0);
6901+}
6902+
6903+void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode)
6904+{
6905+ u32 l;
6906+ int stallmode;
6907+ int gpout0 = 1;
6908+ int gpout1;
6909+
6910+ switch (mode) {
6911+ case OMAP_DSS_PARALLELMODE_BYPASS:
6912+ stallmode = 0;
6913+ gpout1 = 1;
6914+ break;
6915+
6916+ case OMAP_DSS_PARALLELMODE_RFBI:
6917+ stallmode = 1;
6918+ gpout1 = 0;
6919+ break;
6920+
6921+ case OMAP_DSS_PARALLELMODE_DSI:
6922+ stallmode = 1;
6923+ gpout1 = 1;
6924+ break;
6925+
6926+ default:
6927+ BUG();
6928+ return;
6929+ }
6930+
6931+ enable_clocks(1);
6932+
6933+ l = dispc_read_reg(DISPC_CONTROL);
6934+
6935+ l = FLD_MOD(l, stallmode, 11, 11);
6936+ l = FLD_MOD(l, gpout0, 15, 15);
6937+ l = FLD_MOD(l, gpout1, 16, 16);
6938+
6939+ dispc_write_reg(DISPC_CONTROL, l);
6940+
6941+ enable_clocks(0);
6942+}
6943+
6944+static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
6945+ int vsw, int vfp, int vbp)
6946+{
6947+ if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
6948+ if (hsw < 1 || hsw > 64 ||
6949+ hfp < 1 || hfp > 256 ||
6950+ hbp < 1 || hbp > 256 ||
6951+ vsw < 1 || vsw > 64 ||
6952+ vfp < 0 || vfp > 255 ||
6953+ vbp < 0 || vbp > 255)
6954+ return false;
6955+ } else {
6956+ if (hsw < 1 || hsw > 256 ||
6957+ hfp < 1 || hfp > 4096 ||
6958+ hbp < 1 || hbp > 4096 ||
6959+ vsw < 1 || vsw > 256 ||
6960+ vfp < 0 || vfp > 4095 ||
6961+ vbp < 0 || vbp > 4095)
6962+ return false;
6963+ }
6964+
6965+ return true;
6966+}
6967+
6968+bool dispc_lcd_timings_ok(struct omap_video_timings *timings)
6969+{
6970+ return _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
6971+ timings->hbp, timings->vsw,
6972+ timings->vfp, timings->vbp);
6973+}
6974+
6975+static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp,
6976+ int vsw, int vfp, int vbp)
6977+{
6978+ u32 timing_h, timing_v;
6979+
6980+ if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
6981+ timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) |
6982+ FLD_VAL(hbp-1, 27, 20);
6983+
6984+ timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) |
6985+ FLD_VAL(vbp, 27, 20);
6986+ } else {
6987+ timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
6988+ FLD_VAL(hbp-1, 31, 20);
6989+
6990+ timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
6991+ FLD_VAL(vbp, 31, 20);
6992+ }
6993+
6994+ enable_clocks(1);
6995+ dispc_write_reg(DISPC_TIMING_H, timing_h);
6996+ dispc_write_reg(DISPC_TIMING_V, timing_v);
6997+ enable_clocks(0);
6998+}
6999+
7000+/* change name to mode? */
7001+void dispc_set_lcd_timings(struct omap_video_timings *timings)
7002+{
7003+ unsigned xtot, ytot;
7004+ unsigned long ht, vt;
7005+
7006+ if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp,
7007+ timings->hbp, timings->vsw,
7008+ timings->vfp, timings->vbp))
7009+ BUG();
7010+
7011+ _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp,
7012+ timings->vsw, timings->vfp, timings->vbp);
7013+
7014+ dispc_set_lcd_size(timings->x_res, timings->y_res);
7015+
7016+ xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
7017+ ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
7018+
7019+ ht = (timings->pixel_clock * 1000) / xtot;
7020+ vt = (timings->pixel_clock * 1000) / xtot / ytot;
7021+
7022+ DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res);
7023+ DSSDBG("pck %u\n", timings->pixel_clock);
7024+ DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
7025+ timings->hsw, timings->hfp, timings->hbp,
7026+ timings->vsw, timings->vfp, timings->vbp);
7027+
7028+ DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
7029+}
7030+
7031+void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div)
7032+{
7033+ BUG_ON(lck_div < 1);
7034+ BUG_ON(pck_div < 2);
7035+
7036+ enable_clocks(1);
7037+ dispc_write_reg(DISPC_DIVISOR,
7038+ FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
7039+ enable_clocks(0);
7040+}
7041+
7042+static void dispc_get_lcd_divisor(int *lck_div, int *pck_div)
7043+{
7044+ u32 l;
7045+ l = dispc_read_reg(DISPC_DIVISOR);
7046+ *lck_div = FLD_GET(l, 23, 16);
7047+ *pck_div = FLD_GET(l, 7, 0);
7048+}
7049+
7050+unsigned long dispc_fclk_rate(void)
7051+{
7052+ unsigned long r = 0;
7053+
7054+ if (dss_get_dispc_clk_source() == 0)
7055+ r = dss_clk_get_rate(DSS_CLK_FCK1);
7056+ else
7057+#ifdef CONFIG_OMAP2_DSS_DSI
7058+ r = dsi_get_dsi1_pll_rate();
7059+#else
7060+ BUG();
7061+#endif
7062+ return r;
7063+}
7064+
7065+unsigned long dispc_lclk_rate(void)
7066+{
7067+ int lcd;
7068+ unsigned long r;
7069+ u32 l;
7070+
7071+ l = dispc_read_reg(DISPC_DIVISOR);
7072+
7073+ lcd = FLD_GET(l, 23, 16);
7074+
7075+ r = dispc_fclk_rate();
7076+
7077+ return r / lcd;
7078+}
7079+
7080+unsigned long dispc_pclk_rate(void)
7081+{
7082+ int lcd, pcd;
7083+ unsigned long r;
7084+ u32 l;
7085+
7086+ l = dispc_read_reg(DISPC_DIVISOR);
7087+
7088+ lcd = FLD_GET(l, 23, 16);
7089+ pcd = FLD_GET(l, 7, 0);
7090+
7091+ r = dispc_fclk_rate();
7092+
7093+ return r / lcd / pcd;
7094+}
7095+
7096+void dispc_dump_clocks(struct seq_file *s)
7097+{
7098+ int lcd, pcd;
7099+
7100+ enable_clocks(1);
7101+
7102+ dispc_get_lcd_divisor(&lcd, &pcd);
7103+
7104+ seq_printf(s, "- dispc -\n");
7105+
7106+ seq_printf(s, "dispc fclk source = %s\n",
7107+ dss_get_dispc_clk_source() == 0 ?
7108+ "dss1_alwon_fclk" : "dsi1_pll_fclk");
7109+
7110+ seq_printf(s, "pixel clk = %lu / %d / %d = %lu\n",
7111+ dispc_fclk_rate(),
7112+ lcd, pcd,
7113+ dispc_pclk_rate());
7114+
7115+ enable_clocks(0);
7116+}
7117+
7118+void dispc_dump_regs(struct seq_file *s)
7119+{
7120+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r))
7121+
7122+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
7123+
7124+ DUMPREG(DISPC_REVISION);
7125+ DUMPREG(DISPC_SYSCONFIG);
7126+ DUMPREG(DISPC_SYSSTATUS);
7127+ DUMPREG(DISPC_IRQSTATUS);
7128+ DUMPREG(DISPC_IRQENABLE);
7129+ DUMPREG(DISPC_CONTROL);
7130+ DUMPREG(DISPC_CONFIG);
7131+ DUMPREG(DISPC_CAPABLE);
7132+ DUMPREG(DISPC_DEFAULT_COLOR0);
7133+ DUMPREG(DISPC_DEFAULT_COLOR1);
7134+ DUMPREG(DISPC_TRANS_COLOR0);
7135+ DUMPREG(DISPC_TRANS_COLOR1);
7136+ DUMPREG(DISPC_LINE_STATUS);
7137+ DUMPREG(DISPC_LINE_NUMBER);
7138+ DUMPREG(DISPC_TIMING_H);
7139+ DUMPREG(DISPC_TIMING_V);
7140+ DUMPREG(DISPC_POL_FREQ);
7141+ DUMPREG(DISPC_DIVISOR);
7142+ DUMPREG(DISPC_GLOBAL_ALPHA);
7143+ DUMPREG(DISPC_SIZE_DIG);
7144+ DUMPREG(DISPC_SIZE_LCD);
7145+
7146+ DUMPREG(DISPC_GFX_BA0);
7147+ DUMPREG(DISPC_GFX_BA1);
7148+ DUMPREG(DISPC_GFX_POSITION);
7149+ DUMPREG(DISPC_GFX_SIZE);
7150+ DUMPREG(DISPC_GFX_ATTRIBUTES);
7151+ DUMPREG(DISPC_GFX_FIFO_THRESHOLD);
7152+ DUMPREG(DISPC_GFX_FIFO_SIZE_STATUS);
7153+ DUMPREG(DISPC_GFX_ROW_INC);
7154+ DUMPREG(DISPC_GFX_PIXEL_INC);
7155+ DUMPREG(DISPC_GFX_WINDOW_SKIP);
7156+ DUMPREG(DISPC_GFX_TABLE_BA);
7157+
7158+ DUMPREG(DISPC_DATA_CYCLE1);
7159+ DUMPREG(DISPC_DATA_CYCLE2);
7160+ DUMPREG(DISPC_DATA_CYCLE3);
7161+
7162+ DUMPREG(DISPC_CPR_COEF_R);
7163+ DUMPREG(DISPC_CPR_COEF_G);
7164+ DUMPREG(DISPC_CPR_COEF_B);
7165+
7166+ DUMPREG(DISPC_GFX_PRELOAD);
7167+
7168+ DUMPREG(DISPC_VID_BA0(0));
7169+ DUMPREG(DISPC_VID_BA1(0));
7170+ DUMPREG(DISPC_VID_POSITION(0));
7171+ DUMPREG(DISPC_VID_SIZE(0));
7172+ DUMPREG(DISPC_VID_ATTRIBUTES(0));
7173+ DUMPREG(DISPC_VID_FIFO_THRESHOLD(0));
7174+ DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(0));
7175+ DUMPREG(DISPC_VID_ROW_INC(0));
7176+ DUMPREG(DISPC_VID_PIXEL_INC(0));
7177+ DUMPREG(DISPC_VID_FIR(0));
7178+ DUMPREG(DISPC_VID_PICTURE_SIZE(0));
7179+ DUMPREG(DISPC_VID_ACCU0(0));
7180+ DUMPREG(DISPC_VID_ACCU1(0));
7181+
7182+ DUMPREG(DISPC_VID_BA0(1));
7183+ DUMPREG(DISPC_VID_BA1(1));
7184+ DUMPREG(DISPC_VID_POSITION(1));
7185+ DUMPREG(DISPC_VID_SIZE(1));
7186+ DUMPREG(DISPC_VID_ATTRIBUTES(1));
7187+ DUMPREG(DISPC_VID_FIFO_THRESHOLD(1));
7188+ DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1));
7189+ DUMPREG(DISPC_VID_ROW_INC(1));
7190+ DUMPREG(DISPC_VID_PIXEL_INC(1));
7191+ DUMPREG(DISPC_VID_FIR(1));
7192+ DUMPREG(DISPC_VID_PICTURE_SIZE(1));
7193+ DUMPREG(DISPC_VID_ACCU0(1));
7194+ DUMPREG(DISPC_VID_ACCU1(1));
7195+
7196+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 0));
7197+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 1));
7198+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 2));
7199+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 3));
7200+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 4));
7201+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 5));
7202+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 6));
7203+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 7));
7204+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 0));
7205+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 1));
7206+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 2));
7207+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 3));
7208+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 4));
7209+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 5));
7210+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 6));
7211+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 7));
7212+ DUMPREG(DISPC_VID_CONV_COEF(0, 0));
7213+ DUMPREG(DISPC_VID_CONV_COEF(0, 1));
7214+ DUMPREG(DISPC_VID_CONV_COEF(0, 2));
7215+ DUMPREG(DISPC_VID_CONV_COEF(0, 3));
7216+ DUMPREG(DISPC_VID_CONV_COEF(0, 4));
7217+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 0));
7218+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 1));
7219+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 2));
7220+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 3));
7221+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 4));
7222+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 5));
7223+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 6));
7224+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 7));
7225+
7226+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 0));
7227+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 1));
7228+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 2));
7229+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 3));
7230+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 4));
7231+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 5));
7232+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 6));
7233+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 7));
7234+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 0));
7235+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 1));
7236+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 2));
7237+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 3));
7238+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 4));
7239+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 5));
7240+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 6));
7241+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 7));
7242+ DUMPREG(DISPC_VID_CONV_COEF(1, 0));
7243+ DUMPREG(DISPC_VID_CONV_COEF(1, 1));
7244+ DUMPREG(DISPC_VID_CONV_COEF(1, 2));
7245+ DUMPREG(DISPC_VID_CONV_COEF(1, 3));
7246+ DUMPREG(DISPC_VID_CONV_COEF(1, 4));
7247+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 0));
7248+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 1));
7249+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 2));
7250+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 3));
7251+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 4));
7252+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 5));
7253+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 6));
7254+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 7));
7255+
7256+ DUMPREG(DISPC_VID_PRELOAD(0));
7257+ DUMPREG(DISPC_VID_PRELOAD(1));
7258+
7259+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
7260+#undef DUMPREG
7261+}
7262+
7263+static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc,
7264+ bool ihs, bool ivs, u8 acbi, u8 acb)
7265+{
7266+ u32 l = 0;
7267+
7268+ DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n",
7269+ onoff, rf, ieo, ipc, ihs, ivs, acbi, acb);
7270+
7271+ l |= FLD_VAL(onoff, 17, 17);
7272+ l |= FLD_VAL(rf, 16, 16);
7273+ l |= FLD_VAL(ieo, 15, 15);
7274+ l |= FLD_VAL(ipc, 14, 14);
7275+ l |= FLD_VAL(ihs, 13, 13);
7276+ l |= FLD_VAL(ivs, 12, 12);
7277+ l |= FLD_VAL(acbi, 11, 8);
7278+ l |= FLD_VAL(acb, 7, 0);
7279+
7280+ enable_clocks(1);
7281+ dispc_write_reg(DISPC_POL_FREQ, l);
7282+ enable_clocks(0);
7283+}
7284+
7285+void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb)
7286+{
7287+ _dispc_set_pol_freq((config & OMAP_DSS_LCD_ONOFF) != 0,
7288+ (config & OMAP_DSS_LCD_RF) != 0,
7289+ (config & OMAP_DSS_LCD_IEO) != 0,
7290+ (config & OMAP_DSS_LCD_IPC) != 0,
7291+ (config & OMAP_DSS_LCD_IHS) != 0,
7292+ (config & OMAP_DSS_LCD_IVS) != 0,
7293+ acbi, acb);
7294+}
7295+
7296+void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
7297+ u16 *lck_div, u16 *pck_div)
7298+{
7299+ u16 pcd_min = is_tft ? 2 : 3;
7300+ unsigned long best_pck;
7301+ u16 best_ld, cur_ld;
7302+ u16 best_pd, cur_pd;
7303+
7304+ best_pck = 0;
7305+ best_ld = 0;
7306+ best_pd = 0;
7307+
7308+ for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
7309+ unsigned long lck = fck / cur_ld;
7310+
7311+ for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) {
7312+ unsigned long pck = lck / cur_pd;
7313+ long old_delta = abs(best_pck - req_pck);
7314+ long new_delta = abs(pck - req_pck);
7315+
7316+ if (best_pck == 0 || new_delta < old_delta) {
7317+ best_pck = pck;
7318+ best_ld = cur_ld;
7319+ best_pd = cur_pd;
7320+
7321+ if (pck == req_pck)
7322+ goto found;
7323+ }
7324+
7325+ if (pck < req_pck)
7326+ break;
7327+ }
7328+
7329+ if (lck / pcd_min < req_pck)
7330+ break;
7331+ }
7332+
7333+found:
7334+ *lck_div = best_ld;
7335+ *pck_div = best_pd;
7336+}
7337+
7338+int dispc_calc_clock_div(bool is_tft, unsigned long req_pck,
7339+ struct dispc_clock_info *cinfo)
7340+{
7341+ unsigned long prate;
7342+ struct dispc_clock_info cur, best;
7343+ int match = 0;
7344+ int min_fck_per_pck;
7345+ unsigned long fck_rate = dss_clk_get_rate(DSS_CLK_FCK1);
7346+
7347+ if (cpu_is_omap34xx())
7348+ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
7349+ else
7350+ prate = 0;
7351+
7352+ if (req_pck == dispc.cache_req_pck &&
7353+ ((cpu_is_omap34xx() && prate == dispc.cache_prate) ||
7354+ dispc.cache_cinfo.fck == fck_rate)) {
7355+ DSSDBG("dispc clock info found from cache.\n");
7356+ *cinfo = dispc.cache_cinfo;
7357+ return 0;
7358+ }
7359+
7360+ min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
7361+
7362+ if (min_fck_per_pck &&
7363+ req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
7364+ DSSERR("Requested pixel clock not possible with the current "
7365+ "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
7366+ "the constraint off.\n");
7367+ min_fck_per_pck = 0;
7368+ }
7369+
7370+retry:
7371+ memset(&cur, 0, sizeof(cur));
7372+ memset(&best, 0, sizeof(best));
7373+
7374+ if (cpu_is_omap24xx()) {
7375+ /* XXX can we change the clock on omap2? */
7376+ cur.fck = dss_clk_get_rate(DSS_CLK_FCK1);
7377+ cur.fck_div = 1;
7378+
7379+ match = 1;
7380+
7381+ find_lck_pck_divs(is_tft, req_pck, cur.fck,
7382+ &cur.lck_div, &cur.pck_div);
7383+
7384+ cur.lck = cur.fck / cur.lck_div;
7385+ cur.pck = cur.lck / cur.pck_div;
7386+
7387+ best = cur;
7388+
7389+ goto found;
7390+ } else if (cpu_is_omap34xx()) {
7391+ for (cur.fck_div = 16; cur.fck_div > 0; --cur.fck_div) {
7392+ cur.fck = prate / cur.fck_div * 2;
7393+
7394+ if (cur.fck > DISPC_MAX_FCK)
7395+ continue;
7396+
7397+ if (min_fck_per_pck &&
7398+ cur.fck < req_pck * min_fck_per_pck)
7399+ continue;
7400+
7401+ match = 1;
7402+
7403+ find_lck_pck_divs(is_tft, req_pck, cur.fck,
7404+ &cur.lck_div, &cur.pck_div);
7405+
7406+ cur.lck = cur.fck / cur.lck_div;
7407+ cur.pck = cur.lck / cur.pck_div;
7408+
7409+ if (abs(cur.pck - req_pck) < abs(best.pck - req_pck)) {
7410+ best = cur;
7411+
7412+ if (cur.pck == req_pck)
7413+ goto found;
7414+ }
7415+ }
7416+ } else {
7417+ BUG();
7418+ }
7419+
7420+found:
7421+ if (!match) {
7422+ if (min_fck_per_pck) {
7423+ DSSERR("Could not find suitable clock settings.\n"
7424+ "Turning FCK/PCK constraint off and"
7425+ "trying again.\n");
7426+ min_fck_per_pck = 0;
7427+ goto retry;
7428+ }
7429+
7430+ DSSERR("Could not find suitable clock settings.\n");
7431+
7432+ return -EINVAL;
7433+ }
7434+
7435+ if (cinfo)
7436+ *cinfo = best;
7437+
7438+ dispc.cache_req_pck = req_pck;
7439+ dispc.cache_prate = prate;
7440+ dispc.cache_cinfo = best;
7441+
7442+ return 0;
7443+}
7444+
7445+int dispc_set_clock_div(struct dispc_clock_info *cinfo)
7446+{
7447+ unsigned long prate;
7448+ int r;
7449+
7450+ if (cpu_is_omap34xx()) {
7451+ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
7452+ DSSDBG("dpll4_m4 = %ld\n", prate);
7453+ }
7454+
7455+ DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
7456+ DSSDBG("lck = %ld (%d)\n", cinfo->lck, cinfo->lck_div);
7457+ DSSDBG("pck = %ld (%d)\n", cinfo->pck, cinfo->pck_div);
7458+
7459+ if (cpu_is_omap34xx()) {
7460+ r = clk_set_rate(dispc.dpll4_m4_ck, prate / cinfo->fck_div);
7461+ if (r)
7462+ return r;
7463+ }
7464+
7465+ dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div);
7466+
7467+ return 0;
7468+}
7469+
7470+int dispc_get_clock_div(struct dispc_clock_info *cinfo)
7471+{
7472+ cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1);
7473+
7474+ if (cpu_is_omap34xx()) {
7475+ unsigned long prate;
7476+ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
7477+ cinfo->fck_div = prate / (cinfo->fck / 2);
7478+ } else {
7479+ cinfo->fck_div = 0;
7480+ }
7481+
7482+ cinfo->lck_div = REG_GET(DISPC_DIVISOR, 23, 16);
7483+ cinfo->pck_div = REG_GET(DISPC_DIVISOR, 7, 0);
7484+
7485+ cinfo->lck = cinfo->fck / cinfo->lck_div;
7486+ cinfo->pck = cinfo->lck / cinfo->pck_div;
7487+
7488+ return 0;
7489+}
7490+
7491+/* dispc.irq_lock has to be locked by the caller */
7492+static void _omap_dispc_set_irqs(void)
7493+{
7494+ u32 mask;
7495+ u32 old_mask;
7496+ int i;
7497+ struct omap_dispc_isr_data *isr_data;
7498+
7499+ mask = dispc.irq_error_mask;
7500+
7501+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
7502+ isr_data = &dispc.registered_isr[i];
7503+
7504+ if (isr_data->isr == NULL)
7505+ continue;
7506+
7507+ mask |= isr_data->mask;
7508+ }
7509+
7510+ enable_clocks(1);
7511+
7512+ old_mask = dispc_read_reg(DISPC_IRQENABLE);
7513+ /* clear the irqstatus for newly enabled irqs */
7514+ dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
7515+
7516+ dispc_write_reg(DISPC_IRQENABLE, mask);
7517+
7518+ enable_clocks(0);
7519+}
7520+
7521+int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
7522+{
7523+ int i;
7524+ int ret;
7525+ unsigned long flags;
7526+ struct omap_dispc_isr_data *isr_data;
7527+
7528+ if (isr == NULL)
7529+ return -EINVAL;
7530+
7531+ spin_lock_irqsave(&dispc.irq_lock, flags);
7532+
7533+ /* check for duplicate entry */
7534+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
7535+ isr_data = &dispc.registered_isr[i];
7536+ if (isr_data->isr == isr && isr_data->arg == arg &&
7537+ isr_data->mask == mask) {
7538+ ret = -EINVAL;
7539+ goto err;
7540+ }
7541+ }
7542+
7543+ isr_data = NULL;
7544+ ret = -EBUSY;
7545+
7546+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
7547+ isr_data = &dispc.registered_isr[i];
7548+
7549+ if (isr_data->isr != NULL)
7550+ continue;
7551+
7552+ isr_data->isr = isr;
7553+ isr_data->arg = arg;
7554+ isr_data->mask = mask;
7555+ ret = 0;
7556+
7557+ break;
7558+ }
7559+
7560+ _omap_dispc_set_irqs();
7561+
7562+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
7563+
7564+ return 0;
7565+err:
7566+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
7567+
7568+ return ret;
7569+}
7570+EXPORT_SYMBOL(omap_dispc_register_isr);
7571+
7572+int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
7573+{
7574+ int i;
7575+ unsigned long flags;
7576+ int ret = -EINVAL;
7577+ struct omap_dispc_isr_data *isr_data;
7578+
7579+ spin_lock_irqsave(&dispc.irq_lock, flags);
7580+
7581+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
7582+ isr_data = &dispc.registered_isr[i];
7583+ if (isr_data->isr != isr || isr_data->arg != arg ||
7584+ isr_data->mask != mask)
7585+ continue;
7586+
7587+ /* found the correct isr */
7588+
7589+ isr_data->isr = NULL;
7590+ isr_data->arg = NULL;
7591+ isr_data->mask = 0;
7592+
7593+ ret = 0;
7594+ break;
7595+ }
7596+
7597+ if (ret == 0)
7598+ _omap_dispc_set_irqs();
7599+
7600+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
7601+
7602+ return ret;
7603+}
7604+EXPORT_SYMBOL(omap_dispc_unregister_isr);
7605+
7606+#ifdef DEBUG
7607+static void print_irq_status(u32 status)
7608+{
7609+ if ((status & dispc.irq_error_mask) == 0)
7610+ return;
7611+
7612+ printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status);
7613+
7614+#define PIS(x) \
7615+ if (status & DISPC_IRQ_##x) \
7616+ printk(#x " ");
7617+ PIS(GFX_FIFO_UNDERFLOW);
7618+ PIS(OCP_ERR);
7619+ PIS(VID1_FIFO_UNDERFLOW);
7620+ PIS(VID2_FIFO_UNDERFLOW);
7621+ PIS(SYNC_LOST);
7622+ PIS(SYNC_LOST_DIGIT);
7623+#undef PIS
7624+
7625+ printk("\n");
7626+}
7627+#endif
7628+
7629+/* Called from dss.c. Note that we don't touch clocks here,
7630+ * but we presume they are on because we got an IRQ. However,
7631+ * an irq handler may turn the clocks off, so we may not have
7632+ * clock later in the function. */
7633+void dispc_irq_handler(void)
7634+{
7635+ int i;
7636+ u32 irqstatus;
7637+ u32 handledirqs = 0;
7638+ u32 unhandled_errors;
7639+ struct omap_dispc_isr_data *isr_data;
7640+ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
7641+
7642+ spin_lock(&dispc.irq_lock);
7643+
7644+ irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
7645+
7646+#ifdef DEBUG
7647+ if (dss_debug)
7648+ print_irq_status(irqstatus);
7649+#endif
7650+ /* Ack the interrupt. Do it here before clocks are possibly turned
7651+ * off */
7652+ dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
7653+
7654+ /* make a copy and unlock, so that isrs can unregister
7655+ * themselves */
7656+ memcpy(registered_isr, dispc.registered_isr,
7657+ sizeof(registered_isr));
7658+
7659+ spin_unlock(&dispc.irq_lock);
7660+
7661+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
7662+ isr_data = &registered_isr[i];
7663+
7664+ if (!isr_data->isr)
7665+ continue;
7666+
7667+ if (isr_data->mask & irqstatus) {
7668+ isr_data->isr(isr_data->arg, irqstatus);
7669+ handledirqs |= isr_data->mask;
7670+ }
7671+ }
7672+
7673+ spin_lock(&dispc.irq_lock);
7674+
7675+ unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
7676+
7677+ if (unhandled_errors) {
7678+ dispc.error_irqs |= unhandled_errors;
7679+
7680+ dispc.irq_error_mask &= ~unhandled_errors;
7681+ _omap_dispc_set_irqs();
7682+
7683+ schedule_work(&dispc.error_work);
7684+ }
7685+
7686+ spin_unlock(&dispc.irq_lock);
7687+}
7688+
7689+static void dispc_error_worker(struct work_struct *work)
7690+{
7691+ int i;
7692+ u32 errors;
7693+ unsigned long flags;
7694+
7695+ spin_lock_irqsave(&dispc.irq_lock, flags);
7696+ errors = dispc.error_irqs;
7697+ dispc.error_irqs = 0;
7698+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
7699+
7700+ if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) {
7701+ DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n");
7702+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
7703+ struct omap_overlay *ovl;
7704+ ovl = omap_dss_get_overlay(i);
7705+
7706+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
7707+ continue;
7708+
7709+ if (ovl->id == 0) {
7710+ dispc_enable_plane(ovl->id, 0);
7711+ dispc_go(ovl->manager->id);
7712+ mdelay(50);
7713+ break;
7714+ }
7715+ }
7716+ }
7717+
7718+ if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) {
7719+ DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n");
7720+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
7721+ struct omap_overlay *ovl;
7722+ ovl = omap_dss_get_overlay(i);
7723+
7724+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
7725+ continue;
7726+
7727+ if (ovl->id == 1) {
7728+ dispc_enable_plane(ovl->id, 0);
7729+ dispc_go(ovl->manager->id);
7730+ mdelay(50);
7731+ break;
7732+ }
7733+ }
7734+ }
7735+
7736+ if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) {
7737+ DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n");
7738+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
7739+ struct omap_overlay *ovl;
7740+ ovl = omap_dss_get_overlay(i);
7741+
7742+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
7743+ continue;
7744+
7745+ if (ovl->id == 2) {
7746+ dispc_enable_plane(ovl->id, 0);
7747+ dispc_go(ovl->manager->id);
7748+ mdelay(50);
7749+ break;
7750+ }
7751+ }
7752+ }
7753+
7754+ if (errors & DISPC_IRQ_SYNC_LOST) {
7755+ struct omap_overlay_manager *manager = NULL;
7756+ bool enable = false;
7757+
7758+ DSSERR("SYNC_LOST, disabling LCD\n");
7759+
7760+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
7761+ struct omap_overlay_manager *mgr;
7762+ mgr = omap_dss_get_overlay_manager(i);
7763+
7764+ if (mgr->id == OMAP_DSS_CHANNEL_LCD) {
7765+ manager = mgr;
7766+ enable = mgr->device->state ==
7767+ OMAP_DSS_DISPLAY_ACTIVE;
7768+ mgr->device->disable(mgr->device);
7769+ break;
7770+ }
7771+ }
7772+
7773+ if (manager) {
7774+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
7775+ struct omap_overlay *ovl;
7776+ ovl = omap_dss_get_overlay(i);
7777+
7778+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
7779+ continue;
7780+
7781+ if (ovl->id != 0 && ovl->manager == manager)
7782+ dispc_enable_plane(ovl->id, 0);
7783+ }
7784+
7785+ dispc_go(manager->id);
7786+ mdelay(50);
7787+ if (enable)
7788+ manager->device->enable(manager->device);
7789+ }
7790+ }
7791+
7792+ if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) {
7793+ struct omap_overlay_manager *manager = NULL;
7794+ bool enable = false;
7795+
7796+ DSSERR("SYNC_LOST_DIGIT, disabling TV\n");
7797+
7798+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
7799+ struct omap_overlay_manager *mgr;
7800+ mgr = omap_dss_get_overlay_manager(i);
7801+
7802+ if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) {
7803+ manager = mgr;
7804+ enable = mgr->device->state ==
7805+ OMAP_DSS_DISPLAY_ACTIVE;
7806+ mgr->device->disable(mgr->device);
7807+ break;
7808+ }
7809+ }
7810+
7811+ if (manager) {
7812+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
7813+ struct omap_overlay *ovl;
7814+ ovl = omap_dss_get_overlay(i);
7815+
7816+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
7817+ continue;
7818+
7819+ if (ovl->id != 0 && ovl->manager == manager)
7820+ dispc_enable_plane(ovl->id, 0);
7821+ }
7822+
7823+ dispc_go(manager->id);
7824+ mdelay(50);
7825+ if (enable)
7826+ manager->device->enable(manager->device);
7827+ }
7828+ }
7829+
7830+ if (errors & DISPC_IRQ_OCP_ERR) {
7831+ DSSERR("OCP_ERR\n");
7832+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
7833+ struct omap_overlay_manager *mgr;
7834+ mgr = omap_dss_get_overlay_manager(i);
7835+
7836+ if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC)
7837+ mgr->device->disable(mgr->device);
7838+ }
7839+ }
7840+
7841+ spin_lock_irqsave(&dispc.irq_lock, flags);
7842+ dispc.irq_error_mask |= errors;
7843+ _omap_dispc_set_irqs();
7844+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
7845+}
7846+
7847+int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
7848+{
7849+ void dispc_irq_wait_handler(void *data, u32 mask)
7850+ {
7851+ complete((struct completion *)data);
7852+ }
7853+
7854+ int r;
7855+ DECLARE_COMPLETION_ONSTACK(completion);
7856+
7857+ r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
7858+ irqmask);
7859+
7860+ if (r)
7861+ return r;
7862+
7863+ timeout = wait_for_completion_timeout(&completion, timeout);
7864+
7865+ omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
7866+
7867+ if (timeout == 0)
7868+ return -ETIMEDOUT;
7869+
7870+ if (timeout == -ERESTARTSYS)
7871+ return -ERESTARTSYS;
7872+
7873+ return 0;
7874+}
7875+
7876+int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
7877+ unsigned long timeout)
7878+{
7879+ void dispc_irq_wait_handler(void *data, u32 mask)
7880+ {
7881+ complete((struct completion *)data);
7882+ }
7883+
7884+ int r;
7885+ DECLARE_COMPLETION_ONSTACK(completion);
7886+
7887+ r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
7888+ irqmask);
7889+
7890+ if (r)
7891+ return r;
7892+
7893+ timeout = wait_for_completion_interruptible_timeout(&completion,
7894+ timeout);
7895+
7896+ omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
7897+
7898+ if (timeout == 0)
7899+ return -ETIMEDOUT;
7900+
7901+ if (timeout == -ERESTARTSYS)
7902+ return -ERESTARTSYS;
7903+
7904+ return 0;
7905+}
7906+
7907+#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
7908+void dispc_fake_vsync_irq(void)
7909+{
7910+ u32 irqstatus = DISPC_IRQ_VSYNC;
7911+ int i;
7912+
7913+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
7914+ struct omap_dispc_isr_data *isr_data;
7915+ isr_data = &dispc.registered_isr[i];
7916+
7917+ if (!isr_data->isr)
7918+ continue;
7919+
7920+ if (isr_data->mask & irqstatus)
7921+ isr_data->isr(isr_data->arg, irqstatus);
7922+ }
7923+}
7924+#endif
7925+
7926+static void _omap_dispc_initialize_irq(void)
7927+{
7928+ unsigned long flags;
7929+
7930+ spin_lock_irqsave(&dispc.irq_lock, flags);
7931+
7932+ memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
7933+
7934+ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
7935+
7936+ /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
7937+ * so clear it */
7938+ dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
7939+
7940+ _omap_dispc_set_irqs();
7941+
7942+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
7943+}
7944+
7945+void dispc_enable_sidle(void)
7946+{
7947+ REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3); /* SIDLEMODE: smart idle */
7948+}
7949+
7950+void dispc_disable_sidle(void)
7951+{
7952+ REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */
7953+}
7954+
7955+static void _omap_dispc_initial_config(void)
7956+{
7957+ u32 l;
7958+
7959+ l = dispc_read_reg(DISPC_SYSCONFIG);
7960+ l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */
7961+ l = FLD_MOD(l, 2, 4, 3); /* SIDLEMODE: smart idle */
7962+ l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */
7963+ l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */
7964+ dispc_write_reg(DISPC_SYSCONFIG, l);
7965+
7966+ /* FUNCGATED */
7967+ REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
7968+
7969+ /* L3 firewall setting: enable access to OCM RAM */
7970+ if (cpu_is_omap24xx())
7971+ __raw_writel(0x402000b0, OMAP2_IO_ADDRESS(0x680050a0));
7972+
7973+ _dispc_setup_color_conv_coef();
7974+
7975+ dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
7976+
7977+ dispc_read_plane_fifo_sizes();
7978+}
7979+
7980+int dispc_init(void)
7981+{
7982+ u32 rev;
7983+
7984+ spin_lock_init(&dispc.irq_lock);
7985+
7986+ INIT_WORK(&dispc.error_work, dispc_error_worker);
7987+
7988+ dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS);
7989+ if (!dispc.base) {
7990+ DSSERR("can't ioremap DISPC\n");
7991+ return -ENOMEM;
7992+ }
7993+
7994+ if (cpu_is_omap34xx()) {
7995+ dispc.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
7996+ if (IS_ERR(dispc.dpll4_m4_ck)) {
7997+ DSSERR("Failed to get dpll4_m4_ck\n");
7998+ return -ENODEV;
7999+ }
8000+ }
8001+
8002+ enable_clocks(1);
8003+
8004+ _omap_dispc_initial_config();
8005+
8006+ _omap_dispc_initialize_irq();
8007+
8008+ dispc_save_context();
8009+
8010+ rev = dispc_read_reg(DISPC_REVISION);
8011+ printk(KERN_INFO "OMAP DISPC rev %d.%d\n",
8012+ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
8013+
8014+ enable_clocks(0);
8015+
8016+ return 0;
8017+}
8018+
8019+void dispc_exit(void)
8020+{
8021+ if (cpu_is_omap34xx())
8022+ clk_put(dispc.dpll4_m4_ck);
8023+ iounmap(dispc.base);
8024+}
8025+
8026+int dispc_enable_plane(enum omap_plane plane, bool enable)
8027+{
8028+ DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
8029+
8030+ enable_clocks(1);
8031+ _dispc_enable_plane(plane, enable);
8032+ enable_clocks(0);
8033+
8034+ return 0;
8035+}
8036+
8037+int dispc_setup_plane(enum omap_plane plane,
8038+ u32 paddr, u16 screen_width,
8039+ u16 pos_x, u16 pos_y,
8040+ u16 width, u16 height,
8041+ u16 out_width, u16 out_height,
8042+ enum omap_color_mode color_mode,
8043+ bool ilace,
8044+ enum omap_dss_rotation_type rotation_type,
8045+ u8 rotation, bool mirror, u8 global_alpha)
8046+{
8047+ int r = 0;
8048+
8049+ DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
8050+ "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n",
8051+ plane, paddr, screen_width, pos_x, pos_y,
8052+ width, height,
8053+ out_width, out_height,
8054+ ilace, color_mode,
8055+ rotation, mirror);
8056+
8057+ enable_clocks(1);
8058+
8059+ r = _dispc_setup_plane(plane,
8060+ paddr, screen_width,
8061+ pos_x, pos_y,
8062+ width, height,
8063+ out_width, out_height,
8064+ color_mode, ilace,
8065+ rotation_type,
8066+ rotation, mirror,
8067+ global_alpha);
8068+
8069+ enable_clocks(0);
8070+
8071+ return r;
8072+}
8073--- /dev/null
8074+++ b/drivers/video/omap2/dss/display.c
8075@@ -0,0 +1,658 @@
8076+/*
8077+ * linux/drivers/video/omap2/dss/display.c
8078+ *
8079+ * Copyright (C) 2009 Nokia Corporation
8080+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
8081+ *
8082+ * Some code and ideas taken from drivers/video/omap/ driver
8083+ * by Imre Deak.
8084+ *
8085+ * This program is free software; you can redistribute it and/or modify it
8086+ * under the terms of the GNU General Public License version 2 as published by
8087+ * the Free Software Foundation.
8088+ *
8089+ * This program is distributed in the hope that it will be useful, but WITHOUT
8090+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8091+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
8092+ * more details.
8093+ *
8094+ * You should have received a copy of the GNU General Public License along with
8095+ * this program. If not, see <http://www.gnu.org/licenses/>.
8096+ */
8097+
8098+#define DSS_SUBSYS_NAME "DISPLAY"
8099+
8100+#include <linux/kernel.h>
8101+#include <linux/module.h>
8102+#include <linux/jiffies.h>
8103+#include <linux/list.h>
8104+#include <linux/platform_device.h>
8105+
8106+#include <mach/display.h>
8107+#include "dss.h"
8108+
8109+static LIST_HEAD(display_list);
8110+
8111+static ssize_t display_enabled_show(struct device *dev,
8112+ struct device_attribute *attr, char *buf)
8113+{
8114+ struct omap_dss_device *dssdev = to_dss_device(dev);
8115+ bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
8116+
8117+ return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
8118+}
8119+
8120+static ssize_t display_enabled_store(struct device *dev,
8121+ struct device_attribute *attr,
8122+ const char *buf, size_t size)
8123+{
8124+ struct omap_dss_device *dssdev = to_dss_device(dev);
8125+ bool enabled, r;
8126+
8127+ enabled = simple_strtoul(buf, NULL, 10);
8128+
8129+ if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
8130+ if (enabled) {
8131+ r = dssdev->enable(dssdev);
8132+ if (r)
8133+ return r;
8134+ } else {
8135+ dssdev->disable(dssdev);
8136+ }
8137+ }
8138+
8139+ return size;
8140+}
8141+
8142+static ssize_t display_upd_mode_show(struct device *dev,
8143+ struct device_attribute *attr, char *buf)
8144+{
8145+ struct omap_dss_device *dssdev = to_dss_device(dev);
8146+ enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO;
8147+ if (dssdev->get_update_mode)
8148+ mode = dssdev->get_update_mode(dssdev);
8149+ return snprintf(buf, PAGE_SIZE, "%d\n", mode);
8150+}
8151+
8152+static ssize_t display_upd_mode_store(struct device *dev,
8153+ struct device_attribute *attr,
8154+ const char *buf, size_t size)
8155+{
8156+ struct omap_dss_device *dssdev = to_dss_device(dev);
8157+ int val, r;
8158+ enum omap_dss_update_mode mode;
8159+
8160+ val = simple_strtoul(buf, NULL, 10);
8161+
8162+ switch (val) {
8163+ case OMAP_DSS_UPDATE_DISABLED:
8164+ case OMAP_DSS_UPDATE_AUTO:
8165+ case OMAP_DSS_UPDATE_MANUAL:
8166+ mode = (enum omap_dss_update_mode)val;
8167+ break;
8168+ default:
8169+ return -EINVAL;
8170+ }
8171+
8172+ r = dssdev->set_update_mode(dssdev, mode);
8173+ if (r)
8174+ return r;
8175+
8176+ return size;
8177+}
8178+
8179+static ssize_t display_tear_show(struct device *dev,
8180+ struct device_attribute *attr, char *buf)
8181+{
8182+ struct omap_dss_device *dssdev = to_dss_device(dev);
8183+ return snprintf(buf, PAGE_SIZE, "%d\n",
8184+ dssdev->get_te ? dssdev->get_te(dssdev) : 0);
8185+}
8186+
8187+static ssize_t display_tear_store(struct device *dev,
8188+ struct device_attribute *attr, const char *buf, size_t size)
8189+{
8190+ struct omap_dss_device *dssdev = to_dss_device(dev);
8191+ unsigned long te;
8192+ int r;
8193+
8194+ if (!dssdev->enable_te || !dssdev->get_te)
8195+ return -ENOENT;
8196+
8197+ te = simple_strtoul(buf, NULL, 0);
8198+
8199+ r = dssdev->enable_te(dssdev, te);
8200+ if (r)
8201+ return r;
8202+
8203+ return size;
8204+}
8205+
8206+static ssize_t display_timings_show(struct device *dev,
8207+ struct device_attribute *attr, char *buf)
8208+{
8209+ struct omap_dss_device *dssdev = to_dss_device(dev);
8210+ struct omap_video_timings t;
8211+
8212+ if (!dssdev->get_timings)
8213+ return -ENOENT;
8214+
8215+ dssdev->get_timings(dssdev, &t);
8216+
8217+ return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
8218+ t.pixel_clock,
8219+ t.x_res, t.hfp, t.hbp, t.hsw,
8220+ t.y_res, t.vfp, t.vbp, t.vsw);
8221+}
8222+
8223+static ssize_t display_timings_store(struct device *dev,
8224+ struct device_attribute *attr, const char *buf, size_t size)
8225+{
8226+ struct omap_dss_device *dssdev = to_dss_device(dev);
8227+ struct omap_video_timings t;
8228+ int r, found;
8229+
8230+ if (!dssdev->set_timings || !dssdev->check_timings)
8231+ return -ENOENT;
8232+
8233+ found = 0;
8234+#ifdef CONFIG_OMAP2_DSS_VENC
8235+ if (strncmp("pal", buf, 3) == 0) {
8236+ t = omap_dss_pal_timings;
8237+ found = 1;
8238+ } else if (strncmp("ntsc", buf, 4) == 0) {
8239+ t = omap_dss_ntsc_timings;
8240+ found = 1;
8241+ }
8242+#endif
8243+ if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
8244+ &t.pixel_clock,
8245+ &t.x_res, &t.hfp, &t.hbp, &t.hsw,
8246+ &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
8247+ return -EINVAL;
8248+
8249+ r = dssdev->check_timings(dssdev, &t);
8250+ if (r)
8251+ return r;
8252+
8253+ dssdev->set_timings(dssdev, &t);
8254+
8255+ return size;
8256+}
8257+
8258+static ssize_t display_rotate_show(struct device *dev,
8259+ struct device_attribute *attr, char *buf)
8260+{
8261+ struct omap_dss_device *dssdev = to_dss_device(dev);
8262+ int rotate;
8263+ if (!dssdev->get_rotate)
8264+ return -ENOENT;
8265+ rotate = dssdev->get_rotate(dssdev);
8266+ return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
8267+}
8268+
8269+static ssize_t display_rotate_store(struct device *dev,
8270+ struct device_attribute *attr, const char *buf, size_t size)
8271+{
8272+ struct omap_dss_device *dssdev = to_dss_device(dev);
8273+ unsigned long rot;
8274+ int r;
8275+
8276+ if (!dssdev->set_rotate || !dssdev->get_rotate)
8277+ return -ENOENT;
8278+
8279+ rot = simple_strtoul(buf, NULL, 0);
8280+
8281+ r = dssdev->set_rotate(dssdev, rot);
8282+ if (r)
8283+ return r;
8284+
8285+ return size;
8286+}
8287+
8288+static ssize_t display_mirror_show(struct device *dev,
8289+ struct device_attribute *attr, char *buf)
8290+{
8291+ struct omap_dss_device *dssdev = to_dss_device(dev);
8292+ int mirror;
8293+ if (!dssdev->get_mirror)
8294+ return -ENOENT;
8295+ mirror = dssdev->get_mirror(dssdev);
8296+ return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
8297+}
8298+
8299+static ssize_t display_mirror_store(struct device *dev,
8300+ struct device_attribute *attr, const char *buf, size_t size)
8301+{
8302+ struct omap_dss_device *dssdev = to_dss_device(dev);
8303+ unsigned long mirror;
8304+ int r;
8305+
8306+ if (!dssdev->set_mirror || !dssdev->get_mirror)
8307+ return -ENOENT;
8308+
8309+ mirror = simple_strtoul(buf, NULL, 0);
8310+
8311+ r = dssdev->set_mirror(dssdev, mirror);
8312+ if (r)
8313+ return r;
8314+
8315+ return size;
8316+}
8317+
8318+static ssize_t display_wss_show(struct device *dev,
8319+ struct device_attribute *attr, char *buf)
8320+{
8321+ struct omap_dss_device *dssdev = to_dss_device(dev);
8322+ unsigned int wss;
8323+
8324+ if (!dssdev->get_wss)
8325+ return -ENOENT;
8326+
8327+ wss = dssdev->get_wss(dssdev);
8328+
8329+ return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
8330+}
8331+
8332+static ssize_t display_wss_store(struct device *dev,
8333+ struct device_attribute *attr, const char *buf, size_t size)
8334+{
8335+ struct omap_dss_device *dssdev = to_dss_device(dev);
8336+ unsigned long wss;
8337+ int r;
8338+
8339+ if (!dssdev->get_wss || !dssdev->set_wss)
8340+ return -ENOENT;
8341+
8342+ if (strict_strtoul(buf, 0, &wss))
8343+ return -EINVAL;
8344+
8345+ if (wss > 0xfffff)
8346+ return -EINVAL;
8347+
8348+ r = dssdev->set_wss(dssdev, wss);
8349+ if (r)
8350+ return r;
8351+
8352+ return size;
8353+}
8354+
8355+static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
8356+ display_enabled_show, display_enabled_store);
8357+static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR,
8358+ display_upd_mode_show, display_upd_mode_store);
8359+static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
8360+ display_tear_show, display_tear_store);
8361+static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
8362+ display_timings_show, display_timings_store);
8363+static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
8364+ display_rotate_show, display_rotate_store);
8365+static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
8366+ display_mirror_show, display_mirror_store);
8367+static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
8368+ display_wss_show, display_wss_store);
8369+
8370+static struct device_attribute *display_sysfs_attrs[] = {
8371+ &dev_attr_enabled,
8372+ &dev_attr_update_mode,
8373+ &dev_attr_tear_elim,
8374+ &dev_attr_timings,
8375+ &dev_attr_rotate,
8376+ &dev_attr_mirror,
8377+ &dev_attr_wss,
8378+ NULL
8379+};
8380+
8381+static void default_get_resolution(struct omap_dss_device *dssdev,
8382+ u16 *xres, u16 *yres)
8383+{
8384+ *xres = dssdev->panel.timings.x_res;
8385+ *yres = dssdev->panel.timings.y_res;
8386+}
8387+
8388+void default_get_overlay_fifo_thresholds(enum omap_plane plane,
8389+ u32 fifo_size, enum omap_burst_size *burst_size,
8390+ u32 *fifo_low, u32 *fifo_high)
8391+{
8392+ unsigned burst_size_bytes;
8393+
8394+ *burst_size = OMAP_DSS_BURST_16x32;
8395+ burst_size_bytes = 16 * 32 / 8;
8396+
8397+ *fifo_high = fifo_size - 1;
8398+ *fifo_low = fifo_size - burst_size_bytes;
8399+}
8400+
8401+static int default_wait_vsync(struct omap_dss_device *dssdev)
8402+{
8403+ unsigned long timeout = msecs_to_jiffies(500);
8404+ u32 irq;
8405+
8406+ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
8407+ irq = DISPC_IRQ_EVSYNC_ODD;
8408+ else
8409+ irq = DISPC_IRQ_VSYNC;
8410+
8411+ return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
8412+}
8413+
8414+static int default_get_recommended_bpp(struct omap_dss_device *dssdev)
8415+{
8416+ if (dssdev->panel.recommended_bpp)
8417+ return dssdev->panel.recommended_bpp;
8418+
8419+ switch (dssdev->type) {
8420+ case OMAP_DISPLAY_TYPE_DPI:
8421+ if (dssdev->phy.dpi.data_lines == 24)
8422+ return 24;
8423+ else
8424+ return 16;
8425+
8426+ case OMAP_DISPLAY_TYPE_DBI:
8427+ case OMAP_DISPLAY_TYPE_DSI:
8428+ if (dssdev->ctrl.pixel_size == 24)
8429+ return 24;
8430+ else
8431+ return 16;
8432+ case OMAP_DISPLAY_TYPE_VENC:
8433+ case OMAP_DISPLAY_TYPE_SDI:
8434+ return 24;
8435+ return 24;
8436+ default:
8437+ BUG();
8438+ }
8439+}
8440+
8441+/* Checks if replication logic should be used. Only use for active matrix,
8442+ * when overlay is in RGB12U or RGB16 mode, and LCD interface is
8443+ * 18bpp or 24bpp */
8444+bool dss_use_replication(struct omap_dss_device *dssdev,
8445+ enum omap_color_mode mode)
8446+{
8447+ int bpp;
8448+
8449+ if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16)
8450+ return false;
8451+
8452+ if (dssdev->type == OMAP_DISPLAY_TYPE_DPI &&
8453+ (dssdev->panel.config & OMAP_DSS_LCD_TFT) == 0)
8454+ return false;
8455+
8456+ switch (dssdev->type) {
8457+ case OMAP_DISPLAY_TYPE_DPI:
8458+ bpp = dssdev->phy.dpi.data_lines;
8459+ break;
8460+ case OMAP_DISPLAY_TYPE_VENC:
8461+ case OMAP_DISPLAY_TYPE_SDI:
8462+ bpp = 24;
8463+ break;
8464+ case OMAP_DISPLAY_TYPE_DBI:
8465+ case OMAP_DISPLAY_TYPE_DSI:
8466+ bpp = dssdev->ctrl.pixel_size;
8467+ break;
8468+ default:
8469+ BUG();
8470+ }
8471+
8472+ return bpp > 16;
8473+}
8474+
8475+void dss_init_device(struct platform_device *pdev,
8476+ struct omap_dss_device *dssdev)
8477+{
8478+ struct device_attribute *attr;
8479+ int i;
8480+ int r;
8481+
8482+ switch (dssdev->type) {
8483+ case OMAP_DISPLAY_TYPE_DPI:
8484+#ifdef CONFIG_OMAP2_DSS_RFBI
8485+ case OMAP_DISPLAY_TYPE_DBI:
8486+#endif
8487+#ifdef CONFIG_OMAP2_DSS_SDI
8488+ case OMAP_DISPLAY_TYPE_SDI:
8489+#endif
8490+#ifdef CONFIG_OMAP2_DSS_DSI
8491+ case OMAP_DISPLAY_TYPE_DSI:
8492+#endif
8493+#ifdef CONFIG_OMAP2_DSS_VENC
8494+ case OMAP_DISPLAY_TYPE_VENC:
8495+#endif
8496+ break;
8497+ default:
8498+ DSSERR("Support for display '%s' not compiled in.\n",
8499+ dssdev->name);
8500+ return;
8501+ }
8502+
8503+ dssdev->get_resolution = default_get_resolution;
8504+ dssdev->get_recommended_bpp = default_get_recommended_bpp;
8505+ dssdev->wait_vsync = default_wait_vsync;
8506+
8507+ switch (dssdev->type) {
8508+ case OMAP_DISPLAY_TYPE_DPI:
8509+ r = dpi_init_display(dssdev);
8510+ break;
8511+#ifdef CONFIG_OMAP2_DSS_RFBI
8512+ case OMAP_DISPLAY_TYPE_DBI:
8513+ r = rfbi_init_display(dssdev);
8514+ break;
8515+#endif
8516+#ifdef CONFIG_OMAP2_DSS_VENC
8517+ case OMAP_DISPLAY_TYPE_VENC:
8518+ r = venc_init_display(dssdev);
8519+ break;
8520+#endif
8521+#ifdef CONFIG_OMAP2_DSS_SDI
8522+ case OMAP_DISPLAY_TYPE_SDI:
8523+ r = sdi_init_display(dssdev);
8524+ break;
8525+#endif
8526+#ifdef CONFIG_OMAP2_DSS_DSI
8527+ case OMAP_DISPLAY_TYPE_DSI:
8528+ r = dsi_init_display(dssdev);
8529+ break;
8530+#endif
8531+ default:
8532+ BUG();
8533+ }
8534+
8535+ if (r) {
8536+ DSSERR("failed to init display %s\n", dssdev->name);
8537+ return;
8538+ }
8539+
8540+ /* create device sysfs files */
8541+ i = 0;
8542+ while ((attr = display_sysfs_attrs[i++]) != NULL) {
8543+ r = device_create_file(&dssdev->dev, attr);
8544+ if (r)
8545+ DSSERR("failed to create sysfs file\n");
8546+ }
8547+
8548+ /* create display? sysfs links */
8549+ r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
8550+ dev_name(&dssdev->dev));
8551+ if (r)
8552+ DSSERR("failed to create sysfs display link\n");
8553+}
8554+
8555+void dss_uninit_device(struct platform_device *pdev,
8556+ struct omap_dss_device *dssdev)
8557+{
8558+ struct device_attribute *attr;
8559+ int i = 0;
8560+
8561+ sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
8562+
8563+ while ((attr = display_sysfs_attrs[i++]) != NULL)
8564+ device_remove_file(&dssdev->dev, attr);
8565+
8566+ if (dssdev->manager)
8567+ dssdev->manager->unset_device(dssdev->manager);
8568+}
8569+
8570+static int dss_suspend_device(struct device *dev, void *data)
8571+{
8572+ int r;
8573+ struct omap_dss_device *dssdev = to_dss_device(dev);
8574+
8575+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
8576+ dssdev->activate_after_resume = false;
8577+ return 0;
8578+ }
8579+
8580+ if (!dssdev->suspend) {
8581+ DSSERR("display '%s' doesn't implement suspend\n",
8582+ dssdev->name);
8583+ return -ENOSYS;
8584+ }
8585+
8586+ r = dssdev->suspend(dssdev);
8587+ if (r)
8588+ return r;
8589+
8590+ dssdev->activate_after_resume = true;
8591+
8592+ return 0;
8593+}
8594+
8595+int dss_suspend_all_devices(void)
8596+{
8597+ int r;
8598+ struct bus_type *bus = dss_get_bus();
8599+
8600+ r = bus_for_each_dev(bus, NULL, NULL, dss_suspend_device);
8601+ if (r) {
8602+ /* resume all displays that were suspended */
8603+ dss_resume_all_devices();
8604+ return r;
8605+ }
8606+
8607+ return 0;
8608+}
8609+
8610+static int dss_resume_device(struct device *dev, void *data)
8611+{
8612+ int r;
8613+ struct omap_dss_device *dssdev = to_dss_device(dev);
8614+
8615+ if (dssdev->activate_after_resume && dssdev->resume) {
8616+ r = dssdev->resume(dssdev);
8617+ if (r)
8618+ return r;
8619+ }
8620+
8621+ dssdev->activate_after_resume = false;
8622+
8623+ return 0;
8624+}
8625+
8626+int dss_resume_all_devices(void)
8627+{
8628+ struct bus_type *bus = dss_get_bus();
8629+
8630+ return bus_for_each_dev(bus, NULL, NULL, dss_resume_device);
8631+}
8632+
8633+
8634+void omap_dss_get_device(struct omap_dss_device *dssdev)
8635+{
8636+ get_device(&dssdev->dev);
8637+}
8638+EXPORT_SYMBOL(omap_dss_get_device);
8639+
8640+void omap_dss_put_device(struct omap_dss_device *dssdev)
8641+{
8642+ put_device(&dssdev->dev);
8643+}
8644+EXPORT_SYMBOL(omap_dss_put_device);
8645+
8646+/* ref count of the found device is incremented. ref count
8647+ * of from-device is decremented. */
8648+struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
8649+{
8650+ struct device *dev;
8651+ struct device *dev_start = NULL;
8652+ struct omap_dss_device *dssdev = NULL;
8653+
8654+ int match(struct device *dev, void *data)
8655+ {
8656+ /* skip panels connected to controllers */
8657+ if (to_dss_device(dev)->panel.ctrl)
8658+ return 0;
8659+
8660+ return 1;
8661+ }
8662+
8663+ if (from)
8664+ dev_start = &from->dev;
8665+ dev = bus_find_device(dss_get_bus(), dev_start, NULL, match);
8666+ if (dev)
8667+ dssdev = to_dss_device(dev);
8668+ if (from)
8669+ put_device(&from->dev);
8670+
8671+ return dssdev;
8672+}
8673+EXPORT_SYMBOL(omap_dss_get_next_device);
8674+
8675+struct omap_dss_device *omap_dss_find_device(void *data,
8676+ int (*match)(struct omap_dss_device *dssdev, void *data))
8677+{
8678+ struct omap_dss_device *dssdev = NULL;
8679+
8680+ while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) {
8681+ if (match(dssdev, data))
8682+ return dssdev;
8683+ }
8684+
8685+ return NULL;
8686+}
8687+EXPORT_SYMBOL(omap_dss_find_device);
8688+
8689+int omap_dss_start_device(struct omap_dss_device *dssdev)
8690+{
8691+ int r;
8692+
8693+ if (!dssdev->driver) {
8694+ DSSDBG("no driver\n");
8695+ r = -ENODEV;
8696+ goto err0;
8697+ }
8698+
8699+ if (dssdev->ctrl.panel && !dssdev->ctrl.panel->driver) {
8700+ DSSDBG("no panel driver\n");
8701+ r = -ENODEV;
8702+ goto err0;
8703+ }
8704+
8705+ if (!try_module_get(dssdev->dev.driver->owner)) {
8706+ r = -ENODEV;
8707+ goto err0;
8708+ }
8709+
8710+ if (dssdev->ctrl.panel) {
8711+ if (!try_module_get(dssdev->ctrl.panel->dev.driver->owner)) {
8712+ r = -ENODEV;
8713+ goto err1;
8714+ }
8715+ }
8716+
8717+ return 0;
8718+err1:
8719+ module_put(dssdev->dev.driver->owner);
8720+err0:
8721+ return r;
8722+}
8723+EXPORT_SYMBOL(omap_dss_start_device);
8724+
8725+void omap_dss_stop_device(struct omap_dss_device *dssdev)
8726+{
8727+ if (dssdev->ctrl.panel)
8728+ module_put(dssdev->ctrl.panel->dev.driver->owner);
8729+
8730+ module_put(dssdev->dev.driver->owner);
8731+}
8732+EXPORT_SYMBOL(omap_dss_stop_device);
8733+
8734--- /dev/null
8735+++ b/drivers/video/omap2/dss/dpi.c
8736@@ -0,0 +1,388 @@
8737+/*
8738+ * linux/drivers/video/omap2/dss/dpi.c
8739+ *
8740+ * Copyright (C) 2009 Nokia Corporation
8741+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
8742+ *
8743+ * Some code and ideas taken from drivers/video/omap/ driver
8744+ * by Imre Deak.
8745+ *
8746+ * This program is free software; you can redistribute it and/or modify it
8747+ * under the terms of the GNU General Public License version 2 as published by
8748+ * the Free Software Foundation.
8749+ *
8750+ * This program is distributed in the hope that it will be useful, but WITHOUT
8751+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8752+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
8753+ * more details.
8754+ *
8755+ * You should have received a copy of the GNU General Public License along with
8756+ * this program. If not, see <http://www.gnu.org/licenses/>.
8757+ */
8758+
8759+#define DSS_SUBSYS_NAME "DPI"
8760+
8761+#include <linux/kernel.h>
8762+#include <linux/clk.h>
8763+#include <linux/delay.h>
8764+#include <linux/errno.h>
8765+
8766+#include <mach/board.h>
8767+#include <mach/display.h>
8768+#include <mach/cpu.h>
8769+
8770+#include "dss.h"
8771+
8772+static struct {
8773+ int update_enabled;
8774+} dpi;
8775+
8776+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
8777+static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req,
8778+ unsigned long *fck, int *lck_div, int *pck_div)
8779+{
8780+ struct dsi_clock_info cinfo;
8781+ int r;
8782+
8783+ r = dsi_pll_calc_pck(is_tft, pck_req, &cinfo);
8784+ if (r)
8785+ return r;
8786+
8787+ r = dsi_pll_program(&cinfo);
8788+ if (r)
8789+ return r;
8790+
8791+ dss_select_clk_source(0, 1);
8792+
8793+ dispc_set_lcd_divisor(cinfo.lck_div, cinfo.pck_div);
8794+
8795+ *fck = cinfo.dsi1_pll_fclk;
8796+ *lck_div = cinfo.lck_div;
8797+ *pck_div = cinfo.pck_div;
8798+
8799+ return 0;
8800+}
8801+#else
8802+static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req,
8803+ unsigned long *fck, int *lck_div, int *pck_div)
8804+{
8805+ struct dispc_clock_info cinfo;
8806+ int r;
8807+
8808+ r = dispc_calc_clock_div(is_tft, pck_req, &cinfo);
8809+ if (r)
8810+ return r;
8811+
8812+ r = dispc_set_clock_div(&cinfo);
8813+ if (r)
8814+ return r;
8815+
8816+ *fck = cinfo.fck;
8817+ *lck_div = cinfo.lck_div;
8818+ *pck_div = cinfo.pck_div;
8819+
8820+ return 0;
8821+}
8822+#endif
8823+
8824+static int dpi_set_mode(struct omap_dss_device *dssdev)
8825+{
8826+ struct omap_video_timings *t = &dssdev->panel.timings;
8827+ int lck_div, pck_div;
8828+ unsigned long fck;
8829+ unsigned long pck;
8830+ bool is_tft;
8831+ int r = 0;
8832+
8833+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
8834+
8835+ dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi,
8836+ dssdev->panel.acb);
8837+
8838+ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
8839+
8840+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
8841+ r = dpi_set_dsi_clk(is_tft, t->pixel_clock * 1000,
8842+ &fck, &lck_div, &pck_div);
8843+#else
8844+ r = dpi_set_dispc_clk(is_tft, t->pixel_clock * 1000,
8845+ &fck, &lck_div, &pck_div);
8846+#endif
8847+ if (r)
8848+ goto err0;
8849+
8850+ pck = fck / lck_div / pck_div / 1000;
8851+
8852+ if (pck != t->pixel_clock) {
8853+ DSSWARN("Could not find exact pixel clock. "
8854+ "Requested %d kHz, got %lu kHz\n",
8855+ t->pixel_clock, pck);
8856+
8857+ t->pixel_clock = pck;
8858+ }
8859+
8860+ dispc_set_lcd_timings(t);
8861+
8862+err0:
8863+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
8864+ return r;
8865+}
8866+
8867+static int dpi_basic_init(struct omap_dss_device *dssdev)
8868+{
8869+ bool is_tft;
8870+
8871+ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
8872+
8873+ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
8874+ dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT :
8875+ OMAP_DSS_LCD_DISPLAY_STN);
8876+ dispc_set_tft_data_lines(dssdev->phy.dpi.data_lines);
8877+
8878+ return 0;
8879+}
8880+
8881+static int dpi_display_enable(struct omap_dss_device *dssdev)
8882+{
8883+ int r;
8884+
8885+ r = omap_dss_start_device(dssdev);
8886+ if (r) {
8887+ DSSERR("failed to start device\n");
8888+ goto err0;
8889+ }
8890+
8891+ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
8892+ DSSERR("display already enabled\n");
8893+ r = -EINVAL;
8894+ goto err1;
8895+ }
8896+
8897+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
8898+
8899+ r = dpi_basic_init(dssdev);
8900+ if (r)
8901+ goto err2;
8902+
8903+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
8904+ dss_clk_enable(DSS_CLK_FCK2);
8905+ r = dsi_pll_init(0, 1);
8906+ if (r)
8907+ goto err3;
8908+#endif
8909+ r = dpi_set_mode(dssdev);
8910+ if (r)
8911+ goto err4;
8912+
8913+ mdelay(2);
8914+
8915+ dispc_enable_lcd_out(1);
8916+
8917+ r = dssdev->driver->enable(dssdev);
8918+ if (r)
8919+ goto err5;
8920+
8921+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
8922+
8923+ return 0;
8924+
8925+err5:
8926+ dispc_enable_lcd_out(0);
8927+err4:
8928+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
8929+ dsi_pll_uninit();
8930+err3:
8931+ dss_clk_disable(DSS_CLK_FCK2);
8932+#endif
8933+err2:
8934+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
8935+err1:
8936+ omap_dss_stop_device(dssdev);
8937+err0:
8938+ return r;
8939+}
8940+
8941+static int dpi_display_resume(struct omap_dss_device *dssdev);
8942+
8943+static void dpi_display_disable(struct omap_dss_device *dssdev)
8944+{
8945+ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
8946+ return;
8947+
8948+ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
8949+ dpi_display_resume(dssdev);
8950+
8951+ dssdev->driver->disable(dssdev);
8952+
8953+ dispc_enable_lcd_out(0);
8954+
8955+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
8956+ dss_select_clk_source(0, 0);
8957+ dsi_pll_uninit();
8958+ dss_clk_disable(DSS_CLK_FCK2);
8959+#endif
8960+
8961+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
8962+
8963+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
8964+
8965+ omap_dss_stop_device(dssdev);
8966+}
8967+
8968+static int dpi_display_suspend(struct omap_dss_device *dssdev)
8969+{
8970+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
8971+ return -EINVAL;
8972+
8973+ DSSDBG("dpi_display_suspend\n");
8974+
8975+ if (dssdev->driver->suspend)
8976+ dssdev->driver->suspend(dssdev);
8977+
8978+ dispc_enable_lcd_out(0);
8979+
8980+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
8981+
8982+ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
8983+
8984+ return 0;
8985+}
8986+
8987+static int dpi_display_resume(struct omap_dss_device *dssdev)
8988+{
8989+ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
8990+ return -EINVAL;
8991+
8992+ DSSDBG("dpi_display_resume\n");
8993+
8994+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
8995+
8996+ dispc_enable_lcd_out(1);
8997+
8998+ if (dssdev->driver->resume)
8999+ dssdev->driver->resume(dssdev);
9000+
9001+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
9002+
9003+ return 0;
9004+}
9005+
9006+static void dpi_set_timings(struct omap_dss_device *dssdev,
9007+ struct omap_video_timings *timings)
9008+{
9009+ DSSDBG("dpi_set_timings\n");
9010+ dssdev->panel.timings = *timings;
9011+ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
9012+ dpi_set_mode(dssdev);
9013+ dispc_go(OMAP_DSS_CHANNEL_LCD);
9014+ }
9015+}
9016+
9017+static int dpi_check_timings(struct omap_dss_device *dssdev,
9018+ struct omap_video_timings *timings)
9019+{
9020+ bool is_tft;
9021+ int r;
9022+ int lck_div, pck_div;
9023+ unsigned long fck;
9024+ unsigned long pck;
9025+
9026+ if (!dispc_lcd_timings_ok(timings))
9027+ return -EINVAL;
9028+
9029+ if (timings->pixel_clock == 0)
9030+ return -EINVAL;
9031+
9032+ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
9033+
9034+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
9035+ {
9036+ struct dsi_clock_info cinfo;
9037+ r = dsi_pll_calc_pck(is_tft, timings->pixel_clock * 1000,
9038+ &cinfo);
9039+
9040+ if (r)
9041+ return r;
9042+
9043+ fck = cinfo.dsi1_pll_fclk;
9044+ lck_div = cinfo.lck_div;
9045+ pck_div = cinfo.pck_div;
9046+ }
9047+#else
9048+ {
9049+ struct dispc_clock_info cinfo;
9050+ r = dispc_calc_clock_div(is_tft, timings->pixel_clock * 1000,
9051+ &cinfo);
9052+
9053+ if (r)
9054+ return r;
9055+
9056+ fck = cinfo.fck;
9057+ lck_div = cinfo.lck_div;
9058+ pck_div = cinfo.pck_div;
9059+ }
9060+#endif
9061+
9062+ pck = fck / lck_div / pck_div / 1000;
9063+
9064+ timings->pixel_clock = pck;
9065+
9066+ return 0;
9067+}
9068+
9069+static void dpi_get_timings(struct omap_dss_device *dssdev,
9070+ struct omap_video_timings *timings)
9071+{
9072+ *timings = dssdev->panel.timings;
9073+}
9074+
9075+static int dpi_display_set_update_mode(struct omap_dss_device *dssdev,
9076+ enum omap_dss_update_mode mode)
9077+{
9078+ if (mode == OMAP_DSS_UPDATE_MANUAL)
9079+ return -EINVAL;
9080+
9081+ if (mode == OMAP_DSS_UPDATE_DISABLED) {
9082+ dispc_enable_lcd_out(0);
9083+ dpi.update_enabled = 0;
9084+ } else {
9085+ dispc_enable_lcd_out(1);
9086+ dpi.update_enabled = 1;
9087+ }
9088+
9089+ return 0;
9090+}
9091+
9092+static enum omap_dss_update_mode dpi_display_get_update_mode(
9093+ struct omap_dss_device *dssdev)
9094+{
9095+ return dpi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
9096+ OMAP_DSS_UPDATE_DISABLED;
9097+}
9098+
9099+int dpi_init_display(struct omap_dss_device *dssdev)
9100+{
9101+ DSSDBG("init_display\n");
9102+
9103+ dssdev->enable = dpi_display_enable;
9104+ dssdev->disable = dpi_display_disable;
9105+ dssdev->suspend = dpi_display_suspend;
9106+ dssdev->resume = dpi_display_resume;
9107+ dssdev->set_timings = dpi_set_timings;
9108+ dssdev->check_timings = dpi_check_timings;
9109+ dssdev->get_timings = dpi_get_timings;
9110+ dssdev->set_update_mode = dpi_display_set_update_mode;
9111+ dssdev->get_update_mode = dpi_display_get_update_mode;
9112+
9113+ return 0;
9114+}
9115+
9116+int dpi_init(void)
9117+{
9118+ return 0;
9119+}
9120+
9121+void dpi_exit(void)
9122+{
9123+}
9124+
9125--- /dev/null
9126+++ b/drivers/video/omap2/dss/dsi.c
9127@@ -0,0 +1,3509 @@
9128+/*
9129+ * linux/drivers/video/omap2/dss/dsi.c
9130+ *
9131+ * Copyright (C) 2009 Nokia Corporation
9132+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
9133+ *
9134+ * This program is free software; you can redistribute it and/or modify it
9135+ * under the terms of the GNU General Public License version 2 as published by
9136+ * the Free Software Foundation.
9137+ *
9138+ * This program is distributed in the hope that it will be useful, but WITHOUT
9139+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9140+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9141+ * more details.
9142+ *
9143+ * You should have received a copy of the GNU General Public License along with
9144+ * this program. If not, see <http://www.gnu.org/licenses/>.
9145+ */
9146+
9147+#define DSS_SUBSYS_NAME "DSI"
9148+
9149+#include <linux/kernel.h>
9150+#include <linux/io.h>
9151+#include <linux/clk.h>
9152+#include <linux/device.h>
9153+#include <linux/err.h>
9154+#include <linux/interrupt.h>
9155+#include <linux/delay.h>
9156+#include <linux/mutex.h>
9157+#include <linux/seq_file.h>
9158+#include <linux/platform_device.h>
9159+#include <linux/regulator/consumer.h>
9160+#include <linux/kthread.h>
9161+#include <linux/wait.h>
9162+
9163+#include <mach/board.h>
9164+#include <mach/display.h>
9165+#include <mach/clock.h>
9166+
9167+#include "dss.h"
9168+
9169+/*#define VERBOSE_IRQ*/
9170+
9171+#define DSI_BASE 0x4804FC00
9172+
9173+struct dsi_reg { u16 idx; };
9174+
9175+#define DSI_REG(idx) ((const struct dsi_reg) { idx })
9176+
9177+#define DSI_SZ_REGS SZ_1K
9178+/* DSI Protocol Engine */
9179+
9180+#define DSI_REVISION DSI_REG(0x0000)
9181+#define DSI_SYSCONFIG DSI_REG(0x0010)
9182+#define DSI_SYSSTATUS DSI_REG(0x0014)
9183+#define DSI_IRQSTATUS DSI_REG(0x0018)
9184+#define DSI_IRQENABLE DSI_REG(0x001C)
9185+#define DSI_CTRL DSI_REG(0x0040)
9186+#define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048)
9187+#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C)
9188+#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050)
9189+#define DSI_CLK_CTRL DSI_REG(0x0054)
9190+#define DSI_TIMING1 DSI_REG(0x0058)
9191+#define DSI_TIMING2 DSI_REG(0x005C)
9192+#define DSI_VM_TIMING1 DSI_REG(0x0060)
9193+#define DSI_VM_TIMING2 DSI_REG(0x0064)
9194+#define DSI_VM_TIMING3 DSI_REG(0x0068)
9195+#define DSI_CLK_TIMING DSI_REG(0x006C)
9196+#define DSI_TX_FIFO_VC_SIZE DSI_REG(0x0070)
9197+#define DSI_RX_FIFO_VC_SIZE DSI_REG(0x0074)
9198+#define DSI_COMPLEXIO_CFG2 DSI_REG(0x0078)
9199+#define DSI_RX_FIFO_VC_FULLNESS DSI_REG(0x007C)
9200+#define DSI_VM_TIMING4 DSI_REG(0x0080)
9201+#define DSI_TX_FIFO_VC_EMPTINESS DSI_REG(0x0084)
9202+#define DSI_VM_TIMING5 DSI_REG(0x0088)
9203+#define DSI_VM_TIMING6 DSI_REG(0x008C)
9204+#define DSI_VM_TIMING7 DSI_REG(0x0090)
9205+#define DSI_STOPCLK_TIMING DSI_REG(0x0094)
9206+#define DSI_VC_CTRL(n) DSI_REG(0x0100 + (n * 0x20))
9207+#define DSI_VC_TE(n) DSI_REG(0x0104 + (n * 0x20))
9208+#define DSI_VC_LONG_PACKET_HEADER(n) DSI_REG(0x0108 + (n * 0x20))
9209+#define DSI_VC_LONG_PACKET_PAYLOAD(n) DSI_REG(0x010C + (n * 0x20))
9210+#define DSI_VC_SHORT_PACKET_HEADER(n) DSI_REG(0x0110 + (n * 0x20))
9211+#define DSI_VC_IRQSTATUS(n) DSI_REG(0x0118 + (n * 0x20))
9212+#define DSI_VC_IRQENABLE(n) DSI_REG(0x011C + (n * 0x20))
9213+
9214+/* DSIPHY_SCP */
9215+
9216+#define DSI_DSIPHY_CFG0 DSI_REG(0x200 + 0x0000)
9217+#define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004)
9218+#define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008)
9219+#define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014)
9220+
9221+/* DSI_PLL_CTRL_SCP */
9222+
9223+#define DSI_PLL_CONTROL DSI_REG(0x300 + 0x0000)
9224+#define DSI_PLL_STATUS DSI_REG(0x300 + 0x0004)
9225+#define DSI_PLL_GO DSI_REG(0x300 + 0x0008)
9226+#define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C)
9227+#define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010)
9228+
9229+#define REG_GET(idx, start, end) \
9230+ FLD_GET(dsi_read_reg(idx), start, end)
9231+
9232+#define REG_FLD_MOD(idx, val, start, end) \
9233+ dsi_write_reg(idx, FLD_MOD(dsi_read_reg(idx), val, start, end))
9234+
9235+/* Global interrupts */
9236+#define DSI_IRQ_VC0 (1 << 0)
9237+#define DSI_IRQ_VC1 (1 << 1)
9238+#define DSI_IRQ_VC2 (1 << 2)
9239+#define DSI_IRQ_VC3 (1 << 3)
9240+#define DSI_IRQ_WAKEUP (1 << 4)
9241+#define DSI_IRQ_RESYNC (1 << 5)
9242+#define DSI_IRQ_PLL_LOCK (1 << 7)
9243+#define DSI_IRQ_PLL_UNLOCK (1 << 8)
9244+#define DSI_IRQ_PLL_RECALL (1 << 9)
9245+#define DSI_IRQ_COMPLEXIO_ERR (1 << 10)
9246+#define DSI_IRQ_HS_TX_TIMEOUT (1 << 14)
9247+#define DSI_IRQ_LP_RX_TIMEOUT (1 << 15)
9248+#define DSI_IRQ_TE_TRIGGER (1 << 16)
9249+#define DSI_IRQ_ACK_TRIGGER (1 << 17)
9250+#define DSI_IRQ_SYNC_LOST (1 << 18)
9251+#define DSI_IRQ_LDO_POWER_GOOD (1 << 19)
9252+#define DSI_IRQ_TA_TIMEOUT (1 << 20)
9253+#define DSI_IRQ_ERROR_MASK \
9254+ (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
9255+ DSI_IRQ_TA_TIMEOUT)
9256+#define DSI_IRQ_CHANNEL_MASK 0xf
9257+
9258+/* Virtual channel interrupts */
9259+#define DSI_VC_IRQ_CS (1 << 0)
9260+#define DSI_VC_IRQ_ECC_CORR (1 << 1)
9261+#define DSI_VC_IRQ_PACKET_SENT (1 << 2)
9262+#define DSI_VC_IRQ_FIFO_TX_OVF (1 << 3)
9263+#define DSI_VC_IRQ_FIFO_RX_OVF (1 << 4)
9264+#define DSI_VC_IRQ_BTA (1 << 5)
9265+#define DSI_VC_IRQ_ECC_NO_CORR (1 << 6)
9266+#define DSI_VC_IRQ_FIFO_TX_UDF (1 << 7)
9267+#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8)
9268+#define DSI_VC_IRQ_ERROR_MASK \
9269+ (DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \
9270+ DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \
9271+ DSI_VC_IRQ_FIFO_TX_UDF)
9272+
9273+/* ComplexIO interrupts */
9274+#define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0)
9275+#define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1)
9276+#define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2)
9277+#define DSI_CIO_IRQ_ERRESC1 (1 << 5)
9278+#define DSI_CIO_IRQ_ERRESC2 (1 << 6)
9279+#define DSI_CIO_IRQ_ERRESC3 (1 << 7)
9280+#define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10)
9281+#define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11)
9282+#define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12)
9283+#define DSI_CIO_IRQ_STATEULPS1 (1 << 15)
9284+#define DSI_CIO_IRQ_STATEULPS2 (1 << 16)
9285+#define DSI_CIO_IRQ_STATEULPS3 (1 << 17)
9286+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20)
9287+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21)
9288+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22)
9289+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23)
9290+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24)
9291+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25)
9292+#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30)
9293+#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31)
9294+
9295+#define DSI_DT_DCS_SHORT_WRITE_0 0x05
9296+#define DSI_DT_DCS_SHORT_WRITE_1 0x15
9297+#define DSI_DT_DCS_READ 0x06
9298+#define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37
9299+#define DSI_DT_NULL_PACKET 0x09
9300+#define DSI_DT_DCS_LONG_WRITE 0x39
9301+
9302+#define DSI_DT_RX_ACK_WITH_ERR 0x02
9303+#define DSI_DT_RX_DCS_LONG_READ 0x1c
9304+#define DSI_DT_RX_SHORT_READ_1 0x21
9305+#define DSI_DT_RX_SHORT_READ_2 0x22
9306+
9307+#define FINT_MAX 2100000
9308+#define FINT_MIN 750000
9309+#define REGN_MAX (1 << 7)
9310+#define REGM_MAX ((1 << 11) - 1)
9311+#define REGM3_MAX (1 << 4)
9312+#define REGM4_MAX (1 << 4)
9313+
9314+enum fifo_size {
9315+ DSI_FIFO_SIZE_0 = 0,
9316+ DSI_FIFO_SIZE_32 = 1,
9317+ DSI_FIFO_SIZE_64 = 2,
9318+ DSI_FIFO_SIZE_96 = 3,
9319+ DSI_FIFO_SIZE_128 = 4,
9320+};
9321+
9322+enum dsi_vc_mode {
9323+ DSI_VC_MODE_L4 = 0,
9324+ DSI_VC_MODE_VP,
9325+};
9326+
9327+struct dsi_update_region {
9328+ bool dirty;
9329+ u16 x, y, w, h;
9330+ struct omap_dss_device *device;
9331+};
9332+
9333+static struct
9334+{
9335+ void __iomem *base;
9336+
9337+ unsigned long dsi1_pll_fclk; /* Hz */
9338+ unsigned long dsi2_pll_fclk; /* Hz */
9339+ unsigned long dsiphy; /* Hz */
9340+ unsigned long ddr_clk; /* Hz */
9341+
9342+ struct regulator *vdds_dsi_reg;
9343+
9344+ struct {
9345+ enum dsi_vc_mode mode;
9346+ struct omap_dss_device *dssdev;
9347+ enum fifo_size fifo_size;
9348+ int dest_per; /* destination peripheral 0-3 */
9349+ } vc[4];
9350+
9351+ struct mutex lock;
9352+ struct mutex bus_lock;
9353+
9354+ unsigned pll_locked;
9355+
9356+ struct completion bta_completion;
9357+
9358+ struct task_struct *thread;
9359+ wait_queue_head_t waitqueue;
9360+
9361+ spinlock_t update_lock;
9362+ bool framedone_received;
9363+ struct dsi_update_region update_region;
9364+ struct dsi_update_region active_update_region;
9365+ struct completion update_completion;
9366+
9367+ enum omap_dss_update_mode user_update_mode;
9368+ enum omap_dss_update_mode update_mode;
9369+ bool te_enabled;
9370+ bool use_ext_te;
9371+
9372+ unsigned long cache_req_pck;
9373+ unsigned long cache_clk_freq;
9374+ struct dsi_clock_info cache_cinfo;
9375+
9376+ u32 errors;
9377+ spinlock_t errors_lock;
9378+#ifdef DEBUG
9379+ ktime_t perf_setup_time;
9380+ ktime_t perf_start_time;
9381+ ktime_t perf_start_time_auto;
9382+ int perf_measure_frames;
9383+#endif
9384+ int debug_read;
9385+ int debug_write;
9386+} dsi;
9387+
9388+#ifdef DEBUG
9389+static unsigned int dsi_perf;
9390+module_param_named(dsi_perf, dsi_perf, bool, 0644);
9391+#endif
9392+
9393+static inline void dsi_write_reg(const struct dsi_reg idx, u32 val)
9394+{
9395+ __raw_writel(val, dsi.base + idx.idx);
9396+}
9397+
9398+static inline u32 dsi_read_reg(const struct dsi_reg idx)
9399+{
9400+ return __raw_readl(dsi.base + idx.idx);
9401+}
9402+
9403+
9404+void dsi_save_context(void)
9405+{
9406+}
9407+
9408+void dsi_restore_context(void)
9409+{
9410+}
9411+
9412+void dsi_bus_lock(void)
9413+{
9414+ mutex_lock(&dsi.bus_lock);
9415+}
9416+EXPORT_SYMBOL(dsi_bus_lock);
9417+
9418+void dsi_bus_unlock(void)
9419+{
9420+ mutex_unlock(&dsi.bus_lock);
9421+}
9422+EXPORT_SYMBOL(dsi_bus_unlock);
9423+
9424+static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
9425+ int value)
9426+{
9427+ int t = 100000;
9428+
9429+ while (REG_GET(idx, bitnum, bitnum) != value) {
9430+ if (--t == 0)
9431+ return !value;
9432+ }
9433+
9434+ return value;
9435+}
9436+
9437+#ifdef DEBUG
9438+static void dsi_perf_mark_setup(void)
9439+{
9440+ dsi.perf_setup_time = ktime_get();
9441+}
9442+
9443+static void dsi_perf_mark_start(void)
9444+{
9445+ dsi.perf_start_time = ktime_get();
9446+}
9447+
9448+static void dsi_perf_mark_start_auto(void)
9449+{
9450+ dsi.perf_measure_frames = 0;
9451+ dsi.perf_start_time_auto = ktime_get();
9452+}
9453+
9454+static void dsi_perf_show(const char *name)
9455+{
9456+ ktime_t t, setup_time, trans_time;
9457+ u32 total_bytes;
9458+ u32 setup_us, trans_us, total_us;
9459+
9460+ if (!dsi_perf)
9461+ return;
9462+
9463+ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED)
9464+ return;
9465+
9466+ t = ktime_get();
9467+
9468+ setup_time = ktime_sub(dsi.perf_start_time, dsi.perf_setup_time);
9469+ setup_us = (u32)ktime_to_us(setup_time);
9470+ if (setup_us == 0)
9471+ setup_us = 1;
9472+
9473+ trans_time = ktime_sub(t, dsi.perf_start_time);
9474+ trans_us = (u32)ktime_to_us(trans_time);
9475+ if (trans_us == 0)
9476+ trans_us = 1;
9477+
9478+ total_us = setup_us + trans_us;
9479+
9480+ total_bytes = dsi.active_update_region.w *
9481+ dsi.active_update_region.h *
9482+ dsi.active_update_region.device->ctrl.pixel_size / 8;
9483+
9484+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
9485+ static u32 s_total_trans_us, s_total_setup_us;
9486+ static u32 s_min_trans_us = 0xffffffff, s_min_setup_us;
9487+ static u32 s_max_trans_us, s_max_setup_us;
9488+ const int numframes = 100;
9489+ ktime_t total_time_auto;
9490+ u32 total_time_auto_us;
9491+
9492+ dsi.perf_measure_frames++;
9493+
9494+ if (setup_us < s_min_setup_us)
9495+ s_min_setup_us = setup_us;
9496+
9497+ if (setup_us > s_max_setup_us)
9498+ s_max_setup_us = setup_us;
9499+
9500+ s_total_setup_us += setup_us;
9501+
9502+ if (trans_us < s_min_trans_us)
9503+ s_min_trans_us = trans_us;
9504+
9505+ if (trans_us > s_max_trans_us)
9506+ s_max_trans_us = trans_us;
9507+
9508+ s_total_trans_us += trans_us;
9509+
9510+ if (dsi.perf_measure_frames < numframes)
9511+ return;
9512+
9513+ total_time_auto = ktime_sub(t, dsi.perf_start_time_auto);
9514+ total_time_auto_us = (u32)ktime_to_us(total_time_auto);
9515+
9516+ printk(KERN_INFO "DSI(%s): %u fps, setup %u/%u/%u, "
9517+ "trans %u/%u/%u\n",
9518+ name,
9519+ 1000 * 1000 * numframes / total_time_auto_us,
9520+ s_min_setup_us,
9521+ s_max_setup_us,
9522+ s_total_setup_us / numframes,
9523+ s_min_trans_us,
9524+ s_max_trans_us,
9525+ s_total_trans_us / numframes);
9526+
9527+ s_total_setup_us = 0;
9528+ s_min_setup_us = 0xffffffff;
9529+ s_max_setup_us = 0;
9530+ s_total_trans_us = 0;
9531+ s_min_trans_us = 0xffffffff;
9532+ s_max_trans_us = 0;
9533+ dsi_perf_mark_start_auto();
9534+ } else {
9535+ printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
9536+ "%u bytes, %u kbytes/sec\n",
9537+ name,
9538+ setup_us,
9539+ trans_us,
9540+ total_us,
9541+ 1000*1000 / total_us,
9542+ total_bytes,
9543+ total_bytes * 1000 / total_us);
9544+ }
9545+}
9546+#else
9547+#define dsi_perf_mark_setup()
9548+#define dsi_perf_mark_start()
9549+#define dsi_perf_mark_start_auto()
9550+#define dsi_perf_show(x)
9551+#endif
9552+
9553+static void print_irq_status(u32 status)
9554+{
9555+#ifndef VERBOSE_IRQ
9556+ if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
9557+ return;
9558+#endif
9559+ printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status);
9560+
9561+#define PIS(x) \
9562+ if (status & DSI_IRQ_##x) \
9563+ printk(#x " ");
9564+#ifdef VERBOSE_IRQ
9565+ PIS(VC0);
9566+ PIS(VC1);
9567+ PIS(VC2);
9568+ PIS(VC3);
9569+#endif
9570+ PIS(WAKEUP);
9571+ PIS(RESYNC);
9572+ PIS(PLL_LOCK);
9573+ PIS(PLL_UNLOCK);
9574+ PIS(PLL_RECALL);
9575+ PIS(COMPLEXIO_ERR);
9576+ PIS(HS_TX_TIMEOUT);
9577+ PIS(LP_RX_TIMEOUT);
9578+ PIS(TE_TRIGGER);
9579+ PIS(ACK_TRIGGER);
9580+ PIS(SYNC_LOST);
9581+ PIS(LDO_POWER_GOOD);
9582+ PIS(TA_TIMEOUT);
9583+#undef PIS
9584+
9585+ printk("\n");
9586+}
9587+
9588+static void print_irq_status_vc(int channel, u32 status)
9589+{
9590+#ifndef VERBOSE_IRQ
9591+ if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
9592+ return;
9593+#endif
9594+ printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status);
9595+
9596+#define PIS(x) \
9597+ if (status & DSI_VC_IRQ_##x) \
9598+ printk(#x " ");
9599+ PIS(CS);
9600+ PIS(ECC_CORR);
9601+#ifdef VERBOSE_IRQ
9602+ PIS(PACKET_SENT);
9603+#endif
9604+ PIS(FIFO_TX_OVF);
9605+ PIS(FIFO_RX_OVF);
9606+ PIS(BTA);
9607+ PIS(ECC_NO_CORR);
9608+ PIS(FIFO_TX_UDF);
9609+ PIS(PP_BUSY_CHANGE);
9610+#undef PIS
9611+ printk("\n");
9612+}
9613+
9614+static void print_irq_status_cio(u32 status)
9615+{
9616+ printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
9617+
9618+#define PIS(x) \
9619+ if (status & DSI_CIO_IRQ_##x) \
9620+ printk(#x " ");
9621+ PIS(ERRSYNCESC1);
9622+ PIS(ERRSYNCESC2);
9623+ PIS(ERRSYNCESC3);
9624+ PIS(ERRESC1);
9625+ PIS(ERRESC2);
9626+ PIS(ERRESC3);
9627+ PIS(ERRCONTROL1);
9628+ PIS(ERRCONTROL2);
9629+ PIS(ERRCONTROL3);
9630+ PIS(STATEULPS1);
9631+ PIS(STATEULPS2);
9632+ PIS(STATEULPS3);
9633+ PIS(ERRCONTENTIONLP0_1);
9634+ PIS(ERRCONTENTIONLP1_1);
9635+ PIS(ERRCONTENTIONLP0_2);
9636+ PIS(ERRCONTENTIONLP1_2);
9637+ PIS(ERRCONTENTIONLP0_3);
9638+ PIS(ERRCONTENTIONLP1_3);
9639+ PIS(ULPSACTIVENOT_ALL0);
9640+ PIS(ULPSACTIVENOT_ALL1);
9641+#undef PIS
9642+
9643+ printk("\n");
9644+}
9645+
9646+static int debug_irq;
9647+
9648+/* called from dss */
9649+void dsi_irq_handler(void)
9650+{
9651+ u32 irqstatus, vcstatus, ciostatus;
9652+ int i;
9653+
9654+ irqstatus = dsi_read_reg(DSI_IRQSTATUS);
9655+
9656+ if (irqstatus & DSI_IRQ_ERROR_MASK) {
9657+ DSSERR("DSI error, irqstatus %x\n", irqstatus);
9658+ print_irq_status(irqstatus);
9659+ spin_lock(&dsi.errors_lock);
9660+ dsi.errors |= irqstatus & DSI_IRQ_ERROR_MASK;
9661+ spin_unlock(&dsi.errors_lock);
9662+ } else if (debug_irq) {
9663+ print_irq_status(irqstatus);
9664+ }
9665+
9666+ for (i = 0; i < 4; ++i) {
9667+ if ((irqstatus & (1<<i)) == 0)
9668+ continue;
9669+
9670+ vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i));
9671+
9672+ if (vcstatus & DSI_VC_IRQ_BTA)
9673+ complete(&dsi.bta_completion);
9674+
9675+ if (vcstatus & DSI_VC_IRQ_ERROR_MASK) {
9676+ DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
9677+ i, vcstatus);
9678+ print_irq_status_vc(i, vcstatus);
9679+ } else if (debug_irq) {
9680+ print_irq_status_vc(i, vcstatus);
9681+ }
9682+
9683+ dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus);
9684+ }
9685+
9686+ if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
9687+ ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
9688+
9689+ dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
9690+
9691+ DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
9692+ print_irq_status_cio(ciostatus);
9693+ }
9694+
9695+ dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
9696+}
9697+
9698+
9699+static void _dsi_initialize_irq(void)
9700+{
9701+ u32 l;
9702+ int i;
9703+
9704+ /* disable all interrupts */
9705+ dsi_write_reg(DSI_IRQENABLE, 0);
9706+ for (i = 0; i < 4; ++i)
9707+ dsi_write_reg(DSI_VC_IRQENABLE(i), 0);
9708+ dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0);
9709+
9710+ /* clear interrupt status */
9711+ l = dsi_read_reg(DSI_IRQSTATUS);
9712+ dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK);
9713+
9714+ for (i = 0; i < 4; ++i) {
9715+ l = dsi_read_reg(DSI_VC_IRQSTATUS(i));
9716+ dsi_write_reg(DSI_VC_IRQSTATUS(i), l);
9717+ }
9718+
9719+ l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
9720+ dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l);
9721+
9722+ /* enable error irqs */
9723+ l = DSI_IRQ_ERROR_MASK;
9724+ dsi_write_reg(DSI_IRQENABLE, l);
9725+
9726+ l = DSI_VC_IRQ_ERROR_MASK;
9727+ for (i = 0; i < 4; ++i)
9728+ dsi_write_reg(DSI_VC_IRQENABLE(i), l);
9729+
9730+ /* XXX zonda responds incorrectly, causing control error:
9731+ Exit from LP-ESC mode to LP11 uses wrong transition states on the
9732+ data lines LP0 and LN0. */
9733+ dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE,
9734+ -1 & (~DSI_CIO_IRQ_ERRCONTROL2));
9735+}
9736+
9737+static u32 dsi_get_errors(void)
9738+{
9739+ unsigned long flags;
9740+ u32 e;
9741+ spin_lock_irqsave(&dsi.errors_lock, flags);
9742+ e = dsi.errors;
9743+ dsi.errors = 0;
9744+ spin_unlock_irqrestore(&dsi.errors_lock, flags);
9745+ return e;
9746+}
9747+
9748+static void dsi_vc_enable_bta_irq(int channel)
9749+{
9750+ u32 l;
9751+
9752+ dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA);
9753+
9754+ l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
9755+ l |= DSI_VC_IRQ_BTA;
9756+ dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
9757+}
9758+
9759+static void dsi_vc_disable_bta_irq(int channel)
9760+{
9761+ u32 l;
9762+
9763+ l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
9764+ l &= ~DSI_VC_IRQ_BTA;
9765+ dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
9766+}
9767+
9768+/* DSI func clock. this could also be DSI2_PLL_FCLK */
9769+static inline void enable_clocks(bool enable)
9770+{
9771+ if (enable)
9772+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
9773+ else
9774+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
9775+}
9776+
9777+/* source clock for DSI PLL. this could also be PCLKFREE */
9778+static inline void dsi_enable_pll_clock(bool enable)
9779+{
9780+ if (enable)
9781+ dss_clk_enable(DSS_CLK_FCK2);
9782+ else
9783+ dss_clk_disable(DSS_CLK_FCK2);
9784+
9785+ if (enable && dsi.pll_locked) {
9786+ if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1)
9787+ DSSERR("cannot lock PLL when enabling clocks\n");
9788+ }
9789+}
9790+
9791+#ifdef DEBUG
9792+static void _dsi_print_reset_status(void)
9793+{
9794+ u32 l;
9795+
9796+ if (!dss_debug)
9797+ return;
9798+
9799+ /* A dummy read using the SCP interface to any DSIPHY register is
9800+ * required after DSIPHY reset to complete the reset of the DSI complex
9801+ * I/O. */
9802+ l = dsi_read_reg(DSI_DSIPHY_CFG5);
9803+
9804+ printk(KERN_DEBUG "DSI resets: ");
9805+
9806+ l = dsi_read_reg(DSI_PLL_STATUS);
9807+ printk("PLL (%d) ", FLD_GET(l, 0, 0));
9808+
9809+ l = dsi_read_reg(DSI_COMPLEXIO_CFG1);
9810+ printk("CIO (%d) ", FLD_GET(l, 29, 29));
9811+
9812+ l = dsi_read_reg(DSI_DSIPHY_CFG5);
9813+ printk("PHY (%x, %d, %d, %d)\n",
9814+ FLD_GET(l, 28, 26),
9815+ FLD_GET(l, 29, 29),
9816+ FLD_GET(l, 30, 30),
9817+ FLD_GET(l, 31, 31));
9818+}
9819+#else
9820+#define _dsi_print_reset_status()
9821+#endif
9822+
9823+static inline int dsi_if_enable(bool enable)
9824+{
9825+ DSSDBG("dsi_if_enable(%d)\n", enable);
9826+
9827+ enable = enable ? 1 : 0;
9828+ REG_FLD_MOD(DSI_CTRL, enable, 0, 0); /* IF_EN */
9829+
9830+ if (wait_for_bit_change(DSI_CTRL, 0, enable) != enable) {
9831+ DSSERR("Failed to set dsi_if_enable to %d\n", enable);
9832+ return -EIO;
9833+ }
9834+
9835+ return 0;
9836+}
9837+
9838+static unsigned long dsi_fclk_rate(void)
9839+{
9840+ unsigned long r;
9841+
9842+ if (dss_get_dsi_clk_source() == 0) {
9843+ /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */
9844+ r = dss_clk_get_rate(DSS_CLK_FCK1);
9845+ } else {
9846+ /* DSI FCLK source is DSI2_PLL_FCLK */
9847+ r = dsi.dsi2_pll_fclk;
9848+ }
9849+
9850+ return r;
9851+}
9852+
9853+static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev)
9854+{
9855+ unsigned n;
9856+ unsigned long dsi_fclk;
9857+ unsigned long lp_clk, lp_clk_req;
9858+
9859+ dsi_fclk = dsi_fclk_rate();
9860+
9861+ lp_clk_req = dssdev->phy.dsi.lp_clk_hz;
9862+
9863+ for (n = 1; n < (1 << 13) - 1; ++n) {
9864+ lp_clk = dsi_fclk / 2 / n;
9865+ if (lp_clk <= lp_clk_req)
9866+ break;
9867+ }
9868+
9869+ if (n == (1 << 13) - 1) {
9870+ DSSERR("Failed to find LP_CLK_DIVISOR\n");
9871+ return -EINVAL;
9872+ }
9873+
9874+ DSSDBG("LP_CLK_DIV %u, LP_CLK %lu (req %lu)\n", n, lp_clk, lp_clk_req);
9875+
9876+ REG_FLD_MOD(DSI_CLK_CTRL, n, 12, 0); /* LP_CLK_DIVISOR */
9877+ if (dsi_fclk > 30*1000*1000)
9878+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 21, 21); /* LP_RX_SYNCHRO_ENABLE */
9879+
9880+ return 0;
9881+}
9882+
9883+
9884+enum dsi_pll_power_state {
9885+ DSI_PLL_POWER_OFF = 0x0,
9886+ DSI_PLL_POWER_ON_HSCLK = 0x1,
9887+ DSI_PLL_POWER_ON_ALL = 0x2,
9888+ DSI_PLL_POWER_ON_DIV = 0x3,
9889+};
9890+
9891+static int dsi_pll_power(enum dsi_pll_power_state state)
9892+{
9893+ int t = 0;
9894+
9895+ REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30); /* PLL_PWR_CMD */
9896+
9897+ /* PLL_PWR_STATUS */
9898+ while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) {
9899+ udelay(1);
9900+ if (t++ > 1000) {
9901+ DSSERR("Failed to set DSI PLL power mode to %d\n",
9902+ state);
9903+ return -ENODEV;
9904+ }
9905+ }
9906+
9907+ return 0;
9908+}
9909+
9910+int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck,
9911+ struct dsi_clock_info *cinfo)
9912+{
9913+ struct dsi_clock_info cur, best;
9914+ int min_fck_per_pck;
9915+ int match = 0;
9916+ unsigned long dss_clk_fck2;
9917+
9918+ dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2);
9919+
9920+ if (req_pck == dsi.cache_req_pck &&
9921+ dsi.cache_cinfo.clkin == dss_clk_fck2) {
9922+ DSSDBG("DSI clock info found from cache\n");
9923+ *cinfo = dsi.cache_cinfo;
9924+ return 0;
9925+ }
9926+
9927+ min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
9928+
9929+ if (min_fck_per_pck &&
9930+ req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
9931+ DSSERR("Requested pixel clock not possible with the current "
9932+ "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
9933+ "the constraint off.\n");
9934+ min_fck_per_pck = 0;
9935+ }
9936+
9937+ DSSDBG("dsi_pll_calc\n");
9938+
9939+retry:
9940+ memset(&best, 0, sizeof(best));
9941+
9942+ memset(&cur, 0, sizeof(cur));
9943+ cur.clkin = dss_clk_fck2;
9944+ cur.use_dss2_fck = 1;
9945+ cur.highfreq = 0;
9946+
9947+ /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
9948+ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
9949+ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
9950+ for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
9951+ if (cur.highfreq == 0)
9952+ cur.fint = cur.clkin / cur.regn;
9953+ else
9954+ cur.fint = cur.clkin / (2 * cur.regn);
9955+
9956+ if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
9957+ continue;
9958+
9959+ /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
9960+ for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
9961+ unsigned long a, b;
9962+
9963+ a = 2 * cur.regm * (cur.clkin/1000);
9964+ b = cur.regn * (cur.highfreq + 1);
9965+ cur.dsiphy = a / b * 1000;
9966+
9967+ if (cur.dsiphy > 1800 * 1000 * 1000)
9968+ break;
9969+
9970+ /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */
9971+ for (cur.regm3 = 1; cur.regm3 < REGM3_MAX;
9972+ ++cur.regm3) {
9973+ cur.dsi1_pll_fclk = cur.dsiphy / cur.regm3;
9974+
9975+ /* this will narrow down the search a bit,
9976+ * but still give pixclocks below what was
9977+ * requested */
9978+ if (cur.dsi1_pll_fclk < req_pck)
9979+ break;
9980+
9981+ if (cur.dsi1_pll_fclk > DISPC_MAX_FCK)
9982+ continue;
9983+
9984+ if (min_fck_per_pck &&
9985+ cur.dsi1_pll_fclk <
9986+ req_pck * min_fck_per_pck)
9987+ continue;
9988+
9989+ match = 1;
9990+
9991+ find_lck_pck_divs(is_tft, req_pck,
9992+ cur.dsi1_pll_fclk,
9993+ &cur.lck_div,
9994+ &cur.pck_div);
9995+
9996+ cur.lck = cur.dsi1_pll_fclk / cur.lck_div;
9997+ cur.pck = cur.lck / cur.pck_div;
9998+
9999+ if (abs(cur.pck - req_pck) <
10000+ abs(best.pck - req_pck)) {
10001+ best = cur;
10002+
10003+ if (cur.pck == req_pck)
10004+ goto found;
10005+ }
10006+ }
10007+ }
10008+ }
10009+found:
10010+ if (!match) {
10011+ if (min_fck_per_pck) {
10012+ DSSERR("Could not find suitable clock settings.\n"
10013+ "Turning FCK/PCK constraint off and"
10014+ "trying again.\n");
10015+ min_fck_per_pck = 0;
10016+ goto retry;
10017+ }
10018+
10019+ DSSERR("Could not find suitable clock settings.\n");
10020+
10021+ return -EINVAL;
10022+ }
10023+
10024+ /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */
10025+ best.regm4 = best.dsiphy / 48000000;
10026+ if (best.regm4 > REGM4_MAX)
10027+ best.regm4 = REGM4_MAX;
10028+ else if (best.regm4 == 0)
10029+ best.regm4 = 1;
10030+ best.dsi2_pll_fclk = best.dsiphy / best.regm4;
10031+
10032+ if (cinfo)
10033+ *cinfo = best;
10034+
10035+ dsi.cache_req_pck = req_pck;
10036+ dsi.cache_clk_freq = 0;
10037+ dsi.cache_cinfo = best;
10038+
10039+ return 0;
10040+}
10041+
10042+static int dsi_pll_calc_ddrfreq(unsigned long clk_freq,
10043+ struct dsi_clock_info *cinfo)
10044+{
10045+ struct dsi_clock_info cur, best;
10046+ const bool use_dss2_fck = 1;
10047+ unsigned long datafreq;
10048+ unsigned long dss_clk_fck2;
10049+
10050+ DSSDBG("dsi_pll_calc_ddrfreq\n");
10051+
10052+ dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2);
10053+
10054+ if (clk_freq == dsi.cache_clk_freq &&
10055+ dsi.cache_cinfo.clkin == dss_clk_fck2) {
10056+ DSSDBG("DSI clock info found from cache\n");
10057+ *cinfo = dsi.cache_cinfo;
10058+ return 0;
10059+ }
10060+
10061+ datafreq = clk_freq * 4;
10062+
10063+ memset(&best, 0, sizeof(best));
10064+
10065+ memset(&cur, 0, sizeof(cur));
10066+ cur.use_dss2_fck = use_dss2_fck;
10067+ if (use_dss2_fck) {
10068+ cur.clkin = dss_clk_fck2;
10069+ cur.highfreq = 0;
10070+ } else {
10071+ cur.clkin = dispc_pclk_rate();
10072+ if (cur.clkin < 32000000)
10073+ cur.highfreq = 0;
10074+ else
10075+ cur.highfreq = 1;
10076+ }
10077+
10078+ /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
10079+ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
10080+ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
10081+ for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
10082+ if (cur.highfreq == 0)
10083+ cur.fint = cur.clkin / cur.regn;
10084+ else
10085+ cur.fint = cur.clkin / (2 * cur.regn);
10086+
10087+ if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
10088+ continue;
10089+
10090+ /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
10091+ for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
10092+ unsigned long a, b;
10093+
10094+ a = 2 * cur.regm * (cur.clkin/1000);
10095+ b = cur.regn * (cur.highfreq + 1);
10096+ cur.dsiphy = a / b * 1000;
10097+
10098+ if (cur.dsiphy > 1800 * 1000 * 1000)
10099+ break;
10100+
10101+ if (abs(cur.dsiphy - datafreq) <
10102+ abs(best.dsiphy - datafreq)) {
10103+ best = cur;
10104+ /* DSSDBG("best %ld\n", best.dsiphy); */
10105+ }
10106+
10107+ if (cur.dsiphy == datafreq)
10108+ goto found;
10109+ }
10110+ }
10111+found:
10112+ /* DSI1_PLL_FCLK (regm3) is not used. Set it to something sane. */
10113+ best.regm3 = best.dsiphy / 48000000;
10114+ if (best.regm3 > REGM3_MAX)
10115+ best.regm3 = REGM3_MAX;
10116+ else if (best.regm3 == 0)
10117+ best.regm3 = 1;
10118+ best.dsi1_pll_fclk = best.dsiphy / best.regm3;
10119+
10120+ /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */
10121+ best.regm4 = best.dsiphy / 48000000;
10122+ if (best.regm4 > REGM4_MAX)
10123+ best.regm4 = REGM4_MAX;
10124+ else if (best.regm4 == 0)
10125+ best.regm4 = 1;
10126+ best.dsi2_pll_fclk = best.dsiphy / best.regm4;
10127+
10128+ if (cinfo)
10129+ *cinfo = best;
10130+
10131+ dsi.cache_clk_freq = clk_freq;
10132+ dsi.cache_req_pck = 0;
10133+ dsi.cache_cinfo = best;
10134+
10135+ return 0;
10136+}
10137+
10138+int dsi_pll_program(struct dsi_clock_info *cinfo)
10139+{
10140+ int r = 0;
10141+ u32 l;
10142+
10143+ DSSDBG("dsi_pll_program\n");
10144+
10145+ dsi.dsiphy = cinfo->dsiphy;
10146+ dsi.ddr_clk = dsi.dsiphy / 4;
10147+ dsi.dsi1_pll_fclk = cinfo->dsi1_pll_fclk;
10148+ dsi.dsi2_pll_fclk = cinfo->dsi2_pll_fclk;
10149+
10150+ DSSDBG("DSI Fint %ld\n", cinfo->fint);
10151+
10152+ DSSDBG("clkin (%s) rate %ld, highfreq %d\n",
10153+ cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree",
10154+ cinfo->clkin,
10155+ cinfo->highfreq);
10156+
10157+ /* DSIPHY == CLKIN4DDR */
10158+ DSSDBG("DSIPHY = 2 * %d / %d * %lu / %d = %lu\n",
10159+ cinfo->regm,
10160+ cinfo->regn,
10161+ cinfo->clkin,
10162+ cinfo->highfreq + 1,
10163+ cinfo->dsiphy);
10164+
10165+ DSSDBG("Data rate on 1 DSI lane %ld Mbps\n",
10166+ dsi.dsiphy / 1000 / 1000 / 2);
10167+
10168+ DSSDBG("Clock lane freq %ld Hz\n", dsi.ddr_clk);
10169+
10170+ DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n",
10171+ cinfo->regm3, cinfo->dsi1_pll_fclk);
10172+ DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n",
10173+ cinfo->regm4, cinfo->dsi2_pll_fclk);
10174+
10175+ REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */
10176+
10177+ l = dsi_read_reg(DSI_PLL_CONFIGURATION1);
10178+ l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */
10179+ l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */
10180+ l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */
10181+ l = FLD_MOD(l, cinfo->regm3 - 1, 22, 19); /* DSI_CLOCK_DIV */
10182+ l = FLD_MOD(l, cinfo->regm4 - 1, 26, 23); /* DSIPROTO_CLOCK_DIV */
10183+ dsi_write_reg(DSI_PLL_CONFIGURATION1, l);
10184+
10185+ l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
10186+ l = FLD_MOD(l, 7, 4, 1); /* DSI_PLL_FREQSEL */
10187+ /* DSI_PLL_CLKSEL */
10188+ l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1, 11, 11);
10189+ l = FLD_MOD(l, cinfo->highfreq, 12, 12); /* DSI_PLL_HIGHFREQ */
10190+ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
10191+ l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
10192+ l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
10193+ dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
10194+
10195+ REG_FLD_MOD(DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
10196+
10197+ if (wait_for_bit_change(DSI_PLL_GO, 0, 0) != 0) {
10198+ DSSERR("dsi pll go bit not going down.\n");
10199+ r = -EIO;
10200+ goto err;
10201+ }
10202+
10203+ if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) {
10204+ DSSERR("cannot lock PLL\n");
10205+ r = -EIO;
10206+ goto err;
10207+ }
10208+
10209+ dsi.pll_locked = 1;
10210+
10211+ l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
10212+ l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */
10213+ l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */
10214+ l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */
10215+ l = FLD_MOD(l, 0, 7, 7); /* DSI_PLL_TIGHTPHASELOCK */
10216+ l = FLD_MOD(l, 0, 8, 8); /* DSI_PLL_DRIFTGUARDEN */
10217+ l = FLD_MOD(l, 0, 10, 9); /* DSI_PLL_LOCKSEL */
10218+ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
10219+ l = FLD_MOD(l, 1, 14, 14); /* DSIPHY_CLKINEN */
10220+ l = FLD_MOD(l, 0, 15, 15); /* DSI_BYPASSEN */
10221+ l = FLD_MOD(l, 1, 16, 16); /* DSS_CLOCK_EN */
10222+ l = FLD_MOD(l, 0, 17, 17); /* DSS_CLOCK_PWDN */
10223+ l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */
10224+ l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */
10225+ l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */
10226+ dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
10227+
10228+ DSSDBG("PLL config done\n");
10229+err:
10230+ return r;
10231+}
10232+
10233+int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv)
10234+{
10235+ int r = 0;
10236+ enum dsi_pll_power_state pwstate;
10237+ struct dispc_clock_info cinfo;
10238+
10239+ DSSDBG("PLL init\n");
10240+
10241+ enable_clocks(1);
10242+ dsi_enable_pll_clock(1);
10243+
10244+ /* XXX this should be calculated depending on the screen size,
10245+ * required framerate and DSI speed.
10246+ * For now 48MHz is enough for 864x480@60 with 360Mbps/lane
10247+ * with two lanes */
10248+ r = dispc_calc_clock_div(1, 48 * 1000 * 1000, &cinfo);
10249+ if (r)
10250+ goto err0;
10251+
10252+ r = dispc_set_clock_div(&cinfo);
10253+ if (r) {
10254+ DSSERR("Failed to set basic clocks\n");
10255+ goto err0;
10256+ }
10257+
10258+ r = regulator_enable(dsi.vdds_dsi_reg);
10259+ if (r)
10260+ goto err0;
10261+
10262+ /* XXX PLL does not come out of reset without this... */
10263+ dispc_pck_free_enable(1);
10264+
10265+ if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) {
10266+ DSSERR("PLL not coming out of reset.\n");
10267+ r = -ENODEV;
10268+ goto err1;
10269+ }
10270+
10271+ /* XXX ... but if left on, we get problems when planes do not
10272+ * fill the whole display. No idea about this */
10273+ dispc_pck_free_enable(0);
10274+
10275+ if (enable_hsclk && enable_hsdiv)
10276+ pwstate = DSI_PLL_POWER_ON_ALL;
10277+ else if (enable_hsclk)
10278+ pwstate = DSI_PLL_POWER_ON_HSCLK;
10279+ else if (enable_hsdiv)
10280+ pwstate = DSI_PLL_POWER_ON_DIV;
10281+ else
10282+ pwstate = DSI_PLL_POWER_OFF;
10283+
10284+ r = dsi_pll_power(pwstate);
10285+
10286+ if (r)
10287+ goto err1;
10288+
10289+ DSSDBG("PLL init done\n");
10290+
10291+ return 0;
10292+err1:
10293+ regulator_disable(dsi.vdds_dsi_reg);
10294+err0:
10295+ enable_clocks(0);
10296+ dsi_enable_pll_clock(0);
10297+ return r;
10298+}
10299+
10300+void dsi_pll_uninit(void)
10301+{
10302+ enable_clocks(0);
10303+ dsi_enable_pll_clock(0);
10304+
10305+ dsi.pll_locked = 0;
10306+ dsi_pll_power(DSI_PLL_POWER_OFF);
10307+ regulator_disable(dsi.vdds_dsi_reg);
10308+ DSSDBG("PLL uninit done\n");
10309+}
10310+
10311+unsigned long dsi_get_dsi1_pll_rate(void)
10312+{
10313+ return dsi.dsi1_pll_fclk;
10314+}
10315+
10316+unsigned long dsi_get_dsi2_pll_rate(void)
10317+{
10318+ return dsi.dsi2_pll_fclk;
10319+}
10320+
10321+void dsi_dump_clocks(struct seq_file *s)
10322+{
10323+ int clksel;
10324+
10325+ enable_clocks(1);
10326+
10327+ clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11);
10328+
10329+ seq_printf(s, "- dsi -\n");
10330+
10331+ seq_printf(s, "dsi fclk source = %s\n",
10332+ dss_get_dsi_clk_source() == 0 ?
10333+ "dss1_alwon_fclk" : "dsi2_pll_fclk");
10334+
10335+ seq_printf(s, "dsi pll source = %s\n",
10336+ clksel == 0 ?
10337+ "dss2_alwon_fclk" : "pclkfree");
10338+
10339+ seq_printf(s, "DSIPHY\t\t%lu\nDDR_CLK\t\t%lu\n",
10340+ dsi.dsiphy, dsi.ddr_clk);
10341+
10342+ seq_printf(s, "dsi1_pll_fck\t%lu (%s)\n"
10343+ "dsi2_pll_fck\t%lu (%s)\n",
10344+ dsi.dsi1_pll_fclk,
10345+ dss_get_dispc_clk_source() == 0 ? "off" : "on",
10346+ dsi.dsi2_pll_fclk,
10347+ dss_get_dsi_clk_source() == 0 ? "off" : "on");
10348+
10349+ enable_clocks(0);
10350+}
10351+
10352+void dsi_dump_regs(struct seq_file *s)
10353+{
10354+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r))
10355+
10356+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
10357+
10358+ DUMPREG(DSI_REVISION);
10359+ DUMPREG(DSI_SYSCONFIG);
10360+ DUMPREG(DSI_SYSSTATUS);
10361+ DUMPREG(DSI_IRQSTATUS);
10362+ DUMPREG(DSI_IRQENABLE);
10363+ DUMPREG(DSI_CTRL);
10364+ DUMPREG(DSI_COMPLEXIO_CFG1);
10365+ DUMPREG(DSI_COMPLEXIO_IRQ_STATUS);
10366+ DUMPREG(DSI_COMPLEXIO_IRQ_ENABLE);
10367+ DUMPREG(DSI_CLK_CTRL);
10368+ DUMPREG(DSI_TIMING1);
10369+ DUMPREG(DSI_TIMING2);
10370+ DUMPREG(DSI_VM_TIMING1);
10371+ DUMPREG(DSI_VM_TIMING2);
10372+ DUMPREG(DSI_VM_TIMING3);
10373+ DUMPREG(DSI_CLK_TIMING);
10374+ DUMPREG(DSI_TX_FIFO_VC_SIZE);
10375+ DUMPREG(DSI_RX_FIFO_VC_SIZE);
10376+ DUMPREG(DSI_COMPLEXIO_CFG2);
10377+ DUMPREG(DSI_RX_FIFO_VC_FULLNESS);
10378+ DUMPREG(DSI_VM_TIMING4);
10379+ DUMPREG(DSI_TX_FIFO_VC_EMPTINESS);
10380+ DUMPREG(DSI_VM_TIMING5);
10381+ DUMPREG(DSI_VM_TIMING6);
10382+ DUMPREG(DSI_VM_TIMING7);
10383+ DUMPREG(DSI_STOPCLK_TIMING);
10384+
10385+ DUMPREG(DSI_VC_CTRL(0));
10386+ DUMPREG(DSI_VC_TE(0));
10387+ DUMPREG(DSI_VC_LONG_PACKET_HEADER(0));
10388+ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(0));
10389+ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(0));
10390+ DUMPREG(DSI_VC_IRQSTATUS(0));
10391+ DUMPREG(DSI_VC_IRQENABLE(0));
10392+
10393+ DUMPREG(DSI_VC_CTRL(1));
10394+ DUMPREG(DSI_VC_TE(1));
10395+ DUMPREG(DSI_VC_LONG_PACKET_HEADER(1));
10396+ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(1));
10397+ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(1));
10398+ DUMPREG(DSI_VC_IRQSTATUS(1));
10399+ DUMPREG(DSI_VC_IRQENABLE(1));
10400+
10401+ DUMPREG(DSI_VC_CTRL(2));
10402+ DUMPREG(DSI_VC_TE(2));
10403+ DUMPREG(DSI_VC_LONG_PACKET_HEADER(2));
10404+ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(2));
10405+ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(2));
10406+ DUMPREG(DSI_VC_IRQSTATUS(2));
10407+ DUMPREG(DSI_VC_IRQENABLE(2));
10408+
10409+ DUMPREG(DSI_VC_CTRL(3));
10410+ DUMPREG(DSI_VC_TE(3));
10411+ DUMPREG(DSI_VC_LONG_PACKET_HEADER(3));
10412+ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(3));
10413+ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(3));
10414+ DUMPREG(DSI_VC_IRQSTATUS(3));
10415+ DUMPREG(DSI_VC_IRQENABLE(3));
10416+
10417+ DUMPREG(DSI_DSIPHY_CFG0);
10418+ DUMPREG(DSI_DSIPHY_CFG1);
10419+ DUMPREG(DSI_DSIPHY_CFG2);
10420+ DUMPREG(DSI_DSIPHY_CFG5);
10421+
10422+ DUMPREG(DSI_PLL_CONTROL);
10423+ DUMPREG(DSI_PLL_STATUS);
10424+ DUMPREG(DSI_PLL_GO);
10425+ DUMPREG(DSI_PLL_CONFIGURATION1);
10426+ DUMPREG(DSI_PLL_CONFIGURATION2);
10427+
10428+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
10429+#undef DUMPREG
10430+}
10431+
10432+enum dsi_complexio_power_state {
10433+ DSI_COMPLEXIO_POWER_OFF = 0x0,
10434+ DSI_COMPLEXIO_POWER_ON = 0x1,
10435+ DSI_COMPLEXIO_POWER_ULPS = 0x2,
10436+};
10437+
10438+static int dsi_complexio_power(enum dsi_complexio_power_state state)
10439+{
10440+ int t = 0;
10441+
10442+ /* PWR_CMD */
10443+ REG_FLD_MOD(DSI_COMPLEXIO_CFG1, state, 28, 27);
10444+
10445+ /* PWR_STATUS */
10446+ while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) {
10447+ udelay(1);
10448+ if (t++ > 1000) {
10449+ DSSERR("failed to set complexio power state to "
10450+ "%d\n", state);
10451+ return -ENODEV;
10452+ }
10453+ }
10454+
10455+ return 0;
10456+}
10457+
10458+static void dsi_complexio_config(struct omap_dss_device *dssdev)
10459+{
10460+ u32 r;
10461+
10462+ int clk_lane = dssdev->phy.dsi.clk_lane;
10463+ int data1_lane = dssdev->phy.dsi.data1_lane;
10464+ int data2_lane = dssdev->phy.dsi.data2_lane;
10465+ int clk_pol = dssdev->phy.dsi.clk_pol;
10466+ int data1_pol = dssdev->phy.dsi.data1_pol;
10467+ int data2_pol = dssdev->phy.dsi.data2_pol;
10468+
10469+ r = dsi_read_reg(DSI_COMPLEXIO_CFG1);
10470+ r = FLD_MOD(r, clk_lane, 2, 0);
10471+ r = FLD_MOD(r, clk_pol, 3, 3);
10472+ r = FLD_MOD(r, data1_lane, 6, 4);
10473+ r = FLD_MOD(r, data1_pol, 7, 7);
10474+ r = FLD_MOD(r, data2_lane, 10, 8);
10475+ r = FLD_MOD(r, data2_pol, 11, 11);
10476+ dsi_write_reg(DSI_COMPLEXIO_CFG1, r);
10477+
10478+ /* The configuration of the DSI complex I/O (number of data lanes,
10479+ position, differential order) should not be changed while
10480+ DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for
10481+ the hardware to take into account a new configuration of the complex
10482+ I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to
10483+ follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1,
10484+ then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set
10485+ DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the
10486+ DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the
10487+ DSI complex I/O configuration is unknown. */
10488+
10489+ /*
10490+ REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
10491+ REG_FLD_MOD(DSI_CTRL, 0, 0, 0);
10492+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20);
10493+ REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
10494+ */
10495+}
10496+
10497+static inline unsigned ns2ddr(unsigned ns)
10498+{
10499+ /* convert time in ns to ddr ticks, rounding up */
10500+ return (ns * (dsi.ddr_clk/1000/1000) + 999) / 1000;
10501+}
10502+
10503+static inline unsigned ddr2ns(unsigned ddr)
10504+{
10505+ return ddr * 1000 * 1000 / (dsi.ddr_clk / 1000);
10506+}
10507+
10508+static void dsi_complexio_timings(void)
10509+{
10510+ u32 r;
10511+ u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
10512+ u32 tlpx_half, tclk_trail, tclk_zero;
10513+ u32 tclk_prepare;
10514+
10515+ /* calculate timings */
10516+
10517+ /* 1 * DDR_CLK = 2 * UI */
10518+
10519+ /* min 40ns + 4*UI max 85ns + 6*UI */
10520+ ths_prepare = ns2ddr(70) + 2;
10521+
10522+ /* min 145ns + 10*UI */
10523+ ths_prepare_ths_zero = ns2ddr(175) + 2;
10524+
10525+ /* min max(8*UI, 60ns+4*UI) */
10526+ ths_trail = ns2ddr(60) + 5;
10527+
10528+ /* min 100ns */
10529+ ths_exit = ns2ddr(145);
10530+
10531+ /* tlpx min 50n */
10532+ tlpx_half = ns2ddr(25);
10533+
10534+ /* min 60ns */
10535+ tclk_trail = ns2ddr(60) + 2;
10536+
10537+ /* min 38ns, max 95ns */
10538+ tclk_prepare = ns2ddr(65);
10539+
10540+ /* min tclk-prepare + tclk-zero = 300ns */
10541+ tclk_zero = ns2ddr(260);
10542+
10543+ DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n",
10544+ ths_prepare, ddr2ns(ths_prepare),
10545+ ths_prepare_ths_zero, ddr2ns(ths_prepare_ths_zero));
10546+ DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n",
10547+ ths_trail, ddr2ns(ths_trail),
10548+ ths_exit, ddr2ns(ths_exit));
10549+
10550+ DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), "
10551+ "tclk_zero %u (%uns)\n",
10552+ tlpx_half, ddr2ns(tlpx_half),
10553+ tclk_trail, ddr2ns(tclk_trail),
10554+ tclk_zero, ddr2ns(tclk_zero));
10555+ DSSDBG("tclk_prepare %u (%uns)\n",
10556+ tclk_prepare, ddr2ns(tclk_prepare));
10557+
10558+ /* program timings */
10559+
10560+ r = dsi_read_reg(DSI_DSIPHY_CFG0);
10561+ r = FLD_MOD(r, ths_prepare, 31, 24);
10562+ r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16);
10563+ r = FLD_MOD(r, ths_trail, 15, 8);
10564+ r = FLD_MOD(r, ths_exit, 7, 0);
10565+ dsi_write_reg(DSI_DSIPHY_CFG0, r);
10566+
10567+ r = dsi_read_reg(DSI_DSIPHY_CFG1);
10568+ r = FLD_MOD(r, tlpx_half, 22, 16);
10569+ r = FLD_MOD(r, tclk_trail, 15, 8);
10570+ r = FLD_MOD(r, tclk_zero, 7, 0);
10571+ dsi_write_reg(DSI_DSIPHY_CFG1, r);
10572+
10573+ r = dsi_read_reg(DSI_DSIPHY_CFG2);
10574+ r = FLD_MOD(r, tclk_prepare, 7, 0);
10575+ dsi_write_reg(DSI_DSIPHY_CFG2, r);
10576+}
10577+
10578+
10579+static int dsi_complexio_init(struct omap_dss_device *dssdev)
10580+{
10581+ int r = 0;
10582+
10583+ DSSDBG("dsi_complexio_init\n");
10584+
10585+ /* CIO_CLK_ICG, enable L3 clk to CIO */
10586+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
10587+
10588+ /* A dummy read using the SCP interface to any DSIPHY register is
10589+ * required after DSIPHY reset to complete the reset of the DSI complex
10590+ * I/O. */
10591+ dsi_read_reg(DSI_DSIPHY_CFG5);
10592+
10593+ if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) {
10594+ DSSERR("ComplexIO PHY not coming out of reset.\n");
10595+ r = -ENODEV;
10596+ goto err;
10597+ }
10598+
10599+ dsi_complexio_config(dssdev);
10600+
10601+ r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON);
10602+
10603+ if (r)
10604+ goto err;
10605+
10606+ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
10607+ DSSERR("ComplexIO not coming out of reset.\n");
10608+ r = -ENODEV;
10609+ goto err;
10610+ }
10611+
10612+ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
10613+ DSSERR("ComplexIO LDO power down.\n");
10614+ r = -ENODEV;
10615+ goto err;
10616+ }
10617+
10618+ dsi_complexio_timings();
10619+
10620+ /*
10621+ The configuration of the DSI complex I/O (number of data lanes,
10622+ position, differential order) should not be changed while
10623+ DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the
10624+ hardware to recognize a new configuration of the complex I/O (done
10625+ in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow
10626+ this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next
10627+ reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20]
10628+ LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN
10629+ bit to 1. If the sequence is not followed, the DSi complex I/O
10630+ configuration is undetermined.
10631+ */
10632+ dsi_if_enable(1);
10633+ dsi_if_enable(0);
10634+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
10635+ dsi_if_enable(1);
10636+ dsi_if_enable(0);
10637+
10638+ DSSDBG("CIO init done\n");
10639+err:
10640+ return r;
10641+}
10642+
10643+static void dsi_complexio_uninit(void)
10644+{
10645+ dsi_complexio_power(DSI_COMPLEXIO_POWER_OFF);
10646+}
10647+
10648+static int _dsi_wait_reset(void)
10649+{
10650+ int i = 0;
10651+
10652+ while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) {
10653+ if (i++ > 5) {
10654+ DSSERR("soft reset failed\n");
10655+ return -ENODEV;
10656+ }
10657+ udelay(1);
10658+ }
10659+
10660+ return 0;
10661+}
10662+
10663+static int _dsi_reset(void)
10664+{
10665+ /* Soft reset */
10666+ REG_FLD_MOD(DSI_SYSCONFIG, 1, 1, 1);
10667+ return _dsi_wait_reset();
10668+}
10669+
10670+
10671+static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2,
10672+ enum fifo_size size3, enum fifo_size size4)
10673+{
10674+ u32 r = 0;
10675+ int add = 0;
10676+ int i;
10677+
10678+ dsi.vc[0].fifo_size = size1;
10679+ dsi.vc[1].fifo_size = size2;
10680+ dsi.vc[2].fifo_size = size3;
10681+ dsi.vc[3].fifo_size = size4;
10682+
10683+ for (i = 0; i < 4; i++) {
10684+ u8 v;
10685+ int size = dsi.vc[i].fifo_size;
10686+
10687+ if (add + size > 4) {
10688+ DSSERR("Illegal FIFO configuration\n");
10689+ BUG();
10690+ }
10691+
10692+ v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
10693+ r |= v << (8 * i);
10694+ /*DSSDBG("TX FIFO vc %d: size %d, add %d\n", i, size, add); */
10695+ add += size;
10696+ }
10697+
10698+ dsi_write_reg(DSI_TX_FIFO_VC_SIZE, r);
10699+}
10700+
10701+static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2,
10702+ enum fifo_size size3, enum fifo_size size4)
10703+{
10704+ u32 r = 0;
10705+ int add = 0;
10706+ int i;
10707+
10708+ dsi.vc[0].fifo_size = size1;
10709+ dsi.vc[1].fifo_size = size2;
10710+ dsi.vc[2].fifo_size = size3;
10711+ dsi.vc[3].fifo_size = size4;
10712+
10713+ for (i = 0; i < 4; i++) {
10714+ u8 v;
10715+ int size = dsi.vc[i].fifo_size;
10716+
10717+ if (add + size > 4) {
10718+ DSSERR("Illegal FIFO configuration\n");
10719+ BUG();
10720+ }
10721+
10722+ v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
10723+ r |= v << (8 * i);
10724+ /*DSSDBG("RX FIFO vc %d: size %d, add %d\n", i, size, add); */
10725+ add += size;
10726+ }
10727+
10728+ dsi_write_reg(DSI_RX_FIFO_VC_SIZE, r);
10729+}
10730+
10731+static int dsi_force_tx_stop_mode_io(void)
10732+{
10733+ u32 r;
10734+
10735+ r = dsi_read_reg(DSI_TIMING1);
10736+ r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
10737+ dsi_write_reg(DSI_TIMING1, r);
10738+
10739+ if (wait_for_bit_change(DSI_TIMING1, 15, 0) != 0) {
10740+ DSSERR("TX_STOP bit not going down\n");
10741+ return -EIO;
10742+ }
10743+
10744+ return 0;
10745+}
10746+
10747+static void dsi_vc_print_status(int channel)
10748+{
10749+ u32 r;
10750+
10751+ r = dsi_read_reg(DSI_VC_CTRL(channel));
10752+ DSSDBG("vc %d: TX_FIFO_NOT_EMPTY %d, BTA_EN %d, VC_BUSY %d, "
10753+ "TX_FIFO_FULL %d, RX_FIFO_NOT_EMPTY %d, ",
10754+ channel,
10755+ FLD_GET(r, 5, 5),
10756+ FLD_GET(r, 6, 6),
10757+ FLD_GET(r, 15, 15),
10758+ FLD_GET(r, 16, 16),
10759+ FLD_GET(r, 20, 20));
10760+
10761+ r = dsi_read_reg(DSI_TX_FIFO_VC_EMPTINESS);
10762+ DSSDBG("EMPTINESS %d\n", (r >> (8 * channel)) & 0xff);
10763+}
10764+
10765+static int dsi_vc_enable(int channel, bool enable)
10766+{
10767+ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
10768+ DSSDBG("dsi_vc_enable channel %d, enable %d\n",
10769+ channel, enable);
10770+
10771+ enable = enable ? 1 : 0;
10772+
10773+ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0);
10774+
10775+ if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) {
10776+ DSSERR("Failed to set dsi_vc_enable to %d\n", enable);
10777+ return -EIO;
10778+ }
10779+
10780+ return 0;
10781+}
10782+
10783+static void dsi_vc_initial_config(int channel)
10784+{
10785+ u32 r;
10786+
10787+ DSSDBGF("%d", channel);
10788+
10789+ r = dsi_read_reg(DSI_VC_CTRL(channel));
10790+
10791+ if (FLD_GET(r, 15, 15)) /* VC_BUSY */
10792+ DSSERR("VC(%d) busy when trying to configure it!\n",
10793+ channel);
10794+
10795+ r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */
10796+ r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */
10797+ r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
10798+ r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
10799+ r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
10800+ r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
10801+ r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
10802+
10803+ r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
10804+ r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
10805+
10806+ dsi_write_reg(DSI_VC_CTRL(channel), r);
10807+
10808+ dsi.vc[channel].mode = DSI_VC_MODE_L4;
10809+}
10810+
10811+static void dsi_vc_config_l4(int channel)
10812+{
10813+ if (dsi.vc[channel].mode == DSI_VC_MODE_L4)
10814+ return;
10815+
10816+ DSSDBGF("%d", channel);
10817+
10818+ dsi_vc_enable(channel, 0);
10819+
10820+ if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */
10821+ DSSERR("vc(%d) busy when trying to config for L4\n", channel);
10822+
10823+ REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
10824+
10825+ dsi_vc_enable(channel, 1);
10826+
10827+ dsi.vc[channel].mode = DSI_VC_MODE_L4;
10828+}
10829+
10830+static void dsi_vc_config_vp(int channel)
10831+{
10832+ if (dsi.vc[channel].mode == DSI_VC_MODE_VP)
10833+ return;
10834+
10835+ DSSDBGF("%d", channel);
10836+
10837+ dsi_vc_enable(channel, 0);
10838+
10839+ if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */
10840+ DSSERR("vc(%d) busy when trying to config for VP\n", channel);
10841+
10842+ REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */
10843+
10844+ dsi_vc_enable(channel, 1);
10845+
10846+ dsi.vc[channel].mode = DSI_VC_MODE_VP;
10847+}
10848+
10849+
10850+static void dsi_vc_enable_hs(int channel, bool enable)
10851+{
10852+ DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
10853+
10854+ dsi_vc_enable(channel, 0);
10855+ dsi_if_enable(0);
10856+
10857+ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 9, 9);
10858+
10859+ dsi_vc_enable(channel, 1);
10860+ dsi_if_enable(1);
10861+
10862+ dsi_force_tx_stop_mode_io();
10863+}
10864+
10865+static void dsi_vc_flush_long_data(int channel)
10866+{
10867+ while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
10868+ u32 val;
10869+ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
10870+ DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n",
10871+ (val >> 0) & 0xff,
10872+ (val >> 8) & 0xff,
10873+ (val >> 16) & 0xff,
10874+ (val >> 24) & 0xff);
10875+ }
10876+}
10877+
10878+static void dsi_show_rx_ack_with_err(u16 err)
10879+{
10880+ DSSERR("\tACK with ERROR (%#x):\n", err);
10881+ if (err & (1 << 0))
10882+ DSSERR("\t\tSoT Error\n");
10883+ if (err & (1 << 1))
10884+ DSSERR("\t\tSoT Sync Error\n");
10885+ if (err & (1 << 2))
10886+ DSSERR("\t\tEoT Sync Error\n");
10887+ if (err & (1 << 3))
10888+ DSSERR("\t\tEscape Mode Entry Command Error\n");
10889+ if (err & (1 << 4))
10890+ DSSERR("\t\tLP Transmit Sync Error\n");
10891+ if (err & (1 << 5))
10892+ DSSERR("\t\tHS Receive Timeout Error\n");
10893+ if (err & (1 << 6))
10894+ DSSERR("\t\tFalse Control Error\n");
10895+ if (err & (1 << 7))
10896+ DSSERR("\t\t(reserved7)\n");
10897+ if (err & (1 << 8))
10898+ DSSERR("\t\tECC Error, single-bit (corrected)\n");
10899+ if (err & (1 << 9))
10900+ DSSERR("\t\tECC Error, multi-bit (not corrected)\n");
10901+ if (err & (1 << 10))
10902+ DSSERR("\t\tChecksum Error\n");
10903+ if (err & (1 << 11))
10904+ DSSERR("\t\tData type not recognized\n");
10905+ if (err & (1 << 12))
10906+ DSSERR("\t\tInvalid VC ID\n");
10907+ if (err & (1 << 13))
10908+ DSSERR("\t\tInvalid Transmission Length\n");
10909+ if (err & (1 << 14))
10910+ DSSERR("\t\t(reserved14)\n");
10911+ if (err & (1 << 15))
10912+ DSSERR("\t\tDSI Protocol Violation\n");
10913+}
10914+
10915+static u16 dsi_vc_flush_receive_data(int channel)
10916+{
10917+ /* RX_FIFO_NOT_EMPTY */
10918+ while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
10919+ u32 val;
10920+ u8 dt;
10921+ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
10922+ DSSDBG("\trawval %#08x\n", val);
10923+ dt = FLD_GET(val, 5, 0);
10924+ if (dt == DSI_DT_RX_ACK_WITH_ERR) {
10925+ u16 err = FLD_GET(val, 23, 8);
10926+ dsi_show_rx_ack_with_err(err);
10927+ } else if (dt == DSI_DT_RX_SHORT_READ_1) {
10928+ DSSDBG("\tDCS short response, 1 byte: %#x\n",
10929+ FLD_GET(val, 23, 8));
10930+ } else if (dt == DSI_DT_RX_SHORT_READ_2) {
10931+ DSSDBG("\tDCS short response, 2 byte: %#x\n",
10932+ FLD_GET(val, 23, 8));
10933+ } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
10934+ DSSDBG("\tDCS long response, len %d\n",
10935+ FLD_GET(val, 23, 8));
10936+ dsi_vc_flush_long_data(channel);
10937+ } else {
10938+ DSSERR("\tunknown datatype 0x%02x\n", dt);
10939+ }
10940+ }
10941+ return 0;
10942+}
10943+
10944+static int dsi_vc_send_bta(int channel)
10945+{
10946+ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO &&
10947+ (dsi.debug_write || dsi.debug_read))
10948+ DSSDBG("dsi_vc_send_bta %d\n", channel);
10949+
10950+ WARN_ON(!mutex_is_locked(&dsi.bus_lock));
10951+
10952+ if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */
10953+ DSSERR("rx fifo not empty when sending BTA, dumping data:\n");
10954+ dsi_vc_flush_receive_data(channel);
10955+ }
10956+
10957+ REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
10958+
10959+ return 0;
10960+}
10961+
10962+int dsi_vc_send_bta_sync(int channel)
10963+{
10964+ int r = 0;
10965+ u32 err;
10966+
10967+ INIT_COMPLETION(dsi.bta_completion);
10968+
10969+ dsi_vc_enable_bta_irq(channel);
10970+
10971+ r = dsi_vc_send_bta(channel);
10972+ if (r)
10973+ goto err;
10974+
10975+ if (wait_for_completion_timeout(&dsi.bta_completion,
10976+ msecs_to_jiffies(500)) == 0) {
10977+ DSSERR("Failed to receive BTA\n");
10978+ r = -EIO;
10979+ goto err;
10980+ }
10981+
10982+ err = dsi_get_errors();
10983+ if (err) {
10984+ DSSERR("Error while sending BTA: %x\n", err);
10985+ r = -EIO;
10986+ goto err;
10987+ }
10988+err:
10989+ dsi_vc_disable_bta_irq(channel);
10990+
10991+ return r;
10992+}
10993+EXPORT_SYMBOL(dsi_vc_send_bta_sync);
10994+
10995+static inline void dsi_vc_write_long_header(int channel, u8 data_type,
10996+ u16 len, u8 ecc)
10997+{
10998+ u32 val;
10999+ u8 data_id;
11000+
11001+ WARN_ON(!mutex_is_locked(&dsi.bus_lock));
11002+
11003+ /*data_id = data_type | channel << 6; */
11004+ data_id = data_type | dsi.vc[channel].dest_per << 6;
11005+
11006+ val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
11007+ FLD_VAL(ecc, 31, 24);
11008+
11009+ dsi_write_reg(DSI_VC_LONG_PACKET_HEADER(channel), val);
11010+}
11011+
11012+static inline void dsi_vc_write_long_payload(int channel,
11013+ u8 b1, u8 b2, u8 b3, u8 b4)
11014+{
11015+ u32 val;
11016+
11017+ val = b4 << 24 | b3 << 16 | b2 << 8 | b1 << 0;
11018+
11019+/* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n",
11020+ b1, b2, b3, b4, val); */
11021+
11022+ dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(channel), val);
11023+}
11024+
11025+static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len,
11026+ u8 ecc)
11027+{
11028+ /*u32 val; */
11029+ int i;
11030+ u8 *p;
11031+ int r = 0;
11032+ u8 b1, b2, b3, b4;
11033+
11034+ if (dsi.debug_write)
11035+ DSSDBG("dsi_vc_send_long, %d bytes\n", len);
11036+
11037+ /* len + header */
11038+ if (dsi.vc[channel].fifo_size * 32 * 4 < len + 4) {
11039+ DSSERR("unable to send long packet: packet too long.\n");
11040+ return -EINVAL;
11041+ }
11042+
11043+ dsi_vc_config_l4(channel);
11044+
11045+ dsi_vc_write_long_header(channel, data_type, len, ecc);
11046+
11047+ /*dsi_vc_print_status(0); */
11048+
11049+ p = data;
11050+ for (i = 0; i < len >> 2; i++) {
11051+ if (dsi.debug_write)
11052+ DSSDBG("\tsending full packet %d\n", i);
11053+ /*dsi_vc_print_status(0); */
11054+
11055+ b1 = *p++;
11056+ b2 = *p++;
11057+ b3 = *p++;
11058+ b4 = *p++;
11059+
11060+ dsi_vc_write_long_payload(channel, b1, b2, b3, b4);
11061+ }
11062+
11063+ i = len % 4;
11064+ if (i) {
11065+ b1 = 0; b2 = 0; b3 = 0;
11066+
11067+ if (dsi.debug_write)
11068+ DSSDBG("\tsending remainder bytes %d\n", i);
11069+
11070+ switch (i) {
11071+ case 3:
11072+ b1 = *p++;
11073+ b2 = *p++;
11074+ b3 = *p++;
11075+ break;
11076+ case 2:
11077+ b1 = *p++;
11078+ b2 = *p++;
11079+ break;
11080+ case 1:
11081+ b1 = *p++;
11082+ break;
11083+ }
11084+
11085+ dsi_vc_write_long_payload(channel, b1, b2, b3, 0);
11086+ }
11087+
11088+ return r;
11089+}
11090+
11091+static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc)
11092+{
11093+ u32 r;
11094+ u8 data_id;
11095+
11096+ WARN_ON(!mutex_is_locked(&dsi.bus_lock));
11097+
11098+ if (dsi.debug_write)
11099+ DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
11100+ channel,
11101+ data_type, data & 0xff, (data >> 8) & 0xff);
11102+
11103+ dsi_vc_config_l4(channel);
11104+
11105+ if (FLD_GET(dsi_read_reg(DSI_VC_CTRL(channel)), 16, 16)) {
11106+ DSSERR("ERROR FIFO FULL, aborting transfer\n");
11107+ return -EINVAL;
11108+ }
11109+
11110+ data_id = data_type | channel << 6;
11111+
11112+ r = (data_id << 0) | (data << 8) | (ecc << 24);
11113+
11114+ dsi_write_reg(DSI_VC_SHORT_PACKET_HEADER(channel), r);
11115+
11116+ return 0;
11117+}
11118+
11119+int dsi_vc_send_null(int channel)
11120+{
11121+ u8 nullpkg[] = {0, 0, 0, 0};
11122+ return dsi_vc_send_long(0, DSI_DT_NULL_PACKET, nullpkg, 4, 0);
11123+}
11124+EXPORT_SYMBOL(dsi_vc_send_null);
11125+
11126+int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len)
11127+{
11128+ int r;
11129+
11130+ BUG_ON(len == 0);
11131+
11132+ if (len == 1) {
11133+ r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_0,
11134+ data[0], 0);
11135+ } else if (len == 2) {
11136+ r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_1,
11137+ data[0] | (data[1] << 8), 0);
11138+ } else {
11139+ /* 0x39 = DCS Long Write */
11140+ r = dsi_vc_send_long(channel, DSI_DT_DCS_LONG_WRITE,
11141+ data, len, 0);
11142+ }
11143+
11144+ return r;
11145+}
11146+EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
11147+
11148+int dsi_vc_dcs_write(int channel, u8 *data, int len)
11149+{
11150+ int r;
11151+
11152+ r = dsi_vc_dcs_write_nosync(channel, data, len);
11153+ if (r)
11154+ return r;
11155+
11156+ r = dsi_vc_send_bta_sync(channel);
11157+
11158+ return r;
11159+}
11160+EXPORT_SYMBOL(dsi_vc_dcs_write);
11161+
11162+int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
11163+{
11164+ u32 val;
11165+ u8 dt;
11166+ int r;
11167+
11168+ if (dsi.debug_read)
11169+ DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %u)\n", channel, dcs_cmd);
11170+
11171+ r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0);
11172+ if (r)
11173+ return r;
11174+
11175+ r = dsi_vc_send_bta_sync(channel);
11176+ if (r)
11177+ return r;
11178+
11179+ /* RX_FIFO_NOT_EMPTY */
11180+ if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) {
11181+ DSSERR("RX fifo empty when trying to read.\n");
11182+ return -EIO;
11183+ }
11184+
11185+ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
11186+ if (dsi.debug_read)
11187+ DSSDBG("\theader: %08x\n", val);
11188+ dt = FLD_GET(val, 5, 0);
11189+ if (dt == DSI_DT_RX_ACK_WITH_ERR) {
11190+ u16 err = FLD_GET(val, 23, 8);
11191+ dsi_show_rx_ack_with_err(err);
11192+ return -EIO;
11193+
11194+ } else if (dt == DSI_DT_RX_SHORT_READ_1) {
11195+ u8 data = FLD_GET(val, 15, 8);
11196+ if (dsi.debug_read)
11197+ DSSDBG("\tDCS short response, 1 byte: %02x\n", data);
11198+
11199+ if (buflen < 1)
11200+ return -EIO;
11201+
11202+ buf[0] = data;
11203+
11204+ return 1;
11205+ } else if (dt == DSI_DT_RX_SHORT_READ_2) {
11206+ u16 data = FLD_GET(val, 23, 8);
11207+ if (dsi.debug_read)
11208+ DSSDBG("\tDCS short response, 2 byte: %04x\n", data);
11209+
11210+ if (buflen < 2)
11211+ return -EIO;
11212+
11213+ buf[0] = data & 0xff;
11214+ buf[1] = (data >> 8) & 0xff;
11215+
11216+ return 2;
11217+ } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
11218+ int w;
11219+ int len = FLD_GET(val, 23, 8);
11220+ if (dsi.debug_read)
11221+ DSSDBG("\tDCS long response, len %d\n", len);
11222+
11223+ if (len > buflen)
11224+ return -EIO;
11225+
11226+ /* two byte checksum ends the packet, not included in len */
11227+ for (w = 0; w < len + 2;) {
11228+ int b;
11229+ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
11230+ if (dsi.debug_read)
11231+ DSSDBG("\t\t%02x %02x %02x %02x\n",
11232+ (val >> 0) & 0xff,
11233+ (val >> 8) & 0xff,
11234+ (val >> 16) & 0xff,
11235+ (val >> 24) & 0xff);
11236+
11237+ for (b = 0; b < 4; ++b) {
11238+ if (w < len)
11239+ buf[w] = (val >> (b * 8)) & 0xff;
11240+ /* we discard the 2 byte checksum */
11241+ ++w;
11242+ }
11243+ }
11244+
11245+ return len;
11246+
11247+ } else {
11248+ DSSERR("\tunknown datatype 0x%02x\n", dt);
11249+ return -EIO;
11250+ }
11251+}
11252+EXPORT_SYMBOL(dsi_vc_dcs_read);
11253+
11254+
11255+int dsi_vc_set_max_rx_packet_size(int channel, u16 len)
11256+{
11257+ return dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
11258+ len, 0);
11259+}
11260+EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
11261+
11262+
11263+static int dsi_set_lp_rx_timeout(int ns, int x4, int x16)
11264+{
11265+ u32 r;
11266+ unsigned long fck;
11267+ int ticks;
11268+
11269+ /* ticks in DSI_FCK */
11270+
11271+ fck = dsi_fclk_rate();
11272+ ticks = (fck / 1000 / 1000) * ns / 1000;
11273+
11274+ if (ticks > 0x1fff) {
11275+ DSSERR("LP_TX_TO too high\n");
11276+ return -EINVAL;
11277+ }
11278+
11279+ r = dsi_read_reg(DSI_TIMING2);
11280+ r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */
11281+ r = FLD_MOD(r, x16, 14, 14); /* LP_RX_TO_X16 */
11282+ r = FLD_MOD(r, x4, 13, 13); /* LP_RX_TO_X4 */
11283+ r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */
11284+ dsi_write_reg(DSI_TIMING2, r);
11285+
11286+ DSSDBG("LP_RX_TO %ld ns (%#x ticks)\n",
11287+ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
11288+ (fck / 1000 / 1000),
11289+ ticks);
11290+
11291+ return 0;
11292+}
11293+
11294+static int dsi_set_ta_timeout(int ns, int x8, int x16)
11295+{
11296+ u32 r;
11297+ unsigned long fck;
11298+ int ticks;
11299+
11300+ /* ticks in DSI_FCK */
11301+
11302+ fck = dsi_fclk_rate();
11303+ ticks = (fck / 1000 / 1000) * ns / 1000;
11304+
11305+ if (ticks > 0x1fff) {
11306+ DSSERR("TA_TO too high\n");
11307+ return -EINVAL;
11308+ }
11309+
11310+ r = dsi_read_reg(DSI_TIMING1);
11311+ r = FLD_MOD(r, 1, 31, 31); /* TA_TO */
11312+ r = FLD_MOD(r, x16, 30, 30); /* TA_TO_X16 */
11313+ r = FLD_MOD(r, x8, 29, 29); /* TA_TO_X8 */
11314+ r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */
11315+ dsi_write_reg(DSI_TIMING1, r);
11316+
11317+ DSSDBG("TA_TO %ld ns (%#x ticks)\n",
11318+ (ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1) * 1000) /
11319+ (fck / 1000 / 1000),
11320+ ticks);
11321+
11322+ return 0;
11323+}
11324+
11325+static int dsi_set_stop_state_counter(int ns, int x4, int x16)
11326+{
11327+ u32 r;
11328+ unsigned long fck;
11329+ int ticks;
11330+
11331+ /* ticks in DSI_FCK */
11332+
11333+ fck = dsi_fclk_rate();
11334+ ticks = (fck / 1000 / 1000) * ns / 1000;
11335+
11336+ if (ticks > 0x1fff) {
11337+ DSSERR("STOP_STATE_COUNTER_IO too high\n");
11338+ return -EINVAL;
11339+ }
11340+
11341+ r = dsi_read_reg(DSI_TIMING1);
11342+ r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
11343+ r = FLD_MOD(r, x16, 14, 14); /* STOP_STATE_X16_IO */
11344+ r = FLD_MOD(r, x4, 13, 13); /* STOP_STATE_X4_IO */
11345+ r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */
11346+ dsi_write_reg(DSI_TIMING1, r);
11347+
11348+ DSSDBG("STOP_STATE_COUNTER %ld ns (%#x ticks)\n",
11349+ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
11350+ (fck / 1000 / 1000),
11351+ ticks);
11352+
11353+ return 0;
11354+}
11355+
11356+static int dsi_set_hs_tx_timeout(int ns, int x4, int x16)
11357+{
11358+ u32 r;
11359+ unsigned long fck;
11360+ int ticks;
11361+
11362+ /* ticks in TxByteClkHS */
11363+
11364+ fck = dsi.ddr_clk / 4;
11365+ ticks = (fck / 1000 / 1000) * ns / 1000;
11366+
11367+ if (ticks > 0x1fff) {
11368+ DSSERR("HS_TX_TO too high\n");
11369+ return -EINVAL;
11370+ }
11371+
11372+ r = dsi_read_reg(DSI_TIMING2);
11373+ r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */
11374+ r = FLD_MOD(r, x16, 30, 30); /* HS_TX_TO_X16 */
11375+ r = FLD_MOD(r, x4, 29, 29); /* HS_TX_TO_X8 (4 really) */
11376+ r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */
11377+ dsi_write_reg(DSI_TIMING2, r);
11378+
11379+ DSSDBG("HS_TX_TO %ld ns (%#x ticks)\n",
11380+ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
11381+ (fck / 1000 / 1000),
11382+ ticks);
11383+
11384+ return 0;
11385+}
11386+static int dsi_proto_config(struct omap_dss_device *dssdev)
11387+{
11388+ u32 r;
11389+ int buswidth = 0;
11390+ int div;
11391+
11392+ dsi_config_tx_fifo(DSI_FIFO_SIZE_128,
11393+ DSI_FIFO_SIZE_0,
11394+ DSI_FIFO_SIZE_0,
11395+ DSI_FIFO_SIZE_0);
11396+
11397+ dsi_config_rx_fifo(DSI_FIFO_SIZE_128,
11398+ DSI_FIFO_SIZE_0,
11399+ DSI_FIFO_SIZE_0,
11400+ DSI_FIFO_SIZE_0);
11401+
11402+ /* XXX what values for the timeouts? */
11403+ dsi_set_stop_state_counter(1000, 0, 0);
11404+
11405+ dsi_set_ta_timeout(50000, 1, 1);
11406+
11407+ /* 3000ns * 16 */
11408+ dsi_set_lp_rx_timeout(3000, 0, 1);
11409+
11410+ /* 10000ns * 4 */
11411+ dsi_set_hs_tx_timeout(10000, 1, 0);
11412+
11413+ switch (dssdev->ctrl.pixel_size) {
11414+ case 16:
11415+ buswidth = 0;
11416+ break;
11417+ case 18:
11418+ buswidth = 1;
11419+ break;
11420+ case 24:
11421+ buswidth = 2;
11422+ break;
11423+ default:
11424+ BUG();
11425+ }
11426+
11427+ r = dsi_read_reg(DSI_CTRL);
11428+ r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */
11429+ r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */
11430+ r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */
11431+
11432+ div = dispc_lclk_rate() / dispc_pclk_rate();
11433+ r = FLD_MOD(r, div == 2 ? 0 : 1, 4, 4); /* VP_CLK_RATIO */
11434+ r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
11435+ r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */
11436+ r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */
11437+ r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */
11438+ r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */
11439+ r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */
11440+ r = FLD_MOD(r, 0, 25, 25); /* DCS_CMD_CODE, 1=start, 0=continue */
11441+
11442+ dsi_write_reg(DSI_CTRL, r);
11443+
11444+ dsi_vc_initial_config(0);
11445+
11446+ /* set all vc targets to peripheral 0 */
11447+ dsi.vc[0].dest_per = 0;
11448+ dsi.vc[1].dest_per = 0;
11449+ dsi.vc[2].dest_per = 0;
11450+ dsi.vc[3].dest_per = 0;
11451+
11452+ return 0;
11453+}
11454+
11455+static void dsi_proto_timings(struct omap_dss_device *dssdev)
11456+{
11457+ unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
11458+ unsigned tclk_pre, tclk_post;
11459+ unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
11460+ unsigned ths_trail, ths_exit;
11461+ unsigned ddr_clk_pre, ddr_clk_post;
11462+ unsigned enter_hs_mode_lat, exit_hs_mode_lat;
11463+ unsigned ths_eot;
11464+ u32 r;
11465+
11466+ r = dsi_read_reg(DSI_DSIPHY_CFG0);
11467+ ths_prepare = FLD_GET(r, 31, 24);
11468+ ths_prepare_ths_zero = FLD_GET(r, 23, 16);
11469+ ths_zero = ths_prepare_ths_zero - ths_prepare;
11470+ ths_trail = FLD_GET(r, 15, 8);
11471+ ths_exit = FLD_GET(r, 7, 0);
11472+
11473+ r = dsi_read_reg(DSI_DSIPHY_CFG1);
11474+ tlpx = FLD_GET(r, 22, 16) * 2;
11475+ tclk_trail = FLD_GET(r, 15, 8);
11476+ tclk_zero = FLD_GET(r, 7, 0);
11477+
11478+ r = dsi_read_reg(DSI_DSIPHY_CFG2);
11479+ tclk_prepare = FLD_GET(r, 7, 0);
11480+
11481+ /* min 8*UI */
11482+ tclk_pre = 20;
11483+ /* min 60ns + 52*UI */
11484+ tclk_post = ns2ddr(60) + 26;
11485+
11486+ /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */
11487+ if (dssdev->phy.dsi.data1_lane != 0 &&
11488+ dssdev->phy.dsi.data2_lane != 0)
11489+ ths_eot = 2;
11490+ else
11491+ ths_eot = 4;
11492+
11493+ ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
11494+ 4);
11495+ ddr_clk_post = DIV_ROUND_UP(tclk_post + tclk_trail, 4) + ths_eot;
11496+
11497+ BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255);
11498+ BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255);
11499+
11500+ r = dsi_read_reg(DSI_CLK_TIMING);
11501+ r = FLD_MOD(r, ddr_clk_pre, 15, 8);
11502+ r = FLD_MOD(r, ddr_clk_post, 7, 0);
11503+ dsi_write_reg(DSI_CLK_TIMING, r);
11504+
11505+ DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n",
11506+ ddr_clk_pre,
11507+ ddr_clk_post);
11508+
11509+ enter_hs_mode_lat = 1 + DIV_ROUND_UP(tlpx, 4) +
11510+ DIV_ROUND_UP(ths_prepare, 4) +
11511+ DIV_ROUND_UP(ths_zero + 3, 4);
11512+
11513+ exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot;
11514+
11515+ r = FLD_VAL(enter_hs_mode_lat, 31, 16) |
11516+ FLD_VAL(exit_hs_mode_lat, 15, 0);
11517+ dsi_write_reg(DSI_VM_TIMING7, r);
11518+
11519+ DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
11520+ enter_hs_mode_lat, exit_hs_mode_lat);
11521+}
11522+
11523+
11524+#define DSI_DECL_VARS \
11525+ int __dsi_cb = 0; u32 __dsi_cv = 0;
11526+
11527+#define DSI_FLUSH(ch) \
11528+ if (__dsi_cb > 0) { \
11529+ /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \
11530+ dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \
11531+ __dsi_cb = __dsi_cv = 0; \
11532+ }
11533+
11534+#define DSI_PUSH(ch, data) \
11535+ do { \
11536+ __dsi_cv |= (data) << (__dsi_cb * 8); \
11537+ /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \
11538+ if (++__dsi_cb > 3) \
11539+ DSI_FLUSH(ch); \
11540+ } while (0)
11541+
11542+static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
11543+ int x, int y, int w, int h)
11544+{
11545+ /* Note: supports only 24bit colors in 32bit container */
11546+ int first = 1;
11547+ int fifo_stalls = 0;
11548+ int max_dsi_packet_size;
11549+ int max_data_per_packet;
11550+ int max_pixels_per_packet;
11551+ int pixels_left;
11552+ int bytespp = dssdev->ctrl.pixel_size / 8;
11553+ int scr_width;
11554+ u32 __iomem *data;
11555+ int start_offset;
11556+ int horiz_inc;
11557+ int current_x;
11558+ struct omap_overlay *ovl;
11559+
11560+ debug_irq = 0;
11561+
11562+ DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n",
11563+ x, y, w, h);
11564+
11565+ ovl = dssdev->manager->overlays[0];
11566+
11567+ if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U)
11568+ return -EINVAL;
11569+
11570+ if (dssdev->ctrl.pixel_size != 24)
11571+ return -EINVAL;
11572+
11573+ scr_width = ovl->info.screen_width;
11574+ data = ovl->info.vaddr;
11575+
11576+ start_offset = scr_width * y + x;
11577+ horiz_inc = scr_width - w;
11578+ current_x = x;
11579+
11580+ /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes
11581+ * in fifo */
11582+
11583+ /* When using CPU, max long packet size is TX buffer size */
11584+ max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4;
11585+
11586+ /* we seem to get better perf if we divide the tx fifo to half,
11587+ and while the other half is being sent, we fill the other half
11588+ max_dsi_packet_size /= 2; */
11589+
11590+ max_data_per_packet = max_dsi_packet_size - 4 - 1;
11591+
11592+ max_pixels_per_packet = max_data_per_packet / bytespp;
11593+
11594+ DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet);
11595+
11596+ pixels_left = w * h;
11597+
11598+ DSSDBG("total pixels %d\n", pixels_left);
11599+
11600+ data += start_offset;
11601+
11602+ while (pixels_left > 0) {
11603+ /* 0x2c = write_memory_start */
11604+ /* 0x3c = write_memory_continue */
11605+ u8 dcs_cmd = first ? 0x2c : 0x3c;
11606+ int pixels;
11607+ DSI_DECL_VARS;
11608+ first = 0;
11609+
11610+#if 1
11611+ /* using fifo not empty */
11612+ /* TX_FIFO_NOT_EMPTY */
11613+ while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) {
11614+ udelay(1);
11615+ fifo_stalls++;
11616+ if (fifo_stalls > 0xfffff) {
11617+ DSSERR("fifo stalls overflow, pixels left %d\n",
11618+ pixels_left);
11619+ dsi_if_enable(0);
11620+ return -EIO;
11621+ }
11622+ }
11623+#elif 1
11624+ /* using fifo emptiness */
11625+ while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 <
11626+ max_dsi_packet_size) {
11627+ fifo_stalls++;
11628+ if (fifo_stalls > 0xfffff) {
11629+ DSSERR("fifo stalls overflow, pixels left %d\n",
11630+ pixels_left);
11631+ dsi_if_enable(0);
11632+ return -EIO;
11633+ }
11634+ }
11635+#else
11636+ while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 == 0) {
11637+ fifo_stalls++;
11638+ if (fifo_stalls > 0xfffff) {
11639+ DSSERR("fifo stalls overflow, pixels left %d\n",
11640+ pixels_left);
11641+ dsi_if_enable(0);
11642+ return -EIO;
11643+ }
11644+ }
11645+#endif
11646+ pixels = min(max_pixels_per_packet, pixels_left);
11647+
11648+ pixels_left -= pixels;
11649+
11650+ dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE,
11651+ 1 + pixels * bytespp, 0);
11652+
11653+ DSI_PUSH(0, dcs_cmd);
11654+
11655+ while (pixels-- > 0) {
11656+ u32 pix = __raw_readl(data++);
11657+
11658+ DSI_PUSH(0, (pix >> 16) & 0xff);
11659+ DSI_PUSH(0, (pix >> 8) & 0xff);
11660+ DSI_PUSH(0, (pix >> 0) & 0xff);
11661+
11662+ current_x++;
11663+ if (current_x == x+w) {
11664+ current_x = x;
11665+ data += horiz_inc;
11666+ }
11667+ }
11668+
11669+ DSI_FLUSH(0);
11670+ }
11671+
11672+ return 0;
11673+}
11674+
11675+static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
11676+ u16 x, u16 y, u16 w, u16 h)
11677+{
11678+ int bytespp = dssdev->ctrl.pixel_size / 8;
11679+ int len;
11680+ int total_len;
11681+ int packet_payload;
11682+ int packet_len;
11683+ u32 l;
11684+ bool use_te_trigger;
11685+ const int channel = 0;
11686+
11687+ use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
11688+
11689+ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
11690+ DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
11691+ x, y, w, h);
11692+
11693+ len = w * h * bytespp;
11694+
11695+ /* XXX: one packet could be longer, I think? Line buffer is
11696+ * 1024 x 24bits, but we have to put DCS cmd there also.
11697+ * 1023 * 3 should work, but causes strange color effects. */
11698+ packet_payload = min(w, (u16)1020) * bytespp;
11699+
11700+ packet_len = packet_payload + 1; /* 1 byte for DCS cmd */
11701+ total_len = (len / packet_payload) * packet_len;
11702+
11703+ if (len % packet_payload)
11704+ total_len += (len % packet_payload) + 1;
11705+
11706+ if (0)
11707+ dsi_vc_print_status(1);
11708+
11709+ l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
11710+ dsi_write_reg(DSI_VC_TE(channel), l);
11711+
11712+ dsi_vc_write_long_header(channel, DSI_DT_DCS_LONG_WRITE, packet_len, 0);
11713+
11714+ if (use_te_trigger)
11715+ l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
11716+ else
11717+ l = FLD_MOD(l, 1, 31, 31); /* TE_START */
11718+ dsi_write_reg(DSI_VC_TE(channel), l);
11719+
11720+ /* We put SIDLEMODE to no-idle for the duration of the transfer,
11721+ * because DSS interrupts are not capable of waking up the CPU and the
11722+ * framedone interrupt could be delayed for quite a long time. I think
11723+ * the same goes for any DSS interrupts, but for some reason I have not
11724+ * seen the problem anywhere else than here.
11725+ */
11726+ dispc_disable_sidle();
11727+
11728+ dss_start_update(dssdev);
11729+
11730+ if (use_te_trigger) {
11731+ /* disable LP_RX_TO, so that we can receive TE. Time to wait
11732+ * for TE is longer than the timer allows */
11733+ REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
11734+
11735+ dsi_vc_send_bta(channel);
11736+ }
11737+}
11738+
11739+static void dsi_framedone_irq_callback(void *data, u32 mask)
11740+{
11741+ /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
11742+ * turns itself off. However, DSI still has the pixels in its buffers,
11743+ * and is sending the data.
11744+ */
11745+
11746+ /* SIDLEMODE back to smart-idle */
11747+ dispc_enable_sidle();
11748+
11749+ dsi.framedone_received = true;
11750+ wake_up(&dsi.waitqueue);
11751+}
11752+
11753+static void dsi_set_update_region(struct omap_dss_device *dssdev,
11754+ u16 x, u16 y, u16 w, u16 h)
11755+{
11756+ spin_lock(&dsi.update_lock);
11757+ if (dsi.update_region.dirty) {
11758+ dsi.update_region.x = min(x, dsi.update_region.x);
11759+ dsi.update_region.y = min(y, dsi.update_region.y);
11760+ dsi.update_region.w = max(w, dsi.update_region.w);
11761+ dsi.update_region.h = max(h, dsi.update_region.h);
11762+ } else {
11763+ dsi.update_region.x = x;
11764+ dsi.update_region.y = y;
11765+ dsi.update_region.w = w;
11766+ dsi.update_region.h = h;
11767+ }
11768+
11769+ dsi.update_region.device = dssdev;
11770+ dsi.update_region.dirty = true;
11771+
11772+ spin_unlock(&dsi.update_lock);
11773+
11774+}
11775+
11776+static void dsi_start_auto_update(struct omap_dss_device *dssdev)
11777+{
11778+ u16 w, h;
11779+ int i;
11780+
11781+ DSSDBG("starting auto update\n");
11782+
11783+ /* In automatic mode the overlay settings are applied like on DPI/SDI.
11784+ * Mark the overlays dirty, so that we get the overlays configured, as
11785+ * manual mode has left them in bad shape after config partia planes */
11786+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
11787+ struct omap_overlay *ovl;
11788+ ovl = omap_dss_get_overlay(i);
11789+ if (ovl->manager == dssdev->manager)
11790+ ovl->info_dirty = true;
11791+ }
11792+ dssdev->manager->apply(dssdev->manager);
11793+
11794+ dssdev->get_resolution(dssdev, &w, &h);
11795+
11796+ dsi_set_update_region(dssdev, 0, 0, w, h);
11797+
11798+ dsi_perf_mark_start_auto();
11799+
11800+ wake_up(&dsi.waitqueue);
11801+}
11802+
11803+static int dsi_set_te(struct omap_dss_device *dssdev, bool enable)
11804+{
11805+ int r;
11806+ r = dssdev->driver->enable_te(dssdev, enable);
11807+ /* XXX for some reason, DSI TE breaks if we don't wait here.
11808+ * Panel bug? Needs more studying */
11809+ msleep(100);
11810+ return r;
11811+}
11812+
11813+static void dsi_handle_framedone(void)
11814+{
11815+ int r;
11816+ const int channel = 0;
11817+ bool use_te_trigger;
11818+
11819+ use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
11820+
11821+ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
11822+ DSSDBG("FRAMEDONE\n");
11823+
11824+ if (use_te_trigger) {
11825+ /* enable LP_RX_TO again after the TE */
11826+ REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
11827+ }
11828+
11829+ /* Send BTA after the frame. We need this for the TE to work, as TE
11830+ * trigger is only sent for BTAs without preceding packet. Thus we need
11831+ * to BTA after the pixel packets so that next BTA will cause TE
11832+ * trigger.
11833+ *
11834+ * This is not needed when TE is not in use, but we do it anyway to
11835+ * make sure that the transfer has been completed. It would be more
11836+ * optimal, but more complex, to wait only just before starting next
11837+ * transfer. */
11838+ r = dsi_vc_send_bta_sync(channel);
11839+ if (r)
11840+ DSSERR("BTA after framedone failed\n");
11841+
11842+#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
11843+ dispc_fake_vsync_irq();
11844+#endif
11845+}
11846+
11847+static int dsi_update_thread(void *data)
11848+{
11849+ unsigned long timeout;
11850+ struct omap_dss_device *device;
11851+ u16 x, y, w, h;
11852+
11853+ while (1) {
11854+ bool sched;
11855+
11856+ wait_event_interruptible(dsi.waitqueue,
11857+ dsi.update_mode == OMAP_DSS_UPDATE_AUTO ||
11858+ (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL &&
11859+ dsi.update_region.dirty == true) ||
11860+ kthread_should_stop());
11861+
11862+ if (kthread_should_stop())
11863+ break;
11864+
11865+ dsi_bus_lock();
11866+
11867+ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED ||
11868+ kthread_should_stop()) {
11869+ dsi_bus_unlock();
11870+ break;
11871+ }
11872+
11873+ dsi_perf_mark_setup();
11874+
11875+ if (dsi.update_region.dirty) {
11876+ spin_lock(&dsi.update_lock);
11877+ dsi.active_update_region = dsi.update_region;
11878+ dsi.update_region.dirty = false;
11879+ spin_unlock(&dsi.update_lock);
11880+ }
11881+
11882+ device = dsi.active_update_region.device;
11883+ x = dsi.active_update_region.x;
11884+ y = dsi.active_update_region.y;
11885+ w = dsi.active_update_region.w;
11886+ h = dsi.active_update_region.h;
11887+
11888+ if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
11889+
11890+ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL) {
11891+ dss_setup_partial_planes(device,
11892+ &x, &y, &w, &h);
11893+#if 1
11894+ /* XXX there seems to be a bug in this driver
11895+ * or OMAP hardware. Some updates with certain
11896+ * widths and x coordinates fail. These widths
11897+ * are always odd, so "fix" it here for now */
11898+ if (w & 1) {
11899+ u16 dw, dh;
11900+ device->get_resolution(device,
11901+ &dw, &dh);
11902+ if (x + w == dw)
11903+ x &= ~1;
11904+ ++w;
11905+
11906+ dss_setup_partial_planes(device,
11907+ &x, &y, &w, &h);
11908+ }
11909+#endif
11910+ }
11911+
11912+ dispc_set_lcd_size(w, h);
11913+ }
11914+
11915+ if (dsi.active_update_region.dirty) {
11916+ dsi.active_update_region.dirty = false;
11917+ /* XXX TODO we don't need to send the coords, if they
11918+ * are the same that are already programmed to the
11919+ * panel. That should speed up manual update a bit */
11920+ device->driver->setup_update(device, x, y, w, h);
11921+ }
11922+
11923+ dsi_perf_mark_start();
11924+
11925+ if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
11926+ dsi_vc_config_vp(0);
11927+
11928+ if (dsi.te_enabled && dsi.use_ext_te)
11929+ device->driver->wait_for_te(device);
11930+
11931+ dsi.framedone_received = false;
11932+
11933+ dsi_update_screen_dispc(device, x, y, w, h);
11934+
11935+ /* wait for framedone */
11936+ timeout = msecs_to_jiffies(1000);
11937+ timeout = wait_event_timeout(dsi.waitqueue,
11938+ dsi.framedone_received == true,
11939+ timeout);
11940+
11941+ if (timeout == 0) {
11942+ DSSERR("framedone timeout\n");
11943+ DSSERR("failed update %d,%d %dx%d\n",
11944+ x, y, w, h);
11945+
11946+ dispc_enable_sidle();
11947+ dispc_enable_lcd_out(0);
11948+ } else {
11949+ dsi_handle_framedone();
11950+ dsi_perf_show("DISPC");
11951+ }
11952+ } else {
11953+ dsi_update_screen_l4(device, x, y, w, h);
11954+ dsi_perf_show("L4");
11955+ }
11956+
11957+ sched = atomic_read(&dsi.bus_lock.count) < 0;
11958+
11959+ complete_all(&dsi.update_completion);
11960+
11961+ dsi_bus_unlock();
11962+
11963+ /* XXX We need to give others chance to get the bus lock. Is
11964+ * there a better way for this? */
11965+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO && sched)
11966+ schedule_timeout_interruptible(1);
11967+ }
11968+
11969+ DSSDBG("update thread exiting\n");
11970+
11971+ return 0;
11972+}
11973+
11974+
11975+
11976+/* Display funcs */
11977+
11978+static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
11979+{
11980+ int r;
11981+
11982+ r = omap_dispc_register_isr(dsi_framedone_irq_callback, NULL,
11983+ DISPC_IRQ_FRAMEDONE);
11984+ if (r) {
11985+ DSSERR("can't get FRAMEDONE irq\n");
11986+ return r;
11987+ }
11988+
11989+ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
11990+
11991+ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_DSI);
11992+ dispc_enable_fifohandcheck(1);
11993+
11994+ dispc_set_tft_data_lines(dssdev->ctrl.pixel_size);
11995+
11996+ {
11997+ struct omap_video_timings timings = {
11998+ .hsw = 1,
11999+ .hfp = 1,
12000+ .hbp = 1,
12001+ .vsw = 1,
12002+ .vfp = 0,
12003+ .vbp = 0,
12004+ };
12005+
12006+ dispc_set_lcd_timings(&timings);
12007+ }
12008+
12009+ return 0;
12010+}
12011+
12012+static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
12013+{
12014+ omap_dispc_unregister_isr(dsi_framedone_irq_callback, NULL,
12015+ DISPC_IRQ_FRAMEDONE);
12016+}
12017+
12018+static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
12019+{
12020+ struct dsi_clock_info cinfo;
12021+ int r;
12022+
12023+ _dsi_print_reset_status();
12024+
12025+ r = dsi_pll_init(1, 0);
12026+ if (r)
12027+ goto err0;
12028+
12029+ r = dsi_pll_calc_ddrfreq(dssdev->phy.dsi.ddr_clk_hz, &cinfo);
12030+ if (r)
12031+ goto err1;
12032+
12033+ r = dsi_pll_program(&cinfo);
12034+ if (r)
12035+ goto err1;
12036+
12037+ DSSDBG("PLL OK\n");
12038+
12039+ r = dsi_complexio_init(dssdev);
12040+ if (r)
12041+ goto err1;
12042+
12043+ _dsi_print_reset_status();
12044+
12045+ dsi_proto_timings(dssdev);
12046+ dsi_set_lp_clk_divisor(dssdev);
12047+
12048+ if (1)
12049+ _dsi_print_reset_status();
12050+
12051+ r = dsi_proto_config(dssdev);
12052+ if (r)
12053+ goto err2;
12054+
12055+ /* enable interface */
12056+ dsi_vc_enable(0, 1);
12057+ dsi_if_enable(1);
12058+ dsi_force_tx_stop_mode_io();
12059+
12060+ if (dssdev->driver->enable) {
12061+ r = dssdev->driver->enable(dssdev);
12062+ if (r)
12063+ goto err3;
12064+ }
12065+
12066+ /* enable high-speed after initial config */
12067+ dsi_vc_enable_hs(0, 1);
12068+
12069+ return 0;
12070+err3:
12071+ dsi_if_enable(0);
12072+err2:
12073+ dsi_complexio_uninit();
12074+err1:
12075+ dsi_pll_uninit();
12076+err0:
12077+ return r;
12078+}
12079+
12080+static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
12081+{
12082+ if (dssdev->driver->disable)
12083+ dssdev->driver->disable(dssdev);
12084+
12085+ dsi_complexio_uninit();
12086+ dsi_pll_uninit();
12087+}
12088+
12089+static int dsi_core_init(void)
12090+{
12091+ /* Autoidle */
12092+ REG_FLD_MOD(DSI_SYSCONFIG, 1, 0, 0);
12093+
12094+ /* ENWAKEUP */
12095+ REG_FLD_MOD(DSI_SYSCONFIG, 1, 2, 2);
12096+
12097+ /* SIDLEMODE smart-idle */
12098+ REG_FLD_MOD(DSI_SYSCONFIG, 2, 4, 3);
12099+
12100+ _dsi_initialize_irq();
12101+
12102+ return 0;
12103+}
12104+
12105+static int dsi_display_enable(struct omap_dss_device *dssdev)
12106+{
12107+ int r = 0;
12108+
12109+ DSSDBG("dsi_display_enable\n");
12110+
12111+ mutex_lock(&dsi.lock);
12112+ dsi_bus_lock();
12113+
12114+ r = omap_dss_start_device(dssdev);
12115+ if (r) {
12116+ DSSERR("failed to start device\n");
12117+ goto err0;
12118+ }
12119+
12120+ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
12121+ DSSERR("dssdev already enabled\n");
12122+ r = -EINVAL;
12123+ goto err1;
12124+ }
12125+
12126+ enable_clocks(1);
12127+ dsi_enable_pll_clock(1);
12128+
12129+ r = _dsi_reset();
12130+ if (r)
12131+ goto err2;
12132+
12133+ dsi_core_init();
12134+
12135+ r = dsi_display_init_dispc(dssdev);
12136+ if (r)
12137+ goto err2;
12138+
12139+ r = dsi_display_init_dsi(dssdev);
12140+ if (r)
12141+ goto err3;
12142+
12143+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
12144+
12145+ dsi.use_ext_te = dssdev->phy.dsi.ext_te;
12146+ r = dsi_set_te(dssdev, dsi.te_enabled);
12147+ if (r)
12148+ goto err3;
12149+
12150+ dsi.update_mode = dsi.user_update_mode;
12151+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
12152+ dsi_start_auto_update(dssdev);
12153+
12154+ dsi_bus_unlock();
12155+ mutex_unlock(&dsi.lock);
12156+
12157+ return 0;
12158+
12159+err3:
12160+ dsi_display_uninit_dispc(dssdev);
12161+err2:
12162+ enable_clocks(0);
12163+ dsi_enable_pll_clock(0);
12164+err1:
12165+ omap_dss_stop_device(dssdev);
12166+err0:
12167+ dsi_bus_unlock();
12168+ mutex_unlock(&dsi.lock);
12169+ DSSDBG("dsi_display_enable FAILED\n");
12170+ return r;
12171+}
12172+
12173+static void dsi_display_disable(struct omap_dss_device *dssdev)
12174+{
12175+ DSSDBG("dsi_display_disable\n");
12176+
12177+ mutex_lock(&dsi.lock);
12178+ dsi_bus_lock();
12179+
12180+ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
12181+ dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
12182+ goto end;
12183+
12184+ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
12185+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
12186+
12187+ dsi_display_uninit_dispc(dssdev);
12188+
12189+ dsi_display_uninit_dsi(dssdev);
12190+
12191+ enable_clocks(0);
12192+ dsi_enable_pll_clock(0);
12193+
12194+ omap_dss_stop_device(dssdev);
12195+end:
12196+ dsi_bus_unlock();
12197+ mutex_unlock(&dsi.lock);
12198+}
12199+
12200+static int dsi_display_suspend(struct omap_dss_device *dssdev)
12201+{
12202+ DSSDBG("dsi_display_suspend\n");
12203+
12204+ mutex_lock(&dsi.lock);
12205+ dsi_bus_lock();
12206+
12207+ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
12208+ dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
12209+ goto end;
12210+
12211+ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
12212+ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
12213+
12214+ dsi_display_uninit_dispc(dssdev);
12215+
12216+ dsi_display_uninit_dsi(dssdev);
12217+
12218+ enable_clocks(0);
12219+ dsi_enable_pll_clock(0);
12220+end:
12221+ dsi_bus_unlock();
12222+ mutex_unlock(&dsi.lock);
12223+
12224+ return 0;
12225+}
12226+
12227+static int dsi_display_resume(struct omap_dss_device *dssdev)
12228+{
12229+ int r;
12230+
12231+ DSSDBG("dsi_display_resume\n");
12232+
12233+ mutex_lock(&dsi.lock);
12234+ dsi_bus_lock();
12235+
12236+ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
12237+ DSSERR("dssdev not suspended\n");
12238+ r = -EINVAL;
12239+ goto err0;
12240+ }
12241+
12242+ enable_clocks(1);
12243+ dsi_enable_pll_clock(1);
12244+
12245+ r = _dsi_reset();
12246+ if (r)
12247+ goto err1;
12248+
12249+ dsi_core_init();
12250+
12251+ r = dsi_display_init_dispc(dssdev);
12252+ if (r)
12253+ goto err1;
12254+
12255+ r = dsi_display_init_dsi(dssdev);
12256+ if (r)
12257+ goto err2;
12258+
12259+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
12260+
12261+ r = dsi_set_te(dssdev, dsi.te_enabled);
12262+ if (r)
12263+ goto err2;
12264+
12265+ dsi.update_mode = dsi.user_update_mode;
12266+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
12267+ dsi_start_auto_update(dssdev);
12268+
12269+ dsi_bus_unlock();
12270+ mutex_unlock(&dsi.lock);
12271+
12272+ return 0;
12273+
12274+err2:
12275+ dsi_display_uninit_dispc(dssdev);
12276+err1:
12277+ enable_clocks(0);
12278+ dsi_enable_pll_clock(0);
12279+err0:
12280+ dsi_bus_unlock();
12281+ mutex_unlock(&dsi.lock);
12282+ DSSDBG("dsi_display_resume FAILED\n");
12283+ return r;
12284+}
12285+
12286+static int dsi_display_update(struct omap_dss_device *dssdev,
12287+ u16 x, u16 y, u16 w, u16 h)
12288+{
12289+ int r = 0;
12290+ u16 dw, dh;
12291+
12292+ DSSDBG("dsi_display_update(%d,%d %dx%d)\n", x, y, w, h);
12293+
12294+ mutex_lock(&dsi.lock);
12295+
12296+ if (dsi.update_mode != OMAP_DSS_UPDATE_MANUAL)
12297+ goto end;
12298+
12299+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
12300+ goto end;
12301+
12302+ dssdev->get_resolution(dssdev, &dw, &dh);
12303+
12304+ if (x > dw || y > dh)
12305+ goto end;
12306+
12307+ if (x + w > dw)
12308+ w = dw - x;
12309+
12310+ if (y + h > dh)
12311+ h = dh - y;
12312+
12313+ if (w == 0 || h == 0)
12314+ goto end;
12315+
12316+ dsi_set_update_region(dssdev, x, y, w, h);
12317+
12318+ wake_up(&dsi.waitqueue);
12319+
12320+end:
12321+ mutex_unlock(&dsi.lock);
12322+
12323+ return r;
12324+}
12325+
12326+static int dsi_display_sync(struct omap_dss_device *dssdev)
12327+{
12328+ bool wait;
12329+
12330+ DSSDBG("dsi_display_sync()\n");
12331+
12332+ mutex_lock(&dsi.lock);
12333+ dsi_bus_lock();
12334+
12335+ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL &&
12336+ dsi.update_region.dirty) {
12337+ INIT_COMPLETION(dsi.update_completion);
12338+ wait = true;
12339+ } else {
12340+ wait = false;
12341+ }
12342+
12343+ dsi_bus_unlock();
12344+ mutex_unlock(&dsi.lock);
12345+
12346+ if (wait)
12347+ wait_for_completion_interruptible(&dsi.update_completion);
12348+
12349+ DSSDBG("dsi_display_sync() done\n");
12350+ return 0;
12351+}
12352+
12353+static int dsi_display_set_update_mode(struct omap_dss_device *dssdev,
12354+ enum omap_dss_update_mode mode)
12355+{
12356+ DSSDBGF("%d", mode);
12357+
12358+ mutex_lock(&dsi.lock);
12359+ dsi_bus_lock();
12360+
12361+ if (dsi.update_mode != mode) {
12362+ dsi.user_update_mode = mode;
12363+ dsi.update_mode = mode;
12364+
12365+ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE &&
12366+ mode == OMAP_DSS_UPDATE_AUTO)
12367+ dsi_start_auto_update(dssdev);
12368+ }
12369+
12370+ dsi_bus_unlock();
12371+ mutex_unlock(&dsi.lock);
12372+
12373+ return 0;
12374+}
12375+
12376+static enum omap_dss_update_mode dsi_display_get_update_mode(
12377+ struct omap_dss_device *dssdev)
12378+{
12379+ return dsi.update_mode;
12380+}
12381+
12382+
12383+static int dsi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
12384+{
12385+ int r = 0;
12386+
12387+ DSSDBGF("%d", enable);
12388+
12389+ if (!dssdev->driver->enable_te)
12390+ return -ENOENT;
12391+
12392+ dsi_bus_lock();
12393+
12394+ dsi.te_enabled = enable;
12395+
12396+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
12397+ goto end;
12398+
12399+ r = dsi_set_te(dssdev, enable);
12400+end:
12401+ dsi_bus_unlock();
12402+
12403+ return r;
12404+}
12405+
12406+static int dsi_display_get_te(struct omap_dss_device *dssdev)
12407+{
12408+ return dsi.te_enabled;
12409+}
12410+
12411+static int dsi_display_set_rotate(struct omap_dss_device *dssdev, u8 rotate)
12412+{
12413+
12414+ DSSDBGF("%d", rotate);
12415+
12416+ if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
12417+ return -EINVAL;
12418+
12419+ dsi_bus_lock();
12420+ dssdev->driver->set_rotate(dssdev, rotate);
12421+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
12422+ u16 w, h;
12423+ /* the display dimensions may have changed, so set a new
12424+ * update region */
12425+ dssdev->get_resolution(dssdev, &w, &h);
12426+ dsi_set_update_region(dssdev, 0, 0, w, h);
12427+ }
12428+ dsi_bus_unlock();
12429+
12430+ return 0;
12431+}
12432+
12433+static u8 dsi_display_get_rotate(struct omap_dss_device *dssdev)
12434+{
12435+ if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
12436+ return 0;
12437+
12438+ return dssdev->driver->get_rotate(dssdev);
12439+}
12440+
12441+static int dsi_display_set_mirror(struct omap_dss_device *dssdev, bool mirror)
12442+{
12443+ DSSDBGF("%d", mirror);
12444+
12445+ if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
12446+ return -EINVAL;
12447+
12448+ dsi_bus_lock();
12449+ dssdev->driver->set_mirror(dssdev, mirror);
12450+ dsi_bus_unlock();
12451+
12452+ return 0;
12453+}
12454+
12455+static bool dsi_display_get_mirror(struct omap_dss_device *dssdev)
12456+{
12457+ if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
12458+ return 0;
12459+
12460+ return dssdev->driver->get_mirror(dssdev);
12461+}
12462+
12463+static int dsi_display_run_test(struct omap_dss_device *dssdev, int test_num)
12464+{
12465+ int r;
12466+
12467+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
12468+ return -EIO;
12469+
12470+ DSSDBGF("%d", test_num);
12471+
12472+ dsi_bus_lock();
12473+
12474+ /* run test first in low speed mode */
12475+ dsi_vc_enable_hs(0, 0);
12476+
12477+ if (dssdev->driver->run_test) {
12478+ r = dssdev->driver->run_test(dssdev, test_num);
12479+ if (r)
12480+ goto end;
12481+ }
12482+
12483+ /* then in high speed */
12484+ dsi_vc_enable_hs(0, 1);
12485+
12486+ if (dssdev->driver->run_test) {
12487+ r = dssdev->driver->run_test(dssdev, test_num);
12488+ if (r)
12489+ goto end;
12490+ }
12491+
12492+end:
12493+ dsi_vc_enable_hs(0, 1);
12494+
12495+ dsi_bus_unlock();
12496+
12497+ return r;
12498+}
12499+
12500+static int dsi_display_memory_read(struct omap_dss_device *dssdev,
12501+ void *buf, size_t size,
12502+ u16 x, u16 y, u16 w, u16 h)
12503+{
12504+ int r;
12505+
12506+ DSSDBGF("");
12507+
12508+ if (!dssdev->driver->memory_read)
12509+ return -EINVAL;
12510+
12511+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
12512+ return -EIO;
12513+
12514+ dsi_bus_lock();
12515+
12516+ r = dssdev->driver->memory_read(dssdev, buf, size,
12517+ x, y, w, h);
12518+
12519+ dsi_bus_unlock();
12520+
12521+ return r;
12522+}
12523+
12524+void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
12525+ u32 fifo_size, enum omap_burst_size *burst_size,
12526+ u32 *fifo_low, u32 *fifo_high)
12527+{
12528+ unsigned burst_size_bytes;
12529+
12530+ *burst_size = OMAP_DSS_BURST_16x32;
12531+ burst_size_bytes = 16 * 32 / 8;
12532+
12533+ *fifo_high = fifo_size - burst_size_bytes;
12534+ *fifo_low = 0;
12535+}
12536+
12537+int dsi_init_display(struct omap_dss_device *dssdev)
12538+{
12539+ DSSDBG("DSI init\n");
12540+
12541+ dssdev->enable = dsi_display_enable;
12542+ dssdev->disable = dsi_display_disable;
12543+ dssdev->suspend = dsi_display_suspend;
12544+ dssdev->resume = dsi_display_resume;
12545+ dssdev->update = dsi_display_update;
12546+ dssdev->sync = dsi_display_sync;
12547+ dssdev->set_update_mode = dsi_display_set_update_mode;
12548+ dssdev->get_update_mode = dsi_display_get_update_mode;
12549+ dssdev->enable_te = dsi_display_enable_te;
12550+ dssdev->get_te = dsi_display_get_te;
12551+
12552+ dssdev->get_rotate = dsi_display_get_rotate;
12553+ dssdev->set_rotate = dsi_display_set_rotate;
12554+
12555+ dssdev->get_mirror = dsi_display_get_mirror;
12556+ dssdev->set_mirror = dsi_display_set_mirror;
12557+
12558+ dssdev->run_test = dsi_display_run_test;
12559+ dssdev->memory_read = dsi_display_memory_read;
12560+
12561+ dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
12562+
12563+ dsi.vc[0].dssdev = dssdev;
12564+ dsi.vc[1].dssdev = dssdev;
12565+
12566+ return 0;
12567+}
12568+
12569+int dsi_init(struct platform_device *pdev)
12570+{
12571+ u32 rev;
12572+ struct sched_param param = {
12573+ .sched_priority = MAX_USER_RT_PRIO-1
12574+ };
12575+
12576+ spin_lock_init(&dsi.errors_lock);
12577+ dsi.errors = 0;
12578+
12579+ /* XXX fail properly */
12580+
12581+ init_completion(&dsi.bta_completion);
12582+ init_completion(&dsi.update_completion);
12583+
12584+ dsi.thread = kthread_create(dsi_update_thread, NULL, "dsi");
12585+ if (IS_ERR(dsi.thread)) {
12586+ DSSERR("cannot create kthread\n");
12587+ return PTR_ERR(dsi.thread);
12588+ }
12589+ sched_setscheduler(dsi.thread, SCHED_FIFO, &param);
12590+
12591+ init_waitqueue_head(&dsi.waitqueue);
12592+ spin_lock_init(&dsi.update_lock);
12593+
12594+ mutex_init(&dsi.lock);
12595+ mutex_init(&dsi.bus_lock);
12596+
12597+ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
12598+ dsi.user_update_mode = OMAP_DSS_UPDATE_DISABLED;
12599+
12600+ dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS);
12601+ if (!dsi.base) {
12602+ DSSERR("can't ioremap DSI\n");
12603+ return -ENOMEM;
12604+ }
12605+
12606+ dsi.vdds_dsi_reg = regulator_get(&pdev->dev, "vdds_dsi");
12607+ if (IS_ERR(dsi.vdds_dsi_reg)) {
12608+ iounmap(dsi.base);
12609+ DSSERR("can't get VDDS_DSI regulator\n");
12610+ return PTR_ERR(dsi.vdds_dsi_reg);
12611+ }
12612+
12613+ enable_clocks(1);
12614+
12615+ rev = dsi_read_reg(DSI_REVISION);
12616+ printk(KERN_INFO "OMAP DSI rev %d.%d\n",
12617+ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
12618+
12619+ enable_clocks(0);
12620+
12621+ wake_up_process(dsi.thread);
12622+
12623+ return 0;
12624+}
12625+
12626+void dsi_exit(void)
12627+{
12628+ kthread_stop(dsi.thread);
12629+
12630+ regulator_put(dsi.vdds_dsi_reg);
12631+
12632+ iounmap(dsi.base);
12633+
12634+ DSSDBG("omap_dsi_exit\n");
12635+}
12636+
12637--- /dev/null
12638+++ b/drivers/video/omap2/dss/dss.c
12639@@ -0,0 +1,347 @@
12640+/*
12641+ * linux/drivers/video/omap2/dss/dss.c
12642+ *
12643+ * Copyright (C) 2009 Nokia Corporation
12644+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
12645+ *
12646+ * Some code and ideas taken from drivers/video/omap/ driver
12647+ * by Imre Deak.
12648+ *
12649+ * This program is free software; you can redistribute it and/or modify it
12650+ * under the terms of the GNU General Public License version 2 as published by
12651+ * the Free Software Foundation.
12652+ *
12653+ * This program is distributed in the hope that it will be useful, but WITHOUT
12654+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12655+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12656+ * more details.
12657+ *
12658+ * You should have received a copy of the GNU General Public License along with
12659+ * this program. If not, see <http://www.gnu.org/licenses/>.
12660+ */
12661+
12662+#define DSS_SUBSYS_NAME "DSS"
12663+
12664+#include <linux/kernel.h>
12665+#include <linux/io.h>
12666+#include <linux/err.h>
12667+#include <linux/delay.h>
12668+#include <linux/interrupt.h>
12669+#include <linux/seq_file.h>
12670+
12671+#include <mach/display.h>
12672+#include "dss.h"
12673+
12674+#define DSS_BASE 0x48050000
12675+
12676+#define DSS_SZ_REGS SZ_512
12677+
12678+struct dss_reg {
12679+ u16 idx;
12680+};
12681+
12682+#define DSS_REG(idx) ((const struct dss_reg) { idx })
12683+
12684+#define DSS_REVISION DSS_REG(0x0000)
12685+#define DSS_SYSCONFIG DSS_REG(0x0010)
12686+#define DSS_SYSSTATUS DSS_REG(0x0014)
12687+#define DSS_IRQSTATUS DSS_REG(0x0018)
12688+#define DSS_CONTROL DSS_REG(0x0040)
12689+#define DSS_SDI_CONTROL DSS_REG(0x0044)
12690+#define DSS_PLL_CONTROL DSS_REG(0x0048)
12691+#define DSS_SDI_STATUS DSS_REG(0x005C)
12692+
12693+#define REG_GET(idx, start, end) \
12694+ FLD_GET(dss_read_reg(idx), start, end)
12695+
12696+#define REG_FLD_MOD(idx, val, start, end) \
12697+ dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
12698+
12699+static struct {
12700+ void __iomem *base;
12701+
12702+ u32 ctx[DSS_SZ_REGS / sizeof(u32)];
12703+} dss;
12704+
12705+static int _omap_dss_wait_reset(void);
12706+
12707+static inline void dss_write_reg(const struct dss_reg idx, u32 val)
12708+{
12709+ __raw_writel(val, dss.base + idx.idx);
12710+}
12711+
12712+static inline u32 dss_read_reg(const struct dss_reg idx)
12713+{
12714+ return __raw_readl(dss.base + idx.idx);
12715+}
12716+
12717+#define SR(reg) \
12718+ dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
12719+#define RR(reg) \
12720+ dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
12721+
12722+void dss_save_context(void)
12723+{
12724+ if (cpu_is_omap24xx())
12725+ return;
12726+
12727+ SR(SYSCONFIG);
12728+ SR(CONTROL);
12729+
12730+#ifdef CONFIG_OMAP2_DSS_SDI
12731+ SR(SDI_CONTROL);
12732+ SR(PLL_CONTROL);
12733+#endif
12734+}
12735+
12736+void dss_restore_context(void)
12737+{
12738+ if (_omap_dss_wait_reset())
12739+ DSSERR("DSS not coming out of reset after sleep\n");
12740+
12741+ RR(SYSCONFIG);
12742+ RR(CONTROL);
12743+
12744+#ifdef CONFIG_OMAP2_DSS_SDI
12745+ RR(SDI_CONTROL);
12746+ RR(PLL_CONTROL);
12747+#endif
12748+}
12749+
12750+#undef SR
12751+#undef RR
12752+
12753+void dss_sdi_init(u8 datapairs)
12754+{
12755+ u32 l;
12756+
12757+ BUG_ON(datapairs > 3 || datapairs < 1);
12758+
12759+ l = dss_read_reg(DSS_SDI_CONTROL);
12760+ l = FLD_MOD(l, 0xf, 19, 15); /* SDI_PDIV */
12761+ l = FLD_MOD(l, datapairs-1, 3, 2); /* SDI_PRSEL */
12762+ l = FLD_MOD(l, 2, 1, 0); /* SDI_BWSEL */
12763+ dss_write_reg(DSS_SDI_CONTROL, l);
12764+
12765+ l = dss_read_reg(DSS_PLL_CONTROL);
12766+ l = FLD_MOD(l, 0x7, 25, 22); /* SDI_PLL_FREQSEL */
12767+ l = FLD_MOD(l, 0xb, 16, 11); /* SDI_PLL_REGN */
12768+ l = FLD_MOD(l, 0xb4, 10, 1); /* SDI_PLL_REGM */
12769+ dss_write_reg(DSS_PLL_CONTROL, l);
12770+}
12771+
12772+void dss_sdi_enable(void)
12773+{
12774+ dispc_pck_free_enable(1);
12775+
12776+ /* Reset SDI PLL */
12777+ REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
12778+ udelay(1); /* wait 2x PCLK */
12779+
12780+ /* Lock SDI PLL */
12781+ REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
12782+
12783+ /* Waiting for PLL lock request to complete */
12784+ while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6))
12785+ ;
12786+
12787+ /* Clearing PLL_GO bit */
12788+ REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
12789+
12790+ /* Waiting for PLL to lock */
12791+ while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5)))
12792+ ;
12793+
12794+ dispc_lcd_enable_signal(1);
12795+
12796+ /* Waiting for SDI reset to complete */
12797+ while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2)))
12798+ ;
12799+}
12800+
12801+void dss_sdi_disable(void)
12802+{
12803+ dispc_lcd_enable_signal(0);
12804+
12805+ dispc_pck_free_enable(0);
12806+
12807+ /* Reset SDI PLL */
12808+ REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
12809+}
12810+
12811+void dss_dump_regs(struct seq_file *s)
12812+{
12813+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
12814+
12815+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
12816+
12817+ DUMPREG(DSS_REVISION);
12818+ DUMPREG(DSS_SYSCONFIG);
12819+ DUMPREG(DSS_SYSSTATUS);
12820+ DUMPREG(DSS_IRQSTATUS);
12821+ DUMPREG(DSS_CONTROL);
12822+ DUMPREG(DSS_SDI_CONTROL);
12823+ DUMPREG(DSS_PLL_CONTROL);
12824+ DUMPREG(DSS_SDI_STATUS);
12825+
12826+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
12827+#undef DUMPREG
12828+}
12829+
12830+void dss_select_clk_source(bool dsi, bool dispc)
12831+{
12832+ u32 r;
12833+ r = dss_read_reg(DSS_CONTROL);
12834+ r = FLD_MOD(r, dsi, 1, 1); /* DSI_CLK_SWITCH */
12835+ r = FLD_MOD(r, dispc, 0, 0); /* DISPC_CLK_SWITCH */
12836+ dss_write_reg(DSS_CONTROL, r);
12837+}
12838+
12839+int dss_get_dsi_clk_source(void)
12840+{
12841+ return FLD_GET(dss_read_reg(DSS_CONTROL), 1, 1);
12842+}
12843+
12844+int dss_get_dispc_clk_source(void)
12845+{
12846+ return FLD_GET(dss_read_reg(DSS_CONTROL), 0, 0);
12847+}
12848+
12849+static irqreturn_t dss_irq_handler_omap2(int irq, void *arg)
12850+{
12851+ dispc_irq_handler();
12852+
12853+ return IRQ_HANDLED;
12854+}
12855+
12856+static irqreturn_t dss_irq_handler_omap3(int irq, void *arg)
12857+{
12858+ u32 irqstatus;
12859+
12860+ irqstatus = dss_read_reg(DSS_IRQSTATUS);
12861+
12862+ if (irqstatus & (1<<0)) /* DISPC_IRQ */
12863+ dispc_irq_handler();
12864+#ifdef CONFIG_OMAP2_DSS_DSI
12865+ if (irqstatus & (1<<1)) /* DSI_IRQ */
12866+ dsi_irq_handler();
12867+#endif
12868+
12869+ return IRQ_HANDLED;
12870+}
12871+
12872+static int _omap_dss_wait_reset(void)
12873+{
12874+ unsigned timeout = 1000;
12875+
12876+ while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
12877+ udelay(1);
12878+ if (!--timeout) {
12879+ DSSERR("soft reset failed\n");
12880+ return -ENODEV;
12881+ }
12882+ }
12883+
12884+ return 0;
12885+}
12886+
12887+static int _omap_dss_reset(void)
12888+{
12889+ /* Soft reset */
12890+ REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
12891+ return _omap_dss_wait_reset();
12892+}
12893+
12894+void dss_set_venc_output(enum omap_dss_venc_type type)
12895+{
12896+ int l = 0;
12897+
12898+ if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
12899+ l = 0;
12900+ else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
12901+ l = 1;
12902+ else
12903+ BUG();
12904+
12905+ /* venc out selection. 0 = comp, 1 = svideo */
12906+ REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
12907+}
12908+
12909+void dss_set_dac_pwrdn_bgz(bool enable)
12910+{
12911+ REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
12912+}
12913+
12914+int dss_init(bool skip_init)
12915+{
12916+ int r;
12917+ u32 rev;
12918+
12919+ dss.base = ioremap(DSS_BASE, DSS_SZ_REGS);
12920+ if (!dss.base) {
12921+ DSSERR("can't ioremap DSS\n");
12922+ r = -ENOMEM;
12923+ goto fail0;
12924+ }
12925+
12926+ if (!skip_init) {
12927+ /* disable LCD and DIGIT output. This seems to fix the synclost
12928+ * problem that we get, if the bootloader starts the DSS and
12929+ * the kernel resets it */
12930+ omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
12931+
12932+ /* We need to wait here a bit, otherwise we sometimes start to
12933+ * get synclost errors, and after that only power cycle will
12934+ * restore DSS functionality. I have no idea why this happens.
12935+ * And we have to wait _before_ resetting the DSS, but after
12936+ * enabling clocks.
12937+ */
12938+ msleep(50);
12939+
12940+ _omap_dss_reset();
12941+ }
12942+
12943+ /* autoidle */
12944+ REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
12945+
12946+ /* Select DPLL */
12947+ REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
12948+
12949+#ifdef CONFIG_OMAP2_DSS_VENC
12950+ REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
12951+ REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
12952+ REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
12953+#endif
12954+
12955+ r = request_irq(INT_24XX_DSS_IRQ,
12956+ cpu_is_omap24xx()
12957+ ? dss_irq_handler_omap2
12958+ : dss_irq_handler_omap3,
12959+ 0, "OMAP DSS", NULL);
12960+
12961+ if (r < 0) {
12962+ DSSERR("omap2 dss: request_irq failed\n");
12963+ goto fail1;
12964+ }
12965+
12966+ dss_save_context();
12967+
12968+ rev = dss_read_reg(DSS_REVISION);
12969+ printk(KERN_INFO "OMAP DSS rev %d.%d\n",
12970+ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
12971+
12972+ return 0;
12973+
12974+fail1:
12975+ iounmap(dss.base);
12976+fail0:
12977+ return r;
12978+}
12979+
12980+void dss_exit(void)
12981+{
12982+ free_irq(INT_24XX_DSS_IRQ, NULL);
12983+
12984+ iounmap(dss.base);
12985+}
12986+
12987--- /dev/null
12988+++ b/drivers/video/omap2/dss/dss.h
12989@@ -0,0 +1,356 @@
12990+/*
12991+ * linux/drivers/video/omap2/dss/dss.h
12992+ *
12993+ * Copyright (C) 2009 Nokia Corporation
12994+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
12995+ *
12996+ * Some code and ideas taken from drivers/video/omap/ driver
12997+ * by Imre Deak.
12998+ *
12999+ * This program is free software; you can redistribute it and/or modify it
13000+ * under the terms of the GNU General Public License version 2 as published by
13001+ * the Free Software Foundation.
13002+ *
13003+ * This program is distributed in the hope that it will be useful, but WITHOUT
13004+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13005+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13006+ * more details.
13007+ *
13008+ * You should have received a copy of the GNU General Public License along with
13009+ * this program. If not, see <http://www.gnu.org/licenses/>.
13010+ */
13011+
13012+#ifndef __OMAP2_DSS_H
13013+#define __OMAP2_DSS_H
13014+
13015+#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT
13016+#define DEBUG
13017+#endif
13018+
13019+#ifdef DEBUG
13020+extern unsigned int dss_debug;
13021+#ifdef DSS_SUBSYS_NAME
13022+#define DSSDBG(format, ...) \
13023+ if (dss_debug) \
13024+ printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \
13025+ ## __VA_ARGS__)
13026+#else
13027+#define DSSDBG(format, ...) \
13028+ if (dss_debug) \
13029+ printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__)
13030+#endif
13031+
13032+#ifdef DSS_SUBSYS_NAME
13033+#define DSSDBGF(format, ...) \
13034+ if (dss_debug) \
13035+ printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \
13036+ ": %s(" format ")\n", \
13037+ __func__, \
13038+ ## __VA_ARGS__)
13039+#else
13040+#define DSSDBGF(format, ...) \
13041+ if (dss_debug) \
13042+ printk(KERN_DEBUG "omapdss: " \
13043+ ": %s(" format ")\n", \
13044+ __func__, \
13045+ ## __VA_ARGS__)
13046+#endif
13047+
13048+#else /* DEBUG */
13049+#define DSSDBG(format, ...)
13050+#define DSSDBGF(format, ...)
13051+#endif
13052+
13053+
13054+#ifdef DSS_SUBSYS_NAME
13055+#define DSSERR(format, ...) \
13056+ printk(KERN_ERR "omapdss " DSS_SUBSYS_NAME " error: " format, \
13057+ ## __VA_ARGS__)
13058+#else
13059+#define DSSERR(format, ...) \
13060+ printk(KERN_ERR "omapdss error: " format, ## __VA_ARGS__)
13061+#endif
13062+
13063+#ifdef DSS_SUBSYS_NAME
13064+#define DSSINFO(format, ...) \
13065+ printk(KERN_INFO "omapdss " DSS_SUBSYS_NAME ": " format, \
13066+ ## __VA_ARGS__)
13067+#else
13068+#define DSSINFO(format, ...) \
13069+ printk(KERN_INFO "omapdss: " format, ## __VA_ARGS__)
13070+#endif
13071+
13072+#ifdef DSS_SUBSYS_NAME
13073+#define DSSWARN(format, ...) \
13074+ printk(KERN_WARNING "omapdss " DSS_SUBSYS_NAME ": " format, \
13075+ ## __VA_ARGS__)
13076+#else
13077+#define DSSWARN(format, ...) \
13078+ printk(KERN_WARNING "omapdss: " format, ## __VA_ARGS__)
13079+#endif
13080+
13081+/* OMAP TRM gives bitfields as start:end, where start is the higher bit
13082+ number. For example 7:0 */
13083+#define FLD_MASK(start, end) (((1 << (start - end + 1)) - 1) << (end))
13084+#define FLD_VAL(val, start, end) (((val) << end) & FLD_MASK(start, end))
13085+#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
13086+#define FLD_MOD(orig, val, start, end) \
13087+ (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
13088+
13089+#define DISPC_MAX_FCK 173000000
13090+
13091+enum omap_burst_size {
13092+ OMAP_DSS_BURST_4x32 = 0,
13093+ OMAP_DSS_BURST_8x32 = 1,
13094+ OMAP_DSS_BURST_16x32 = 2,
13095+};
13096+
13097+enum omap_parallel_interface_mode {
13098+ OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */
13099+ OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */
13100+ OMAP_DSS_PARALLELMODE_DSI,
13101+};
13102+
13103+enum dss_clock {
13104+ DSS_CLK_ICK = 1 << 0,
13105+ DSS_CLK_FCK1 = 1 << 1,
13106+ DSS_CLK_FCK2 = 1 << 2,
13107+ DSS_CLK_54M = 1 << 3,
13108+ DSS_CLK_96M = 1 << 4,
13109+};
13110+
13111+struct dispc_clock_info {
13112+ /* rates that we get with dividers below */
13113+ unsigned long fck;
13114+ unsigned long lck;
13115+ unsigned long pck;
13116+
13117+ /* dividers */
13118+ u16 fck_div;
13119+ u16 lck_div;
13120+ u16 pck_div;
13121+};
13122+
13123+struct dsi_clock_info {
13124+ /* rates that we get with dividers below */
13125+ unsigned long fint;
13126+ unsigned long dsiphy;
13127+ unsigned long clkin;
13128+ unsigned long dsi1_pll_fclk;
13129+ unsigned long dsi2_pll_fclk;
13130+ unsigned long lck;
13131+ unsigned long pck;
13132+
13133+ /* dividers */
13134+ u16 regn;
13135+ u16 regm;
13136+ u16 regm3;
13137+ u16 regm4;
13138+
13139+ u16 lck_div;
13140+ u16 pck_div;
13141+
13142+ u8 highfreq;
13143+ bool use_dss2_fck;
13144+};
13145+
13146+struct seq_file;
13147+struct platform_device;
13148+
13149+/* core */
13150+void dss_clk_enable(enum dss_clock clks);
13151+void dss_clk_disable(enum dss_clock clks);
13152+unsigned long dss_clk_get_rate(enum dss_clock clk);
13153+int dss_need_ctx_restore(void);
13154+void dss_dump_clocks(struct seq_file *s);
13155+struct bus_type *dss_get_bus(void);
13156+
13157+/* display */
13158+int dss_suspend_all_devices(void);
13159+int dss_resume_all_devices(void);
13160+
13161+void dss_init_device(struct platform_device *pdev,
13162+ struct omap_dss_device *dssdev);
13163+void dss_uninit_device(struct platform_device *pdev,
13164+ struct omap_dss_device *dssdev);
13165+bool dss_use_replication(struct omap_dss_device *dssdev,
13166+ enum omap_color_mode mode);
13167+void default_get_overlay_fifo_thresholds(enum omap_plane plane,
13168+ u32 fifo_size, enum omap_burst_size *burst_size,
13169+ u32 *fifo_low, u32 *fifo_high);
13170+
13171+/* manager */
13172+int dss_init_overlay_managers(struct platform_device *pdev);
13173+void dss_uninit_overlay_managers(struct platform_device *pdev);
13174+int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
13175+void dss_setup_partial_planes(struct omap_dss_device *dssdev,
13176+ u16 *x, u16 *y, u16 *w, u16 *h);
13177+void dss_start_update(struct omap_dss_device *dssdev);
13178+
13179+/* overlay */
13180+void dss_init_overlays(struct platform_device *pdev);
13181+void dss_uninit_overlays(struct platform_device *pdev);
13182+int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev);
13183+void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
13184+#ifdef L4_EXAMPLE
13185+void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr);
13186+#endif
13187+void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
13188+
13189+/* DSS */
13190+int dss_init(bool skip_init);
13191+void dss_exit(void);
13192+
13193+void dss_save_context(void);
13194+void dss_restore_context(void);
13195+
13196+void dss_dump_regs(struct seq_file *s);
13197+
13198+void dss_sdi_init(u8 datapairs);
13199+void dss_sdi_enable(void);
13200+void dss_sdi_disable(void);
13201+
13202+void dss_select_clk_source(bool dsi, bool dispc);
13203+int dss_get_dsi_clk_source(void);
13204+int dss_get_dispc_clk_source(void);
13205+void dss_set_venc_output(enum omap_dss_venc_type type);
13206+void dss_set_dac_pwrdn_bgz(bool enable);
13207+
13208+/* SDI */
13209+int sdi_init(bool skip_init);
13210+void sdi_exit(void);
13211+int sdi_init_display(struct omap_dss_device *display);
13212+
13213+/* DSI */
13214+int dsi_init(struct platform_device *pdev);
13215+void dsi_exit(void);
13216+
13217+void dsi_dump_clocks(struct seq_file *s);
13218+void dsi_dump_regs(struct seq_file *s);
13219+
13220+void dsi_save_context(void);
13221+void dsi_restore_context(void);
13222+
13223+int dsi_init_display(struct omap_dss_device *display);
13224+void dsi_irq_handler(void);
13225+unsigned long dsi_get_dsi1_pll_rate(void);
13226+unsigned long dsi_get_dsi2_pll_rate(void);
13227+int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck,
13228+ struct dsi_clock_info *cinfo);
13229+int dsi_pll_program(struct dsi_clock_info *cinfo);
13230+int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv);
13231+void dsi_pll_uninit(void);
13232+void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
13233+ u32 fifo_size, enum omap_burst_size *burst_size,
13234+ u32 *fifo_low, u32 *fifo_high);
13235+
13236+/* DPI */
13237+int dpi_init(void);
13238+void dpi_exit(void);
13239+int dpi_init_display(struct omap_dss_device *dssdev);
13240+
13241+/* DISPC */
13242+int dispc_init(void);
13243+void dispc_exit(void);
13244+void dispc_dump_clocks(struct seq_file *s);
13245+void dispc_dump_regs(struct seq_file *s);
13246+void dispc_irq_handler(void);
13247+void dispc_fake_vsync_irq(void);
13248+
13249+void dispc_save_context(void);
13250+void dispc_restore_context(void);
13251+
13252+void dispc_enable_sidle(void);
13253+void dispc_disable_sidle(void);
13254+
13255+void dispc_lcd_enable_signal_polarity(bool act_high);
13256+void dispc_lcd_enable_signal(bool enable);
13257+void dispc_pck_free_enable(bool enable);
13258+void dispc_enable_fifohandcheck(bool enable);
13259+
13260+void dispc_set_lcd_size(u16 width, u16 height);
13261+void dispc_set_digit_size(u16 width, u16 height);
13262+u32 dispc_get_plane_fifo_size(enum omap_plane plane);
13263+void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high);
13264+void dispc_enable_fifomerge(bool enable);
13265+void dispc_set_burst_size(enum omap_plane plane,
13266+ enum omap_burst_size burst_size);
13267+
13268+void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
13269+void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
13270+void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y);
13271+void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
13272+void dispc_set_channel_out(enum omap_plane plane,
13273+ enum omap_channel channel_out);
13274+
13275+int dispc_setup_plane(enum omap_plane plane,
13276+ u32 paddr, u16 screen_width,
13277+ u16 pos_x, u16 pos_y,
13278+ u16 width, u16 height,
13279+ u16 out_width, u16 out_height,
13280+ enum omap_color_mode color_mode,
13281+ bool ilace,
13282+ enum omap_dss_rotation_type rotation_type,
13283+ u8 rotation, bool mirror,
13284+ u8 global_alpha);
13285+
13286+bool dispc_go_busy(enum omap_channel channel);
13287+void dispc_go(enum omap_channel channel);
13288+void dispc_enable_lcd_out(bool enable);
13289+void dispc_enable_digit_out(bool enable);
13290+int dispc_enable_plane(enum omap_plane plane, bool enable);
13291+void dispc_enable_replication(enum omap_plane plane, bool enable);
13292+
13293+void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode);
13294+void dispc_set_tft_data_lines(u8 data_lines);
13295+void dispc_set_lcd_display_type(enum omap_lcd_display_type type);
13296+void dispc_set_loadmode(enum omap_dss_load_mode mode);
13297+
13298+void dispc_set_default_color(enum omap_channel channel, u32 color);
13299+u32 dispc_get_default_color(enum omap_channel channel);
13300+void dispc_set_trans_key(enum omap_channel ch,
13301+ enum omap_dss_trans_key_type type,
13302+ u32 trans_key);
13303+void dispc_get_trans_key(enum omap_channel ch,
13304+ enum omap_dss_trans_key_type *type,
13305+ u32 *trans_key);
13306+void dispc_enable_trans_key(enum omap_channel ch, bool enable);
13307+void dispc_enable_alpha_blending(enum omap_channel ch, bool enable);
13308+bool dispc_trans_key_enabled(enum omap_channel ch);
13309+bool dispc_alpha_blending_enabled(enum omap_channel ch);
13310+
13311+bool dispc_lcd_timings_ok(struct omap_video_timings *timings);
13312+void dispc_set_lcd_timings(struct omap_video_timings *timings);
13313+unsigned long dispc_fclk_rate(void);
13314+unsigned long dispc_lclk_rate(void);
13315+unsigned long dispc_pclk_rate(void);
13316+void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb);
13317+void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
13318+ u16 *lck_div, u16 *pck_div);
13319+int dispc_calc_clock_div(bool is_tft, unsigned long req_pck,
13320+ struct dispc_clock_info *cinfo);
13321+int dispc_set_clock_div(struct dispc_clock_info *cinfo);
13322+int dispc_get_clock_div(struct dispc_clock_info *cinfo);
13323+void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div);
13324+
13325+
13326+/* VENC */
13327+int venc_init(struct platform_device *pdev);
13328+void venc_exit(void);
13329+void venc_dump_regs(struct seq_file *s);
13330+int venc_init_display(struct omap_dss_device *display);
13331+
13332+/* RFBI */
13333+int rfbi_init(void);
13334+void rfbi_exit(void);
13335+void rfbi_dump_regs(struct seq_file *s);
13336+
13337+int rfbi_configure(int rfbi_module, int bpp, int lines);
13338+void rfbi_enable_rfbi(bool enable);
13339+void rfbi_transfer_area(u16 width, u16 height,
13340+ void (callback)(void *data), void *data);
13341+void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
13342+unsigned long rfbi_get_max_tx_rate(void);
13343+int rfbi_init_display(struct omap_dss_device *display);
13344+
13345+#endif
13346--- /dev/null
13347+++ b/drivers/video/omap2/dss/manager.c
13348@@ -0,0 +1,1487 @@
13349+/*
13350+ * linux/drivers/video/omap2/dss/manager.c
13351+ *
13352+ * Copyright (C) 2009 Nokia Corporation
13353+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
13354+ *
13355+ * Some code and ideas taken from drivers/video/omap/ driver
13356+ * by Imre Deak.
13357+ *
13358+ * This program is free software; you can redistribute it and/or modify it
13359+ * under the terms of the GNU General Public License version 2 as published by
13360+ * the Free Software Foundation.
13361+ *
13362+ * This program is distributed in the hope that it will be useful, but WITHOUT
13363+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13364+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13365+ * more details.
13366+ *
13367+ * You should have received a copy of the GNU General Public License along with
13368+ * this program. If not, see <http://www.gnu.org/licenses/>.
13369+ */
13370+
13371+#define DSS_SUBSYS_NAME "MANAGER"
13372+
13373+#include <linux/kernel.h>
13374+#include <linux/module.h>
13375+#include <linux/platform_device.h>
13376+#include <linux/spinlock.h>
13377+#include <linux/jiffies.h>
13378+
13379+#include <mach/display.h>
13380+#include <mach/cpu.h>
13381+
13382+#include "dss.h"
13383+
13384+static int num_managers;
13385+static struct list_head manager_list;
13386+
13387+static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
13388+{
13389+ return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
13390+}
13391+
13392+static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
13393+{
13394+ return snprintf(buf, PAGE_SIZE, "%s\n",
13395+ mgr->device ? mgr->device->name : "<none>");
13396+}
13397+
13398+static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
13399+ const char *buf, size_t size)
13400+{
13401+ int r = 0;
13402+ size_t len = size;
13403+ struct omap_dss_device *dssdev = NULL;
13404+
13405+ int match(struct omap_dss_device *dssdev, void *data)
13406+ {
13407+ const char *str = data;
13408+ return sysfs_streq(dssdev->name, str);
13409+ }
13410+
13411+ if (buf[size-1] == '\n')
13412+ --len;
13413+
13414+ if (len > 0)
13415+ dssdev = omap_dss_find_device((void *)buf, match);
13416+
13417+ if (len > 0 && dssdev == NULL)
13418+ return -EINVAL;
13419+
13420+ if (dssdev)
13421+ DSSDBG("display %s found\n", dssdev->name);
13422+
13423+ if (mgr->device) {
13424+ r = mgr->unset_device(mgr);
13425+ if (r) {
13426+ DSSERR("failed to unset display\n");
13427+ goto put_device;
13428+ }
13429+ }
13430+
13431+ if (dssdev) {
13432+ r = mgr->set_device(mgr, dssdev);
13433+ if (r) {
13434+ DSSERR("failed to set manager\n");
13435+ goto put_device;
13436+ }
13437+
13438+ r = mgr->apply(mgr);
13439+ if (r) {
13440+ DSSERR("failed to apply dispc config\n");
13441+ goto put_device;
13442+ }
13443+ }
13444+
13445+put_device:
13446+ if (dssdev)
13447+ omap_dss_put_device(dssdev);
13448+
13449+ return r ? r : size;
13450+}
13451+
13452+static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
13453+ char *buf)
13454+{
13455+ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color);
13456+}
13457+
13458+static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
13459+ const char *buf, size_t size)
13460+{
13461+ struct omap_overlay_manager_info info;
13462+ u32 color;
13463+ int r;
13464+
13465+ if (sscanf(buf, "%d", &color) != 1)
13466+ return -EINVAL;
13467+
13468+ mgr->get_manager_info(mgr, &info);
13469+
13470+ info.default_color = color;
13471+
13472+ r = mgr->set_manager_info(mgr, &info);
13473+ if (r)
13474+ return r;
13475+
13476+ r = mgr->apply(mgr);
13477+ if (r)
13478+ return r;
13479+
13480+ return size;
13481+}
13482+
13483+static const char *trans_key_type_str[] = {
13484+ "gfx-destination",
13485+ "video-source",
13486+};
13487+
13488+static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
13489+ char *buf)
13490+{
13491+ enum omap_dss_trans_key_type key_type;
13492+
13493+ key_type = mgr->info.trans_key_type;
13494+ BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
13495+
13496+ return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
13497+}
13498+
13499+static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
13500+ const char *buf, size_t size)
13501+{
13502+ enum omap_dss_trans_key_type key_type;
13503+ struct omap_overlay_manager_info info;
13504+ int r;
13505+
13506+ for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
13507+ key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
13508+ if (sysfs_streq(buf, trans_key_type_str[key_type]))
13509+ break;
13510+ }
13511+
13512+ if (key_type == ARRAY_SIZE(trans_key_type_str))
13513+ return -EINVAL;
13514+
13515+ mgr->get_manager_info(mgr, &info);
13516+
13517+ info.trans_key_type = key_type;
13518+
13519+ r = mgr->set_manager_info(mgr, &info);
13520+ if (r)
13521+ return r;
13522+
13523+ r = mgr->apply(mgr);
13524+ if (r)
13525+ return r;
13526+
13527+ return size;
13528+}
13529+
13530+static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
13531+ char *buf)
13532+{
13533+ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key);
13534+}
13535+
13536+static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
13537+ const char *buf, size_t size)
13538+{
13539+ struct omap_overlay_manager_info info;
13540+ u32 key_value;
13541+ int r;
13542+
13543+ if (sscanf(buf, "%d", &key_value) != 1)
13544+ return -EINVAL;
13545+
13546+ mgr->get_manager_info(mgr, &info);
13547+
13548+ info.trans_key = key_value;
13549+
13550+ r = mgr->set_manager_info(mgr, &info);
13551+ if (r)
13552+ return r;
13553+
13554+ r = mgr->apply(mgr);
13555+ if (r)
13556+ return r;
13557+
13558+ return size;
13559+}
13560+
13561+static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
13562+ char *buf)
13563+{
13564+ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_enabled);
13565+}
13566+
13567+static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
13568+ const char *buf, size_t size)
13569+{
13570+ struct omap_overlay_manager_info info;
13571+ int enable;
13572+ int r;
13573+
13574+ if (sscanf(buf, "%d", &enable) != 1)
13575+ return -EINVAL;
13576+
13577+ mgr->get_manager_info(mgr, &info);
13578+
13579+ info.trans_enabled = enable ? true : false;
13580+
13581+ r = mgr->set_manager_info(mgr, &info);
13582+ if (r)
13583+ return r;
13584+
13585+ r = mgr->apply(mgr);
13586+ if (r)
13587+ return r;
13588+
13589+ return size;
13590+}
13591+
13592+static ssize_t manager_alpha_blending_enabled_show(
13593+ struct omap_overlay_manager *mgr, char *buf)
13594+{
13595+ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled);
13596+}
13597+
13598+static ssize_t manager_alpha_blending_enabled_store(
13599+ struct omap_overlay_manager *mgr,
13600+ const char *buf, size_t size)
13601+{
13602+ struct omap_overlay_manager_info info;
13603+ int enable;
13604+ int r;
13605+
13606+ if (sscanf(buf, "%d", &enable) != 1)
13607+ return -EINVAL;
13608+
13609+ mgr->get_manager_info(mgr, &info);
13610+
13611+ info.alpha_enabled = enable ? true : false;
13612+
13613+ r = mgr->set_manager_info(mgr, &info);
13614+ if (r)
13615+ return r;
13616+
13617+ r = mgr->apply(mgr);
13618+ if (r)
13619+ return r;
13620+
13621+ return size;
13622+}
13623+
13624+struct manager_attribute {
13625+ struct attribute attr;
13626+ ssize_t (*show)(struct omap_overlay_manager *, char *);
13627+ ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
13628+};
13629+
13630+#define MANAGER_ATTR(_name, _mode, _show, _store) \
13631+ struct manager_attribute manager_attr_##_name = \
13632+ __ATTR(_name, _mode, _show, _store)
13633+
13634+static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
13635+static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
13636+ manager_display_show, manager_display_store);
13637+static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
13638+ manager_default_color_show, manager_default_color_store);
13639+static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
13640+ manager_trans_key_type_show, manager_trans_key_type_store);
13641+static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
13642+ manager_trans_key_value_show, manager_trans_key_value_store);
13643+static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
13644+ manager_trans_key_enabled_show,
13645+ manager_trans_key_enabled_store);
13646+static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
13647+ manager_alpha_blending_enabled_show,
13648+ manager_alpha_blending_enabled_store);
13649+
13650+
13651+static struct attribute *manager_sysfs_attrs[] = {
13652+ &manager_attr_name.attr,
13653+ &manager_attr_display.attr,
13654+ &manager_attr_default_color.attr,
13655+ &manager_attr_trans_key_type.attr,
13656+ &manager_attr_trans_key_value.attr,
13657+ &manager_attr_trans_key_enabled.attr,
13658+ &manager_attr_alpha_blending_enabled.attr,
13659+ NULL
13660+};
13661+
13662+static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
13663+ char *buf)
13664+{
13665+ struct omap_overlay_manager *manager;
13666+ struct manager_attribute *manager_attr;
13667+
13668+ manager = container_of(kobj, struct omap_overlay_manager, kobj);
13669+ manager_attr = container_of(attr, struct manager_attribute, attr);
13670+
13671+ if (!manager_attr->show)
13672+ return -ENOENT;
13673+
13674+ return manager_attr->show(manager, buf);
13675+}
13676+
13677+static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
13678+ const char *buf, size_t size)
13679+{
13680+ struct omap_overlay_manager *manager;
13681+ struct manager_attribute *manager_attr;
13682+
13683+ manager = container_of(kobj, struct omap_overlay_manager, kobj);
13684+ manager_attr = container_of(attr, struct manager_attribute, attr);
13685+
13686+ if (!manager_attr->store)
13687+ return -ENOENT;
13688+
13689+ return manager_attr->store(manager, buf, size);
13690+}
13691+
13692+static struct sysfs_ops manager_sysfs_ops = {
13693+ .show = manager_attr_show,
13694+ .store = manager_attr_store,
13695+};
13696+
13697+static struct kobj_type manager_ktype = {
13698+ .sysfs_ops = &manager_sysfs_ops,
13699+ .default_attrs = manager_sysfs_attrs,
13700+};
13701+
13702+/*
13703+ * We have 4 levels of cache for the dispc settings. First two are in SW and
13704+ * the latter two in HW.
13705+ *
13706+ * +--------------------+
13707+ * |overlay/manager_info|
13708+ * +--------------------+
13709+ * v
13710+ * apply()
13711+ * v
13712+ * +--------------------+
13713+ * | dss_cache |
13714+ * +--------------------+
13715+ * v
13716+ * configure()
13717+ * v
13718+ * +--------------------+
13719+ * | shadow registers |
13720+ * +--------------------+
13721+ * v
13722+ * VFP or lcd/digit_enable
13723+ * v
13724+ * +--------------------+
13725+ * | registers |
13726+ * +--------------------+
13727+ */
13728+
13729+struct overlay_cache_data {
13730+ /* If true, cache changed, but not written to shadow registers. Set
13731+ * in apply(), cleared when registers written. */
13732+ bool dirty;
13733+ /* If true, shadow registers contain changed values not yet in real
13734+ * registers. Set when writing to shadow registers, cleared at
13735+ * VSYNC/EVSYNC */
13736+ bool shadow_dirty;
13737+
13738+ bool enabled;
13739+
13740+ u32 paddr;
13741+ void __iomem *vaddr;
13742+ u16 screen_width;
13743+ u16 width;
13744+ u16 height;
13745+ enum omap_color_mode color_mode;
13746+ u8 rotation;
13747+ enum omap_dss_rotation_type rotation_type;
13748+ bool mirror;
13749+
13750+ u16 pos_x;
13751+ u16 pos_y;
13752+ u16 out_width; /* if 0, out_width == width */
13753+ u16 out_height; /* if 0, out_height == height */
13754+ u8 global_alpha;
13755+
13756+ enum omap_channel channel;
13757+ bool replication;
13758+ bool ilace;
13759+
13760+ enum omap_burst_size burst_size;
13761+ u32 fifo_low;
13762+ u32 fifo_high;
13763+
13764+ bool manual_update;
13765+};
13766+
13767+struct manager_cache_data {
13768+ /* If true, cache changed, but not written to shadow registers. Set
13769+ * in apply(), cleared when registers written. */
13770+ bool dirty;
13771+ /* If true, shadow registers contain changed values not yet in real
13772+ * registers. Set when writing to shadow registers, cleared at
13773+ * VSYNC/EVSYNC */
13774+ bool shadow_dirty;
13775+
13776+ u32 default_color;
13777+
13778+ enum omap_dss_trans_key_type trans_key_type;
13779+ u32 trans_key;
13780+ bool trans_enabled;
13781+
13782+ bool alpha_enabled;
13783+
13784+ bool manual_upd_display;
13785+ bool manual_update;
13786+ bool do_manual_update;
13787+
13788+ /* manual update region */
13789+ u16 x, y, w, h;
13790+};
13791+
13792+static struct {
13793+ spinlock_t lock;
13794+ struct overlay_cache_data overlay_cache[3];
13795+ struct manager_cache_data manager_cache[2];
13796+
13797+ bool irq_enabled;
13798+} dss_cache;
13799+
13800+
13801+
13802+static int omap_dss_set_device(struct omap_overlay_manager *mgr,
13803+ struct omap_dss_device *dssdev)
13804+{
13805+ int i;
13806+ int r;
13807+
13808+ if (dssdev->manager) {
13809+ DSSERR("display '%s' already has a manager '%s'\n",
13810+ dssdev->name, dssdev->manager->name);
13811+ return -EINVAL;
13812+ }
13813+
13814+ if ((mgr->supported_displays & dssdev->type) == 0) {
13815+ DSSERR("display '%s' does not support manager '%s'\n",
13816+ dssdev->name, mgr->name);
13817+ return -EINVAL;
13818+ }
13819+
13820+ for (i = 0; i < mgr->num_overlays; i++) {
13821+ struct omap_overlay *ovl = mgr->overlays[i];
13822+
13823+ if (ovl->manager != mgr || !ovl->info.enabled)
13824+ continue;
13825+
13826+ r = dss_check_overlay(ovl, dssdev);
13827+ if (r)
13828+ return r;
13829+ }
13830+
13831+ dssdev->manager = mgr;
13832+ mgr->device = dssdev;
13833+ mgr->device_changed = true;
13834+
13835+ return 0;
13836+}
13837+
13838+static int omap_dss_unset_device(struct omap_overlay_manager *mgr)
13839+{
13840+ if (!mgr->device) {
13841+ DSSERR("failed to unset display, display not set.\n");
13842+ return -EINVAL;
13843+ }
13844+
13845+ mgr->device->manager = NULL;
13846+ mgr->device = NULL;
13847+ mgr->device_changed = true;
13848+
13849+ return 0;
13850+}
13851+
13852+static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
13853+{
13854+ unsigned long timeout = msecs_to_jiffies(500);
13855+ struct manager_cache_data *mc;
13856+ enum omap_channel channel;
13857+ u32 irq;
13858+ int r;
13859+ int i;
13860+
13861+ if (!mgr->device)
13862+ return 0;
13863+
13864+ if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) {
13865+ irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
13866+ channel = OMAP_DSS_CHANNEL_DIGIT;
13867+ } else {
13868+ if (mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
13869+ enum omap_dss_update_mode mode;
13870+ mode = mgr->device->get_update_mode(mgr->device);
13871+ if (mode != OMAP_DSS_UPDATE_AUTO)
13872+ return 0;
13873+
13874+ irq = DISPC_IRQ_FRAMEDONE;
13875+ } else {
13876+ irq = DISPC_IRQ_VSYNC;
13877+ }
13878+ channel = OMAP_DSS_CHANNEL_LCD;
13879+ }
13880+
13881+ mc = &dss_cache.manager_cache[mgr->id];
13882+ i = 0;
13883+ while (1) {
13884+ unsigned long flags;
13885+ bool shadow_dirty, dirty;
13886+
13887+ spin_lock_irqsave(&dss_cache.lock, flags);
13888+ dirty = mc->dirty;
13889+ shadow_dirty = mc->shadow_dirty;
13890+ spin_unlock_irqrestore(&dss_cache.lock, flags);
13891+
13892+ if (!dirty && !shadow_dirty) {
13893+ r = 0;
13894+ break;
13895+ }
13896+
13897+ /* 4 iterations is the worst case:
13898+ * 1 - initial iteration, dirty = true (between VFP and VSYNC)
13899+ * 2 - first VSYNC, dirty = true
13900+ * 3 - dirty = false, shadow_dirty = true
13901+ * 4 - shadow_dirty = false */
13902+ if (i++ == 3) {
13903+ DSSERR("mgr(%d)->wait_for_go() not finishing\n",
13904+ mgr->id);
13905+ r = 0;
13906+ break;
13907+ }
13908+
13909+ r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
13910+ if (r == -ERESTARTSYS)
13911+ break;
13912+
13913+ if (r) {
13914+ DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
13915+ break;
13916+ }
13917+ }
13918+
13919+ return r;
13920+}
13921+
13922+int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
13923+{
13924+ unsigned long timeout = msecs_to_jiffies(500);
13925+ enum omap_channel channel;
13926+ struct overlay_cache_data *oc;
13927+ struct omap_dss_device *dssdev;
13928+ u32 irq;
13929+ int r;
13930+ int i;
13931+
13932+ if (!ovl->manager || !ovl->manager->device)
13933+ return 0;
13934+
13935+ dssdev = ovl->manager->device;
13936+
13937+ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
13938+ irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
13939+ channel = OMAP_DSS_CHANNEL_DIGIT;
13940+ } else {
13941+ if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
13942+ enum omap_dss_update_mode mode;
13943+ mode = dssdev->get_update_mode(dssdev);
13944+ if (mode != OMAP_DSS_UPDATE_AUTO)
13945+ return 0;
13946+
13947+ irq = DISPC_IRQ_FRAMEDONE;
13948+ } else {
13949+ irq = DISPC_IRQ_VSYNC;
13950+ }
13951+ channel = OMAP_DSS_CHANNEL_LCD;
13952+ }
13953+
13954+ oc = &dss_cache.overlay_cache[ovl->id];
13955+ i = 0;
13956+ while (1) {
13957+ unsigned long flags;
13958+ bool shadow_dirty, dirty;
13959+
13960+ spin_lock_irqsave(&dss_cache.lock, flags);
13961+ dirty = oc->dirty;
13962+ shadow_dirty = oc->shadow_dirty;
13963+ spin_unlock_irqrestore(&dss_cache.lock, flags);
13964+
13965+ if (!dirty && !shadow_dirty) {
13966+ r = 0;
13967+ break;
13968+ }
13969+
13970+ /* 4 iterations is the worst case:
13971+ * 1 - initial iteration, dirty = true (between VFP and VSYNC)
13972+ * 2 - first VSYNC, dirty = true
13973+ * 3 - dirty = false, shadow_dirty = true
13974+ * 4 - shadow_dirty = false */
13975+ if (i++ == 3) {
13976+ DSSERR("ovl(%d)->wait_for_go() not finishing\n",
13977+ ovl->id);
13978+ r = 0;
13979+ break;
13980+ }
13981+
13982+ r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
13983+ if (r == -ERESTARTSYS)
13984+ break;
13985+
13986+ if (r) {
13987+ DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
13988+ break;
13989+ }
13990+ }
13991+
13992+ return r;
13993+}
13994+
13995+static int overlay_enabled(struct omap_overlay *ovl)
13996+{
13997+ return ovl->info.enabled && ovl->manager && ovl->manager->device;
13998+}
13999+
14000+/* Is rect1 a subset of rect2? */
14001+static bool rectangle_subset(int x1, int y1, int w1, int h1,
14002+ int x2, int y2, int w2, int h2)
14003+{
14004+ if (x1 < x2 || y1 < y2)
14005+ return false;
14006+
14007+ if (x1 + w1 > x2 + w2)
14008+ return false;
14009+
14010+ if (y1 + h1 > y2 + h2)
14011+ return false;
14012+
14013+ return true;
14014+}
14015+
14016+/* Do rect1 and rect2 overlap? */
14017+static bool rectangle_intersects(int x1, int y1, int w1, int h1,
14018+ int x2, int y2, int w2, int h2)
14019+{
14020+ if (x1 >= x2 + w2)
14021+ return false;
14022+
14023+ if (x2 >= x1 + w1)
14024+ return false;
14025+
14026+ if (y1 >= y2 + h2)
14027+ return false;
14028+
14029+ if (y2 >= y1 + h1)
14030+ return false;
14031+
14032+ return true;
14033+}
14034+
14035+static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc)
14036+{
14037+ if (oc->out_width != 0 && oc->width != oc->out_width)
14038+ return true;
14039+
14040+ if (oc->out_height != 0 && oc->height != oc->out_height)
14041+ return true;
14042+
14043+ return false;
14044+}
14045+
14046+static int configure_overlay(enum omap_plane plane)
14047+{
14048+ struct overlay_cache_data *c;
14049+ struct manager_cache_data *mc;
14050+ u16 outw, outh;
14051+ u16 x, y, w, h;
14052+ u32 paddr;
14053+ int r;
14054+
14055+ DSSDBGF("%d", plane);
14056+
14057+ c = &dss_cache.overlay_cache[plane];
14058+
14059+ if (!c->enabled) {
14060+ dispc_enable_plane(plane, 0);
14061+ return 0;
14062+ }
14063+
14064+ mc = &dss_cache.manager_cache[c->channel];
14065+
14066+ x = c->pos_x;
14067+ y = c->pos_y;
14068+ w = c->width;
14069+ h = c->height;
14070+ outw = c->out_width == 0 ? c->width : c->out_width;
14071+ outh = c->out_height == 0 ? c->height : c->out_height;
14072+ paddr = c->paddr;
14073+
14074+ if (c->manual_update && mc->do_manual_update) {
14075+ unsigned bpp;
14076+ /* If the overlay is outside the update region, disable it */
14077+ if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
14078+ x, y, outw, outh)) {
14079+ dispc_enable_plane(plane, 0);
14080+ return 0;
14081+ }
14082+
14083+ switch (c->color_mode) {
14084+ case OMAP_DSS_COLOR_RGB16:
14085+ case OMAP_DSS_COLOR_ARGB16:
14086+ case OMAP_DSS_COLOR_YUV2:
14087+ case OMAP_DSS_COLOR_UYVY:
14088+ bpp = 16;
14089+ break;
14090+
14091+ case OMAP_DSS_COLOR_RGB24P:
14092+ bpp = 24;
14093+ break;
14094+
14095+ case OMAP_DSS_COLOR_RGB24U:
14096+ case OMAP_DSS_COLOR_ARGB32:
14097+ case OMAP_DSS_COLOR_RGBA32:
14098+ case OMAP_DSS_COLOR_RGBX32:
14099+ bpp = 32;
14100+ break;
14101+
14102+ default:
14103+ BUG();
14104+ }
14105+
14106+ if (dispc_is_overlay_scaled(c)) {
14107+ /* If the overlay is scaled, the update area has
14108+ * already been enlarged to cover the whole overlay. We
14109+ * only need to adjust x/y here */
14110+ x = c->pos_x - mc->x;
14111+ y = c->pos_y - mc->y;
14112+ } else {
14113+ if (mc->x > c->pos_x) {
14114+ x = 0;
14115+ w -= (mc->x - c->pos_x);
14116+ paddr += (mc->x - c->pos_x) * bpp / 8;
14117+ } else {
14118+ x = c->pos_x - mc->x;
14119+ }
14120+
14121+ if (mc->y > c->pos_y) {
14122+ y = 0;
14123+ h -= (mc->y - c->pos_y);
14124+ paddr += (mc->y - c->pos_y) * c->screen_width *
14125+ bpp / 8;
14126+ } else {
14127+ y = c->pos_y - mc->y;
14128+ }
14129+
14130+ if (mc->w < (x+w))
14131+ w -= (x+w) - (mc->w);
14132+
14133+ if (mc->h < (y+h))
14134+ h -= (y+h) - (mc->h);
14135+
14136+ outw = w;
14137+ outh = h;
14138+ }
14139+ }
14140+
14141+ r = dispc_setup_plane(plane,
14142+ paddr,
14143+ c->screen_width,
14144+ x, y,
14145+ w, h,
14146+ outw, outh,
14147+ c->color_mode,
14148+ c->ilace,
14149+ c->rotation_type,
14150+ c->rotation,
14151+ c->mirror,
14152+ c->global_alpha);
14153+
14154+ if (r) {
14155+ /* this shouldn't happen */
14156+ DSSERR("dispc_setup_plane failed for ovl %d\n", plane);
14157+ dispc_enable_plane(plane, 0);
14158+ return r;
14159+ }
14160+
14161+ dispc_enable_replication(plane, c->replication);
14162+
14163+ dispc_set_burst_size(plane, c->burst_size);
14164+ dispc_setup_plane_fifo(plane, c->fifo_low, c->fifo_high);
14165+
14166+ dispc_enable_plane(plane, 1);
14167+
14168+ return 0;
14169+}
14170+
14171+static void configure_manager(enum omap_channel channel)
14172+{
14173+ struct manager_cache_data *c;
14174+
14175+ DSSDBGF("%d", channel);
14176+
14177+ c = &dss_cache.manager_cache[channel];
14178+
14179+ dispc_set_trans_key(channel, c->trans_key_type, c->trans_key);
14180+ dispc_enable_trans_key(channel, c->trans_enabled);
14181+ dispc_enable_alpha_blending(channel, c->alpha_enabled);
14182+}
14183+
14184+/* configure_dispc() tries to write values from cache to shadow registers.
14185+ * It writes only to those managers/overlays that are not busy.
14186+ * returns 0 if everything could be written to shadow registers.
14187+ * returns 1 if not everything could be written to shadow registers. */
14188+static int configure_dispc(void)
14189+{
14190+ struct overlay_cache_data *oc;
14191+ struct manager_cache_data *mc;
14192+ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
14193+ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
14194+ int i;
14195+ int r;
14196+ bool mgr_busy[2];
14197+ bool mgr_go[2];
14198+ bool busy;
14199+
14200+ r = 0;
14201+ busy = false;
14202+
14203+ mgr_busy[0] = dispc_go_busy(0);
14204+ mgr_busy[1] = dispc_go_busy(1);
14205+ mgr_go[0] = false;
14206+ mgr_go[1] = false;
14207+
14208+ /* Commit overlay settings */
14209+ for (i = 0; i < num_ovls; ++i) {
14210+ oc = &dss_cache.overlay_cache[i];
14211+ mc = &dss_cache.manager_cache[oc->channel];
14212+
14213+ if (!oc->dirty)
14214+ continue;
14215+
14216+ if (oc->manual_update && !mc->do_manual_update)
14217+ continue;
14218+
14219+ if (mgr_busy[oc->channel]) {
14220+ busy = true;
14221+ continue;
14222+ }
14223+
14224+ r = configure_overlay(i);
14225+ if (r)
14226+ DSSERR("configure_overlay %d failed\n", i);
14227+
14228+ oc->dirty = false;
14229+ oc->shadow_dirty = true;
14230+ mgr_go[oc->channel] = true;
14231+ }
14232+
14233+ /* Commit manager settings */
14234+ for (i = 0; i < num_mgrs; ++i) {
14235+ mc = &dss_cache.manager_cache[i];
14236+
14237+ if (!mc->dirty)
14238+ continue;
14239+
14240+ if (mc->manual_update && !mc->do_manual_update)
14241+ continue;
14242+
14243+ if (mgr_busy[i]) {
14244+ busy = true;
14245+ continue;
14246+ }
14247+
14248+ configure_manager(i);
14249+ mc->dirty = false;
14250+ mc->shadow_dirty = true;
14251+ mgr_go[i] = true;
14252+ }
14253+
14254+ /* set GO */
14255+ for (i = 0; i < num_mgrs; ++i) {
14256+ mc = &dss_cache.manager_cache[i];
14257+
14258+ if (!mgr_go[i])
14259+ continue;
14260+
14261+ /* We don't need GO with manual update display. LCD iface will
14262+ * always be turned off after frame, and new settings will be
14263+ * taken in to use at next update */
14264+ if (!mc->manual_upd_display)
14265+ dispc_go(i);
14266+ }
14267+
14268+ if (busy)
14269+ r = 1;
14270+ else
14271+ r = 0;
14272+
14273+ return r;
14274+}
14275+
14276+/* Configure dispc for partial update. Return possibly modified update
14277+ * area */
14278+void dss_setup_partial_planes(struct omap_dss_device *dssdev,
14279+ u16 *xi, u16 *yi, u16 *wi, u16 *hi)
14280+{
14281+ struct overlay_cache_data *oc;
14282+ struct manager_cache_data *mc;
14283+ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
14284+ struct omap_overlay_manager *mgr;
14285+ int i;
14286+ u16 x, y, w, h;
14287+ unsigned long flags;
14288+
14289+ x = *xi;
14290+ y = *yi;
14291+ w = *wi;
14292+ h = *hi;
14293+
14294+ DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n",
14295+ *xi, *yi, *wi, *hi);
14296+
14297+ mgr = dssdev->manager;
14298+
14299+ if (!mgr) {
14300+ DSSDBG("no manager\n");
14301+ return;
14302+ }
14303+
14304+ spin_lock_irqsave(&dss_cache.lock, flags);
14305+
14306+ /* We need to show the whole overlay if it is scaled. So look for
14307+ * those, and make the update area larger if found.
14308+ * Also mark the overlay cache dirty */
14309+ for (i = 0; i < num_ovls; ++i) {
14310+ unsigned x1, y1, x2, y2;
14311+ unsigned outw, outh;
14312+
14313+ oc = &dss_cache.overlay_cache[i];
14314+
14315+ if (oc->channel != mgr->id)
14316+ continue;
14317+
14318+ oc->dirty = true;
14319+
14320+ if (!oc->enabled)
14321+ continue;
14322+
14323+ if (!dispc_is_overlay_scaled(oc))
14324+ continue;
14325+
14326+ outw = oc->out_width == 0 ? oc->width : oc->out_width;
14327+ outh = oc->out_height == 0 ? oc->height : oc->out_height;
14328+
14329+ /* is the overlay outside the update region? */
14330+ if (!rectangle_intersects(x, y, w, h,
14331+ oc->pos_x, oc->pos_y,
14332+ outw, outh))
14333+ continue;
14334+
14335+ /* if the overlay totally inside the update region? */
14336+ if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
14337+ x, y, w, h))
14338+ continue;
14339+
14340+ if (x > oc->pos_x)
14341+ x1 = oc->pos_x;
14342+ else
14343+ x1 = x;
14344+
14345+ if (y > oc->pos_y)
14346+ y1 = oc->pos_y;
14347+ else
14348+ y1 = y;
14349+
14350+ if ((x + w) < (oc->pos_x + outw))
14351+ x2 = oc->pos_x + outw;
14352+ else
14353+ x2 = x + w;
14354+
14355+ if ((y + h) < (oc->pos_y + outh))
14356+ y2 = oc->pos_y + outh;
14357+ else
14358+ y2 = y + h;
14359+
14360+ x = x1;
14361+ y = y1;
14362+ w = x2 - x1;
14363+ h = y2 - y1;
14364+
14365+ DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n",
14366+ i, x, y, w, h);
14367+ }
14368+
14369+ mc = &dss_cache.manager_cache[mgr->id];
14370+ mc->do_manual_update = true;
14371+ mc->x = x;
14372+ mc->y = y;
14373+ mc->w = w;
14374+ mc->h = h;
14375+
14376+ configure_dispc();
14377+
14378+ mc->do_manual_update = false;
14379+
14380+ spin_unlock_irqrestore(&dss_cache.lock, flags);
14381+
14382+ *xi = x;
14383+ *yi = y;
14384+ *wi = w;
14385+ *hi = h;
14386+}
14387+
14388+void dss_start_update(struct omap_dss_device *dssdev)
14389+{
14390+ struct manager_cache_data *mc;
14391+ struct overlay_cache_data *oc;
14392+ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
14393+ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
14394+ struct omap_overlay_manager *mgr;
14395+ int i;
14396+
14397+ mgr = dssdev->manager;
14398+
14399+ for (i = 0; i < num_ovls; ++i) {
14400+ oc = &dss_cache.overlay_cache[i];
14401+ if (oc->channel != mgr->id)
14402+ continue;
14403+
14404+ oc->shadow_dirty = false;
14405+ }
14406+
14407+ for (i = 0; i < num_mgrs; ++i) {
14408+ mc = &dss_cache.manager_cache[i];
14409+ if (mgr->id != i)
14410+ continue;
14411+
14412+ mc->shadow_dirty = false;
14413+ }
14414+
14415+ dispc_enable_lcd_out(1);
14416+}
14417+
14418+static void dss_apply_irq_handler(void *data, u32 mask)
14419+{
14420+ struct manager_cache_data *mc;
14421+ struct overlay_cache_data *oc;
14422+ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
14423+ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
14424+ int i, r;
14425+ bool mgr_busy[2];
14426+
14427+ mgr_busy[0] = dispc_go_busy(0);
14428+ mgr_busy[1] = dispc_go_busy(1);
14429+
14430+ spin_lock(&dss_cache.lock);
14431+
14432+ for (i = 0; i < num_ovls; ++i) {
14433+ oc = &dss_cache.overlay_cache[i];
14434+ if (!mgr_busy[oc->channel])
14435+ oc->shadow_dirty = false;
14436+ }
14437+
14438+ for (i = 0; i < num_mgrs; ++i) {
14439+ mc = &dss_cache.manager_cache[i];
14440+ if (!mgr_busy[i])
14441+ mc->shadow_dirty = false;
14442+ }
14443+
14444+ r = configure_dispc();
14445+ if (r == 1)
14446+ goto end;
14447+
14448+ /* re-read busy flags */
14449+ mgr_busy[0] = dispc_go_busy(0);
14450+ mgr_busy[1] = dispc_go_busy(1);
14451+
14452+ /* keep running as long as there are busy managers, so that
14453+ * we can collect overlay-applied information */
14454+ for (i = 0; i < num_mgrs; ++i) {
14455+ if (mgr_busy[i])
14456+ goto end;
14457+ }
14458+
14459+ omap_dispc_unregister_isr(dss_apply_irq_handler, NULL,
14460+ DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
14461+ DISPC_IRQ_EVSYNC_EVEN);
14462+ dss_cache.irq_enabled = false;
14463+
14464+end:
14465+ spin_unlock(&dss_cache.lock);
14466+}
14467+
14468+static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
14469+{
14470+ struct overlay_cache_data *oc;
14471+ struct manager_cache_data *mc;
14472+ int i;
14473+ struct omap_overlay *ovl;
14474+ int num_planes_enabled = 0;
14475+ bool use_fifomerge;
14476+ unsigned long flags;
14477+ int r;
14478+
14479+ DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
14480+
14481+ spin_lock_irqsave(&dss_cache.lock, flags);
14482+
14483+ /* Configure overlays */
14484+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
14485+ struct omap_dss_device *dssdev;
14486+
14487+ ovl = omap_dss_get_overlay(i);
14488+
14489+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
14490+ continue;
14491+
14492+ oc = &dss_cache.overlay_cache[ovl->id];
14493+
14494+ if (!overlay_enabled(ovl)) {
14495+ if (oc->enabled) {
14496+ oc->enabled = false;
14497+ oc->dirty = true;
14498+ }
14499+ continue;
14500+ }
14501+
14502+ if (!ovl->info_dirty) {
14503+ if (oc->enabled)
14504+ ++num_planes_enabled;
14505+ continue;
14506+ }
14507+
14508+ dssdev = ovl->manager->device;
14509+
14510+ if (dss_check_overlay(ovl, dssdev)) {
14511+ if (oc->enabled) {
14512+ oc->enabled = false;
14513+ oc->dirty = true;
14514+ }
14515+ continue;
14516+ }
14517+
14518+ ovl->info_dirty = false;
14519+ oc->dirty = true;
14520+
14521+ oc->paddr = ovl->info.paddr;
14522+ oc->vaddr = ovl->info.vaddr;
14523+ oc->screen_width = ovl->info.screen_width;
14524+ oc->width = ovl->info.width;
14525+ oc->height = ovl->info.height;
14526+ oc->color_mode = ovl->info.color_mode;
14527+ oc->rotation = ovl->info.rotation;
14528+ oc->rotation_type = ovl->info.rotation_type;
14529+ oc->mirror = ovl->info.mirror;
14530+ oc->pos_x = ovl->info.pos_x;
14531+ oc->pos_y = ovl->info.pos_y;
14532+ oc->out_width = ovl->info.out_width;
14533+ oc->out_height = ovl->info.out_height;
14534+ oc->global_alpha = ovl->info.global_alpha;
14535+
14536+ oc->replication =
14537+ dss_use_replication(dssdev, ovl->info.color_mode);
14538+
14539+ oc->ilace = dssdev->type == OMAP_DISPLAY_TYPE_VENC;
14540+
14541+ oc->channel = ovl->manager->id;
14542+
14543+ oc->enabled = true;
14544+
14545+ oc->manual_update =
14546+ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
14547+ dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO;
14548+
14549+ ++num_planes_enabled;
14550+ }
14551+
14552+ /* Configure managers */
14553+ list_for_each_entry(mgr, &manager_list, list) {
14554+ struct omap_dss_device *dssdev;
14555+
14556+ if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
14557+ continue;
14558+
14559+ mc = &dss_cache.manager_cache[mgr->id];
14560+
14561+ if (mgr->device_changed) {
14562+ mgr->device_changed = false;
14563+ mgr->info_dirty = true;
14564+ }
14565+
14566+ if (!mgr->info_dirty)
14567+ continue;
14568+
14569+ if (!mgr->device)
14570+ continue;
14571+
14572+ dssdev = mgr->device;
14573+
14574+ mgr->info_dirty = false;
14575+ mc->dirty = true;
14576+
14577+ mc->default_color = mgr->info.default_color;
14578+ mc->trans_key_type = mgr->info.trans_key_type;
14579+ mc->trans_key = mgr->info.trans_key;
14580+ mc->trans_enabled = mgr->info.trans_enabled;
14581+ mc->alpha_enabled = mgr->info.alpha_enabled;
14582+
14583+ mc->manual_upd_display =
14584+ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
14585+
14586+ mc->manual_update =
14587+ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
14588+ dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO;
14589+ }
14590+
14591+ /* XXX TODO: Try to get fifomerge working. The problem is that it
14592+ * affects both managers, not individually but at the same time. This
14593+ * means the change has to be well synchronized. I guess the proper way
14594+ * is to have a two step process for fifo merge:
14595+ * fifomerge enable:
14596+ * 1. disable other planes, leaving one plane enabled
14597+ * 2. wait until the planes are disabled on HW
14598+ * 3. config merged fifo thresholds, enable fifomerge
14599+ * fifomerge disable:
14600+ * 1. config unmerged fifo thresholds, disable fifomerge
14601+ * 2. wait until fifo changes are in HW
14602+ * 3. enable planes
14603+ */
14604+ use_fifomerge = false;
14605+
14606+ /* Configure overlay fifos */
14607+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
14608+ struct omap_dss_device *dssdev;
14609+ u32 size;
14610+
14611+ ovl = omap_dss_get_overlay(i);
14612+
14613+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
14614+ continue;
14615+
14616+ oc = &dss_cache.overlay_cache[ovl->id];
14617+
14618+ if (!oc->enabled)
14619+ continue;
14620+
14621+ dssdev = ovl->manager->device;
14622+
14623+ size = dispc_get_plane_fifo_size(ovl->id);
14624+ if (use_fifomerge)
14625+ size *= 3;
14626+
14627+ switch (dssdev->type) {
14628+ case OMAP_DISPLAY_TYPE_DPI:
14629+ case OMAP_DISPLAY_TYPE_DBI:
14630+ case OMAP_DISPLAY_TYPE_SDI:
14631+ case OMAP_DISPLAY_TYPE_VENC:
14632+ default_get_overlay_fifo_thresholds(ovl->id, size,
14633+ &oc->burst_size, &oc->fifo_low,
14634+ &oc->fifo_high);
14635+ break;
14636+#ifdef CONFIG_OMAP2_DSS_DSI
14637+ case OMAP_DISPLAY_TYPE_DSI:
14638+ dsi_get_overlay_fifo_thresholds(ovl->id, size,
14639+ &oc->burst_size, &oc->fifo_low,
14640+ &oc->fifo_high);
14641+ break;
14642+#endif
14643+ default:
14644+ BUG();
14645+ }
14646+ }
14647+
14648+ r = 0;
14649+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
14650+ if (!dss_cache.irq_enabled) {
14651+ r = omap_dispc_register_isr(dss_apply_irq_handler, NULL,
14652+ DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
14653+ DISPC_IRQ_EVSYNC_EVEN);
14654+ dss_cache.irq_enabled = true;
14655+ }
14656+ configure_dispc();
14657+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
14658+
14659+ spin_unlock_irqrestore(&dss_cache.lock, flags);
14660+
14661+ return r;
14662+}
14663+
14664+static int dss_check_manager(struct omap_overlay_manager *mgr)
14665+{
14666+ /* OMAP supports only graphics source transparency color key and alpha
14667+ * blending simultaneously. See TRM 15.4.2.4.2.2 Alpha Mode */
14668+
14669+ if (mgr->info.alpha_enabled && mgr->info.trans_enabled &&
14670+ mgr->info.trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST)
14671+ return -EINVAL;
14672+
14673+ return 0;
14674+}
14675+
14676+static int omap_dss_mgr_set_info(struct omap_overlay_manager *mgr,
14677+ struct omap_overlay_manager_info *info)
14678+{
14679+ int r;
14680+ struct omap_overlay_manager_info old_info;
14681+
14682+ old_info = mgr->info;
14683+ mgr->info = *info;
14684+
14685+ r = dss_check_manager(mgr);
14686+ if (r) {
14687+ mgr->info = old_info;
14688+ return r;
14689+ }
14690+
14691+ mgr->info_dirty = true;
14692+
14693+ return 0;
14694+}
14695+
14696+static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,
14697+ struct omap_overlay_manager_info *info)
14698+{
14699+ *info = mgr->info;
14700+}
14701+
14702+static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
14703+{
14704+ ++num_managers;
14705+ list_add_tail(&manager->list, &manager_list);
14706+}
14707+
14708+int dss_init_overlay_managers(struct platform_device *pdev)
14709+{
14710+ int i, r;
14711+
14712+ spin_lock_init(&dss_cache.lock);
14713+
14714+ INIT_LIST_HEAD(&manager_list);
14715+
14716+ num_managers = 0;
14717+
14718+ for (i = 0; i < 2; ++i) {
14719+ struct omap_overlay_manager *mgr;
14720+ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
14721+
14722+ BUG_ON(mgr == NULL);
14723+
14724+ switch (i) {
14725+ case 0:
14726+ mgr->name = "lcd";
14727+ mgr->id = OMAP_DSS_CHANNEL_LCD;
14728+ mgr->supported_displays =
14729+ OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
14730+ OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI;
14731+ break;
14732+ case 1:
14733+ mgr->name = "tv";
14734+ mgr->id = OMAP_DSS_CHANNEL_DIGIT;
14735+ mgr->supported_displays = OMAP_DISPLAY_TYPE_VENC;
14736+ break;
14737+ }
14738+
14739+ mgr->set_device = &omap_dss_set_device;
14740+ mgr->unset_device = &omap_dss_unset_device;
14741+ mgr->apply = &omap_dss_mgr_apply;
14742+ mgr->set_manager_info = &omap_dss_mgr_set_info;
14743+ mgr->get_manager_info = &omap_dss_mgr_get_info;
14744+ mgr->wait_for_go = &dss_mgr_wait_for_go;
14745+
14746+ mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
14747+
14748+ dss_overlay_setup_dispc_manager(mgr);
14749+
14750+ omap_dss_add_overlay_manager(mgr);
14751+
14752+ r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
14753+ &pdev->dev.kobj, "manager%d", i);
14754+
14755+ if (r) {
14756+ DSSERR("failed to create sysfs file\n");
14757+ continue;
14758+ }
14759+ }
14760+
14761+#ifdef L4_EXAMPLE
14762+ {
14763+ int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr)
14764+ {
14765+ DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);
14766+
14767+ return 0;
14768+ }
14769+
14770+ struct omap_overlay_manager *mgr;
14771+ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
14772+
14773+ BUG_ON(mgr == NULL);
14774+
14775+ mgr->name = "l4";
14776+ mgr->supported_displays =
14777+ OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI;
14778+
14779+ mgr->set_device = &omap_dss_set_device;
14780+ mgr->unset_device = &omap_dss_unset_device;
14781+ mgr->apply = &omap_dss_mgr_apply_l4;
14782+ mgr->set_manager_info = &omap_dss_mgr_set_info;
14783+ mgr->get_manager_info = &omap_dss_mgr_get_info;
14784+
14785+ dss_overlay_setup_l4_manager(mgr);
14786+
14787+ omap_dss_add_overlay_manager(mgr);
14788+
14789+ r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
14790+ &pdev->dev.kobj, "managerl4");
14791+
14792+ if (r)
14793+ DSSERR("failed to create sysfs file\n");
14794+ }
14795+#endif
14796+
14797+ return 0;
14798+}
14799+
14800+void dss_uninit_overlay_managers(struct platform_device *pdev)
14801+{
14802+ struct omap_overlay_manager *mgr;
14803+
14804+ while (!list_empty(&manager_list)) {
14805+ mgr = list_first_entry(&manager_list,
14806+ struct omap_overlay_manager, list);
14807+ list_del(&mgr->list);
14808+ kobject_del(&mgr->kobj);
14809+ kobject_put(&mgr->kobj);
14810+ kfree(mgr);
14811+ }
14812+
14813+ num_managers = 0;
14814+}
14815+
14816+int omap_dss_get_num_overlay_managers(void)
14817+{
14818+ return num_managers;
14819+}
14820+EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
14821+
14822+struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
14823+{
14824+ int i = 0;
14825+ struct omap_overlay_manager *mgr;
14826+
14827+ list_for_each_entry(mgr, &manager_list, list) {
14828+ if (i++ == num)
14829+ return mgr;
14830+ }
14831+
14832+ return NULL;
14833+}
14834+EXPORT_SYMBOL(omap_dss_get_overlay_manager);
14835+
14836--- /dev/null
14837+++ b/drivers/video/omap2/dss/overlay.c
14838@@ -0,0 +1,673 @@
14839+/*
14840+ * linux/drivers/video/omap2/dss/overlay.c
14841+ *
14842+ * Copyright (C) 2009 Nokia Corporation
14843+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
14844+ *
14845+ * Some code and ideas taken from drivers/video/omap/ driver
14846+ * by Imre Deak.
14847+ *
14848+ * This program is free software; you can redistribute it and/or modify it
14849+ * under the terms of the GNU General Public License version 2 as published by
14850+ * the Free Software Foundation.
14851+ *
14852+ * This program is distributed in the hope that it will be useful, but WITHOUT
14853+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14854+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14855+ * more details.
14856+ *
14857+ * You should have received a copy of the GNU General Public License along with
14858+ * this program. If not, see <http://www.gnu.org/licenses/>.
14859+ */
14860+
14861+#define DSS_SUBSYS_NAME "OVERLAY"
14862+
14863+#include <linux/kernel.h>
14864+#include <linux/module.h>
14865+#include <linux/err.h>
14866+#include <linux/sysfs.h>
14867+#include <linux/kobject.h>
14868+#include <linux/platform_device.h>
14869+#include <linux/delay.h>
14870+
14871+#include <mach/display.h>
14872+
14873+#include "dss.h"
14874+
14875+static int num_overlays;
14876+static struct list_head overlay_list;
14877+
14878+static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
14879+{
14880+ return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
14881+}
14882+
14883+static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
14884+{
14885+ return snprintf(buf, PAGE_SIZE, "%s\n",
14886+ ovl->manager ? ovl->manager->name : "<none>");
14887+}
14888+
14889+static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
14890+ size_t size)
14891+{
14892+ int i, r;
14893+ struct omap_overlay_manager *mgr = NULL;
14894+ struct omap_overlay_manager *old_mgr;
14895+ int len = size;
14896+
14897+ if (buf[size-1] == '\n')
14898+ --len;
14899+
14900+ if (len > 0) {
14901+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
14902+ mgr = omap_dss_get_overlay_manager(i);
14903+
14904+ if (strncmp(buf, mgr->name, len) == 0)
14905+ break;
14906+
14907+ mgr = NULL;
14908+ }
14909+ }
14910+
14911+ if (len > 0 && mgr == NULL)
14912+ return -EINVAL;
14913+
14914+ if (mgr)
14915+ DSSDBG("manager %s found\n", mgr->name);
14916+
14917+ if (mgr == ovl->manager)
14918+ return size;
14919+
14920+ old_mgr = ovl->manager;
14921+
14922+ /* detach old manager */
14923+ if (old_mgr) {
14924+ r = ovl->unset_manager(ovl);
14925+ if (r) {
14926+ DSSERR("detach failed\n");
14927+ return r;
14928+ }
14929+
14930+ r = old_mgr->apply(old_mgr);
14931+ if (r)
14932+ return r;
14933+ }
14934+
14935+ if (mgr) {
14936+ r = ovl->set_manager(ovl, mgr);
14937+ if (r) {
14938+ DSSERR("Failed to attach overlay\n");
14939+ return r;
14940+ }
14941+
14942+ r = mgr->apply(mgr);
14943+ if (r)
14944+ return r;
14945+ }
14946+
14947+ return size;
14948+}
14949+
14950+static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
14951+{
14952+ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
14953+ ovl->info.width, ovl->info.height);
14954+}
14955+
14956+static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
14957+{
14958+ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.screen_width);
14959+}
14960+
14961+static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
14962+{
14963+ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
14964+ ovl->info.pos_x, ovl->info.pos_y);
14965+}
14966+
14967+static ssize_t overlay_position_store(struct omap_overlay *ovl,
14968+ const char *buf, size_t size)
14969+{
14970+ int r;
14971+ char *last;
14972+ struct omap_overlay_info info;
14973+
14974+ ovl->get_overlay_info(ovl, &info);
14975+
14976+ info.pos_x = simple_strtoul(buf, &last, 10);
14977+ ++last;
14978+ if (last - buf >= size)
14979+ return -EINVAL;
14980+
14981+ info.pos_y = simple_strtoul(last, &last, 10);
14982+
14983+ r = ovl->set_overlay_info(ovl, &info);
14984+ if (r)
14985+ return r;
14986+
14987+ if (ovl->manager) {
14988+ r = ovl->manager->apply(ovl->manager);
14989+ if (r)
14990+ return r;
14991+ }
14992+
14993+ return size;
14994+}
14995+
14996+static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
14997+{
14998+ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
14999+ ovl->info.out_width, ovl->info.out_height);
15000+}
15001+
15002+static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
15003+ const char *buf, size_t size)
15004+{
15005+ int r;
15006+ char *last;
15007+ struct omap_overlay_info info;
15008+
15009+ ovl->get_overlay_info(ovl, &info);
15010+
15011+ info.out_width = simple_strtoul(buf, &last, 10);
15012+ ++last;
15013+ if (last - buf >= size)
15014+ return -EINVAL;
15015+
15016+ info.out_height = simple_strtoul(last, &last, 10);
15017+
15018+ r = ovl->set_overlay_info(ovl, &info);
15019+ if (r)
15020+ return r;
15021+
15022+ if (ovl->manager) {
15023+ r = ovl->manager->apply(ovl->manager);
15024+ if (r)
15025+ return r;
15026+ }
15027+
15028+ return size;
15029+}
15030+
15031+static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
15032+{
15033+ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled);
15034+}
15035+
15036+static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
15037+ size_t size)
15038+{
15039+ int r;
15040+ struct omap_overlay_info info;
15041+
15042+ ovl->get_overlay_info(ovl, &info);
15043+
15044+ info.enabled = simple_strtoul(buf, NULL, 10);
15045+
15046+ r = ovl->set_overlay_info(ovl, &info);
15047+ if (r)
15048+ return r;
15049+
15050+ if (ovl->manager) {
15051+ r = ovl->manager->apply(ovl->manager);
15052+ if (r)
15053+ return r;
15054+ }
15055+
15056+ return size;
15057+}
15058+
15059+static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
15060+{
15061+ return snprintf(buf, PAGE_SIZE, "%d\n",
15062+ ovl->info.global_alpha);
15063+}
15064+
15065+static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
15066+ const char *buf, size_t size)
15067+{
15068+ int r;
15069+ struct omap_overlay_info info;
15070+
15071+ ovl->get_overlay_info(ovl, &info);
15072+
15073+ /* Video1 plane does not support global alpha
15074+ * to always make it 255 completely opaque
15075+ */
15076+ if (ovl->id == OMAP_DSS_VIDEO1)
15077+ info.global_alpha = 255;
15078+ else
15079+ info.global_alpha = simple_strtoul(buf, NULL, 10);
15080+
15081+ r = ovl->set_overlay_info(ovl, &info);
15082+ if (r)
15083+ return r;
15084+
15085+ if (ovl->manager) {
15086+ r = ovl->manager->apply(ovl->manager);
15087+ if (r)
15088+ return r;
15089+ }
15090+
15091+ return size;
15092+}
15093+
15094+struct overlay_attribute {
15095+ struct attribute attr;
15096+ ssize_t (*show)(struct omap_overlay *, char *);
15097+ ssize_t (*store)(struct omap_overlay *, const char *, size_t);
15098+};
15099+
15100+#define OVERLAY_ATTR(_name, _mode, _show, _store) \
15101+ struct overlay_attribute overlay_attr_##_name = \
15102+ __ATTR(_name, _mode, _show, _store)
15103+
15104+static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
15105+static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
15106+ overlay_manager_show, overlay_manager_store);
15107+static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
15108+static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
15109+static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
15110+ overlay_position_show, overlay_position_store);
15111+static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
15112+ overlay_output_size_show, overlay_output_size_store);
15113+static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
15114+ overlay_enabled_show, overlay_enabled_store);
15115+static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
15116+ overlay_global_alpha_show, overlay_global_alpha_store);
15117+
15118+static struct attribute *overlay_sysfs_attrs[] = {
15119+ &overlay_attr_name.attr,
15120+ &overlay_attr_manager.attr,
15121+ &overlay_attr_input_size.attr,
15122+ &overlay_attr_screen_width.attr,
15123+ &overlay_attr_position.attr,
15124+ &overlay_attr_output_size.attr,
15125+ &overlay_attr_enabled.attr,
15126+ &overlay_attr_global_alpha.attr,
15127+ NULL
15128+};
15129+
15130+static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
15131+ char *buf)
15132+{
15133+ struct omap_overlay *overlay;
15134+ struct overlay_attribute *overlay_attr;
15135+
15136+ overlay = container_of(kobj, struct omap_overlay, kobj);
15137+ overlay_attr = container_of(attr, struct overlay_attribute, attr);
15138+
15139+ if (!overlay_attr->show)
15140+ return -ENOENT;
15141+
15142+ return overlay_attr->show(overlay, buf);
15143+}
15144+
15145+static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
15146+ const char *buf, size_t size)
15147+{
15148+ struct omap_overlay *overlay;
15149+ struct overlay_attribute *overlay_attr;
15150+
15151+ overlay = container_of(kobj, struct omap_overlay, kobj);
15152+ overlay_attr = container_of(attr, struct overlay_attribute, attr);
15153+
15154+ if (!overlay_attr->store)
15155+ return -ENOENT;
15156+
15157+ return overlay_attr->store(overlay, buf, size);
15158+}
15159+
15160+static struct sysfs_ops overlay_sysfs_ops = {
15161+ .show = overlay_attr_show,
15162+ .store = overlay_attr_store,
15163+};
15164+
15165+static struct kobj_type overlay_ktype = {
15166+ .sysfs_ops = &overlay_sysfs_ops,
15167+ .default_attrs = overlay_sysfs_attrs,
15168+};
15169+
15170+/* Check if overlay parameters are compatible with display */
15171+int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
15172+{
15173+ struct omap_overlay_info *info;
15174+ u16 outw, outh;
15175+ u16 dw, dh;
15176+
15177+ if (!dssdev)
15178+ return 0;
15179+
15180+ if (!ovl->info.enabled)
15181+ return 0;
15182+
15183+ info = &ovl->info;
15184+
15185+ if (info->paddr == 0) {
15186+ DSSDBG("check_overlay failed: paddr 0\n");
15187+ return -EINVAL;
15188+ }
15189+
15190+ dssdev->get_resolution(dssdev, &dw, &dh);
15191+
15192+ DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n",
15193+ ovl->id,
15194+ info->pos_x, info->pos_y,
15195+ info->width, info->height,
15196+ info->out_width, info->out_height,
15197+ dw, dh);
15198+
15199+ if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
15200+ outw = info->width;
15201+ outh = info->height;
15202+ } else {
15203+ if (info->out_width == 0)
15204+ outw = info->width;
15205+ else
15206+ outw = info->out_width;
15207+
15208+ if (info->out_height == 0)
15209+ outh = info->height;
15210+ else
15211+ outh = info->out_height;
15212+ }
15213+
15214+ if (dw < info->pos_x + outw) {
15215+ DSSDBG("check_overlay failed 1: %d < %d + %d\n",
15216+ dw, info->pos_x, outw);
15217+ return -EINVAL;
15218+ }
15219+
15220+ if (dh < info->pos_y + outh) {
15221+ DSSDBG("check_overlay failed 2: %d < %d + %d\n",
15222+ dh, info->pos_y, outh);
15223+ return -EINVAL;
15224+ }
15225+
15226+ if ((ovl->supported_modes & info->color_mode) == 0) {
15227+ DSSERR("overlay doesn't support mode %d\n", info->color_mode);
15228+ return -EINVAL;
15229+ }
15230+
15231+ return 0;
15232+}
15233+
15234+static int dss_ovl_set_overlay_info(struct omap_overlay *ovl,
15235+ struct omap_overlay_info *info)
15236+{
15237+ int r;
15238+ struct omap_overlay_info old_info;
15239+
15240+ old_info = ovl->info;
15241+ ovl->info = *info;
15242+
15243+ if (ovl->manager) {
15244+ r = dss_check_overlay(ovl, ovl->manager->device);
15245+ if (r) {
15246+ ovl->info = old_info;
15247+ return r;
15248+ }
15249+ }
15250+
15251+ ovl->info_dirty = true;
15252+
15253+ return 0;
15254+}
15255+
15256+static void dss_ovl_get_overlay_info(struct omap_overlay *ovl,
15257+ struct omap_overlay_info *info)
15258+{
15259+ *info = ovl->info;
15260+}
15261+
15262+static int dss_ovl_wait_for_go(struct omap_overlay *ovl)
15263+{
15264+ return dss_mgr_wait_for_go_ovl(ovl);
15265+}
15266+
15267+static int omap_dss_set_manager(struct omap_overlay *ovl,
15268+ struct omap_overlay_manager *mgr)
15269+{
15270+ if (!mgr)
15271+ return -EINVAL;
15272+
15273+ if (ovl->manager) {
15274+ DSSERR("overlay '%s' already has a manager '%s'\n",
15275+ ovl->name, ovl->manager->name);
15276+ return -EINVAL;
15277+ }
15278+
15279+ if (ovl->info.enabled) {
15280+ DSSERR("overlay has to be disabled to change the manager\n");
15281+ return -EINVAL;
15282+ }
15283+
15284+ ovl->manager = mgr;
15285+
15286+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
15287+ /* XXX: on manual update display, in auto update mode, a bug happens
15288+ * here. When an overlay is first enabled on LCD, then it's disabled,
15289+ * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT
15290+ * errors. Waiting before changing the channel_out fixes it. I'm
15291+ * guessing that the overlay is still somehow being used for the LCD,
15292+ * but I don't understand how or why. */
15293+ msleep(40);
15294+ dispc_set_channel_out(ovl->id, mgr->id);
15295+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
15296+
15297+ return 0;
15298+}
15299+
15300+static int omap_dss_unset_manager(struct omap_overlay *ovl)
15301+{
15302+ int r;
15303+
15304+ if (!ovl->manager) {
15305+ DSSERR("failed to detach overlay: manager not set\n");
15306+ return -EINVAL;
15307+ }
15308+
15309+ if (ovl->info.enabled) {
15310+ DSSERR("overlay has to be disabled to unset the manager\n");
15311+ return -EINVAL;
15312+ }
15313+
15314+ r = ovl->wait_for_go(ovl);
15315+ if (r)
15316+ return r;
15317+
15318+ ovl->manager = NULL;
15319+
15320+ return 0;
15321+}
15322+
15323+int omap_dss_get_num_overlays(void)
15324+{
15325+ return num_overlays;
15326+}
15327+EXPORT_SYMBOL(omap_dss_get_num_overlays);
15328+
15329+struct omap_overlay *omap_dss_get_overlay(int num)
15330+{
15331+ int i = 0;
15332+ struct omap_overlay *ovl;
15333+
15334+ list_for_each_entry(ovl, &overlay_list, list) {
15335+ if (i++ == num)
15336+ return ovl;
15337+ }
15338+
15339+ return NULL;
15340+}
15341+EXPORT_SYMBOL(omap_dss_get_overlay);
15342+
15343+static void omap_dss_add_overlay(struct omap_overlay *overlay)
15344+{
15345+ ++num_overlays;
15346+ list_add_tail(&overlay->list, &overlay_list);
15347+}
15348+
15349+static struct omap_overlay *dispc_overlays[3];
15350+
15351+void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
15352+{
15353+ mgr->num_overlays = 3;
15354+ mgr->overlays = dispc_overlays;
15355+}
15356+
15357+#ifdef L4_EXAMPLE
15358+static struct omap_overlay *l4_overlays[1];
15359+void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr)
15360+{
15361+ mgr->num_overlays = 1;
15362+ mgr->overlays = l4_overlays;
15363+}
15364+#endif
15365+
15366+void dss_init_overlays(struct platform_device *pdev)
15367+{
15368+ int i, r;
15369+
15370+ INIT_LIST_HEAD(&overlay_list);
15371+
15372+ num_overlays = 0;
15373+
15374+ for (i = 0; i < 3; ++i) {
15375+ struct omap_overlay *ovl;
15376+ ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
15377+
15378+ BUG_ON(ovl == NULL);
15379+
15380+ switch (i) {
15381+ case 0:
15382+ ovl->name = "gfx";
15383+ ovl->id = OMAP_DSS_GFX;
15384+ ovl->supported_modes = OMAP_DSS_COLOR_GFX_OMAP3;
15385+ ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
15386+ ovl->info.global_alpha = 255;
15387+ break;
15388+ case 1:
15389+ ovl->name = "vid1";
15390+ ovl->id = OMAP_DSS_VIDEO1;
15391+ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3;
15392+ ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
15393+ OMAP_DSS_OVL_CAP_DISPC;
15394+ ovl->info.global_alpha = 255;
15395+ break;
15396+ case 2:
15397+ ovl->name = "vid2";
15398+ ovl->id = OMAP_DSS_VIDEO2;
15399+ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3;
15400+ ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
15401+ OMAP_DSS_OVL_CAP_DISPC;
15402+ ovl->info.global_alpha = 255;
15403+ break;
15404+ }
15405+
15406+ ovl->set_manager = &omap_dss_set_manager;
15407+ ovl->unset_manager = &omap_dss_unset_manager;
15408+ ovl->set_overlay_info = &dss_ovl_set_overlay_info;
15409+ ovl->get_overlay_info = &dss_ovl_get_overlay_info;
15410+ ovl->wait_for_go = &dss_ovl_wait_for_go;
15411+
15412+ omap_dss_add_overlay(ovl);
15413+
15414+ r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
15415+ &pdev->dev.kobj, "overlay%d", i);
15416+
15417+ if (r) {
15418+ DSSERR("failed to create sysfs file\n");
15419+ continue;
15420+ }
15421+
15422+ dispc_overlays[i] = ovl;
15423+ }
15424+
15425+#ifdef L4_EXAMPLE
15426+ {
15427+ struct omap_overlay *ovl;
15428+ ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
15429+
15430+ BUG_ON(ovl == NULL);
15431+
15432+ ovl->name = "l4";
15433+ ovl->supported_modes = OMAP_DSS_COLOR_RGB24U;
15434+
15435+ ovl->set_manager = &omap_dss_set_manager;
15436+ ovl->unset_manager = &omap_dss_unset_manager;
15437+ ovl->set_overlay_info = &dss_ovl_set_overlay_info;
15438+ ovl->get_overlay_info = &dss_ovl_get_overlay_info;
15439+
15440+ omap_dss_add_overlay(ovl);
15441+
15442+ r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
15443+ &pdev->dev.kobj, "overlayl4");
15444+
15445+ if (r)
15446+ DSSERR("failed to create sysfs file\n");
15447+
15448+ l4_overlays[0] = ovl;
15449+ }
15450+#endif
15451+}
15452+
15453+/* connect overlays to the new device, if not already connected. if force
15454+ * selected, connect always. */
15455+void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
15456+{
15457+ int i;
15458+ struct omap_overlay_manager *lcd_mgr;
15459+ struct omap_overlay_manager *tv_mgr;
15460+ struct omap_overlay_manager *mgr = NULL;
15461+
15462+ lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD);
15463+ tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV);
15464+
15465+ if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) {
15466+ if (!lcd_mgr->device || force) {
15467+ if (lcd_mgr->device)
15468+ lcd_mgr->unset_device(lcd_mgr);
15469+ lcd_mgr->set_device(lcd_mgr, dssdev);
15470+ mgr = lcd_mgr;
15471+ }
15472+ }
15473+
15474+ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
15475+ if (!tv_mgr->device || force) {
15476+ if (tv_mgr->device)
15477+ tv_mgr->unset_device(tv_mgr);
15478+ tv_mgr->set_device(tv_mgr, dssdev);
15479+ mgr = tv_mgr;
15480+ }
15481+ }
15482+
15483+ if (mgr) {
15484+ for (i = 0; i < 3; i++) {
15485+ struct omap_overlay *ovl;
15486+ ovl = omap_dss_get_overlay(i);
15487+ if (!ovl->manager || force) {
15488+ if (ovl->manager)
15489+ omap_dss_unset_manager(ovl);
15490+ omap_dss_set_manager(ovl, mgr);
15491+ }
15492+ }
15493+ }
15494+}
15495+
15496+void dss_uninit_overlays(struct platform_device *pdev)
15497+{
15498+ struct omap_overlay *ovl;
15499+
15500+ while (!list_empty(&overlay_list)) {
15501+ ovl = list_first_entry(&overlay_list,
15502+ struct omap_overlay, list);
15503+ list_del(&ovl->list);
15504+ kobject_del(&ovl->kobj);
15505+ kobject_put(&ovl->kobj);
15506+ kfree(ovl);
15507+ }
15508+
15509+ num_overlays = 0;
15510+}
15511+
15512--- /dev/null
15513+++ b/drivers/video/omap2/dss/rfbi.c
15514@@ -0,0 +1,1310 @@
15515+/*
15516+ * linux/drivers/video/omap2/dss/rfbi.c
15517+ *
15518+ * Copyright (C) 2009 Nokia Corporation
15519+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
15520+ *
15521+ * Some code and ideas taken from drivers/video/omap/ driver
15522+ * by Imre Deak.
15523+ *
15524+ * This program is free software; you can redistribute it and/or modify it
15525+ * under the terms of the GNU General Public License version 2 as published by
15526+ * the Free Software Foundation.
15527+ *
15528+ * This program is distributed in the hope that it will be useful, but WITHOUT
15529+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15530+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15531+ * more details.
15532+ *
15533+ * You should have received a copy of the GNU General Public License along with
15534+ * this program. If not, see <http://www.gnu.org/licenses/>.
15535+ */
15536+
15537+#define DSS_SUBSYS_NAME "RFBI"
15538+
15539+#include <linux/kernel.h>
15540+#include <linux/dma-mapping.h>
15541+#include <linux/vmalloc.h>
15542+#include <linux/clk.h>
15543+#include <linux/io.h>
15544+#include <linux/delay.h>
15545+#include <linux/kfifo.h>
15546+#include <linux/ktime.h>
15547+#include <linux/hrtimer.h>
15548+#include <linux/seq_file.h>
15549+
15550+#include <mach/board.h>
15551+#include <mach/display.h>
15552+#include "dss.h"
15553+
15554+/*#define MEASURE_PERF*/
15555+
15556+#define RFBI_BASE 0x48050800
15557+
15558+struct rfbi_reg { u16 idx; };
15559+
15560+#define RFBI_REG(idx) ((const struct rfbi_reg) { idx })
15561+
15562+#define RFBI_REVISION RFBI_REG(0x0000)
15563+#define RFBI_SYSCONFIG RFBI_REG(0x0010)
15564+#define RFBI_SYSSTATUS RFBI_REG(0x0014)
15565+#define RFBI_CONTROL RFBI_REG(0x0040)
15566+#define RFBI_PIXEL_CNT RFBI_REG(0x0044)
15567+#define RFBI_LINE_NUMBER RFBI_REG(0x0048)
15568+#define RFBI_CMD RFBI_REG(0x004c)
15569+#define RFBI_PARAM RFBI_REG(0x0050)
15570+#define RFBI_DATA RFBI_REG(0x0054)
15571+#define RFBI_READ RFBI_REG(0x0058)
15572+#define RFBI_STATUS RFBI_REG(0x005c)
15573+
15574+#define RFBI_CONFIG(n) RFBI_REG(0x0060 + (n)*0x18)
15575+#define RFBI_ONOFF_TIME(n) RFBI_REG(0x0064 + (n)*0x18)
15576+#define RFBI_CYCLE_TIME(n) RFBI_REG(0x0068 + (n)*0x18)
15577+#define RFBI_DATA_CYCLE1(n) RFBI_REG(0x006c + (n)*0x18)
15578+#define RFBI_DATA_CYCLE2(n) RFBI_REG(0x0070 + (n)*0x18)
15579+#define RFBI_DATA_CYCLE3(n) RFBI_REG(0x0074 + (n)*0x18)
15580+
15581+#define RFBI_VSYNC_WIDTH RFBI_REG(0x0090)
15582+#define RFBI_HSYNC_WIDTH RFBI_REG(0x0094)
15583+
15584+#define RFBI_CMD_FIFO_LEN_BYTES (16 * sizeof(struct update_param))
15585+
15586+#define REG_FLD_MOD(idx, val, start, end) \
15587+ rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
15588+
15589+/* To work around an RFBI transfer rate limitation */
15590+#define OMAP_RFBI_RATE_LIMIT 1
15591+
15592+enum omap_rfbi_cycleformat {
15593+ OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0,
15594+ OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1,
15595+ OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2,
15596+ OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3,
15597+};
15598+
15599+enum omap_rfbi_datatype {
15600+ OMAP_DSS_RFBI_DATATYPE_12 = 0,
15601+ OMAP_DSS_RFBI_DATATYPE_16 = 1,
15602+ OMAP_DSS_RFBI_DATATYPE_18 = 2,
15603+ OMAP_DSS_RFBI_DATATYPE_24 = 3,
15604+};
15605+
15606+enum omap_rfbi_parallelmode {
15607+ OMAP_DSS_RFBI_PARALLELMODE_8 = 0,
15608+ OMAP_DSS_RFBI_PARALLELMODE_9 = 1,
15609+ OMAP_DSS_RFBI_PARALLELMODE_12 = 2,
15610+ OMAP_DSS_RFBI_PARALLELMODE_16 = 3,
15611+};
15612+
15613+enum update_cmd {
15614+ RFBI_CMD_UPDATE = 0,
15615+ RFBI_CMD_SYNC = 1,
15616+};
15617+
15618+static int rfbi_convert_timings(struct rfbi_timings *t);
15619+static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
15620+static void process_cmd_fifo(void);
15621+
15622+static struct {
15623+ void __iomem *base;
15624+
15625+ unsigned long l4_khz;
15626+
15627+ enum omap_rfbi_datatype datatype;
15628+ enum omap_rfbi_parallelmode parallelmode;
15629+
15630+ enum omap_rfbi_te_mode te_mode;
15631+ int te_enabled;
15632+
15633+ void (*framedone_callback)(void *data);
15634+ void *framedone_callback_data;
15635+
15636+ struct omap_dss_device *dssdev[2];
15637+
15638+ struct kfifo *cmd_fifo;
15639+ spinlock_t cmd_lock;
15640+ struct completion cmd_done;
15641+ atomic_t cmd_fifo_full;
15642+ atomic_t cmd_pending;
15643+#ifdef MEASURE_PERF
15644+ unsigned perf_bytes;
15645+ ktime_t perf_setup_time;
15646+ ktime_t perf_start_time;
15647+#endif
15648+} rfbi;
15649+
15650+struct update_region {
15651+ u16 x;
15652+ u16 y;
15653+ u16 w;
15654+ u16 h;
15655+};
15656+
15657+struct update_param {
15658+ u8 rfbi_module;
15659+ u8 cmd;
15660+
15661+ union {
15662+ struct update_region r;
15663+ struct completion *sync;
15664+ } par;
15665+};
15666+
15667+static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
15668+{
15669+ __raw_writel(val, rfbi.base + idx.idx);
15670+}
15671+
15672+static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
15673+{
15674+ return __raw_readl(rfbi.base + idx.idx);
15675+}
15676+
15677+static void rfbi_enable_clocks(bool enable)
15678+{
15679+ if (enable)
15680+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
15681+ else
15682+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
15683+}
15684+
15685+void omap_rfbi_write_command(const void *buf, u32 len)
15686+{
15687+ rfbi_enable_clocks(1);
15688+ switch (rfbi.parallelmode) {
15689+ case OMAP_DSS_RFBI_PARALLELMODE_8:
15690+ {
15691+ const u8 *b = buf;
15692+ for (; len; len--)
15693+ rfbi_write_reg(RFBI_CMD, *b++);
15694+ break;
15695+ }
15696+
15697+ case OMAP_DSS_RFBI_PARALLELMODE_16:
15698+ {
15699+ const u16 *w = buf;
15700+ BUG_ON(len & 1);
15701+ for (; len; len -= 2)
15702+ rfbi_write_reg(RFBI_CMD, *w++);
15703+ break;
15704+ }
15705+
15706+ case OMAP_DSS_RFBI_PARALLELMODE_9:
15707+ case OMAP_DSS_RFBI_PARALLELMODE_12:
15708+ default:
15709+ BUG();
15710+ }
15711+ rfbi_enable_clocks(0);
15712+}
15713+EXPORT_SYMBOL(omap_rfbi_write_command);
15714+
15715+void omap_rfbi_read_data(void *buf, u32 len)
15716+{
15717+ rfbi_enable_clocks(1);
15718+ switch (rfbi.parallelmode) {
15719+ case OMAP_DSS_RFBI_PARALLELMODE_8:
15720+ {
15721+ u8 *b = buf;
15722+ for (; len; len--) {
15723+ rfbi_write_reg(RFBI_READ, 0);
15724+ *b++ = rfbi_read_reg(RFBI_READ);
15725+ }
15726+ break;
15727+ }
15728+
15729+ case OMAP_DSS_RFBI_PARALLELMODE_16:
15730+ {
15731+ u16 *w = buf;
15732+ BUG_ON(len & ~1);
15733+ for (; len; len -= 2) {
15734+ rfbi_write_reg(RFBI_READ, 0);
15735+ *w++ = rfbi_read_reg(RFBI_READ);
15736+ }
15737+ break;
15738+ }
15739+
15740+ case OMAP_DSS_RFBI_PARALLELMODE_9:
15741+ case OMAP_DSS_RFBI_PARALLELMODE_12:
15742+ default:
15743+ BUG();
15744+ }
15745+ rfbi_enable_clocks(0);
15746+}
15747+EXPORT_SYMBOL(omap_rfbi_read_data);
15748+
15749+void omap_rfbi_write_data(const void *buf, u32 len)
15750+{
15751+ rfbi_enable_clocks(1);
15752+ switch (rfbi.parallelmode) {
15753+ case OMAP_DSS_RFBI_PARALLELMODE_8:
15754+ {
15755+ const u8 *b = buf;
15756+ for (; len; len--)
15757+ rfbi_write_reg(RFBI_PARAM, *b++);
15758+ break;
15759+ }
15760+
15761+ case OMAP_DSS_RFBI_PARALLELMODE_16:
15762+ {
15763+ const u16 *w = buf;
15764+ BUG_ON(len & 1);
15765+ for (; len; len -= 2)
15766+ rfbi_write_reg(RFBI_PARAM, *w++);
15767+ break;
15768+ }
15769+
15770+ case OMAP_DSS_RFBI_PARALLELMODE_9:
15771+ case OMAP_DSS_RFBI_PARALLELMODE_12:
15772+ default:
15773+ BUG();
15774+
15775+ }
15776+ rfbi_enable_clocks(0);
15777+}
15778+EXPORT_SYMBOL(omap_rfbi_write_data);
15779+
15780+void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
15781+ u16 x, u16 y,
15782+ u16 w, u16 h)
15783+{
15784+ int start_offset = scr_width * y + x;
15785+ int horiz_offset = scr_width - w;
15786+ int i;
15787+
15788+ rfbi_enable_clocks(1);
15789+
15790+ if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
15791+ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
15792+ const u16 __iomem *pd = buf;
15793+ pd += start_offset;
15794+
15795+ for (; h; --h) {
15796+ for (i = 0; i < w; ++i) {
15797+ const u8 __iomem *b = (const u8 __iomem *)pd;
15798+ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
15799+ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
15800+ ++pd;
15801+ }
15802+ pd += horiz_offset;
15803+ }
15804+ } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 &&
15805+ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
15806+ const u32 __iomem *pd = buf;
15807+ pd += start_offset;
15808+
15809+ for (; h; --h) {
15810+ for (i = 0; i < w; ++i) {
15811+ const u8 __iomem *b = (const u8 __iomem *)pd;
15812+ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+2));
15813+ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
15814+ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
15815+ ++pd;
15816+ }
15817+ pd += horiz_offset;
15818+ }
15819+ } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
15820+ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) {
15821+ const u16 __iomem *pd = buf;
15822+ pd += start_offset;
15823+
15824+ for (; h; --h) {
15825+ for (i = 0; i < w; ++i) {
15826+ rfbi_write_reg(RFBI_PARAM, __raw_readw(pd));
15827+ ++pd;
15828+ }
15829+ pd += horiz_offset;
15830+ }
15831+ } else {
15832+ BUG();
15833+ }
15834+
15835+ rfbi_enable_clocks(0);
15836+}
15837+EXPORT_SYMBOL(omap_rfbi_write_pixels);
15838+
15839+#ifdef MEASURE_PERF
15840+static void perf_mark_setup(void)
15841+{
15842+ rfbi.perf_setup_time = ktime_get();
15843+}
15844+
15845+static void perf_mark_start(void)
15846+{
15847+ rfbi.perf_start_time = ktime_get();
15848+}
15849+
15850+static void perf_show(const char *name)
15851+{
15852+ ktime_t t, setup_time, trans_time;
15853+ u32 total_bytes;
15854+ u32 setup_us, trans_us, total_us;
15855+
15856+ t = ktime_get();
15857+
15858+ setup_time = ktime_sub(rfbi.perf_start_time, rfbi.perf_setup_time);
15859+ setup_us = (u32)ktime_to_us(setup_time);
15860+ if (setup_us == 0)
15861+ setup_us = 1;
15862+
15863+ trans_time = ktime_sub(t, rfbi.perf_start_time);
15864+ trans_us = (u32)ktime_to_us(trans_time);
15865+ if (trans_us == 0)
15866+ trans_us = 1;
15867+
15868+ total_us = setup_us + trans_us;
15869+
15870+ total_bytes = rfbi.perf_bytes;
15871+
15872+ DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, "
15873+ "%u kbytes/sec\n",
15874+ name,
15875+ setup_us,
15876+ trans_us,
15877+ total_us,
15878+ 1000*1000 / total_us,
15879+ total_bytes,
15880+ total_bytes * 1000 / total_us);
15881+}
15882+#else
15883+#define perf_mark_setup()
15884+#define perf_mark_start()
15885+#define perf_show(x)
15886+#endif
15887+
15888+void rfbi_transfer_area(u16 width, u16 height,
15889+ void (callback)(void *data), void *data)
15890+{
15891+ u32 l;
15892+
15893+ /*BUG_ON(callback == 0);*/
15894+ BUG_ON(rfbi.framedone_callback != NULL);
15895+
15896+ DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
15897+
15898+ dispc_set_lcd_size(width, height);
15899+
15900+ dispc_enable_lcd_out(1);
15901+
15902+ rfbi.framedone_callback = callback;
15903+ rfbi.framedone_callback_data = data;
15904+
15905+ rfbi_enable_clocks(1);
15906+
15907+ rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
15908+
15909+ l = rfbi_read_reg(RFBI_CONTROL);
15910+ l = FLD_MOD(l, 1, 0, 0); /* enable */
15911+ if (!rfbi.te_enabled)
15912+ l = FLD_MOD(l, 1, 4, 4); /* ITE */
15913+
15914+ perf_mark_start();
15915+
15916+ rfbi_write_reg(RFBI_CONTROL, l);
15917+}
15918+
15919+static void framedone_callback(void *data, u32 mask)
15920+{
15921+ void (*callback)(void *data);
15922+
15923+ DSSDBG("FRAMEDONE\n");
15924+
15925+ perf_show("DISPC");
15926+
15927+ REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0);
15928+
15929+ rfbi_enable_clocks(0);
15930+
15931+ callback = rfbi.framedone_callback;
15932+ rfbi.framedone_callback = NULL;
15933+
15934+ /*callback(rfbi.framedone_callback_data);*/
15935+
15936+ atomic_set(&rfbi.cmd_pending, 0);
15937+
15938+ process_cmd_fifo();
15939+}
15940+
15941+#if 1 /* VERBOSE */
15942+static void rfbi_print_timings(void)
15943+{
15944+ u32 l;
15945+ u32 time;
15946+
15947+ l = rfbi_read_reg(RFBI_CONFIG(0));
15948+ time = 1000000000 / rfbi.l4_khz;
15949+ if (l & (1 << 4))
15950+ time *= 2;
15951+
15952+ DSSDBG("Tick time %u ps\n", time);
15953+ l = rfbi_read_reg(RFBI_ONOFF_TIME(0));
15954+ DSSDBG("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
15955+ "REONTIME %d, REOFFTIME %d\n",
15956+ l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
15957+ (l >> 20) & 0x0f, (l >> 24) & 0x3f);
15958+
15959+ l = rfbi_read_reg(RFBI_CYCLE_TIME(0));
15960+ DSSDBG("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
15961+ "ACCESSTIME %d\n",
15962+ (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
15963+ (l >> 22) & 0x3f);
15964+}
15965+#else
15966+static void rfbi_print_timings(void) {}
15967+#endif
15968+
15969+
15970+
15971+
15972+static u32 extif_clk_period;
15973+
15974+static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
15975+{
15976+ int bus_tick = extif_clk_period * div;
15977+ return (ps + bus_tick - 1) / bus_tick * bus_tick;
15978+}
15979+
15980+static int calc_reg_timing(struct rfbi_timings *t, int div)
15981+{
15982+ t->clk_div = div;
15983+
15984+ t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div);
15985+
15986+ t->we_on_time = round_to_extif_ticks(t->we_on_time, div);
15987+ t->we_off_time = round_to_extif_ticks(t->we_off_time, div);
15988+ t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div);
15989+
15990+ t->re_on_time = round_to_extif_ticks(t->re_on_time, div);
15991+ t->re_off_time = round_to_extif_ticks(t->re_off_time, div);
15992+ t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div);
15993+
15994+ t->access_time = round_to_extif_ticks(t->access_time, div);
15995+ t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div);
15996+ t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div);
15997+
15998+ DSSDBG("[reg]cson %d csoff %d reon %d reoff %d\n",
15999+ t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
16000+ DSSDBG("[reg]weon %d weoff %d recyc %d wecyc %d\n",
16001+ t->we_on_time, t->we_off_time, t->re_cycle_time,
16002+ t->we_cycle_time);
16003+ DSSDBG("[reg]rdaccess %d cspulse %d\n",
16004+ t->access_time, t->cs_pulse_width);
16005+
16006+ return rfbi_convert_timings(t);
16007+}
16008+
16009+static int calc_extif_timings(struct rfbi_timings *t)
16010+{
16011+ u32 max_clk_div;
16012+ int div;
16013+
16014+ rfbi_get_clk_info(&extif_clk_period, &max_clk_div);
16015+ for (div = 1; div <= max_clk_div; div++) {
16016+ if (calc_reg_timing(t, div) == 0)
16017+ break;
16018+ }
16019+
16020+ if (div <= max_clk_div)
16021+ return 0;
16022+
16023+ DSSERR("can't setup timings\n");
16024+ return -1;
16025+}
16026+
16027+
16028+void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
16029+{
16030+ int r;
16031+
16032+ if (!t->converted) {
16033+ r = calc_extif_timings(t);
16034+ if (r < 0)
16035+ DSSERR("Failed to calc timings\n");
16036+ }
16037+
16038+ BUG_ON(!t->converted);
16039+
16040+ rfbi_enable_clocks(1);
16041+ rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]);
16042+ rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]);
16043+
16044+ /* TIMEGRANULARITY */
16045+ REG_FLD_MOD(RFBI_CONFIG(rfbi_module),
16046+ (t->tim[2] ? 1 : 0), 4, 4);
16047+
16048+ rfbi_print_timings();
16049+ rfbi_enable_clocks(0);
16050+}
16051+
16052+static int ps_to_rfbi_ticks(int time, int div)
16053+{
16054+ unsigned long tick_ps;
16055+ int ret;
16056+
16057+ /* Calculate in picosecs to yield more exact results */
16058+ tick_ps = 1000000000 / (rfbi.l4_khz) * div;
16059+
16060+ ret = (time + tick_ps - 1) / tick_ps;
16061+
16062+ return ret;
16063+}
16064+
16065+#ifdef OMAP_RFBI_RATE_LIMIT
16066+unsigned long rfbi_get_max_tx_rate(void)
16067+{
16068+ unsigned long l4_rate, dss1_rate;
16069+ int min_l4_ticks = 0;
16070+ int i;
16071+
16072+ /* According to TI this can't be calculated so make the
16073+ * adjustments for a couple of known frequencies and warn for
16074+ * others.
16075+ */
16076+ static const struct {
16077+ unsigned long l4_clk; /* HZ */
16078+ unsigned long dss1_clk; /* HZ */
16079+ unsigned long min_l4_ticks;
16080+ } ftab[] = {
16081+ { 55, 132, 7, }, /* 7.86 MPix/s */
16082+ { 110, 110, 12, }, /* 9.16 MPix/s */
16083+ { 110, 132, 10, }, /* 11 Mpix/s */
16084+ { 120, 120, 10, }, /* 12 Mpix/s */
16085+ { 133, 133, 10, }, /* 13.3 Mpix/s */
16086+ };
16087+
16088+ l4_rate = rfbi.l4_khz / 1000;
16089+ dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000;
16090+
16091+ for (i = 0; i < ARRAY_SIZE(ftab); i++) {
16092+ /* Use a window instead of an exact match, to account
16093+ * for different DPLL multiplier / divider pairs.
16094+ */
16095+ if (abs(ftab[i].l4_clk - l4_rate) < 3 &&
16096+ abs(ftab[i].dss1_clk - dss1_rate) < 3) {
16097+ min_l4_ticks = ftab[i].min_l4_ticks;
16098+ break;
16099+ }
16100+ }
16101+ if (i == ARRAY_SIZE(ftab)) {
16102+ /* Can't be sure, return anyway the maximum not
16103+ * rate-limited. This might cause a problem only for the
16104+ * tearing synchronisation.
16105+ */
16106+ DSSERR("can't determine maximum RFBI transfer rate\n");
16107+ return rfbi.l4_khz * 1000;
16108+ }
16109+ return rfbi.l4_khz * 1000 / min_l4_ticks;
16110+}
16111+#else
16112+int rfbi_get_max_tx_rate(void)
16113+{
16114+ return rfbi.l4_khz * 1000;
16115+}
16116+#endif
16117+
16118+static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
16119+{
16120+ *clk_period = 1000000000 / rfbi.l4_khz;
16121+ *max_clk_div = 2;
16122+}
16123+
16124+static int rfbi_convert_timings(struct rfbi_timings *t)
16125+{
16126+ u32 l;
16127+ int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
16128+ int actim, recyc, wecyc;
16129+ int div = t->clk_div;
16130+
16131+ if (div <= 0 || div > 2)
16132+ return -1;
16133+
16134+ /* Make sure that after conversion it still holds that:
16135+ * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
16136+ * csoff > cson, csoff >= max(weoff, reoff), actim > reon
16137+ */
16138+ weon = ps_to_rfbi_ticks(t->we_on_time, div);
16139+ weoff = ps_to_rfbi_ticks(t->we_off_time, div);
16140+ if (weoff <= weon)
16141+ weoff = weon + 1;
16142+ if (weon > 0x0f)
16143+ return -1;
16144+ if (weoff > 0x3f)
16145+ return -1;
16146+
16147+ reon = ps_to_rfbi_ticks(t->re_on_time, div);
16148+ reoff = ps_to_rfbi_ticks(t->re_off_time, div);
16149+ if (reoff <= reon)
16150+ reoff = reon + 1;
16151+ if (reon > 0x0f)
16152+ return -1;
16153+ if (reoff > 0x3f)
16154+ return -1;
16155+
16156+ cson = ps_to_rfbi_ticks(t->cs_on_time, div);
16157+ csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
16158+ if (csoff <= cson)
16159+ csoff = cson + 1;
16160+ if (csoff < max(weoff, reoff))
16161+ csoff = max(weoff, reoff);
16162+ if (cson > 0x0f)
16163+ return -1;
16164+ if (csoff > 0x3f)
16165+ return -1;
16166+
16167+ l = cson;
16168+ l |= csoff << 4;
16169+ l |= weon << 10;
16170+ l |= weoff << 14;
16171+ l |= reon << 20;
16172+ l |= reoff << 24;
16173+
16174+ t->tim[0] = l;
16175+
16176+ actim = ps_to_rfbi_ticks(t->access_time, div);
16177+ if (actim <= reon)
16178+ actim = reon + 1;
16179+ if (actim > 0x3f)
16180+ return -1;
16181+
16182+ wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
16183+ if (wecyc < weoff)
16184+ wecyc = weoff;
16185+ if (wecyc > 0x3f)
16186+ return -1;
16187+
16188+ recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
16189+ if (recyc < reoff)
16190+ recyc = reoff;
16191+ if (recyc > 0x3f)
16192+ return -1;
16193+
16194+ cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
16195+ if (cs_pulse > 0x3f)
16196+ return -1;
16197+
16198+ l = wecyc;
16199+ l |= recyc << 6;
16200+ l |= cs_pulse << 12;
16201+ l |= actim << 22;
16202+
16203+ t->tim[1] = l;
16204+
16205+ t->tim[2] = div - 1;
16206+
16207+ t->converted = 1;
16208+
16209+ return 0;
16210+}
16211+
16212+/* xxx FIX module selection missing */
16213+int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
16214+ unsigned hs_pulse_time, unsigned vs_pulse_time,
16215+ int hs_pol_inv, int vs_pol_inv, int extif_div)
16216+{
16217+ int hs, vs;
16218+ int min;
16219+ u32 l;
16220+
16221+ hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
16222+ vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
16223+ if (hs < 2)
16224+ return -EDOM;
16225+ if (mode == OMAP_DSS_RFBI_TE_MODE_2)
16226+ min = 2;
16227+ else /* OMAP_DSS_RFBI_TE_MODE_1 */
16228+ min = 4;
16229+ if (vs < min)
16230+ return -EDOM;
16231+ if (vs == hs)
16232+ return -EINVAL;
16233+ rfbi.te_mode = mode;
16234+ DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n",
16235+ mode, hs, vs, hs_pol_inv, vs_pol_inv);
16236+
16237+ rfbi_enable_clocks(1);
16238+ rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
16239+ rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
16240+
16241+ l = rfbi_read_reg(RFBI_CONFIG(0));
16242+ if (hs_pol_inv)
16243+ l &= ~(1 << 21);
16244+ else
16245+ l |= 1 << 21;
16246+ if (vs_pol_inv)
16247+ l &= ~(1 << 20);
16248+ else
16249+ l |= 1 << 20;
16250+ rfbi_enable_clocks(0);
16251+
16252+ return 0;
16253+}
16254+EXPORT_SYMBOL(omap_rfbi_setup_te);
16255+
16256+/* xxx FIX module selection missing */
16257+int omap_rfbi_enable_te(bool enable, unsigned line)
16258+{
16259+ u32 l;
16260+
16261+ DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode);
16262+ if (line > (1 << 11) - 1)
16263+ return -EINVAL;
16264+
16265+ rfbi_enable_clocks(1);
16266+ l = rfbi_read_reg(RFBI_CONFIG(0));
16267+ l &= ~(0x3 << 2);
16268+ if (enable) {
16269+ rfbi.te_enabled = 1;
16270+ l |= rfbi.te_mode << 2;
16271+ } else
16272+ rfbi.te_enabled = 0;
16273+ rfbi_write_reg(RFBI_CONFIG(0), l);
16274+ rfbi_write_reg(RFBI_LINE_NUMBER, line);
16275+ rfbi_enable_clocks(0);
16276+
16277+ return 0;
16278+}
16279+EXPORT_SYMBOL(omap_rfbi_enable_te);
16280+
16281+#if 0
16282+static void rfbi_enable_config(int enable1, int enable2)
16283+{
16284+ u32 l;
16285+ int cs = 0;
16286+
16287+ if (enable1)
16288+ cs |= 1<<0;
16289+ if (enable2)
16290+ cs |= 1<<1;
16291+
16292+ rfbi_enable_clocks(1);
16293+
16294+ l = rfbi_read_reg(RFBI_CONTROL);
16295+
16296+ l = FLD_MOD(l, cs, 3, 2);
16297+ l = FLD_MOD(l, 0, 1, 1);
16298+
16299+ rfbi_write_reg(RFBI_CONTROL, l);
16300+
16301+
16302+ l = rfbi_read_reg(RFBI_CONFIG(0));
16303+ l = FLD_MOD(l, 0, 3, 2); /* TRIGGERMODE: ITE */
16304+ /*l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
16305+ /*l |= FLD_VAL(0, 8, 7); */ /* L4FORMAT, 1pix/L4 */
16306+
16307+ l = FLD_MOD(l, 0, 16, 16); /* A0POLARITY */
16308+ l = FLD_MOD(l, 1, 20, 20); /* TE_VSYNC_POLARITY */
16309+ l = FLD_MOD(l, 1, 21, 21); /* HSYNCPOLARITY */
16310+
16311+ l = FLD_MOD(l, OMAP_DSS_RFBI_PARALLELMODE_8, 1, 0);
16312+ rfbi_write_reg(RFBI_CONFIG(0), l);
16313+
16314+ rfbi_enable_clocks(0);
16315+}
16316+#endif
16317+
16318+int rfbi_configure(int rfbi_module, int bpp, int lines)
16319+{
16320+ u32 l;
16321+ int cycle1 = 0, cycle2 = 0, cycle3 = 0;
16322+ enum omap_rfbi_cycleformat cycleformat;
16323+ enum omap_rfbi_datatype datatype;
16324+ enum omap_rfbi_parallelmode parallelmode;
16325+
16326+ switch (bpp) {
16327+ case 12:
16328+ datatype = OMAP_DSS_RFBI_DATATYPE_12;
16329+ break;
16330+ case 16:
16331+ datatype = OMAP_DSS_RFBI_DATATYPE_16;
16332+ break;
16333+ case 18:
16334+ datatype = OMAP_DSS_RFBI_DATATYPE_18;
16335+ break;
16336+ case 24:
16337+ datatype = OMAP_DSS_RFBI_DATATYPE_24;
16338+ break;
16339+ default:
16340+ BUG();
16341+ return 1;
16342+ }
16343+ rfbi.datatype = datatype;
16344+
16345+ switch (lines) {
16346+ case 8:
16347+ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8;
16348+ break;
16349+ case 9:
16350+ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9;
16351+ break;
16352+ case 12:
16353+ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12;
16354+ break;
16355+ case 16:
16356+ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16;
16357+ break;
16358+ default:
16359+ BUG();
16360+ return 1;
16361+ }
16362+ rfbi.parallelmode = parallelmode;
16363+
16364+ if ((bpp % lines) == 0) {
16365+ switch (bpp / lines) {
16366+ case 1:
16367+ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1;
16368+ break;
16369+ case 2:
16370+ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1;
16371+ break;
16372+ case 3:
16373+ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1;
16374+ break;
16375+ default:
16376+ BUG();
16377+ return 1;
16378+ }
16379+ } else if ((2 * bpp % lines) == 0) {
16380+ if ((2 * bpp / lines) == 3)
16381+ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2;
16382+ else {
16383+ BUG();
16384+ return 1;
16385+ }
16386+ } else {
16387+ BUG();
16388+ return 1;
16389+ }
16390+
16391+ switch (cycleformat) {
16392+ case OMAP_DSS_RFBI_CYCLEFORMAT_1_1:
16393+ cycle1 = lines;
16394+ break;
16395+
16396+ case OMAP_DSS_RFBI_CYCLEFORMAT_2_1:
16397+ cycle1 = lines;
16398+ cycle2 = lines;
16399+ break;
16400+
16401+ case OMAP_DSS_RFBI_CYCLEFORMAT_3_1:
16402+ cycle1 = lines;
16403+ cycle2 = lines;
16404+ cycle3 = lines;
16405+ break;
16406+
16407+ case OMAP_DSS_RFBI_CYCLEFORMAT_3_2:
16408+ cycle1 = lines;
16409+ cycle2 = (lines / 2) | ((lines / 2) << 16);
16410+ cycle3 = (lines << 16);
16411+ break;
16412+ }
16413+
16414+ rfbi_enable_clocks(1);
16415+
16416+ REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */
16417+
16418+ l = 0;
16419+ l |= FLD_VAL(parallelmode, 1, 0);
16420+ l |= FLD_VAL(0, 3, 2); /* TRIGGERMODE: ITE */
16421+ l |= FLD_VAL(0, 4, 4); /* TIMEGRANULARITY */
16422+ l |= FLD_VAL(datatype, 6, 5);
16423+ /* l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
16424+ l |= FLD_VAL(0, 8, 7); /* L4FORMAT, 1pix/L4 */
16425+ l |= FLD_VAL(cycleformat, 10, 9);
16426+ l |= FLD_VAL(0, 12, 11); /* UNUSEDBITS */
16427+ l |= FLD_VAL(0, 16, 16); /* A0POLARITY */
16428+ l |= FLD_VAL(0, 17, 17); /* REPOLARITY */
16429+ l |= FLD_VAL(0, 18, 18); /* WEPOLARITY */
16430+ l |= FLD_VAL(0, 19, 19); /* CSPOLARITY */
16431+ l |= FLD_VAL(1, 20, 20); /* TE_VSYNC_POLARITY */
16432+ l |= FLD_VAL(1, 21, 21); /* HSYNCPOLARITY */
16433+ rfbi_write_reg(RFBI_CONFIG(rfbi_module), l);
16434+
16435+ rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1);
16436+ rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2);
16437+ rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3);
16438+
16439+
16440+ l = rfbi_read_reg(RFBI_CONTROL);
16441+ l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */
16442+ l = FLD_MOD(l, 0, 1, 1); /* clear bypass */
16443+ rfbi_write_reg(RFBI_CONTROL, l);
16444+
16445+
16446+ DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n",
16447+ bpp, lines, cycle1, cycle2, cycle3);
16448+
16449+ rfbi_enable_clocks(0);
16450+
16451+ return 0;
16452+}
16453+EXPORT_SYMBOL(rfbi_configure);
16454+
16455+static int rfbi_find_display(struct omap_dss_device *dssdev)
16456+{
16457+ if (dssdev == rfbi.dssdev[0])
16458+ return 0;
16459+
16460+ if (dssdev == rfbi.dssdev[1])
16461+ return 1;
16462+
16463+ BUG();
16464+ return -1;
16465+}
16466+
16467+
16468+static void signal_fifo_waiters(void)
16469+{
16470+ if (atomic_read(&rfbi.cmd_fifo_full) > 0) {
16471+ /* DSSDBG("SIGNALING: Fifo not full for waiter!\n"); */
16472+ complete(&rfbi.cmd_done);
16473+ atomic_dec(&rfbi.cmd_fifo_full);
16474+ }
16475+}
16476+
16477+/* returns 1 for async op, and 0 for sync op */
16478+static int do_update(struct omap_dss_device *dssdev, struct update_region *upd)
16479+{
16480+ u16 x = upd->x;
16481+ u16 y = upd->y;
16482+ u16 w = upd->w;
16483+ u16 h = upd->h;
16484+
16485+ perf_mark_setup();
16486+
16487+ if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
16488+ /*dssdev->driver->enable_te(dssdev, 1); */
16489+ dss_setup_partial_planes(dssdev, &x, &y, &w, &h);
16490+ }
16491+
16492+#ifdef MEASURE_PERF
16493+ rfbi.perf_bytes = w * h * 2; /* XXX always 16bit */
16494+#endif
16495+
16496+ dssdev->driver->setup_update(dssdev, x, y, w, h);
16497+
16498+ if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
16499+ rfbi_transfer_area(w, h, NULL, NULL);
16500+ return 1;
16501+ } else {
16502+ struct omap_overlay *ovl;
16503+ void __iomem *addr;
16504+ int scr_width;
16505+
16506+ ovl = dssdev->manager->overlays[0];
16507+ scr_width = ovl->info.screen_width;
16508+ addr = ovl->info.vaddr;
16509+
16510+ omap_rfbi_write_pixels(addr, scr_width, x, y, w, h);
16511+
16512+ perf_show("L4");
16513+
16514+ return 0;
16515+ }
16516+}
16517+
16518+static void process_cmd_fifo(void)
16519+{
16520+ int len;
16521+ struct update_param p;
16522+ struct omap_dss_device *dssdev;
16523+ unsigned long flags;
16524+
16525+ if (atomic_inc_return(&rfbi.cmd_pending) != 1)
16526+ return;
16527+
16528+ while (true) {
16529+ spin_lock_irqsave(rfbi.cmd_fifo->lock, flags);
16530+
16531+ len = __kfifo_get(rfbi.cmd_fifo, (unsigned char *)&p,
16532+ sizeof(struct update_param));
16533+ if (len == 0) {
16534+ DSSDBG("nothing more in fifo\n");
16535+ atomic_set(&rfbi.cmd_pending, 0);
16536+ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
16537+ break;
16538+ }
16539+
16540+ /* DSSDBG("fifo full %d\n", rfbi.cmd_fifo_full.counter);*/
16541+
16542+ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
16543+
16544+ BUG_ON(len != sizeof(struct update_param));
16545+ BUG_ON(p.rfbi_module > 1);
16546+
16547+ dssdev = rfbi.dssdev[p.rfbi_module];
16548+
16549+ if (p.cmd == RFBI_CMD_UPDATE) {
16550+ if (do_update(dssdev, &p.par.r))
16551+ break; /* async op */
16552+ } else if (p.cmd == RFBI_CMD_SYNC) {
16553+ DSSDBG("Signaling SYNC done!\n");
16554+ complete(p.par.sync);
16555+ } else
16556+ BUG();
16557+ }
16558+
16559+ signal_fifo_waiters();
16560+}
16561+
16562+static void rfbi_push_cmd(struct update_param *p)
16563+{
16564+ int ret;
16565+
16566+ while (1) {
16567+ unsigned long flags;
16568+ int available;
16569+
16570+ spin_lock_irqsave(rfbi.cmd_fifo->lock, flags);
16571+ available = RFBI_CMD_FIFO_LEN_BYTES -
16572+ __kfifo_len(rfbi.cmd_fifo);
16573+
16574+/* DSSDBG("%d bytes left in fifo\n", available); */
16575+ if (available < sizeof(struct update_param)) {
16576+ DSSDBG("Going to wait because FIFO FULL..\n");
16577+ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
16578+ atomic_inc(&rfbi.cmd_fifo_full);
16579+ wait_for_completion(&rfbi.cmd_done);
16580+ /*DSSDBG("Woke up because fifo not full anymore\n");*/
16581+ continue;
16582+ }
16583+
16584+ ret = __kfifo_put(rfbi.cmd_fifo, (unsigned char *)p,
16585+ sizeof(struct update_param));
16586+/* DSSDBG("pushed %d bytes\n", ret);*/
16587+
16588+ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
16589+
16590+ BUG_ON(ret != sizeof(struct update_param));
16591+
16592+ break;
16593+ }
16594+}
16595+
16596+static void rfbi_push_update(int rfbi_module, int x, int y, int w, int h)
16597+{
16598+ struct update_param p;
16599+
16600+ p.rfbi_module = rfbi_module;
16601+ p.cmd = RFBI_CMD_UPDATE;
16602+
16603+ p.par.r.x = x;
16604+ p.par.r.y = y;
16605+ p.par.r.w = w;
16606+ p.par.r.h = h;
16607+
16608+ DSSDBG("RFBI pushed %d,%d %dx%d\n", x, y, w, h);
16609+
16610+ rfbi_push_cmd(&p);
16611+
16612+ process_cmd_fifo();
16613+}
16614+
16615+static void rfbi_push_sync(int rfbi_module, struct completion *sync_comp)
16616+{
16617+ struct update_param p;
16618+
16619+ p.rfbi_module = rfbi_module;
16620+ p.cmd = RFBI_CMD_SYNC;
16621+ p.par.sync = sync_comp;
16622+
16623+ rfbi_push_cmd(&p);
16624+
16625+ DSSDBG("RFBI sync pushed to cmd fifo\n");
16626+
16627+ process_cmd_fifo();
16628+}
16629+
16630+void rfbi_dump_regs(struct seq_file *s)
16631+{
16632+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
16633+
16634+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
16635+
16636+ DUMPREG(RFBI_REVISION);
16637+ DUMPREG(RFBI_SYSCONFIG);
16638+ DUMPREG(RFBI_SYSSTATUS);
16639+ DUMPREG(RFBI_CONTROL);
16640+ DUMPREG(RFBI_PIXEL_CNT);
16641+ DUMPREG(RFBI_LINE_NUMBER);
16642+ DUMPREG(RFBI_CMD);
16643+ DUMPREG(RFBI_PARAM);
16644+ DUMPREG(RFBI_DATA);
16645+ DUMPREG(RFBI_READ);
16646+ DUMPREG(RFBI_STATUS);
16647+
16648+ DUMPREG(RFBI_CONFIG(0));
16649+ DUMPREG(RFBI_ONOFF_TIME(0));
16650+ DUMPREG(RFBI_CYCLE_TIME(0));
16651+ DUMPREG(RFBI_DATA_CYCLE1(0));
16652+ DUMPREG(RFBI_DATA_CYCLE2(0));
16653+ DUMPREG(RFBI_DATA_CYCLE3(0));
16654+
16655+ DUMPREG(RFBI_CONFIG(1));
16656+ DUMPREG(RFBI_ONOFF_TIME(1));
16657+ DUMPREG(RFBI_CYCLE_TIME(1));
16658+ DUMPREG(RFBI_DATA_CYCLE1(1));
16659+ DUMPREG(RFBI_DATA_CYCLE2(1));
16660+ DUMPREG(RFBI_DATA_CYCLE3(1));
16661+
16662+ DUMPREG(RFBI_VSYNC_WIDTH);
16663+ DUMPREG(RFBI_HSYNC_WIDTH);
16664+
16665+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
16666+#undef DUMPREG
16667+}
16668+
16669+int rfbi_init(void)
16670+{
16671+ u32 rev;
16672+ u32 l;
16673+
16674+ spin_lock_init(&rfbi.cmd_lock);
16675+ rfbi.cmd_fifo = kfifo_alloc(RFBI_CMD_FIFO_LEN_BYTES, GFP_KERNEL,
16676+ &rfbi.cmd_lock);
16677+ if (IS_ERR(rfbi.cmd_fifo))
16678+ return -ENOMEM;
16679+
16680+ init_completion(&rfbi.cmd_done);
16681+ atomic_set(&rfbi.cmd_fifo_full, 0);
16682+ atomic_set(&rfbi.cmd_pending, 0);
16683+
16684+ rfbi.base = ioremap(RFBI_BASE, SZ_256);
16685+ if (!rfbi.base) {
16686+ DSSERR("can't ioremap RFBI\n");
16687+ return -ENOMEM;
16688+ }
16689+
16690+ rfbi_enable_clocks(1);
16691+
16692+ msleep(10);
16693+
16694+ rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
16695+
16696+ /* Enable autoidle and smart-idle */
16697+ l = rfbi_read_reg(RFBI_SYSCONFIG);
16698+ l |= (1 << 0) | (2 << 3);
16699+ rfbi_write_reg(RFBI_SYSCONFIG, l);
16700+
16701+ rev = rfbi_read_reg(RFBI_REVISION);
16702+ printk(KERN_INFO "OMAP RFBI rev %d.%d\n",
16703+ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
16704+
16705+ rfbi_enable_clocks(0);
16706+
16707+ return 0;
16708+}
16709+
16710+void rfbi_exit(void)
16711+{
16712+ DSSDBG("rfbi_exit\n");
16713+
16714+ kfifo_free(rfbi.cmd_fifo);
16715+
16716+ iounmap(rfbi.base);
16717+}
16718+
16719+/* struct omap_display support */
16720+static int rfbi_display_update(struct omap_dss_device *dssdev,
16721+ u16 x, u16 y, u16 w, u16 h)
16722+{
16723+ int rfbi_module;
16724+
16725+ if (w == 0 || h == 0)
16726+ return 0;
16727+
16728+ rfbi_module = rfbi_find_display(dssdev);
16729+
16730+ rfbi_push_update(rfbi_module, x, y, w, h);
16731+
16732+ return 0;
16733+}
16734+
16735+static int rfbi_display_sync(struct omap_dss_device *dssdev)
16736+{
16737+ struct completion sync_comp;
16738+ int rfbi_module;
16739+
16740+ rfbi_module = rfbi_find_display(dssdev);
16741+
16742+ init_completion(&sync_comp);
16743+ rfbi_push_sync(rfbi_module, &sync_comp);
16744+ DSSDBG("Waiting for SYNC to happen...\n");
16745+ wait_for_completion(&sync_comp);
16746+ DSSDBG("Released from SYNC\n");
16747+ return 0;
16748+}
16749+
16750+static int rfbi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
16751+{
16752+ dssdev->driver->enable_te(dssdev, enable);
16753+ return 0;
16754+}
16755+
16756+static int rfbi_display_enable(struct omap_dss_device *dssdev)
16757+{
16758+ int r;
16759+
16760+ r = omap_dss_start_device(dssdev);
16761+ if (r) {
16762+ DSSERR("failed to start device\n");
16763+ goto err0;
16764+ }
16765+
16766+ r = omap_dispc_register_isr(framedone_callback, NULL,
16767+ DISPC_IRQ_FRAMEDONE);
16768+ if (r) {
16769+ DSSERR("can't get FRAMEDONE irq\n");
16770+ goto err1;
16771+ }
16772+
16773+ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
16774+
16775+ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_RFBI);
16776+
16777+ dispc_set_tft_data_lines(dssdev->ctrl.pixel_size);
16778+
16779+ rfbi_configure(dssdev->phy.rfbi.channel,
16780+ dssdev->ctrl.pixel_size,
16781+ dssdev->phy.rfbi.data_lines);
16782+
16783+ rfbi_set_timings(dssdev->phy.rfbi.channel,
16784+ &dssdev->ctrl.rfbi_timings);
16785+
16786+
16787+ if (dssdev->driver->enable) {
16788+ r = dssdev->driver->enable(dssdev);
16789+ if (r)
16790+ goto err2;
16791+ }
16792+
16793+ return 0;
16794+err2:
16795+ omap_dispc_unregister_isr(framedone_callback, NULL,
16796+ DISPC_IRQ_FRAMEDONE);
16797+err1:
16798+ omap_dss_stop_device(dssdev);
16799+err0:
16800+ return r;
16801+}
16802+
16803+static void rfbi_display_disable(struct omap_dss_device *dssdev)
16804+{
16805+ dssdev->driver->disable(dssdev);
16806+ omap_dispc_unregister_isr(framedone_callback, NULL,
16807+ DISPC_IRQ_FRAMEDONE);
16808+ omap_dss_stop_device(dssdev);
16809+}
16810+
16811+int rfbi_init_display(struct omap_dss_device *dssdev)
16812+{
16813+ dssdev->enable = rfbi_display_enable;
16814+ dssdev->disable = rfbi_display_disable;
16815+ dssdev->update = rfbi_display_update;
16816+ dssdev->sync = rfbi_display_sync;
16817+ dssdev->enable_te = rfbi_display_enable_te;
16818+
16819+ rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
16820+
16821+ dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
16822+
16823+ return 0;
16824+}
16825--- /dev/null
16826+++ b/drivers/video/omap2/dss/sdi.c
16827@@ -0,0 +1,261 @@
16828+/*
16829+ * linux/drivers/video/omap2/dss/sdi.c
16830+ *
16831+ * Copyright (C) 2009 Nokia Corporation
16832+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
16833+ *
16834+ * This program is free software; you can redistribute it and/or modify it
16835+ * under the terms of the GNU General Public License version 2 as published by
16836+ * the Free Software Foundation.
16837+ *
16838+ * This program is distributed in the hope that it will be useful, but WITHOUT
16839+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16840+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16841+ * more details.
16842+ *
16843+ * You should have received a copy of the GNU General Public License along with
16844+ * this program. If not, see <http://www.gnu.org/licenses/>.
16845+ */
16846+
16847+#define DSS_SUBSYS_NAME "SDI"
16848+
16849+#include <linux/kernel.h>
16850+#include <linux/clk.h>
16851+#include <linux/delay.h>
16852+#include <linux/err.h>
16853+
16854+#include <mach/board.h>
16855+#include <mach/display.h>
16856+#include "dss.h"
16857+
16858+static struct {
16859+ bool skip_init;
16860+ bool update_enabled;
16861+} sdi;
16862+
16863+static void sdi_basic_init(void)
16864+{
16865+ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
16866+
16867+ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
16868+ dispc_set_tft_data_lines(24);
16869+ dispc_lcd_enable_signal_polarity(1);
16870+}
16871+
16872+static int sdi_display_enable(struct omap_dss_device *dssdev)
16873+{
16874+ struct omap_video_timings *t = &dssdev->panel.timings;
16875+ struct dispc_clock_info cinfo;
16876+ u16 lck_div, pck_div;
16877+ unsigned long fck;
16878+ unsigned long pck;
16879+ int r;
16880+
16881+ r = omap_dss_start_device(dssdev);
16882+ if (r) {
16883+ DSSERR("failed to start device\n");
16884+ goto err0;
16885+ }
16886+
16887+ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
16888+ DSSERR("dssdev already enabled\n");
16889+ r = -EINVAL;
16890+ goto err1;
16891+ }
16892+
16893+ /* In case of skip_init sdi_init has already enabled the clocks */
16894+ if (!sdi.skip_init)
16895+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
16896+
16897+ sdi_basic_init();
16898+
16899+ /* 15.5.9.1.2 */
16900+ dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
16901+
16902+ dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi,
16903+ dssdev->panel.acb);
16904+
16905+ if (!sdi.skip_init)
16906+ r = dispc_calc_clock_div(1, t->pixel_clock * 1000,
16907+ &cinfo);
16908+ else
16909+ r = dispc_get_clock_div(&cinfo);
16910+
16911+ if (r)
16912+ goto err2;
16913+
16914+ fck = cinfo.fck;
16915+ lck_div = cinfo.lck_div;
16916+ pck_div = cinfo.pck_div;
16917+
16918+ pck = fck / lck_div / pck_div / 1000;
16919+
16920+ if (pck != t->pixel_clock) {
16921+ DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
16922+ "got %lu kHz\n",
16923+ t->pixel_clock, pck);
16924+
16925+ t->pixel_clock = pck;
16926+ }
16927+
16928+
16929+ dispc_set_lcd_timings(t);
16930+
16931+ r = dispc_set_clock_div(&cinfo);
16932+ if (r)
16933+ goto err2;
16934+
16935+ if (!sdi.skip_init) {
16936+ dss_sdi_init(dssdev->phy.sdi.datapairs);
16937+ dss_sdi_enable();
16938+ mdelay(2);
16939+ }
16940+
16941+ dispc_enable_lcd_out(1);
16942+
16943+ if (dssdev->driver->enable) {
16944+ r = dssdev->driver->enable(dssdev);
16945+ if (r)
16946+ goto err3;
16947+ }
16948+
16949+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
16950+
16951+ sdi.skip_init = 0;
16952+
16953+ return 0;
16954+err3:
16955+ dispc_enable_lcd_out(0);
16956+err2:
16957+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
16958+err1:
16959+ omap_dss_stop_device(dssdev);
16960+err0:
16961+ return r;
16962+}
16963+
16964+static int sdi_display_resume(struct omap_dss_device *dssdev);
16965+
16966+static void sdi_display_disable(struct omap_dss_device *dssdev)
16967+{
16968+ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
16969+ return;
16970+
16971+ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
16972+ sdi_display_resume(dssdev);
16973+
16974+ if (dssdev->driver->disable)
16975+ dssdev->driver->disable(dssdev);
16976+
16977+ dispc_enable_lcd_out(0);
16978+
16979+ dss_sdi_disable();
16980+
16981+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
16982+
16983+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
16984+
16985+ omap_dss_stop_device(dssdev);
16986+}
16987+
16988+static int sdi_display_suspend(struct omap_dss_device *dssdev)
16989+{
16990+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
16991+ return -EINVAL;
16992+
16993+ if (dssdev->driver->suspend)
16994+ dssdev->driver->suspend(dssdev);
16995+
16996+ dispc_enable_lcd_out(0);
16997+
16998+ dss_sdi_disable();
16999+
17000+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
17001+
17002+ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
17003+
17004+ return 0;
17005+}
17006+
17007+static int sdi_display_resume(struct omap_dss_device *dssdev)
17008+{
17009+ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
17010+ return -EINVAL;
17011+
17012+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
17013+
17014+ dss_sdi_enable();
17015+ mdelay(2);
17016+
17017+ dispc_enable_lcd_out(1);
17018+
17019+ if (dssdev->driver->resume)
17020+ dssdev->driver->resume(dssdev);
17021+
17022+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
17023+
17024+ return 0;
17025+}
17026+
17027+static int sdi_display_set_update_mode(struct omap_dss_device *dssdev,
17028+ enum omap_dss_update_mode mode)
17029+{
17030+ if (mode == OMAP_DSS_UPDATE_MANUAL)
17031+ return -EINVAL;
17032+
17033+ if (mode == OMAP_DSS_UPDATE_DISABLED) {
17034+ dispc_enable_lcd_out(0);
17035+ sdi.update_enabled = 0;
17036+ } else {
17037+ dispc_enable_lcd_out(1);
17038+ sdi.update_enabled = 1;
17039+ }
17040+
17041+ return 0;
17042+}
17043+
17044+static enum omap_dss_update_mode sdi_display_get_update_mode(
17045+ struct omap_dss_device *dssdev)
17046+{
17047+ return sdi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
17048+ OMAP_DSS_UPDATE_DISABLED;
17049+}
17050+
17051+static void sdi_get_timings(struct omap_dss_device *dssdev,
17052+ struct omap_video_timings *timings)
17053+{
17054+ *timings = dssdev->panel.timings;
17055+}
17056+
17057+int sdi_init_display(struct omap_dss_device *dssdev)
17058+{
17059+ DSSDBG("SDI init\n");
17060+
17061+ dssdev->enable = sdi_display_enable;
17062+ dssdev->disable = sdi_display_disable;
17063+ dssdev->suspend = sdi_display_suspend;
17064+ dssdev->resume = sdi_display_resume;
17065+ dssdev->set_update_mode = sdi_display_set_update_mode;
17066+ dssdev->get_update_mode = sdi_display_get_update_mode;
17067+ dssdev->get_timings = sdi_get_timings;
17068+
17069+ return 0;
17070+}
17071+
17072+int sdi_init(bool skip_init)
17073+{
17074+ /* we store this for first display enable, then clear it */
17075+ sdi.skip_init = skip_init;
17076+
17077+ /*
17078+ * Enable clocks already here, otherwise there would be a toggle
17079+ * of them until sdi_display_enable is called.
17080+ */
17081+ if (skip_init)
17082+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
17083+ return 0;
17084+}
17085+
17086+void sdi_exit(void)
17087+{
17088+}
17089--- /dev/null
17090+++ b/drivers/video/omap2/dss/venc.c
17091@@ -0,0 +1,797 @@
17092+/*
17093+ * linux/drivers/video/omap2/dss/venc.c
17094+ *
17095+ * Copyright (C) 2009 Nokia Corporation
17096+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
17097+ *
17098+ * VENC settings from TI's DSS driver
17099+ *
17100+ * This program is free software; you can redistribute it and/or modify it
17101+ * under the terms of the GNU General Public License version 2 as published by
17102+ * the Free Software Foundation.
17103+ *
17104+ * This program is distributed in the hope that it will be useful, but WITHOUT
17105+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17106+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17107+ * more details.
17108+ *
17109+ * You should have received a copy of the GNU General Public License along with
17110+ * this program. If not, see <http://www.gnu.org/licenses/>.
17111+ */
17112+
17113+#define DSS_SUBSYS_NAME "VENC"
17114+
17115+#include <linux/kernel.h>
17116+#include <linux/module.h>
17117+#include <linux/clk.h>
17118+#include <linux/err.h>
17119+#include <linux/io.h>
17120+#include <linux/mutex.h>
17121+#include <linux/completion.h>
17122+#include <linux/delay.h>
17123+#include <linux/string.h>
17124+#include <linux/seq_file.h>
17125+#include <linux/platform_device.h>
17126+#include <linux/regulator/consumer.h>
17127+
17128+#include <mach/display.h>
17129+#include <mach/cpu.h>
17130+
17131+#include "dss.h"
17132+
17133+#define VENC_BASE 0x48050C00
17134+
17135+/* Venc registers */
17136+#define VENC_REV_ID 0x00
17137+#define VENC_STATUS 0x04
17138+#define VENC_F_CONTROL 0x08
17139+#define VENC_VIDOUT_CTRL 0x10
17140+#define VENC_SYNC_CTRL 0x14
17141+#define VENC_LLEN 0x1C
17142+#define VENC_FLENS 0x20
17143+#define VENC_HFLTR_CTRL 0x24
17144+#define VENC_CC_CARR_WSS_CARR 0x28
17145+#define VENC_C_PHASE 0x2C
17146+#define VENC_GAIN_U 0x30
17147+#define VENC_GAIN_V 0x34
17148+#define VENC_GAIN_Y 0x38
17149+#define VENC_BLACK_LEVEL 0x3C
17150+#define VENC_BLANK_LEVEL 0x40
17151+#define VENC_X_COLOR 0x44
17152+#define VENC_M_CONTROL 0x48
17153+#define VENC_BSTAMP_WSS_DATA 0x4C
17154+#define VENC_S_CARR 0x50
17155+#define VENC_LINE21 0x54
17156+#define VENC_LN_SEL 0x58
17157+#define VENC_L21__WC_CTL 0x5C
17158+#define VENC_HTRIGGER_VTRIGGER 0x60
17159+#define VENC_SAVID__EAVID 0x64
17160+#define VENC_FLEN__FAL 0x68
17161+#define VENC_LAL__PHASE_RESET 0x6C
17162+#define VENC_HS_INT_START_STOP_X 0x70
17163+#define VENC_HS_EXT_START_STOP_X 0x74
17164+#define VENC_VS_INT_START_X 0x78
17165+#define VENC_VS_INT_STOP_X__VS_INT_START_Y 0x7C
17166+#define VENC_VS_INT_STOP_Y__VS_EXT_START_X 0x80
17167+#define VENC_VS_EXT_STOP_X__VS_EXT_START_Y 0x84
17168+#define VENC_VS_EXT_STOP_Y 0x88
17169+#define VENC_AVID_START_STOP_X 0x90
17170+#define VENC_AVID_START_STOP_Y 0x94
17171+#define VENC_FID_INT_START_X__FID_INT_START_Y 0xA0
17172+#define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X 0xA4
17173+#define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y 0xA8
17174+#define VENC_TVDETGP_INT_START_STOP_X 0xB0
17175+#define VENC_TVDETGP_INT_START_STOP_Y 0xB4
17176+#define VENC_GEN_CTRL 0xB8
17177+#define VENC_OUTPUT_CONTROL 0xC4
17178+#define VENC_OUTPUT_TEST 0xC8
17179+#define VENC_DAC_B__DAC_C 0xC8
17180+
17181+struct venc_config {
17182+ u32 f_control;
17183+ u32 vidout_ctrl;
17184+ u32 sync_ctrl;
17185+ u32 llen;
17186+ u32 flens;
17187+ u32 hfltr_ctrl;
17188+ u32 cc_carr_wss_carr;
17189+ u32 c_phase;
17190+ u32 gain_u;
17191+ u32 gain_v;
17192+ u32 gain_y;
17193+ u32 black_level;
17194+ u32 blank_level;
17195+ u32 x_color;
17196+ u32 m_control;
17197+ u32 bstamp_wss_data;
17198+ u32 s_carr;
17199+ u32 line21;
17200+ u32 ln_sel;
17201+ u32 l21__wc_ctl;
17202+ u32 htrigger_vtrigger;
17203+ u32 savid__eavid;
17204+ u32 flen__fal;
17205+ u32 lal__phase_reset;
17206+ u32 hs_int_start_stop_x;
17207+ u32 hs_ext_start_stop_x;
17208+ u32 vs_int_start_x;
17209+ u32 vs_int_stop_x__vs_int_start_y;
17210+ u32 vs_int_stop_y__vs_ext_start_x;
17211+ u32 vs_ext_stop_x__vs_ext_start_y;
17212+ u32 vs_ext_stop_y;
17213+ u32 avid_start_stop_x;
17214+ u32 avid_start_stop_y;
17215+ u32 fid_int_start_x__fid_int_start_y;
17216+ u32 fid_int_offset_y__fid_ext_start_x;
17217+ u32 fid_ext_start_y__fid_ext_offset_y;
17218+ u32 tvdetgp_int_start_stop_x;
17219+ u32 tvdetgp_int_start_stop_y;
17220+ u32 gen_ctrl;
17221+};
17222+
17223+/* from TRM */
17224+static const struct venc_config venc_config_pal_trm = {
17225+ .f_control = 0,
17226+ .vidout_ctrl = 1,
17227+ .sync_ctrl = 0x40,
17228+ .llen = 0x35F, /* 863 */
17229+ .flens = 0x270, /* 624 */
17230+ .hfltr_ctrl = 0,
17231+ .cc_carr_wss_carr = 0x2F7225ED,
17232+ .c_phase = 0,
17233+ .gain_u = 0x111,
17234+ .gain_v = 0x181,
17235+ .gain_y = 0x140,
17236+ .black_level = 0x3B,
17237+ .blank_level = 0x3B,
17238+ .x_color = 0x7,
17239+ .m_control = 0x2,
17240+ .bstamp_wss_data = 0x3F,
17241+ .s_carr = 0x2A098ACB,
17242+ .line21 = 0,
17243+ .ln_sel = 0x01290015,
17244+ .l21__wc_ctl = 0x0000F603,
17245+ .htrigger_vtrigger = 0,
17246+
17247+ .savid__eavid = 0x06A70108,
17248+ .flen__fal = 0x00180270,
17249+ .lal__phase_reset = 0x00040135,
17250+ .hs_int_start_stop_x = 0x00880358,
17251+ .hs_ext_start_stop_x = 0x000F035F,
17252+ .vs_int_start_x = 0x01A70000,
17253+ .vs_int_stop_x__vs_int_start_y = 0x000001A7,
17254+ .vs_int_stop_y__vs_ext_start_x = 0x01AF0000,
17255+ .vs_ext_stop_x__vs_ext_start_y = 0x000101AF,
17256+ .vs_ext_stop_y = 0x00000025,
17257+ .avid_start_stop_x = 0x03530083,
17258+ .avid_start_stop_y = 0x026C002E,
17259+ .fid_int_start_x__fid_int_start_y = 0x0001008A,
17260+ .fid_int_offset_y__fid_ext_start_x = 0x002E0138,
17261+ .fid_ext_start_y__fid_ext_offset_y = 0x01380001,
17262+
17263+ .tvdetgp_int_start_stop_x = 0x00140001,
17264+ .tvdetgp_int_start_stop_y = 0x00010001,
17265+ .gen_ctrl = 0x00FF0000,
17266+};
17267+
17268+/* from TRM */
17269+static const struct venc_config venc_config_ntsc_trm = {
17270+ .f_control = 0,
17271+ .vidout_ctrl = 1,
17272+ .sync_ctrl = 0x8040,
17273+ .llen = 0x359,
17274+ .flens = 0x20C,
17275+ .hfltr_ctrl = 0,
17276+ .cc_carr_wss_carr = 0x043F2631,
17277+ .c_phase = 0,
17278+ .gain_u = 0x102,
17279+ .gain_v = 0x16C,
17280+ .gain_y = 0x12F,
17281+ .black_level = 0x43,
17282+ .blank_level = 0x38,
17283+ .x_color = 0x7,
17284+ .m_control = 0x1,
17285+ .bstamp_wss_data = 0x38,
17286+ .s_carr = 0x21F07C1F,
17287+ .line21 = 0,
17288+ .ln_sel = 0x01310011,
17289+ .l21__wc_ctl = 0x0000F003,
17290+ .htrigger_vtrigger = 0,
17291+
17292+ .savid__eavid = 0x069300F4,
17293+ .flen__fal = 0x0016020C,
17294+ .lal__phase_reset = 0x00060107,
17295+ .hs_int_start_stop_x = 0x008E0350,
17296+ .hs_ext_start_stop_x = 0x000F0359,
17297+ .vs_int_start_x = 0x01A00000,
17298+ .vs_int_stop_x__vs_int_start_y = 0x020701A0,
17299+ .vs_int_stop_y__vs_ext_start_x = 0x01AC0024,
17300+ .vs_ext_stop_x__vs_ext_start_y = 0x020D01AC,
17301+ .vs_ext_stop_y = 0x00000006,
17302+ .avid_start_stop_x = 0x03480078,
17303+ .avid_start_stop_y = 0x02060024,
17304+ .fid_int_start_x__fid_int_start_y = 0x0001008A,
17305+ .fid_int_offset_y__fid_ext_start_x = 0x01AC0106,
17306+ .fid_ext_start_y__fid_ext_offset_y = 0x01060006,
17307+
17308+ .tvdetgp_int_start_stop_x = 0x00140001,
17309+ .tvdetgp_int_start_stop_y = 0x00010001,
17310+ .gen_ctrl = 0x00F90000,
17311+};
17312+
17313+static const struct venc_config venc_config_pal_bdghi = {
17314+ .f_control = 0,
17315+ .vidout_ctrl = 0,
17316+ .sync_ctrl = 0,
17317+ .hfltr_ctrl = 0,
17318+ .x_color = 0,
17319+ .line21 = 0,
17320+ .ln_sel = 21,
17321+ .htrigger_vtrigger = 0,
17322+ .tvdetgp_int_start_stop_x = 0x00140001,
17323+ .tvdetgp_int_start_stop_y = 0x00010001,
17324+ .gen_ctrl = 0x00FB0000,
17325+
17326+ .llen = 864-1,
17327+ .flens = 625-1,
17328+ .cc_carr_wss_carr = 0x2F7625ED,
17329+ .c_phase = 0xDF,
17330+ .gain_u = 0x111,
17331+ .gain_v = 0x181,
17332+ .gain_y = 0x140,
17333+ .black_level = 0x3e,
17334+ .blank_level = 0x3e,
17335+ .m_control = 0<<2 | 1<<1,
17336+ .bstamp_wss_data = 0x42,
17337+ .s_carr = 0x2a098acb,
17338+ .l21__wc_ctl = 0<<13 | 0x16<<8 | 0<<0,
17339+ .savid__eavid = 0x06A70108,
17340+ .flen__fal = 23<<16 | 624<<0,
17341+ .lal__phase_reset = 2<<17 | 310<<0,
17342+ .hs_int_start_stop_x = 0x00920358,
17343+ .hs_ext_start_stop_x = 0x000F035F,
17344+ .vs_int_start_x = 0x1a7<<16,
17345+ .vs_int_stop_x__vs_int_start_y = 0x000601A7,
17346+ .vs_int_stop_y__vs_ext_start_x = 0x01AF0036,
17347+ .vs_ext_stop_x__vs_ext_start_y = 0x27101af,
17348+ .vs_ext_stop_y = 0x05,
17349+ .avid_start_stop_x = 0x03530082,
17350+ .avid_start_stop_y = 0x0270002E,
17351+ .fid_int_start_x__fid_int_start_y = 0x0005008A,
17352+ .fid_int_offset_y__fid_ext_start_x = 0x002E0138,
17353+ .fid_ext_start_y__fid_ext_offset_y = 0x01380005,
17354+};
17355+
17356+const struct omap_video_timings omap_dss_pal_timings = {
17357+ .x_res = 720,
17358+ .y_res = 574,
17359+ .pixel_clock = 13500,
17360+ .hsw = 64,
17361+ .hfp = 12,
17362+ .hbp = 68,
17363+ .vsw = 5,
17364+ .vfp = 5,
17365+ .vbp = 41,
17366+};
17367+EXPORT_SYMBOL(omap_dss_pal_timings);
17368+
17369+const struct omap_video_timings omap_dss_ntsc_timings = {
17370+ .x_res = 720,
17371+ .y_res = 482,
17372+ .pixel_clock = 13500,
17373+ .hsw = 64,
17374+ .hfp = 16,
17375+ .hbp = 58,
17376+ .vsw = 6,
17377+ .vfp = 6,
17378+ .vbp = 31,
17379+};
17380+EXPORT_SYMBOL(omap_dss_ntsc_timings);
17381+
17382+static struct {
17383+ void __iomem *base;
17384+ struct mutex venc_lock;
17385+ u32 wss_data;
17386+ struct regulator *vdda_dac_reg;
17387+} venc;
17388+
17389+static inline void venc_write_reg(int idx, u32 val)
17390+{
17391+ __raw_writel(val, venc.base + idx);
17392+}
17393+
17394+static inline u32 venc_read_reg(int idx)
17395+{
17396+ u32 l = __raw_readl(venc.base + idx);
17397+ return l;
17398+}
17399+
17400+static void venc_write_config(const struct venc_config *config)
17401+{
17402+ DSSDBG("write venc conf\n");
17403+
17404+ venc_write_reg(VENC_LLEN, config->llen);
17405+ venc_write_reg(VENC_FLENS, config->flens);
17406+ venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr);
17407+ venc_write_reg(VENC_C_PHASE, config->c_phase);
17408+ venc_write_reg(VENC_GAIN_U, config->gain_u);
17409+ venc_write_reg(VENC_GAIN_V, config->gain_v);
17410+ venc_write_reg(VENC_GAIN_Y, config->gain_y);
17411+ venc_write_reg(VENC_BLACK_LEVEL, config->black_level);
17412+ venc_write_reg(VENC_BLANK_LEVEL, config->blank_level);
17413+ venc_write_reg(VENC_M_CONTROL, config->m_control);
17414+ venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
17415+ venc.wss_data);
17416+ venc_write_reg(VENC_S_CARR, config->s_carr);
17417+ venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl);
17418+ venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid);
17419+ venc_write_reg(VENC_FLEN__FAL, config->flen__fal);
17420+ venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset);
17421+ venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x);
17422+ venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x);
17423+ venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x);
17424+ venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y,
17425+ config->vs_int_stop_x__vs_int_start_y);
17426+ venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X,
17427+ config->vs_int_stop_y__vs_ext_start_x);
17428+ venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y,
17429+ config->vs_ext_stop_x__vs_ext_start_y);
17430+ venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y);
17431+ venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x);
17432+ venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y);
17433+ venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y,
17434+ config->fid_int_start_x__fid_int_start_y);
17435+ venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X,
17436+ config->fid_int_offset_y__fid_ext_start_x);
17437+ venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y,
17438+ config->fid_ext_start_y__fid_ext_offset_y);
17439+
17440+ venc_write_reg(VENC_DAC_B__DAC_C, venc_read_reg(VENC_DAC_B__DAC_C));
17441+ venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl);
17442+ venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl);
17443+ venc_write_reg(VENC_X_COLOR, config->x_color);
17444+ venc_write_reg(VENC_LINE21, config->line21);
17445+ venc_write_reg(VENC_LN_SEL, config->ln_sel);
17446+ venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger);
17447+ venc_write_reg(VENC_TVDETGP_INT_START_STOP_X,
17448+ config->tvdetgp_int_start_stop_x);
17449+ venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y,
17450+ config->tvdetgp_int_start_stop_y);
17451+ venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl);
17452+ venc_write_reg(VENC_F_CONTROL, config->f_control);
17453+ venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl);
17454+}
17455+
17456+static void venc_reset(void)
17457+{
17458+ int t = 1000;
17459+
17460+ venc_write_reg(VENC_F_CONTROL, 1<<8);
17461+ while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) {
17462+ if (--t == 0) {
17463+ DSSERR("Failed to reset venc\n");
17464+ return;
17465+ }
17466+ }
17467+
17468+ /* the magical sleep that makes things work */
17469+ msleep(20);
17470+}
17471+
17472+static void venc_enable_clocks(int enable)
17473+{
17474+ if (enable)
17475+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
17476+ DSS_CLK_96M);
17477+ else
17478+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
17479+ DSS_CLK_96M);
17480+}
17481+
17482+static const struct venc_config *venc_timings_to_config(
17483+ struct omap_video_timings *timings)
17484+{
17485+ if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
17486+ return &venc_config_pal_trm;
17487+
17488+ if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
17489+ return &venc_config_ntsc_trm;
17490+
17491+ BUG();
17492+}
17493+
17494+
17495+
17496+
17497+
17498+/* driver */
17499+static int venc_panel_probe(struct omap_dss_device *dssdev)
17500+{
17501+ dssdev->panel.timings = omap_dss_pal_timings;
17502+
17503+ return 0;
17504+}
17505+
17506+static void venc_panel_remove(struct omap_dss_device *dssdev)
17507+{
17508+}
17509+
17510+static int venc_panel_enable(struct omap_dss_device *dssdev)
17511+{
17512+ int r = 0;
17513+
17514+ /* wait couple of vsyncs until enabling the LCD */
17515+ msleep(50);
17516+
17517+ if (dssdev->platform_enable)
17518+ r = dssdev->platform_enable(dssdev);
17519+
17520+ return r;
17521+}
17522+
17523+static void venc_panel_disable(struct omap_dss_device *dssdev)
17524+{
17525+ if (dssdev->platform_disable)
17526+ dssdev->platform_disable(dssdev);
17527+
17528+ /* wait at least 5 vsyncs after disabling the LCD */
17529+
17530+ msleep(100);
17531+}
17532+
17533+static int venc_panel_suspend(struct omap_dss_device *dssdev)
17534+{
17535+ venc_panel_disable(dssdev);
17536+ return 0;
17537+}
17538+
17539+static int venc_panel_resume(struct omap_dss_device *dssdev)
17540+{
17541+ return venc_panel_enable(dssdev);
17542+}
17543+
17544+static struct omap_dss_driver venc_driver = {
17545+ .probe = venc_panel_probe,
17546+ .remove = venc_panel_remove,
17547+
17548+ .enable = venc_panel_enable,
17549+ .disable = venc_panel_disable,
17550+ .suspend = venc_panel_suspend,
17551+ .resume = venc_panel_resume,
17552+
17553+ .driver = {
17554+ .name = "venc",
17555+ .owner = THIS_MODULE,
17556+ },
17557+};
17558+/* driver end */
17559+
17560+
17561+
17562+int venc_init(struct platform_device *pdev)
17563+{
17564+ u8 rev_id;
17565+
17566+ mutex_init(&venc.venc_lock);
17567+
17568+ venc.wss_data = 0;
17569+
17570+ venc.base = ioremap(VENC_BASE, SZ_1K);
17571+ if (!venc.base) {
17572+ DSSERR("can't ioremap VENC\n");
17573+ return -ENOMEM;
17574+ }
17575+
17576+ venc.vdda_dac_reg = regulator_get(&pdev->dev, "vdda_dac");
17577+ if (IS_ERR(venc.vdda_dac_reg)) {
17578+ iounmap(venc.base);
17579+ DSSERR("can't get VDDA_DAC regulator\n");
17580+ return PTR_ERR(venc.vdda_dac_reg);
17581+ }
17582+
17583+ venc_enable_clocks(1);
17584+
17585+ rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
17586+ printk(KERN_INFO "OMAP VENC rev %d\n", rev_id);
17587+
17588+ venc_enable_clocks(0);
17589+
17590+ return omap_dss_register_driver(&venc_driver);
17591+}
17592+
17593+void venc_exit(void)
17594+{
17595+ omap_dss_unregister_driver(&venc_driver);
17596+
17597+ regulator_put(venc.vdda_dac_reg);
17598+
17599+ iounmap(venc.base);
17600+}
17601+
17602+static void venc_power_on(struct omap_dss_device *dssdev)
17603+{
17604+ u32 l;
17605+
17606+ venc_enable_clocks(1);
17607+
17608+ venc_reset();
17609+ venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
17610+
17611+ dss_set_venc_output(dssdev->phy.venc.type);
17612+ dss_set_dac_pwrdn_bgz(1);
17613+
17614+ l = 0;
17615+
17616+ if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
17617+ l |= 1 << 1;
17618+ else /* S-Video */
17619+ l |= (1 << 0) | (1 << 2);
17620+
17621+ if (dssdev->phy.venc.invert_polarity == false)
17622+ l |= 1 << 3;
17623+
17624+ venc_write_reg(VENC_OUTPUT_CONTROL, l);
17625+
17626+ dispc_set_digit_size(dssdev->panel.timings.x_res,
17627+ dssdev->panel.timings.y_res/2);
17628+
17629+ regulator_enable(venc.vdda_dac_reg);
17630+
17631+ if (dssdev->platform_enable)
17632+ dssdev->platform_enable(dssdev);
17633+
17634+ dispc_enable_digit_out(1);
17635+}
17636+
17637+static void venc_power_off(struct omap_dss_device *dssdev)
17638+{
17639+ venc_write_reg(VENC_OUTPUT_CONTROL, 0);
17640+ dss_set_dac_pwrdn_bgz(0);
17641+
17642+ dispc_enable_digit_out(0);
17643+
17644+ if (dssdev->platform_disable)
17645+ dssdev->platform_disable(dssdev);
17646+
17647+ regulator_disable(venc.vdda_dac_reg);
17648+
17649+ venc_enable_clocks(0);
17650+}
17651+
17652+static int venc_enable_display(struct omap_dss_device *dssdev)
17653+{
17654+ int r = 0;
17655+
17656+ DSSDBG("venc_enable_display\n");
17657+
17658+ mutex_lock(&venc.venc_lock);
17659+
17660+ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
17661+ r = -EINVAL;
17662+ goto err;
17663+ }
17664+
17665+ venc_power_on(dssdev);
17666+
17667+ venc.wss_data = 0;
17668+
17669+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
17670+err:
17671+ mutex_unlock(&venc.venc_lock);
17672+
17673+ return r;
17674+}
17675+
17676+static void venc_disable_display(struct omap_dss_device *dssdev)
17677+{
17678+ DSSDBG("venc_disable_display\n");
17679+
17680+ mutex_lock(&venc.venc_lock);
17681+
17682+ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
17683+ goto end;
17684+
17685+ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
17686+ /* suspended is the same as disabled with venc */
17687+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
17688+ goto end;
17689+ }
17690+
17691+ venc_power_off(dssdev);
17692+
17693+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
17694+end:
17695+ mutex_unlock(&venc.venc_lock);
17696+}
17697+
17698+static int venc_display_suspend(struct omap_dss_device *dssdev)
17699+{
17700+ int r = 0;
17701+
17702+ DSSDBG("venc_display_suspend\n");
17703+
17704+ mutex_lock(&venc.venc_lock);
17705+
17706+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
17707+ r = -EINVAL;
17708+ goto err;
17709+ }
17710+
17711+ venc_power_off(dssdev);
17712+
17713+ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
17714+err:
17715+ mutex_unlock(&venc.venc_lock);
17716+
17717+ return r;
17718+}
17719+
17720+static int venc_display_resume(struct omap_dss_device *dssdev)
17721+{
17722+ int r = 0;
17723+
17724+ DSSDBG("venc_display_resume\n");
17725+
17726+ mutex_lock(&venc.venc_lock);
17727+
17728+ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
17729+ r = -EINVAL;
17730+ goto err;
17731+ }
17732+
17733+ venc_power_on(dssdev);
17734+
17735+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
17736+err:
17737+ mutex_unlock(&venc.venc_lock);
17738+
17739+ return r;
17740+}
17741+
17742+static void venc_get_timings(struct omap_dss_device *dssdev,
17743+ struct omap_video_timings *timings)
17744+{
17745+ *timings = dssdev->panel.timings;
17746+}
17747+
17748+static void venc_set_timings(struct omap_dss_device *dssdev,
17749+ struct omap_video_timings *timings)
17750+{
17751+ DSSDBG("venc_set_timings\n");
17752+
17753+ /* Reset WSS data when the TV standard changes. */
17754+ if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings)))
17755+ venc.wss_data = 0;
17756+
17757+ dssdev->panel.timings = *timings;
17758+ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
17759+ /* turn the venc off and on to get new timings to use */
17760+ venc_disable_display(dssdev);
17761+ venc_enable_display(dssdev);
17762+ }
17763+}
17764+
17765+static int venc_check_timings(struct omap_dss_device *dssdev,
17766+ struct omap_video_timings *timings)
17767+{
17768+ DSSDBG("venc_check_timings\n");
17769+
17770+ if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
17771+ return 0;
17772+
17773+ if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
17774+ return 0;
17775+
17776+ return -EINVAL;
17777+}
17778+
17779+static u32 venc_get_wss(struct omap_dss_device *dssdev)
17780+{
17781+ /* Invert due to VENC_L21_WC_CTL:INV=1 */
17782+ return (venc.wss_data >> 8) ^ 0xfffff;
17783+}
17784+
17785+static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
17786+{
17787+ const struct venc_config *config;
17788+
17789+ DSSDBG("venc_set_wss\n");
17790+
17791+ mutex_lock(&venc.venc_lock);
17792+
17793+ config = venc_timings_to_config(&dssdev->panel.timings);
17794+
17795+ /* Invert due to VENC_L21_WC_CTL:INV=1 */
17796+ venc.wss_data = (wss ^ 0xfffff) << 8;
17797+
17798+ venc_enable_clocks(1);
17799+
17800+ venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
17801+ venc.wss_data);
17802+
17803+ venc_enable_clocks(0);
17804+
17805+ mutex_unlock(&venc.venc_lock);
17806+
17807+ return 0;
17808+}
17809+
17810+static enum omap_dss_update_mode venc_display_get_update_mode(
17811+ struct omap_dss_device *dssdev)
17812+{
17813+ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
17814+ return OMAP_DSS_UPDATE_AUTO;
17815+ else
17816+ return OMAP_DSS_UPDATE_DISABLED;
17817+}
17818+
17819+int venc_init_display(struct omap_dss_device *dssdev)
17820+{
17821+ DSSDBG("init_display\n");
17822+
17823+ dssdev->enable = venc_enable_display;
17824+ dssdev->disable = venc_disable_display;
17825+ dssdev->suspend = venc_display_suspend;
17826+ dssdev->resume = venc_display_resume;
17827+ dssdev->get_timings = venc_get_timings;
17828+ dssdev->set_timings = venc_set_timings;
17829+ dssdev->check_timings = venc_check_timings;
17830+ dssdev->get_wss = venc_get_wss;
17831+ dssdev->set_wss = venc_set_wss;
17832+ dssdev->get_update_mode = venc_display_get_update_mode;
17833+
17834+ return 0;
17835+}
17836+
17837+void venc_dump_regs(struct seq_file *s)
17838+{
17839+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
17840+
17841+ venc_enable_clocks(1);
17842+
17843+ DUMPREG(VENC_F_CONTROL);
17844+ DUMPREG(VENC_VIDOUT_CTRL);
17845+ DUMPREG(VENC_SYNC_CTRL);
17846+ DUMPREG(VENC_LLEN);
17847+ DUMPREG(VENC_FLENS);
17848+ DUMPREG(VENC_HFLTR_CTRL);
17849+ DUMPREG(VENC_CC_CARR_WSS_CARR);
17850+ DUMPREG(VENC_C_PHASE);
17851+ DUMPREG(VENC_GAIN_U);
17852+ DUMPREG(VENC_GAIN_V);
17853+ DUMPREG(VENC_GAIN_Y);
17854+ DUMPREG(VENC_BLACK_LEVEL);
17855+ DUMPREG(VENC_BLANK_LEVEL);
17856+ DUMPREG(VENC_X_COLOR);
17857+ DUMPREG(VENC_M_CONTROL);
17858+ DUMPREG(VENC_BSTAMP_WSS_DATA);
17859+ DUMPREG(VENC_S_CARR);
17860+ DUMPREG(VENC_LINE21);
17861+ DUMPREG(VENC_LN_SEL);
17862+ DUMPREG(VENC_L21__WC_CTL);
17863+ DUMPREG(VENC_HTRIGGER_VTRIGGER);
17864+ DUMPREG(VENC_SAVID__EAVID);
17865+ DUMPREG(VENC_FLEN__FAL);
17866+ DUMPREG(VENC_LAL__PHASE_RESET);
17867+ DUMPREG(VENC_HS_INT_START_STOP_X);
17868+ DUMPREG(VENC_HS_EXT_START_STOP_X);
17869+ DUMPREG(VENC_VS_INT_START_X);
17870+ DUMPREG(VENC_VS_INT_STOP_X__VS_INT_START_Y);
17871+ DUMPREG(VENC_VS_INT_STOP_Y__VS_EXT_START_X);
17872+ DUMPREG(VENC_VS_EXT_STOP_X__VS_EXT_START_Y);
17873+ DUMPREG(VENC_VS_EXT_STOP_Y);
17874+ DUMPREG(VENC_AVID_START_STOP_X);
17875+ DUMPREG(VENC_AVID_START_STOP_Y);
17876+ DUMPREG(VENC_FID_INT_START_X__FID_INT_START_Y);
17877+ DUMPREG(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X);
17878+ DUMPREG(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y);
17879+ DUMPREG(VENC_TVDETGP_INT_START_STOP_X);
17880+ DUMPREG(VENC_TVDETGP_INT_START_STOP_Y);
17881+ DUMPREG(VENC_GEN_CTRL);
17882+ DUMPREG(VENC_OUTPUT_CONTROL);
17883+ DUMPREG(VENC_OUTPUT_TEST);
17884+
17885+ venc_enable_clocks(0);
17886+
17887+#undef DUMPREG
17888+}
17889--- /dev/null
17890+++ b/drivers/video/omap2/omapfb/Kconfig
17891@@ -0,0 +1,37 @@
17892+menuconfig FB_OMAP2
17893+ tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)"
17894+ depends on FB && OMAP2_DSS
17895+
17896+ select OMAP2_VRAM
17897+ select OMAP2_VRFB
17898+ select FB_CFB_FILLRECT
17899+ select FB_CFB_COPYAREA
17900+ select FB_CFB_IMAGEBLIT
17901+ help
17902+ Frame buffer driver for OMAP2/3 based boards.
17903+
17904+config FB_OMAP2_DEBUG_SUPPORT
17905+ bool "Debug support for OMAP2/3 FB"
17906+ default y
17907+ depends on FB_OMAP2
17908+ help
17909+ Support for debug output. You have to enable the actual printing
17910+ with debug module parameter.
17911+
17912+config FB_OMAP2_FORCE_AUTO_UPDATE
17913+ bool "Force main display to automatic update mode"
17914+ depends on FB_OMAP2
17915+ help
17916+ Forces main display to automatic update mode (if possible),
17917+ and also enables tearsync (if possible). By default
17918+ displays that support manual update are started in manual
17919+ update mode.
17920+
17921+config FB_OMAP2_NUM_FBS
17922+ int "Number of framebuffers"
17923+ range 1 10
17924+ default 3
17925+ depends on FB_OMAP2
17926+ help
17927+ Select the number of framebuffers created. OMAP2/3 has 3 overlays
17928+ so normally this would be 3.
17929--- /dev/null
17930+++ b/drivers/video/omap2/omapfb/Makefile
17931@@ -0,0 +1,2 @@
17932+obj-$(CONFIG_FB_OMAP2) += omapfb.o
17933+omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
17934--- /dev/null
17935+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
17936@@ -0,0 +1,727 @@
17937+/*
17938+ * linux/drivers/video/omap2/omapfb-ioctl.c
17939+ *
17940+ * Copyright (C) 2008 Nokia Corporation
17941+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
17942+ *
17943+ * Some code and ideas taken from drivers/video/omap/ driver
17944+ * by Imre Deak.
17945+ *
17946+ * This program is free software; you can redistribute it and/or modify it
17947+ * under the terms of the GNU General Public License version 2 as published by
17948+ * the Free Software Foundation.
17949+ *
17950+ * This program is distributed in the hope that it will be useful, but WITHOUT
17951+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17952+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17953+ * more details.
17954+ *
17955+ * You should have received a copy of the GNU General Public License along with
17956+ * this program. If not, see <http://www.gnu.org/licenses/>.
17957+ */
17958+
17959+#include <linux/fb.h>
17960+#include <linux/device.h>
17961+#include <linux/uaccess.h>
17962+#include <linux/platform_device.h>
17963+#include <linux/mm.h>
17964+#include <linux/omapfb.h>
17965+#include <linux/vmalloc.h>
17966+
17967+#include <mach/display.h>
17968+#include <mach/vrfb.h>
17969+#include <mach/vram.h>
17970+
17971+#include "omapfb.h"
17972+
17973+static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
17974+{
17975+ struct omapfb_info *ofbi = FB2OFB(fbi);
17976+ struct omapfb2_device *fbdev = ofbi->fbdev;
17977+ struct omap_dss_device *display = fb2display(fbi);
17978+ struct omap_overlay *ovl;
17979+ struct omap_overlay_info info;
17980+ int r = 0;
17981+
17982+ DBG("omapfb_setup_plane\n");
17983+
17984+ if (ofbi->num_overlays != 1) {
17985+ r = -EINVAL;
17986+ goto out;
17987+ }
17988+
17989+ /* XXX uses only the first overlay */
17990+ ovl = ofbi->overlays[0];
17991+
17992+ if (pi->enabled && !ofbi->region.size) {
17993+ /*
17994+ * This plane's memory was freed, can't enable it
17995+ * until it's reallocated.
17996+ */
17997+ r = -EINVAL;
17998+ goto out;
17999+ }
18000+
18001+ ovl->get_overlay_info(ovl, &info);
18002+
18003+ info.pos_x = pi->pos_x;
18004+ info.pos_y = pi->pos_y;
18005+ info.out_width = pi->out_width;
18006+ info.out_height = pi->out_height;
18007+ info.enabled = pi->enabled;
18008+
18009+ r = ovl->set_overlay_info(ovl, &info);
18010+ if (r)
18011+ goto out;
18012+
18013+ if (ovl->manager) {
18014+ r = ovl->manager->apply(ovl->manager);
18015+ if (r)
18016+ goto out;
18017+ }
18018+
18019+ if (display) {
18020+ u16 w, h;
18021+
18022+ if (display->sync)
18023+ display->sync(display);
18024+
18025+ display->get_resolution(display, &w, &h);
18026+
18027+ if (display->update)
18028+ display->update(display, 0, 0, w, h);
18029+ }
18030+
18031+out:
18032+ if (r)
18033+ dev_err(fbdev->dev, "setup_plane failed\n");
18034+ return r;
18035+}
18036+
18037+static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
18038+{
18039+ struct omapfb_info *ofbi = FB2OFB(fbi);
18040+
18041+ if (ofbi->num_overlays != 1) {
18042+ memset(pi, 0, sizeof(*pi));
18043+ } else {
18044+ struct omap_overlay_info *ovli;
18045+ struct omap_overlay *ovl;
18046+
18047+ ovl = ofbi->overlays[0];
18048+ ovli = &ovl->info;
18049+
18050+ pi->pos_x = ovli->pos_x;
18051+ pi->pos_y = ovli->pos_y;
18052+ pi->enabled = ovli->enabled;
18053+ pi->channel_out = 0; /* xxx */
18054+ pi->mirror = 0;
18055+ pi->out_width = ovli->out_width;
18056+ pi->out_height = ovli->out_height;
18057+ }
18058+
18059+ return 0;
18060+}
18061+
18062+static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
18063+{
18064+ struct omapfb_info *ofbi = FB2OFB(fbi);
18065+ struct omapfb2_device *fbdev = ofbi->fbdev;
18066+ struct omapfb2_mem_region *rg;
18067+ int r, i;
18068+ size_t size;
18069+
18070+ if (mi->type > OMAPFB_MEMTYPE_MAX)
18071+ return -EINVAL;
18072+
18073+ size = PAGE_ALIGN(mi->size);
18074+
18075+ rg = &ofbi->region;
18076+
18077+ for (i = 0; i < ofbi->num_overlays; i++) {
18078+ if (ofbi->overlays[i]->info.enabled)
18079+ return -EBUSY;
18080+ }
18081+
18082+ if (rg->size != size || rg->type != mi->type) {
18083+ r = omapfb_realloc_fbmem(fbi, size, mi->type);
18084+ if (r) {
18085+ dev_err(fbdev->dev, "realloc fbmem failed\n");
18086+ return r;
18087+ }
18088+ }
18089+
18090+ return 0;
18091+}
18092+
18093+static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
18094+{
18095+ struct omapfb_info *ofbi = FB2OFB(fbi);
18096+ struct omapfb2_mem_region *rg;
18097+
18098+ rg = &ofbi->region;
18099+ memset(mi, 0, sizeof(*mi));
18100+
18101+ mi->size = rg->size;
18102+ mi->type = rg->type;
18103+
18104+ return 0;
18105+}
18106+
18107+static int omapfb_update_window(struct fb_info *fbi,
18108+ u32 x, u32 y, u32 w, u32 h)
18109+{
18110+ struct omap_dss_device *display = fb2display(fbi);
18111+ u16 dw, dh;
18112+
18113+ if (!display)
18114+ return 0;
18115+
18116+ if (w == 0 || h == 0)
18117+ return 0;
18118+
18119+ display->get_resolution(display, &dw, &dh);
18120+
18121+ if (x + w > dw || y + h > dh)
18122+ return -EINVAL;
18123+
18124+ display->update(display, x, y, w, h);
18125+
18126+ return 0;
18127+}
18128+
18129+static int omapfb_set_update_mode(struct fb_info *fbi,
18130+ enum omapfb_update_mode mode)
18131+{
18132+ struct omap_dss_device *display = fb2display(fbi);
18133+ enum omap_dss_update_mode um;
18134+ int r;
18135+
18136+ if (!display || !display->set_update_mode)
18137+ return -EINVAL;
18138+
18139+ switch (mode) {
18140+ case OMAPFB_UPDATE_DISABLED:
18141+ um = OMAP_DSS_UPDATE_DISABLED;
18142+ break;
18143+
18144+ case OMAPFB_AUTO_UPDATE:
18145+ um = OMAP_DSS_UPDATE_AUTO;
18146+ break;
18147+
18148+ case OMAPFB_MANUAL_UPDATE:
18149+ um = OMAP_DSS_UPDATE_MANUAL;
18150+ break;
18151+
18152+ default:
18153+ return -EINVAL;
18154+ }
18155+
18156+ r = display->set_update_mode(display, um);
18157+
18158+ return r;
18159+}
18160+
18161+static int omapfb_get_update_mode(struct fb_info *fbi,
18162+ enum omapfb_update_mode *mode)
18163+{
18164+ struct omap_dss_device *display = fb2display(fbi);
18165+ enum omap_dss_update_mode m;
18166+
18167+ if (!display || !display->get_update_mode)
18168+ return -EINVAL;
18169+
18170+ m = display->get_update_mode(display);
18171+
18172+ switch (m) {
18173+ case OMAP_DSS_UPDATE_DISABLED:
18174+ *mode = OMAPFB_UPDATE_DISABLED;
18175+ break;
18176+ case OMAP_DSS_UPDATE_AUTO:
18177+ *mode = OMAPFB_AUTO_UPDATE;
18178+ break;
18179+ case OMAP_DSS_UPDATE_MANUAL:
18180+ *mode = OMAPFB_MANUAL_UPDATE;
18181+ break;
18182+ default:
18183+ BUG();
18184+ }
18185+
18186+ return 0;
18187+}
18188+
18189+/* XXX this color key handling is a hack... */
18190+static struct omapfb_color_key omapfb_color_keys[2];
18191+
18192+static int _omapfb_set_color_key(struct omap_overlay_manager *mgr,
18193+ struct omapfb_color_key *ck)
18194+{
18195+ struct omap_overlay_manager_info info;
18196+ enum omap_dss_trans_key_type kt;
18197+ int r;
18198+
18199+ mgr->get_manager_info(mgr, &info);
18200+
18201+ if (ck->key_type == OMAPFB_COLOR_KEY_DISABLED) {
18202+ info.trans_enabled = false;
18203+ omapfb_color_keys[mgr->id] = *ck;
18204+
18205+ r = mgr->set_manager_info(mgr, &info);
18206+ if (r)
18207+ return r;
18208+
18209+ r = mgr->apply(mgr);
18210+
18211+ return r;
18212+ }
18213+
18214+ switch (ck->key_type) {
18215+ case OMAPFB_COLOR_KEY_GFX_DST:
18216+ kt = OMAP_DSS_COLOR_KEY_GFX_DST;
18217+ break;
18218+ case OMAPFB_COLOR_KEY_VID_SRC:
18219+ kt = OMAP_DSS_COLOR_KEY_VID_SRC;
18220+ break;
18221+ default:
18222+ return -EINVAL;
18223+ }
18224+
18225+ info.default_color = ck->background;
18226+ info.trans_key = ck->trans_key;
18227+ info.trans_key_type = kt;
18228+ info.trans_enabled = true;
18229+
18230+ omapfb_color_keys[mgr->id] = *ck;
18231+
18232+ r = mgr->set_manager_info(mgr, &info);
18233+ if (r)
18234+ return r;
18235+
18236+ r = mgr->apply(mgr);
18237+
18238+ return r;
18239+}
18240+
18241+static int omapfb_set_color_key(struct fb_info *fbi,
18242+ struct omapfb_color_key *ck)
18243+{
18244+ struct omapfb_info *ofbi = FB2OFB(fbi);
18245+ struct omapfb2_device *fbdev = ofbi->fbdev;
18246+ int r;
18247+ int i;
18248+ struct omap_overlay_manager *mgr = NULL;
18249+
18250+ omapfb_lock(fbdev);
18251+
18252+ for (i = 0; i < ofbi->num_overlays; i++) {
18253+ if (ofbi->overlays[i]->manager) {
18254+ mgr = ofbi->overlays[i]->manager;
18255+ break;
18256+ }
18257+ }
18258+
18259+ if (!mgr) {
18260+ r = -EINVAL;
18261+ goto err;
18262+ }
18263+
18264+ r = _omapfb_set_color_key(mgr, ck);
18265+err:
18266+ omapfb_unlock(fbdev);
18267+
18268+ return r;
18269+}
18270+
18271+static int omapfb_get_color_key(struct fb_info *fbi,
18272+ struct omapfb_color_key *ck)
18273+{
18274+ struct omapfb_info *ofbi = FB2OFB(fbi);
18275+ struct omapfb2_device *fbdev = ofbi->fbdev;
18276+ struct omap_overlay_manager *mgr = NULL;
18277+ int r = 0;
18278+ int i;
18279+
18280+ omapfb_lock(fbdev);
18281+
18282+ for (i = 0; i < ofbi->num_overlays; i++) {
18283+ if (ofbi->overlays[i]->manager) {
18284+ mgr = ofbi->overlays[i]->manager;
18285+ break;
18286+ }
18287+ }
18288+
18289+ if (!mgr) {
18290+ r = -EINVAL;
18291+ goto err;
18292+ }
18293+
18294+ *ck = omapfb_color_keys[mgr->id];
18295+err:
18296+ omapfb_unlock(fbdev);
18297+
18298+ return r;
18299+}
18300+
18301+static int omapfb_memory_read(struct fb_info *fbi,
18302+ struct omapfb_memory_read *mr)
18303+{
18304+ struct omap_dss_device *display = fb2display(fbi);
18305+ void *buf;
18306+ int r;
18307+
18308+ if (!display || !display->memory_read)
18309+ return -ENOENT;
18310+
18311+ if (!access_ok(VERIFY_WRITE, mr->buffer, mr->buffer_size))
18312+ return -EFAULT;
18313+
18314+ if (mr->w * mr->h * 3 > mr->buffer_size)
18315+ return -EINVAL;
18316+
18317+ buf = vmalloc(mr->buffer_size);
18318+ if (!buf) {
18319+ DBG("vmalloc failed\n");
18320+ return -ENOMEM;
18321+ }
18322+
18323+ r = display->memory_read(display, buf, mr->buffer_size,
18324+ mr->x, mr->y, mr->w, mr->h);
18325+
18326+ if (r > 0) {
18327+ if (copy_to_user(mr->buffer, buf, mr->buffer_size))
18328+ r = -EFAULT;
18329+ }
18330+
18331+ vfree(buf);
18332+
18333+ return r;
18334+}
18335+
18336+static int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev,
18337+ struct omapfb_ovl_colormode *mode)
18338+{
18339+ int ovl_idx = mode->overlay_idx;
18340+ int mode_idx = mode->mode_idx;
18341+ struct omap_overlay *ovl;
18342+ enum omap_color_mode supported_modes;
18343+ struct fb_var_screeninfo var;
18344+ int i;
18345+
18346+ if (ovl_idx >= fbdev->num_overlays)
18347+ return -ENODEV;
18348+ ovl = fbdev->overlays[ovl_idx];
18349+ supported_modes = ovl->supported_modes;
18350+
18351+ mode_idx = mode->mode_idx;
18352+
18353+ for (i = 0; i < sizeof(supported_modes) * 8; i++) {
18354+ if (!(supported_modes & (1 << i)))
18355+ continue;
18356+ /*
18357+ * It's possible that the FB doesn't support a mode
18358+ * that is supported by the overlay, so call the
18359+ * following here.
18360+ */
18361+ if (dss_mode_to_fb_mode(1 << i, &var) < 0)
18362+ continue;
18363+
18364+ mode_idx--;
18365+ if (mode_idx < 0)
18366+ break;
18367+ }
18368+
18369+ if (i == sizeof(supported_modes) * 8)
18370+ return -ENOENT;
18371+
18372+ mode->bits_per_pixel = var.bits_per_pixel;
18373+ mode->nonstd = var.nonstd;
18374+ mode->red = var.red;
18375+ mode->green = var.green;
18376+ mode->blue = var.blue;
18377+ mode->transp = var.transp;
18378+
18379+ return 0;
18380+}
18381+
18382+static int omapfb_wait_for_go(struct fb_info *fbi)
18383+{
18384+ struct omapfb_info *ofbi = FB2OFB(fbi);
18385+ int r = 0;
18386+ int i;
18387+
18388+ for (i = 0; i < ofbi->num_overlays; ++i) {
18389+ struct omap_overlay *ovl = ofbi->overlays[i];
18390+ r = ovl->wait_for_go(ovl);
18391+ if (r)
18392+ break;
18393+ }
18394+
18395+ return r;
18396+}
18397+
18398+int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
18399+{
18400+ struct omapfb_info *ofbi = FB2OFB(fbi);
18401+ struct omapfb2_device *fbdev = ofbi->fbdev;
18402+ struct omap_dss_device *display = fb2display(fbi);
18403+
18404+ union {
18405+ struct omapfb_update_window_old uwnd_o;
18406+ struct omapfb_update_window uwnd;
18407+ struct omapfb_plane_info plane_info;
18408+ struct omapfb_caps caps;
18409+ struct omapfb_mem_info mem_info;
18410+ struct omapfb_color_key color_key;
18411+ struct omapfb_ovl_colormode ovl_colormode;
18412+ enum omapfb_update_mode update_mode;
18413+ int test_num;
18414+ struct omapfb_memory_read memory_read;
18415+ struct omapfb_vram_info vram_info;
18416+ } p;
18417+
18418+ int r = 0;
18419+
18420+ switch (cmd) {
18421+ case OMAPFB_SYNC_GFX:
18422+ DBG("ioctl SYNC_GFX\n");
18423+ if (!display || !display->sync) {
18424+ /* DSS1 never returns an error here, so we neither */
18425+ /*r = -EINVAL;*/
18426+ break;
18427+ }
18428+
18429+ r = display->sync(display);
18430+ break;
18431+
18432+ case OMAPFB_UPDATE_WINDOW_OLD:
18433+ DBG("ioctl UPDATE_WINDOW_OLD\n");
18434+ if (!display || !display->update) {
18435+ r = -EINVAL;
18436+ break;
18437+ }
18438+
18439+ if (copy_from_user(&p.uwnd_o,
18440+ (void __user *)arg,
18441+ sizeof(p.uwnd_o))) {
18442+ r = -EFAULT;
18443+ break;
18444+ }
18445+
18446+ r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y,
18447+ p.uwnd_o.width, p.uwnd_o.height);
18448+ break;
18449+
18450+ case OMAPFB_UPDATE_WINDOW:
18451+ DBG("ioctl UPDATE_WINDOW\n");
18452+ if (!display || !display->update) {
18453+ r = -EINVAL;
18454+ break;
18455+ }
18456+
18457+ if (copy_from_user(&p.uwnd, (void __user *)arg,
18458+ sizeof(p.uwnd))) {
18459+ r = -EFAULT;
18460+ break;
18461+ }
18462+
18463+ r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y,
18464+ p.uwnd.width, p.uwnd.height);
18465+ break;
18466+
18467+ case OMAPFB_SETUP_PLANE:
18468+ DBG("ioctl SETUP_PLANE\n");
18469+ if (copy_from_user(&p.plane_info, (void __user *)arg,
18470+ sizeof(p.plane_info)))
18471+ r = -EFAULT;
18472+ else
18473+ r = omapfb_setup_plane(fbi, &p.plane_info);
18474+ break;
18475+
18476+ case OMAPFB_QUERY_PLANE:
18477+ DBG("ioctl QUERY_PLANE\n");
18478+ r = omapfb_query_plane(fbi, &p.plane_info);
18479+ if (r < 0)
18480+ break;
18481+ if (copy_to_user((void __user *)arg, &p.plane_info,
18482+ sizeof(p.plane_info)))
18483+ r = -EFAULT;
18484+ break;
18485+
18486+ case OMAPFB_SETUP_MEM:
18487+ DBG("ioctl SETUP_MEM\n");
18488+ if (copy_from_user(&p.mem_info, (void __user *)arg,
18489+ sizeof(p.mem_info)))
18490+ r = -EFAULT;
18491+ else
18492+ r = omapfb_setup_mem(fbi, &p.mem_info);
18493+ break;
18494+
18495+ case OMAPFB_QUERY_MEM:
18496+ DBG("ioctl QUERY_MEM\n");
18497+ r = omapfb_query_mem(fbi, &p.mem_info);
18498+ if (r < 0)
18499+ break;
18500+ if (copy_to_user((void __user *)arg, &p.mem_info,
18501+ sizeof(p.mem_info)))
18502+ r = -EFAULT;
18503+ break;
18504+
18505+ case OMAPFB_GET_CAPS:
18506+ DBG("ioctl GET_CAPS\n");
18507+ if (!display) {
18508+ r = -EINVAL;
18509+ break;
18510+ }
18511+
18512+ memset(&p.caps, 0, sizeof(p.caps));
18513+ p.caps.ctrl = display->caps;
18514+
18515+ if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
18516+ r = -EFAULT;
18517+ break;
18518+
18519+ case OMAPFB_GET_OVERLAY_COLORMODE:
18520+ DBG("ioctl GET_OVERLAY_COLORMODE\n");
18521+ if (copy_from_user(&p.ovl_colormode, (void __user *)arg,
18522+ sizeof(p.ovl_colormode))) {
18523+ r = -EFAULT;
18524+ break;
18525+ }
18526+ r = omapfb_get_ovl_colormode(fbdev, &p.ovl_colormode);
18527+ if (r < 0)
18528+ break;
18529+ if (copy_to_user((void __user *)arg, &p.ovl_colormode,
18530+ sizeof(p.ovl_colormode)))
18531+ r = -EFAULT;
18532+ break;
18533+
18534+ case OMAPFB_SET_UPDATE_MODE:
18535+ DBG("ioctl SET_UPDATE_MODE\n");
18536+ if (get_user(p.update_mode, (int __user *)arg))
18537+ r = -EFAULT;
18538+ else
18539+ r = omapfb_set_update_mode(fbi, p.update_mode);
18540+ break;
18541+
18542+ case OMAPFB_GET_UPDATE_MODE:
18543+ DBG("ioctl GET_UPDATE_MODE\n");
18544+ r = omapfb_get_update_mode(fbi, &p.update_mode);
18545+ if (r)
18546+ break;
18547+ if (put_user(p.update_mode,
18548+ (enum omapfb_update_mode __user *)arg))
18549+ r = -EFAULT;
18550+ break;
18551+
18552+ case OMAPFB_SET_COLOR_KEY:
18553+ DBG("ioctl SET_COLOR_KEY\n");
18554+ if (copy_from_user(&p.color_key, (void __user *)arg,
18555+ sizeof(p.color_key)))
18556+ r = -EFAULT;
18557+ else
18558+ r = omapfb_set_color_key(fbi, &p.color_key);
18559+ break;
18560+
18561+ case OMAPFB_GET_COLOR_KEY:
18562+ DBG("ioctl GET_COLOR_KEY\n");
18563+ r = omapfb_get_color_key(fbi, &p.color_key);
18564+ if (r)
18565+ break;
18566+ if (copy_to_user((void __user *)arg, &p.color_key,
18567+ sizeof(p.color_key)))
18568+ r = -EFAULT;
18569+ break;
18570+
18571+ case OMAPFB_WAITFORVSYNC:
18572+ DBG("ioctl WAITFORVSYNC\n");
18573+ if (!display) {
18574+ r = -EINVAL;
18575+ break;
18576+ }
18577+
18578+ r = display->wait_vsync(display);
18579+ break;
18580+
18581+ case OMAPFB_WAITFORGO:
18582+ DBG("ioctl WAITFORGO\n");
18583+ if (!display) {
18584+ r = -EINVAL;
18585+ break;
18586+ }
18587+
18588+ r = omapfb_wait_for_go(fbi);
18589+ break;
18590+
18591+ /* LCD and CTRL tests do the same thing for backward
18592+ * compatibility */
18593+ case OMAPFB_LCD_TEST:
18594+ DBG("ioctl LCD_TEST\n");
18595+ if (get_user(p.test_num, (int __user *)arg)) {
18596+ r = -EFAULT;
18597+ break;
18598+ }
18599+ if (!display || !display->run_test) {
18600+ r = -EINVAL;
18601+ break;
18602+ }
18603+
18604+ r = display->run_test(display, p.test_num);
18605+
18606+ break;
18607+
18608+ case OMAPFB_CTRL_TEST:
18609+ DBG("ioctl CTRL_TEST\n");
18610+ if (get_user(p.test_num, (int __user *)arg)) {
18611+ r = -EFAULT;
18612+ break;
18613+ }
18614+ if (!display || !display->run_test) {
18615+ r = -EINVAL;
18616+ break;
18617+ }
18618+
18619+ r = display->run_test(display, p.test_num);
18620+
18621+ break;
18622+
18623+ case OMAPFB_MEMORY_READ:
18624+ DBG("ioctl MEMORY_READ\n");
18625+
18626+ if (copy_from_user(&p.memory_read, (void __user *)arg,
18627+ sizeof(p.memory_read))) {
18628+ r = -EFAULT;
18629+ break;
18630+ }
18631+
18632+ r = omapfb_memory_read(fbi, &p.memory_read);
18633+
18634+ break;
18635+
18636+ case OMAPFB_GET_VRAM_INFO: {
18637+ unsigned long vram, free, largest;
18638+
18639+ DBG("ioctl GET_VRAM_INFO\n");
18640+
18641+ omap_vram_get_info(&vram, &free, &largest);
18642+ p.vram_info.total = vram;
18643+ p.vram_info.free = free;
18644+ p.vram_info.largest_free_block = largest;
18645+
18646+ if (copy_to_user((void __user *)arg, &p.vram_info,
18647+ sizeof(p.vram_info)))
18648+ r = -EFAULT;
18649+ break;
18650+ }
18651+
18652+ default:
18653+ dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd);
18654+ r = -EINVAL;
18655+ }
18656+
18657+ if (r < 0)
18658+ DBG("ioctl failed: %d\n", r);
18659+
18660+ return r;
18661+}
18662+
18663+
18664--- /dev/null
18665+++ b/drivers/video/omap2/omapfb/omapfb-main.c
18666@@ -0,0 +1,2137 @@
18667+/*
18668+ * linux/drivers/video/omap2/omapfb-main.c
18669+ *
18670+ * Copyright (C) 2008 Nokia Corporation
18671+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
18672+ *
18673+ * Some code and ideas taken from drivers/video/omap/ driver
18674+ * by Imre Deak.
18675+ *
18676+ * This program is free software; you can redistribute it and/or modify it
18677+ * under the terms of the GNU General Public License version 2 as published by
18678+ * the Free Software Foundation.
18679+ *
18680+ * This program is distributed in the hope that it will be useful, but WITHOUT
18681+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18682+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18683+ * more details.
18684+ *
18685+ * You should have received a copy of the GNU General Public License along with
18686+ * this program. If not, see <http://www.gnu.org/licenses/>.
18687+ */
18688+
18689+#include <linux/module.h>
18690+#include <linux/delay.h>
18691+#include <linux/fb.h>
18692+#include <linux/dma-mapping.h>
18693+#include <linux/vmalloc.h>
18694+#include <linux/device.h>
18695+#include <linux/platform_device.h>
18696+#include <linux/omapfb.h>
18697+
18698+#include <mach/display.h>
18699+#include <mach/vram.h>
18700+#include <mach/vrfb.h>
18701+
18702+#include "omapfb.h"
18703+
18704+#define MODULE_NAME "omapfb"
18705+
18706+#define OMAPFB_PLANE_XRES_MIN 8
18707+#define OMAPFB_PLANE_YRES_MIN 8
18708+
18709+static char *def_mode;
18710+static char *def_vram;
18711+static int def_vrfb;
18712+static int def_rotate;
18713+static int def_mirror;
18714+
18715+#ifdef DEBUG
18716+unsigned int omapfb_debug;
18717+module_param_named(debug, omapfb_debug, bool, 0644);
18718+static unsigned int omapfb_test_pattern;
18719+module_param_named(test, omapfb_test_pattern, bool, 0644);
18720+#endif
18721+
18722+static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi);
18723+
18724+#ifdef DEBUG
18725+static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color)
18726+{
18727+ struct fb_var_screeninfo *var = &fbi->var;
18728+ struct fb_fix_screeninfo *fix = &fbi->fix;
18729+ void __iomem *addr = fbi->screen_base;
18730+ const unsigned bytespp = var->bits_per_pixel >> 3;
18731+ const unsigned line_len = fix->line_length / bytespp;
18732+
18733+ int r = (color >> 16) & 0xff;
18734+ int g = (color >> 8) & 0xff;
18735+ int b = (color >> 0) & 0xff;
18736+
18737+ if (var->bits_per_pixel == 16) {
18738+ u16 __iomem *p = (u16 __iomem *)addr;
18739+ p += y * line_len + x;
18740+
18741+ r = r * 32 / 256;
18742+ g = g * 64 / 256;
18743+ b = b * 32 / 256;
18744+
18745+ __raw_writew((r << 11) | (g << 5) | (b << 0), p);
18746+ } else if (var->bits_per_pixel == 24) {
18747+ u8 __iomem *p = (u8 __iomem *)addr;
18748+ p += (y * line_len + x) * 3;
18749+
18750+ __raw_writeb(b, p + 0);
18751+ __raw_writeb(g, p + 1);
18752+ __raw_writeb(r, p + 2);
18753+ } else if (var->bits_per_pixel == 32) {
18754+ u32 __iomem *p = (u32 __iomem *)addr;
18755+ p += y * line_len + x;
18756+ __raw_writel(color, p);
18757+ }
18758+}
18759+
18760+static void fill_fb(struct fb_info *fbi)
18761+{
18762+ struct fb_var_screeninfo *var = &fbi->var;
18763+ const short w = var->xres_virtual;
18764+ const short h = var->yres_virtual;
18765+ void __iomem *addr = fbi->screen_base;
18766+ int y, x;
18767+
18768+ if (!addr)
18769+ return;
18770+
18771+ DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length);
18772+
18773+ for (y = 0; y < h; y++) {
18774+ for (x = 0; x < w; x++) {
18775+ if (x < 20 && y < 20)
18776+ draw_pixel(fbi, x, y, 0xffffff);
18777+ else if (x < 20 && (y > 20 && y < h - 20))
18778+ draw_pixel(fbi, x, y, 0xff);
18779+ else if (y < 20 && (x > 20 && x < w - 20))
18780+ draw_pixel(fbi, x, y, 0xff00);
18781+ else if (x > w - 20 && (y > 20 && y < h - 20))
18782+ draw_pixel(fbi, x, y, 0xff0000);
18783+ else if (y > h - 20 && (x > 20 && x < w - 20))
18784+ draw_pixel(fbi, x, y, 0xffff00);
18785+ else if (x == 20 || x == w - 20 ||
18786+ y == 20 || y == h - 20)
18787+ draw_pixel(fbi, x, y, 0xffffff);
18788+ else if (x == y || w - x == h - y)
18789+ draw_pixel(fbi, x, y, 0xff00ff);
18790+ else if (w - x == y || x == h - y)
18791+ draw_pixel(fbi, x, y, 0x00ffff);
18792+ else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) {
18793+ int t = x * 3 / w;
18794+ unsigned r = 0, g = 0, b = 0;
18795+ unsigned c;
18796+ if (var->bits_per_pixel == 16) {
18797+ if (t == 0)
18798+ b = (y % 32) * 256 / 32;
18799+ else if (t == 1)
18800+ g = (y % 64) * 256 / 64;
18801+ else if (t == 2)
18802+ r = (y % 32) * 256 / 32;
18803+ } else {
18804+ if (t == 0)
18805+ b = (y % 256);
18806+ else if (t == 1)
18807+ g = (y % 256);
18808+ else if (t == 2)
18809+ r = (y % 256);
18810+ }
18811+ c = (r << 16) | (g << 8) | (b << 0);
18812+ draw_pixel(fbi, x, y, c);
18813+ } else {
18814+ draw_pixel(fbi, x, y, 0);
18815+ }
18816+ }
18817+ }
18818+}
18819+#endif
18820+
18821+static unsigned omapfb_get_vrfb_offset(struct omapfb_info *ofbi, int rot)
18822+{
18823+ struct vrfb *vrfb = &ofbi->region.vrfb;
18824+ unsigned offset;
18825+
18826+ switch (rot) {
18827+ case FB_ROTATE_UR:
18828+ offset = 0;
18829+ break;
18830+ case FB_ROTATE_CW:
18831+ offset = vrfb->yoffset;
18832+ break;
18833+ case FB_ROTATE_UD:
18834+ offset = vrfb->yoffset * OMAP_VRFB_LINE_LEN + vrfb->xoffset;
18835+ break;
18836+ case FB_ROTATE_CCW:
18837+ offset = vrfb->xoffset * OMAP_VRFB_LINE_LEN;
18838+ break;
18839+ default:
18840+ BUG();
18841+ }
18842+
18843+ offset *= vrfb->bytespp;
18844+
18845+ return offset;
18846+}
18847+
18848+static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi, int rot)
18849+{
18850+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
18851+ return ofbi->region.vrfb.paddr[rot]
18852+ + omapfb_get_vrfb_offset(ofbi, rot);
18853+ } else {
18854+ return ofbi->region.paddr;
18855+ }
18856+}
18857+
18858+static u32 omapfb_get_region_paddr(struct omapfb_info *ofbi)
18859+{
18860+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
18861+ return ofbi->region.vrfb.paddr[0];
18862+ else
18863+ return ofbi->region.paddr;
18864+}
18865+
18866+static void __iomem *omapfb_get_region_vaddr(struct omapfb_info *ofbi)
18867+{
18868+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
18869+ return ofbi->region.vrfb.vaddr[0];
18870+ else
18871+ return ofbi->region.vaddr;
18872+}
18873+
18874+static struct omapfb_colormode omapfb_colormodes[] = {
18875+ {
18876+ .dssmode = OMAP_DSS_COLOR_UYVY,
18877+ .bits_per_pixel = 16,
18878+ .nonstd = OMAPFB_COLOR_YUV422,
18879+ }, {
18880+ .dssmode = OMAP_DSS_COLOR_YUV2,
18881+ .bits_per_pixel = 16,
18882+ .nonstd = OMAPFB_COLOR_YUY422,
18883+ }, {
18884+ .dssmode = OMAP_DSS_COLOR_ARGB16,
18885+ .bits_per_pixel = 16,
18886+ .red = { .length = 4, .offset = 8, .msb_right = 0 },
18887+ .green = { .length = 4, .offset = 4, .msb_right = 0 },
18888+ .blue = { .length = 4, .offset = 0, .msb_right = 0 },
18889+ .transp = { .length = 4, .offset = 12, .msb_right = 0 },
18890+ }, {
18891+ .dssmode = OMAP_DSS_COLOR_RGB16,
18892+ .bits_per_pixel = 16,
18893+ .red = { .length = 5, .offset = 11, .msb_right = 0 },
18894+ .green = { .length = 6, .offset = 5, .msb_right = 0 },
18895+ .blue = { .length = 5, .offset = 0, .msb_right = 0 },
18896+ .transp = { .length = 0, .offset = 0, .msb_right = 0 },
18897+ }, {
18898+ .dssmode = OMAP_DSS_COLOR_RGB24P,
18899+ .bits_per_pixel = 24,
18900+ .red = { .length = 8, .offset = 16, .msb_right = 0 },
18901+ .green = { .length = 8, .offset = 8, .msb_right = 0 },
18902+ .blue = { .length = 8, .offset = 0, .msb_right = 0 },
18903+ .transp = { .length = 0, .offset = 0, .msb_right = 0 },
18904+ }, {
18905+ .dssmode = OMAP_DSS_COLOR_RGB24U,
18906+ .bits_per_pixel = 32,
18907+ .red = { .length = 8, .offset = 16, .msb_right = 0 },
18908+ .green = { .length = 8, .offset = 8, .msb_right = 0 },
18909+ .blue = { .length = 8, .offset = 0, .msb_right = 0 },
18910+ .transp = { .length = 0, .offset = 0, .msb_right = 0 },
18911+ }, {
18912+ .dssmode = OMAP_DSS_COLOR_ARGB32,
18913+ .bits_per_pixel = 32,
18914+ .red = { .length = 8, .offset = 16, .msb_right = 0 },
18915+ .green = { .length = 8, .offset = 8, .msb_right = 0 },
18916+ .blue = { .length = 8, .offset = 0, .msb_right = 0 },
18917+ .transp = { .length = 8, .offset = 24, .msb_right = 0 },
18918+ }, {
18919+ .dssmode = OMAP_DSS_COLOR_RGBA32,
18920+ .bits_per_pixel = 32,
18921+ .red = { .length = 8, .offset = 24, .msb_right = 0 },
18922+ .green = { .length = 8, .offset = 16, .msb_right = 0 },
18923+ .blue = { .length = 8, .offset = 8, .msb_right = 0 },
18924+ .transp = { .length = 8, .offset = 0, .msb_right = 0 },
18925+ }, {
18926+ .dssmode = OMAP_DSS_COLOR_RGBX32,
18927+ .bits_per_pixel = 32,
18928+ .red = { .length = 8, .offset = 24, .msb_right = 0 },
18929+ .green = { .length = 8, .offset = 16, .msb_right = 0 },
18930+ .blue = { .length = 8, .offset = 8, .msb_right = 0 },
18931+ .transp = { .length = 0, .offset = 0, .msb_right = 0 },
18932+ },
18933+};
18934+
18935+static bool cmp_var_to_colormode(struct fb_var_screeninfo *var,
18936+ struct omapfb_colormode *color)
18937+{
18938+ bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2)
18939+ {
18940+ return f1->length == f2->length &&
18941+ f1->offset == f2->offset &&
18942+ f1->msb_right == f2->msb_right;
18943+ }
18944+
18945+ if (var->bits_per_pixel == 0 ||
18946+ var->red.length == 0 ||
18947+ var->blue.length == 0 ||
18948+ var->green.length == 0)
18949+ return 0;
18950+
18951+ return var->bits_per_pixel == color->bits_per_pixel &&
18952+ cmp_component(&var->red, &color->red) &&
18953+ cmp_component(&var->green, &color->green) &&
18954+ cmp_component(&var->blue, &color->blue) &&
18955+ cmp_component(&var->transp, &color->transp);
18956+}
18957+
18958+static void assign_colormode_to_var(struct fb_var_screeninfo *var,
18959+ struct omapfb_colormode *color)
18960+{
18961+ var->bits_per_pixel = color->bits_per_pixel;
18962+ var->nonstd = color->nonstd;
18963+ var->red = color->red;
18964+ var->green = color->green;
18965+ var->blue = color->blue;
18966+ var->transp = color->transp;
18967+}
18968+
18969+static enum omap_color_mode fb_mode_to_dss_mode(struct fb_var_screeninfo *var)
18970+{
18971+ enum omap_color_mode dssmode;
18972+ int i;
18973+
18974+ /* first match with nonstd field */
18975+ if (var->nonstd) {
18976+ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
18977+ struct omapfb_colormode *mode = &omapfb_colormodes[i];
18978+ if (var->nonstd == mode->nonstd) {
18979+ assign_colormode_to_var(var, mode);
18980+ return mode->dssmode;
18981+ }
18982+ }
18983+
18984+ return -EINVAL;
18985+ }
18986+
18987+ /* then try exact match of bpp and colors */
18988+ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
18989+ struct omapfb_colormode *mode = &omapfb_colormodes[i];
18990+ if (cmp_var_to_colormode(var, mode)) {
18991+ assign_colormode_to_var(var, mode);
18992+ return mode->dssmode;
18993+ }
18994+ }
18995+
18996+ /* match with bpp if user has not filled color fields
18997+ * properly */
18998+ switch (var->bits_per_pixel) {
18999+ case 1:
19000+ dssmode = OMAP_DSS_COLOR_CLUT1;
19001+ break;
19002+ case 2:
19003+ dssmode = OMAP_DSS_COLOR_CLUT2;
19004+ break;
19005+ case 4:
19006+ dssmode = OMAP_DSS_COLOR_CLUT4;
19007+ break;
19008+ case 8:
19009+ dssmode = OMAP_DSS_COLOR_CLUT8;
19010+ break;
19011+ case 12:
19012+ dssmode = OMAP_DSS_COLOR_RGB12U;
19013+ break;
19014+ case 16:
19015+ dssmode = OMAP_DSS_COLOR_RGB16;
19016+ break;
19017+ case 24:
19018+ dssmode = OMAP_DSS_COLOR_RGB24P;
19019+ break;
19020+ case 32:
19021+ dssmode = OMAP_DSS_COLOR_RGB24U;
19022+ break;
19023+ default:
19024+ return -EINVAL;
19025+ }
19026+
19027+ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
19028+ struct omapfb_colormode *mode = &omapfb_colormodes[i];
19029+ if (dssmode == mode->dssmode) {
19030+ assign_colormode_to_var(var, mode);
19031+ return mode->dssmode;
19032+ }
19033+ }
19034+
19035+ return -EINVAL;
19036+}
19037+
19038+int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
19039+ struct fb_var_screeninfo *var)
19040+{
19041+ int i;
19042+
19043+ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
19044+ struct omapfb_colormode *mode = &omapfb_colormodes[i];
19045+ if (dssmode == mode->dssmode) {
19046+ assign_colormode_to_var(var, mode);
19047+ return 0;
19048+ }
19049+ }
19050+ return -ENOENT;
19051+}
19052+
19053+void set_fb_fix(struct fb_info *fbi)
19054+{
19055+ struct fb_fix_screeninfo *fix = &fbi->fix;
19056+ struct fb_var_screeninfo *var = &fbi->var;
19057+ struct omapfb_info *ofbi = FB2OFB(fbi);
19058+ struct omapfb2_mem_region *rg = &ofbi->region;
19059+
19060+ DBG("set_fb_fix\n");
19061+
19062+ /* used by open/write in fbmem.c */
19063+ fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
19064+
19065+ DBG("changing rotation to %d\n", var->rotate);
19066+
19067+ /* used by mmap in fbmem.c */
19068+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
19069+ switch (var->nonstd) {
19070+ case OMAPFB_COLOR_YUV422:
19071+ case OMAPFB_COLOR_YUY422:
19072+ fix->line_length =
19073+ (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
19074+ break;
19075+ default:
19076+ fix->line_length =
19077+ (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
19078+ break;
19079+ }
19080+ } else
19081+ fix->line_length =
19082+ (var->xres_virtual * var->bits_per_pixel) >> 3;
19083+ fix->smem_start = omapfb_get_region_paddr(ofbi);
19084+ fix->smem_len = rg->size;
19085+
19086+ fix->type = FB_TYPE_PACKED_PIXELS;
19087+
19088+ if (var->nonstd)
19089+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
19090+ else {
19091+ switch (var->bits_per_pixel) {
19092+ case 32:
19093+ case 24:
19094+ case 16:
19095+ case 12:
19096+ fix->visual = FB_VISUAL_TRUECOLOR;
19097+ /* 12bpp is stored in 16 bits */
19098+ break;
19099+ case 1:
19100+ case 2:
19101+ case 4:
19102+ case 8:
19103+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
19104+ break;
19105+ }
19106+ }
19107+
19108+ fix->accel = FB_ACCEL_NONE;
19109+
19110+ fix->xpanstep = 1;
19111+ fix->ypanstep = 1;
19112+
19113+ if (rg->size && ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
19114+ unsigned bytespp;
19115+ bool yuv_mode;
19116+ enum omap_color_mode mode;
19117+
19118+ mode = fb_mode_to_dss_mode(var);
19119+
19120+ bytespp = var->bits_per_pixel >> 3;
19121+
19122+ if (mode == OMAP_DSS_COLOR_YUV2 || mode == OMAP_DSS_COLOR_UYVY)
19123+ yuv_mode = true;
19124+ else
19125+ yuv_mode = false;
19126+
19127+ omap_vrfb_setup(&rg->vrfb, rg->paddr,
19128+ var->xres_virtual,
19129+ var->yres_virtual,
19130+ bytespp, yuv_mode);
19131+ }
19132+}
19133+
19134+/* check new var and possibly modify it to be ok */
19135+int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
19136+{
19137+ struct omapfb_info *ofbi = FB2OFB(fbi);
19138+ struct omap_dss_device *display = fb2display(fbi);
19139+ unsigned long max_frame_size;
19140+ unsigned long line_size;
19141+ int xres_min, yres_min;
19142+ int xres_max, yres_max;
19143+ enum omap_color_mode mode = 0;
19144+ int i;
19145+ int bytespp;
19146+
19147+ DBG("check_fb_var %d\n", ofbi->id);
19148+
19149+ if (ofbi->region.size == 0)
19150+ return 0;
19151+
19152+ mode = fb_mode_to_dss_mode(var);
19153+ if (mode < 0) {
19154+ DBG("cannot convert var to omap dss mode\n");
19155+ return -EINVAL;
19156+ }
19157+
19158+ for (i = 0; i < ofbi->num_overlays; ++i) {
19159+ if ((ofbi->overlays[i]->supported_modes & mode) == 0) {
19160+ DBG("invalid mode\n");
19161+ return -EINVAL;
19162+ }
19163+ }
19164+
19165+ if (var->rotate < 0 || var->rotate > 3)
19166+ return -EINVAL;
19167+
19168+ xres_min = OMAPFB_PLANE_XRES_MIN;
19169+ xres_max = 2048;
19170+ yres_min = OMAPFB_PLANE_YRES_MIN;
19171+ yres_max = 2048;
19172+
19173+ bytespp = var->bits_per_pixel >> 3;
19174+
19175+ /* XXX: some applications seem to set virtual res to 0. */
19176+ if (var->xres_virtual == 0)
19177+ var->xres_virtual = var->xres;
19178+
19179+ if (var->yres_virtual == 0)
19180+ var->yres_virtual = var->yres;
19181+
19182+ if (var->xres_virtual < xres_min || var->yres_virtual < yres_min)
19183+ return -EINVAL;
19184+
19185+ if (var->xres < xres_min)
19186+ var->xres = xres_min;
19187+ if (var->yres < yres_min)
19188+ var->yres = yres_min;
19189+ if (var->xres > xres_max)
19190+ var->xres = xres_max;
19191+ if (var->yres > yres_max)
19192+ var->yres = yres_max;
19193+
19194+ if (var->xres > var->xres_virtual)
19195+ var->xres = var->xres_virtual;
19196+ if (var->yres > var->yres_virtual)
19197+ var->yres = var->yres_virtual;
19198+
19199+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
19200+ line_size = OMAP_VRFB_LINE_LEN * bytespp;
19201+ else
19202+ line_size = var->xres_virtual * bytespp;
19203+
19204+ max_frame_size = ofbi->region.size;
19205+
19206+ DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size);
19207+
19208+ if (line_size * var->yres_virtual > max_frame_size) {
19209+ DBG("can't fit FB into memory, reducing y\n");
19210+ var->yres_virtual = max_frame_size / line_size;
19211+
19212+ if (var->yres_virtual < yres_min)
19213+ var->yres_virtual = yres_min;
19214+
19215+ if (var->yres > var->yres_virtual)
19216+ var->yres = var->yres_virtual;
19217+ }
19218+
19219+ if (line_size * var->yres_virtual > max_frame_size) {
19220+ DBG("can't fit FB into memory, reducing x\n");
19221+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
19222+ return -EINVAL;
19223+
19224+ var->xres_virtual = max_frame_size / var->yres_virtual /
19225+ bytespp;
19226+
19227+ if (var->xres_virtual < xres_min)
19228+ var->xres_virtual = xres_min;
19229+
19230+ if (var->xres > var->xres_virtual)
19231+ var->xres = var->xres_virtual;
19232+
19233+ line_size = var->xres_virtual * bytespp;
19234+ }
19235+
19236+ if (line_size * var->yres_virtual > max_frame_size) {
19237+ DBG("cannot fit FB to memory\n");
19238+ return -EINVAL;
19239+ }
19240+
19241+ if (var->xres + var->xoffset > var->xres_virtual)
19242+ var->xoffset = var->xres_virtual - var->xres;
19243+ if (var->yres + var->yoffset > var->yres_virtual)
19244+ var->yoffset = var->yres_virtual - var->yres;
19245+
19246+ DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n",
19247+ var->xres, var->yres,
19248+ var->xres_virtual, var->yres_virtual);
19249+
19250+ var->height = -1;
19251+ var->width = -1;
19252+ var->grayscale = 0;
19253+
19254+ if (display && display->get_timings) {
19255+ struct omap_video_timings timings;
19256+ display->get_timings(display, &timings);
19257+
19258+ /* pixclock in ps, the rest in pixclock */
19259+ var->pixclock = timings.pixel_clock != 0 ?
19260+ KHZ2PICOS(timings.pixel_clock) :
19261+ 0;
19262+ var->left_margin = timings.hfp;
19263+ var->right_margin = timings.hbp;
19264+ var->upper_margin = timings.vfp;
19265+ var->lower_margin = timings.vbp;
19266+ var->hsync_len = timings.hsw;
19267+ var->vsync_len = timings.vsw;
19268+ } else {
19269+ var->pixclock = 0;
19270+ var->left_margin = 0;
19271+ var->right_margin = 0;
19272+ var->upper_margin = 0;
19273+ var->lower_margin = 0;
19274+ var->hsync_len = 0;
19275+ var->vsync_len = 0;
19276+ }
19277+
19278+ /* TODO: get these from panel->config */
19279+ var->vmode = FB_VMODE_NONINTERLACED;
19280+ var->sync = 0;
19281+
19282+ return 0;
19283+}
19284+
19285+/*
19286+ * ---------------------------------------------------------------------------
19287+ * fbdev framework callbacks
19288+ * ---------------------------------------------------------------------------
19289+ */
19290+static int omapfb_open(struct fb_info *fbi, int user)
19291+{
19292+ return 0;
19293+}
19294+
19295+static int omapfb_release(struct fb_info *fbi, int user)
19296+{
19297+#if 0
19298+ struct omapfb_info *ofbi = FB2OFB(fbi);
19299+ struct omapfb2_device *fbdev = ofbi->fbdev;
19300+ struct omap_dss_device *display = fb2display(fbi);
19301+
19302+ DBG("Closing fb with plane index %d\n", ofbi->id);
19303+
19304+ omapfb_lock(fbdev);
19305+
19306+ if (display && display->get_update_mode && display->update) {
19307+ /* XXX this update should be removed, I think. But it's
19308+ * good for debugging */
19309+ if (display->get_update_mode(display) ==
19310+ OMAP_DSS_UPDATE_MANUAL) {
19311+ u16 w, h;
19312+
19313+ if (display->sync)
19314+ display->sync(display);
19315+
19316+ display->get_resolution(display, &w, &h);
19317+ display->update(display, 0, 0, w, h);
19318+ }
19319+ }
19320+
19321+ if (display && display->sync)
19322+ display->sync(display);
19323+
19324+ omapfb_unlock(fbdev);
19325+#endif
19326+ return 0;
19327+}
19328+
19329+/* setup overlay according to the fb */
19330+static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
19331+ u16 posx, u16 posy, u16 outw, u16 outh)
19332+{
19333+ int r = 0;
19334+ struct omapfb_info *ofbi = FB2OFB(fbi);
19335+ struct fb_var_screeninfo *var = &fbi->var;
19336+ struct fb_fix_screeninfo *fix = &fbi->fix;
19337+ enum omap_color_mode mode = 0;
19338+ int offset;
19339+ u32 data_start_p;
19340+ void __iomem *data_start_v;
19341+ struct omap_overlay_info info;
19342+ int xres, yres;
19343+ int screen_width;
19344+ int mirror;
19345+ int rotation = var->rotate;
19346+ int i;
19347+
19348+ for (i = 0; i < ofbi->num_overlays; i++) {
19349+ if (ovl != ofbi->overlays[i])
19350+ continue;
19351+
19352+ rotation = (rotation + ofbi->rotation[i]) % 4;
19353+ break;
19354+ }
19355+
19356+ DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
19357+ posx, posy, outw, outh);
19358+
19359+ if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW) {
19360+ xres = var->yres;
19361+ yres = var->xres;
19362+ } else {
19363+ xres = var->xres;
19364+ yres = var->yres;
19365+ }
19366+
19367+ offset = ((var->yoffset * var->xres_virtual +
19368+ var->xoffset) * var->bits_per_pixel) >> 3;
19369+
19370+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
19371+ data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
19372+ data_start_v = NULL;
19373+ } else {
19374+ data_start_p = omapfb_get_region_paddr(ofbi);
19375+ data_start_v = omapfb_get_region_vaddr(ofbi);
19376+ }
19377+
19378+ data_start_p += offset;
19379+ data_start_v += offset;
19380+
19381+ mode = fb_mode_to_dss_mode(var);
19382+
19383+ if (mode == -EINVAL) {
19384+ DBG("fb_mode_to_dss_mode failed");
19385+ r = -EINVAL;
19386+ goto err;
19387+ }
19388+
19389+ switch (var->nonstd) {
19390+ case OMAPFB_COLOR_YUV422:
19391+ case OMAPFB_COLOR_YUY422:
19392+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
19393+ screen_width = fix->line_length
19394+ / (var->bits_per_pixel >> 2);
19395+ break;
19396+ }
19397+ default:
19398+ screen_width = fix->line_length / (var->bits_per_pixel >> 3);
19399+ break;
19400+ }
19401+
19402+ ovl->get_overlay_info(ovl, &info);
19403+
19404+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
19405+ mirror = 0;
19406+ else
19407+ mirror = ofbi->mirror;
19408+
19409+ info.paddr = data_start_p;
19410+ info.vaddr = data_start_v;
19411+ info.screen_width = screen_width;
19412+ info.width = xres;
19413+ info.height = yres;
19414+ info.color_mode = mode;
19415+ info.rotation_type = ofbi->rotation_type;
19416+ info.rotation = rotation;
19417+ info.mirror = mirror;
19418+
19419+ info.pos_x = posx;
19420+ info.pos_y = posy;
19421+ info.out_width = outw;
19422+ info.out_height = outh;
19423+
19424+ r = ovl->set_overlay_info(ovl, &info);
19425+ if (r) {
19426+ DBG("ovl->setup_overlay_info failed\n");
19427+ goto err;
19428+ }
19429+
19430+ return 0;
19431+
19432+err:
19433+ DBG("setup_overlay failed\n");
19434+ return r;
19435+}
19436+
19437+/* apply var to the overlay */
19438+int omapfb_apply_changes(struct fb_info *fbi, int init)
19439+{
19440+ int r = 0;
19441+ struct omapfb_info *ofbi = FB2OFB(fbi);
19442+ struct fb_var_screeninfo *var = &fbi->var;
19443+ struct omap_overlay *ovl;
19444+ u16 posx, posy;
19445+ u16 outw, outh;
19446+ int i;
19447+
19448+#ifdef DEBUG
19449+ if (omapfb_test_pattern)
19450+ fill_fb(fbi);
19451+#endif
19452+
19453+ for (i = 0; i < ofbi->num_overlays; i++) {
19454+ ovl = ofbi->overlays[i];
19455+
19456+ DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
19457+
19458+ if (ofbi->region.size == 0) {
19459+ /* the fb is not available. disable the overlay */
19460+ omapfb_overlay_enable(ovl, 0);
19461+ if (!init && ovl->manager)
19462+ ovl->manager->apply(ovl->manager);
19463+ continue;
19464+ }
19465+
19466+ if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
19467+ int rotation = (var->rotate + ofbi->rotation[i]) % 4;
19468+ if (rotation == FB_ROTATE_CW ||
19469+ rotation == FB_ROTATE_CCW) {
19470+ outw = var->yres;
19471+ outh = var->xres;
19472+ } else {
19473+ outw = var->xres;
19474+ outh = var->yres;
19475+ }
19476+ } else {
19477+ outw = ovl->info.out_width;
19478+ outh = ovl->info.out_height;
19479+ }
19480+
19481+ if (init) {
19482+ posx = 0;
19483+ posy = 0;
19484+ } else {
19485+ posx = ovl->info.pos_x;
19486+ posy = ovl->info.pos_y;
19487+ }
19488+
19489+ r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
19490+ if (r)
19491+ goto err;
19492+
19493+ if (!init && ovl->manager)
19494+ ovl->manager->apply(ovl->manager);
19495+ }
19496+ return 0;
19497+err:
19498+ DBG("apply_changes failed\n");
19499+ return r;
19500+}
19501+
19502+/* checks var and eventually tweaks it to something supported,
19503+ * DO NOT MODIFY PAR */
19504+static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
19505+{
19506+ int r;
19507+
19508+ DBG("check_var(%d)\n", FB2OFB(fbi)->id);
19509+
19510+ r = check_fb_var(fbi, var);
19511+
19512+ return r;
19513+}
19514+
19515+/* set the video mode according to info->var */
19516+static int omapfb_set_par(struct fb_info *fbi)
19517+{
19518+ int r;
19519+
19520+ DBG("set_par(%d)\n", FB2OFB(fbi)->id);
19521+
19522+ set_fb_fix(fbi);
19523+ r = omapfb_apply_changes(fbi, 0);
19524+
19525+ return r;
19526+}
19527+
19528+static int omapfb_pan_display(struct fb_var_screeninfo *var,
19529+ struct fb_info *fbi)
19530+{
19531+ struct omapfb_info *ofbi = FB2OFB(fbi);
19532+ int r = 0;
19533+
19534+ DBG("pan_display(%d)\n", ofbi->id);
19535+
19536+ if (var->xoffset != fbi->var.xoffset ||
19537+ var->yoffset != fbi->var.yoffset) {
19538+ struct fb_var_screeninfo new_var;
19539+
19540+ new_var = fbi->var;
19541+ new_var.xoffset = var->xoffset;
19542+ new_var.yoffset = var->yoffset;
19543+
19544+ r = check_fb_var(fbi, &new_var);
19545+
19546+ if (r == 0) {
19547+ fbi->var = new_var;
19548+ set_fb_fix(fbi);
19549+ r = omapfb_apply_changes(fbi, 0);
19550+ }
19551+ }
19552+
19553+ return r;
19554+}
19555+
19556+static void mmap_user_open(struct vm_area_struct *vma)
19557+{
19558+ struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
19559+
19560+ atomic_inc(&ofbi->map_count);
19561+}
19562+
19563+static void mmap_user_close(struct vm_area_struct *vma)
19564+{
19565+ struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
19566+
19567+ atomic_dec(&ofbi->map_count);
19568+}
19569+
19570+static struct vm_operations_struct mmap_user_ops = {
19571+ .open = mmap_user_open,
19572+ .close = mmap_user_close,
19573+};
19574+
19575+static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
19576+{
19577+ struct omapfb_info *ofbi = FB2OFB(fbi);
19578+ struct fb_fix_screeninfo *fix = &fbi->fix;
19579+ unsigned long off;
19580+ unsigned long start;
19581+ u32 len;
19582+
19583+ if (vma->vm_end - vma->vm_start == 0)
19584+ return 0;
19585+ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
19586+ return -EINVAL;
19587+ off = vma->vm_pgoff << PAGE_SHIFT;
19588+
19589+ start = omapfb_get_region_paddr(ofbi);
19590+ len = fix->smem_len;
19591+ if (off >= len)
19592+ return -EINVAL;
19593+ if ((vma->vm_end - vma->vm_start + off) > len)
19594+ return -EINVAL;
19595+
19596+ off += start;
19597+
19598+ DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off);
19599+
19600+ vma->vm_pgoff = off >> PAGE_SHIFT;
19601+ vma->vm_flags |= VM_IO | VM_RESERVED;
19602+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
19603+ vma->vm_ops = &mmap_user_ops;
19604+ vma->vm_private_data = ofbi;
19605+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
19606+ vma->vm_end - vma->vm_start, vma->vm_page_prot))
19607+ return -EAGAIN;
19608+ /* vm_ops.open won't be called for mmap itself. */
19609+ atomic_inc(&ofbi->map_count);
19610+ return 0;
19611+}
19612+
19613+/* Store a single color palette entry into a pseudo palette or the hardware
19614+ * palette if one is available. For now we support only 16bpp and thus store
19615+ * the entry only to the pseudo palette.
19616+ */
19617+static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
19618+ u_int blue, u_int transp, int update_hw_pal)
19619+{
19620+ /*struct omapfb_info *ofbi = FB2OFB(fbi);*/
19621+ /*struct omapfb2_device *fbdev = ofbi->fbdev;*/
19622+ struct fb_var_screeninfo *var = &fbi->var;
19623+ int r = 0;
19624+
19625+ enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */
19626+
19627+ /*switch (plane->color_mode) {*/
19628+ switch (mode) {
19629+ case OMAPFB_COLOR_YUV422:
19630+ case OMAPFB_COLOR_YUV420:
19631+ case OMAPFB_COLOR_YUY422:
19632+ r = -EINVAL;
19633+ break;
19634+ case OMAPFB_COLOR_CLUT_8BPP:
19635+ case OMAPFB_COLOR_CLUT_4BPP:
19636+ case OMAPFB_COLOR_CLUT_2BPP:
19637+ case OMAPFB_COLOR_CLUT_1BPP:
19638+ /*
19639+ if (fbdev->ctrl->setcolreg)
19640+ r = fbdev->ctrl->setcolreg(regno, red, green, blue,
19641+ transp, update_hw_pal);
19642+ */
19643+ /* Fallthrough */
19644+ r = -EINVAL;
19645+ break;
19646+ case OMAPFB_COLOR_RGB565:
19647+ case OMAPFB_COLOR_RGB444:
19648+ case OMAPFB_COLOR_RGB24P:
19649+ case OMAPFB_COLOR_RGB24U:
19650+ if (r != 0)
19651+ break;
19652+
19653+ if (regno < 0) {
19654+ r = -EINVAL;
19655+ break;
19656+ }
19657+
19658+ if (regno < 16) {
19659+ u16 pal;
19660+ pal = ((red >> (16 - var->red.length)) <<
19661+ var->red.offset) |
19662+ ((green >> (16 - var->green.length)) <<
19663+ var->green.offset) |
19664+ (blue >> (16 - var->blue.length));
19665+ ((u32 *)(fbi->pseudo_palette))[regno] = pal;
19666+ }
19667+ break;
19668+ default:
19669+ BUG();
19670+ }
19671+ return r;
19672+}
19673+
19674+static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
19675+ u_int transp, struct fb_info *info)
19676+{
19677+ DBG("setcolreg\n");
19678+
19679+ return _setcolreg(info, regno, red, green, blue, transp, 1);
19680+}
19681+
19682+static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
19683+{
19684+ int count, index, r;
19685+ u16 *red, *green, *blue, *transp;
19686+ u16 trans = 0xffff;
19687+
19688+ DBG("setcmap\n");
19689+
19690+ red = cmap->red;
19691+ green = cmap->green;
19692+ blue = cmap->blue;
19693+ transp = cmap->transp;
19694+ index = cmap->start;
19695+
19696+ for (count = 0; count < cmap->len; count++) {
19697+ if (transp)
19698+ trans = *transp++;
19699+ r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
19700+ count == cmap->len - 1);
19701+ if (r != 0)
19702+ return r;
19703+ }
19704+
19705+ return 0;
19706+}
19707+
19708+static void omapfb_vrfb_suspend_all(struct omapfb2_device *fbdev)
19709+{
19710+ int i;
19711+
19712+ for (i = 0; i < fbdev->num_fbs; i++) {
19713+ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
19714+
19715+ if (ofbi->region.vrfb.vaddr[0])
19716+ omap_vrfb_suspend_ctx(&ofbi->region.vrfb);
19717+ }
19718+}
19719+
19720+static void omapfb_vrfb_resume_all(struct omapfb2_device *fbdev)
19721+{
19722+ int i;
19723+
19724+ for (i = 0; i < fbdev->num_fbs; i++) {
19725+ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
19726+
19727+ if (ofbi->region.vrfb.vaddr[0])
19728+ omap_vrfb_resume_ctx(&ofbi->region.vrfb);
19729+ }
19730+}
19731+
19732+static int omapfb_blank(int blank, struct fb_info *fbi)
19733+{
19734+ struct omapfb_info *ofbi = FB2OFB(fbi);
19735+ struct omapfb2_device *fbdev = ofbi->fbdev;
19736+ struct omap_dss_device *display = fb2display(fbi);
19737+ int do_update = 0;
19738+ int r = 0;
19739+
19740+ omapfb_lock(fbdev);
19741+
19742+ switch (blank) {
19743+ case FB_BLANK_UNBLANK:
19744+ if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
19745+ goto exit;
19746+
19747+ omapfb_vrfb_resume_all(fbdev);
19748+
19749+ if (display->resume)
19750+ r = display->resume(display);
19751+
19752+ if (r == 0 && display->get_update_mode &&
19753+ display->get_update_mode(display) ==
19754+ OMAP_DSS_UPDATE_MANUAL)
19755+ do_update = 1;
19756+
19757+ break;
19758+
19759+ case FB_BLANK_NORMAL:
19760+ /* FB_BLANK_NORMAL could be implemented.
19761+ * Needs DSS additions. */
19762+ case FB_BLANK_VSYNC_SUSPEND:
19763+ case FB_BLANK_HSYNC_SUSPEND:
19764+ case FB_BLANK_POWERDOWN:
19765+ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
19766+ goto exit;
19767+
19768+ if (display->suspend)
19769+ r = display->suspend(display);
19770+
19771+ omapfb_vrfb_suspend_all(fbdev);
19772+
19773+ break;
19774+
19775+ default:
19776+ r = -EINVAL;
19777+ }
19778+
19779+exit:
19780+ omapfb_unlock(fbdev);
19781+
19782+ if (r == 0 && do_update && display->update) {
19783+ u16 w, h;
19784+ display->get_resolution(display, &w, &h);
19785+
19786+ r = display->update(display, 0, 0, w, h);
19787+ }
19788+
19789+ return r;
19790+}
19791+
19792+#if 0
19793+/* XXX fb_read and fb_write are needed for VRFB */
19794+ssize_t omapfb_write(struct fb_info *info, const char __user *buf,
19795+ size_t count, loff_t *ppos)
19796+{
19797+ DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos);
19798+ /* XXX needed for VRFB */
19799+ return count;
19800+}
19801+#endif
19802+
19803+static struct fb_ops omapfb_ops = {
19804+ .owner = THIS_MODULE,
19805+ .fb_open = omapfb_open,
19806+ .fb_release = omapfb_release,
19807+ .fb_fillrect = cfb_fillrect,
19808+ .fb_copyarea = cfb_copyarea,
19809+ .fb_imageblit = cfb_imageblit,
19810+ .fb_blank = omapfb_blank,
19811+ .fb_ioctl = omapfb_ioctl,
19812+ .fb_check_var = omapfb_check_var,
19813+ .fb_set_par = omapfb_set_par,
19814+ .fb_pan_display = omapfb_pan_display,
19815+ .fb_mmap = omapfb_mmap,
19816+ .fb_setcolreg = omapfb_setcolreg,
19817+ .fb_setcmap = omapfb_setcmap,
19818+ /*.fb_write = omapfb_write,*/
19819+};
19820+
19821+static void omapfb_free_fbmem(struct fb_info *fbi)
19822+{
19823+ struct omapfb_info *ofbi = FB2OFB(fbi);
19824+ struct omapfb2_device *fbdev = ofbi->fbdev;
19825+ struct omapfb2_mem_region *rg;
19826+
19827+ rg = &ofbi->region;
19828+
19829+ if (rg->paddr)
19830+ if (omap_vram_free(rg->paddr, rg->size))
19831+ dev_err(fbdev->dev, "VRAM FREE failed\n");
19832+
19833+ if (rg->vaddr)
19834+ iounmap(rg->vaddr);
19835+
19836+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
19837+ /* unmap the 0 angle rotation */
19838+ if (rg->vrfb.vaddr[0]) {
19839+ iounmap(rg->vrfb.vaddr[0]);
19840+ omap_vrfb_release_ctx(&rg->vrfb);
19841+ }
19842+ }
19843+
19844+ rg->vaddr = NULL;
19845+ rg->paddr = 0;
19846+ rg->alloc = 0;
19847+ rg->size = 0;
19848+}
19849+
19850+static void clear_fb_info(struct fb_info *fbi)
19851+{
19852+ memset(&fbi->var, 0, sizeof(fbi->var));
19853+ memset(&fbi->fix, 0, sizeof(fbi->fix));
19854+ strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
19855+}
19856+
19857+static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
19858+{
19859+ int i;
19860+
19861+ DBG("free all fbmem\n");
19862+
19863+ for (i = 0; i < fbdev->num_fbs; i++) {
19864+ struct fb_info *fbi = fbdev->fbs[i];
19865+ omapfb_free_fbmem(fbi);
19866+ clear_fb_info(fbi);
19867+ }
19868+
19869+ return 0;
19870+}
19871+
19872+static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
19873+ unsigned long paddr)
19874+{
19875+ struct omapfb_info *ofbi = FB2OFB(fbi);
19876+ struct omapfb2_device *fbdev = ofbi->fbdev;
19877+ struct omapfb2_mem_region *rg;
19878+ void __iomem *vaddr;
19879+ int r;
19880+
19881+ rg = &ofbi->region;
19882+ memset(rg, 0, sizeof(*rg));
19883+
19884+ size = PAGE_ALIGN(size);
19885+
19886+ if (!paddr) {
19887+ DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
19888+ r = omap_vram_alloc(OMAP_VRAM_MEMTYPE_SDRAM, size, &paddr);
19889+ } else {
19890+ DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
19891+ ofbi->id);
19892+ r = omap_vram_reserve(paddr, size);
19893+ }
19894+
19895+ if (r) {
19896+ dev_err(fbdev->dev, "failed to allocate framebuffer\n");
19897+ return -ENOMEM;
19898+ }
19899+
19900+ if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) {
19901+ vaddr = ioremap_wc(paddr, size);
19902+
19903+ if (!vaddr) {
19904+ dev_err(fbdev->dev, "failed to ioremap framebuffer\n");
19905+ omap_vram_free(paddr, size);
19906+ return -ENOMEM;
19907+ }
19908+
19909+ DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
19910+ } else {
19911+ void __iomem *va;
19912+
19913+ r = omap_vrfb_request_ctx(&rg->vrfb);
19914+ if (r) {
19915+ dev_err(fbdev->dev, "vrfb create ctx failed\n");
19916+ return r;
19917+ }
19918+
19919+ /* only ioremap the 0 angle view */
19920+ va = ioremap_wc(rg->vrfb.paddr[0], size);
19921+
19922+ if (!va) {
19923+ printk(KERN_ERR "vrfb: ioremap failed\n");
19924+ omap_vrfb_release_ctx(&rg->vrfb);
19925+ return -ENOMEM;
19926+ }
19927+
19928+ DBG("ioremapped vrfb area 0 to %p\n", va);
19929+
19930+ rg->vrfb.vaddr[0] = va;
19931+
19932+ vaddr = NULL;
19933+ }
19934+
19935+ rg->paddr = paddr;
19936+ rg->vaddr = vaddr;
19937+ rg->size = size;
19938+ rg->alloc = 1;
19939+
19940+ return 0;
19941+}
19942+
19943+/* allocate fbmem using display resolution as reference */
19944+static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
19945+ unsigned long paddr)
19946+{
19947+ struct omapfb_info *ofbi = FB2OFB(fbi);
19948+ struct omap_dss_device *display;
19949+ int bytespp;
19950+
19951+ display = fb2display(fbi);
19952+
19953+ if (!display)
19954+ return 0;
19955+
19956+ switch (display->get_recommended_bpp(display)) {
19957+ case 16:
19958+ bytespp = 2;
19959+ break;
19960+ case 24:
19961+ bytespp = 4;
19962+ break;
19963+ default:
19964+ bytespp = 4;
19965+ break;
19966+ }
19967+
19968+ if (!size) {
19969+ u16 w, h;
19970+
19971+ display->get_resolution(display, &w, &h);
19972+
19973+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
19974+#ifdef DEBUG
19975+ int oldw = w, oldh = h;
19976+#endif
19977+
19978+ omap_vrfb_adjust_size(&w, &h, bytespp);
19979+
19980+ /* Because we change the resolution of the 0 degree
19981+ * view, we need to alloc max(w, h) for height */
19982+ h = max(w, h);
19983+ w = OMAP_VRFB_LINE_LEN;
19984+
19985+ DBG("adjusting fb mem size for VRFB, %dx%d -> %dx%d\n",
19986+ oldw, oldh, w, h);
19987+ }
19988+
19989+ size = w * h * bytespp;
19990+ }
19991+
19992+ if (!size)
19993+ return 0;
19994+
19995+ return omapfb_alloc_fbmem(fbi, size, paddr);
19996+}
19997+
19998+static enum omap_color_mode fb_format_to_dss_mode(enum omapfb_color_format fmt)
19999+{
20000+ enum omap_color_mode mode;
20001+
20002+ switch (fmt) {
20003+ case OMAPFB_COLOR_RGB565:
20004+ mode = OMAP_DSS_COLOR_RGB16;
20005+ break;
20006+ case OMAPFB_COLOR_YUV422:
20007+ mode = OMAP_DSS_COLOR_YUV2;
20008+ break;
20009+ case OMAPFB_COLOR_CLUT_8BPP:
20010+ mode = OMAP_DSS_COLOR_CLUT8;
20011+ break;
20012+ case OMAPFB_COLOR_CLUT_4BPP:
20013+ mode = OMAP_DSS_COLOR_CLUT4;
20014+ break;
20015+ case OMAPFB_COLOR_CLUT_2BPP:
20016+ mode = OMAP_DSS_COLOR_CLUT2;
20017+ break;
20018+ case OMAPFB_COLOR_CLUT_1BPP:
20019+ mode = OMAP_DSS_COLOR_CLUT1;
20020+ break;
20021+ case OMAPFB_COLOR_RGB444:
20022+ mode = OMAP_DSS_COLOR_RGB12U;
20023+ break;
20024+ case OMAPFB_COLOR_YUY422:
20025+ mode = OMAP_DSS_COLOR_UYVY;
20026+ break;
20027+ case OMAPFB_COLOR_ARGB16:
20028+ mode = OMAP_DSS_COLOR_ARGB16;
20029+ break;
20030+ case OMAPFB_COLOR_RGB24U:
20031+ mode = OMAP_DSS_COLOR_RGB24U;
20032+ break;
20033+ case OMAPFB_COLOR_RGB24P:
20034+ mode = OMAP_DSS_COLOR_RGB24P;
20035+ break;
20036+ case OMAPFB_COLOR_ARGB32:
20037+ mode = OMAP_DSS_COLOR_ARGB32;
20038+ break;
20039+ case OMAPFB_COLOR_RGBA32:
20040+ mode = OMAP_DSS_COLOR_RGBA32;
20041+ break;
20042+ case OMAPFB_COLOR_RGBX32:
20043+ mode = OMAP_DSS_COLOR_RGBX32;
20044+ break;
20045+ default:
20046+ mode = -EINVAL;
20047+ }
20048+
20049+ return mode;
20050+}
20051+
20052+static int omapfb_parse_vram_param(const char *param, int max_entries,
20053+ unsigned long *sizes, unsigned long *paddrs)
20054+{
20055+ int fbnum;
20056+ unsigned long size;
20057+ unsigned long paddr = 0;
20058+ char *p, *start;
20059+
20060+ start = (char *)param;
20061+
20062+ while (1) {
20063+ p = start;
20064+
20065+ fbnum = simple_strtoul(p, &p, 10);
20066+
20067+ if (p == param)
20068+ return -EINVAL;
20069+
20070+ if (*p != ':')
20071+ return -EINVAL;
20072+
20073+ if (fbnum >= max_entries)
20074+ return -EINVAL;
20075+
20076+ size = memparse(p + 1, &p);
20077+
20078+ if (!size)
20079+ return -EINVAL;
20080+
20081+ paddr = 0;
20082+
20083+ if (*p == '@') {
20084+ paddr = simple_strtoul(p + 1, &p, 16);
20085+
20086+ if (!paddr)
20087+ return -EINVAL;
20088+
20089+ }
20090+
20091+ paddrs[fbnum] = paddr;
20092+ sizes[fbnum] = size;
20093+
20094+ if (*p == 0)
20095+ break;
20096+
20097+ if (*p != ',')
20098+ return -EINVAL;
20099+
20100+ ++p;
20101+
20102+ start = p;
20103+ }
20104+
20105+ return 0;
20106+}
20107+
20108+static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
20109+{
20110+ int i, r;
20111+ unsigned long vram_sizes[10];
20112+ unsigned long vram_paddrs[10];
20113+
20114+ memset(&vram_sizes, 0, sizeof(vram_sizes));
20115+ memset(&vram_paddrs, 0, sizeof(vram_paddrs));
20116+
20117+ if (def_vram && omapfb_parse_vram_param(def_vram, 10,
20118+ vram_sizes, vram_paddrs)) {
20119+ dev_err(fbdev->dev, "failed to parse vram parameter\n");
20120+
20121+ memset(&vram_sizes, 0, sizeof(vram_sizes));
20122+ memset(&vram_paddrs, 0, sizeof(vram_paddrs));
20123+ }
20124+
20125+ if (fbdev->dev->platform_data) {
20126+ struct omapfb_platform_data *opd;
20127+ opd = fbdev->dev->platform_data;
20128+ for (i = 0; i < opd->mem_desc.region_cnt; ++i) {
20129+ if (!vram_sizes[i]) {
20130+ unsigned long size;
20131+ unsigned long paddr;
20132+
20133+ size = opd->mem_desc.region[i].size;
20134+ paddr = opd->mem_desc.region[i].paddr;
20135+
20136+ vram_sizes[i] = size;
20137+ vram_paddrs[i] = paddr;
20138+ }
20139+ }
20140+ }
20141+
20142+ for (i = 0; i < fbdev->num_fbs; i++) {
20143+ /* allocate memory automatically only for fb0, or if
20144+ * excplicitly defined with vram or plat data option */
20145+ if (i == 0 || vram_sizes[i] != 0) {
20146+ r = omapfb_alloc_fbmem_display(fbdev->fbs[i],
20147+ vram_sizes[i], vram_paddrs[i]);
20148+
20149+ if (r)
20150+ return r;
20151+ }
20152+ }
20153+
20154+ for (i = 0; i < fbdev->num_fbs; i++) {
20155+ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
20156+ struct omapfb2_mem_region *rg;
20157+ rg = &ofbi->region;
20158+
20159+ DBG("region%d phys %08x virt %p size=%lu\n",
20160+ i,
20161+ rg->paddr,
20162+ rg->vaddr,
20163+ rg->size);
20164+ }
20165+
20166+ return 0;
20167+}
20168+
20169+int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
20170+{
20171+ struct omapfb_info *ofbi = FB2OFB(fbi);
20172+ struct omapfb2_device *fbdev = ofbi->fbdev;
20173+ struct omap_dss_device *display = fb2display(fbi);
20174+ struct omapfb2_mem_region *rg = &ofbi->region;
20175+ unsigned long old_size = rg->size;
20176+ unsigned long old_paddr = rg->paddr;
20177+ int old_type = rg->type;
20178+ int r;
20179+
20180+ if (type > OMAPFB_MEMTYPE_MAX)
20181+ return -EINVAL;
20182+
20183+ size = PAGE_ALIGN(size);
20184+
20185+ if (old_size == size && old_type == type)
20186+ return 0;
20187+
20188+ if (display && display->sync)
20189+ display->sync(display);
20190+
20191+ omapfb_free_fbmem(fbi);
20192+
20193+ if (size == 0) {
20194+ clear_fb_info(fbi);
20195+ return 0;
20196+ }
20197+
20198+ r = omapfb_alloc_fbmem(fbi, size, 0);
20199+
20200+ if (r) {
20201+ if (old_size)
20202+ omapfb_alloc_fbmem(fbi, old_size, old_paddr);
20203+
20204+ if (rg->size == 0)
20205+ clear_fb_info(fbi);
20206+
20207+ return r;
20208+ }
20209+
20210+ if (old_size == size)
20211+ return 0;
20212+
20213+ if (old_size == 0) {
20214+ DBG("initializing fb %d\n", ofbi->id);
20215+ r = omapfb_fb_init(fbdev, fbi);
20216+ if (r) {
20217+ DBG("omapfb_fb_init failed\n");
20218+ goto err;
20219+ }
20220+ r = omapfb_apply_changes(fbi, 1);
20221+ if (r) {
20222+ DBG("omapfb_apply_changes failed\n");
20223+ goto err;
20224+ }
20225+ } else {
20226+ struct fb_var_screeninfo new_var;
20227+ memcpy(&new_var, &fbi->var, sizeof(new_var));
20228+ r = check_fb_var(fbi, &new_var);
20229+ if (r)
20230+ goto err;
20231+ memcpy(&fbi->var, &new_var, sizeof(fbi->var));
20232+ set_fb_fix(fbi);
20233+ }
20234+
20235+ return 0;
20236+err:
20237+ omapfb_free_fbmem(fbi);
20238+ clear_fb_info(fbi);
20239+ return r;
20240+}
20241+
20242+/* initialize fb_info, var, fix to something sane based on the display */
20243+static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
20244+{
20245+ struct fb_var_screeninfo *var = &fbi->var;
20246+ struct omap_dss_device *display = fb2display(fbi);
20247+ struct omapfb_info *ofbi = FB2OFB(fbi);
20248+ int r = 0;
20249+
20250+ fbi->fbops = &omapfb_ops;
20251+ fbi->flags = FBINFO_FLAG_DEFAULT;
20252+ fbi->pseudo_palette = fbdev->pseudo_palette;
20253+
20254+ if (ofbi->region.size == 0) {
20255+ clear_fb_info(fbi);
20256+ return 0;
20257+ }
20258+
20259+ var->nonstd = 0;
20260+ var->bits_per_pixel = 0;
20261+
20262+ var->rotate = def_rotate;
20263+
20264+ /*
20265+ * Check if there is a default color format set in the board file,
20266+ * and use this format instead the default deducted from the
20267+ * display bpp.
20268+ */
20269+ if (fbdev->dev->platform_data) {
20270+ struct omapfb_platform_data *opd;
20271+ int id = ofbi->id;
20272+
20273+ opd = fbdev->dev->platform_data;
20274+ if (opd->mem_desc.region[id].format_used) {
20275+ enum omap_color_mode mode;
20276+ enum omapfb_color_format format;
20277+
20278+ format = opd->mem_desc.region[id].format;
20279+ mode = fb_format_to_dss_mode(format);
20280+ if (mode < 0) {
20281+ r = mode;
20282+ goto err;
20283+ }
20284+ r = dss_mode_to_fb_mode(mode, var);
20285+ if (r < 0)
20286+ goto err;
20287+ }
20288+ }
20289+
20290+ if (display) {
20291+ u16 w, h;
20292+ int rotation = (var->rotate + ofbi->rotation[0]) % 4;
20293+
20294+ display->get_resolution(display, &w, &h);
20295+
20296+ if (rotation == FB_ROTATE_CW ||
20297+ rotation == FB_ROTATE_CCW) {
20298+ var->xres = h;
20299+ var->yres = w;
20300+ } else {
20301+ var->xres = w;
20302+ var->yres = h;
20303+ }
20304+
20305+ var->xres_virtual = var->xres;
20306+ var->yres_virtual = var->yres;
20307+
20308+ if (!var->bits_per_pixel) {
20309+ switch (display->get_recommended_bpp(display)) {
20310+ case 16:
20311+ var->bits_per_pixel = 16;
20312+ break;
20313+ case 24:
20314+ var->bits_per_pixel = 32;
20315+ break;
20316+ default:
20317+ dev_err(fbdev->dev, "illegal display "
20318+ "bpp\n");
20319+ return -EINVAL;
20320+ }
20321+ }
20322+ } else {
20323+ /* if there's no display, let's just guess some basic values */
20324+ var->xres = 320;
20325+ var->yres = 240;
20326+ var->xres_virtual = var->xres;
20327+ var->yres_virtual = var->yres;
20328+ if (!var->bits_per_pixel)
20329+ var->bits_per_pixel = 16;
20330+ }
20331+
20332+ r = check_fb_var(fbi, var);
20333+ if (r)
20334+ goto err;
20335+
20336+ set_fb_fix(fbi);
20337+
20338+ r = fb_alloc_cmap(&fbi->cmap, 256, 0);
20339+ if (r)
20340+ dev_err(fbdev->dev, "unable to allocate color map memory\n");
20341+
20342+err:
20343+ return r;
20344+}
20345+
20346+static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi)
20347+{
20348+ fb_dealloc_cmap(&fbi->cmap);
20349+}
20350+
20351+
20352+static void omapfb_free_resources(struct omapfb2_device *fbdev)
20353+{
20354+ int i;
20355+
20356+ DBG("free_resources\n");
20357+
20358+ if (fbdev == NULL)
20359+ return;
20360+
20361+ for (i = 0; i < fbdev->num_fbs; i++)
20362+ unregister_framebuffer(fbdev->fbs[i]);
20363+
20364+ /* free the reserved fbmem */
20365+ omapfb_free_all_fbmem(fbdev);
20366+
20367+ for (i = 0; i < fbdev->num_fbs; i++) {
20368+ fbinfo_cleanup(fbdev, fbdev->fbs[i]);
20369+ framebuffer_release(fbdev->fbs[i]);
20370+ }
20371+
20372+ for (i = 0; i < fbdev->num_displays; i++) {
20373+ if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED)
20374+ fbdev->displays[i]->disable(fbdev->displays[i]);
20375+
20376+ omap_dss_put_device(fbdev->displays[i]);
20377+ }
20378+
20379+ dev_set_drvdata(fbdev->dev, NULL);
20380+ kfree(fbdev);
20381+}
20382+
20383+static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
20384+{
20385+ int r, i;
20386+
20387+ fbdev->num_fbs = 0;
20388+
20389+ DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS);
20390+
20391+ /* allocate fb_infos */
20392+ for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
20393+ struct fb_info *fbi;
20394+ struct omapfb_info *ofbi;
20395+
20396+ fbi = framebuffer_alloc(sizeof(struct omapfb_info),
20397+ fbdev->dev);
20398+
20399+ if (fbi == NULL) {
20400+ dev_err(fbdev->dev,
20401+ "unable to allocate memory for plane info\n");
20402+ return -ENOMEM;
20403+ }
20404+
20405+ clear_fb_info(fbi);
20406+
20407+ fbdev->fbs[i] = fbi;
20408+
20409+ ofbi = FB2OFB(fbi);
20410+ ofbi->fbdev = fbdev;
20411+ ofbi->id = i;
20412+
20413+ /* assign these early, so that fb alloc can use them */
20414+ ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
20415+ OMAP_DSS_ROT_DMA;
20416+ ofbi->mirror = def_mirror;
20417+
20418+ fbdev->num_fbs++;
20419+ }
20420+
20421+ DBG("fb_infos allocated\n");
20422+
20423+ /* assign overlays for the fbs */
20424+ for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
20425+ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
20426+
20427+ ofbi->overlays[0] = fbdev->overlays[i];
20428+ ofbi->num_overlays = 1;
20429+ }
20430+
20431+ /* allocate fb memories */
20432+ r = omapfb_allocate_all_fbs(fbdev);
20433+ if (r) {
20434+ dev_err(fbdev->dev, "failed to allocate fbmem\n");
20435+ return r;
20436+ }
20437+
20438+ DBG("fbmems allocated\n");
20439+
20440+ /* setup fb_infos */
20441+ for (i = 0; i < fbdev->num_fbs; i++) {
20442+ r = omapfb_fb_init(fbdev, fbdev->fbs[i]);
20443+ if (r) {
20444+ dev_err(fbdev->dev, "failed to setup fb_info\n");
20445+ return r;
20446+ }
20447+ }
20448+
20449+ DBG("fb_infos initialized\n");
20450+
20451+ for (i = 0; i < fbdev->num_fbs; i++) {
20452+ r = register_framebuffer(fbdev->fbs[i]);
20453+ if (r != 0) {
20454+ dev_err(fbdev->dev,
20455+ "registering framebuffer %d failed\n", i);
20456+ return r;
20457+ }
20458+ }
20459+
20460+ DBG("framebuffers registered\n");
20461+
20462+ for (i = 0; i < fbdev->num_fbs; i++) {
20463+ r = omapfb_apply_changes(fbdev->fbs[i], 1);
20464+ if (r) {
20465+ dev_err(fbdev->dev, "failed to change mode\n");
20466+ return r;
20467+ }
20468+ }
20469+
20470+ DBG("create sysfs for fbs\n");
20471+ r = omapfb_create_sysfs(fbdev);
20472+ if (r) {
20473+ dev_err(fbdev->dev, "failed to create sysfs entries\n");
20474+ return r;
20475+ }
20476+
20477+ /* Enable fb0 */
20478+ if (fbdev->num_fbs > 0) {
20479+ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
20480+
20481+ if (ofbi->num_overlays > 0) {
20482+ struct omap_overlay *ovl = ofbi->overlays[0];
20483+
20484+ r = omapfb_overlay_enable(ovl, 1);
20485+
20486+ if (r) {
20487+ dev_err(fbdev->dev,
20488+ "failed to enable overlay\n");
20489+ return r;
20490+ }
20491+ }
20492+ }
20493+
20494+ DBG("create_framebuffers done\n");
20495+
20496+ return 0;
20497+}
20498+
20499+static int omapfb_mode_to_timings(const char *mode_str,
20500+ struct omap_video_timings *timings, u8 *bpp)
20501+{
20502+ struct fb_info fbi;
20503+ struct fb_var_screeninfo var;
20504+ struct fb_ops fbops;
20505+ int r;
20506+
20507+#ifdef CONFIG_OMAP2_DSS_VENC
20508+ if (strcmp(mode_str, "pal") == 0) {
20509+ *timings = omap_dss_pal_timings;
20510+ *bpp = 0;
20511+ return 0;
20512+ } else if (strcmp(mode_str, "ntsc") == 0) {
20513+ *timings = omap_dss_ntsc_timings;
20514+ *bpp = 0;
20515+ return 0;
20516+ }
20517+#endif
20518+
20519+ /* this is quite a hack, but I wanted to use the modedb and for
20520+ * that we need fb_info and var, so we create dummy ones */
20521+
20522+ memset(&fbi, 0, sizeof(fbi));
20523+ memset(&var, 0, sizeof(var));
20524+ memset(&fbops, 0, sizeof(fbops));
20525+ fbi.fbops = &fbops;
20526+
20527+ r = fb_find_mode(&var, &fbi, mode_str, NULL, 0, NULL, 24);
20528+
20529+ if (r != 0) {
20530+ timings->pixel_clock = PICOS2KHZ(var.pixclock);
20531+ timings->hfp = var.left_margin;
20532+ timings->hbp = var.right_margin;
20533+ timings->vfp = var.upper_margin;
20534+ timings->vbp = var.lower_margin;
20535+ timings->hsw = var.hsync_len;
20536+ timings->vsw = var.vsync_len;
20537+ timings->x_res = var.xres;
20538+ timings->y_res = var.yres;
20539+
20540+ switch (var.bits_per_pixel) {
20541+ case 16:
20542+ *bpp = 16;
20543+ break;
20544+ case 24:
20545+ case 32:
20546+ default:
20547+ *bpp = 24;
20548+ break;
20549+ }
20550+
20551+ return 0;
20552+ } else {
20553+ return -EINVAL;
20554+ }
20555+}
20556+
20557+static int omapfb_set_def_mode(struct omap_dss_device *display, char *mode_str)
20558+{
20559+ int r;
20560+ u8 bpp;
20561+ struct omap_video_timings timings;
20562+
20563+ r = omapfb_mode_to_timings(mode_str, &timings, &bpp);
20564+ if (r)
20565+ return r;
20566+
20567+ display->panel.recommended_bpp = bpp;
20568+
20569+ if (!display->check_timings || !display->set_timings)
20570+ return -EINVAL;
20571+
20572+ r = display->check_timings(display, &timings);
20573+ if (r)
20574+ return r;
20575+
20576+ display->set_timings(display, &timings);
20577+
20578+ return 0;
20579+}
20580+
20581+static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
20582+{
20583+ char *str, *options, *this_opt;
20584+ int r = 0;
20585+
20586+ str = kmalloc(strlen(def_mode) + 1, GFP_KERNEL);
20587+ strcpy(str, def_mode);
20588+ options = str;
20589+
20590+ while (!r && (this_opt = strsep(&options, ",")) != NULL) {
20591+ char *p, *display_str, *mode_str;
20592+ struct omap_dss_device *display;
20593+ int i;
20594+
20595+ p = strchr(this_opt, ':');
20596+ if (!p) {
20597+ r = -EINVAL;
20598+ break;
20599+ }
20600+
20601+ *p = 0;
20602+ display_str = this_opt;
20603+ mode_str = p + 1;
20604+
20605+ display = NULL;
20606+ for (i = 0; i < fbdev->num_displays; ++i) {
20607+ if (strcmp(fbdev->displays[i]->name,
20608+ display_str) == 0) {
20609+ display = fbdev->displays[i];
20610+ break;
20611+ }
20612+ }
20613+
20614+ if (!display) {
20615+ r = -EINVAL;
20616+ break;
20617+ }
20618+
20619+ r = omapfb_set_def_mode(display, mode_str);
20620+ if (r)
20621+ break;
20622+ }
20623+
20624+ kfree(str);
20625+
20626+ return r;
20627+}
20628+
20629+static int omapfb_probe(struct platform_device *pdev)
20630+{
20631+ struct omapfb2_device *fbdev = NULL;
20632+ int r = 0;
20633+ int i;
20634+ struct omap_overlay *ovl;
20635+ struct omap_dss_device *def_display;
20636+ struct omap_dss_device *dssdev;
20637+
20638+ DBG("omapfb_probe\n");
20639+
20640+ if (pdev->num_resources != 0) {
20641+ dev_err(&pdev->dev, "probed for an unknown device\n");
20642+ r = -ENODEV;
20643+ goto err0;
20644+ }
20645+
20646+ fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL);
20647+ if (fbdev == NULL) {
20648+ r = -ENOMEM;
20649+ goto err0;
20650+ }
20651+
20652+ mutex_init(&fbdev->mtx);
20653+
20654+ fbdev->dev = &pdev->dev;
20655+ platform_set_drvdata(pdev, fbdev);
20656+
20657+ fbdev->num_displays = 0;
20658+ dssdev = NULL;
20659+ for_each_dss_dev(dssdev) {
20660+ omap_dss_get_device(dssdev);
20661+ fbdev->displays[fbdev->num_displays++] = dssdev;
20662+ }
20663+
20664+ if (fbdev->num_displays == 0) {
20665+ dev_err(&pdev->dev, "no displays\n");
20666+ r = -EINVAL;
20667+ goto cleanup;
20668+ }
20669+
20670+ fbdev->num_overlays = omap_dss_get_num_overlays();
20671+ for (i = 0; i < fbdev->num_overlays; i++)
20672+ fbdev->overlays[i] = omap_dss_get_overlay(i);
20673+
20674+ fbdev->num_managers = omap_dss_get_num_overlay_managers();
20675+ for (i = 0; i < fbdev->num_managers; i++)
20676+ fbdev->managers[i] = omap_dss_get_overlay_manager(i);
20677+
20678+ if (def_mode && strlen(def_mode) > 0) {
20679+ if (omapfb_parse_def_modes(fbdev))
20680+ dev_warn(&pdev->dev, "cannot parse default modes\n");
20681+ }
20682+
20683+ r = omapfb_create_framebuffers(fbdev);
20684+ if (r)
20685+ goto cleanup;
20686+
20687+ for (i = 0; i < fbdev->num_managers; i++) {
20688+ struct omap_overlay_manager *mgr;
20689+ mgr = fbdev->managers[i];
20690+ r = mgr->apply(mgr);
20691+ if (r)
20692+ dev_warn(fbdev->dev, "failed to apply dispc config\n");
20693+ }
20694+
20695+ DBG("mgr->apply'ed\n");
20696+
20697+ /* gfx overlay should be the default one. find a display
20698+ * connected to that, and use it as default display */
20699+ ovl = omap_dss_get_overlay(0);
20700+ if (ovl->manager && ovl->manager->device) {
20701+ def_display = ovl->manager->device;
20702+ } else {
20703+ dev_warn(&pdev->dev, "cannot find default display\n");
20704+ def_display = NULL;
20705+ }
20706+
20707+ if (def_display) {
20708+ u16 w, h;
20709+ r = def_display->enable(def_display);
20710+ if (r)
20711+ dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
20712+ def_display->name);
20713+
20714+ /* set the update mode */
20715+ if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
20716+#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE
20717+ if (def_display->enable_te)
20718+ def_display->enable_te(def_display, 1);
20719+ if (def_display->set_update_mode)
20720+ def_display->set_update_mode(def_display,
20721+ OMAP_DSS_UPDATE_AUTO);
20722+#else /* MANUAL_UPDATE */
20723+ if (def_display->enable_te)
20724+ def_display->enable_te(def_display, 0);
20725+ if (def_display->set_update_mode)
20726+ def_display->set_update_mode(def_display,
20727+ OMAP_DSS_UPDATE_MANUAL);
20728+
20729+ def_display->get_resolution(def_display, &w, &h);
20730+ def_display->update(def_display, 0, 0, w, h);
20731+#endif
20732+ } else {
20733+ if (def_display->set_update_mode)
20734+ def_display->set_update_mode(def_display,
20735+ OMAP_DSS_UPDATE_AUTO);
20736+ }
20737+ }
20738+
20739+ return 0;
20740+
20741+cleanup:
20742+ omapfb_free_resources(fbdev);
20743+err0:
20744+ dev_err(&pdev->dev, "failed to setup omapfb\n");
20745+ return r;
20746+}
20747+
20748+static int omapfb_remove(struct platform_device *pdev)
20749+{
20750+ struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
20751+
20752+ /* FIXME: wait till completion of pending events */
20753+
20754+ omapfb_remove_sysfs(fbdev);
20755+
20756+ omapfb_free_resources(fbdev);
20757+
20758+ return 0;
20759+}
20760+
20761+static struct platform_driver omapfb_driver = {
20762+ .probe = omapfb_probe,
20763+ .remove = omapfb_remove,
20764+ .driver = {
20765+ .name = "omapfb",
20766+ .owner = THIS_MODULE,
20767+ },
20768+};
20769+
20770+static int __init omapfb_init(void)
20771+{
20772+ DBG("omapfb_init\n");
20773+
20774+ if (platform_driver_register(&omapfb_driver)) {
20775+ printk(KERN_ERR "failed to register omapfb driver\n");
20776+ return -ENODEV;
20777+ }
20778+
20779+ return 0;
20780+}
20781+
20782+static void __exit omapfb_exit(void)
20783+{
20784+ DBG("omapfb_exit\n");
20785+ platform_driver_unregister(&omapfb_driver);
20786+}
20787+
20788+module_param_named(mode, def_mode, charp, 0);
20789+module_param_named(vram, def_vram, charp, 0);
20790+module_param_named(rotate, def_rotate, int, 0);
20791+module_param_named(vrfb, def_vrfb, bool, 0);
20792+module_param_named(mirror, def_mirror, bool, 0);
20793+
20794+/* late_initcall to let panel/ctrl drivers loaded first.
20795+ * I guess better option would be a more dynamic approach,
20796+ * so that omapfb reacts to new panels when they are loaded */
20797+late_initcall(omapfb_init);
20798+/*module_init(omapfb_init);*/
20799+module_exit(omapfb_exit);
20800+
20801+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
20802+MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
20803+MODULE_LICENSE("GPL v2");
20804--- /dev/null
20805+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
20806@@ -0,0 +1,507 @@
20807+/*
20808+ * linux/drivers/video/omap2/omapfb-sysfs.c
20809+ *
20810+ * Copyright (C) 2008 Nokia Corporation
20811+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
20812+ *
20813+ * Some code and ideas taken from drivers/video/omap/ driver
20814+ * by Imre Deak.
20815+ *
20816+ * This program is free software; you can redistribute it and/or modify it
20817+ * under the terms of the GNU General Public License version 2 as published by
20818+ * the Free Software Foundation.
20819+ *
20820+ * This program is distributed in the hope that it will be useful, but WITHOUT
20821+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20822+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
20823+ * more details.
20824+ *
20825+ * You should have received a copy of the GNU General Public License along with
20826+ * this program. If not, see <http://www.gnu.org/licenses/>.
20827+ */
20828+
20829+#include <linux/fb.h>
20830+#include <linux/sysfs.h>
20831+#include <linux/device.h>
20832+#include <linux/uaccess.h>
20833+#include <linux/platform_device.h>
20834+#include <linux/kernel.h>
20835+#include <linux/mm.h>
20836+#include <linux/omapfb.h>
20837+
20838+#include <mach/display.h>
20839+#include <mach/vrfb.h>
20840+
20841+#include "omapfb.h"
20842+
20843+static ssize_t show_rotate_type(struct device *dev,
20844+ struct device_attribute *attr, char *buf)
20845+{
20846+ struct fb_info *fbi = dev_get_drvdata(dev);
20847+ struct omapfb_info *ofbi = FB2OFB(fbi);
20848+
20849+ return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->rotation_type);
20850+}
20851+
20852+static ssize_t store_rotate_type(struct device *dev,
20853+ struct device_attribute *attr,
20854+ const char *buf, size_t count)
20855+{
20856+ struct fb_info *fbi = dev_get_drvdata(dev);
20857+ struct omapfb_info *ofbi = FB2OFB(fbi);
20858+ enum omap_dss_rotation_type rot_type;
20859+ int r;
20860+
20861+ rot_type = simple_strtoul(buf, NULL, 0);
20862+
20863+ if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB)
20864+ return -EINVAL;
20865+
20866+ lock_fb_info(fbi);
20867+
20868+ r = 0;
20869+ if (rot_type == ofbi->rotation_type)
20870+ goto out;
20871+
20872+ if (ofbi->region.size) {
20873+ r = -EBUSY;
20874+ goto out;
20875+ }
20876+
20877+ ofbi->rotation_type = rot_type;
20878+
20879+ /*
20880+ * Since the VRAM for this FB is not allocated at the moment we don't
20881+ * need to do any further parameter checking at this point.
20882+ */
20883+out:
20884+ unlock_fb_info(fbi);
20885+
20886+ return r ? r : count;
20887+}
20888+
20889+
20890+static ssize_t show_mirror(struct device *dev,
20891+ struct device_attribute *attr, char *buf)
20892+{
20893+ struct fb_info *fbi = dev_get_drvdata(dev);
20894+ struct omapfb_info *ofbi = FB2OFB(fbi);
20895+
20896+ return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->mirror);
20897+}
20898+
20899+static ssize_t store_mirror(struct device *dev,
20900+ struct device_attribute *attr,
20901+ const char *buf, size_t count)
20902+{
20903+ struct fb_info *fbi = dev_get_drvdata(dev);
20904+ struct omapfb_info *ofbi = FB2OFB(fbi);
20905+ bool mirror;
20906+ int r;
20907+ struct fb_var_screeninfo new_var;
20908+
20909+ mirror = simple_strtoul(buf, NULL, 0);
20910+
20911+ if (mirror != 0 && mirror != 1)
20912+ return -EINVAL;
20913+
20914+ lock_fb_info(fbi);
20915+
20916+ ofbi->mirror = mirror;
20917+
20918+ memcpy(&new_var, &fbi->var, sizeof(new_var));
20919+ r = check_fb_var(fbi, &new_var);
20920+ if (r)
20921+ goto out;
20922+ memcpy(&fbi->var, &new_var, sizeof(fbi->var));
20923+
20924+ set_fb_fix(fbi);
20925+
20926+ r = omapfb_apply_changes(fbi, 0);
20927+ if (r)
20928+ goto out;
20929+
20930+ r = count;
20931+out:
20932+ unlock_fb_info(fbi);
20933+
20934+ return r;
20935+}
20936+
20937+static ssize_t show_overlays(struct device *dev,
20938+ struct device_attribute *attr, char *buf)
20939+{
20940+ struct fb_info *fbi = dev_get_drvdata(dev);
20941+ struct omapfb_info *ofbi = FB2OFB(fbi);
20942+ struct omapfb2_device *fbdev = ofbi->fbdev;
20943+ ssize_t l = 0;
20944+ int t;
20945+
20946+ omapfb_lock(fbdev);
20947+ lock_fb_info(fbi);
20948+
20949+ for (t = 0; t < ofbi->num_overlays; t++) {
20950+ struct omap_overlay *ovl = ofbi->overlays[t];
20951+ int ovlnum;
20952+
20953+ for (ovlnum = 0; ovlnum < fbdev->num_overlays; ++ovlnum)
20954+ if (ovl == fbdev->overlays[ovlnum])
20955+ break;
20956+
20957+ l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
20958+ t == 0 ? "" : ",", ovlnum);
20959+ }
20960+
20961+ l += snprintf(buf + l, PAGE_SIZE - l, "\n");
20962+
20963+ unlock_fb_info(fbi);
20964+ omapfb_unlock(fbdev);
20965+
20966+ return l;
20967+}
20968+
20969+static struct omapfb_info *get_overlay_fb(struct omapfb2_device *fbdev,
20970+ struct omap_overlay *ovl)
20971+{
20972+ int i, t;
20973+
20974+ for (i = 0; i < fbdev->num_fbs; i++) {
20975+ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
20976+
20977+ for (t = 0; t < ofbi->num_overlays; t++) {
20978+ if (ofbi->overlays[t] == ovl)
20979+ return ofbi;
20980+ }
20981+ }
20982+
20983+ return NULL;
20984+}
20985+
20986+static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
20987+ const char *buf, size_t count)
20988+{
20989+ struct fb_info *fbi = dev_get_drvdata(dev);
20990+ struct omapfb_info *ofbi = FB2OFB(fbi);
20991+ struct omapfb2_device *fbdev = ofbi->fbdev;
20992+ struct omap_overlay *ovls[OMAPFB_MAX_OVL_PER_FB];
20993+ struct omap_overlay *ovl;
20994+ int num_ovls, r, i;
20995+ int len;
20996+ bool added = false;
20997+
20998+ num_ovls = 0;
20999+
21000+ len = strlen(buf);
21001+ if (buf[len - 1] == '\n')
21002+ len = len - 1;
21003+
21004+ omapfb_lock(fbdev);
21005+ lock_fb_info(fbi);
21006+
21007+ if (len > 0) {
21008+ char *p = (char *)buf;
21009+ int ovlnum;
21010+
21011+ while (p < buf + len) {
21012+ int found;
21013+ if (num_ovls == OMAPFB_MAX_OVL_PER_FB) {
21014+ r = -EINVAL;
21015+ goto out;
21016+ }
21017+
21018+ ovlnum = simple_strtoul(p, &p, 0);
21019+ if (ovlnum > fbdev->num_overlays) {
21020+ r = -EINVAL;
21021+ goto out;
21022+ }
21023+
21024+ found = 0;
21025+ for (i = 0; i < num_ovls; ++i) {
21026+ if (ovls[i] == fbdev->overlays[ovlnum]) {
21027+ found = 1;
21028+ break;
21029+ }
21030+ }
21031+
21032+ if (!found)
21033+ ovls[num_ovls++] = fbdev->overlays[ovlnum];
21034+
21035+ p++;
21036+ }
21037+ }
21038+
21039+ for (i = 0; i < num_ovls; ++i) {
21040+ struct omapfb_info *ofbi2 = get_overlay_fb(fbdev, ovls[i]);
21041+ if (ofbi2 && ofbi2 != ofbi) {
21042+ dev_err(fbdev->dev, "overlay already in use\n");
21043+ r = -EINVAL;
21044+ goto out;
21045+ }
21046+ }
21047+
21048+ /* detach unused overlays */
21049+ for (i = 0; i < ofbi->num_overlays; ++i) {
21050+ int t, found;
21051+
21052+ ovl = ofbi->overlays[i];
21053+
21054+ found = 0;
21055+
21056+ for (t = 0; t < num_ovls; ++t) {
21057+ if (ovl == ovls[t]) {
21058+ found = 1;
21059+ break;
21060+ }
21061+ }
21062+
21063+ if (found)
21064+ continue;
21065+
21066+ DBG("detaching %d\n", ofbi->overlays[i]->id);
21067+
21068+ omapfb_overlay_enable(ovl, 0);
21069+
21070+ if (ovl->manager)
21071+ ovl->manager->apply(ovl->manager);
21072+
21073+ for (t = i + 1; t < ofbi->num_overlays; t++) {
21074+ ofbi->rotation[t-1] = ofbi->rotation[t];
21075+ ofbi->overlays[t-1] = ofbi->overlays[t];
21076+ }
21077+
21078+ ofbi->num_overlays--;
21079+ i--;
21080+ }
21081+
21082+ for (i = 0; i < num_ovls; ++i) {
21083+ int t, found;
21084+
21085+ ovl = ovls[i];
21086+
21087+ found = 0;
21088+
21089+ for (t = 0; t < ofbi->num_overlays; ++t) {
21090+ if (ovl == ofbi->overlays[t]) {
21091+ found = 1;
21092+ break;
21093+ }
21094+ }
21095+
21096+ if (found)
21097+ continue;
21098+ ofbi->rotation[ofbi->num_overlays] = 0;
21099+ ofbi->overlays[ofbi->num_overlays++] = ovl;
21100+
21101+ added = true;
21102+ }
21103+
21104+ if (added) {
21105+ r = omapfb_apply_changes(fbi, 0);
21106+ if (r)
21107+ goto out;
21108+ }
21109+
21110+ r = count;
21111+out:
21112+ unlock_fb_info(fbi);
21113+ omapfb_unlock(fbdev);
21114+
21115+ return r;
21116+}
21117+
21118+static ssize_t show_overlays_rotate(struct device *dev,
21119+ struct device_attribute *attr, char *buf)
21120+{
21121+ struct fb_info *fbi = dev_get_drvdata(dev);
21122+ struct omapfb_info *ofbi = FB2OFB(fbi);
21123+ ssize_t l = 0;
21124+ int t;
21125+
21126+ lock_fb_info(fbi);
21127+
21128+ for (t = 0; t < ofbi->num_overlays; t++) {
21129+ l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
21130+ t == 0 ? "" : ",", ofbi->rotation[t]);
21131+ }
21132+
21133+ l += snprintf(buf + l, PAGE_SIZE - l, "\n");
21134+
21135+ unlock_fb_info(fbi);
21136+
21137+ return l;
21138+}
21139+
21140+static ssize_t store_overlays_rotate(struct device *dev,
21141+ struct device_attribute *attr, const char *buf, size_t count)
21142+{
21143+ struct fb_info *fbi = dev_get_drvdata(dev);
21144+ struct omapfb_info *ofbi = FB2OFB(fbi);
21145+ int num_ovls = 0, r, i;
21146+ int len;
21147+ bool changed = false;
21148+ u8 rotation[OMAPFB_MAX_OVL_PER_FB];
21149+
21150+ len = strlen(buf);
21151+ if (buf[len - 1] == '\n')
21152+ len = len - 1;
21153+
21154+ lock_fb_info(fbi);
21155+
21156+ if (len > 0) {
21157+ char *p = (char *)buf;
21158+
21159+ while (p < buf + len) {
21160+ int rot;
21161+
21162+ if (num_ovls == ofbi->num_overlays) {
21163+ r = -EINVAL;
21164+ goto out;
21165+ }
21166+
21167+ rot = simple_strtoul(p, &p, 0);
21168+ if (rot < 0 || rot > 3) {
21169+ r = -EINVAL;
21170+ goto out;
21171+ }
21172+
21173+ if (ofbi->rotation[num_ovls] != rot)
21174+ changed = true;
21175+
21176+ rotation[num_ovls++] = rot;
21177+
21178+ p++;
21179+ }
21180+ }
21181+
21182+ if (num_ovls != ofbi->num_overlays) {
21183+ r = -EINVAL;
21184+ goto out;
21185+ }
21186+
21187+ if (changed) {
21188+ for (i = 0; i < num_ovls; ++i)
21189+ ofbi->rotation[i] = rotation[i];
21190+
21191+ r = omapfb_apply_changes(fbi, 0);
21192+ if (r)
21193+ goto out;
21194+
21195+ /* FIXME error handling? */
21196+ }
21197+
21198+ r = count;
21199+out:
21200+ unlock_fb_info(fbi);
21201+
21202+ return r;
21203+}
21204+
21205+static ssize_t show_size(struct device *dev,
21206+ struct device_attribute *attr, char *buf)
21207+{
21208+ struct fb_info *fbi = dev_get_drvdata(dev);
21209+ struct omapfb_info *ofbi = FB2OFB(fbi);
21210+
21211+ return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region.size);
21212+}
21213+
21214+static ssize_t store_size(struct device *dev, struct device_attribute *attr,
21215+ const char *buf, size_t count)
21216+{
21217+ struct fb_info *fbi = dev_get_drvdata(dev);
21218+ struct omapfb_info *ofbi = FB2OFB(fbi);
21219+ unsigned long size;
21220+ int r;
21221+ int i;
21222+
21223+ size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0));
21224+
21225+ lock_fb_info(fbi);
21226+
21227+ for (i = 0; i < ofbi->num_overlays; i++) {
21228+ if (ofbi->overlays[i]->info.enabled) {
21229+ r = -EBUSY;
21230+ goto out;
21231+ }
21232+ }
21233+
21234+ if (size != ofbi->region.size) {
21235+ r = omapfb_realloc_fbmem(fbi, size, ofbi->region.type);
21236+ if (r) {
21237+ dev_err(dev, "realloc fbmem failed\n");
21238+ goto out;
21239+ }
21240+ }
21241+
21242+ r = count;
21243+out:
21244+ unlock_fb_info(fbi);
21245+
21246+ return r;
21247+}
21248+
21249+static ssize_t show_phys(struct device *dev,
21250+ struct device_attribute *attr, char *buf)
21251+{
21252+ struct fb_info *fbi = dev_get_drvdata(dev);
21253+ struct omapfb_info *ofbi = FB2OFB(fbi);
21254+
21255+ return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region.paddr);
21256+}
21257+
21258+static ssize_t show_virt(struct device *dev,
21259+ struct device_attribute *attr, char *buf)
21260+{
21261+ struct fb_info *fbi = dev_get_drvdata(dev);
21262+ struct omapfb_info *ofbi = FB2OFB(fbi);
21263+
21264+ return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr);
21265+}
21266+
21267+static struct device_attribute omapfb_attrs[] = {
21268+ __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type,
21269+ store_rotate_type),
21270+ __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror),
21271+ __ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size),
21272+ __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
21273+ __ATTR(overlays_rotate, S_IRUGO | S_IWUSR, show_overlays_rotate,
21274+ store_overlays_rotate),
21275+ __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
21276+ __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
21277+};
21278+
21279+int omapfb_create_sysfs(struct omapfb2_device *fbdev)
21280+{
21281+ int i;
21282+ int r;
21283+
21284+ DBG("create sysfs for fbs\n");
21285+ for (i = 0; i < fbdev->num_fbs; i++) {
21286+ int t;
21287+ for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) {
21288+ r = device_create_file(fbdev->fbs[i]->dev,
21289+ &omapfb_attrs[t]);
21290+
21291+ if (r) {
21292+ dev_err(fbdev->dev, "failed to create sysfs "
21293+ "file\n");
21294+ return r;
21295+ }
21296+ }
21297+ }
21298+
21299+ return 0;
21300+}
21301+
21302+void omapfb_remove_sysfs(struct omapfb2_device *fbdev)
21303+{
21304+ int i, t;
21305+
21306+ DBG("remove sysfs for fbs\n");
21307+ for (i = 0; i < fbdev->num_fbs; i++) {
21308+ for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++)
21309+ device_remove_file(fbdev->fbs[i]->dev,
21310+ &omapfb_attrs[t]);
21311+ }
21312+}
21313+
21314--- /dev/null
21315+++ b/drivers/video/omap2/omapfb/omapfb.h
21316@@ -0,0 +1,146 @@
21317+/*
21318+ * linux/drivers/video/omap2/omapfb.h
21319+ *
21320+ * Copyright (C) 2008 Nokia Corporation
21321+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
21322+ *
21323+ * Some code and ideas taken from drivers/video/omap/ driver
21324+ * by Imre Deak.
21325+ *
21326+ * This program is free software; you can redistribute it and/or modify it
21327+ * under the terms of the GNU General Public License version 2 as published by
21328+ * the Free Software Foundation.
21329+ *
21330+ * This program is distributed in the hope that it will be useful, but WITHOUT
21331+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21332+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
21333+ * more details.
21334+ *
21335+ * You should have received a copy of the GNU General Public License along with
21336+ * this program. If not, see <http://www.gnu.org/licenses/>.
21337+ */
21338+
21339+#ifndef __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
21340+#define __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
21341+
21342+#ifdef CONFIG_FB_OMAP2_DEBUG_SUPPORT
21343+#define DEBUG
21344+#endif
21345+
21346+#include <mach/display.h>
21347+
21348+#ifdef DEBUG
21349+extern unsigned int omapfb_debug;
21350+#define DBG(format, ...) \
21351+ if (omapfb_debug) \
21352+ printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__)
21353+#else
21354+#define DBG(format, ...)
21355+#endif
21356+
21357+#define FB2OFB(fb_info) ((struct omapfb_info *)(fb_info->par))
21358+
21359+/* max number of overlays to which a framebuffer data can be direct */
21360+#define OMAPFB_MAX_OVL_PER_FB 3
21361+
21362+struct omapfb2_mem_region {
21363+ u32 paddr;
21364+ void __iomem *vaddr;
21365+ struct vrfb vrfb;
21366+ unsigned long size;
21367+ u8 type; /* OMAPFB_PLANE_MEM_* */
21368+ bool alloc; /* allocated by the driver */
21369+ bool map; /* kernel mapped by the driver */
21370+};
21371+
21372+/* appended to fb_info */
21373+struct omapfb_info {
21374+ int id;
21375+ struct omapfb2_mem_region region;
21376+ atomic_t map_count;
21377+ int num_overlays;
21378+ struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
21379+ struct omapfb2_device *fbdev;
21380+ enum omap_dss_rotation_type rotation_type;
21381+ u8 rotation[OMAPFB_MAX_OVL_PER_FB];
21382+ bool mirror;
21383+};
21384+
21385+struct omapfb2_device {
21386+ struct device *dev;
21387+ struct mutex mtx;
21388+
21389+ u32 pseudo_palette[17];
21390+
21391+ int state;
21392+
21393+ unsigned num_fbs;
21394+ struct fb_info *fbs[10];
21395+
21396+ unsigned num_displays;
21397+ struct omap_dss_device *displays[10];
21398+ unsigned num_overlays;
21399+ struct omap_overlay *overlays[10];
21400+ unsigned num_managers;
21401+ struct omap_overlay_manager *managers[10];
21402+};
21403+
21404+struct omapfb_colormode {
21405+ enum omap_color_mode dssmode;
21406+ u32 bits_per_pixel;
21407+ u32 nonstd;
21408+ struct fb_bitfield red;
21409+ struct fb_bitfield green;
21410+ struct fb_bitfield blue;
21411+ struct fb_bitfield transp;
21412+};
21413+
21414+void set_fb_fix(struct fb_info *fbi);
21415+int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var);
21416+int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type);
21417+int omapfb_apply_changes(struct fb_info *fbi, int init);
21418+
21419+int omapfb_create_sysfs(struct omapfb2_device *fbdev);
21420+void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
21421+
21422+int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
21423+
21424+int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
21425+ struct fb_var_screeninfo *var);
21426+
21427+/* find the display connected to this fb, if any */
21428+static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
21429+{
21430+ struct omapfb_info *ofbi = FB2OFB(fbi);
21431+ int i;
21432+
21433+ /* XXX: returns the display connected to first attached overlay */
21434+ for (i = 0; i < ofbi->num_overlays; i++) {
21435+ if (ofbi->overlays[i]->manager)
21436+ return ofbi->overlays[i]->manager->device;
21437+ }
21438+
21439+ return NULL;
21440+}
21441+
21442+static inline void omapfb_lock(struct omapfb2_device *fbdev)
21443+{
21444+ mutex_lock(&fbdev->mtx);
21445+}
21446+
21447+static inline void omapfb_unlock(struct omapfb2_device *fbdev)
21448+{
21449+ mutex_unlock(&fbdev->mtx);
21450+}
21451+
21452+static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
21453+ int enable)
21454+{
21455+ struct omap_overlay_info info;
21456+
21457+ ovl->get_overlay_info(ovl, &info);
21458+ info.enabled = enable;
21459+ return ovl->set_overlay_info(ovl, &info);
21460+}
21461+
21462+#endif
21463--- /dev/null
21464+++ b/drivers/video/omap2/vram.c
21465@@ -0,0 +1,655 @@
21466+/*
21467+ * VRAM manager for OMAP
21468+ *
21469+ * Copyright (C) 2009 Nokia Corporation
21470+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
21471+ *
21472+ * This program is free software; you can redistribute it and/or modify
21473+ * it under the terms of the GNU General Public License version 2 as
21474+ * published by the Free Software Foundation.
21475+ *
21476+ * This program is distributed in the hope that it will be useful, but
21477+ * WITHOUT ANY WARRANTY; without even the implied warranty of
21478+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21479+ * General Public License for more details.
21480+ *
21481+ * You should have received a copy of the GNU General Public License along
21482+ * with this program; if not, write to the Free Software Foundation, Inc.,
21483+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21484+ */
21485+
21486+/*#define DEBUG*/
21487+
21488+#include <linux/kernel.h>
21489+#include <linux/mm.h>
21490+#include <linux/list.h>
21491+#include <linux/seq_file.h>
21492+#include <linux/bootmem.h>
21493+#include <linux/completion.h>
21494+#include <linux/debugfs.h>
21495+#include <linux/jiffies.h>
21496+#include <linux/module.h>
21497+
21498+#include <asm/setup.h>
21499+
21500+#include <mach/sram.h>
21501+#include <mach/vram.h>
21502+#include <mach/dma.h>
21503+
21504+#ifdef DEBUG
21505+#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__)
21506+#else
21507+#define DBG(format, ...)
21508+#endif
21509+
21510+#define OMAP2_SRAM_START 0x40200000
21511+/* Maximum size, in reality this is smaller if SRAM is partially locked. */
21512+#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */
21513+
21514+/* postponed regions are used to temporarily store region information at boot
21515+ * time when we cannot yet allocate the region list */
21516+#define MAX_POSTPONED_REGIONS 10
21517+
21518+static bool vram_initialized;
21519+static int postponed_cnt;
21520+static struct {
21521+ unsigned long paddr;
21522+ size_t size;
21523+} postponed_regions[MAX_POSTPONED_REGIONS];
21524+
21525+struct vram_alloc {
21526+ struct list_head list;
21527+ unsigned long paddr;
21528+ unsigned pages;
21529+};
21530+
21531+struct vram_region {
21532+ struct list_head list;
21533+ struct list_head alloc_list;
21534+ unsigned long paddr;
21535+ unsigned pages;
21536+};
21537+
21538+static DEFINE_MUTEX(region_mutex);
21539+static LIST_HEAD(region_list);
21540+
21541+static inline int region_mem_type(unsigned long paddr)
21542+{
21543+ if (paddr >= OMAP2_SRAM_START &&
21544+ paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
21545+ return OMAP_VRAM_MEMTYPE_SRAM;
21546+ else
21547+ return OMAP_VRAM_MEMTYPE_SDRAM;
21548+}
21549+
21550+static struct vram_region *omap_vram_create_region(unsigned long paddr,
21551+ unsigned pages)
21552+{
21553+ struct vram_region *rm;
21554+
21555+ rm = kzalloc(sizeof(*rm), GFP_KERNEL);
21556+
21557+ if (rm) {
21558+ INIT_LIST_HEAD(&rm->alloc_list);
21559+ rm->paddr = paddr;
21560+ rm->pages = pages;
21561+ }
21562+
21563+ return rm;
21564+}
21565+
21566+#if 0
21567+static void omap_vram_free_region(struct vram_region *vr)
21568+{
21569+ list_del(&vr->list);
21570+ kfree(vr);
21571+}
21572+#endif
21573+
21574+static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr,
21575+ unsigned long paddr, unsigned pages)
21576+{
21577+ struct vram_alloc *va;
21578+ struct vram_alloc *new;
21579+
21580+ new = kzalloc(sizeof(*va), GFP_KERNEL);
21581+
21582+ if (!new)
21583+ return NULL;
21584+
21585+ new->paddr = paddr;
21586+ new->pages = pages;
21587+
21588+ list_for_each_entry(va, &vr->alloc_list, list) {
21589+ if (va->paddr > new->paddr)
21590+ break;
21591+ }
21592+
21593+ list_add_tail(&new->list, &va->list);
21594+
21595+ return new;
21596+}
21597+
21598+static void omap_vram_free_allocation(struct vram_alloc *va)
21599+{
21600+ list_del(&va->list);
21601+ kfree(va);
21602+}
21603+
21604+int omap_vram_add_region(unsigned long paddr, size_t size)
21605+{
21606+ struct vram_region *rm;
21607+ unsigned pages;
21608+
21609+ if (vram_initialized) {
21610+ DBG("adding region paddr %08lx size %d\n",
21611+ paddr, size);
21612+
21613+ size &= PAGE_MASK;
21614+ pages = size >> PAGE_SHIFT;
21615+
21616+ rm = omap_vram_create_region(paddr, pages);
21617+ if (rm == NULL)
21618+ return -ENOMEM;
21619+
21620+ list_add(&rm->list, &region_list);
21621+ } else {
21622+ if (postponed_cnt == MAX_POSTPONED_REGIONS)
21623+ return -ENOMEM;
21624+
21625+ postponed_regions[postponed_cnt].paddr = paddr;
21626+ postponed_regions[postponed_cnt].size = size;
21627+
21628+ ++postponed_cnt;
21629+ }
21630+ return 0;
21631+}
21632+
21633+int omap_vram_free(unsigned long paddr, size_t size)
21634+{
21635+ struct vram_region *rm;
21636+ struct vram_alloc *alloc;
21637+ unsigned start, end;
21638+
21639+ DBG("free mem paddr %08lx size %d\n", paddr, size);
21640+
21641+ size = PAGE_ALIGN(size);
21642+
21643+ mutex_lock(&region_mutex);
21644+
21645+ list_for_each_entry(rm, &region_list, list) {
21646+ list_for_each_entry(alloc, &rm->alloc_list, list) {
21647+ start = alloc->paddr;
21648+ end = alloc->paddr + (alloc->pages >> PAGE_SHIFT);
21649+
21650+ if (start >= paddr && end < paddr + size)
21651+ goto found;
21652+ }
21653+ }
21654+
21655+ mutex_unlock(&region_mutex);
21656+ return -EINVAL;
21657+
21658+found:
21659+ omap_vram_free_allocation(alloc);
21660+
21661+ mutex_unlock(&region_mutex);
21662+ return 0;
21663+}
21664+EXPORT_SYMBOL(omap_vram_free);
21665+
21666+static int _omap_vram_reserve(unsigned long paddr, unsigned pages)
21667+{
21668+ struct vram_region *rm;
21669+ struct vram_alloc *alloc;
21670+ size_t size;
21671+
21672+ size = pages << PAGE_SHIFT;
21673+
21674+ list_for_each_entry(rm, &region_list, list) {
21675+ unsigned long start, end;
21676+
21677+ DBG("checking region %lx %d\n", rm->paddr, rm->pages);
21678+
21679+ if (region_mem_type(rm->paddr) != region_mem_type(paddr))
21680+ continue;
21681+
21682+ start = rm->paddr;
21683+ end = start + (rm->pages << PAGE_SHIFT) - 1;
21684+ if (start > paddr || end < paddr + size - 1)
21685+ continue;
21686+
21687+ DBG("block ok, checking allocs\n");
21688+
21689+ list_for_each_entry(alloc, &rm->alloc_list, list) {
21690+ end = alloc->paddr - 1;
21691+
21692+ if (start <= paddr && end >= paddr + size - 1)
21693+ goto found;
21694+
21695+ start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
21696+ }
21697+
21698+ end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1;
21699+
21700+ if (!(start <= paddr && end >= paddr + size - 1))
21701+ continue;
21702+found:
21703+ DBG("found area start %lx, end %lx\n", start, end);
21704+
21705+ if (omap_vram_create_allocation(rm, paddr, pages) == NULL)
21706+ return -ENOMEM;
21707+
21708+ return 0;
21709+ }
21710+
21711+ return -ENOMEM;
21712+}
21713+
21714+int omap_vram_reserve(unsigned long paddr, size_t size)
21715+{
21716+ unsigned pages;
21717+ int r;
21718+
21719+ DBG("reserve mem paddr %08lx size %d\n", paddr, size);
21720+
21721+ size = PAGE_ALIGN(size);
21722+ pages = size >> PAGE_SHIFT;
21723+
21724+ mutex_lock(&region_mutex);
21725+
21726+ r = _omap_vram_reserve(paddr, pages);
21727+
21728+ mutex_unlock(&region_mutex);
21729+
21730+ return r;
21731+}
21732+EXPORT_SYMBOL(omap_vram_reserve);
21733+
21734+static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data)
21735+{
21736+ struct completion *compl = data;
21737+ complete(compl);
21738+}
21739+
21740+static int _omap_vram_clear(u32 paddr, unsigned pages)
21741+{
21742+ struct completion compl;
21743+ unsigned elem_count;
21744+ unsigned frame_count;
21745+ int r;
21746+ int lch;
21747+
21748+ init_completion(&compl);
21749+
21750+ r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA",
21751+ _omap_vram_dma_cb,
21752+ &compl, &lch);
21753+ if (r) {
21754+ pr_err("VRAM: request_dma failed for memory clear\n");
21755+ return -EBUSY;
21756+ }
21757+
21758+ elem_count = pages * PAGE_SIZE / 4;
21759+ frame_count = 1;
21760+
21761+ omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32,
21762+ elem_count, frame_count,
21763+ OMAP_DMA_SYNC_ELEMENT,
21764+ 0, 0);
21765+
21766+ omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC,
21767+ paddr, 0, 0);
21768+
21769+ omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000);
21770+
21771+ omap_start_dma(lch);
21772+
21773+ if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) {
21774+ omap_stop_dma(lch);
21775+ pr_err("VRAM: dma timeout while clearing memory\n");
21776+ r = -EIO;
21777+ goto err;
21778+ }
21779+
21780+ r = 0;
21781+err:
21782+ omap_free_dma(lch);
21783+
21784+ return r;
21785+}
21786+
21787+static int _omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr)
21788+{
21789+ struct vram_region *rm;
21790+ struct vram_alloc *alloc;
21791+
21792+ list_for_each_entry(rm, &region_list, list) {
21793+ unsigned long start, end;
21794+
21795+ DBG("checking region %lx %d\n", rm->paddr, rm->pages);
21796+
21797+ if (region_mem_type(rm->paddr) != mtype)
21798+ continue;
21799+
21800+ start = rm->paddr;
21801+
21802+ list_for_each_entry(alloc, &rm->alloc_list, list) {
21803+ end = alloc->paddr;
21804+
21805+ if (end - start >= pages << PAGE_SHIFT)
21806+ goto found;
21807+
21808+ start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
21809+ }
21810+
21811+ end = rm->paddr + (rm->pages << PAGE_SHIFT);
21812+found:
21813+ if (end - start < pages << PAGE_SHIFT)
21814+ continue;
21815+
21816+ DBG("found %lx, end %lx\n", start, end);
21817+
21818+ alloc = omap_vram_create_allocation(rm, start, pages);
21819+ if (alloc == NULL)
21820+ return -ENOMEM;
21821+
21822+ *paddr = start;
21823+
21824+ _omap_vram_clear(start, pages);
21825+
21826+ return 0;
21827+ }
21828+
21829+ return -ENOMEM;
21830+}
21831+
21832+int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr)
21833+{
21834+ unsigned pages;
21835+ int r;
21836+
21837+ BUG_ON(mtype > OMAP_VRAM_MEMTYPE_MAX || !size);
21838+
21839+ DBG("alloc mem type %d size %d\n", mtype, size);
21840+
21841+ size = PAGE_ALIGN(size);
21842+ pages = size >> PAGE_SHIFT;
21843+
21844+ mutex_lock(&region_mutex);
21845+
21846+ r = _omap_vram_alloc(mtype, pages, paddr);
21847+
21848+ mutex_unlock(&region_mutex);
21849+
21850+ return r;
21851+}
21852+EXPORT_SYMBOL(omap_vram_alloc);
21853+
21854+void omap_vram_get_info(unsigned long *vram,
21855+ unsigned long *free_vram,
21856+ unsigned long *largest_free_block)
21857+{
21858+ struct vram_region *vr;
21859+ struct vram_alloc *va;
21860+
21861+ *vram = 0;
21862+ *free_vram = 0;
21863+ *largest_free_block = 0;
21864+
21865+ mutex_lock(&region_mutex);
21866+
21867+ list_for_each_entry(vr, &region_list, list) {
21868+ unsigned free;
21869+ unsigned long pa;
21870+
21871+ pa = vr->paddr;
21872+ *vram += vr->pages << PAGE_SHIFT;
21873+
21874+ list_for_each_entry(va, &vr->alloc_list, list) {
21875+ free = va->paddr - pa;
21876+ *free_vram += free;
21877+ if (free > *largest_free_block)
21878+ *largest_free_block = free;
21879+ pa = va->paddr + (va->pages << PAGE_SHIFT);
21880+ }
21881+
21882+ free = vr->paddr + (vr->pages << PAGE_SHIFT) - pa;
21883+ *free_vram += free;
21884+ if (free > *largest_free_block)
21885+ *largest_free_block = free;
21886+ }
21887+
21888+ mutex_unlock(&region_mutex);
21889+}
21890+EXPORT_SYMBOL(omap_vram_get_info);
21891+
21892+#if defined(CONFIG_DEBUG_FS)
21893+static int vram_debug_show(struct seq_file *s, void *unused)
21894+{
21895+ struct vram_region *vr;
21896+ struct vram_alloc *va;
21897+ unsigned size;
21898+
21899+ mutex_lock(&region_mutex);
21900+
21901+ list_for_each_entry(vr, &region_list, list) {
21902+ size = vr->pages << PAGE_SHIFT;
21903+ seq_printf(s, "%08lx-%08lx (%d bytes)\n",
21904+ vr->paddr, vr->paddr + size - 1,
21905+ size);
21906+
21907+ list_for_each_entry(va, &vr->alloc_list, list) {
21908+ size = va->pages << PAGE_SHIFT;
21909+ seq_printf(s, " %08lx-%08lx (%d bytes)\n",
21910+ va->paddr, va->paddr + size - 1,
21911+ size);
21912+ }
21913+ }
21914+
21915+ mutex_unlock(&region_mutex);
21916+
21917+ return 0;
21918+}
21919+
21920+static int vram_debug_open(struct inode *inode, struct file *file)
21921+{
21922+ return single_open(file, vram_debug_show, inode->i_private);
21923+}
21924+
21925+static const struct file_operations vram_debug_fops = {
21926+ .open = vram_debug_open,
21927+ .read = seq_read,
21928+ .llseek = seq_lseek,
21929+ .release = single_release,
21930+};
21931+
21932+static int __init omap_vram_create_debugfs(void)
21933+{
21934+ struct dentry *d;
21935+
21936+ d = debugfs_create_file("vram", S_IRUGO, NULL,
21937+ NULL, &vram_debug_fops);
21938+ if (IS_ERR(d))
21939+ return PTR_ERR(d);
21940+
21941+ return 0;
21942+}
21943+#endif
21944+
21945+static __init int omap_vram_init(void)
21946+{
21947+ int i;
21948+
21949+ vram_initialized = 1;
21950+
21951+ for (i = 0; i < postponed_cnt; i++)
21952+ omap_vram_add_region(postponed_regions[i].paddr,
21953+ postponed_regions[i].size);
21954+
21955+#ifdef CONFIG_DEBUG_FS
21956+ if (omap_vram_create_debugfs())
21957+ pr_err("VRAM: Failed to create debugfs file\n");
21958+#endif
21959+
21960+ return 0;
21961+}
21962+
21963+arch_initcall(omap_vram_init);
21964+
21965+/* boottime vram alloc stuff */
21966+
21967+/* set from board file */
21968+static u32 omap_vram_sram_start __initdata;
21969+static u32 omap_vram_sram_size __initdata;
21970+
21971+/* set from board file */
21972+static u32 omap_vram_sdram_start __initdata;
21973+static u32 omap_vram_sdram_size __initdata;
21974+
21975+/* set from kernel cmdline */
21976+static u32 omap_vram_def_sdram_size __initdata;
21977+static u32 omap_vram_def_sdram_start __initdata;
21978+
21979+static void __init omap_vram_early_vram(char **p)
21980+{
21981+ omap_vram_def_sdram_size = memparse(*p, p);
21982+ if (**p == ',')
21983+ omap_vram_def_sdram_start = simple_strtoul((*p) + 1, p, 16);
21984+}
21985+__early_param("vram=", omap_vram_early_vram);
21986+
21987+/*
21988+ * Called from map_io. We need to call to this early enough so that we
21989+ * can reserve the fixed SDRAM regions before VM could get hold of them.
21990+ */
21991+void __init omap_vram_reserve_sdram(void)
21992+{
21993+ struct bootmem_data *bdata;
21994+ unsigned long sdram_start, sdram_size;
21995+ u32 paddr;
21996+ u32 size = 0;
21997+
21998+ /* cmdline arg overrides the board file definition */
21999+ if (omap_vram_def_sdram_size) {
22000+ size = omap_vram_def_sdram_size;
22001+ paddr = omap_vram_def_sdram_start;
22002+ }
22003+
22004+ if (!size) {
22005+ size = omap_vram_sdram_size;
22006+ paddr = omap_vram_sdram_start;
22007+ }
22008+
22009+#ifdef CONFIG_OMAP2_VRAM_SIZE
22010+ if (!size) {
22011+ size = CONFIG_OMAP2_VRAM_SIZE * 1024 * 1024;
22012+ paddr = 0;
22013+ }
22014+#endif
22015+
22016+ if (!size)
22017+ return;
22018+
22019+ size = PAGE_ALIGN(size);
22020+
22021+ bdata = NODE_DATA(0)->bdata;
22022+ sdram_start = bdata->node_min_pfn << PAGE_SHIFT;
22023+ sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start;
22024+
22025+ if (paddr) {
22026+ if ((paddr & ~PAGE_MASK) || paddr < sdram_start ||
22027+ paddr + size > sdram_start + sdram_size) {
22028+ pr_err("Illegal SDRAM region for VRAM\n");
22029+ return;
22030+ }
22031+
22032+ if (reserve_bootmem(paddr, size, BOOTMEM_EXCLUSIVE) < 0) {
22033+ pr_err("FB: failed to reserve VRAM\n");
22034+ return;
22035+ }
22036+ } else {
22037+ if (size > sdram_size) {
22038+ pr_err("Illegal SDRAM size for VRAM\n");
22039+ return;
22040+ }
22041+
22042+ paddr = virt_to_phys(alloc_bootmem_pages(size));
22043+ BUG_ON(paddr & ~PAGE_MASK);
22044+ }
22045+
22046+ omap_vram_add_region(paddr, size);
22047+
22048+ pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
22049+}
22050+
22051+/*
22052+ * Called at sram init time, before anything is pushed to the SRAM stack.
22053+ * Because of the stack scheme, we will allocate everything from the
22054+ * start of the lowest address region to the end of SRAM. This will also
22055+ * include padding for page alignment and possible holes between regions.
22056+ *
22057+ * As opposed to the SDRAM case, we'll also do any dynamic allocations at
22058+ * this point, since the driver built as a module would have problem with
22059+ * freeing / reallocating the regions.
22060+ */
22061+unsigned long __init omap_vram_reserve_sram(unsigned long sram_pstart,
22062+ unsigned long sram_vstart,
22063+ unsigned long sram_size,
22064+ unsigned long pstart_avail,
22065+ unsigned long size_avail)
22066+{
22067+ unsigned long pend_avail;
22068+ unsigned long reserved;
22069+ u32 paddr;
22070+ u32 size;
22071+
22072+ paddr = omap_vram_sram_start;
22073+ size = omap_vram_sram_size;
22074+
22075+ if (!size)
22076+ return 0;
22077+
22078+ reserved = 0;
22079+ pend_avail = pstart_avail + size_avail;
22080+
22081+ if (!paddr) {
22082+ /* Dynamic allocation */
22083+ if ((size_avail & PAGE_MASK) < size) {
22084+ pr_err("Not enough SRAM for VRAM\n");
22085+ return 0;
22086+ }
22087+ size_avail = (size_avail - size) & PAGE_MASK;
22088+ paddr = pstart_avail + size_avail;
22089+ }
22090+
22091+ if (paddr < sram_pstart ||
22092+ paddr + size > sram_pstart + sram_size) {
22093+ pr_err("Illegal SRAM region for VRAM\n");
22094+ return 0;
22095+ }
22096+
22097+ /* Reserve everything above the start of the region. */
22098+ if (pend_avail - paddr > reserved)
22099+ reserved = pend_avail - paddr;
22100+ size_avail = pend_avail - reserved - pstart_avail;
22101+
22102+ omap_vram_add_region(paddr, size);
22103+
22104+ if (reserved)
22105+ pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved);
22106+
22107+ return reserved;
22108+}
22109+
22110+void __init omap_vram_set_sdram_vram(u32 size, u32 start)
22111+{
22112+ omap_vram_sdram_start = start;
22113+ omap_vram_sdram_size = size;
22114+}
22115+
22116+void __init omap_vram_set_sram_vram(u32 size, u32 start)
22117+{
22118+ omap_vram_sram_start = start;
22119+ omap_vram_sram_size = size;
22120+}
22121--- /dev/null
22122+++ b/drivers/video/omap2/vrfb.c
22123@@ -0,0 +1,277 @@
22124+/*
22125+ * VRFB Rotation Engine
22126+ *
22127+ * Copyright (C) 2009 Nokia Corporation
22128+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
22129+ *
22130+ * This program is free software; you can redistribute it and/or modify
22131+ * it under the terms of the GNU General Public License version 2 as
22132+ * published by the Free Software Foundation.
22133+ *
22134+ * This program is distributed in the hope that it will be useful, but
22135+ * WITHOUT ANY WARRANTY; without even the implied warranty of
22136+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22137+ * General Public License for more details.
22138+ *
22139+ * You should have received a copy of the GNU General Public License along
22140+ * with this program; if not, write to the Free Software Foundation, Inc.,
22141+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22142+ */
22143+
22144+#include <linux/kernel.h>
22145+#include <linux/module.h>
22146+#include <linux/ioport.h>
22147+#include <linux/io.h>
22148+#include <linux/bitops.h>
22149+#include <linux/mutex.h>
22150+
22151+#include <mach/io.h>
22152+#include <mach/vrfb.h>
22153+#include <mach/sdrc.h>
22154+/*#define DEBUG*/
22155+
22156+#ifdef DEBUG
22157+#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
22158+#else
22159+#define DBG(format, ...)
22160+#endif
22161+
22162+#define SMS_ROT_VIRT_BASE(context, rot) \
22163+ (((context >= 4) ? 0xD0000000 : 0x70000000) \
22164+ + (0x4000000 * (context)) \
22165+ + (0x1000000 * (rot)))
22166+
22167+#define OMAP_VRFB_SIZE (2048 * 2048 * 4)
22168+
22169+#define VRFB_PAGE_WIDTH_EXP 5 /* Assuming SDRAM pagesize= 1024 */
22170+#define VRFB_PAGE_HEIGHT_EXP 5 /* 1024 = 2^5 * 2^5 */
22171+#define VRFB_PAGE_WIDTH (1 << VRFB_PAGE_WIDTH_EXP)
22172+#define VRFB_PAGE_HEIGHT (1 << VRFB_PAGE_HEIGHT_EXP)
22173+#define SMS_IMAGEHEIGHT_OFFSET 16
22174+#define SMS_IMAGEWIDTH_OFFSET 0
22175+#define SMS_PH_OFFSET 8
22176+#define SMS_PW_OFFSET 4
22177+#define SMS_PS_OFFSET 0
22178+
22179+#define VRFB_NUM_CTXS 12
22180+/* bitmap of reserved contexts */
22181+static unsigned long ctx_map;
22182+/* bitmap of contexts for which we have to keep the HW context valid */
22183+static unsigned long ctx_map_active;
22184+
22185+static DEFINE_MUTEX(ctx_lock);
22186+
22187+/*
22188+ * Access to this happens from client drivers or the PM core after wake-up.
22189+ * For the first case we require locking at the driver level, for the second
22190+ * we don't need locking, since no drivers will run until after the wake-up
22191+ * has finished.
22192+ */
22193+static struct {
22194+ u32 physical_ba;
22195+ u32 control;
22196+ u32 size;
22197+} vrfb_hw_context[VRFB_NUM_CTXS];
22198+
22199+static inline void restore_hw_context(int ctx)
22200+{
22201+ omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx);
22202+ omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx);
22203+ omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx);
22204+}
22205+
22206+void omap_vrfb_restore_context(void)
22207+{
22208+ int i;
22209+ unsigned long map = ctx_map_active;
22210+
22211+ for (i = ffs(map); i; i = ffs(map)) {
22212+ /* i=1..32 */
22213+ i--;
22214+ map &= ~(1 << i);
22215+ restore_hw_context(i);
22216+ }
22217+}
22218+
22219+void omap_vrfb_adjust_size(u16 *width, u16 *height,
22220+ u8 bytespp)
22221+{
22222+ *width = ALIGN(*width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
22223+ *height = ALIGN(*height, VRFB_PAGE_HEIGHT);
22224+}
22225+EXPORT_SYMBOL(omap_vrfb_adjust_size);
22226+
22227+void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
22228+ u16 width, u16 height,
22229+ unsigned bytespp, bool yuv_mode)
22230+{
22231+ unsigned pixel_size_exp;
22232+ u16 vrfb_width;
22233+ u16 vrfb_height;
22234+ u8 ctx = vrfb->context;
22235+ u32 size;
22236+ u32 control;
22237+
22238+ DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d)\n", ctx, paddr,
22239+ width, height, color_mode);
22240+
22241+ /* For YUV2 and UYVY modes VRFB needs to handle pixels a bit
22242+ * differently. See TRM. */
22243+ if (yuv_mode) {
22244+ bytespp *= 2;
22245+ width /= 2;
22246+ }
22247+
22248+ if (bytespp == 4)
22249+ pixel_size_exp = 2;
22250+ else if (bytespp == 2)
22251+ pixel_size_exp = 1;
22252+ else
22253+ BUG();
22254+
22255+ vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
22256+ vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT);
22257+
22258+ DBG("vrfb w %u, h %u bytespp %d\n", vrfb_width, vrfb_height, bytespp);
22259+
22260+ size = vrfb_width << SMS_IMAGEWIDTH_OFFSET;
22261+ size |= vrfb_height << SMS_IMAGEHEIGHT_OFFSET;
22262+
22263+ control = pixel_size_exp << SMS_PS_OFFSET;
22264+ control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET;
22265+ control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
22266+
22267+ vrfb_hw_context[ctx].physical_ba = paddr;
22268+ vrfb_hw_context[ctx].size = size;
22269+ vrfb_hw_context[ctx].control = control;
22270+
22271+ omap2_sms_write_rot_physical_ba(paddr, ctx);
22272+ omap2_sms_write_rot_size(size, ctx);
22273+ omap2_sms_write_rot_control(control, ctx);
22274+
22275+ DBG("vrfb offset pixels %d, %d\n",
22276+ vrfb_width - width, vrfb_height - height);
22277+
22278+ vrfb->xoffset = vrfb_width - width;
22279+ vrfb->yoffset = vrfb_height - height;
22280+ vrfb->bytespp = bytespp;
22281+}
22282+EXPORT_SYMBOL(omap_vrfb_setup);
22283+
22284+void omap_vrfb_release_ctx(struct vrfb *vrfb)
22285+{
22286+ int rot;
22287+ int ctx = vrfb->context;
22288+
22289+ if (ctx == 0xff)
22290+ return;
22291+
22292+ DBG("release ctx %d\n", ctx);
22293+
22294+ mutex_lock(&ctx_lock);
22295+
22296+ BUG_ON(!(ctx_map & (1 << ctx)));
22297+
22298+ clear_bit(ctx, &ctx_map_active);
22299+ clear_bit(ctx, &ctx_map);
22300+
22301+ for (rot = 0; rot < 4; ++rot) {
22302+ if (vrfb->paddr[rot]) {
22303+ release_mem_region(vrfb->paddr[rot], OMAP_VRFB_SIZE);
22304+ vrfb->paddr[rot] = 0;
22305+ }
22306+ }
22307+
22308+ vrfb->context = 0xff;
22309+
22310+ mutex_unlock(&ctx_lock);
22311+}
22312+EXPORT_SYMBOL(omap_vrfb_release_ctx);
22313+
22314+int omap_vrfb_request_ctx(struct vrfb *vrfb)
22315+{
22316+ int rot;
22317+ u32 paddr;
22318+ u8 ctx;
22319+ int r;
22320+
22321+ DBG("request ctx\n");
22322+
22323+ mutex_lock(&ctx_lock);
22324+
22325+ for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
22326+ if ((ctx_map & (1 << ctx)) == 0)
22327+ break;
22328+
22329+ if (ctx == VRFB_NUM_CTXS) {
22330+ pr_err("vrfb: no free contexts\n");
22331+ r = -EBUSY;
22332+ goto out;
22333+ }
22334+
22335+ DBG("found free ctx %d\n", ctx);
22336+
22337+ set_bit(ctx, &ctx_map);
22338+ WARN_ON(ctx_map_active & (1 << ctx));
22339+ set_bit(ctx, &ctx_map_active);
22340+
22341+ memset(vrfb, 0, sizeof(*vrfb));
22342+
22343+ vrfb->context = ctx;
22344+
22345+ for (rot = 0; rot < 4; ++rot) {
22346+ paddr = SMS_ROT_VIRT_BASE(ctx, rot);
22347+ if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
22348+ pr_err("vrfb: failed to reserve VRFB "
22349+ "area for ctx %d, rotation %d\n",
22350+ ctx, rot * 90);
22351+ omap_vrfb_release_ctx(vrfb);
22352+ r = -ENOMEM;
22353+ goto out;
22354+ }
22355+
22356+ vrfb->paddr[rot] = paddr;
22357+
22358+ DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]);
22359+ }
22360+
22361+ r = 0;
22362+out:
22363+ mutex_unlock(&ctx_lock);
22364+ return r;
22365+}
22366+EXPORT_SYMBOL(omap_vrfb_request_ctx);
22367+
22368+void omap_vrfb_suspend_ctx(struct vrfb *vrfb)
22369+{
22370+ DBG("suspend ctx %d\n", vrfb->context);
22371+ mutex_lock(&ctx_lock);
22372+
22373+ BUG_ON(vrfb->context >= VRFB_NUM_CTXS);
22374+ BUG_ON(!((1 << vrfb->context) & ctx_map_active));
22375+
22376+ clear_bit(vrfb->context, &ctx_map_active);
22377+ mutex_unlock(&ctx_lock);
22378+}
22379+EXPORT_SYMBOL(omap_vrfb_suspend_ctx);
22380+
22381+void omap_vrfb_resume_ctx(struct vrfb *vrfb)
22382+{
22383+ DBG("resume ctx %d\n", vrfb->context);
22384+ mutex_lock(&ctx_lock);
22385+
22386+ BUG_ON(vrfb->context >= VRFB_NUM_CTXS);
22387+ BUG_ON((1 << vrfb->context) & ctx_map_active);
22388+
22389+ /*
22390+ * omap_vrfb_restore_context is normally called by the core domain
22391+ * save / restore logic, but since this VRFB context was suspended
22392+ * those calls didn't actually restore the context and now we might
22393+ * have an invalid context. Do an explicit restore here.
22394+ */
22395+ restore_hw_context(vrfb->context);
22396+ set_bit(vrfb->context, &ctx_map_active);
22397+ mutex_unlock(&ctx_lock);
22398+}
22399+EXPORT_SYMBOL(omap_vrfb_resume_ctx);
22400+
22401--- /dev/null
22402+++ b/include/linux/omapfb.h
22403@@ -0,0 +1,242 @@
22404+/*
22405+ * File: include/linux/omapfb.h
22406+ *
22407+ * Framebuffer driver for TI OMAP boards
22408+ *
22409+ * Copyright (C) 2004 Nokia Corporation
22410+ * Author: Imre Deak <imre.deak@nokia.com>
22411+ *
22412+ * This program is free software; you can redistribute it and/or modify it
22413+ * under the terms of the GNU General Public License as published by the
22414+ * Free Software Foundation; either version 2 of the License, or (at your
22415+ * option) any later version.
22416+ *
22417+ * This program is distributed in the hope that it will be useful, but
22418+ * WITHOUT ANY WARRANTY; without even the implied warranty of
22419+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22420+ * General Public License for more details.
22421+ *
22422+ * You should have received a copy of the GNU General Public License along
22423+ * with this program; if not, write to the Free Software Foundation, Inc.,
22424+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22425+ */
22426+
22427+#ifndef __LINUX_OMAPFB_H__
22428+#define __LINUX_OMAPFB_H__
22429+
22430+#include <linux/fb.h>
22431+#include <linux/ioctl.h>
22432+#include <linux/types.h>
22433+
22434+/* IOCTL commands. */
22435+
22436+#define OMAP_IOW(num, dtype) _IOW('O', num, dtype)
22437+#define OMAP_IOR(num, dtype) _IOR('O', num, dtype)
22438+#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype)
22439+#define OMAP_IO(num) _IO('O', num)
22440+
22441+#define OMAPFB_MIRROR OMAP_IOW(31, int)
22442+#define OMAPFB_SYNC_GFX OMAP_IO(37)
22443+#define OMAPFB_VSYNC OMAP_IO(38)
22444+#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int)
22445+#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps)
22446+#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int)
22447+#define OMAPFB_LCD_TEST OMAP_IOW(45, int)
22448+#define OMAPFB_CTRL_TEST OMAP_IOW(46, int)
22449+#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old)
22450+#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key)
22451+#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key)
22452+#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info)
22453+#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info)
22454+#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window)
22455+#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info)
22456+#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info)
22457+#define OMAPFB_WAITFORVSYNC OMAP_IO(57)
22458+#define OMAPFB_MEMORY_READ OMAP_IOR(58, struct omapfb_memory_read)
22459+#define OMAPFB_GET_OVERLAY_COLORMODE OMAP_IOR(59, struct omapfb_ovl_colormode)
22460+#define OMAPFB_WAITFORGO OMAP_IO(60)
22461+#define OMAPFB_GET_VRAM_INFO OMAP_IOR(61, struct omapfb_vram_info)
22462+
22463+#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff
22464+#define OMAPFB_CAPS_LCDC_MASK 0x00fff000
22465+#define OMAPFB_CAPS_PANEL_MASK 0xff000000
22466+
22467+#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000
22468+#define OMAPFB_CAPS_TEARSYNC 0x00002000
22469+#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000
22470+#define OMAPFB_CAPS_PLANE_SCALE 0x00008000
22471+#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000
22472+#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000
22473+#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000
22474+#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000
22475+#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000
22476+
22477+/* Values from DSP must map to lower 16-bits */
22478+#define OMAPFB_FORMAT_MASK 0x00ff
22479+#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100
22480+#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200
22481+#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400
22482+#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800
22483+#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000
22484+
22485+#define OMAPFB_MEMTYPE_SDRAM 0
22486+#define OMAPFB_MEMTYPE_SRAM 1
22487+#define OMAPFB_MEMTYPE_MAX 1
22488+
22489+enum omapfb_color_format {
22490+ OMAPFB_COLOR_RGB565 = 0,
22491+ OMAPFB_COLOR_YUV422,
22492+ OMAPFB_COLOR_YUV420,
22493+ OMAPFB_COLOR_CLUT_8BPP,
22494+ OMAPFB_COLOR_CLUT_4BPP,
22495+ OMAPFB_COLOR_CLUT_2BPP,
22496+ OMAPFB_COLOR_CLUT_1BPP,
22497+ OMAPFB_COLOR_RGB444,
22498+ OMAPFB_COLOR_YUY422,
22499+
22500+ OMAPFB_COLOR_ARGB16,
22501+ OMAPFB_COLOR_RGB24U, /* RGB24, 32-bit container */
22502+ OMAPFB_COLOR_RGB24P, /* RGB24, 24-bit container */
22503+ OMAPFB_COLOR_ARGB32,
22504+ OMAPFB_COLOR_RGBA32,
22505+ OMAPFB_COLOR_RGBX32,
22506+};
22507+
22508+struct omapfb_update_window {
22509+ __u32 x, y;
22510+ __u32 width, height;
22511+ __u32 format;
22512+ __u32 out_x, out_y;
22513+ __u32 out_width, out_height;
22514+ __u32 reserved[8];
22515+};
22516+
22517+struct omapfb_update_window_old {
22518+ __u32 x, y;
22519+ __u32 width, height;
22520+ __u32 format;
22521+};
22522+
22523+enum omapfb_plane {
22524+ OMAPFB_PLANE_GFX = 0,
22525+ OMAPFB_PLANE_VID1,
22526+ OMAPFB_PLANE_VID2,
22527+};
22528+
22529+enum omapfb_channel_out {
22530+ OMAPFB_CHANNEL_OUT_LCD = 0,
22531+ OMAPFB_CHANNEL_OUT_DIGIT,
22532+};
22533+
22534+struct omapfb_plane_info {
22535+ __u32 pos_x;
22536+ __u32 pos_y;
22537+ __u8 enabled;
22538+ __u8 channel_out;
22539+ __u8 mirror;
22540+ __u8 reserved1;
22541+ __u32 out_width;
22542+ __u32 out_height;
22543+ __u32 reserved2[12];
22544+};
22545+
22546+struct omapfb_mem_info {
22547+ __u32 size;
22548+ __u8 type;
22549+ __u8 reserved[3];
22550+};
22551+
22552+struct omapfb_caps {
22553+ __u32 ctrl;
22554+ __u32 plane_color;
22555+ __u32 wnd_color;
22556+};
22557+
22558+enum omapfb_color_key_type {
22559+ OMAPFB_COLOR_KEY_DISABLED = 0,
22560+ OMAPFB_COLOR_KEY_GFX_DST,
22561+ OMAPFB_COLOR_KEY_VID_SRC,
22562+};
22563+
22564+struct omapfb_color_key {
22565+ __u8 channel_out;
22566+ __u32 background;
22567+ __u32 trans_key;
22568+ __u8 key_type;
22569+};
22570+
22571+enum omapfb_update_mode {
22572+ OMAPFB_UPDATE_DISABLED = 0,
22573+ OMAPFB_AUTO_UPDATE,
22574+ OMAPFB_MANUAL_UPDATE
22575+};
22576+
22577+struct omapfb_memory_read {
22578+ __u16 x;
22579+ __u16 y;
22580+ __u16 w;
22581+ __u16 h;
22582+ size_t buffer_size;
22583+ void __user *buffer;
22584+};
22585+
22586+struct omapfb_ovl_colormode {
22587+ __u8 overlay_idx;
22588+ __u8 mode_idx;
22589+ __u32 bits_per_pixel;
22590+ __u32 nonstd;
22591+ struct fb_bitfield red;
22592+ struct fb_bitfield green;
22593+ struct fb_bitfield blue;
22594+ struct fb_bitfield transp;
22595+};
22596+
22597+struct omapfb_vram_info {
22598+ __u32 total;
22599+ __u32 free;
22600+ __u32 largest_free_block;
22601+ __u32 reserved[5];
22602+};
22603+
22604+#ifdef __KERNEL__
22605+
22606+#include <mach/board.h>
22607+
22608+#ifdef CONFIG_ARCH_OMAP1
22609+#define OMAPFB_PLANE_NUM 1
22610+#else
22611+#define OMAPFB_PLANE_NUM 3
22612+#endif
22613+
22614+struct omapfb_mem_region {
22615+ u32 paddr;
22616+ void __iomem *vaddr;
22617+ unsigned long size;
22618+ u8 type; /* OMAPFB_PLANE_MEM_* */
22619+ enum omapfb_color_format format;/* OMAPFB_COLOR_* */
22620+ unsigned format_used:1; /* Must be set when format is set.
22621+ * Needed b/c of the badly chosen 0
22622+ * base for OMAPFB_COLOR_* values
22623+ */
22624+ unsigned alloc:1; /* allocated by the driver */
22625+ unsigned map:1; /* kernel mapped by the driver */
22626+};
22627+
22628+struct omapfb_mem_desc {
22629+ int region_cnt;
22630+ struct omapfb_mem_region region[OMAPFB_PLANE_NUM];
22631+};
22632+
22633+struct omapfb_platform_data {
22634+ struct omap_lcd_config lcd;
22635+ struct omapfb_mem_desc mem_desc;
22636+ void *ctrl_platform_data;
22637+};
22638+
22639+/* in arch/arm/plat-omap/fb.c */
22640+extern void omapfb_set_ctrl_platform_data(void *pdata);
22641+extern void omapfb_reserve_sdram(void);
22642+
22643+#endif
22644+
22645+#endif /* __OMAPFB_H */
22646

Archive Download this file



interactive