Make beagleboard as subtarget from omap35xx
[oweals/openwrt.git] / target / linux / omap35xx / patches-2.6.32 / 001-DSS2.patch
1 diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
2 new file mode 100644
3 index 0000000..0af0e9e
4 --- /dev/null
5 +++ b/Documentation/arm/OMAP/DSS
6 @@ -0,0 +1,317 @@
7 +OMAP2/3 Display Subsystem
8 +-------------------------
9 +
10 +This is an almost total rewrite of the OMAP FB driver in drivers/video/omap
11 +(let's call it DSS1). The main differences between DSS1 and DSS2 are DSI,
12 +TV-out and multiple display support, but there are lots of small improvements
13 +also.
14 +
15 +The DSS2 driver (omapdss module) is in arch/arm/plat-omap/dss/, and the FB,
16 +panel and controller drivers are in drivers/video/omap2/. DSS1 and DSS2 live
17 +currently side by side, you can choose which one to use.
18 +
19 +Features
20 +--------
21 +
22 +Working and tested features include:
23 +
24 +- MIPI DPI (parallel) output
25 +- MIPI DSI output in command mode
26 +- MIPI DBI (RFBI) output
27 +- SDI output
28 +- TV output
29 +- All pieces can be compiled as a module or inside kernel
30 +- Use DISPC to update any of the outputs
31 +- Use CPU to update RFBI or DSI output
32 +- OMAP DISPC planes
33 +- RGB16, RGB24 packed, RGB24 unpacked
34 +- YUV2, UYVY
35 +- Scaling
36 +- Adjusting DSS FCK to find a good pixel clock
37 +- Use DSI DPLL to create DSS FCK
38 +
39 +Tested boards include:
40 +- OMAP3 SDP board
41 +- Beagle board
42 +- N810
43 +
44 +omapdss driver
45 +--------------
46 +
47 +The DSS driver does not itself have any support for Linux framebuffer, V4L or
48 +such like the current ones, but it has an internal kernel API that upper level
49 +drivers can use.
50 +
51 +The DSS driver models OMAP's overlays, overlay managers and displays in a
52 +flexible way to enable non-common multi-display configuration. In addition to
53 +modelling the hardware overlays, omapdss supports virtual overlays and overlay
54 +managers. These can be used when updating a display with CPU or system DMA.
55 +
56 +Panel and controller drivers
57 +----------------------------
58 +
59 +The drivers implement panel or controller specific functionality and are not
60 +usually visible to users except through omapfb driver.  They register
61 +themselves to the DSS driver.
62 +
63 +omapfb driver
64 +-------------
65 +
66 +The omapfb driver implements arbitrary number of standard linux framebuffers.
67 +These framebuffers can be routed flexibly to any overlays, thus allowing very
68 +dynamic display architecture.
69 +
70 +The driver exports some omapfb specific ioctls, which are compatible with the
71 +ioctls in the old driver.
72 +
73 +The rest of the non standard features are exported via sysfs. Whether the final
74 +implementation will use sysfs, or ioctls, is still open.
75 +
76 +V4L2 drivers
77 +------------
78 +
79 +V4L2 is being implemented in TI.
80 +
81 +From omapdss point of view the V4L2 drivers should be similar to framebuffer
82 +driver.
83 +
84 +Architecture
85 +--------------------
86 +
87 +Some clarification what the different components do:
88 +
89 +    - Framebuffer is a memory area inside OMAP's SRAM/SDRAM that contains the
90 +      pixel data for the image. Framebuffer has width and height and color
91 +      depth.
92 +    - Overlay defines where the pixels are read from and where they go on the
93 +      screen. The overlay may be smaller than framebuffer, thus displaying only
94 +      part of the framebuffer. The position of the overlay may be changed if
95 +      the overlay is smaller than the display.
96 +    - Overlay manager combines the overlays in to one image and feeds them to
97 +      display.
98 +    - Display is the actual physical display device.
99 +
100 +A framebuffer can be connected to multiple overlays to show the same pixel data
101 +on all of the overlays. Note that in this case the overlay input sizes must be
102 +the same, but, in case of video overlays, the output size can be different. Any
103 +framebuffer can be connected to any overlay.
104 +
105 +An overlay can be connected to one overlay manager. Also DISPC overlays can be
106 +connected only to DISPC overlay managers, and virtual overlays can be only
107 +connected to virtual overlays.
108 +
109 +An overlay manager can be connected to one display. There are certain
110 +restrictions which kinds of displays an overlay manager can be connected:
111 +
112 +    - DISPC TV overlay manager can be only connected to TV display.
113 +    - Virtual overlay managers can only be connected to DBI or DSI displays.
114 +    - DISPC LCD overlay manager can be connected to all displays, except TV
115 +      display.
116 +
117 +Sysfs
118 +-----
119 +The sysfs interface is mainly used for testing. I don't think sysfs
120 +interface is the best for this in the final version, but I don't quite know
121 +what would be the best interfaces for these things.
122 +
123 +The sysfs interface is divided to two parts: DSS and FB.
124 +
125 +/sys/class/graphics/fb? directory:
126 +mirror         0=off, 1=on
127 +rotate         Rotation 0-3 for 0, 90, 180, 270 degrees
128 +rotate_type    0 = DMA rotation, 1 = VRFB rotation
129 +overlays       List of overlay numbers to which framebuffer pixels go
130 +phys_addr      Physical address of the framebuffer
131 +virt_addr      Virtual address of the framebuffer
132 +size           Size of the framebuffer
133 +
134 +/sys/devices/platform/omapdss/overlay? directory:
135 +enabled                0=off, 1=on
136 +input_size     width,height (ie. the framebuffer size)
137 +manager                Destination overlay manager name
138 +name
139 +output_size    width,height
140 +position       x,y
141 +screen_width   width
142 +global_alpha           global alpha 0-255 0=transparent 255=opaque
143 +
144 +/sys/devices/platform/omapdss/manager? directory:
145 +display                                Destination display
146 +name
147 +alpha_blending_enabled         0=off, 1=on
148 +trans_key_enabled              0=off, 1=on
149 +trans_key_type                 gfx-destination, video-source
150 +trans_key_value                        transparency color key (RGB24)
151 +default_color                  default background color (RGB24)
152 +
153 +/sys/devices/platform/omapdss/display? directory:
154 +ctrl_name      Controller name
155 +mirror         0=off, 1=on
156 +update_mode    0=off, 1=auto, 2=manual
157 +enabled                0=off, 1=on
158 +name
159 +rotate         Rotation 0-3 for 0, 90, 180, 270 degrees
160 +timings                Display timings (pixclock,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw)
161 +               When writing, two special timings are accepted for tv-out:
162 +               "pal" and "ntsc"
163 +panel_name
164 +tear_elim      Tearing elimination 0=off, 1=on
165 +
166 +There are also some debugfs files at <debugfs>/omapdss/ which show information
167 +about clocks and registers.
168 +
169 +Examples
170 +--------
171 +
172 +The following definitions have been made for the examples below:
173 +
174 +ovl0=/sys/devices/platform/omapdss/overlay0
175 +ovl1=/sys/devices/platform/omapdss/overlay1
176 +ovl2=/sys/devices/platform/omapdss/overlay2
177 +
178 +mgr0=/sys/devices/platform/omapdss/manager0
179 +mgr1=/sys/devices/platform/omapdss/manager1
180 +
181 +lcd=/sys/devices/platform/omapdss/display0
182 +dvi=/sys/devices/platform/omapdss/display1
183 +tv=/sys/devices/platform/omapdss/display2
184 +
185 +fb0=/sys/class/graphics/fb0
186 +fb1=/sys/class/graphics/fb1
187 +fb2=/sys/class/graphics/fb2
188 +
189 +Default setup on OMAP3 SDP
190 +--------------------------
191 +
192 +Here's the default setup on OMAP3 SDP board. All planes go to LCD. DVI
193 +and TV-out are not in use. The columns from left to right are:
194 +framebuffers, overlays, overlay managers, displays. Framebuffers are
195 +handled by omapfb, and the rest by the DSS.
196 +
197 +FB0 --- GFX  -\            DVI
198 +FB1 --- VID1 --+- LCD ---- LCD
199 +FB2 --- VID2 -/   TV ----- TV
200 +
201 +Example: Switch from LCD to DVI
202 +----------------------
203 +
204 +w=`cat $dvi/timings | cut -d "," -f 2 | cut -d "/" -f 1`
205 +h=`cat $dvi/timings | cut -d "," -f 3 | cut -d "/" -f 1`
206 +
207 +echo "0" > $lcd/enabled
208 +echo "" > $mgr0/display
209 +fbset -fb /dev/fb0 -xres $w -yres $h -vxres $w -vyres $h
210 +# at this point you have to switch the dvi/lcd dip-switch from the omap board
211 +echo "dvi" > $mgr0/display
212 +echo "1" > $dvi/enabled
213 +
214 +After this the configuration looks like:
215 +
216 +FB0 --- GFX  -\         -- DVI
217 +FB1 --- VID1 --+- LCD -/   LCD
218 +FB2 --- VID2 -/   TV ----- TV
219 +
220 +Example: Clone GFX overlay to LCD and TV
221 +-------------------------------
222 +
223 +w=`cat $tv/timings | cut -d "," -f 2 | cut -d "/" -f 1`
224 +h=`cat $tv/timings | cut -d "," -f 3 | cut -d "/" -f 1`
225 +
226 +echo "0" > $ovl0/enabled
227 +echo "0" > $ovl1/enabled
228 +
229 +echo "" > $fb1/overlays
230 +echo "0,1" > $fb0/overlays
231 +
232 +echo "$w,$h" > $ovl1/output_size
233 +echo "tv" > $ovl1/manager
234 +
235 +echo "1" > $ovl0/enabled
236 +echo "1" > $ovl1/enabled
237 +
238 +echo "1" > $tv/enabled
239 +
240 +After this the configuration looks like (only relevant parts shown):
241 +
242 +FB0 +-- GFX  ---- LCD ---- LCD
243 +     \- VID1 ---- TV  ---- TV
244 +
245 +Misc notes
246 +----------
247 +
248 +OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator.
249 +
250 +Using DSI DPLL to generate pixel clock it is possible produce the pixel clock
251 +of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI.
252 +
253 +Rotation and mirroring currently only supports RGB565 and RGB8888 modes. VRFB
254 +does not support mirroring.
255 +
256 +VRFB rotation requires much more memory than non-rotated framebuffer, so you
257 +probably need to increase your vram setting before using VRFB rotation. Also,
258 +many applications may not work with VRFB if they do not pay attention to all
259 +framebuffer parameters.
260 +
261 +Kernel boot arguments
262 +---------------------
263 +
264 +vram=<size>
265 +       - Amount of total VRAM to preallocate. For example, "10M". omapfb
266 +         allocates memory for framebuffers from VRAM.
267 +
268 +omapfb.mode=<display>:<mode>[,...]
269 +       - Default video mode for specified displays. For example,
270 +         "dvi:800x400MR-24@60".  See drivers/video/modedb.c.
271 +         There are also two special modes: "pal" and "ntsc" that
272 +         can be used to tv out.
273 +
274 +omapfb.vram=<fbnum>:<size>[@<physaddr>][,...]
275 +       - VRAM allocated for a framebuffer. Normally omapfb allocates vram
276 +         depending on the display size. With this you can manually allocate
277 +         more or define the physical address of each framebuffer. For example,
278 +         "1:4M" to allocate 4M for fb1.
279 +
280 +omapfb.debug=<y|n>
281 +       - Enable debug printing. You have to have OMAPFB debug support enabled
282 +         in kernel config.
283 +
284 +omapfb.test=<y|n>
285 +       - Draw test pattern to framebuffer whenever framebuffer settings change.
286 +         You need to have OMAPFB debug support enabled in kernel config.
287 +
288 +omapfb.vrfb=<y|n>
289 +       - Use VRFB rotation for all framebuffers.
290 +
291 +omapfb.rotate=<angle>
292 +       - Default rotation applied to all framebuffers.
293 +         0 - 0 degree rotation
294 +         1 - 90 degree rotation
295 +         2 - 180 degree rotation
296 +         3 - 270 degree rotation
297 +
298 +omapfb.mirror=<y|n>
299 +       - Default mirror for all framebuffers. Only works with DMA rotation.
300 +
301 +omapdss.def_disp=<display>
302 +       - Name of default display, to which all overlays will be connected.
303 +         Common examples are "lcd" or "tv".
304 +
305 +omapdss.debug=<y|n>
306 +       - Enable debug printing. You have to have DSS debug support enabled in
307 +         kernel config.
308 +
309 +TODO
310 +----
311 +
312 +DSS locking
313 +
314 +Error checking
315 +- Lots of checks are missing or implemented just as BUG()
316 +
317 +System DMA update for DSI
318 +- Can be used for RGB16 and RGB24P modes. Probably not for RGB24U (how
319 +  to skip the empty byte?)
320 +
321 +OMAP1 support
322 +- Not sure if needed
323 +
324 diff --git a/MAINTAINERS b/MAINTAINERS
325 index 8824115..3f5d39f 100644
326 --- a/MAINTAINERS
327 +++ b/MAINTAINERS
328 @@ -3819,6 +3819,23 @@ L:       linux-omap@vger.kernel.org
329  S:     Maintained
330  F:     drivers/video/omap/
331  
332 +OMAP DISPLAY SUBSYSTEM SUPPORT (DSS2)
333 +M:     Tomi Valkeinen <tomi.valkeinen@nokia.com>
334 +L:     linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
335 +L:     linux-omap@vger.kernel.org
336 +S:     Maintained
337 +F:     drivers/video/omap2/dss/
338 +F:     drivers/video/omap2/vrfb.c
339 +F:     drivers/video/omap2/vram.c
340 +F:     Documentation/arm/OMAP/DSS
341 +
342 +OMAP FRAMEBUFFER SUPPORT (FOR DSS2)
343 +M:     Tomi Valkeinen <tomi.valkeinen@nokia.com>
344 +L:     linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
345 +L:     linux-omap@vger.kernel.org
346 +S:     Maintained
347 +F:     drivers/video/omap2/omapfb/
348 +
349  OMAP MMC SUPPORT
350  M:     Jarkko Lavinen <jarkko.lavinen@nokia.com>
351  L:     linux-omap@vger.kernel.org
352 diff --git a/arch/arm/configs/omap_3430sdp_defconfig b/arch/arm/configs/omap_3430sdp_defconfig
353 index 8a4a7e2..59e26e4 100644
354 --- a/arch/arm/configs/omap_3430sdp_defconfig
355 +++ b/arch/arm/configs/omap_3430sdp_defconfig
356 @@ -1336,10 +1336,33 @@ CONFIG_FB_CFB_IMAGEBLIT=y
357  #
358  # CONFIG_FB_S1D13XXX is not set
359  # CONFIG_FB_VIRTUAL is not set
360 -CONFIG_FB_OMAP=y
361 -# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
362 +# CONFIG_FB_METRONOME is not set
363 +# CONFIG_FB_MB862XX is not set
364 +# CONFIG_FB_BROADSHEET is not set
365 +# CONFIG_FB_OMAP_LCD_VGA is not set
366  # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
367 -CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2
368 +CONFIG_OMAP2_VRAM=y
369 +CONFIG_OMAP2_VRFB=y
370 +CONFIG_OMAP2_DSS=y
371 +CONFIG_OMAP2_VRAM_SIZE=4
372 +CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
373 +# CONFIG_OMAP2_DSS_RFBI is not set
374 +CONFIG_OMAP2_DSS_VENC=y
375 +# CONFIG_OMAP2_DSS_SDI is not set
376 +# CONFIG_OMAP2_DSS_DSI is not set
377 +# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
378 +CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
379 +CONFIG_FB_OMAP2=y
380 +CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
381 +# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
382 +CONFIG_FB_OMAP2_NUM_FBS=3
383 +
384 +#
385 +# OMAP2/3 Display Device Drivers
386 +#
387 +CONFIG_PANEL_GENERIC=y
388 +# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set
389 +CONFIG_PANEL_SHARP_LS037V7DW01=y
390  # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
391  
392  #
393 diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
394 index ed2a48a..6fbde33 100644
395 --- a/arch/arm/mach-omap1/board-nokia770.c
396 +++ b/arch/arm/mach-omap1/board-nokia770.c
397 @@ -14,6 +14,7 @@
398  #include <linux/platform_device.h>
399  #include <linux/input.h>
400  #include <linux/clk.h>
401 +#include <linux/omapfb.h>
402  
403  #include <linux/spi/spi.h>
404  #include <linux/spi/ads7846.h>
405 @@ -32,7 +33,6 @@
406  #include <mach/keypad.h>
407  #include <mach/common.h>
408  #include <mach/dsp_common.h>
409 -#include <mach/omapfb.h>
410  #include <mach/hwa742.h>
411  #include <mach/lcd_mipid.h>
412  #include <mach/mmc.h>
413 diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
414 index efaf053..60631be 100644
415 --- a/arch/arm/mach-omap2/board-3430sdp.c
416 +++ b/arch/arm/mach-omap2/board-3430sdp.c
417 @@ -36,6 +36,7 @@
418  #include <mach/common.h>
419  #include <mach/dma.h>
420  #include <mach/gpmc.h>
421 +#include <mach/display.h>
422  
423  #include <mach/control.h>
424  #include <mach/keypad.h>
425 @@ -152,31 +153,152 @@ static struct spi_board_info sdp3430_spi_board_info[] __initdata = {
426         },
427  };
428  
429 -static struct platform_device sdp3430_lcd_device = {
430 -       .name           = "sdp2430_lcd",
431 -       .id             = -1,
432 +
433 +#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO       8
434 +#define SDP3430_LCD_PANEL_ENABLE_GPIO          5
435 +
436 +static unsigned backlight_gpio;
437 +static unsigned enable_gpio;
438 +static int lcd_enabled;
439 +static int dvi_enabled;
440 +
441 +static void __init sdp3430_display_init(void)
442 +{
443 +       int r;
444 +
445 +       enable_gpio    = SDP3430_LCD_PANEL_ENABLE_GPIO;
446 +       backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO;
447 +
448 +       r = gpio_request(enable_gpio, "LCD reset");
449 +       if (r) {
450 +               printk(KERN_ERR "failed to get LCD reset GPIO\n");
451 +               goto err0;
452 +       }
453 +
454 +       r = gpio_request(backlight_gpio, "LCD Backlight");
455 +       if (r) {
456 +               printk(KERN_ERR "failed to get LCD backlight GPIO\n");
457 +               goto err1;
458 +       }
459 +
460 +       gpio_direction_output(enable_gpio, 0);
461 +       gpio_direction_output(backlight_gpio, 0);
462 +
463 +       return;
464 +err1:
465 +       gpio_free(enable_gpio);
466 +err0:
467 +       return;
468 +}
469 +
470 +static int sdp3430_panel_enable_lcd(struct omap_dss_device *dssdev)
471 +{
472 +       if (dvi_enabled) {
473 +               printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
474 +               return -EINVAL;
475 +       }
476 +
477 +       gpio_direction_output(enable_gpio, 1);
478 +       gpio_direction_output(backlight_gpio, 1);
479 +
480 +       lcd_enabled = 1;
481 +
482 +       return 0;
483 +}
484 +
485 +static void sdp3430_panel_disable_lcd(struct omap_dss_device *dssdev)
486 +{
487 +       lcd_enabled = 0;
488 +
489 +       gpio_direction_output(enable_gpio, 0);
490 +       gpio_direction_output(backlight_gpio, 0);
491 +}
492 +
493 +static int sdp3430_panel_enable_dvi(struct omap_dss_device *dssdev)
494 +{
495 +       if (lcd_enabled) {
496 +               printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
497 +               return -EINVAL;
498 +       }
499 +
500 +       dvi_enabled = 1;
501 +
502 +       return 0;
503 +}
504 +
505 +static void sdp3430_panel_disable_dvi(struct omap_dss_device *dssdev)
506 +{
507 +       dvi_enabled = 0;
508 +}
509 +
510 +static int sdp3430_panel_enable_tv(struct omap_dss_device *dssdev)
511 +{
512 +       return 0;
513 +}
514 +
515 +static void sdp3430_panel_disable_tv(struct omap_dss_device *dssdev)
516 +{
517 +}
518 +
519 +
520 +static struct omap_dss_device sdp3430_lcd_device = {
521 +       .name                   = "lcd",
522 +       .driver_name            = "sharp_ls_panel",
523 +       .type                   = OMAP_DISPLAY_TYPE_DPI,
524 +       .phy.dpi.data_lines     = 16,
525 +       .platform_enable        = sdp3430_panel_enable_lcd,
526 +       .platform_disable       = sdp3430_panel_disable_lcd,
527  };
528  
529 -static struct regulator_consumer_supply sdp3430_vdac_supply = {
530 -       .supply         = "vdac",
531 -       .dev            = &sdp3430_lcd_device.dev,
532 +static struct omap_dss_device sdp3430_dvi_device = {
533 +       .name                   = "dvi",
534 +       .driver_name            = "generic_panel",
535 +       .type                   = OMAP_DISPLAY_TYPE_DPI,
536 +       .phy.dpi.data_lines     = 24,
537 +       .platform_enable        = sdp3430_panel_enable_dvi,
538 +       .platform_disable       = sdp3430_panel_disable_dvi,
539  };
540  
541 -static struct regulator_consumer_supply sdp3430_vdvi_supply = {
542 -       .supply         = "vdvi",
543 -       .dev            = &sdp3430_lcd_device.dev,
544 +static struct omap_dss_device sdp3430_tv_device = {
545 +       .name                   = "tv",
546 +       .driver_name            = "venc",
547 +       .type                   = OMAP_DISPLAY_TYPE_VENC,
548 +       .phy.venc.type          = OMAP_DSS_VENC_TYPE_SVIDEO,
549 +       .platform_enable        = sdp3430_panel_enable_tv,
550 +       .platform_disable       = sdp3430_panel_disable_tv,
551  };
552  
553 -static struct platform_device *sdp3430_devices[] __initdata = {
554 +
555 +static struct omap_dss_device *sdp3430_dss_devices[] = {
556         &sdp3430_lcd_device,
557 +       &sdp3430_dvi_device,
558 +       &sdp3430_tv_device,
559  };
560  
561 -static struct omap_lcd_config sdp3430_lcd_config __initdata = {
562 -       .ctrl_name      = "internal",
563 +static struct omap_dss_board_info sdp3430_dss_data = {
564 +       .num_devices    = ARRAY_SIZE(sdp3430_dss_devices),
565 +       .devices        = sdp3430_dss_devices,
566 +       .default_device = &sdp3430_lcd_device,
567 +};
568 +
569 +static struct platform_device sdp3430_dss_device = {
570 +       .name           = "omapdss",
571 +       .id             = -1,
572 +       .dev            = {
573 +               .platform_data = &sdp3430_dss_data,
574 +       },
575 +};
576 +
577 +static struct regulator_consumer_supply sdp3430_vdda_dac_supply = {
578 +       .supply         = "vdda_dac",
579 +       .dev            = &sdp3430_dss_device.dev,
580 +};
581 +
582 +static struct platform_device *sdp3430_devices[] __initdata = {
583 +       &sdp3430_dss_device,
584  };
585  
586  static struct omap_board_config_kernel sdp3430_config[] __initdata = {
587 -       { OMAP_TAG_LCD,         &sdp3430_lcd_config },
588  };
589  
590  static void __init omap_3430sdp_init_irq(void)
591 @@ -392,22 +514,34 @@ static struct regulator_init_data sdp3430_vdac = {
592                                         | REGULATOR_CHANGE_STATUS,
593         },
594         .num_consumer_supplies  = 1,
595 -       .consumer_supplies      = &sdp3430_vdac_supply,
596 +       .consumer_supplies      = &sdp3430_vdda_dac_supply,
597  };
598  
599  /* VPLL2 for digital video outputs */
600 +static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = {
601 +       {
602 +               .supply         = "vdvi",
603 +               .dev            = &sdp3430_lcd_device.dev,
604 +       },
605 +       {
606 +               .supply         = "vdds_dsi",
607 +               .dev            = &sdp3430_dss_device.dev,
608 +       }
609 +};
610 +
611  static struct regulator_init_data sdp3430_vpll2 = {
612         .constraints = {
613                 .name                   = "VDVI",
614                 .min_uV                 = 1800000,
615                 .max_uV                 = 1800000,
616 +               .apply_uV               = true,
617                 .valid_modes_mask       = REGULATOR_MODE_NORMAL
618                                         | REGULATOR_MODE_STANDBY,
619                 .valid_ops_mask         = REGULATOR_CHANGE_MODE
620                                         | REGULATOR_CHANGE_STATUS,
621         },
622 -       .num_consumer_supplies  = 1,
623 -       .consumer_supplies      = &sdp3430_vdvi_supply,
624 +       .num_consumer_supplies  = ARRAY_SIZE(sdp3430_vpll2_supplies),
625 +       .consumer_supplies      = sdp3430_vpll2_supplies,
626  };
627  
628  static struct twl4030_platform_data sdp3430_twldata = {
629 @@ -499,6 +633,7 @@ static void __init omap_3430sdp_init(void)
630         omap_serial_init();
631         usb_musb_init();
632         board_smc91x_init();
633 +       sdp3430_display_init();
634         enable_board_wakeup_source();
635  }
636  
637 diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
638 index e2dbedd..8524067 100644
639 --- a/arch/arm/mach-omap2/clock24xx.c
640 +++ b/arch/arm/mach-omap2/clock24xx.c
641 @@ -116,10 +116,10 @@ static struct omap_clk omap24xx_clks[] = {
642         CLK(NULL,       "mdm_ick",      &mdm_ick,       CK_243X),
643         CLK(NULL,       "mdm_osc_ck",   &mdm_osc_ck,    CK_243X),
644         /* DSS domain clocks */
645 -       CLK("omapfb",   "ick",          &dss_ick,       CK_243X | CK_242X),
646 -       CLK("omapfb",   "dss1_fck",     &dss1_fck,      CK_243X | CK_242X),
647 -       CLK("omapfb",   "dss2_fck",     &dss2_fck,      CK_243X | CK_242X),
648 -       CLK("omapfb",   "tv_fck",       &dss_54m_fck,   CK_243X | CK_242X),
649 +       CLK("omapdss",  "ick",          &dss_ick,       CK_243X | CK_242X),
650 +       CLK("omapdss",  "dss1_fck",     &dss1_fck,      CK_243X | CK_242X),
651 +       CLK("omapdss",  "dss2_fck",     &dss2_fck,      CK_243X | CK_242X),
652 +       CLK("omapdss",  "tv_fck",       &dss_54m_fck,   CK_243X | CK_242X),
653         /* L3 domain clocks */
654         CLK(NULL,       "core_l3_ck",   &core_l3_ck,    CK_243X | CK_242X),
655         CLK(NULL,       "ssi_fck",      &ssi_ssr_sst_fck, CK_243X | CK_242X),
656 diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
657 index 489556e..0a7e9ac 100644
658 --- a/arch/arm/mach-omap2/clock34xx.c
659 +++ b/arch/arm/mach-omap2/clock34xx.c
660 @@ -236,13 +236,13 @@ static struct omap_clk omap34xx_clks[] = {
661         CLK("omap_rng", "ick",          &rng_ick,       CK_343X),
662         CLK(NULL,       "sha11_ick",    &sha11_ick,     CK_343X),
663         CLK(NULL,       "des1_ick",     &des1_ick,      CK_343X),
664 -       CLK("omapfb",   "dss1_fck",     &dss1_alwon_fck_3430es1, CK_3430ES1),
665 -       CLK("omapfb",   "dss1_fck",     &dss1_alwon_fck_3430es2, CK_3430ES2),
666 -       CLK("omapfb",   "tv_fck",       &dss_tv_fck,    CK_343X),
667 -       CLK("omapfb",   "video_fck",    &dss_96m_fck,   CK_343X),
668 -       CLK("omapfb",   "dss2_fck",     &dss2_alwon_fck, CK_343X),
669 -       CLK("omapfb",   "ick",          &dss_ick_3430es1,       CK_3430ES1),
670 -       CLK("omapfb",   "ick",          &dss_ick_3430es2,       CK_3430ES2),
671 +       CLK("omapdss",  "dss1_fck",     &dss1_alwon_fck_3430es1, CK_3430ES1),
672 +       CLK("omapdss",  "dss1_fck",     &dss1_alwon_fck_3430es2, CK_3430ES2),
673 +       CLK("omapdss",  "tv_fck",       &dss_tv_fck,    CK_343X),
674 +       CLK("omapdss",  "video_fck",    &dss_96m_fck,   CK_343X),
675 +       CLK("omapdss",  "dss2_fck",     &dss2_alwon_fck, CK_343X),
676 +       CLK("omapdss",  "ick",          &dss_ick_3430es1,       CK_3430ES1),
677 +       CLK("omapdss",  "ick",          &dss_ick_3430es2,       CK_3430ES2),
678         CLK(NULL,       "cam_mclk",     &cam_mclk,      CK_343X),
679         CLK(NULL,       "cam_ick",      &cam_ick,       CK_343X),
680         CLK(NULL,       "csi2_96m_fck", &csi2_96m_fck,  CK_343X),
681 diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
682 index e3a3bad..adbb905 100644
683 --- a/arch/arm/mach-omap2/io.c
684 +++ b/arch/arm/mach-omap2/io.c
685 @@ -22,17 +22,18 @@
686  #include <linux/init.h>
687  #include <linux/io.h>
688  #include <linux/clk.h>
689 +#include <linux/omapfb.h>
690  
691  #include <asm/tlb.h>
692  
693  #include <asm/mach/map.h>
694  
695  #include <mach/mux.h>
696 -#include <mach/omapfb.h>
697  #include <mach/sram.h>
698  #include <mach/sdrc.h>
699  #include <mach/gpmc.h>
700  #include <mach/serial.h>
701 +#include <mach/vram.h>
702  
703  #ifndef CONFIG_ARCH_OMAP4      /* FIXME: Remove this once clkdev is ready */
704  #include "clock.h"
705 @@ -246,6 +247,7 @@ void __init omap2_map_common_io(void)
706         omap2_check_revision();
707         omap_sram_init();
708         omapfb_reserve_sdram();
709 +       omap_vram_reserve_sdram();
710  }
711  
712  /*
713 diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c
714 index 9e3bd4f..6a5a2c5 100644
715 --- a/arch/arm/mach-omap2/sdrc.c
716 +++ b/arch/arm/mach-omap2/sdrc.c
717 @@ -133,3 +133,19 @@ void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
718                 (1 << SDRC_POWER_PAGEPOLICY_SHIFT);
719         sdrc_write_reg(l, SDRC_POWER);
720  }
721 +
722 +void omap2_sms_write_rot_control(u32 val, unsigned ctx)
723 +{
724 +       sms_write_reg(val, SMS_ROT_CONTROL(ctx));
725 +}
726 +
727 +void omap2_sms_write_rot_size(u32 val, unsigned ctx)
728 +{
729 +       sms_write_reg(val, SMS_ROT_SIZE(ctx));
730 +}
731 +
732 +void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
733 +{
734 +       sms_write_reg(val, SMS_ROT_PHYSICAL_BA(ctx));
735 +}
736 +
737 diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
738 index 3746222..70fbeae 100644
739 --- a/arch/arm/plat-omap/fb.c
740 +++ b/arch/arm/plat-omap/fb.c
741 @@ -28,13 +28,13 @@
742  #include <linux/platform_device.h>
743  #include <linux/bootmem.h>
744  #include <linux/io.h>
745 +#include <linux/omapfb.h>
746  
747  #include <mach/hardware.h>
748  #include <asm/mach/map.h>
749  
750  #include <mach/board.h>
751  #include <mach/sram.h>
752 -#include <mach/omapfb.h>
753  
754  #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
755  
756 @@ -327,7 +327,33 @@ static inline int omap_init_fb(void)
757  
758  arch_initcall(omap_init_fb);
759  
760 -#else
761 +#elif defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
762 +
763 +static u64 omap_fb_dma_mask = ~(u32)0;
764 +static struct omapfb_platform_data omapfb_config;
765 +
766 +static struct platform_device omap_fb_device = {
767 +       .name           = "omapfb",
768 +       .id             = -1,
769 +       .dev = {
770 +               .dma_mask               = &omap_fb_dma_mask,
771 +               .coherent_dma_mask      = ~(u32)0,
772 +               .platform_data          = &omapfb_config,
773 +       },
774 +       .num_resources = 0,
775 +};
776 +
777 +void omapfb_set_platform_data(struct omapfb_platform_data *data)
778 +{
779 +       omapfb_config = *data;
780 +}
781 +
782 +static inline int omap_init_fb(void)
783 +{
784 +       return platform_device_register(&omap_fb_device);
785 +}
786 +
787 +arch_initcall(omap_init_fb);
788  
789  void omapfb_reserve_sdram(void) {}
790  unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
791 @@ -339,5 +365,16 @@ unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
792         return 0;
793  }
794  
795 +#else
796 +
797 +void omapfb_reserve_sdram(void) {}
798 +unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
799 +                                 unsigned long sram_vstart,
800 +                                 unsigned long sram_size,
801 +                                 unsigned long start_avail,
802 +                                 unsigned long size_avail)
803 +{
804 +       return 0;
805 +}
806  
807  #endif
808 diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
809 new file mode 100644
810 index 0000000..4c7422e
811 --- /dev/null
812 +++ b/arch/arm/plat-omap/include/mach/display.h
813 @@ -0,0 +1,540 @@
814 +/*
815 + * linux/include/asm-arm/arch-omap/display.h
816 + *
817 + * Copyright (C) 2008 Nokia Corporation
818 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
819 + *
820 + * This program is free software; you can redistribute it and/or modify it
821 + * under the terms of the GNU General Public License version 2 as published by
822 + * the Free Software Foundation.
823 + *
824 + * This program is distributed in the hope that it will be useful, but WITHOUT
825 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
826 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
827 + * more details.
828 + *
829 + * You should have received a copy of the GNU General Public License along with
830 + * this program.  If not, see <http://www.gnu.org/licenses/>.
831 + */
832 +
833 +#ifndef __ASM_ARCH_OMAP_DISPLAY_H
834 +#define __ASM_ARCH_OMAP_DISPLAY_H
835 +
836 +#include <linux/list.h>
837 +#include <linux/kobject.h>
838 +#include <linux/device.h>
839 +#include <asm/atomic.h>
840 +
841 +#define DISPC_IRQ_FRAMEDONE            (1 << 0)
842 +#define DISPC_IRQ_VSYNC                        (1 << 1)
843 +#define DISPC_IRQ_EVSYNC_EVEN          (1 << 2)
844 +#define DISPC_IRQ_EVSYNC_ODD           (1 << 3)
845 +#define DISPC_IRQ_ACBIAS_COUNT_STAT    (1 << 4)
846 +#define DISPC_IRQ_PROG_LINE_NUM                (1 << 5)
847 +#define DISPC_IRQ_GFX_FIFO_UNDERFLOW   (1 << 6)
848 +#define DISPC_IRQ_GFX_END_WIN          (1 << 7)
849 +#define DISPC_IRQ_PAL_GAMMA_MASK       (1 << 8)
850 +#define DISPC_IRQ_OCP_ERR              (1 << 9)
851 +#define DISPC_IRQ_VID1_FIFO_UNDERFLOW  (1 << 10)
852 +#define DISPC_IRQ_VID1_END_WIN         (1 << 11)
853 +#define DISPC_IRQ_VID2_FIFO_UNDERFLOW  (1 << 12)
854 +#define DISPC_IRQ_VID2_END_WIN         (1 << 13)
855 +#define DISPC_IRQ_SYNC_LOST            (1 << 14)
856 +#define DISPC_IRQ_SYNC_LOST_DIGIT      (1 << 15)
857 +#define DISPC_IRQ_WAKEUP               (1 << 16)
858 +
859 +struct omap_dss_device;
860 +struct omap_overlay_manager;
861 +
862 +enum omap_display_type {
863 +       OMAP_DISPLAY_TYPE_NONE          = 0,
864 +       OMAP_DISPLAY_TYPE_DPI           = 1 << 0,
865 +       OMAP_DISPLAY_TYPE_DBI           = 1 << 1,
866 +       OMAP_DISPLAY_TYPE_SDI           = 1 << 2,
867 +       OMAP_DISPLAY_TYPE_DSI           = 1 << 3,
868 +       OMAP_DISPLAY_TYPE_VENC          = 1 << 4,
869 +};
870 +
871 +enum omap_plane {
872 +       OMAP_DSS_GFX    = 0,
873 +       OMAP_DSS_VIDEO1 = 1,
874 +       OMAP_DSS_VIDEO2 = 2
875 +};
876 +
877 +enum omap_channel {
878 +       OMAP_DSS_CHANNEL_LCD    = 0,
879 +       OMAP_DSS_CHANNEL_DIGIT  = 1,
880 +};
881 +
882 +enum omap_color_mode {
883 +       OMAP_DSS_COLOR_CLUT1    = 1 << 0,  /* BITMAP 1 */
884 +       OMAP_DSS_COLOR_CLUT2    = 1 << 1,  /* BITMAP 2 */
885 +       OMAP_DSS_COLOR_CLUT4    = 1 << 2,  /* BITMAP 4 */
886 +       OMAP_DSS_COLOR_CLUT8    = 1 << 3,  /* BITMAP 8 */
887 +       OMAP_DSS_COLOR_RGB12U   = 1 << 4,  /* RGB12, 16-bit container */
888 +       OMAP_DSS_COLOR_ARGB16   = 1 << 5,  /* ARGB16 */
889 +       OMAP_DSS_COLOR_RGB16    = 1 << 6,  /* RGB16 */
890 +       OMAP_DSS_COLOR_RGB24U   = 1 << 7,  /* RGB24, 32-bit container */
891 +       OMAP_DSS_COLOR_RGB24P   = 1 << 8,  /* RGB24, 24-bit container */
892 +       OMAP_DSS_COLOR_YUV2     = 1 << 9,  /* YUV2 4:2:2 co-sited */
893 +       OMAP_DSS_COLOR_UYVY     = 1 << 10, /* UYVY 4:2:2 co-sited */
894 +       OMAP_DSS_COLOR_ARGB32   = 1 << 11, /* ARGB32 */
895 +       OMAP_DSS_COLOR_RGBA32   = 1 << 12, /* RGBA32 */
896 +       OMAP_DSS_COLOR_RGBX32   = 1 << 13, /* RGBx32 */
897 +
898 +       OMAP_DSS_COLOR_GFX_OMAP3 =
899 +               OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
900 +               OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
901 +               OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
902 +               OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
903 +               OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
904 +               OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
905 +
906 +       OMAP_DSS_COLOR_VID_OMAP3 =
907 +               OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
908 +               OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
909 +               OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
910 +               OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 |
911 +               OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
912 +};
913 +
914 +enum omap_lcd_display_type {
915 +       OMAP_DSS_LCD_DISPLAY_STN,
916 +       OMAP_DSS_LCD_DISPLAY_TFT,
917 +};
918 +
919 +enum omap_dss_load_mode {
920 +       OMAP_DSS_LOAD_CLUT_AND_FRAME    = 0,
921 +       OMAP_DSS_LOAD_CLUT_ONLY         = 1,
922 +       OMAP_DSS_LOAD_FRAME_ONLY        = 2,
923 +       OMAP_DSS_LOAD_CLUT_ONCE_FRAME   = 3,
924 +};
925 +
926 +enum omap_dss_trans_key_type {
927 +       OMAP_DSS_COLOR_KEY_GFX_DST = 0,
928 +       OMAP_DSS_COLOR_KEY_VID_SRC = 1,
929 +};
930 +
931 +enum omap_rfbi_te_mode {
932 +       OMAP_DSS_RFBI_TE_MODE_1 = 1,
933 +       OMAP_DSS_RFBI_TE_MODE_2 = 2,
934 +};
935 +
936 +enum omap_panel_config {
937 +       OMAP_DSS_LCD_IVS                = 1<<0,
938 +       OMAP_DSS_LCD_IHS                = 1<<1,
939 +       OMAP_DSS_LCD_IPC                = 1<<2,
940 +       OMAP_DSS_LCD_IEO                = 1<<3,
941 +       OMAP_DSS_LCD_RF                 = 1<<4,
942 +       OMAP_DSS_LCD_ONOFF              = 1<<5,
943 +
944 +       OMAP_DSS_LCD_TFT                = 1<<20,
945 +};
946 +
947 +enum omap_dss_venc_type {
948 +       OMAP_DSS_VENC_TYPE_COMPOSITE,
949 +       OMAP_DSS_VENC_TYPE_SVIDEO,
950 +};
951 +
952 +enum omap_display_caps {
953 +       OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0,
954 +};
955 +
956 +enum omap_dss_update_mode {
957 +       OMAP_DSS_UPDATE_DISABLED = 0,
958 +       OMAP_DSS_UPDATE_AUTO,
959 +       OMAP_DSS_UPDATE_MANUAL,
960 +};
961 +
962 +enum omap_dss_display_state {
963 +       OMAP_DSS_DISPLAY_DISABLED = 0,
964 +       OMAP_DSS_DISPLAY_ACTIVE,
965 +       OMAP_DSS_DISPLAY_SUSPENDED,
966 +};
967 +
968 +/* XXX perhaps this should be removed */
969 +enum omap_dss_overlay_managers {
970 +       OMAP_DSS_OVL_MGR_LCD,
971 +       OMAP_DSS_OVL_MGR_TV,
972 +};
973 +
974 +enum omap_dss_rotation_type {
975 +       OMAP_DSS_ROT_DMA = 0,
976 +       OMAP_DSS_ROT_VRFB = 1,
977 +};
978 +
979 +enum omap_overlay_caps {
980 +       OMAP_DSS_OVL_CAP_SCALE = 1 << 0,
981 +       OMAP_DSS_OVL_CAP_DISPC = 1 << 1,
982 +};
983 +
984 +enum omap_overlay_manager_caps {
985 +       OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0,
986 +};
987 +
988 +/* RFBI */
989 +
990 +struct rfbi_timings {
991 +       int cs_on_time;
992 +       int cs_off_time;
993 +       int we_on_time;
994 +       int we_off_time;
995 +       int re_on_time;
996 +       int re_off_time;
997 +       int we_cycle_time;
998 +       int re_cycle_time;
999 +       int cs_pulse_width;
1000 +       int access_time;
1001 +
1002 +       int clk_div;
1003 +
1004 +       u32 tim[5];             /* set by rfbi_convert_timings() */
1005 +
1006 +       int converted;
1007 +};
1008 +
1009 +void omap_rfbi_write_command(const void *buf, u32 len);
1010 +void omap_rfbi_read_data(void *buf, u32 len);
1011 +void omap_rfbi_write_data(const void *buf, u32 len);
1012 +void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
1013 +               u16 x, u16 y,
1014 +               u16 w, u16 h);
1015 +int omap_rfbi_enable_te(bool enable, unsigned line);
1016 +int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
1017 +                            unsigned hs_pulse_time, unsigned vs_pulse_time,
1018 +                            int hs_pol_inv, int vs_pol_inv, int extif_div);
1019 +
1020 +/* DSI */
1021 +void dsi_bus_lock(void);
1022 +void dsi_bus_unlock(void);
1023 +int dsi_vc_dcs_write(int channel, u8 *data, int len);
1024 +int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len);
1025 +int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen);
1026 +int dsi_vc_set_max_rx_packet_size(int channel, u16 len);
1027 +int dsi_vc_send_null(int channel);
1028 +int dsi_vc_send_bta_sync(int channel);
1029 +
1030 +/* Board specific data */
1031 +struct omap_dss_board_info {
1032 +       int (*get_last_off_on_transaction_id)(struct device *dev);
1033 +       int num_devices;
1034 +       struct omap_dss_device **devices;
1035 +       struct omap_dss_device *default_device;
1036 +};
1037 +
1038 +struct omap_video_timings {
1039 +       /* Unit: pixels */
1040 +       u16 x_res;
1041 +       /* Unit: pixels */
1042 +       u16 y_res;
1043 +       /* Unit: KHz */
1044 +       u32 pixel_clock;
1045 +       /* Unit: pixel clocks */
1046 +       u16 hsw;        /* Horizontal synchronization pulse width */
1047 +       /* Unit: pixel clocks */
1048 +       u16 hfp;        /* Horizontal front porch */
1049 +       /* Unit: pixel clocks */
1050 +       u16 hbp;        /* Horizontal back porch */
1051 +       /* Unit: line clocks */
1052 +       u16 vsw;        /* Vertical synchronization pulse width */
1053 +       /* Unit: line clocks */
1054 +       u16 vfp;        /* Vertical front porch */
1055 +       /* Unit: line clocks */
1056 +       u16 vbp;        /* Vertical back porch */
1057 +};
1058 +
1059 +#ifdef CONFIG_OMAP2_DSS_VENC
1060 +/* Hardcoded timings for tv modes. Venc only uses these to
1061 + * identify the mode, and does not actually use the configs
1062 + * itself. However, the configs should be something that
1063 + * a normal monitor can also show */
1064 +const extern struct omap_video_timings omap_dss_pal_timings;
1065 +const extern struct omap_video_timings omap_dss_ntsc_timings;
1066 +#endif
1067 +
1068 +struct omap_overlay_info {
1069 +       bool enabled;
1070 +
1071 +       u32 paddr;
1072 +       void __iomem *vaddr;
1073 +       u16 screen_width;
1074 +       u16 width;
1075 +       u16 height;
1076 +       enum omap_color_mode color_mode;
1077 +       u8 rotation;
1078 +       enum omap_dss_rotation_type rotation_type;
1079 +       bool mirror;
1080 +
1081 +       u16 pos_x;
1082 +       u16 pos_y;
1083 +       u16 out_width;  /* if 0, out_width == width */
1084 +       u16 out_height; /* if 0, out_height == height */
1085 +       u8 global_alpha;
1086 +};
1087 +
1088 +struct omap_overlay {
1089 +       struct kobject kobj;
1090 +       struct list_head list;
1091 +
1092 +       /* static fields */
1093 +       const char *name;
1094 +       int id;
1095 +       enum omap_color_mode supported_modes;
1096 +       enum omap_overlay_caps caps;
1097 +
1098 +       /* dynamic fields */
1099 +       struct omap_overlay_manager *manager;
1100 +       struct omap_overlay_info info;
1101 +
1102 +       /* if true, info has been changed, but not applied() yet */
1103 +       bool info_dirty;
1104 +
1105 +       int (*set_manager)(struct omap_overlay *ovl,
1106 +               struct omap_overlay_manager *mgr);
1107 +       int (*unset_manager)(struct omap_overlay *ovl);
1108 +
1109 +       int (*set_overlay_info)(struct omap_overlay *ovl,
1110 +                       struct omap_overlay_info *info);
1111 +       void (*get_overlay_info)(struct omap_overlay *ovl,
1112 +                       struct omap_overlay_info *info);
1113 +
1114 +       int (*wait_for_go)(struct omap_overlay *ovl);
1115 +};
1116 +
1117 +struct omap_overlay_manager_info {
1118 +       u32 default_color;
1119 +
1120 +       enum omap_dss_trans_key_type trans_key_type;
1121 +       u32 trans_key;
1122 +       bool trans_enabled;
1123 +
1124 +       bool alpha_enabled;
1125 +};
1126 +
1127 +struct omap_overlay_manager {
1128 +       struct kobject kobj;
1129 +       struct list_head list;
1130 +
1131 +       /* static fields */
1132 +       const char *name;
1133 +       int id;
1134 +       enum omap_overlay_manager_caps caps;
1135 +       int num_overlays;
1136 +       struct omap_overlay **overlays;
1137 +       enum omap_display_type supported_displays;
1138 +
1139 +       /* dynamic fields */
1140 +       struct omap_dss_device *device;
1141 +       struct omap_overlay_manager_info info;
1142 +
1143 +       bool device_changed;
1144 +       /* if true, info has been changed but not applied() yet */
1145 +       bool info_dirty;
1146 +
1147 +       int (*set_device)(struct omap_overlay_manager *mgr,
1148 +               struct omap_dss_device *dssdev);
1149 +       int (*unset_device)(struct omap_overlay_manager *mgr);
1150 +
1151 +       int (*set_manager_info)(struct omap_overlay_manager *mgr,
1152 +                       struct omap_overlay_manager_info *info);
1153 +       void (*get_manager_info)(struct omap_overlay_manager *mgr,
1154 +                       struct omap_overlay_manager_info *info);
1155 +
1156 +       int (*apply)(struct omap_overlay_manager *mgr);
1157 +       int (*wait_for_go)(struct omap_overlay_manager *mgr);
1158 +};
1159 +
1160 +struct omap_dss_device {
1161 +       struct device dev;
1162 +
1163 +       enum omap_display_type type;
1164 +
1165 +       union {
1166 +               struct {
1167 +                       u8 data_lines;
1168 +               } dpi;
1169 +
1170 +               struct {
1171 +                       u8 channel;
1172 +                       u8 data_lines;
1173 +               } rfbi;
1174 +
1175 +               struct {
1176 +                       u8 datapairs;
1177 +               } sdi;
1178 +
1179 +               struct {
1180 +                       u8 clk_lane;
1181 +                       u8 clk_pol;
1182 +                       u8 data1_lane;
1183 +                       u8 data1_pol;
1184 +                       u8 data2_lane;
1185 +                       u8 data2_pol;
1186 +                       unsigned long lp_clk_hz;
1187 +                       unsigned long ddr_clk_hz;
1188 +
1189 +                       bool ext_te;
1190 +                       u8 ext_te_gpio;
1191 +               } dsi;
1192 +
1193 +               struct {
1194 +                       enum omap_dss_venc_type type;
1195 +                       bool invert_polarity;
1196 +               } venc;
1197 +       } phy;
1198 +
1199 +       struct {
1200 +               struct omap_video_timings timings;
1201 +
1202 +               int acbi;       /* ac-bias pin transitions per interrupt */
1203 +               /* Unit: line clocks */
1204 +               int acb;        /* ac-bias pin frequency */
1205 +
1206 +               enum omap_panel_config config;
1207 +
1208 +               u8 recommended_bpp;
1209 +
1210 +               struct omap_dss_device *ctrl;
1211 +       } panel;
1212 +
1213 +       struct {
1214 +               u8 pixel_size;
1215 +               struct rfbi_timings rfbi_timings;
1216 +               struct omap_dss_device *panel;
1217 +       } ctrl;
1218 +
1219 +       int reset_gpio;
1220 +
1221 +       int max_backlight_level;
1222 +
1223 +       const char *name;
1224 +
1225 +       /* used to match device to driver */
1226 +       const char *driver_name;
1227 +
1228 +       void *data;
1229 +
1230 +       struct omap_dss_driver *driver;
1231 +
1232 +       /* helper variable for driver suspend/resume */
1233 +       bool activate_after_resume;
1234 +
1235 +       enum omap_display_caps caps;
1236 +
1237 +       struct omap_overlay_manager *manager;
1238 +
1239 +       enum omap_dss_display_state state;
1240 +
1241 +       int (*enable)(struct omap_dss_device *dssdev);
1242 +       void (*disable)(struct omap_dss_device *dssdev);
1243 +
1244 +       int (*suspend)(struct omap_dss_device *dssdev);
1245 +       int (*resume)(struct omap_dss_device *dssdev);
1246 +
1247 +       void (*get_resolution)(struct omap_dss_device *dssdev,
1248 +                       u16 *xres, u16 *yres);
1249 +       int (*get_recommended_bpp)(struct omap_dss_device *dssdev);
1250 +
1251 +       int (*check_timings)(struct omap_dss_device *dssdev,
1252 +                       struct omap_video_timings *timings);
1253 +       void (*set_timings)(struct omap_dss_device *dssdev,
1254 +                       struct omap_video_timings *timings);
1255 +       void (*get_timings)(struct omap_dss_device *dssdev,
1256 +                       struct omap_video_timings *timings);
1257 +       int (*update)(struct omap_dss_device *dssdev,
1258 +                              u16 x, u16 y, u16 w, u16 h);
1259 +       int (*sync)(struct omap_dss_device *dssdev);
1260 +       int (*wait_vsync)(struct omap_dss_device *dssdev);
1261 +
1262 +       int (*set_update_mode)(struct omap_dss_device *dssdev,
1263 +                       enum omap_dss_update_mode);
1264 +       enum omap_dss_update_mode (*get_update_mode)
1265 +               (struct omap_dss_device *dssdev);
1266 +
1267 +       int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
1268 +       int (*get_te)(struct omap_dss_device *dssdev);
1269 +
1270 +       u8 (*get_rotate)(struct omap_dss_device *dssdev);
1271 +       int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
1272 +
1273 +       bool (*get_mirror)(struct omap_dss_device *dssdev);
1274 +       int (*set_mirror)(struct omap_dss_device *dssdev, bool enable);
1275 +
1276 +       int (*run_test)(struct omap_dss_device *dssdev, int test);
1277 +       int (*memory_read)(struct omap_dss_device *dssdev,
1278 +                       void *buf, size_t size,
1279 +                       u16 x, u16 y, u16 w, u16 h);
1280 +
1281 +       int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
1282 +       u32 (*get_wss)(struct omap_dss_device *dssdev);
1283 +
1284 +       /* platform specific  */
1285 +       int (*platform_enable)(struct omap_dss_device *dssdev);
1286 +       void (*platform_disable)(struct omap_dss_device *dssdev);
1287 +       int (*set_backlight)(struct omap_dss_device *dssdev, int level);
1288 +       int (*get_backlight)(struct omap_dss_device *dssdev);
1289 +};
1290 +
1291 +struct omap_dss_driver {
1292 +       struct device_driver driver;
1293 +
1294 +       int (*probe)(struct omap_dss_device *);
1295 +       void (*remove)(struct omap_dss_device *);
1296 +
1297 +       int (*enable)(struct omap_dss_device *display);
1298 +       void (*disable)(struct omap_dss_device *display);
1299 +       int (*suspend)(struct omap_dss_device *display);
1300 +       int (*resume)(struct omap_dss_device *display);
1301 +       int (*run_test)(struct omap_dss_device *display, int test);
1302 +
1303 +       void (*setup_update)(struct omap_dss_device *dssdev,
1304 +                       u16 x, u16 y, u16 w, u16 h);
1305 +
1306 +       int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
1307 +       int (*wait_for_te)(struct omap_dss_device *dssdev);
1308 +
1309 +       u8 (*get_rotate)(struct omap_dss_device *dssdev);
1310 +       int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
1311 +
1312 +       bool (*get_mirror)(struct omap_dss_device *dssdev);
1313 +       int (*set_mirror)(struct omap_dss_device *dssdev, bool enable);
1314 +
1315 +       int (*memory_read)(struct omap_dss_device *dssdev,
1316 +                       void *buf, size_t size,
1317 +                       u16 x, u16 y, u16 w, u16 h);
1318 +};
1319 +
1320 +int omap_dss_register_driver(struct omap_dss_driver *);
1321 +void omap_dss_unregister_driver(struct omap_dss_driver *);
1322 +
1323 +int omap_dss_register_device(struct omap_dss_device *);
1324 +void omap_dss_unregister_device(struct omap_dss_device *);
1325 +
1326 +void omap_dss_get_device(struct omap_dss_device *dssdev);
1327 +void omap_dss_put_device(struct omap_dss_device *dssdev);
1328 +#define for_each_dss_dev(d) while ((d = omap_dss_get_next_device(d)) != NULL)
1329 +struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from);
1330 +struct omap_dss_device *omap_dss_find_device(void *data,
1331 +               int (*match)(struct omap_dss_device *dssdev, void *data));
1332 +
1333 +int omap_dss_start_device(struct omap_dss_device *dssdev);
1334 +void omap_dss_stop_device(struct omap_dss_device *dssdev);
1335 +
1336 +int omap_dss_get_num_overlay_managers(void);
1337 +struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
1338 +
1339 +int omap_dss_get_num_overlays(void);
1340 +struct omap_overlay *omap_dss_get_overlay(int num);
1341 +
1342 +typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
1343 +int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
1344 +int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
1345 +
1346 +int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout);
1347 +int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
1348 +               unsigned long timeout);
1349 +
1350 +#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
1351 +#define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
1352 +
1353 +#endif
1354 diff --git a/arch/arm/plat-omap/include/mach/omapfb.h b/arch/arm/plat-omap/include/mach/omapfb.h
1355 deleted file mode 100644
1356 index b226bdf..0000000
1357 --- a/arch/arm/plat-omap/include/mach/omapfb.h
1358 +++ /dev/null
1359 @@ -1,398 +0,0 @@
1360 -/*
1361 - * File: arch/arm/plat-omap/include/mach/omapfb.h
1362 - *
1363 - * Framebuffer driver for TI OMAP boards
1364 - *
1365 - * Copyright (C) 2004 Nokia Corporation
1366 - * Author: Imre Deak <imre.deak@nokia.com>
1367 - *
1368 - * This program is free software; you can redistribute it and/or modify it
1369 - * under the terms of the GNU General Public License as published by the
1370 - * Free Software Foundation; either version 2 of the License, or (at your
1371 - * option) any later version.
1372 - *
1373 - * This program is distributed in the hope that it will be useful, but
1374 - * WITHOUT ANY WARRANTY; without even the implied warranty of
1375 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1376 - * General Public License for more details.
1377 - *
1378 - * You should have received a copy of the GNU General Public License along
1379 - * with this program; if not, write to the Free Software Foundation, Inc.,
1380 - * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
1381 - */
1382 -
1383 -#ifndef __OMAPFB_H
1384 -#define __OMAPFB_H
1385 -
1386 -#include <asm/ioctl.h>
1387 -#include <asm/types.h>
1388 -
1389 -/* IOCTL commands. */
1390 -
1391 -#define OMAP_IOW(num, dtype)   _IOW('O', num, dtype)
1392 -#define OMAP_IOR(num, dtype)   _IOR('O', num, dtype)
1393 -#define OMAP_IOWR(num, dtype)  _IOWR('O', num, dtype)
1394 -#define OMAP_IO(num)           _IO('O', num)
1395 -
1396 -#define OMAPFB_MIRROR          OMAP_IOW(31, int)
1397 -#define OMAPFB_SYNC_GFX                OMAP_IO(37)
1398 -#define OMAPFB_VSYNC           OMAP_IO(38)
1399 -#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int)
1400 -#define OMAPFB_GET_CAPS                OMAP_IOR(42, struct omapfb_caps)
1401 -#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int)
1402 -#define OMAPFB_LCD_TEST                OMAP_IOW(45, int)
1403 -#define OMAPFB_CTRL_TEST       OMAP_IOW(46, int)
1404 -#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old)
1405 -#define OMAPFB_SET_COLOR_KEY   OMAP_IOW(50, struct omapfb_color_key)
1406 -#define OMAPFB_GET_COLOR_KEY   OMAP_IOW(51, struct omapfb_color_key)
1407 -#define OMAPFB_SETUP_PLANE     OMAP_IOW(52, struct omapfb_plane_info)
1408 -#define OMAPFB_QUERY_PLANE     OMAP_IOW(53, struct omapfb_plane_info)
1409 -#define OMAPFB_UPDATE_WINDOW   OMAP_IOW(54, struct omapfb_update_window)
1410 -#define OMAPFB_SETUP_MEM       OMAP_IOW(55, struct omapfb_mem_info)
1411 -#define OMAPFB_QUERY_MEM       OMAP_IOW(56, struct omapfb_mem_info)
1412 -
1413 -#define OMAPFB_CAPS_GENERIC_MASK       0x00000fff
1414 -#define OMAPFB_CAPS_LCDC_MASK          0x00fff000
1415 -#define OMAPFB_CAPS_PANEL_MASK         0xff000000
1416 -
1417 -#define OMAPFB_CAPS_MANUAL_UPDATE      0x00001000
1418 -#define OMAPFB_CAPS_TEARSYNC           0x00002000
1419 -#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000
1420 -#define OMAPFB_CAPS_PLANE_SCALE                0x00008000
1421 -#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE        0x00010000
1422 -#define OMAPFB_CAPS_WINDOW_SCALE       0x00020000
1423 -#define OMAPFB_CAPS_WINDOW_OVERLAY     0x00040000
1424 -#define OMAPFB_CAPS_WINDOW_ROTATE      0x00080000
1425 -#define OMAPFB_CAPS_SET_BACKLIGHT      0x01000000
1426 -
1427 -/* Values from DSP must map to lower 16-bits */
1428 -#define OMAPFB_FORMAT_MASK             0x00ff
1429 -#define OMAPFB_FORMAT_FLAG_DOUBLE      0x0100
1430 -#define OMAPFB_FORMAT_FLAG_TEARSYNC    0x0200
1431 -#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400
1432 -#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY      0x0800
1433 -#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY     0x1000
1434 -
1435 -#define OMAPFB_EVENT_READY     1
1436 -#define OMAPFB_EVENT_DISABLED  2
1437 -
1438 -#define OMAPFB_MEMTYPE_SDRAM           0
1439 -#define OMAPFB_MEMTYPE_SRAM            1
1440 -#define OMAPFB_MEMTYPE_MAX             1
1441 -
1442 -enum omapfb_color_format {
1443 -       OMAPFB_COLOR_RGB565 = 0,
1444 -       OMAPFB_COLOR_YUV422,
1445 -       OMAPFB_COLOR_YUV420,
1446 -       OMAPFB_COLOR_CLUT_8BPP,
1447 -       OMAPFB_COLOR_CLUT_4BPP,
1448 -       OMAPFB_COLOR_CLUT_2BPP,
1449 -       OMAPFB_COLOR_CLUT_1BPP,
1450 -       OMAPFB_COLOR_RGB444,
1451 -       OMAPFB_COLOR_YUY422,
1452 -};
1453 -
1454 -struct omapfb_update_window {
1455 -       __u32 x, y;
1456 -       __u32 width, height;
1457 -       __u32 format;
1458 -       __u32 out_x, out_y;
1459 -       __u32 out_width, out_height;
1460 -       __u32 reserved[8];
1461 -};
1462 -
1463 -struct omapfb_update_window_old {
1464 -       __u32 x, y;
1465 -       __u32 width, height;
1466 -       __u32 format;
1467 -};
1468 -
1469 -enum omapfb_plane {
1470 -       OMAPFB_PLANE_GFX = 0,
1471 -       OMAPFB_PLANE_VID1,
1472 -       OMAPFB_PLANE_VID2,
1473 -};
1474 -
1475 -enum omapfb_channel_out {
1476 -       OMAPFB_CHANNEL_OUT_LCD = 0,
1477 -       OMAPFB_CHANNEL_OUT_DIGIT,
1478 -};
1479 -
1480 -struct omapfb_plane_info {
1481 -       __u32 pos_x;
1482 -       __u32 pos_y;
1483 -       __u8  enabled;
1484 -       __u8  channel_out;
1485 -       __u8  mirror;
1486 -       __u8  reserved1;
1487 -       __u32 out_width;
1488 -       __u32 out_height;
1489 -       __u32 reserved2[12];
1490 -};
1491 -
1492 -struct omapfb_mem_info {
1493 -       __u32 size;
1494 -       __u8  type;
1495 -       __u8  reserved[3];
1496 -};
1497 -
1498 -struct omapfb_caps {
1499 -       __u32 ctrl;
1500 -       __u32 plane_color;
1501 -       __u32 wnd_color;
1502 -};
1503 -
1504 -enum omapfb_color_key_type {
1505 -       OMAPFB_COLOR_KEY_DISABLED = 0,
1506 -       OMAPFB_COLOR_KEY_GFX_DST,
1507 -       OMAPFB_COLOR_KEY_VID_SRC,
1508 -};
1509 -
1510 -struct omapfb_color_key {
1511 -       __u8  channel_out;
1512 -       __u32 background;
1513 -       __u32 trans_key;
1514 -       __u8  key_type;
1515 -};
1516 -
1517 -enum omapfb_update_mode {
1518 -       OMAPFB_UPDATE_DISABLED = 0,
1519 -       OMAPFB_AUTO_UPDATE,
1520 -       OMAPFB_MANUAL_UPDATE
1521 -};
1522 -
1523 -#ifdef __KERNEL__
1524 -
1525 -#include <linux/completion.h>
1526 -#include <linux/interrupt.h>
1527 -#include <linux/fb.h>
1528 -#include <linux/mutex.h>
1529 -
1530 -#include <mach/board.h>
1531 -
1532 -#define OMAP_LCDC_INV_VSYNC             0x0001
1533 -#define OMAP_LCDC_INV_HSYNC             0x0002
1534 -#define OMAP_LCDC_INV_PIX_CLOCK         0x0004
1535 -#define OMAP_LCDC_INV_OUTPUT_EN         0x0008
1536 -#define OMAP_LCDC_HSVS_RISING_EDGE      0x0010
1537 -#define OMAP_LCDC_HSVS_OPPOSITE         0x0020
1538 -
1539 -#define OMAP_LCDC_SIGNAL_MASK          0x003f
1540 -
1541 -#define OMAP_LCDC_PANEL_TFT            0x0100
1542 -
1543 -#define OMAPFB_PLANE_XRES_MIN          8
1544 -#define OMAPFB_PLANE_YRES_MIN          8
1545 -
1546 -#ifdef CONFIG_ARCH_OMAP1
1547 -#define OMAPFB_PLANE_NUM               1
1548 -#else
1549 -#define OMAPFB_PLANE_NUM               3
1550 -#endif
1551 -
1552 -struct omapfb_device;
1553 -
1554 -struct lcd_panel {
1555 -       const char      *name;
1556 -       int             config;         /* TFT/STN, signal inversion */
1557 -       int             bpp;            /* Pixel format in fb mem */
1558 -       int             data_lines;     /* Lines on LCD HW interface */
1559 -
1560 -       int             x_res, y_res;
1561 -       int             pixel_clock;    /* In kHz */
1562 -       int             hsw;            /* Horizontal synchronization
1563 -                                          pulse width */
1564 -       int             hfp;            /* Horizontal front porch */
1565 -       int             hbp;            /* Horizontal back porch */
1566 -       int             vsw;            /* Vertical synchronization
1567 -                                          pulse width */
1568 -       int             vfp;            /* Vertical front porch */
1569 -       int             vbp;            /* Vertical back porch */
1570 -       int             acb;            /* ac-bias pin frequency */
1571 -       int             pcd;            /* pixel clock divider.
1572 -                                          Obsolete use pixel_clock instead */
1573 -
1574 -       int             (*init)         (struct lcd_panel *panel,
1575 -                                        struct omapfb_device *fbdev);
1576 -       void            (*cleanup)      (struct lcd_panel *panel);
1577 -       int             (*enable)       (struct lcd_panel *panel);
1578 -       void            (*disable)      (struct lcd_panel *panel);
1579 -       unsigned long   (*get_caps)     (struct lcd_panel *panel);
1580 -       int             (*set_bklight_level)(struct lcd_panel *panel,
1581 -                                            unsigned int level);
1582 -       unsigned int    (*get_bklight_level)(struct lcd_panel *panel);
1583 -       unsigned int    (*get_bklight_max)  (struct lcd_panel *panel);
1584 -       int             (*run_test)     (struct lcd_panel *panel, int test_num);
1585 -};
1586 -
1587 -struct extif_timings {
1588 -       int cs_on_time;
1589 -       int cs_off_time;
1590 -       int we_on_time;
1591 -       int we_off_time;
1592 -       int re_on_time;
1593 -       int re_off_time;
1594 -       int we_cycle_time;
1595 -       int re_cycle_time;
1596 -       int cs_pulse_width;
1597 -       int access_time;
1598 -
1599 -       int clk_div;
1600 -
1601 -       u32 tim[5];             /* set by extif->convert_timings */
1602 -
1603 -       int converted;
1604 -};
1605 -
1606 -struct lcd_ctrl_extif {
1607 -       int  (*init)            (struct omapfb_device *fbdev);
1608 -       void (*cleanup)         (void);
1609 -       void (*get_clk_info)    (u32 *clk_period, u32 *max_clk_div);
1610 -       unsigned long (*get_max_tx_rate)(void);
1611 -       int  (*convert_timings) (struct extif_timings *timings);
1612 -       void (*set_timings)     (const struct extif_timings *timings);
1613 -       void (*set_bits_per_cycle)(int bpc);
1614 -       void (*write_command)   (const void *buf, unsigned int len);
1615 -       void (*read_data)       (void *buf, unsigned int len);
1616 -       void (*write_data)      (const void *buf, unsigned int len);
1617 -       void (*transfer_area)   (int width, int height,
1618 -                                void (callback)(void * data), void *data);
1619 -       int  (*setup_tearsync)  (unsigned pin_cnt,
1620 -                                unsigned hs_pulse_time, unsigned vs_pulse_time,
1621 -                                int hs_pol_inv, int vs_pol_inv, int div);
1622 -       int  (*enable_tearsync) (int enable, unsigned line);
1623 -
1624 -       unsigned long           max_transmit_size;
1625 -};
1626 -
1627 -struct omapfb_notifier_block {
1628 -       struct notifier_block   nb;
1629 -       void                    *data;
1630 -       int                     plane_idx;
1631 -};
1632 -
1633 -typedef int (*omapfb_notifier_callback_t)(struct notifier_block *,
1634 -                                         unsigned long event,
1635 -                                         void *fbi);
1636 -
1637 -struct omapfb_mem_region {
1638 -       u32             paddr;
1639 -       void __iomem    *vaddr;
1640 -       unsigned long   size;
1641 -       u8              type;           /* OMAPFB_PLANE_MEM_* */
1642 -       unsigned        alloc:1;        /* allocated by the driver */
1643 -       unsigned        map:1;          /* kernel mapped by the driver */
1644 -};
1645 -
1646 -struct omapfb_mem_desc {
1647 -       int                             region_cnt;
1648 -       struct omapfb_mem_region        region[OMAPFB_PLANE_NUM];
1649 -};
1650 -
1651 -struct lcd_ctrl {
1652 -       const char      *name;
1653 -       void            *data;
1654 -
1655 -       int             (*init)           (struct omapfb_device *fbdev,
1656 -                                          int ext_mode,
1657 -                                          struct omapfb_mem_desc *req_md);
1658 -       void            (*cleanup)        (void);
1659 -       void            (*bind_client)    (struct omapfb_notifier_block *nb);
1660 -       void            (*get_caps)       (int plane, struct omapfb_caps *caps);
1661 -       int             (*set_update_mode)(enum omapfb_update_mode mode);
1662 -       enum omapfb_update_mode (*get_update_mode)(void);
1663 -       int             (*setup_plane)    (int plane, int channel_out,
1664 -                                          unsigned long offset,
1665 -                                          int screen_width,
1666 -                                          int pos_x, int pos_y, int width,
1667 -                                          int height, int color_mode);
1668 -       int             (*set_rotate)     (int angle);
1669 -       int             (*setup_mem)      (int plane, size_t size,
1670 -                                          int mem_type, unsigned long *paddr);
1671 -       int             (*mmap)           (struct fb_info *info,
1672 -                                          struct vm_area_struct *vma);
1673 -       int             (*set_scale)      (int plane,
1674 -                                          int orig_width, int orig_height,
1675 -                                          int out_width, int out_height);
1676 -       int             (*enable_plane)   (int plane, int enable);
1677 -       int             (*update_window)  (struct fb_info *fbi,
1678 -                                          struct omapfb_update_window *win,
1679 -                                          void (*callback)(void *),
1680 -                                          void *callback_data);
1681 -       void            (*sync)           (void);
1682 -       void            (*suspend)        (void);
1683 -       void            (*resume)         (void);
1684 -       int             (*run_test)       (int test_num);
1685 -       int             (*setcolreg)      (u_int regno, u16 red, u16 green,
1686 -                                          u16 blue, u16 transp,
1687 -                                          int update_hw_mem);
1688 -       int             (*set_color_key)  (struct omapfb_color_key *ck);
1689 -       int             (*get_color_key)  (struct omapfb_color_key *ck);
1690 -};
1691 -
1692 -enum omapfb_state {
1693 -       OMAPFB_DISABLED = 0,
1694 -       OMAPFB_SUSPENDED= 99,
1695 -       OMAPFB_ACTIVE   = 100
1696 -};
1697 -
1698 -struct omapfb_plane_struct {
1699 -       int                             idx;
1700 -       struct omapfb_plane_info        info;
1701 -       enum omapfb_color_format        color_mode;
1702 -       struct omapfb_device            *fbdev;
1703 -};
1704 -
1705 -struct omapfb_device {
1706 -       int                     state;
1707 -       int                     ext_lcdc;               /* Using external
1708 -                                                           LCD controller */
1709 -       struct mutex            rqueue_mutex;
1710 -
1711 -       int                     palette_size;
1712 -       u32                     pseudo_palette[17];
1713 -
1714 -       struct lcd_panel        *panel;                 /* LCD panel */
1715 -       const struct lcd_ctrl   *ctrl;                  /* LCD controller */
1716 -       const struct lcd_ctrl   *int_ctrl;              /* internal LCD ctrl */
1717 -       struct lcd_ctrl_extif   *ext_if;                /* LCD ctrl external
1718 -                                                          interface */
1719 -       struct device           *dev;
1720 -       struct fb_var_screeninfo        new_var;        /* for mode changes */
1721 -
1722 -       struct omapfb_mem_desc          mem_desc;
1723 -       struct fb_info                  *fb_info[OMAPFB_PLANE_NUM];
1724 -};
1725 -
1726 -struct omapfb_platform_data {
1727 -       struct omap_lcd_config          lcd;
1728 -       struct omapfb_mem_desc          mem_desc;
1729 -       void                            *ctrl_platform_data;
1730 -};
1731 -
1732 -#ifdef CONFIG_ARCH_OMAP1
1733 -extern struct lcd_ctrl omap1_lcd_ctrl;
1734 -#else
1735 -extern struct lcd_ctrl omap2_disp_ctrl;
1736 -#endif
1737 -
1738 -extern void omapfb_reserve_sdram(void);
1739 -extern void omapfb_register_panel(struct lcd_panel *panel);
1740 -extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
1741 -extern void omapfb_notify_clients(struct omapfb_device *fbdev,
1742 -                                 unsigned long event);
1743 -extern int  omapfb_register_client(struct omapfb_notifier_block *nb,
1744 -                                  omapfb_notifier_callback_t callback,
1745 -                                  void *callback_data);
1746 -extern int  omapfb_unregister_client(struct omapfb_notifier_block *nb);
1747 -extern int  omapfb_update_window_async(struct fb_info *fbi,
1748 -                                      struct omapfb_update_window *win,
1749 -                                      void (*callback)(void *),
1750 -                                      void *callback_data);
1751 -
1752 -/* in arch/arm/plat-omap/fb.c */
1753 -extern void omapfb_set_ctrl_platform_data(void *pdata);
1754 -
1755 -#endif /* __KERNEL__ */
1756 -
1757 -#endif /* __OMAPFB_H */
1758 diff --git a/arch/arm/plat-omap/include/mach/sdrc.h b/arch/arm/plat-omap/include/mach/sdrc.h
1759 index 1c09c78..3b157ce 100644
1760 --- a/arch/arm/plat-omap/include/mach/sdrc.h
1761 +++ b/arch/arm/plat-omap/include/mach/sdrc.h
1762 @@ -88,7 +88,10 @@
1763  
1764  /* SMS register offsets - read/write with sms_{read,write}_reg() */
1765  
1766 -#define SMS_SYSCONFIG          0x010
1767 +#define SMS_SYSCONFIG                  0x010
1768 +#define SMS_ROT_CONTROL(context)       (0x180 + 0x10 * context)
1769 +#define SMS_ROT_SIZE(context)          (0x184 + 0x10 * context)
1770 +#define SMS_ROT_PHYSICAL_BA(context)   (0x188 + 0x10 * context)
1771  /* REVISIT: fill in other SMS registers here */
1772  
1773  
1774 @@ -121,6 +124,10 @@ int omap2_sdrc_get_params(unsigned long r,
1775                           struct omap_sdrc_params **sdrc_cs0,
1776                           struct omap_sdrc_params **sdrc_cs1);
1777  
1778 +void omap2_sms_write_rot_control(u32 val, unsigned ctx);
1779 +void omap2_sms_write_rot_size(u32 val, unsigned ctx);
1780 +void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx);
1781 +
1782  #ifdef CONFIG_ARCH_OMAP2
1783  
1784  struct memory_timings {
1785 diff --git a/arch/arm/plat-omap/include/mach/vram.h b/arch/arm/plat-omap/include/mach/vram.h
1786 new file mode 100644
1787 index 0000000..fe72f81
1788 --- /dev/null
1789 +++ b/arch/arm/plat-omap/include/mach/vram.h
1790 @@ -0,0 +1,63 @@
1791 +/*
1792 + * VRAM manager for OMAP
1793 + *
1794 + * Copyright (C) 2009 Nokia Corporation
1795 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
1796 + *
1797 + * This program is free software; you can redistribute it and/or modify
1798 + * it under the terms of the GNU General Public License version 2 as
1799 + * published by the Free Software Foundation.
1800 + *
1801 + * This program is distributed in the hope that it will be useful, but
1802 + * WITHOUT ANY WARRANTY; without even the implied warranty of
1803 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1804 + * General Public License for more details.
1805 + *
1806 + * You should have received a copy of the GNU General Public License along
1807 + * with this program; if not, write to the Free Software Foundation, Inc.,
1808 + * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
1809 + */
1810 +
1811 +#ifndef __OMAP_VRAM_H__
1812 +#define __OMAP_VRAM_H__
1813 +
1814 +#include <linux/autoconf.h>
1815 +#include <linux/types.h>
1816 +
1817 +#define OMAP_VRAM_MEMTYPE_SDRAM                0
1818 +#define OMAP_VRAM_MEMTYPE_SRAM         1
1819 +#define OMAP_VRAM_MEMTYPE_MAX          1
1820 +
1821 +extern int omap_vram_add_region(unsigned long paddr, size_t size);
1822 +extern int omap_vram_free(unsigned long paddr, size_t size);
1823 +extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr);
1824 +extern int omap_vram_reserve(unsigned long paddr, size_t size);
1825 +extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram,
1826 +               unsigned long *largest_free_block);
1827 +
1828 +#ifdef CONFIG_OMAP2_VRAM
1829 +extern void omap_vram_set_sdram_vram(u32 size, u32 start);
1830 +extern void omap_vram_set_sram_vram(u32 size, u32 start);
1831 +
1832 +extern void omap_vram_reserve_sdram(void);
1833 +extern unsigned long omap_vram_reserve_sram(unsigned long sram_pstart,
1834 +                                           unsigned long sram_vstart,
1835 +                                           unsigned long sram_size,
1836 +                                           unsigned long pstart_avail,
1837 +                                           unsigned long size_avail);
1838 +#else
1839 +static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { }
1840 +static inline void omap_vram_set_sram_vram(u32 size, u32 start) { }
1841 +
1842 +static inline void omap_vram_reserve_sdram(void) { }
1843 +static inline unsigned long omap_vram_reserve_sram(unsigned long sram_pstart,
1844 +                                           unsigned long sram_vstart,
1845 +                                           unsigned long sram_size,
1846 +                                           unsigned long pstart_avail,
1847 +                                           unsigned long size_avail)
1848 +{
1849 +       return 0;
1850 +}
1851 +#endif
1852 +
1853 +#endif
1854 diff --git a/arch/arm/plat-omap/include/mach/vrfb.h b/arch/arm/plat-omap/include/mach/vrfb.h
1855 new file mode 100644
1856 index 0000000..8790612
1857 --- /dev/null
1858 +++ b/arch/arm/plat-omap/include/mach/vrfb.h
1859 @@ -0,0 +1,46 @@
1860 +/*
1861 + * VRFB Rotation Engine
1862 + *
1863 + * Copyright (C) 2009 Nokia Corporation
1864 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
1865 + *
1866 + * This program is free software; you can redistribute it and/or modify
1867 + * it under the terms of the GNU General Public License version 2 as
1868 + * published by the Free Software Foundation.
1869 + *
1870 + * This program is distributed in the hope that it will be useful, but
1871 + * WITHOUT ANY WARRANTY; without even the implied warranty of
1872 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1873 + * General Public License for more details.
1874 + *
1875 + * You should have received a copy of the GNU General Public License along
1876 + * with this program; if not, write to the Free Software Foundation, Inc.,
1877 + * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
1878 + */
1879 +
1880 +#ifndef __OMAP_VRFB_H__
1881 +#define __OMAP_VRFB_H__
1882 +
1883 +#define OMAP_VRFB_LINE_LEN 2048
1884 +
1885 +struct vrfb {
1886 +       u8 context;
1887 +       void __iomem *vaddr[4];
1888 +       unsigned long paddr[4];
1889 +       u16 xoffset;
1890 +       u16 yoffset;
1891 +       u8 bytespp;
1892 +};
1893 +
1894 +extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
1895 +extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
1896 +extern void omap_vrfb_suspend_ctx(struct vrfb *vrfb);
1897 +extern void omap_vrfb_resume_ctx(struct vrfb *vrfb);
1898 +extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
1899 +               u8 bytespp);
1900 +extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
1901 +               u16 width, u16 height,
1902 +               unsigned bytespp, bool yuv_mode);
1903 +extern void omap_vrfb_restore_context(void);
1904 +
1905 +#endif /* __VRFB_H */
1906 diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
1907 index 75d1f26..aa9fb63 100644
1908 --- a/arch/arm/plat-omap/sram.c
1909 +++ b/arch/arm/plat-omap/sram.c
1910 @@ -28,6 +28,7 @@
1911  #include <mach/sram.h>
1912  #include <mach/board.h>
1913  #include <mach/cpu.h>
1914 +#include <mach/vram.h>
1915  
1916  #include <mach/control.h>
1917  
1918 @@ -185,6 +186,13 @@ void __init omap_detect_sram(void)
1919                                        omap_sram_start + SRAM_BOOTLOADER_SZ,
1920                                        omap_sram_size - SRAM_BOOTLOADER_SZ);
1921         omap_sram_size -= reserved;
1922 +
1923 +       reserved = omap_vram_reserve_sram(omap_sram_start, omap_sram_base,
1924 +                       omap_sram_size,
1925 +                       omap_sram_start + SRAM_BOOTLOADER_SZ,
1926 +                       omap_sram_size - SRAM_BOOTLOADER_SZ);
1927 +       omap_sram_size -= reserved;
1928 +
1929         omap_sram_ceil = omap_sram_base + omap_sram_size;
1930  }
1931  
1932 diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
1933 index 9bbb285..af0448f 100644
1934 --- a/drivers/video/Kconfig
1935 +++ b/drivers/video/Kconfig
1936 @@ -2161,6 +2161,7 @@ config FB_BROADSHEET
1937           a bridge adapter.
1938  
1939  source "drivers/video/omap/Kconfig"
1940 +source "drivers/video/omap2/Kconfig"
1941  
1942  source "drivers/video/backlight/Kconfig"
1943  source "drivers/video/display/Kconfig"
1944 diff --git a/drivers/video/Makefile b/drivers/video/Makefile
1945 index 80232e1..0f8da33 100644
1946 --- a/drivers/video/Makefile
1947 +++ b/drivers/video/Makefile
1948 @@ -124,6 +124,7 @@ obj-$(CONFIG_FB_SM501)            += sm501fb.o
1949  obj-$(CONFIG_FB_XILINX)           += xilinxfb.o
1950  obj-$(CONFIG_FB_SH_MOBILE_LCDC)          += sh_mobile_lcdcfb.o
1951  obj-$(CONFIG_FB_OMAP)             += omap/
1952 +obj-y                             += omap2/
1953  obj-$(CONFIG_XEN_FBDEV_FRONTEND)  += xen-fbfront.o
1954  obj-$(CONFIG_FB_CARMINE)          += carminefb.o
1955  obj-$(CONFIG_FB_MB862XX)         += mb862xx/
1956 diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
1957 index 551e3e9..455c605 100644
1958 --- a/drivers/video/omap/Kconfig
1959 +++ b/drivers/video/omap/Kconfig
1960 @@ -1,6 +1,7 @@
1961  config FB_OMAP
1962         tristate "OMAP frame buffer support (EXPERIMENTAL)"
1963 -       depends on FB && ARCH_OMAP
1964 +       depends on FB && ARCH_OMAP && (OMAP2_DSS = "n")
1965 +
1966         select FB_CFB_FILLRECT
1967         select FB_CFB_COPYAREA
1968         select FB_CFB_IMAGEBLIT
1969 @@ -72,7 +73,7 @@ config FB_OMAP_LCD_MIPID
1970  
1971  config FB_OMAP_BOOTLOADER_INIT
1972         bool "Check bootloader initialization"
1973 -       depends on FB_OMAP
1974 +       depends on FB_OMAP || FB_OMAP2
1975         help
1976           Say Y here if you want to enable checking if the bootloader has
1977           already initialized the display controller. In this case the
1978 diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c
1979 index 70dadf9..e0d693e 100644
1980 --- a/drivers/video/omap/blizzard.c
1981 +++ b/drivers/video/omap/blizzard.c
1982 @@ -27,9 +27,9 @@
1983  #include <linux/clk.h>
1984  
1985  #include <mach/dma.h>
1986 -#include <mach/omapfb.h>
1987  #include <mach/blizzard.h>
1988  
1989 +#include "omapfb.h"
1990  #include "dispc.h"
1991  
1992  #define MODULE_NAME                            "blizzard"
1993 diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
1994 index f16e421..3f828e6 100644
1995 --- a/drivers/video/omap/dispc.c
1996 +++ b/drivers/video/omap/dispc.c
1997 @@ -24,11 +24,12 @@
1998  #include <linux/vmalloc.h>
1999  #include <linux/clk.h>
2000  #include <linux/io.h>
2001 +#include <linux/platform_device.h>
2002  
2003  #include <mach/sram.h>
2004 -#include <mach/omapfb.h>
2005  #include <mach/board.h>
2006  
2007 +#include "omapfb.h"
2008  #include "dispc.h"
2009  
2010  #define MODULE_NAME                    "dispc"
2011 @@ -188,6 +189,11 @@ static struct {
2012         struct omapfb_color_key color_key;
2013  } dispc;
2014  
2015 +static struct platform_device omapdss_device = {
2016 +       .name           = "omapdss",
2017 +       .id             = -1,
2018 +};
2019 +
2020  static void enable_lcd_clocks(int enable);
2021  
2022  static void inline dispc_write_reg(int idx, u32 val)
2023 @@ -907,20 +913,20 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
2024  
2025  static int get_dss_clocks(void)
2026  {
2027 -       dispc.dss_ick = clk_get(dispc.fbdev->dev, "ick");
2028 +       dispc.dss_ick = clk_get(&omapdss_device.dev, "ick");
2029         if (IS_ERR(dispc.dss_ick)) {
2030                 dev_err(dispc.fbdev->dev, "can't get ick\n");
2031                 return PTR_ERR(dispc.dss_ick);
2032         }
2033  
2034 -       dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck");
2035 +       dispc.dss1_fck = clk_get(&omapdss_device.dev, "dss1_fck");
2036         if (IS_ERR(dispc.dss1_fck)) {
2037                 dev_err(dispc.fbdev->dev, "can't get dss1_fck\n");
2038                 clk_put(dispc.dss_ick);
2039                 return PTR_ERR(dispc.dss1_fck);
2040         }
2041  
2042 -       dispc.dss_54m_fck = clk_get(dispc.fbdev->dev, "tv_fck");
2043 +       dispc.dss_54m_fck = clk_get(&omapdss_device.dev, "tv_fck");
2044         if (IS_ERR(dispc.dss_54m_fck)) {
2045                 dev_err(dispc.fbdev->dev, "can't get tv_fck\n");
2046                 clk_put(dispc.dss_ick);
2047 @@ -1371,6 +1377,12 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
2048         int skip_init = 0;
2049         int i;
2050  
2051 +       r = platform_device_register(&omapdss_device);
2052 +       if (r) {
2053 +               dev_err(fbdev->dev, "can't register omapdss device\n");
2054 +               return r;
2055 +       }
2056 +
2057         memset(&dispc, 0, sizeof(dispc));
2058  
2059         dispc.base = ioremap(DISPC_BASE, SZ_1K);
2060 @@ -1508,6 +1520,7 @@ static void omap_dispc_cleanup(void)
2061         free_irq(INT_24XX_DSS_IRQ, dispc.fbdev);
2062         put_dss_clocks();
2063         iounmap(dispc.base);
2064 +       platform_device_unregister(&omapdss_device);
2065  }
2066  
2067  const struct lcd_ctrl omap2_int_ctrl = {
2068 diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
2069 index ca51583..b84fb7c 100644
2070 --- a/drivers/video/omap/hwa742.c
2071 +++ b/drivers/video/omap/hwa742.c
2072 @@ -27,8 +27,8 @@
2073  #include <linux/clk.h>
2074  
2075  #include <mach/dma.h>
2076 -#include <mach/omapfb.h>
2077  #include <mach/hwa742.h>
2078 +#include "omapfb.h"
2079  
2080  #define HWA742_REV_CODE_REG       0x0
2081  #define HWA742_CONFIG_REG         0x2
2082 diff --git a/drivers/video/omap/lcd_2430sdp.c b/drivers/video/omap/lcd_2430sdp.c
2083 index 393712b..7b7690a 100644
2084 --- a/drivers/video/omap/lcd_2430sdp.c
2085 +++ b/drivers/video/omap/lcd_2430sdp.c
2086 @@ -28,9 +28,10 @@
2087  #include <linux/i2c/twl4030.h>
2088  
2089  #include <mach/mux.h>
2090 -#include <mach/omapfb.h>
2091  #include <asm/mach-types.h>
2092  
2093 +#include "omapfb.h"
2094 +
2095  #define SDP2430_LCD_PANEL_BACKLIGHT_GPIO       91
2096  #define SDP2430_LCD_PANEL_ENABLE_GPIO          154
2097  #define SDP3430_LCD_PANEL_BACKLIGHT_GPIO       24
2098 diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/omap/lcd_ams_delta.c
2099 index 1f74399..1d3fd13 100644
2100 --- a/drivers/video/omap/lcd_ams_delta.c
2101 +++ b/drivers/video/omap/lcd_ams_delta.c
2102 @@ -27,7 +27,8 @@
2103  
2104  #include <mach/board-ams-delta.h>
2105  #include <mach/hardware.h>
2106 -#include <mach/omapfb.h>
2107 +
2108 +#include "omapfb.h"
2109  
2110  #define AMS_DELTA_DEFAULT_CONTRAST     112
2111  
2112 diff --git a/drivers/video/omap/lcd_apollon.c b/drivers/video/omap/lcd_apollon.c
2113 index 626ae3a..e099ad1 100644
2114 --- a/drivers/video/omap/lcd_apollon.c
2115 +++ b/drivers/video/omap/lcd_apollon.c
2116 @@ -26,7 +26,8 @@
2117  
2118  #include <mach/gpio.h>
2119  #include <mach/mux.h>
2120 -#include <mach/omapfb.h>
2121 +
2122 +#include "omapfb.h"
2123  
2124  /* #define USE_35INCH_LCD 1 */
2125  
2126 diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c
2127 index 417ae5e..8df6887 100644
2128 --- a/drivers/video/omap/lcd_h3.c
2129 +++ b/drivers/video/omap/lcd_h3.c
2130 @@ -24,7 +24,7 @@
2131  #include <linux/i2c/tps65010.h>
2132  
2133  #include <mach/gpio.h>
2134 -#include <mach/omapfb.h>
2135 +#include "omapfb.h"
2136  
2137  #define MODULE_NAME    "omapfb-lcd_h3"
2138  
2139 diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c
2140 index 0c398bd..03a06a9 100644
2141 --- a/drivers/video/omap/lcd_h4.c
2142 +++ b/drivers/video/omap/lcd_h4.c
2143 @@ -22,7 +22,7 @@
2144  #include <linux/module.h>
2145  #include <linux/platform_device.h>
2146  
2147 -#include <mach/omapfb.h>
2148 +#include "omapfb.h"
2149  
2150  static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
2151  {
2152 diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
2153 index cdbd8bb..18f1422 100644
2154 --- a/drivers/video/omap/lcd_inn1510.c
2155 +++ b/drivers/video/omap/lcd_inn1510.c
2156 @@ -24,7 +24,7 @@
2157  #include <linux/io.h>
2158  
2159  #include <mach/fpga.h>
2160 -#include <mach/omapfb.h>
2161 +#include "omapfb.h"
2162  
2163  static int innovator1510_panel_init(struct lcd_panel *panel,
2164                                     struct omapfb_device *fbdev)
2165 diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
2166 index 268f7f8..9fff86f 100644
2167 --- a/drivers/video/omap/lcd_inn1610.c
2168 +++ b/drivers/video/omap/lcd_inn1610.c
2169 @@ -23,7 +23,7 @@
2170  #include <linux/platform_device.h>
2171  
2172  #include <mach/gpio.h>
2173 -#include <mach/omapfb.h>
2174 +#include "omapfb.h"
2175  
2176  #define MODULE_NAME    "omapfb-lcd_h3"
2177  
2178 diff --git a/drivers/video/omap/lcd_ldp.c b/drivers/video/omap/lcd_ldp.c
2179 index dbfe897..44a43ea 100644
2180 --- a/drivers/video/omap/lcd_ldp.c
2181 +++ b/drivers/video/omap/lcd_ldp.c
2182 @@ -28,9 +28,10 @@
2183  
2184  #include <mach/gpio.h>
2185  #include <mach/mux.h>
2186 -#include <mach/omapfb.h>
2187  #include <asm/mach-types.h>
2188  
2189 +#include "omapfb.h"
2190 +
2191  #define LCD_PANEL_BACKLIGHT_GPIO       (15 + OMAP_MAX_GPIO_LINES)
2192  #define LCD_PANEL_ENABLE_GPIO          (7 + OMAP_MAX_GPIO_LINES)
2193  
2194 diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c
2195 index 918ee89..62e1975 100644
2196 --- a/drivers/video/omap/lcd_mipid.c
2197 +++ b/drivers/video/omap/lcd_mipid.c
2198 @@ -23,9 +23,10 @@
2199  #include <linux/workqueue.h>
2200  #include <linux/spi/spi.h>
2201  
2202 -#include <mach/omapfb.h>
2203  #include <mach/lcd_mipid.h>
2204  
2205 +#include "omapfb.h"
2206 +
2207  #define MIPID_MODULE_NAME              "lcd_mipid"
2208  
2209  #define MIPID_CMD_READ_DISP_ID         0x04
2210 diff --git a/drivers/video/omap/lcd_omap2evm.c b/drivers/video/omap/lcd_omap2evm.c
2211 index 7a2bbe2..c3be87c 100644
2212 --- a/drivers/video/omap/lcd_omap2evm.c
2213 +++ b/drivers/video/omap/lcd_omap2evm.c
2214 @@ -27,9 +27,10 @@
2215  #include <linux/i2c/twl4030.h>
2216  
2217  #include <mach/mux.h>
2218 -#include <mach/omapfb.h>
2219  #include <asm/mach-types.h>
2220  
2221 +#include "omapfb.h"
2222 +
2223  #define LCD_PANEL_ENABLE_GPIO  154
2224  #define LCD_PANEL_LR           128
2225  #define LCD_PANEL_UD           129
2226 diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c
2227 index 4011910..0608a25 100644
2228 --- a/drivers/video/omap/lcd_omap3beagle.c
2229 +++ b/drivers/video/omap/lcd_omap3beagle.c
2230 @@ -26,9 +26,10 @@
2231  #include <linux/i2c/twl4030.h>
2232  
2233  #include <mach/mux.h>
2234 -#include <mach/omapfb.h>
2235  #include <asm/mach-types.h>
2236  
2237 +#include "omapfb.h"
2238 +
2239  #define LCD_PANEL_ENABLE_GPIO       170
2240  
2241  static int omap3beagle_panel_init(struct lcd_panel *panel,
2242 diff --git a/drivers/video/omap/lcd_omap3evm.c b/drivers/video/omap/lcd_omap3evm.c
2243 index b6a4c2c..c204afb 100644
2244 --- a/drivers/video/omap/lcd_omap3evm.c
2245 +++ b/drivers/video/omap/lcd_omap3evm.c
2246 @@ -26,9 +26,10 @@
2247  #include <linux/i2c/twl4030.h>
2248  
2249  #include <mach/mux.h>
2250 -#include <mach/omapfb.h>
2251  #include <asm/mach-types.h>
2252  
2253 +#include "omapfb.h"
2254 +
2255  #define LCD_PANEL_ENABLE_GPIO       153
2256  #define LCD_PANEL_LR                2
2257  #define LCD_PANEL_UD                3
2258 diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c
2259 index b3fa88b..5755b5c 100644
2260 --- a/drivers/video/omap/lcd_osk.c
2261 +++ b/drivers/video/omap/lcd_osk.c
2262 @@ -25,7 +25,7 @@
2263  
2264  #include <mach/gpio.h>
2265  #include <mach/mux.h>
2266 -#include <mach/omapfb.h>
2267 +#include "omapfb.h"
2268  
2269  static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
2270  {
2271 diff --git a/drivers/video/omap/lcd_overo.c b/drivers/video/omap/lcd_overo.c
2272 index 2bc5c92..63ebb1f 100644
2273 --- a/drivers/video/omap/lcd_overo.c
2274 +++ b/drivers/video/omap/lcd_overo.c
2275 @@ -25,9 +25,10 @@
2276  
2277  #include <mach/gpio.h>
2278  #include <mach/mux.h>
2279 -#include <mach/omapfb.h>
2280  #include <asm/mach-types.h>
2281  
2282 +#include "omapfb.h"
2283 +
2284  #define LCD_ENABLE       144
2285  
2286  static int overo_panel_init(struct lcd_panel *panel,
2287 diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c
2288 index 4bf3c79..7e11a75 100644
2289 --- a/drivers/video/omap/lcd_palmte.c
2290 +++ b/drivers/video/omap/lcd_palmte.c
2291 @@ -24,7 +24,7 @@
2292  #include <linux/io.h>
2293  
2294  #include <mach/fpga.h>
2295 -#include <mach/omapfb.h>
2296 +#include "omapfb.h"
2297  
2298  static int palmte_panel_init(struct lcd_panel *panel,
2299                                 struct omapfb_device *fbdev)
2300 diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c
2301 index 48ea1f9..ff0e6d7 100644
2302 --- a/drivers/video/omap/lcd_palmtt.c
2303 +++ b/drivers/video/omap/lcd_palmtt.c
2304 @@ -30,7 +30,7 @@ GPIO13 - screen blanking
2305  #include <linux/io.h>
2306  
2307  #include <mach/gpio.h>
2308 -#include <mach/omapfb.h>
2309 +#include "omapfb.h"
2310  
2311  static int palmtt_panel_init(struct lcd_panel *panel,
2312         struct omapfb_device *fbdev)
2313 diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c
2314 index 0697d29..2334e56 100644
2315 --- a/drivers/video/omap/lcd_palmz71.c
2316 +++ b/drivers/video/omap/lcd_palmz71.c
2317 @@ -24,7 +24,7 @@
2318  #include <linux/platform_device.h>
2319  #include <linux/io.h>
2320  
2321 -#include <mach/omapfb.h>
2322 +#include "omapfb.h"
2323  
2324  static int palmz71_panel_init(struct lcd_panel *panel,
2325                               struct omapfb_device *fbdev)
2326 diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
2327 index ab39492..520ed97 100644
2328 --- a/drivers/video/omap/lcdc.c
2329 +++ b/drivers/video/omap/lcdc.c
2330 @@ -30,10 +30,11 @@
2331  #include <linux/clk.h>
2332  
2333  #include <mach/dma.h>
2334 -#include <mach/omapfb.h>
2335  
2336  #include <asm/mach-types.h>
2337  
2338 +#include "omapfb.h"
2339 +
2340  #include "lcdc.h"
2341  
2342  #define MODULE_NAME                    "lcdc"
2343 diff --git a/drivers/video/omap/omapfb.h b/drivers/video/omap/omapfb.h
2344 new file mode 100644
2345 index 0000000..46e4714
2346 --- /dev/null
2347 +++ b/drivers/video/omap/omapfb.h
2348 @@ -0,0 +1,227 @@
2349 +/*
2350 + * File: drivers/video/omap/omapfb.h
2351 + *
2352 + * Framebuffer driver for TI OMAP boards
2353 + *
2354 + * Copyright (C) 2004 Nokia Corporation
2355 + * Author: Imre Deak <imre.deak@nokia.com>
2356 + *
2357 + * This program is free software; you can redistribute it and/or modify it
2358 + * under the terms of the GNU General Public License as published by the
2359 + * Free Software Foundation; either version 2 of the License, or (at your
2360 + * option) any later version.
2361 + *
2362 + * This program is distributed in the hope that it will be useful, but
2363 + * WITHOUT ANY WARRANTY; without even the implied warranty of
2364 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2365 + * General Public License for more details.
2366 + *
2367 + * You should have received a copy of the GNU General Public License along
2368 + * with this program; if not, write to the Free Software Foundation, Inc.,
2369 + * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
2370 + */
2371 +
2372 +#ifndef __OMAPFB_H
2373 +#define __OMAPFB_H
2374 +
2375 +#include <linux/fb.h>
2376 +#include <linux/mutex.h>
2377 +#include <linux/omapfb.h>
2378 +
2379 +#define OMAPFB_EVENT_READY     1
2380 +#define OMAPFB_EVENT_DISABLED  2
2381 +
2382 +#define OMAP_LCDC_INV_VSYNC             0x0001
2383 +#define OMAP_LCDC_INV_HSYNC             0x0002
2384 +#define OMAP_LCDC_INV_PIX_CLOCK         0x0004
2385 +#define OMAP_LCDC_INV_OUTPUT_EN         0x0008
2386 +#define OMAP_LCDC_HSVS_RISING_EDGE      0x0010
2387 +#define OMAP_LCDC_HSVS_OPPOSITE         0x0020
2388 +
2389 +#define OMAP_LCDC_SIGNAL_MASK          0x003f
2390 +
2391 +#define OMAP_LCDC_PANEL_TFT            0x0100
2392 +
2393 +#define OMAPFB_PLANE_XRES_MIN          8
2394 +#define OMAPFB_PLANE_YRES_MIN          8
2395 +
2396 +struct omapfb_device;
2397 +
2398 +struct lcd_panel {
2399 +       const char      *name;
2400 +       int             config;         /* TFT/STN, signal inversion */
2401 +       int             bpp;            /* Pixel format in fb mem */
2402 +       int             data_lines;     /* Lines on LCD HW interface */
2403 +
2404 +       int             x_res, y_res;
2405 +       int             pixel_clock;    /* In kHz */
2406 +       int             hsw;            /* Horizontal synchronization
2407 +                                          pulse width */
2408 +       int             hfp;            /* Horizontal front porch */
2409 +       int             hbp;            /* Horizontal back porch */
2410 +       int             vsw;            /* Vertical synchronization
2411 +                                          pulse width */
2412 +       int             vfp;            /* Vertical front porch */
2413 +       int             vbp;            /* Vertical back porch */
2414 +       int             acb;            /* ac-bias pin frequency */
2415 +       int             pcd;            /* pixel clock divider.
2416 +                                          Obsolete use pixel_clock instead */
2417 +
2418 +       int             (*init)         (struct lcd_panel *panel,
2419 +                                        struct omapfb_device *fbdev);
2420 +       void            (*cleanup)      (struct lcd_panel *panel);
2421 +       int             (*enable)       (struct lcd_panel *panel);
2422 +       void            (*disable)      (struct lcd_panel *panel);
2423 +       unsigned long   (*get_caps)     (struct lcd_panel *panel);
2424 +       int             (*set_bklight_level)(struct lcd_panel *panel,
2425 +                                            unsigned int level);
2426 +       unsigned int    (*get_bklight_level)(struct lcd_panel *panel);
2427 +       unsigned int    (*get_bklight_max)  (struct lcd_panel *panel);
2428 +       int             (*run_test)     (struct lcd_panel *panel, int test_num);
2429 +};
2430 +
2431 +struct extif_timings {
2432 +       int cs_on_time;
2433 +       int cs_off_time;
2434 +       int we_on_time;
2435 +       int we_off_time;
2436 +       int re_on_time;
2437 +       int re_off_time;
2438 +       int we_cycle_time;
2439 +       int re_cycle_time;
2440 +       int cs_pulse_width;
2441 +       int access_time;
2442 +
2443 +       int clk_div;
2444 +
2445 +       u32 tim[5];             /* set by extif->convert_timings */
2446 +
2447 +       int converted;
2448 +};
2449 +
2450 +struct lcd_ctrl_extif {
2451 +       int  (*init)            (struct omapfb_device *fbdev);
2452 +       void (*cleanup)         (void);
2453 +       void (*get_clk_info)    (u32 *clk_period, u32 *max_clk_div);
2454 +       unsigned long (*get_max_tx_rate)(void);
2455 +       int  (*convert_timings) (struct extif_timings *timings);
2456 +       void (*set_timings)     (const struct extif_timings *timings);
2457 +       void (*set_bits_per_cycle)(int bpc);
2458 +       void (*write_command)   (const void *buf, unsigned int len);
2459 +       void (*read_data)       (void *buf, unsigned int len);
2460 +       void (*write_data)      (const void *buf, unsigned int len);
2461 +       void (*transfer_area)   (int width, int height,
2462 +                                void (callback)(void *data), void *data);
2463 +       int  (*setup_tearsync)  (unsigned pin_cnt,
2464 +                                unsigned hs_pulse_time, unsigned vs_pulse_time,
2465 +                                int hs_pol_inv, int vs_pol_inv, int div);
2466 +       int  (*enable_tearsync) (int enable, unsigned line);
2467 +
2468 +       unsigned long           max_transmit_size;
2469 +};
2470 +
2471 +struct omapfb_notifier_block {
2472 +       struct notifier_block   nb;
2473 +       void                    *data;
2474 +       int                     plane_idx;
2475 +};
2476 +
2477 +typedef int (*omapfb_notifier_callback_t)(struct notifier_block *,
2478 +                                         unsigned long event,
2479 +                                         void *fbi);
2480 +
2481 +struct lcd_ctrl {
2482 +       const char      *name;
2483 +       void            *data;
2484 +
2485 +       int             (*init)           (struct omapfb_device *fbdev,
2486 +                                          int ext_mode,
2487 +                                          struct omapfb_mem_desc *req_md);
2488 +       void            (*cleanup)        (void);
2489 +       void            (*bind_client)    (struct omapfb_notifier_block *nb);
2490 +       void            (*get_caps)       (int plane, struct omapfb_caps *caps);
2491 +       int             (*set_update_mode)(enum omapfb_update_mode mode);
2492 +       enum omapfb_update_mode (*get_update_mode)(void);
2493 +       int             (*setup_plane)    (int plane, int channel_out,
2494 +                                          unsigned long offset,
2495 +                                          int screen_width,
2496 +                                          int pos_x, int pos_y, int width,
2497 +                                          int height, int color_mode);
2498 +       int             (*set_rotate)     (int angle);
2499 +       int             (*setup_mem)      (int plane, size_t size,
2500 +                                          int mem_type, unsigned long *paddr);
2501 +       int             (*mmap)           (struct fb_info *info,
2502 +                                          struct vm_area_struct *vma);
2503 +       int             (*set_scale)      (int plane,
2504 +                                          int orig_width, int orig_height,
2505 +                                          int out_width, int out_height);
2506 +       int             (*enable_plane)   (int plane, int enable);
2507 +       int             (*update_window)  (struct fb_info *fbi,
2508 +                                          struct omapfb_update_window *win,
2509 +                                          void (*callback)(void *),
2510 +                                          void *callback_data);
2511 +       void            (*sync)           (void);
2512 +       void            (*suspend)        (void);
2513 +       void            (*resume)         (void);
2514 +       int             (*run_test)       (int test_num);
2515 +       int             (*setcolreg)      (u_int regno, u16 red, u16 green,
2516 +                                          u16 blue, u16 transp,
2517 +                                          int update_hw_mem);
2518 +       int             (*set_color_key)  (struct omapfb_color_key *ck);
2519 +       int             (*get_color_key)  (struct omapfb_color_key *ck);
2520 +};
2521 +
2522 +enum omapfb_state {
2523 +       OMAPFB_DISABLED         = 0,
2524 +       OMAPFB_SUSPENDED        = 99,
2525 +       OMAPFB_ACTIVE           = 100
2526 +};
2527 +
2528 +struct omapfb_plane_struct {
2529 +       int                             idx;
2530 +       struct omapfb_plane_info        info;
2531 +       enum omapfb_color_format        color_mode;
2532 +       struct omapfb_device            *fbdev;
2533 +};
2534 +
2535 +struct omapfb_device {
2536 +       int                     state;
2537 +       int                     ext_lcdc;               /* Using external
2538 +                                                          LCD controller */
2539 +       struct mutex            rqueue_mutex;
2540 +
2541 +       int                     palette_size;
2542 +       u32                     pseudo_palette[17];
2543 +
2544 +       struct lcd_panel        *panel;                 /* LCD panel */
2545 +       const struct lcd_ctrl   *ctrl;                  /* LCD controller */
2546 +       const struct lcd_ctrl   *int_ctrl;              /* internal LCD ctrl */
2547 +       struct lcd_ctrl_extif   *ext_if;                /* LCD ctrl external
2548 +                                                          interface */
2549 +       struct device           *dev;
2550 +       struct fb_var_screeninfo        new_var;        /* for mode changes */
2551 +
2552 +       struct omapfb_mem_desc          mem_desc;
2553 +       struct fb_info                  *fb_info[OMAPFB_PLANE_NUM];
2554 +};
2555 +
2556 +#ifdef CONFIG_ARCH_OMAP1
2557 +extern struct lcd_ctrl omap1_lcd_ctrl;
2558 +#else
2559 +extern struct lcd_ctrl omap2_disp_ctrl;
2560 +#endif
2561 +
2562 +extern void omapfb_register_panel(struct lcd_panel *panel);
2563 +extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
2564 +extern void omapfb_notify_clients(struct omapfb_device *fbdev,
2565 +                                 unsigned long event);
2566 +extern int  omapfb_register_client(struct omapfb_notifier_block *nb,
2567 +                                  omapfb_notifier_callback_t callback,
2568 +                                  void *callback_data);
2569 +extern int  omapfb_unregister_client(struct omapfb_notifier_block *nb);
2570 +extern int  omapfb_update_window_async(struct fb_info *fbi,
2571 +                                      struct omapfb_update_window *win,
2572 +                                      void (*callback)(void *),
2573 +                                      void *callback_data);
2574 +
2575 +#endif /* __OMAPFB_H */
2576 diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
2577 index 0d0c8c8..a27614d 100644
2578 --- a/drivers/video/omap/omapfb_main.c
2579 +++ b/drivers/video/omap/omapfb_main.c
2580 @@ -29,8 +29,8 @@
2581  #include <linux/uaccess.h>
2582  
2583  #include <mach/dma.h>
2584 -#include <mach/omapfb.h>
2585  
2586 +#include "omapfb.h"
2587  #include "lcdc.h"
2588  #include "dispc.h"
2589  
2590 diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
2591 index ee01e84..fed7b1b 100644
2592 --- a/drivers/video/omap/rfbi.c
2593 +++ b/drivers/video/omap/rfbi.c
2594 @@ -27,8 +27,7 @@
2595  #include <linux/clk.h>
2596  #include <linux/io.h>
2597  
2598 -#include <mach/omapfb.h>
2599 -
2600 +#include "omapfb.h"
2601  #include "dispc.h"
2602  
2603  /* To work around an RFBI transfer rate limitation */
2604 diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
2605 index a769462..6853627 100644
2606 --- a/drivers/video/omap/sossi.c
2607 +++ b/drivers/video/omap/sossi.c
2608 @@ -25,8 +25,8 @@
2609  #include <linux/io.h>
2610  
2611  #include <mach/dma.h>
2612 -#include <mach/omapfb.h>
2613  
2614 +#include "omapfb.h"
2615  #include "lcdc.h"
2616  
2617  #define MODULE_NAME            "omapfb-sossi"
2618 diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
2619 new file mode 100644
2620 index 0000000..d877c36
2621 --- /dev/null
2622 +++ b/drivers/video/omap2/Kconfig
2623 @@ -0,0 +1,9 @@
2624 +config OMAP2_VRAM
2625 +       bool
2626 +
2627 +config OMAP2_VRFB
2628 +       bool
2629 +
2630 +source "drivers/video/omap2/dss/Kconfig"
2631 +source "drivers/video/omap2/omapfb/Kconfig"
2632 +source "drivers/video/omap2/displays/Kconfig"
2633 diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
2634 new file mode 100644
2635 index 0000000..d853d05
2636 --- /dev/null
2637 +++ b/drivers/video/omap2/Makefile
2638 @@ -0,0 +1,6 @@
2639 +obj-$(CONFIG_OMAP2_VRAM) += vram.o
2640 +obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
2641 +
2642 +obj-y += dss/
2643 +obj-y += omapfb/
2644 +obj-y += displays/
2645 diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
2646 new file mode 100644
2647 index 0000000..79d2861
2648 --- /dev/null
2649 +++ b/drivers/video/omap2/displays/Kconfig
2650 @@ -0,0 +1,28 @@
2651 +menu "OMAP2/3 Display Device Drivers"
2652 +        depends on OMAP2_DSS
2653 +
2654 +config PANEL_GENERIC
2655 +        tristate "Generic Panel"
2656 +        help
2657 +         Generic panel driver.
2658 +         Used for DVI output for Beagle and OMAP3 SDP.
2659 +
2660 +config PANEL_SAMSUNG_LTE430WQ_F0C
2661 +        tristate "Samsung LTE430WQ-F0C LCD Panel"
2662 +        depends on OMAP2_DSS
2663 +        help
2664 +          LCD Panel used on Overo Palo43
2665 +
2666 +config PANEL_SHARP_LS037V7DW01
2667 +        tristate "Sharp LS037V7DW01 LCD Panel"
2668 +        depends on OMAP2_DSS
2669 +        help
2670 +          LCD Panel used in TI's SDP3430 and EVM boards
2671 +
2672 +config PANEL_TAAL
2673 +        tristate "Taal DSI Panel"
2674 +        depends on OMAP2_DSS_DSI
2675 +        help
2676 +          Taal DSI command mode panel from TPO.
2677 +
2678 +endmenu
2679 diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
2680 new file mode 100644
2681 index 0000000..d44e765
2682 --- /dev/null
2683 +++ b/drivers/video/omap2/displays/Makefile
2684 @@ -0,0 +1,5 @@
2685 +obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o
2686 +obj-$(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) += panel-samsung-lte430wq-f0c.o
2687 +obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
2688 +
2689 +obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
2690 diff --git a/drivers/video/omap2/displays/panel-generic.c b/drivers/video/omap2/displays/panel-generic.c
2691 new file mode 100644
2692 index 0000000..738147e
2693 --- /dev/null
2694 +++ b/drivers/video/omap2/displays/panel-generic.c
2695 @@ -0,0 +1,104 @@
2696 +/*
2697 + * Generic panel support
2698 + *
2699 + * Copyright (C) 2008 Nokia Corporation
2700 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
2701 + *
2702 + * This program is free software; you can redistribute it and/or modify it
2703 + * under the terms of the GNU General Public License version 2 as published by
2704 + * the Free Software Foundation.
2705 + *
2706 + * This program is distributed in the hope that it will be useful, but WITHOUT
2707 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2708 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
2709 + * more details.
2710 + *
2711 + * You should have received a copy of the GNU General Public License along with
2712 + * this program.  If not, see <http://www.gnu.org/licenses/>.
2713 + */
2714 +
2715 +#include <linux/module.h>
2716 +#include <linux/delay.h>
2717 +
2718 +#include <mach/display.h>
2719 +
2720 +static struct omap_video_timings generic_panel_timings = {
2721 +       /* 640 x 480 @ 60 Hz  Reduced blanking VESA CVT 0.31M3-R */
2722 +       .x_res          = 640,
2723 +       .y_res          = 480,
2724 +       .pixel_clock    = 23500,
2725 +       .hfp            = 48,
2726 +       .hsw            = 32,
2727 +       .hbp            = 80,
2728 +       .vfp            = 3,
2729 +       .vsw            = 4,
2730 +       .vbp            = 7,
2731 +};
2732 +
2733 +static int generic_panel_probe(struct omap_dss_device *dssdev)
2734 +{
2735 +       dssdev->panel.config = OMAP_DSS_LCD_TFT;
2736 +       dssdev->panel.timings = generic_panel_timings;
2737 +
2738 +       return 0;
2739 +}
2740 +
2741 +static void generic_panel_remove(struct omap_dss_device *dssdev)
2742 +{
2743 +}
2744 +
2745 +static int generic_panel_enable(struct omap_dss_device *dssdev)
2746 +{
2747 +       int r = 0;
2748 +
2749 +       if (dssdev->platform_enable)
2750 +               r = dssdev->platform_enable(dssdev);
2751 +
2752 +       return r;
2753 +}
2754 +
2755 +static void generic_panel_disable(struct omap_dss_device *dssdev)
2756 +{
2757 +       if (dssdev->platform_disable)
2758 +               dssdev->platform_disable(dssdev);
2759 +}
2760 +
2761 +static int generic_panel_suspend(struct omap_dss_device *dssdev)
2762 +{
2763 +       generic_panel_disable(dssdev);
2764 +       return 0;
2765 +}
2766 +
2767 +static int generic_panel_resume(struct omap_dss_device *dssdev)
2768 +{
2769 +       return generic_panel_enable(dssdev);
2770 +}
2771 +
2772 +static struct omap_dss_driver generic_driver = {
2773 +       .probe          = generic_panel_probe,
2774 +       .remove         = generic_panel_remove,
2775 +
2776 +       .enable         = generic_panel_enable,
2777 +       .disable        = generic_panel_disable,
2778 +       .suspend        = generic_panel_suspend,
2779 +       .resume         = generic_panel_resume,
2780 +
2781 +       .driver         = {
2782 +               .name   = "generic_panel",
2783 +               .owner  = THIS_MODULE,
2784 +       },
2785 +};
2786 +
2787 +static int __init generic_panel_drv_init(void)
2788 +{
2789 +       return omap_dss_register_driver(&generic_driver);
2790 +}
2791 +
2792 +static void __exit generic_panel_drv_exit(void)
2793 +{
2794 +       omap_dss_unregister_driver(&generic_driver);
2795 +}
2796 +
2797 +module_init(generic_panel_drv_init);
2798 +module_exit(generic_panel_drv_exit);
2799 +MODULE_LICENSE("GPL");
2800 diff --git a/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c b/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c
2801 new file mode 100644
2802 index 0000000..eafe581
2803 --- /dev/null
2804 +++ b/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c
2805 @@ -0,0 +1,113 @@
2806 +/*
2807 + * LCD panel driver for Samsung LTE430WQ-F0C
2808 + *
2809 + * Author: Steve Sakoman <steve@sakoman.com>
2810 + *
2811 + * This program is free software; you can redistribute it and/or modify it
2812 + * under the terms of the GNU General Public License version 2 as published by
2813 + * the Free Software Foundation.
2814 + *
2815 + * This program is distributed in the hope that it will be useful, but WITHOUT
2816 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2817 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
2818 + * more details.
2819 + *
2820 + * You should have received a copy of the GNU General Public License along with
2821 + * this program.  If not, see <http://www.gnu.org/licenses/>.
2822 + */
2823 +
2824 +#include <linux/module.h>
2825 +#include <linux/delay.h>
2826 +
2827 +#include <mach/display.h>
2828 +
2829 +static struct omap_video_timings samsung_lte_timings = {
2830 +       .x_res = 480,
2831 +       .y_res = 272,
2832 +
2833 +       .pixel_clock    = 9200,
2834 +
2835 +       .hsw            = 41,
2836 +       .hfp            = 8,
2837 +       .hbp            = 45-41,
2838 +
2839 +       .vsw            = 10,
2840 +       .vfp            = 4,
2841 +       .vbp            = 12-10,
2842 +};
2843 +
2844 +static int samsung_lte_panel_probe(struct omap_dss_device *dssdev)
2845 +{
2846 +       dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
2847 +               OMAP_DSS_LCD_IHS;
2848 +       dssdev->panel.timings = samsung_lte_timings;
2849 +
2850 +       return 0;
2851 +}
2852 +
2853 +static void samsung_lte_panel_remove(struct omap_dss_device *dssdev)
2854 +{
2855 +}
2856 +
2857 +static int samsung_lte_panel_enable(struct omap_dss_device *dssdev)
2858 +{
2859 +       int r = 0;
2860 +
2861 +       /* wait couple of vsyncs until enabling the LCD */
2862 +       msleep(50);
2863 +
2864 +       if (dssdev->platform_enable)
2865 +               r = dssdev->platform_enable(dssdev);
2866 +
2867 +       return r;
2868 +}
2869 +
2870 +static void samsung_lte_panel_disable(struct omap_dss_device *dssdev)
2871 +{
2872 +       if (dssdev->platform_disable)
2873 +               dssdev->platform_disable(dssdev);
2874 +
2875 +       /* wait at least 5 vsyncs after disabling the LCD */
2876 +
2877 +       msleep(100);
2878 +}
2879 +
2880 +static int samsung_lte_panel_suspend(struct omap_dss_device *dssdev)
2881 +{
2882 +       samsung_lte_panel_disable(dssdev);
2883 +       return 0;
2884 +}
2885 +
2886 +static int samsung_lte_panel_resume(struct omap_dss_device *dssdev)
2887 +{
2888 +       return samsung_lte_panel_enable(dssdev);
2889 +}
2890 +
2891 +static struct omap_dss_driver samsung_lte_driver = {
2892 +       .probe          = samsung_lte_panel_probe,
2893 +       .remove         = samsung_lte_panel_remove,
2894 +
2895 +       .enable         = samsung_lte_panel_enable,
2896 +       .disable        = samsung_lte_panel_disable,
2897 +       .suspend        = samsung_lte_panel_suspend,
2898 +       .resume         = samsung_lte_panel_resume,
2899 +
2900 +       .driver         = {
2901 +               .name   = "samsung_lte_panel",
2902 +               .owner  = THIS_MODULE,
2903 +       },
2904 +};
2905 +
2906 +static int __init samsung_lte_panel_drv_init(void)
2907 +{
2908 +       return omap_dss_register_driver(&samsung_lte_driver);
2909 +}
2910 +
2911 +static void __exit samsung_lte_panel_drv_exit(void)
2912 +{
2913 +       omap_dss_unregister_driver(&samsung_lte_driver);
2914 +}
2915 +
2916 +module_init(samsung_lte_panel_drv_init);
2917 +module_exit(samsung_lte_panel_drv_exit);
2918 +MODULE_LICENSE("GPL");
2919 diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
2920 new file mode 100644
2921 index 0000000..2f8f0df
2922 --- /dev/null
2923 +++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
2924 @@ -0,0 +1,153 @@
2925 +/*
2926 + * LCD panel driver for Sharp LS037V7DW01
2927 + *
2928 + * Copyright (C) 2008 Nokia Corporation
2929 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
2930 + *
2931 + * This program is free software; you can redistribute it and/or modify it
2932 + * under the terms of the GNU General Public License version 2 as published by
2933 + * the Free Software Foundation.
2934 + *
2935 + * This program is distributed in the hope that it will be useful, but WITHOUT
2936 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2937 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
2938 + * more details.
2939 + *
2940 + * You should have received a copy of the GNU General Public License along with
2941 + * this program.  If not, see <http://www.gnu.org/licenses/>.
2942 + */
2943 +
2944 +#include <linux/module.h>
2945 +#include <linux/delay.h>
2946 +#include <linux/device.h>
2947 +#include <linux/regulator/consumer.h>
2948 +#include <linux/err.h>
2949 +
2950 +#include <mach/display.h>
2951 +
2952 +struct sharp_data {
2953 +       /* XXX This regulator should actually be in SDP board file, not here,
2954 +        * as it doesn't actually power the LCD, but something else that
2955 +        * affects the output to LCD (I think. Somebody clarify). It doesn't do
2956 +        * harm here, as SDP is the only board using this currently */
2957 +       struct regulator *vdvi_reg;
2958 +};
2959 +
2960 +static struct omap_video_timings sharp_ls_timings = {
2961 +       .x_res = 480,
2962 +       .y_res = 640,
2963 +
2964 +       .pixel_clock    = 19200,
2965 +
2966 +       .hsw            = 2,
2967 +       .hfp            = 1,
2968 +       .hbp            = 28,
2969 +
2970 +       .vsw            = 1,
2971 +       .vfp            = 1,
2972 +       .vbp            = 1,
2973 +};
2974 +
2975 +static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
2976 +{
2977 +       struct sharp_data *sd;
2978 +
2979 +       dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
2980 +               OMAP_DSS_LCD_IHS;
2981 +       dssdev->panel.acb = 0x28;
2982 +       dssdev->panel.timings = sharp_ls_timings;
2983 +
2984 +       sd = kzalloc(sizeof(*sd), GFP_KERNEL);
2985 +       if (!sd)
2986 +               return -ENOMEM;
2987 +
2988 +       dev_set_drvdata(&dssdev->dev, sd);
2989 +
2990 +       sd->vdvi_reg = regulator_get(&dssdev->dev, "vdvi");
2991 +       if (IS_ERR(sd->vdvi_reg)) {
2992 +               kfree(sd);
2993 +               pr_err("failed to get VDVI regulator\n");
2994 +               return PTR_ERR(sd->vdvi_reg);
2995 +       }
2996 +
2997 +       return 0;
2998 +}
2999 +
3000 +static void sharp_ls_panel_remove(struct omap_dss_device *dssdev)
3001 +{
3002 +       struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
3003 +
3004 +       regulator_put(sd->vdvi_reg);
3005 +
3006 +       kfree(sd);
3007 +}
3008 +
3009 +static int sharp_ls_panel_enable(struct omap_dss_device *dssdev)
3010 +{
3011 +       struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
3012 +       int r = 0;
3013 +
3014 +       /* wait couple of vsyncs until enabling the LCD */
3015 +       msleep(50);
3016 +
3017 +       regulator_enable(sd->vdvi_reg);
3018 +
3019 +       if (dssdev->platform_enable)
3020 +               r = dssdev->platform_enable(dssdev);
3021 +
3022 +       return r;
3023 +}
3024 +
3025 +static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
3026 +{
3027 +       struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
3028 +
3029 +       if (dssdev->platform_disable)
3030 +               dssdev->platform_disable(dssdev);
3031 +
3032 +       regulator_disable(sd->vdvi_reg);
3033 +
3034 +       /* wait at least 5 vsyncs after disabling the LCD */
3035 +
3036 +       msleep(100);
3037 +}
3038 +
3039 +static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev)
3040 +{
3041 +       sharp_ls_panel_disable(dssdev);
3042 +       return 0;
3043 +}
3044 +
3045 +static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
3046 +{
3047 +       return sharp_ls_panel_enable(dssdev);
3048 +}
3049 +
3050 +static struct omap_dss_driver sharp_ls_driver = {
3051 +       .probe          = sharp_ls_panel_probe,
3052 +       .remove         = sharp_ls_panel_remove,
3053 +
3054 +       .enable         = sharp_ls_panel_enable,
3055 +       .disable        = sharp_ls_panel_disable,
3056 +       .suspend        = sharp_ls_panel_suspend,
3057 +       .resume         = sharp_ls_panel_resume,
3058 +
3059 +       .driver         = {
3060 +               .name   = "sharp_ls_panel",
3061 +               .owner  = THIS_MODULE,
3062 +       },
3063 +};
3064 +
3065 +static int __init sharp_ls_panel_drv_init(void)
3066 +{
3067 +       return omap_dss_register_driver(&sharp_ls_driver);
3068 +}
3069 +
3070 +static void __exit sharp_ls_panel_drv_exit(void)
3071 +{
3072 +       omap_dss_unregister_driver(&sharp_ls_driver);
3073 +}
3074 +
3075 +module_init(sharp_ls_panel_drv_init);
3076 +module_exit(sharp_ls_panel_drv_exit);
3077 +MODULE_LICENSE("GPL");
3078 diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
3079 new file mode 100644
3080 index 0000000..84f0d47
3081 --- /dev/null
3082 +++ b/drivers/video/omap2/displays/panel-taal.c
3083 @@ -0,0 +1,900 @@
3084 +/*
3085 + * Taal DSI command mode panel
3086 + *
3087 + * Copyright (C) 2009 Nokia Corporation
3088 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
3089 + *
3090 + * This program is free software; you can redistribute it and/or modify it
3091 + * under the terms of the GNU General Public License version 2 as published by
3092 + * the Free Software Foundation.
3093 + *
3094 + * This program is distributed in the hope that it will be useful, but WITHOUT
3095 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3096 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
3097 + * more details.
3098 + *
3099 + * You should have received a copy of the GNU General Public License along with
3100 + * this program.  If not, see <http://www.gnu.org/licenses/>.
3101 + */
3102 +
3103 +/*#define DEBUG*/
3104 +
3105 +#include <linux/module.h>
3106 +#include <linux/delay.h>
3107 +#include <linux/err.h>
3108 +#include <linux/jiffies.h>
3109 +#include <linux/sched.h>
3110 +#include <linux/backlight.h>
3111 +#include <linux/fb.h>
3112 +#include <linux/interrupt.h>
3113 +#include <linux/gpio.h>
3114 +#include <linux/completion.h>
3115 +
3116 +#include <mach/display.h>
3117 +
3118 +/* DSI Virtual channel. Hardcoded for now. */
3119 +#define TCH 0
3120 +
3121 +#define DCS_READ_NUM_ERRORS    0x05
3122 +#define DCS_READ_POWER_MODE    0x0a
3123 +#define DCS_READ_MADCTL                0x0b
3124 +#define DCS_READ_PIXEL_FORMAT  0x0c
3125 +#define DCS_SLEEP_IN           0x10
3126 +#define DCS_SLEEP_OUT          0x11
3127 +#define DCS_DISPLAY_OFF                0x28
3128 +#define DCS_DISPLAY_ON         0x29
3129 +#define DCS_COLUMN_ADDR                0x2a
3130 +#define DCS_PAGE_ADDR          0x2b
3131 +#define DCS_MEMORY_WRITE       0x2c
3132 +#define DCS_TEAR_OFF           0x34
3133 +#define DCS_TEAR_ON            0x35
3134 +#define DCS_MEM_ACC_CTRL       0x36
3135 +#define DCS_PIXEL_FORMAT       0x3a
3136 +#define DCS_BRIGHTNESS         0x51
3137 +#define DCS_CTRL_DISPLAY       0x53
3138 +#define DCS_WRITE_CABC         0x55
3139 +#define DCS_READ_CABC          0x56
3140 +#define DCS_GET_ID1            0xda
3141 +#define DCS_GET_ID2            0xdb
3142 +#define DCS_GET_ID3            0xdc
3143 +
3144 +struct taal_data {
3145 +       struct backlight_device *bldev;
3146 +
3147 +       unsigned long   hw_guard_end;   /* next value of jiffies when we can
3148 +                                        * issue the next sleep in/out command
3149 +                                        */
3150 +       unsigned long   hw_guard_wait;  /* max guard time in jiffies */
3151 +
3152 +       struct omap_dss_device *dssdev;
3153 +
3154 +       bool enabled;
3155 +       u8 rotate;
3156 +       bool mirror;
3157 +
3158 +       bool te_enabled;
3159 +       bool use_ext_te;
3160 +       struct completion te_completion;
3161 +
3162 +       bool use_dsi_bl;
3163 +
3164 +       bool cabc_broken;
3165 +       unsigned cabc_mode;
3166 +
3167 +       bool intro_printed;
3168 +};
3169 +
3170 +static void hw_guard_start(struct taal_data *td, int guard_msec)
3171 +{
3172 +       td->hw_guard_wait = msecs_to_jiffies(guard_msec);
3173 +       td->hw_guard_end = jiffies + td->hw_guard_wait;
3174 +}
3175 +
3176 +static void hw_guard_wait(struct taal_data *td)
3177 +{
3178 +       unsigned long wait = td->hw_guard_end - jiffies;
3179 +
3180 +       if ((long)wait > 0 && wait <= td->hw_guard_wait) {
3181 +               set_current_state(TASK_UNINTERRUPTIBLE);
3182 +               schedule_timeout(wait);
3183 +       }
3184 +}
3185 +
3186 +static int taal_dcs_read_1(u8 dcs_cmd, u8 *data)
3187 +{
3188 +       int r;
3189 +       u8 buf[1];
3190 +
3191 +       r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1);
3192 +
3193 +       if (r < 0)
3194 +               return r;
3195 +
3196 +       *data = buf[0];
3197 +
3198 +       return 0;
3199 +}
3200 +
3201 +static int taal_dcs_write_0(u8 dcs_cmd)
3202 +{
3203 +       return dsi_vc_dcs_write(TCH, &dcs_cmd, 1);
3204 +}
3205 +
3206 +static int taal_dcs_write_1(u8 dcs_cmd, u8 param)
3207 +{
3208 +       u8 buf[2];
3209 +       buf[0] = dcs_cmd;
3210 +       buf[1] = param;
3211 +       return dsi_vc_dcs_write(TCH, buf, 2);
3212 +}
3213 +
3214 +static int taal_sleep_in(struct taal_data *td)
3215 +
3216 +{
3217 +       u8 cmd;
3218 +       int r;
3219 +
3220 +       hw_guard_wait(td);
3221 +
3222 +       cmd = DCS_SLEEP_IN;
3223 +       r = dsi_vc_dcs_write_nosync(TCH, &cmd, 1);
3224 +       if (r)
3225 +               return r;
3226 +
3227 +       hw_guard_start(td, 120);
3228 +
3229 +       msleep(5);
3230 +
3231 +       return 0;
3232 +}
3233 +
3234 +static int taal_sleep_out(struct taal_data *td)
3235 +{
3236 +       int r;
3237 +
3238 +       hw_guard_wait(td);
3239 +
3240 +       r = taal_dcs_write_0(DCS_SLEEP_OUT);
3241 +       if (r)
3242 +               return r;
3243 +
3244 +       hw_guard_start(td, 120);
3245 +
3246 +       msleep(5);
3247 +
3248 +       return 0;
3249 +}
3250 +
3251 +static int taal_get_id(u8 *id1, u8 *id2, u8 *id3)
3252 +{
3253 +       int r;
3254 +
3255 +       r = taal_dcs_read_1(DCS_GET_ID1, id1);
3256 +       if (r)
3257 +               return r;
3258 +       r = taal_dcs_read_1(DCS_GET_ID2, id2);
3259 +       if (r)
3260 +               return r;
3261 +       r = taal_dcs_read_1(DCS_GET_ID3, id3);
3262 +       if (r)
3263 +               return r;
3264 +
3265 +       return 0;
3266 +}
3267 +
3268 +static int taal_set_addr_mode(u8 rotate, bool mirror)
3269 +{
3270 +       int r;
3271 +       u8 mode;
3272 +       int b5, b6, b7;
3273 +
3274 +       r = taal_dcs_read_1(DCS_READ_MADCTL, &mode);
3275 +       if (r)
3276 +               return r;
3277 +
3278 +       switch (rotate) {
3279 +       default:
3280 +       case 0:
3281 +               b7 = 0;
3282 +               b6 = 0;
3283 +               b5 = 0;
3284 +               break;
3285 +       case 1:
3286 +               b7 = 0;
3287 +               b6 = 1;
3288 +               b5 = 1;
3289 +               break;
3290 +       case 2:
3291 +               b7 = 1;
3292 +               b6 = 1;
3293 +               b5 = 0;
3294 +               break;
3295 +       case 3:
3296 +               b7 = 1;
3297 +               b6 = 0;
3298 +               b5 = 1;
3299 +               break;
3300 +       }
3301 +
3302 +       if (mirror)
3303 +               b6 = !b6;
3304 +
3305 +       mode &= ~((1<<7) | (1<<6) | (1<<5));
3306 +       mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
3307 +
3308 +       return taal_dcs_write_1(DCS_MEM_ACC_CTRL, mode);
3309 +}
3310 +
3311 +static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h)
3312 +{
3313 +       int r;
3314 +       u16 x1 = x;
3315 +       u16 x2 = x + w - 1;
3316 +       u16 y1 = y;
3317 +       u16 y2 = y + h - 1;
3318 +
3319 +       u8 buf[5];
3320 +       buf[0] = DCS_COLUMN_ADDR;
3321 +       buf[1] = (x1 >> 8) & 0xff;
3322 +       buf[2] = (x1 >> 0) & 0xff;
3323 +       buf[3] = (x2 >> 8) & 0xff;
3324 +       buf[4] = (x2 >> 0) & 0xff;
3325 +
3326 +       r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf));
3327 +       if (r)
3328 +               return r;
3329 +
3330 +       buf[0] = DCS_PAGE_ADDR;
3331 +       buf[1] = (y1 >> 8) & 0xff;
3332 +       buf[2] = (y1 >> 0) & 0xff;
3333 +       buf[3] = (y2 >> 8) & 0xff;
3334 +       buf[4] = (y2 >> 0) & 0xff;
3335 +
3336 +       r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf));
3337 +       if (r)
3338 +               return r;
3339 +
3340 +       dsi_vc_send_bta_sync(TCH);
3341 +
3342 +       return r;
3343 +}
3344 +
3345 +static int taal_bl_update_status(struct backlight_device *dev)
3346 +{
3347 +       struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
3348 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3349 +       int r;
3350 +       int level;
3351 +
3352 +       if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
3353 +                       dev->props.power == FB_BLANK_UNBLANK)
3354 +               level = dev->props.brightness;
3355 +       else
3356 +               level = 0;
3357 +
3358 +       dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
3359 +
3360 +       if (td->use_dsi_bl) {
3361 +               if (td->enabled) {
3362 +                       dsi_bus_lock();
3363 +                       r = taal_dcs_write_1(DCS_BRIGHTNESS, level);
3364 +                       dsi_bus_unlock();
3365 +                       if (r)
3366 +                               return r;
3367 +               }
3368 +       } else {
3369 +               if (!dssdev->set_backlight)
3370 +                       return -EINVAL;
3371 +
3372 +               r = dssdev->set_backlight(dssdev, level);
3373 +               if (r)
3374 +                       return r;
3375 +       }
3376 +
3377 +       return 0;
3378 +}
3379 +
3380 +static int taal_bl_get_intensity(struct backlight_device *dev)
3381 +{
3382 +       if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
3383 +                       dev->props.power == FB_BLANK_UNBLANK)
3384 +               return dev->props.brightness;
3385 +
3386 +       return 0;
3387 +}
3388 +
3389 +static struct backlight_ops taal_bl_ops = {
3390 +       .get_brightness = taal_bl_get_intensity,
3391 +       .update_status  = taal_bl_update_status,
3392 +};
3393 +
3394 +static void taal_get_timings(struct omap_dss_device *dssdev,
3395 +                       struct omap_video_timings *timings)
3396 +{
3397 +       *timings = dssdev->panel.timings;
3398 +}
3399 +
3400 +static void taal_get_resolution(struct omap_dss_device *dssdev,
3401 +               u16 *xres, u16 *yres)
3402 +{
3403 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3404 +
3405 +       if (td->rotate == 0 || td->rotate == 2) {
3406 +               *xres = dssdev->panel.timings.x_res;
3407 +               *yres = dssdev->panel.timings.y_res;
3408 +       } else {
3409 +               *yres = dssdev->panel.timings.x_res;
3410 +               *xres = dssdev->panel.timings.y_res;
3411 +       }
3412 +}
3413 +
3414 +static irqreturn_t taal_te_isr(int irq, void *data)
3415 +{
3416 +       struct omap_dss_device *dssdev = data;
3417 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3418 +
3419 +       complete_all(&td->te_completion);
3420 +
3421 +       return IRQ_HANDLED;
3422 +}
3423 +
3424 +static ssize_t taal_num_errors_show(struct device *dev,
3425 +               struct device_attribute *attr, char *buf)
3426 +{
3427 +       struct omap_dss_device *dssdev = to_dss_device(dev);
3428 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3429 +       u8 errors;
3430 +       int r;
3431 +
3432 +       if (td->enabled) {
3433 +               dsi_bus_lock();
3434 +               r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors);
3435 +               dsi_bus_unlock();
3436 +       } else {
3437 +               r = -ENODEV;
3438 +       }
3439 +
3440 +       if (r)
3441 +               return r;
3442 +
3443 +       return snprintf(buf, PAGE_SIZE, "%d\n", errors);
3444 +}
3445 +
3446 +static ssize_t taal_hw_revision_show(struct device *dev,
3447 +               struct device_attribute *attr, char *buf)
3448 +{
3449 +       struct omap_dss_device *dssdev = to_dss_device(dev);
3450 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3451 +       u8 id1, id2, id3;
3452 +       int r;
3453 +
3454 +       if (td->enabled) {
3455 +               dsi_bus_lock();
3456 +               r = taal_get_id(&id1, &id2, &id3);
3457 +               dsi_bus_unlock();
3458 +       } else {
3459 +               r = -ENODEV;
3460 +       }
3461 +
3462 +       if (r)
3463 +               return r;
3464 +
3465 +       return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3);
3466 +}
3467 +
3468 +static const char *cabc_modes[] = {
3469 +       "off",          /* used also always when CABC is not supported */
3470 +       "ui",
3471 +       "still-image",
3472 +       "moving-image",
3473 +};
3474 +
3475 +static ssize_t show_cabc_mode(struct device *dev,
3476 +               struct device_attribute *attr,
3477 +               char *buf)
3478 +{
3479 +       struct omap_dss_device *dssdev = to_dss_device(dev);
3480 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3481 +       const char *mode_str;
3482 +       int mode;
3483 +       int len;
3484 +
3485 +       mode = td->cabc_mode;
3486 +
3487 +       mode_str = "unknown";
3488 +       if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
3489 +               mode_str = cabc_modes[mode];
3490 +       len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
3491 +
3492 +       return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
3493 +}
3494 +
3495 +static ssize_t store_cabc_mode(struct device *dev,
3496 +               struct device_attribute *attr,
3497 +               const char *buf, size_t count)
3498 +{
3499 +       struct omap_dss_device *dssdev = to_dss_device(dev);
3500 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3501 +       int i;
3502 +
3503 +       for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
3504 +               if (sysfs_streq(cabc_modes[i], buf))
3505 +                       break;
3506 +       }
3507 +
3508 +       if (i == ARRAY_SIZE(cabc_modes))
3509 +               return -EINVAL;
3510 +
3511 +       if (td->enabled) {
3512 +               dsi_bus_lock();
3513 +               if (!td->cabc_broken)
3514 +                       taal_dcs_write_1(DCS_WRITE_CABC, i);
3515 +               dsi_bus_unlock();
3516 +       }
3517 +
3518 +       td->cabc_mode = i;
3519 +
3520 +       return count;
3521 +}
3522 +
3523 +static ssize_t show_cabc_available_modes(struct device *dev,
3524 +               struct device_attribute *attr,
3525 +               char *buf)
3526 +{
3527 +       int len;
3528 +       int i;
3529 +
3530 +       for (i = 0, len = 0;
3531 +            len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
3532 +               len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
3533 +                       i ? " " : "", cabc_modes[i],
3534 +                       i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
3535 +
3536 +       return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
3537 +}
3538 +
3539 +static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL);
3540 +static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL);
3541 +static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
3542 +               show_cabc_mode, store_cabc_mode);
3543 +static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
3544 +               show_cabc_available_modes, NULL);
3545 +
3546 +static struct attribute *taal_attrs[] = {
3547 +       &dev_attr_num_dsi_errors.attr,
3548 +       &dev_attr_hw_revision.attr,
3549 +       &dev_attr_cabc_mode.attr,
3550 +       &dev_attr_cabc_available_modes.attr,
3551 +       NULL,
3552 +};
3553 +
3554 +static struct attribute_group taal_attr_group = {
3555 +       .attrs = taal_attrs,
3556 +};
3557 +
3558 +static int taal_probe(struct omap_dss_device *dssdev)
3559 +{
3560 +       struct taal_data *td;
3561 +       struct backlight_device *bldev;
3562 +       int r;
3563 +
3564 +       const struct omap_video_timings taal_panel_timings = {
3565 +               .x_res          = 864,
3566 +               .y_res          = 480,
3567 +       };
3568 +
3569 +       dev_dbg(&dssdev->dev, "probe\n");
3570 +
3571 +       dssdev->panel.config = OMAP_DSS_LCD_TFT;
3572 +       dssdev->panel.timings = taal_panel_timings;
3573 +       dssdev->ctrl.pixel_size = 24;
3574 +
3575 +       td = kzalloc(sizeof(*td), GFP_KERNEL);
3576 +       if (!td) {
3577 +               r = -ENOMEM;
3578 +               goto err0;
3579 +       }
3580 +
3581 +       dev_set_drvdata(&dssdev->dev, td);
3582 +
3583 +       dssdev->get_timings = taal_get_timings;
3584 +       dssdev->get_resolution = taal_get_resolution;
3585 +
3586 +       /* if no platform set_backlight() defined, presume DSI backlight
3587 +        * control */
3588 +       if (!dssdev->set_backlight)
3589 +               td->use_dsi_bl = true;
3590 +
3591 +       bldev = backlight_device_register("taal", &dssdev->dev, dssdev,
3592 +                       &taal_bl_ops);
3593 +       if (IS_ERR(bldev)) {
3594 +               r = PTR_ERR(bldev);
3595 +               goto err1;
3596 +       }
3597 +
3598 +       td->bldev = bldev;
3599 +
3600 +       bldev->props.fb_blank = FB_BLANK_UNBLANK;
3601 +       bldev->props.power = FB_BLANK_UNBLANK;
3602 +       if (td->use_dsi_bl) {
3603 +               bldev->props.max_brightness = 255;
3604 +               bldev->props.brightness = 255;
3605 +       } else {
3606 +               bldev->props.max_brightness = 127;
3607 +               bldev->props.brightness = 127;
3608 +       }
3609 +
3610 +       taal_bl_update_status(bldev);
3611 +
3612 +       if (dssdev->phy.dsi.ext_te) {
3613 +               int gpio = dssdev->phy.dsi.ext_te_gpio;
3614 +
3615 +               r = gpio_request(gpio, "taal irq");
3616 +               if (r) {
3617 +                       dev_err(&dssdev->dev, "GPIO request failed\n");
3618 +                       goto err2;
3619 +               }
3620 +
3621 +               gpio_direction_input(gpio);
3622 +
3623 +               r = request_irq(gpio_to_irq(gpio), taal_te_isr,
3624 +                               IRQF_DISABLED | IRQF_TRIGGER_RISING,
3625 +                               "taal vsync", dssdev);
3626 +
3627 +               if (r) {
3628 +                       dev_err(&dssdev->dev, "IRQ request failed\n");
3629 +                       gpio_free(gpio);
3630 +                       goto err2;
3631 +               }
3632 +
3633 +               init_completion(&td->te_completion);
3634 +
3635 +               td->use_ext_te = true;
3636 +       }
3637 +
3638 +       r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group);
3639 +       if (r) {
3640 +               dev_err(&dssdev->dev, "failed to create sysfs files\n");
3641 +               goto err3;
3642 +       }
3643 +
3644 +       return 0;
3645 +err3:
3646 +       if (td->use_ext_te) {
3647 +               int gpio = dssdev->phy.dsi.ext_te_gpio;
3648 +               free_irq(gpio_to_irq(gpio), dssdev);
3649 +               gpio_free(gpio);
3650 +       }
3651 +err2:
3652 +       backlight_device_unregister(bldev);
3653 +err1:
3654 +       kfree(td);
3655 +err0:
3656 +       return r;
3657 +}
3658 +
3659 +static void taal_remove(struct omap_dss_device *dssdev)
3660 +{
3661 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3662 +       struct backlight_device *bldev;
3663 +
3664 +       dev_dbg(&dssdev->dev, "remove\n");
3665 +
3666 +       sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);
3667 +
3668 +       if (td->use_ext_te) {
3669 +               int gpio = dssdev->phy.dsi.ext_te_gpio;
3670 +               free_irq(gpio_to_irq(gpio), dssdev);
3671 +               gpio_free(gpio);
3672 +       }
3673 +
3674 +       bldev = td->bldev;
3675 +       bldev->props.power = FB_BLANK_POWERDOWN;
3676 +       taal_bl_update_status(bldev);
3677 +       backlight_device_unregister(bldev);
3678 +
3679 +       kfree(td);
3680 +}
3681 +
3682 +static int taal_enable(struct omap_dss_device *dssdev)
3683 +{
3684 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3685 +       u8 id1, id2, id3;
3686 +       int r;
3687 +
3688 +       dev_dbg(&dssdev->dev, "enable\n");
3689 +
3690 +       if (dssdev->platform_enable) {
3691 +               r = dssdev->platform_enable(dssdev);
3692 +               if (r)
3693 +                       return r;
3694 +       }
3695 +
3696 +       /* it seems we have to wait a bit until taal is ready */
3697 +       msleep(5);
3698 +
3699 +       r = taal_sleep_out(td);
3700 +       if (r)
3701 +               return r;
3702 +
3703 +       r = taal_get_id(&id1, &id2, &id3);
3704 +       if (r)
3705 +               return r;
3706 +
3707 +       /* on early revisions CABC is broken */
3708 +       if (id2 == 0x00 || id2 == 0xff || id2 == 0x81)
3709 +               td->cabc_broken = true;
3710 +
3711 +       taal_dcs_write_1(DCS_BRIGHTNESS, 0xff);
3712 +       taal_dcs_write_1(DCS_CTRL_DISPLAY, (1<<2) | (1<<5)); /* BL | BCTRL */
3713 +
3714 +       taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
3715 +
3716 +       taal_set_addr_mode(td->rotate, td->mirror);
3717 +       if (!td->cabc_broken)
3718 +               taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode);
3719 +
3720 +       taal_dcs_write_0(DCS_DISPLAY_ON);
3721 +
3722 +       td->enabled = 1;
3723 +
3724 +       if (!td->intro_printed) {
3725 +               dev_info(&dssdev->dev, "revision %02x.%02x.%02x\n",
3726 +                               id1, id2, id3);
3727 +               if (td->cabc_broken)
3728 +                       dev_info(&dssdev->dev,
3729 +                                       "old Taal version, CABC disabled\n");
3730 +               td->intro_printed = true;
3731 +       }
3732 +
3733 +       return 0;
3734 +}
3735 +
3736 +static void taal_disable(struct omap_dss_device *dssdev)
3737 +{
3738 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3739 +
3740 +       dev_dbg(&dssdev->dev, "disable\n");
3741 +
3742 +       taal_dcs_write_0(DCS_DISPLAY_OFF);
3743 +       taal_sleep_in(td);
3744 +
3745 +       /* wait a bit so that the message goes through */
3746 +       msleep(10);
3747 +
3748 +       if (dssdev->platform_disable)
3749 +               dssdev->platform_disable(dssdev);
3750 +
3751 +       td->enabled = 0;
3752 +}
3753 +
3754 +static int taal_suspend(struct omap_dss_device *dssdev)
3755 +{
3756 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3757 +       struct backlight_device *bldev = td->bldev;
3758 +
3759 +       bldev->props.power = FB_BLANK_POWERDOWN;
3760 +       taal_bl_update_status(bldev);
3761 +
3762 +       return 0;
3763 +}
3764 +
3765 +static int taal_resume(struct omap_dss_device *dssdev)
3766 +{
3767 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3768 +       struct backlight_device *bldev = td->bldev;
3769 +
3770 +       bldev->props.power = FB_BLANK_UNBLANK;
3771 +       taal_bl_update_status(bldev);
3772 +
3773 +       return 0;
3774 +}
3775 +
3776 +static void taal_setup_update(struct omap_dss_device *dssdev,
3777 +                                   u16 x, u16 y, u16 w, u16 h)
3778 +{
3779 +       taal_set_update_window(x, y, w, h);
3780 +}
3781 +
3782 +static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
3783 +{
3784 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3785 +       int r;
3786 +
3787 +       td->te_enabled = enable;
3788 +
3789 +       if (enable)
3790 +               r = taal_dcs_write_1(DCS_TEAR_ON, 0);
3791 +       else
3792 +               r = taal_dcs_write_0(DCS_TEAR_OFF);
3793 +
3794 +       return r;
3795 +}
3796 +
3797 +static int taal_wait_te(struct omap_dss_device *dssdev)
3798 +{
3799 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3800 +       long wait = msecs_to_jiffies(500);
3801 +
3802 +       if (!td->use_ext_te || !td->te_enabled)
3803 +               return 0;
3804 +
3805 +       INIT_COMPLETION(td->te_completion);
3806 +       wait = wait_for_completion_timeout(&td->te_completion, wait);
3807 +       if (wait == 0) {
3808 +               dev_err(&dssdev->dev, "timeout waiting TE\n");
3809 +               return -ETIME;
3810 +       }
3811 +
3812 +       return 0;
3813 +}
3814 +
3815 +static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
3816 +{
3817 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3818 +       int r;
3819 +
3820 +       dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
3821 +
3822 +       if (td->enabled) {
3823 +               r = taal_set_addr_mode(rotate, td->mirror);
3824 +
3825 +               if (r)
3826 +                       return r;
3827 +       }
3828 +
3829 +       td->rotate = rotate;
3830 +
3831 +       return 0;
3832 +}
3833 +
3834 +static u8 taal_get_rotate(struct omap_dss_device *dssdev)
3835 +{
3836 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3837 +       return td->rotate;
3838 +}
3839 +
3840 +static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
3841 +{
3842 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3843 +       int r;
3844 +
3845 +       dev_dbg(&dssdev->dev, "mirror %d\n", enable);
3846 +
3847 +       if (td->enabled) {
3848 +               r = taal_set_addr_mode(td->rotate, enable);
3849 +
3850 +               if (r)
3851 +                       return r;
3852 +       }
3853 +
3854 +       td->mirror = enable;
3855 +
3856 +       return 0;
3857 +}
3858 +
3859 +static bool taal_get_mirror(struct omap_dss_device *dssdev)
3860 +{
3861 +       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
3862 +       return td->mirror;
3863 +}
3864 +
3865 +static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
3866 +{
3867 +       u8 id1, id2, id3;
3868 +       int r;
3869 +
3870 +       r = taal_dcs_read_1(DCS_GET_ID1, &id1);
3871 +       if (r)
3872 +               return r;
3873 +       r = taal_dcs_read_1(DCS_GET_ID2, &id2);
3874 +       if (r)
3875 +               return r;
3876 +       r = taal_dcs_read_1(DCS_GET_ID3, &id3);
3877 +       if (r)
3878 +               return r;
3879 +
3880 +       return 0;
3881 +}
3882 +
3883 +static int taal_memory_read(struct omap_dss_device *dssdev,
3884 +               void *buf, size_t size,
3885 +               u16 x, u16 y, u16 w, u16 h)
3886 +{
3887 +       int r;
3888 +       int first = 1;
3889 +       int plen;
3890 +       unsigned buf_used = 0;
3891 +
3892 +       if (size < w * h * 3)
3893 +               return -ENOMEM;
3894 +
3895 +       size = min(w * h * 3,
3896 +                       dssdev->panel.timings.x_res *
3897 +                       dssdev->panel.timings.y_res * 3);
3898 +
3899 +       /* plen 1 or 2 goes into short packet. until checksum error is fixed,
3900 +        * use short packets. plen 32 works, but bigger packets seem to cause
3901 +        * an error. */
3902 +       if (size % 2)
3903 +               plen = 1;
3904 +       else
3905 +               plen = 2;
3906 +
3907 +       taal_setup_update(dssdev, x, y, w, h);
3908 +
3909 +       r = dsi_vc_set_max_rx_packet_size(TCH, plen);
3910 +       if (r)
3911 +               return r;
3912 +
3913 +       while (buf_used < size) {
3914 +               u8 dcs_cmd = first ? 0x2e : 0x3e;
3915 +               first = 0;
3916 +
3917 +               r = dsi_vc_dcs_read(TCH, dcs_cmd,
3918 +                               buf + buf_used, size - buf_used);
3919 +
3920 +               if (r < 0) {
3921 +                       dev_err(&dssdev->dev, "read error\n");
3922 +                       goto err;
3923 +               }
3924 +
3925 +               buf_used += r;
3926 +
3927 +               if (r < plen) {
3928 +                       dev_err(&dssdev->dev, "short read\n");
3929 +                       break;
3930 +               }
3931 +       }
3932 +
3933 +       r = buf_used;
3934 +
3935 +err:
3936 +       dsi_vc_set_max_rx_packet_size(TCH, 1);
3937 +
3938 +       return r;
3939 +}
3940 +
3941 +static struct omap_dss_driver taal_driver = {
3942 +       .probe          = taal_probe,
3943 +       .remove         = taal_remove,
3944 +
3945 +       .enable         = taal_enable,
3946 +       .disable        = taal_disable,
3947 +       .suspend        = taal_suspend,
3948 +       .resume         = taal_resume,
3949 +
3950 +       .setup_update   = taal_setup_update,
3951 +       .enable_te      = taal_enable_te,
3952 +       .wait_for_te    = taal_wait_te,
3953 +       .set_rotate     = taal_rotate,
3954 +       .get_rotate     = taal_get_rotate,
3955 +       .set_mirror     = taal_mirror,
3956 +       .get_mirror     = taal_get_mirror,
3957 +       .run_test       = taal_run_test,
3958 +       .memory_read    = taal_memory_read,
3959 +
3960 +       .driver         = {
3961 +               .name   = "taal",
3962 +               .owner  = THIS_MODULE,
3963 +       },
3964 +};
3965 +
3966 +static int __init taal_init(void)
3967 +{
3968 +       omap_dss_register_driver(&taal_driver);
3969 +
3970 +       return 0;
3971 +}
3972 +
3973 +static void __exit taal_exit(void)
3974 +{
3975 +       omap_dss_unregister_driver(&taal_driver);
3976 +}
3977 +
3978 +module_init(taal_init);
3979 +module_exit(taal_exit);
3980 +
3981 +MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
3982 +MODULE_DESCRIPTION("Taal Driver");
3983 +MODULE_LICENSE("GPL");
3984 diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
3985 new file mode 100644
3986 index 0000000..71d8dec
3987 --- /dev/null
3988 +++ b/drivers/video/omap2/dss/Kconfig
3989 @@ -0,0 +1,89 @@
3990 +menuconfig OMAP2_DSS
3991 +        tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)"
3992 +        depends on ARCH_OMAP2 || ARCH_OMAP3
3993 +        help
3994 +          OMAP2/3 Display Subsystem support.
3995 +
3996 +if OMAP2_DSS
3997 +
3998 +config OMAP2_VRAM_SIZE
3999 +       int "VRAM size (MB)"
4000 +       range 0 32
4001 +       default 0
4002 +       help
4003 +         The amount of SDRAM to reserve at boot time for video RAM use.
4004 +         This VRAM will be used by omapfb and other drivers that need
4005 +         large continuous RAM area for video use.
4006 +
4007 +         You can also set this with "vram=<bytes>" kernel argument, or
4008 +         in the board file.
4009 +
4010 +config OMAP2_DSS_DEBUG_SUPPORT
4011 +        bool "Debug support"
4012 +       default y
4013 +       help
4014 +         This enables debug messages. You need to enable printing
4015 +         with 'debug' module parameter.
4016 +
4017 +config OMAP2_DSS_RFBI
4018 +       bool "RFBI support"
4019 +        default n
4020 +       help
4021 +         MIPI DBI, or RFBI (Remote Framebuffer Interface), support.
4022 +
4023 +config OMAP2_DSS_VENC
4024 +       bool "VENC support"
4025 +        default y
4026 +       help
4027 +         OMAP Video Encoder support.
4028 +
4029 +config OMAP2_DSS_SDI
4030 +       bool "SDI support"
4031 +       depends on ARCH_OMAP3
4032 +        default n
4033 +       help
4034 +         SDI (Serial Display Interface) support.
4035 +
4036 +config OMAP2_DSS_DSI
4037 +       bool "DSI support"
4038 +       depends on ARCH_OMAP3
4039 +        default n
4040 +       help
4041 +         MIPI DSI support.
4042 +
4043 +config OMAP2_DSS_USE_DSI_PLL
4044 +       bool "Use DSI PLL for PCLK (EXPERIMENTAL)"
4045 +       default n
4046 +       depends on OMAP2_DSS_DSI
4047 +       help
4048 +         Use DSI PLL to generate pixel clock.  Currently only for DPI output.
4049 +         DSI PLL can be used to generate higher and more precise pixel clocks.
4050 +
4051 +config OMAP2_DSS_FAKE_VSYNC
4052 +       bool "Fake VSYNC irq from manual update displays"
4053 +       default n
4054 +       help
4055 +         If this is selected, DSI will generate a fake DISPC VSYNC interrupt
4056 +         when DSI has sent a frame. This is only needed with DSI or RFBI
4057 +         displays using manual mode, and you want VSYNC to, for example,
4058 +         time animation.
4059 +
4060 +config OMAP2_DSS_MIN_FCK_PER_PCK
4061 +       int "Minimum FCK/PCK ratio (for scaling)"
4062 +       range 0 32
4063 +       default 0
4064 +       help
4065 +         This can be used to adjust the minimum FCK/PCK ratio.
4066 +
4067 +         With this you can make sure that DISPC FCK is at least
4068 +         n x PCK. Video plane scaling requires higher FCK than
4069 +         normally.
4070 +
4071 +         If this is set to 0, there's no extra constraint on the
4072 +         DISPC FCK. However, the FCK will at minimum be
4073 +         2xPCK (if active matrix) or 3xPCK (if passive matrix).
4074 +
4075 +         Max FCK is 173MHz, so this doesn't work if your PCK
4076 +         is very high.
4077 +
4078 +endif
4079 diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
4080 new file mode 100644
4081 index 0000000..980c72c
4082 --- /dev/null
4083 +++ b/drivers/video/omap2/dss/Makefile
4084 @@ -0,0 +1,6 @@
4085 +obj-$(CONFIG_OMAP2_DSS) += omapdss.o
4086 +omapdss-y := core.o dss.o dispc.o dpi.o display.o manager.o overlay.o
4087 +omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
4088 +omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
4089 +omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
4090 +omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
4091 diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
4092 new file mode 100644
4093 index 0000000..e8d430c
4094 --- /dev/null
4095 +++ b/drivers/video/omap2/dss/core.c
4096 @@ -0,0 +1,917 @@
4097 +/*
4098 + * linux/drivers/video/omap2/dss/core.c
4099 + *
4100 + * Copyright (C) 2009 Nokia Corporation
4101 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4102 + *
4103 + * Some code and ideas taken from drivers/video/omap/ driver
4104 + * by Imre Deak.
4105 + *
4106 + * This program is free software; you can redistribute it and/or modify it
4107 + * under the terms of the GNU General Public License version 2 as published by
4108 + * the Free Software Foundation.
4109 + *
4110 + * This program is distributed in the hope that it will be useful, but WITHOUT
4111 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4112 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
4113 + * more details.
4114 + *
4115 + * You should have received a copy of the GNU General Public License along with
4116 + * this program.  If not, see <http://www.gnu.org/licenses/>.
4117 + */
4118 +
4119 +#define DSS_SUBSYS_NAME "CORE"
4120 +
4121 +#include <linux/kernel.h>
4122 +#include <linux/module.h>
4123 +#include <linux/clk.h>
4124 +#include <linux/err.h>
4125 +#include <linux/platform_device.h>
4126 +#include <linux/seq_file.h>
4127 +#include <linux/debugfs.h>
4128 +#include <linux/io.h>
4129 +#include <linux/device.h>
4130 +
4131 +#include <mach/display.h>
4132 +#include <mach/clock.h>
4133 +
4134 +#include "dss.h"
4135 +
4136 +static struct {
4137 +       struct platform_device *pdev;
4138 +       int             ctx_id;
4139 +
4140 +       struct clk      *dss_ick;
4141 +       struct clk      *dss1_fck;
4142 +       struct clk      *dss2_fck;
4143 +       struct clk      *dss_54m_fck;
4144 +       struct clk      *dss_96m_fck;
4145 +       unsigned        num_clks_enabled;
4146 +} core;
4147 +
4148 +static void dss_clk_enable_all_no_ctx(void);
4149 +static void dss_clk_disable_all_no_ctx(void);
4150 +static void dss_clk_enable_no_ctx(enum dss_clock clks);
4151 +static void dss_clk_disable_no_ctx(enum dss_clock clks);
4152 +
4153 +static char *def_disp_name;
4154 +module_param_named(def_disp, def_disp_name, charp, 0);
4155 +MODULE_PARM_DESC(def_disp_name, "default display name");
4156 +
4157 +#ifdef DEBUG
4158 +unsigned int dss_debug;
4159 +module_param_named(debug, dss_debug, bool, 0644);
4160 +#endif
4161 +
4162 +/* CONTEXT */
4163 +static int dss_get_ctx_id(void)
4164 +{
4165 +       struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
4166 +       int r;
4167 +
4168 +       if (!pdata->get_last_off_on_transaction_id)
4169 +               return 0;
4170 +       r = pdata->get_last_off_on_transaction_id(&core.pdev->dev);
4171 +       if (r < 0) {
4172 +               dev_err(&core.pdev->dev, "getting transaction ID failed, "
4173 +                               "will force context restore\n");
4174 +               r = -1;
4175 +       }
4176 +       return r;
4177 +}
4178 +
4179 +int dss_need_ctx_restore(void)
4180 +{
4181 +       int id = dss_get_ctx_id();
4182 +
4183 +       if (id < 0 || id != core.ctx_id) {
4184 +               DSSDBG("ctx id %d -> id %d\n",
4185 +                               core.ctx_id, id);
4186 +               core.ctx_id = id;
4187 +               return 1;
4188 +       } else {
4189 +               return 0;
4190 +       }
4191 +}
4192 +
4193 +static void save_all_ctx(void)
4194 +{
4195 +       DSSDBG("save context\n");
4196 +
4197 +       dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
4198 +
4199 +       dss_save_context();
4200 +       dispc_save_context();
4201 +#ifdef CONFIG_OMAP2_DSS_DSI
4202 +       dsi_save_context();
4203 +#endif
4204 +
4205 +       dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
4206 +}
4207 +
4208 +static void restore_all_ctx(void)
4209 +{
4210 +       DSSDBG("restore context\n");
4211 +
4212 +       dss_clk_enable_all_no_ctx();
4213 +
4214 +       dss_restore_context();
4215 +       dispc_restore_context();
4216 +#ifdef CONFIG_OMAP2_DSS_DSI
4217 +       dsi_restore_context();
4218 +#endif
4219 +
4220 +       dss_clk_disable_all_no_ctx();
4221 +}
4222 +
4223 +/* CLOCKS */
4224 +void dss_dump_clocks(struct seq_file *s)
4225 +{
4226 +       int i;
4227 +       struct clk *clocks[5] = {
4228 +               core.dss_ick,
4229 +               core.dss1_fck,
4230 +               core.dss2_fck,
4231 +               core.dss_54m_fck,
4232 +               core.dss_96m_fck
4233 +       };
4234 +
4235 +       seq_printf(s, "- dss -\n");
4236 +
4237 +       seq_printf(s, "internal clk count\t%u\n", core.num_clks_enabled);
4238 +
4239 +       for (i = 0; i < 5; i++) {
4240 +               if (!clocks[i])
4241 +                       continue;
4242 +               seq_printf(s, "%-15s\t%lu\t%d\n",
4243 +                               clocks[i]->name,
4244 +                               clk_get_rate(clocks[i]),
4245 +                               clocks[i]->usecount);
4246 +       }
4247 +}
4248 +
4249 +static int dss_get_clock(struct clk **clock, const char *clk_name)
4250 +{
4251 +       struct clk *clk;
4252 +
4253 +       clk = clk_get(&core.pdev->dev, clk_name);
4254 +
4255 +       if (IS_ERR(clk)) {
4256 +               DSSERR("can't get clock %s", clk_name);
4257 +               return PTR_ERR(clk);
4258 +       }
4259 +
4260 +       *clock = clk;
4261 +
4262 +       DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
4263 +
4264 +       return 0;
4265 +}
4266 +
4267 +static int dss_get_clocks(void)
4268 +{
4269 +       int r;
4270 +
4271 +       core.dss_ick = NULL;
4272 +       core.dss1_fck = NULL;
4273 +       core.dss2_fck = NULL;
4274 +       core.dss_54m_fck = NULL;
4275 +       core.dss_96m_fck = NULL;
4276 +
4277 +       r = dss_get_clock(&core.dss_ick, "ick");
4278 +       if (r)
4279 +               goto err;
4280 +
4281 +       r = dss_get_clock(&core.dss1_fck, "dss1_fck");
4282 +       if (r)
4283 +               goto err;
4284 +
4285 +       r = dss_get_clock(&core.dss2_fck, "dss2_fck");
4286 +       if (r)
4287 +               goto err;
4288 +
4289 +       r = dss_get_clock(&core.dss_54m_fck, "tv_fck");
4290 +       if (r)
4291 +               goto err;
4292 +
4293 +       r = dss_get_clock(&core.dss_96m_fck, "video_fck");
4294 +       if (r)
4295 +               goto err;
4296 +
4297 +       return 0;
4298 +
4299 +err:
4300 +       if (core.dss_ick)
4301 +               clk_put(core.dss_ick);
4302 +       if (core.dss1_fck)
4303 +               clk_put(core.dss1_fck);
4304 +       if (core.dss2_fck)
4305 +               clk_put(core.dss2_fck);
4306 +       if (core.dss_54m_fck)
4307 +               clk_put(core.dss_54m_fck);
4308 +       if (core.dss_96m_fck)
4309 +               clk_put(core.dss_96m_fck);
4310 +
4311 +       return r;
4312 +}
4313 +
4314 +static void dss_put_clocks(void)
4315 +{
4316 +       if (core.dss_96m_fck)
4317 +               clk_put(core.dss_96m_fck);
4318 +       clk_put(core.dss_54m_fck);
4319 +       clk_put(core.dss1_fck);
4320 +       clk_put(core.dss2_fck);
4321 +       clk_put(core.dss_ick);
4322 +}
4323 +
4324 +unsigned long dss_clk_get_rate(enum dss_clock clk)
4325 +{
4326 +       switch (clk) {
4327 +       case DSS_CLK_ICK:
4328 +               return clk_get_rate(core.dss_ick);
4329 +       case DSS_CLK_FCK1:
4330 +               return clk_get_rate(core.dss1_fck);
4331 +       case DSS_CLK_FCK2:
4332 +               return clk_get_rate(core.dss2_fck);
4333 +       case DSS_CLK_54M:
4334 +               return clk_get_rate(core.dss_54m_fck);
4335 +       case DSS_CLK_96M:
4336 +               return clk_get_rate(core.dss_96m_fck);
4337 +       }
4338 +
4339 +       BUG();
4340 +       return 0;
4341 +}
4342 +
4343 +static unsigned count_clk_bits(enum dss_clock clks)
4344 +{
4345 +       unsigned num_clks = 0;
4346 +
4347 +       if (clks & DSS_CLK_ICK)
4348 +               ++num_clks;
4349 +       if (clks & DSS_CLK_FCK1)
4350 +               ++num_clks;
4351 +       if (clks & DSS_CLK_FCK2)
4352 +               ++num_clks;
4353 +       if (clks & DSS_CLK_54M)
4354 +               ++num_clks;
4355 +       if (clks & DSS_CLK_96M)
4356 +               ++num_clks;
4357 +
4358 +       return num_clks;
4359 +}
4360 +
4361 +static void dss_clk_enable_no_ctx(enum dss_clock clks)
4362 +{
4363 +       unsigned num_clks = count_clk_bits(clks);
4364 +
4365 +       if (clks & DSS_CLK_ICK)
4366 +               clk_enable(core.dss_ick);
4367 +       if (clks & DSS_CLK_FCK1)
4368 +               clk_enable(core.dss1_fck);
4369 +       if (clks & DSS_CLK_FCK2)
4370 +               clk_enable(core.dss2_fck);
4371 +       if (clks & DSS_CLK_54M)
4372 +               clk_enable(core.dss_54m_fck);
4373 +       if (clks & DSS_CLK_96M)
4374 +               clk_enable(core.dss_96m_fck);
4375 +
4376 +       core.num_clks_enabled += num_clks;
4377 +}
4378 +
4379 +void dss_clk_enable(enum dss_clock clks)
4380 +{
4381 +       dss_clk_enable_no_ctx(clks);
4382 +
4383 +       if (cpu_is_omap34xx() && dss_need_ctx_restore())
4384 +               restore_all_ctx();
4385 +}
4386 +
4387 +static void dss_clk_disable_no_ctx(enum dss_clock clks)
4388 +{
4389 +       unsigned num_clks = count_clk_bits(clks);
4390 +
4391 +       if (clks & DSS_CLK_ICK)
4392 +               clk_disable(core.dss_ick);
4393 +       if (clks & DSS_CLK_FCK1)
4394 +               clk_disable(core.dss1_fck);
4395 +       if (clks & DSS_CLK_FCK2)
4396 +               clk_disable(core.dss2_fck);
4397 +       if (clks & DSS_CLK_54M)
4398 +               clk_disable(core.dss_54m_fck);
4399 +       if (clks & DSS_CLK_96M)
4400 +               clk_disable(core.dss_96m_fck);
4401 +
4402 +       core.num_clks_enabled -= num_clks;
4403 +}
4404 +
4405 +void dss_clk_disable(enum dss_clock clks)
4406 +{
4407 +       if (cpu_is_omap34xx()) {
4408 +               unsigned num_clks = count_clk_bits(clks);
4409 +
4410 +               BUG_ON(core.num_clks_enabled < num_clks);
4411 +
4412 +               if (core.num_clks_enabled == num_clks)
4413 +                       save_all_ctx();
4414 +       }
4415 +
4416 +       dss_clk_disable_no_ctx(clks);
4417 +}
4418 +
4419 +static void dss_clk_enable_all_no_ctx(void)
4420 +{
4421 +       enum dss_clock clks;
4422 +
4423 +       clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
4424 +       if (cpu_is_omap34xx())
4425 +               clks |= DSS_CLK_96M;
4426 +       dss_clk_enable_no_ctx(clks);
4427 +}
4428 +
4429 +static void dss_clk_disable_all_no_ctx(void)
4430 +{
4431 +       enum dss_clock clks;
4432 +
4433 +       clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
4434 +       if (cpu_is_omap34xx())
4435 +               clks |= DSS_CLK_96M;
4436 +       dss_clk_disable_no_ctx(clks);
4437 +}
4438 +
4439 +static void dss_clk_disable_all(void)
4440 +{
4441 +       enum dss_clock clks;
4442 +
4443 +       clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
4444 +       if (cpu_is_omap34xx())
4445 +               clks |= DSS_CLK_96M;
4446 +       dss_clk_disable(clks);
4447 +}
4448 +
4449 +/* DEBUGFS */
4450 +#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
4451 +static void dss_debug_dump_clocks(struct seq_file *s)
4452 +{
4453 +       dss_dump_clocks(s);
4454 +       dispc_dump_clocks(s);
4455 +#ifdef CONFIG_OMAP2_DSS_DSI
4456 +       dsi_dump_clocks(s);
4457 +#endif
4458 +}
4459 +
4460 +static int dss_debug_show(struct seq_file *s, void *unused)
4461 +{
4462 +       void (*func)(struct seq_file *) = s->private;
4463 +       func(s);
4464 +       return 0;
4465 +}
4466 +
4467 +static int dss_debug_open(struct inode *inode, struct file *file)
4468 +{
4469 +       return single_open(file, dss_debug_show, inode->i_private);
4470 +}
4471 +
4472 +static const struct file_operations dss_debug_fops = {
4473 +       .open           = dss_debug_open,
4474 +       .read           = seq_read,
4475 +       .llseek         = seq_lseek,
4476 +       .release        = single_release,
4477 +};
4478 +
4479 +static struct dentry *dss_debugfs_dir;
4480 +
4481 +static int dss_initialize_debugfs(void)
4482 +{
4483 +       dss_debugfs_dir = debugfs_create_dir("omapdss", NULL);
4484 +       if (IS_ERR(dss_debugfs_dir)) {
4485 +               int err = PTR_ERR(dss_debugfs_dir);
4486 +               dss_debugfs_dir = NULL;
4487 +               return err;
4488 +       }
4489 +
4490 +       debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
4491 +                       &dss_debug_dump_clocks, &dss_debug_fops);
4492 +
4493 +       debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir,
4494 +                       &dss_dump_regs, &dss_debug_fops);
4495 +       debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir,
4496 +                       &dispc_dump_regs, &dss_debug_fops);
4497 +#ifdef CONFIG_OMAP2_DSS_RFBI
4498 +       debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir,
4499 +                       &rfbi_dump_regs, &dss_debug_fops);
4500 +#endif
4501 +#ifdef CONFIG_OMAP2_DSS_DSI
4502 +       debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir,
4503 +                       &dsi_dump_regs, &dss_debug_fops);
4504 +#endif
4505 +#ifdef CONFIG_OMAP2_DSS_VENC
4506 +       debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir,
4507 +                       &venc_dump_regs, &dss_debug_fops);
4508 +#endif
4509 +       return 0;
4510 +}
4511 +
4512 +static void dss_uninitialize_debugfs(void)
4513 +{
4514 +       if (dss_debugfs_dir)
4515 +               debugfs_remove_recursive(dss_debugfs_dir);
4516 +}
4517 +#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
4518 +
4519 +/* PLATFORM DEVICE */
4520 +static int omap_dss_probe(struct platform_device *pdev)
4521 +{
4522 +       struct omap_dss_board_info *pdata = pdev->dev.platform_data;
4523 +       int skip_init = 0;
4524 +       int r;
4525 +       int i;
4526 +
4527 +       core.pdev = pdev;
4528 +
4529 +       dss_init_overlay_managers(pdev);
4530 +       dss_init_overlays(pdev);
4531 +
4532 +       r = dss_get_clocks();
4533 +       if (r)
4534 +               goto fail0;
4535 +
4536 +       dss_clk_enable_all_no_ctx();
4537 +
4538 +       core.ctx_id = dss_get_ctx_id();
4539 +       DSSDBG("initial ctx id %u\n", core.ctx_id);
4540 +
4541 +#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
4542 +       /* DISPC_CONTROL */
4543 +       if (omap_readl(0x48050440) & 1) /* LCD enabled? */
4544 +               skip_init = 1;
4545 +#endif
4546 +
4547 +       r = dss_init(skip_init);
4548 +       if (r) {
4549 +               DSSERR("Failed to initialize DSS\n");
4550 +               goto fail0;
4551 +       }
4552 +
4553 +#ifdef CONFIG_OMAP2_DSS_RFBI
4554 +       r = rfbi_init();
4555 +       if (r) {
4556 +               DSSERR("Failed to initialize rfbi\n");
4557 +               goto fail0;
4558 +       }
4559 +#endif
4560 +
4561 +       r = dpi_init();
4562 +       if (r) {
4563 +               DSSERR("Failed to initialize dpi\n");
4564 +               goto fail0;
4565 +       }
4566 +
4567 +       r = dispc_init();
4568 +       if (r) {
4569 +               DSSERR("Failed to initialize dispc\n");
4570 +               goto fail0;
4571 +       }
4572 +#ifdef CONFIG_OMAP2_DSS_VENC
4573 +       r = venc_init(pdev);
4574 +       if (r) {
4575 +               DSSERR("Failed to initialize venc\n");
4576 +               goto fail0;
4577 +       }
4578 +#endif
4579 +       if (cpu_is_omap34xx()) {
4580 +#ifdef CONFIG_OMAP2_DSS_SDI
4581 +               r = sdi_init(skip_init);
4582 +               if (r) {
4583 +                       DSSERR("Failed to initialize SDI\n");
4584 +                       goto fail0;
4585 +               }
4586 +#endif
4587 +#ifdef CONFIG_OMAP2_DSS_DSI
4588 +               r = dsi_init(pdev);
4589 +               if (r) {
4590 +                       DSSERR("Failed to initialize DSI\n");
4591 +                       goto fail0;
4592 +               }
4593 +#endif
4594 +       }
4595 +
4596 +#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
4597 +       r = dss_initialize_debugfs();
4598 +       if (r)
4599 +               goto fail0;
4600 +#endif
4601 +
4602 +       for (i = 0; i < pdata->num_devices; ++i) {
4603 +               struct omap_dss_device *dssdev = pdata->devices[i];
4604 +
4605 +               r = omap_dss_register_device(dssdev);
4606 +               if (r)
4607 +                       DSSERR("device reg failed %d\n", i);
4608 +
4609 +               if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0)
4610 +                       pdata->default_device = dssdev;
4611 +       }
4612 +
4613 +       dss_clk_disable_all();
4614 +
4615 +       return 0;
4616 +
4617 +       /* XXX fail correctly */
4618 +fail0:
4619 +       return r;
4620 +}
4621 +
4622 +static int omap_dss_remove(struct platform_device *pdev)
4623 +{
4624 +       struct omap_dss_board_info *pdata = pdev->dev.platform_data;
4625 +       int i;
4626 +       int c;
4627 +
4628 +#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
4629 +       dss_uninitialize_debugfs();
4630 +#endif
4631 +
4632 +#ifdef CONFIG_OMAP2_DSS_VENC
4633 +       venc_exit();
4634 +#endif
4635 +       dispc_exit();
4636 +       dpi_exit();
4637 +#ifdef CONFIG_OMAP2_DSS_RFBI
4638 +       rfbi_exit();
4639 +#endif
4640 +       if (cpu_is_omap34xx()) {
4641 +#ifdef CONFIG_OMAP2_DSS_DSI
4642 +               dsi_exit();
4643 +#endif
4644 +#ifdef CONFIG_OMAP2_DSS_SDI
4645 +               sdi_exit();
4646 +#endif
4647 +       }
4648 +
4649 +       dss_exit();
4650 +
4651 +       /* these should be removed at some point */
4652 +       c = core.dss_ick->usecount;
4653 +       if (c > 0) {
4654 +               DSSERR("warning: dss_ick usecount %d, disabling\n", c);
4655 +               while (c-- > 0)
4656 +                       clk_disable(core.dss_ick);
4657 +       }
4658 +
4659 +       c = core.dss1_fck->usecount;
4660 +       if (c > 0) {
4661 +               DSSERR("warning: dss1_fck usecount %d, disabling\n", c);
4662 +               while (c-- > 0)
4663 +                       clk_disable(core.dss1_fck);
4664 +       }
4665 +
4666 +       c = core.dss2_fck->usecount;
4667 +       if (c > 0) {
4668 +               DSSERR("warning: dss2_fck usecount %d, disabling\n", c);
4669 +               while (c-- > 0)
4670 +                       clk_disable(core.dss2_fck);
4671 +       }
4672 +
4673 +       c = core.dss_54m_fck->usecount;
4674 +       if (c > 0) {
4675 +               DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c);
4676 +               while (c-- > 0)
4677 +                       clk_disable(core.dss_54m_fck);
4678 +       }
4679 +
4680 +       if (core.dss_96m_fck) {
4681 +               c = core.dss_96m_fck->usecount;
4682 +               if (c > 0) {
4683 +                       DSSERR("warning: dss_96m_fck usecount %d, disabling\n",
4684 +                                       c);
4685 +                       while (c-- > 0)
4686 +                               clk_disable(core.dss_96m_fck);
4687 +               }
4688 +       }
4689 +
4690 +       dss_put_clocks();
4691 +
4692 +       dss_uninit_overlays(pdev);
4693 +       dss_uninit_overlay_managers(pdev);
4694 +
4695 +       for (i = 0; i < pdata->num_devices; ++i)
4696 +               omap_dss_unregister_device(pdata->devices[i]);
4697 +
4698 +       return 0;
4699 +}
4700 +
4701 +static void omap_dss_shutdown(struct platform_device *pdev)
4702 +{
4703 +       DSSDBG("shutdown\n");
4704 +}
4705 +
4706 +static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state)
4707 +{
4708 +       DSSDBG("suspend %d\n", state.event);
4709 +
4710 +       return dss_suspend_all_devices();
4711 +}
4712 +
4713 +static int omap_dss_resume(struct platform_device *pdev)
4714 +{
4715 +       DSSDBG("resume\n");
4716 +
4717 +       return dss_resume_all_devices();
4718 +}
4719 +
4720 +static struct platform_driver omap_dss_driver = {
4721 +       .probe          = omap_dss_probe,
4722 +       .remove         = omap_dss_remove,
4723 +       .shutdown       = omap_dss_shutdown,
4724 +       .suspend        = omap_dss_suspend,
4725 +       .resume         = omap_dss_resume,
4726 +       .driver         = {
4727 +               .name   = "omapdss",
4728 +               .owner  = THIS_MODULE,
4729 +       },
4730 +};
4731 +
4732 +/* BUS */
4733 +static int dss_bus_match(struct device *dev, struct device_driver *driver)
4734 +{
4735 +       struct omap_dss_device *dssdev = to_dss_device(dev);
4736 +
4737 +       DSSDBG("bus_match. dev %s/%s, drv %s\n",
4738 +                       dev_name(dev), dssdev->driver_name, driver->name);
4739 +
4740 +       return strcmp(dssdev->driver_name, driver->name) == 0;
4741 +}
4742 +
4743 +static ssize_t device_name_show(struct device *dev,
4744 +               struct device_attribute *attr, char *buf)
4745 +{
4746 +       struct omap_dss_device *dssdev = to_dss_device(dev);
4747 +       return snprintf(buf, PAGE_SIZE, "%s\n",
4748 +                       dssdev->name ?
4749 +                       dssdev->name : "");
4750 +}
4751 +
4752 +static struct device_attribute default_dev_attrs[] = {
4753 +       __ATTR(name, S_IRUGO, device_name_show, NULL),
4754 +       __ATTR_NULL,
4755 +};
4756 +
4757 +static ssize_t driver_name_show(struct device_driver *drv, char *buf)
4758 +{
4759 +       struct omap_dss_driver *dssdrv = to_dss_driver(drv);
4760 +       return snprintf(buf, PAGE_SIZE, "%s\n",
4761 +                       dssdrv->driver.name ?
4762 +                       dssdrv->driver.name : "");
4763 +}
4764 +static struct driver_attribute default_drv_attrs[] = {
4765 +       __ATTR(name, S_IRUGO, driver_name_show, NULL),
4766 +       __ATTR_NULL,
4767 +};
4768 +
4769 +static struct bus_type dss_bus_type = {
4770 +       .name = "omapdss",
4771 +       .match = dss_bus_match,
4772 +       .dev_attrs = default_dev_attrs,
4773 +       .drv_attrs = default_drv_attrs,
4774 +};
4775 +
4776 +static void dss_bus_release(struct device *dev)
4777 +{
4778 +       DSSDBG("bus_release\n");
4779 +}
4780 +
4781 +static struct device dss_bus = {
4782 +       .release = dss_bus_release,
4783 +};
4784 +
4785 +struct bus_type *dss_get_bus(void)
4786 +{
4787 +       return &dss_bus_type;
4788 +}
4789 +
4790 +/* DRIVER */
4791 +static int dss_driver_probe(struct device *dev)
4792 +{
4793 +       int r;
4794 +       struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
4795 +       struct omap_dss_device *dssdev = to_dss_device(dev);
4796 +       struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
4797 +       bool force;
4798 +
4799 +       DSSDBG("driver_probe: dev %s/%s, drv %s\n",
4800 +                               dev_name(dev), dssdev->driver_name,
4801 +                               dssdrv->driver.name);
4802 +
4803 +       dss_init_device(core.pdev, dssdev);
4804 +
4805 +       /* skip this if the device is behind a ctrl */
4806 +       if (!dssdev->panel.ctrl) {
4807 +               force = pdata->default_device == dssdev;
4808 +               dss_recheck_connections(dssdev, force);
4809 +       }
4810 +
4811 +       r = dssdrv->probe(dssdev);
4812 +
4813 +       if (r) {
4814 +               DSSERR("driver probe failed: %d\n", r);
4815 +               return r;
4816 +       }
4817 +
4818 +       DSSDBG("probe done for device %s\n", dev_name(dev));
4819 +
4820 +       dssdev->driver = dssdrv;
4821 +
4822 +       return 0;
4823 +}
4824 +
4825 +static int dss_driver_remove(struct device *dev)
4826 +{
4827 +       struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
4828 +       struct omap_dss_device *dssdev = to_dss_device(dev);
4829 +
4830 +       DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev),
4831 +                       dssdev->driver_name);
4832 +
4833 +       dssdrv->remove(dssdev);
4834 +
4835 +       dss_uninit_device(core.pdev, dssdev);
4836 +
4837 +       dssdev->driver = NULL;
4838 +
4839 +       return 0;
4840 +}
4841 +
4842 +int omap_dss_register_driver(struct omap_dss_driver *dssdriver)
4843 +{
4844 +       dssdriver->driver.bus = &dss_bus_type;
4845 +       dssdriver->driver.probe = dss_driver_probe;
4846 +       dssdriver->driver.remove = dss_driver_remove;
4847 +       return driver_register(&dssdriver->driver);
4848 +}
4849 +EXPORT_SYMBOL(omap_dss_register_driver);
4850 +
4851 +void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)
4852 +{
4853 +       driver_unregister(&dssdriver->driver);
4854 +}
4855 +EXPORT_SYMBOL(omap_dss_unregister_driver);
4856 +
4857 +/* DEVICE */
4858 +static void reset_device(struct device *dev, int check)
4859 +{
4860 +       u8 *dev_p = (u8 *)dev;
4861 +       u8 *dev_end = dev_p + sizeof(*dev);
4862 +       void *saved_pdata;
4863 +
4864 +       saved_pdata = dev->platform_data;
4865 +       if (check) {
4866 +               /*
4867 +                * Check if there is any other setting than platform_data
4868 +                * in struct device; warn that these will be reset by our
4869 +                * init.
4870 +                */
4871 +               dev->platform_data = NULL;
4872 +               while (dev_p < dev_end) {
4873 +                       if (*dev_p) {
4874 +                               WARN("%s: struct device fields will be "
4875 +                                               "discarded\n",
4876 +                                    __func__);
4877 +                               break;
4878 +                       }
4879 +                       dev_p++;
4880 +               }
4881 +       }
4882 +       memset(dev, 0, sizeof(*dev));
4883 +       dev->platform_data = saved_pdata;
4884 +}
4885 +
4886 +
4887 +static void omap_dss_dev_release(struct device *dev)
4888 +{
4889 +       reset_device(dev, 0);
4890 +}
4891 +
4892 +int omap_dss_register_device(struct omap_dss_device *dssdev)
4893 +{
4894 +       static int dev_num;
4895 +       static int panel_num;
4896 +       int r;
4897 +
4898 +       WARN_ON(!dssdev->driver_name);
4899 +
4900 +       reset_device(&dssdev->dev, 1);
4901 +       dssdev->dev.bus = &dss_bus_type;
4902 +       dssdev->dev.parent = &dss_bus;
4903 +       dssdev->dev.release = omap_dss_dev_release;
4904 +       dev_set_name(&dssdev->dev, "display%d", dev_num++);
4905 +       r = device_register(&dssdev->dev);
4906 +       if (r)
4907 +               return r;
4908 +
4909 +       if (dssdev->ctrl.panel) {
4910 +               struct omap_dss_device *panel = dssdev->ctrl.panel;
4911 +
4912 +               panel->panel.ctrl = dssdev;
4913 +
4914 +               reset_device(&panel->dev, 1);
4915 +               panel->dev.bus = &dss_bus_type;
4916 +               panel->dev.parent = &dssdev->dev;
4917 +               panel->dev.release = omap_dss_dev_release;
4918 +               dev_set_name(&panel->dev, "panel%d", panel_num++);
4919 +               r = device_register(&panel->dev);
4920 +               if (r)
4921 +                       return r;
4922 +       }
4923 +
4924 +       return 0;
4925 +}
4926 +
4927 +void omap_dss_unregister_device(struct omap_dss_device *dssdev)
4928 +{
4929 +       device_unregister(&dssdev->dev);
4930 +
4931 +       if (dssdev->ctrl.panel) {
4932 +               struct omap_dss_device *panel = dssdev->ctrl.panel;
4933 +               device_unregister(&panel->dev);
4934 +       }
4935 +}
4936 +
4937 +/* BUS */
4938 +static int omap_dss_bus_register(void)
4939 +{
4940 +       int r;
4941 +
4942 +       r = bus_register(&dss_bus_type);
4943 +       if (r) {
4944 +               DSSERR("bus register failed\n");
4945 +               return r;
4946 +       }
4947 +
4948 +       dev_set_name(&dss_bus, "omapdss");
4949 +       r = device_register(&dss_bus);
4950 +       if (r) {
4951 +               DSSERR("bus driver register failed\n");
4952 +               bus_unregister(&dss_bus_type);
4953 +               return r;
4954 +       }
4955 +
4956 +       return 0;
4957 +}
4958 +
4959 +/* INIT */
4960 +
4961 +#ifdef CONFIG_OMAP2_DSS_MODULE
4962 +static void omap_dss_bus_unregister(void)
4963 +{
4964 +       device_unregister(&dss_bus);
4965 +
4966 +       bus_unregister(&dss_bus_type);
4967 +}
4968 +
4969 +static int __init omap_dss_init(void)
4970 +{
4971 +       int r;
4972 +
4973 +       r = omap_dss_bus_register();
4974 +       if (r)
4975 +               return r;
4976 +
4977 +       r = platform_driver_register(&omap_dss_driver);
4978 +       if (r) {
4979 +               omap_dss_bus_unregister();
4980 +               return r;
4981 +       }
4982 +
4983 +       return 0;
4984 +}
4985 +
4986 +static void __exit omap_dss_exit(void)
4987 +{
4988 +       platform_driver_unregister(&omap_dss_driver);
4989 +
4990 +       omap_dss_bus_unregister();
4991 +}
4992 +
4993 +module_init(omap_dss_init);
4994 +module_exit(omap_dss_exit);
4995 +#else
4996 +static int __init omap_dss_init(void)
4997 +{
4998 +       return omap_dss_bus_register();
4999 +}
5000 +
5001 +static int __init omap_dss_init2(void)
5002 +{
5003 +       return platform_driver_register(&omap_dss_driver);
5004 +}
5005 +
5006 +core_initcall(omap_dss_init);
5007 +device_initcall(omap_dss_init2);
5008 +#endif
5009 +
5010 +MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
5011 +MODULE_DESCRIPTION("OMAP2/3 Display Subsystem");
5012 +MODULE_LICENSE("GPL v2");
5013 +
5014 diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
5015 new file mode 100644
5016 index 0000000..d648475
5017 --- /dev/null
5018 +++ b/drivers/video/omap2/dss/dispc.c
5019 @@ -0,0 +1,3182 @@
5020 +/*
5021 + * linux/drivers/video/omap2/dss/dispc.c
5022 + *
5023 + * Copyright (C) 2009 Nokia Corporation
5024 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
5025 + *
5026 + * Some code and ideas taken from drivers/video/omap/ driver
5027 + * by Imre Deak.
5028 + *
5029 + * This program is free software; you can redistribute it and/or modify it
5030 + * under the terms of the GNU General Public License version 2 as published by
5031 + * the Free Software Foundation.
5032 + *
5033 + * This program is distributed in the hope that it will be useful, but WITHOUT
5034 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
5035 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
5036 + * more details.
5037 + *
5038 + * You should have received a copy of the GNU General Public License along with
5039 + * this program.  If not, see <http://www.gnu.org/licenses/>.
5040 + */
5041 +
5042 +#define DSS_SUBSYS_NAME "DISPC"
5043 +
5044 +#include <linux/kernel.h>
5045 +#include <linux/dma-mapping.h>
5046 +#include <linux/vmalloc.h>
5047 +#include <linux/clk.h>
5048 +#include <linux/io.h>
5049 +#include <linux/jiffies.h>
5050 +#include <linux/seq_file.h>
5051 +#include <linux/delay.h>
5052 +#include <linux/workqueue.h>
5053 +
5054 +#include <mach/sram.h>
5055 +#include <mach/board.h>
5056 +#include <mach/clock.h>
5057 +
5058 +#include <mach/display.h>
5059 +
5060 +#include "dss.h"
5061 +
5062 +/* DISPC */
5063 +#define DISPC_BASE                     0x48050400
5064 +
5065 +#define DISPC_SZ_REGS                  SZ_1K
5066 +
5067 +struct dispc_reg { u16 idx; };
5068 +
5069 +#define DISPC_REG(idx)                 ((const struct dispc_reg) { idx })
5070 +
5071 +/* DISPC common */
5072 +#define DISPC_REVISION                 DISPC_REG(0x0000)
5073 +#define DISPC_SYSCONFIG                        DISPC_REG(0x0010)
5074 +#define DISPC_SYSSTATUS                        DISPC_REG(0x0014)
5075 +#define DISPC_IRQSTATUS                        DISPC_REG(0x0018)
5076 +#define DISPC_IRQENABLE                        DISPC_REG(0x001C)
5077 +#define DISPC_CONTROL                  DISPC_REG(0x0040)
5078 +#define DISPC_CONFIG                   DISPC_REG(0x0044)
5079 +#define DISPC_CAPABLE                  DISPC_REG(0x0048)
5080 +#define DISPC_DEFAULT_COLOR0           DISPC_REG(0x004C)
5081 +#define DISPC_DEFAULT_COLOR1           DISPC_REG(0x0050)
5082 +#define DISPC_TRANS_COLOR0             DISPC_REG(0x0054)
5083 +#define DISPC_TRANS_COLOR1             DISPC_REG(0x0058)
5084 +#define DISPC_LINE_STATUS              DISPC_REG(0x005C)
5085 +#define DISPC_LINE_NUMBER              DISPC_REG(0x0060)
5086 +#define DISPC_TIMING_H                 DISPC_REG(0x0064)
5087 +#define DISPC_TIMING_V                 DISPC_REG(0x0068)
5088 +#define DISPC_POL_FREQ                 DISPC_REG(0x006C)
5089 +#define DISPC_DIVISOR                  DISPC_REG(0x0070)
5090 +#define DISPC_GLOBAL_ALPHA             DISPC_REG(0x0074)
5091 +#define DISPC_SIZE_DIG                 DISPC_REG(0x0078)
5092 +#define DISPC_SIZE_LCD                 DISPC_REG(0x007C)
5093 +
5094 +/* DISPC GFX plane */
5095 +#define DISPC_GFX_BA0                  DISPC_REG(0x0080)
5096 +#define DISPC_GFX_BA1                  DISPC_REG(0x0084)
5097 +#define DISPC_GFX_POSITION             DISPC_REG(0x0088)
5098 +#define DISPC_GFX_SIZE                 DISPC_REG(0x008C)
5099 +#define DISPC_GFX_ATTRIBUTES           DISPC_REG(0x00A0)
5100 +#define DISPC_GFX_FIFO_THRESHOLD       DISPC_REG(0x00A4)
5101 +#define DISPC_GFX_FIFO_SIZE_STATUS     DISPC_REG(0x00A8)
5102 +#define DISPC_GFX_ROW_INC              DISPC_REG(0x00AC)
5103 +#define DISPC_GFX_PIXEL_INC            DISPC_REG(0x00B0)
5104 +#define DISPC_GFX_WINDOW_SKIP          DISPC_REG(0x00B4)
5105 +#define DISPC_GFX_TABLE_BA             DISPC_REG(0x00B8)
5106 +
5107 +#define DISPC_DATA_CYCLE1              DISPC_REG(0x01D4)
5108 +#define DISPC_DATA_CYCLE2              DISPC_REG(0x01D8)
5109 +#define DISPC_DATA_CYCLE3              DISPC_REG(0x01DC)
5110 +
5111 +#define DISPC_CPR_COEF_R               DISPC_REG(0x0220)
5112 +#define DISPC_CPR_COEF_G               DISPC_REG(0x0224)
5113 +#define DISPC_CPR_COEF_B               DISPC_REG(0x0228)
5114 +
5115 +#define DISPC_GFX_PRELOAD              DISPC_REG(0x022C)
5116 +
5117 +/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */
5118 +#define DISPC_VID_REG(n, idx)          DISPC_REG(0x00BC + (n)*0x90 + idx)
5119 +
5120 +#define DISPC_VID_BA0(n)               DISPC_VID_REG(n, 0x0000)
5121 +#define DISPC_VID_BA1(n)               DISPC_VID_REG(n, 0x0004)
5122 +#define DISPC_VID_POSITION(n)          DISPC_VID_REG(n, 0x0008)
5123 +#define DISPC_VID_SIZE(n)              DISPC_VID_REG(n, 0x000C)
5124 +#define DISPC_VID_ATTRIBUTES(n)                DISPC_VID_REG(n, 0x0010)
5125 +#define DISPC_VID_FIFO_THRESHOLD(n)    DISPC_VID_REG(n, 0x0014)
5126 +#define DISPC_VID_FIFO_SIZE_STATUS(n)  DISPC_VID_REG(n, 0x0018)
5127 +#define DISPC_VID_ROW_INC(n)           DISPC_VID_REG(n, 0x001C)
5128 +#define DISPC_VID_PIXEL_INC(n)         DISPC_VID_REG(n, 0x0020)
5129 +#define DISPC_VID_FIR(n)               DISPC_VID_REG(n, 0x0024)
5130 +#define DISPC_VID_PICTURE_SIZE(n)      DISPC_VID_REG(n, 0x0028)
5131 +#define DISPC_VID_ACCU0(n)             DISPC_VID_REG(n, 0x002C)
5132 +#define DISPC_VID_ACCU1(n)             DISPC_VID_REG(n, 0x0030)
5133 +
5134 +/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
5135 +#define DISPC_VID_FIR_COEF_H(n, i)     DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8)
5136 +/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
5137 +#define DISPC_VID_FIR_COEF_HV(n, i)    DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8)
5138 +/* coef index i = {0, 1, 2, 3, 4} */
5139 +#define DISPC_VID_CONV_COEF(n, i)      DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4)
5140 +/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
5141 +#define DISPC_VID_FIR_COEF_V(n, i)     DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4)
5142 +
5143 +#define DISPC_VID_PRELOAD(n)           DISPC_REG(0x230 + (n)*0x04)
5144 +
5145 +
5146 +#define DISPC_IRQ_MASK_ERROR            (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
5147 +                                        DISPC_IRQ_OCP_ERR | \
5148 +                                        DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
5149 +                                        DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
5150 +                                        DISPC_IRQ_SYNC_LOST | \
5151 +                                        DISPC_IRQ_SYNC_LOST_DIGIT)
5152 +
5153 +#define DISPC_MAX_NR_ISRS              8
5154 +
5155 +struct omap_dispc_isr_data {
5156 +       omap_dispc_isr_t        isr;
5157 +       void                    *arg;
5158 +       u32                     mask;
5159 +};
5160 +
5161 +#define REG_GET(idx, start, end) \
5162 +       FLD_GET(dispc_read_reg(idx), start, end)
5163 +
5164 +#define REG_FLD_MOD(idx, val, start, end)                              \
5165 +       dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
5166 +
5167 +static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES,
5168 +       DISPC_VID_ATTRIBUTES(0),
5169 +       DISPC_VID_ATTRIBUTES(1) };
5170 +
5171 +static struct {
5172 +       void __iomem    *base;
5173 +
5174 +       struct clk      *dpll4_m4_ck;
5175 +
5176 +       unsigned long   cache_req_pck;
5177 +       unsigned long   cache_prate;
5178 +       struct dispc_clock_info cache_cinfo;
5179 +
5180 +       u32     fifo_size[3];
5181 +
5182 +       spinlock_t irq_lock;
5183 +       u32 irq_error_mask;
5184 +       struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
5185 +       u32 error_irqs;
5186 +       struct work_struct error_work;
5187 +
5188 +       u32             ctx[DISPC_SZ_REGS / sizeof(u32)];
5189 +} dispc;
5190 +
5191 +static void _omap_dispc_set_irqs(void);
5192 +
5193 +static inline void dispc_write_reg(const struct dispc_reg idx, u32 val)
5194 +{
5195 +       __raw_writel(val, dispc.base + idx.idx);
5196 +}
5197 +
5198 +static inline u32 dispc_read_reg(const struct dispc_reg idx)
5199 +{
5200 +       return __raw_readl(dispc.base + idx.idx);
5201 +}
5202 +
5203 +#define SR(reg) \
5204 +       dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
5205 +#define RR(reg) \
5206 +       dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)])
5207 +
5208 +void dispc_save_context(void)
5209 +{
5210 +       if (cpu_is_omap24xx())
5211 +               return;
5212 +
5213 +       SR(SYSCONFIG);
5214 +       SR(IRQENABLE);
5215 +       SR(CONTROL);
5216 +       SR(CONFIG);
5217 +       SR(DEFAULT_COLOR0);
5218 +       SR(DEFAULT_COLOR1);
5219 +       SR(TRANS_COLOR0);
5220 +       SR(TRANS_COLOR1);
5221 +       SR(LINE_NUMBER);
5222 +       SR(TIMING_H);
5223 +       SR(TIMING_V);
5224 +       SR(POL_FREQ);
5225 +       SR(DIVISOR);
5226 +       SR(GLOBAL_ALPHA);
5227 +       SR(SIZE_DIG);
5228 +       SR(SIZE_LCD);
5229 +
5230 +       SR(GFX_BA0);
5231 +       SR(GFX_BA1);
5232 +       SR(GFX_POSITION);
5233 +       SR(GFX_SIZE);
5234 +       SR(GFX_ATTRIBUTES);
5235 +       SR(GFX_FIFO_THRESHOLD);
5236 +       SR(GFX_ROW_INC);
5237 +       SR(GFX_PIXEL_INC);
5238 +       SR(GFX_WINDOW_SKIP);
5239 +       SR(GFX_TABLE_BA);
5240 +
5241 +       SR(DATA_CYCLE1);
5242 +       SR(DATA_CYCLE2);
5243 +       SR(DATA_CYCLE3);
5244 +
5245 +       SR(CPR_COEF_R);
5246 +       SR(CPR_COEF_G);
5247 +       SR(CPR_COEF_B);
5248 +
5249 +       SR(GFX_PRELOAD);
5250 +
5251 +       /* VID1 */
5252 +       SR(VID_BA0(0));
5253 +       SR(VID_BA1(0));
5254 +       SR(VID_POSITION(0));
5255 +       SR(VID_SIZE(0));
5256 +       SR(VID_ATTRIBUTES(0));
5257 +       SR(VID_FIFO_THRESHOLD(0));
5258 +       SR(VID_ROW_INC(0));
5259 +       SR(VID_PIXEL_INC(0));
5260 +       SR(VID_FIR(0));
5261 +       SR(VID_PICTURE_SIZE(0));
5262 +       SR(VID_ACCU0(0));
5263 +       SR(VID_ACCU1(0));
5264 +
5265 +       SR(VID_FIR_COEF_H(0, 0));
5266 +       SR(VID_FIR_COEF_H(0, 1));
5267 +       SR(VID_FIR_COEF_H(0, 2));
5268 +       SR(VID_FIR_COEF_H(0, 3));
5269 +       SR(VID_FIR_COEF_H(0, 4));
5270 +       SR(VID_FIR_COEF_H(0, 5));
5271 +       SR(VID_FIR_COEF_H(0, 6));
5272 +       SR(VID_FIR_COEF_H(0, 7));
5273 +
5274 +       SR(VID_FIR_COEF_HV(0, 0));
5275 +       SR(VID_FIR_COEF_HV(0, 1));
5276 +       SR(VID_FIR_COEF_HV(0, 2));
5277 +       SR(VID_FIR_COEF_HV(0, 3));
5278 +       SR(VID_FIR_COEF_HV(0, 4));
5279 +       SR(VID_FIR_COEF_HV(0, 5));
5280 +       SR(VID_FIR_COEF_HV(0, 6));
5281 +       SR(VID_FIR_COEF_HV(0, 7));
5282 +
5283 +       SR(VID_CONV_COEF(0, 0));
5284 +       SR(VID_CONV_COEF(0, 1));
5285 +       SR(VID_CONV_COEF(0, 2));
5286 +       SR(VID_CONV_COEF(0, 3));
5287 +       SR(VID_CONV_COEF(0, 4));
5288 +
5289 +       SR(VID_FIR_COEF_V(0, 0));
5290 +       SR(VID_FIR_COEF_V(0, 1));
5291 +       SR(VID_FIR_COEF_V(0, 2));
5292 +       SR(VID_FIR_COEF_V(0, 3));
5293 +       SR(VID_FIR_COEF_V(0, 4));
5294 +       SR(VID_FIR_COEF_V(0, 5));
5295 +       SR(VID_FIR_COEF_V(0, 6));
5296 +       SR(VID_FIR_COEF_V(0, 7));
5297 +
5298 +       SR(VID_PRELOAD(0));
5299 +
5300 +       /* VID2 */
5301 +       SR(VID_BA0(1));
5302 +       SR(VID_BA1(1));
5303 +       SR(VID_POSITION(1));
5304 +       SR(VID_SIZE(1));
5305 +       SR(VID_ATTRIBUTES(1));
5306 +       SR(VID_FIFO_THRESHOLD(1));
5307 +       SR(VID_ROW_INC(1));
5308 +       SR(VID_PIXEL_INC(1));
5309 +       SR(VID_FIR(1));
5310 +       SR(VID_PICTURE_SIZE(1));
5311 +       SR(VID_ACCU0(1));
5312 +       SR(VID_ACCU1(1));
5313 +
5314 +       SR(VID_FIR_COEF_H(1, 0));
5315 +       SR(VID_FIR_COEF_H(1, 1));
5316 +       SR(VID_FIR_COEF_H(1, 2));
5317 +       SR(VID_FIR_COEF_H(1, 3));
5318 +       SR(VID_FIR_COEF_H(1, 4));
5319 +       SR(VID_FIR_COEF_H(1, 5));
5320 +       SR(VID_FIR_COEF_H(1, 6));
5321 +       SR(VID_FIR_COEF_H(1, 7));
5322 +
5323 +       SR(VID_FIR_COEF_HV(1, 0));
5324 +       SR(VID_FIR_COEF_HV(1, 1));
5325 +       SR(VID_FIR_COEF_HV(1, 2));
5326 +       SR(VID_FIR_COEF_HV(1, 3));
5327 +       SR(VID_FIR_COEF_HV(1, 4));
5328 +       SR(VID_FIR_COEF_HV(1, 5));
5329 +       SR(VID_FIR_COEF_HV(1, 6));
5330 +       SR(VID_FIR_COEF_HV(1, 7));
5331 +
5332 +       SR(VID_CONV_COEF(1, 0));
5333 +       SR(VID_CONV_COEF(1, 1));
5334 +       SR(VID_CONV_COEF(1, 2));
5335 +       SR(VID_CONV_COEF(1, 3));
5336 +       SR(VID_CONV_COEF(1, 4));
5337 +
5338 +       SR(VID_FIR_COEF_V(1, 0));
5339 +       SR(VID_FIR_COEF_V(1, 1));
5340 +       SR(VID_FIR_COEF_V(1, 2));
5341 +       SR(VID_FIR_COEF_V(1, 3));
5342 +       SR(VID_FIR_COEF_V(1, 4));
5343 +       SR(VID_FIR_COEF_V(1, 5));
5344 +       SR(VID_FIR_COEF_V(1, 6));
5345 +       SR(VID_FIR_COEF_V(1, 7));
5346 +
5347 +       SR(VID_PRELOAD(1));
5348 +}
5349 +
5350 +void dispc_restore_context(void)
5351 +{
5352 +       RR(SYSCONFIG);
5353 +       RR(IRQENABLE);
5354 +       /*RR(CONTROL);*/
5355 +       RR(CONFIG);
5356 +       RR(DEFAULT_COLOR0);
5357 +       RR(DEFAULT_COLOR1);
5358 +       RR(TRANS_COLOR0);
5359 +       RR(TRANS_COLOR1);
5360 +       RR(LINE_NUMBER);
5361 +       RR(TIMING_H);
5362 +       RR(TIMING_V);
5363 +       RR(POL_FREQ);
5364 +       RR(DIVISOR);
5365 +       RR(GLOBAL_ALPHA);
5366 +       RR(SIZE_DIG);
5367 +       RR(SIZE_LCD);
5368 +
5369 +       RR(GFX_BA0);
5370 +       RR(GFX_BA1);
5371 +       RR(GFX_POSITION);
5372 +       RR(GFX_SIZE);
5373 +       RR(GFX_ATTRIBUTES);
5374 +       RR(GFX_FIFO_THRESHOLD);
5375 +       RR(GFX_ROW_INC);
5376 +       RR(GFX_PIXEL_INC);
5377 +       RR(GFX_WINDOW_SKIP);
5378 +       RR(GFX_TABLE_BA);
5379 +
5380 +       RR(DATA_CYCLE1);
5381 +       RR(DATA_CYCLE2);
5382 +       RR(DATA_CYCLE3);
5383 +
5384 +       RR(CPR_COEF_R);
5385 +       RR(CPR_COEF_G);
5386 +       RR(CPR_COEF_B);
5387 +
5388 +       RR(GFX_PRELOAD);
5389 +
5390 +       /* VID1 */
5391 +       RR(VID_BA0(0));
5392 +       RR(VID_BA1(0));
5393 +       RR(VID_POSITION(0));
5394 +       RR(VID_SIZE(0));
5395 +       RR(VID_ATTRIBUTES(0));
5396 +       RR(VID_FIFO_THRESHOLD(0));
5397 +       RR(VID_ROW_INC(0));
5398 +       RR(VID_PIXEL_INC(0));
5399 +       RR(VID_FIR(0));
5400 +       RR(VID_PICTURE_SIZE(0));
5401 +       RR(VID_ACCU0(0));
5402 +       RR(VID_ACCU1(0));
5403 +
5404 +       RR(VID_FIR_COEF_H(0, 0));
5405 +       RR(VID_FIR_COEF_H(0, 1));
5406 +       RR(VID_FIR_COEF_H(0, 2));
5407 +       RR(VID_FIR_COEF_H(0, 3));
5408 +       RR(VID_FIR_COEF_H(0, 4));
5409 +       RR(VID_FIR_COEF_H(0, 5));
5410 +       RR(VID_FIR_COEF_H(0, 6));
5411 +       RR(VID_FIR_COEF_H(0, 7));
5412 +
5413 +       RR(VID_FIR_COEF_HV(0, 0));
5414 +       RR(VID_FIR_COEF_HV(0, 1));
5415 +       RR(VID_FIR_COEF_HV(0, 2));
5416 +       RR(VID_FIR_COEF_HV(0, 3));
5417 +       RR(VID_FIR_COEF_HV(0, 4));
5418 +       RR(VID_FIR_COEF_HV(0, 5));
5419 +       RR(VID_FIR_COEF_HV(0, 6));
5420 +       RR(VID_FIR_COEF_HV(0, 7));
5421 +
5422 +       RR(VID_CONV_COEF(0, 0));
5423 +       RR(VID_CONV_COEF(0, 1));
5424 +       RR(VID_CONV_COEF(0, 2));
5425 +       RR(VID_CONV_COEF(0, 3));
5426 +       RR(VID_CONV_COEF(0, 4));
5427 +
5428 +       RR(VID_FIR_COEF_V(0, 0));
5429 +       RR(VID_FIR_COEF_V(0, 1));
5430 +       RR(VID_FIR_COEF_V(0, 2));
5431 +       RR(VID_FIR_COEF_V(0, 3));
5432 +       RR(VID_FIR_COEF_V(0, 4));
5433 +       RR(VID_FIR_COEF_V(0, 5));
5434 +       RR(VID_FIR_COEF_V(0, 6));
5435 +       RR(VID_FIR_COEF_V(0, 7));
5436 +
5437 +       RR(VID_PRELOAD(0));
5438 +
5439 +       /* VID2 */
5440 +       RR(VID_BA0(1));
5441 +       RR(VID_BA1(1));
5442 +       RR(VID_POSITION(1));
5443 +       RR(VID_SIZE(1));
5444 +       RR(VID_ATTRIBUTES(1));
5445 +       RR(VID_FIFO_THRESHOLD(1));
5446 +       RR(VID_ROW_INC(1));
5447 +       RR(VID_PIXEL_INC(1));
5448 +       RR(VID_FIR(1));
5449 +       RR(VID_PICTURE_SIZE(1));
5450 +       RR(VID_ACCU0(1));
5451 +       RR(VID_ACCU1(1));
5452 +
5453 +       RR(VID_FIR_COEF_H(1, 0));
5454 +       RR(VID_FIR_COEF_H(1, 1));
5455 +       RR(VID_FIR_COEF_H(1, 2));
5456 +       RR(VID_FIR_COEF_H(1, 3));
5457 +       RR(VID_FIR_COEF_H(1, 4));
5458 +       RR(VID_FIR_COEF_H(1, 5));
5459 +       RR(VID_FIR_COEF_H(1, 6));
5460 +       RR(VID_FIR_COEF_H(1, 7));
5461 +
5462 +       RR(VID_FIR_COEF_HV(1, 0));
5463 +       RR(VID_FIR_COEF_HV(1, 1));
5464 +       RR(VID_FIR_COEF_HV(1, 2));
5465 +       RR(VID_FIR_COEF_HV(1, 3));
5466 +       RR(VID_FIR_COEF_HV(1, 4));
5467 +       RR(VID_FIR_COEF_HV(1, 5));
5468 +       RR(VID_FIR_COEF_HV(1, 6));
5469 +       RR(VID_FIR_COEF_HV(1, 7));
5470 +
5471 +       RR(VID_CONV_COEF(1, 0));
5472 +       RR(VID_CONV_COEF(1, 1));
5473 +       RR(VID_CONV_COEF(1, 2));
5474 +       RR(VID_CONV_COEF(1, 3));
5475 +       RR(VID_CONV_COEF(1, 4));
5476 +
5477 +       RR(VID_FIR_COEF_V(1, 0));
5478 +       RR(VID_FIR_COEF_V(1, 1));
5479 +       RR(VID_FIR_COEF_V(1, 2));
5480 +       RR(VID_FIR_COEF_V(1, 3));
5481 +       RR(VID_FIR_COEF_V(1, 4));
5482 +       RR(VID_FIR_COEF_V(1, 5));
5483 +       RR(VID_FIR_COEF_V(1, 6));
5484 +       RR(VID_FIR_COEF_V(1, 7));
5485 +
5486 +       RR(VID_PRELOAD(1));
5487 +
5488 +       /* enable last, because LCD & DIGIT enable are here */
5489 +       RR(CONTROL);
5490 +}
5491 +
5492 +#undef SR
5493 +#undef RR
5494 +
5495 +static inline void enable_clocks(bool enable)
5496 +{
5497 +       if (enable)
5498 +               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
5499 +       else
5500 +               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
5501 +}
5502 +
5503 +bool dispc_go_busy(enum omap_channel channel)
5504 +{
5505 +       int bit;
5506 +
5507 +       if (channel == OMAP_DSS_CHANNEL_LCD)
5508 +               bit = 5; /* GOLCD */
5509 +       else
5510 +               bit = 6; /* GODIGIT */
5511 +
5512 +       return REG_GET(DISPC_CONTROL, bit, bit) == 1;
5513 +}
5514 +
5515 +void dispc_go(enum omap_channel channel)
5516 +{
5517 +       int bit;
5518 +
5519 +       enable_clocks(1);
5520 +
5521 +       if (channel == OMAP_DSS_CHANNEL_LCD)
5522 +               bit = 0; /* LCDENABLE */
5523 +       else
5524 +               bit = 1; /* DIGITALENABLE */
5525 +
5526 +       /* if the channel is not enabled, we don't need GO */
5527 +       if (REG_GET(DISPC_CONTROL, bit, bit) == 0)
5528 +               goto end;
5529 +
5530 +       if (channel == OMAP_DSS_CHANNEL_LCD)
5531 +               bit = 5; /* GOLCD */
5532 +       else
5533 +               bit = 6; /* GODIGIT */
5534 +
5535 +       if (REG_GET(DISPC_CONTROL, bit, bit) == 1) {
5536 +               DSSERR("GO bit not down for channel %d\n", channel);
5537 +               goto end;
5538 +       }
5539 +
5540 +       DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT");
5541 +
5542 +       REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
5543 +end:
5544 +       enable_clocks(0);
5545 +}
5546 +
5547 +static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
5548 +{
5549 +       BUG_ON(plane == OMAP_DSS_GFX);
5550 +
5551 +       dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value);
5552 +}
5553 +
5554 +static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
5555 +{
5556 +       BUG_ON(plane == OMAP_DSS_GFX);
5557 +
5558 +       dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value);
5559 +}
5560 +
5561 +static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value)
5562 +{
5563 +       BUG_ON(plane == OMAP_DSS_GFX);
5564 +
5565 +       dispc_write_reg(DISPC_VID_FIR_COEF_V(plane-1, reg), value);
5566 +}
5567 +
5568 +static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
5569 +               int vscaleup, int five_taps)
5570 +{
5571 +       /* Coefficients for horizontal up-sampling */
5572 +       static const u32 coef_hup[8] = {
5573 +               0x00800000,
5574 +               0x0D7CF800,
5575 +               0x1E70F5FF,
5576 +               0x335FF5FE,
5577 +               0xF74949F7,
5578 +               0xF55F33FB,
5579 +               0xF5701EFE,
5580 +               0xF87C0DFF,
5581 +       };
5582 +
5583 +       /* Coefficients for horizontal down-sampling */
5584 +       static const u32 coef_hdown[8] = {
5585 +               0x24382400,
5586 +               0x28371FFE,
5587 +               0x2C361BFB,
5588 +               0x303516F9,
5589 +               0x11343311,
5590 +               0x1635300C,
5591 +               0x1B362C08,
5592 +               0x1F372804,
5593 +       };
5594 +
5595 +       /* Coefficients for horizontal and vertical up-sampling */
5596 +       static const u32 coef_hvup[2][8] = {
5597 +               {
5598 +               0x00800000,
5599 +               0x037B02FF,
5600 +               0x0C6F05FE,
5601 +               0x205907FB,
5602 +               0x00404000,
5603 +               0x075920FE,
5604 +               0x056F0CFF,
5605 +               0x027B0300,
5606 +               },
5607 +               {
5608 +               0x00800000,
5609 +               0x0D7CF8FF,
5610 +               0x1E70F5FE,
5611 +               0x335FF5FB,
5612 +               0xF7404000,
5613 +               0xF55F33FE,
5614 +               0xF5701EFF,
5615 +               0xF87C0D00,
5616 +               },
5617 +       };
5618 +
5619 +       /* Coefficients for horizontal and vertical down-sampling */
5620 +       static const u32 coef_hvdown[2][8] = {
5621 +               {
5622 +               0x24382400,
5623 +               0x28391F04,
5624 +               0x2D381B08,
5625 +               0x3237170C,
5626 +               0x123737F7,
5627 +               0x173732F9,
5628 +               0x1B382DFB,
5629 +               0x1F3928FE,
5630 +               },
5631 +               {
5632 +               0x24382400,
5633 +               0x28371F04,
5634 +               0x2C361B08,
5635 +               0x3035160C,
5636 +               0x113433F7,
5637 +               0x163530F9,
5638 +               0x1B362CFB,
5639 +               0x1F3728FE,
5640 +               },
5641 +       };
5642 +
5643 +       /* Coefficients for vertical up-sampling */
5644 +       static const u32 coef_vup[8] = {
5645 +               0x00000000,
5646 +               0x0000FF00,
5647 +               0x0000FEFF,
5648 +               0x0000FBFE,
5649 +               0x000000F7,
5650 +               0x0000FEFB,
5651 +               0x0000FFFE,
5652 +               0x000000FF,
5653 +       };
5654 +
5655 +
5656 +       /* Coefficients for vertical down-sampling */
5657 +       static const u32 coef_vdown[8] = {
5658 +               0x00000000,
5659 +               0x000004FE,
5660 +               0x000008FB,
5661 +               0x00000CF9,
5662 +               0x0000F711,
5663 +               0x0000F90C,
5664 +               0x0000FB08,
5665 +               0x0000FE04,
5666 +       };
5667 +
5668 +       const u32 *h_coef;
5669 +       const u32 *hv_coef;
5670 +       const u32 *hv_coef_mod;
5671 +       const u32 *v_coef;
5672 +       int i;
5673 +
5674 +       if (hscaleup)
5675 +               h_coef = coef_hup;
5676 +       else
5677 +               h_coef = coef_hdown;
5678 +
5679 +       if (vscaleup) {
5680 +               hv_coef = coef_hvup[five_taps];
5681 +               v_coef = coef_vup;
5682 +
5683 +               if (hscaleup)
5684 +                       hv_coef_mod = NULL;
5685 +               else
5686 +                       hv_coef_mod = coef_hvdown[five_taps];
5687 +       } else {
5688 +               hv_coef = coef_hvdown[five_taps];
5689 +               v_coef = coef_vdown;
5690 +
5691 +               if (hscaleup)
5692 +                       hv_coef_mod = coef_hvup[five_taps];
5693 +               else
5694 +                       hv_coef_mod = NULL;
5695 +       }
5696 +
5697 +       for (i = 0; i < 8; i++) {
5698 +               u32 h, hv;
5699 +
5700 +               h = h_coef[i];
5701 +
5702 +               hv = hv_coef[i];
5703 +
5704 +               if (hv_coef_mod) {
5705 +                       hv &= 0xffffff00;
5706 +                       hv |= (hv_coef_mod[i] & 0xff);
5707 +               }
5708 +
5709 +               _dispc_write_firh_reg(plane, i, h);
5710 +               _dispc_write_firhv_reg(plane, i, hv);
5711 +       }
5712 +
5713 +       if (!five_taps)
5714 +               return;
5715 +
5716 +       for (i = 0; i < 8; i++) {
5717 +               u32 v;
5718 +               v = v_coef[i];
5719 +               _dispc_write_firv_reg(plane, i, v);
5720 +       }
5721 +}
5722 +
5723 +static void _dispc_setup_color_conv_coef(void)
5724 +{
5725 +       const struct color_conv_coef {
5726 +               int  ry,  rcr,  rcb,   gy,  gcr,  gcb,   by,  bcr,  bcb;
5727 +               int  full_range;
5728 +       }  ctbl_bt601_5 = {
5729 +               298,  409,    0,  298, -208, -100,  298,    0,  517, 0,
5730 +       };
5731 +
5732 +       const struct color_conv_coef *ct;
5733 +
5734 +#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
5735 +
5736 +       ct = &ctbl_bt601_5;
5737 +
5738 +       dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry));
5739 +       dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy,  ct->rcb));
5740 +       dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr));
5741 +       dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by));
5742 +       dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0,       ct->bcb));
5743 +
5744 +       dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry));
5745 +       dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy,  ct->rcb));
5746 +       dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr));
5747 +       dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by));
5748 +       dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0,       ct->bcb));
5749 +
5750 +#undef CVAL
5751 +
5752 +       REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11);
5753 +       REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11);
5754 +}
5755 +
5756 +
5757 +static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr)
5758 +{
5759 +       const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0,
5760 +               DISPC_VID_BA0(0),
5761 +               DISPC_VID_BA0(1) };
5762 +
5763 +       dispc_write_reg(ba0_reg[plane], paddr);
5764 +}
5765 +
5766 +static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr)
5767 +{
5768 +       const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1,
5769 +                                     DISPC_VID_BA1(0),
5770 +                                     DISPC_VID_BA1(1) };
5771 +
5772 +       dispc_write_reg(ba1_reg[plane], paddr);
5773 +}
5774 +
5775 +static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y)
5776 +{
5777 +       const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION,
5778 +                                     DISPC_VID_POSITION(0),
5779 +                                     DISPC_VID_POSITION(1) };
5780 +
5781 +       u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
5782 +       dispc_write_reg(pos_reg[plane], val);
5783 +}
5784 +
5785 +static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
5786 +{
5787 +       const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE,
5788 +                                     DISPC_VID_PICTURE_SIZE(0),
5789 +                                     DISPC_VID_PICTURE_SIZE(1) };
5790 +       u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
5791 +       dispc_write_reg(siz_reg[plane], val);
5792 +}
5793 +
5794 +static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
5795 +{
5796 +       u32 val;
5797 +       const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0),
5798 +                                     DISPC_VID_SIZE(1) };
5799 +
5800 +       BUG_ON(plane == OMAP_DSS_GFX);
5801 +
5802 +       val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
5803 +       dispc_write_reg(vsi_reg[plane-1], val);
5804 +}
5805 +
5806 +static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
5807 +{
5808 +
5809 +       BUG_ON(plane == OMAP_DSS_VIDEO1);
5810 +
5811 +       if (plane == OMAP_DSS_GFX)
5812 +               REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
5813 +       else if (plane == OMAP_DSS_VIDEO2)
5814 +               REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16);
5815 +}
5816 +
5817 +static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc)
5818 +{
5819 +       const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC,
5820 +                                    DISPC_VID_PIXEL_INC(0),
5821 +                                    DISPC_VID_PIXEL_INC(1) };
5822 +
5823 +       dispc_write_reg(ri_reg[plane], inc);
5824 +}
5825 +
5826 +static void _dispc_set_row_inc(enum omap_plane plane, s32 inc)
5827 +{
5828 +       const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC,
5829 +                                    DISPC_VID_ROW_INC(0),
5830 +                                    DISPC_VID_ROW_INC(1) };
5831 +
5832 +       dispc_write_reg(ri_reg[plane], inc);
5833 +}
5834 +
5835 +static void _dispc_set_color_mode(enum omap_plane plane,
5836 +               enum omap_color_mode color_mode)
5837 +{
5838 +       u32 m = 0;
5839 +
5840 +       switch (color_mode) {
5841 +       case OMAP_DSS_COLOR_CLUT1:
5842 +               m = 0x0; break;
5843 +       case OMAP_DSS_COLOR_CLUT2:
5844 +               m = 0x1; break;
5845 +       case OMAP_DSS_COLOR_CLUT4:
5846 +               m = 0x2; break;
5847 +       case OMAP_DSS_COLOR_CLUT8:
5848 +               m = 0x3; break;
5849 +       case OMAP_DSS_COLOR_RGB12U:
5850 +               m = 0x4; break;
5851 +       case OMAP_DSS_COLOR_ARGB16:
5852 +               m = 0x5; break;
5853 +       case OMAP_DSS_COLOR_RGB16:
5854 +               m = 0x6; break;
5855 +       case OMAP_DSS_COLOR_RGB24U:
5856 +               m = 0x8; break;
5857 +       case OMAP_DSS_COLOR_RGB24P:
5858 +               m = 0x9; break;
5859 +       case OMAP_DSS_COLOR_YUV2:
5860 +               m = 0xa; break;
5861 +       case OMAP_DSS_COLOR_UYVY:
5862 +               m = 0xb; break;
5863 +       case OMAP_DSS_COLOR_ARGB32:
5864 +               m = 0xc; break;
5865 +       case OMAP_DSS_COLOR_RGBA32:
5866 +               m = 0xd; break;
5867 +       case OMAP_DSS_COLOR_RGBX32:
5868 +               m = 0xe; break;
5869 +       default:
5870 +               BUG(); break;
5871 +       }
5872 +
5873 +       REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1);
5874 +}
5875 +
5876 +static void _dispc_set_channel_out(enum omap_plane plane,
5877 +               enum omap_channel channel)
5878 +{
5879 +       int shift;
5880 +       u32 val;
5881 +
5882 +       switch (plane) {
5883 +       case OMAP_DSS_GFX:
5884 +               shift = 8;
5885 +               break;
5886 +       case OMAP_DSS_VIDEO1:
5887 +       case OMAP_DSS_VIDEO2:
5888 +               shift = 16;
5889 +               break;
5890 +       default:
5891 +               BUG();
5892 +               return;
5893 +       }
5894 +
5895 +       val = dispc_read_reg(dispc_reg_att[plane]);
5896 +       val = FLD_MOD(val, channel, shift, shift);
5897 +       dispc_write_reg(dispc_reg_att[plane], val);
5898 +}
5899 +
5900 +void dispc_set_burst_size(enum omap_plane plane,
5901 +               enum omap_burst_size burst_size)
5902 +{
5903 +       int shift;
5904 +       u32 val;
5905 +
5906 +       enable_clocks(1);
5907 +
5908 +       switch (plane) {
5909 +       case OMAP_DSS_GFX:
5910 +               shift = 6;
5911 +               break;
5912 +       case OMAP_DSS_VIDEO1:
5913 +       case OMAP_DSS_VIDEO2:
5914 +               shift = 14;
5915 +               break;
5916 +       default:
5917 +               BUG();
5918 +               return;
5919 +       }
5920 +
5921 +       val = dispc_read_reg(dispc_reg_att[plane]);
5922 +       val = FLD_MOD(val, burst_size, shift+1, shift);
5923 +       dispc_write_reg(dispc_reg_att[plane], val);
5924 +
5925 +       enable_clocks(0);
5926 +}
5927 +
5928 +static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
5929 +{
5930 +       u32 val;
5931 +
5932 +       BUG_ON(plane == OMAP_DSS_GFX);
5933 +
5934 +       val = dispc_read_reg(dispc_reg_att[plane]);
5935 +       val = FLD_MOD(val, enable, 9, 9);
5936 +       dispc_write_reg(dispc_reg_att[plane], val);
5937 +}
5938 +
5939 +void dispc_enable_replication(enum omap_plane plane, bool enable)
5940 +{
5941 +       int bit;
5942 +
5943 +       if (plane == OMAP_DSS_GFX)
5944 +               bit = 5;
5945 +       else
5946 +               bit = 10;
5947 +
5948 +       enable_clocks(1);
5949 +       REG_FLD_MOD(dispc_reg_att[plane], enable, bit, bit);
5950 +       enable_clocks(0);
5951 +}
5952 +
5953 +void dispc_set_lcd_size(u16 width, u16 height)
5954 +{
5955 +       u32 val;
5956 +       BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
5957 +       val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
5958 +       enable_clocks(1);
5959 +       dispc_write_reg(DISPC_SIZE_LCD, val);
5960 +       enable_clocks(0);
5961 +}
5962 +
5963 +void dispc_set_digit_size(u16 width, u16 height)
5964 +{
5965 +       u32 val;
5966 +       BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
5967 +       val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
5968 +       enable_clocks(1);
5969 +       dispc_write_reg(DISPC_SIZE_DIG, val);
5970 +       enable_clocks(0);
5971 +}
5972 +
5973 +static void dispc_read_plane_fifo_sizes(void)
5974 +{
5975 +       const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
5976 +                                     DISPC_VID_FIFO_SIZE_STATUS(0),
5977 +                                     DISPC_VID_FIFO_SIZE_STATUS(1) };
5978 +       u32 size;
5979 +       int plane;
5980 +
5981 +       enable_clocks(1);
5982 +
5983 +       for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
5984 +               if (cpu_is_omap24xx())
5985 +                       size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0);
5986 +               else if (cpu_is_omap34xx())
5987 +                       size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0);
5988 +               else
5989 +                       BUG();
5990 +
5991 +               dispc.fifo_size[plane] = size;
5992 +       }
5993 +
5994 +       enable_clocks(0);
5995 +}
5996 +
5997 +u32 dispc_get_plane_fifo_size(enum omap_plane plane)
5998 +{
5999 +       return dispc.fifo_size[plane];
6000 +}
6001 +
6002 +void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
6003 +{
6004 +       const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
6005 +                                      DISPC_VID_FIFO_THRESHOLD(0),
6006 +                                      DISPC_VID_FIFO_THRESHOLD(1) };
6007 +       enable_clocks(1);
6008 +
6009 +       DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
6010 +                       plane,
6011 +                       REG_GET(ftrs_reg[plane], 11, 0),
6012 +                       REG_GET(ftrs_reg[plane], 27, 16),
6013 +                       low, high);
6014 +
6015 +       if (cpu_is_omap24xx())
6016 +               dispc_write_reg(ftrs_reg[plane],
6017 +                               FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0));
6018 +       else
6019 +               dispc_write_reg(ftrs_reg[plane],
6020 +                               FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0));
6021 +
6022 +       enable_clocks(0);
6023 +}
6024 +
6025 +void dispc_enable_fifomerge(bool enable)
6026 +{
6027 +       enable_clocks(1);
6028 +
6029 +       DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
6030 +       REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
6031 +
6032 +       enable_clocks(0);
6033 +}
6034 +
6035 +static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc)
6036 +{
6037 +       u32 val;
6038 +       const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0),
6039 +                                     DISPC_VID_FIR(1) };
6040 +
6041 +       BUG_ON(plane == OMAP_DSS_GFX);
6042 +
6043 +       if (cpu_is_omap24xx())
6044 +               val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0);
6045 +       else
6046 +               val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
6047 +       dispc_write_reg(fir_reg[plane-1], val);
6048 +}
6049 +
6050 +static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
6051 +{
6052 +       u32 val;
6053 +       const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0),
6054 +                                     DISPC_VID_ACCU0(1) };
6055 +
6056 +       BUG_ON(plane == OMAP_DSS_GFX);
6057 +
6058 +       val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
6059 +       dispc_write_reg(ac0_reg[plane-1], val);
6060 +}
6061 +
6062 +static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
6063 +{
6064 +       u32 val;
6065 +       const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0),
6066 +                                     DISPC_VID_ACCU1(1) };
6067 +
6068 +       BUG_ON(plane == OMAP_DSS_GFX);
6069 +
6070 +       val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
6071 +       dispc_write_reg(ac1_reg[plane-1], val);
6072 +}
6073 +
6074 +
6075 +static void _dispc_set_scaling(enum omap_plane plane,
6076 +               u16 orig_width, u16 orig_height,
6077 +               u16 out_width, u16 out_height,
6078 +               bool ilace, bool five_taps,
6079 +               bool fieldmode)
6080 +{
6081 +       int fir_hinc;
6082 +       int fir_vinc;
6083 +       int hscaleup, vscaleup;
6084 +       int accu0 = 0;
6085 +       int accu1 = 0;
6086 +       u32 l;
6087 +
6088 +       BUG_ON(plane == OMAP_DSS_GFX);
6089 +
6090 +       hscaleup = orig_width <= out_width;
6091 +       vscaleup = orig_height <= out_height;
6092 +
6093 +       _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps);
6094 +
6095 +       if (!orig_width || orig_width == out_width)
6096 +               fir_hinc = 0;
6097 +       else
6098 +               fir_hinc = 1024 * orig_width / out_width;
6099 +
6100 +       if (!orig_height || orig_height == out_height)
6101 +               fir_vinc = 0;
6102 +       else
6103 +               fir_vinc = 1024 * orig_height / out_height;
6104 +
6105 +       _dispc_set_fir(plane, fir_hinc, fir_vinc);
6106 +
6107 +       l = dispc_read_reg(dispc_reg_att[plane]);
6108 +       l &= ~((0x0f << 5) | (0x3 << 21));
6109 +
6110 +       l |= fir_hinc ? (1 << 5) : 0;
6111 +       l |= fir_vinc ? (1 << 6) : 0;
6112 +
6113 +       l |= hscaleup ? 0 : (1 << 7);
6114 +       l |= vscaleup ? 0 : (1 << 8);
6115 +
6116 +       l |= five_taps ? (1 << 21) : 0;
6117 +       l |= five_taps ? (1 << 22) : 0;
6118 +
6119 +       dispc_write_reg(dispc_reg_att[plane], l);
6120 +
6121 +       /*
6122 +        * field 0 = even field = bottom field
6123 +        * field 1 = odd field = top field
6124 +        */
6125 +       if (ilace && !fieldmode) {
6126 +               accu1 = 0;
6127 +               accu0 = (fir_vinc / 2) & 0x3ff;
6128 +               if (accu0 >= 1024/2) {
6129 +                       accu1 = 1024/2;
6130 +                       accu0 -= accu1;
6131 +               }
6132 +       }
6133 +
6134 +       _dispc_set_vid_accu0(plane, 0, accu0);
6135 +       _dispc_set_vid_accu1(plane, 0, accu1);
6136 +}
6137 +
6138 +static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
6139 +               bool mirroring, enum omap_color_mode color_mode)
6140 +{
6141 +       if (color_mode == OMAP_DSS_COLOR_YUV2 ||
6142 +                       color_mode == OMAP_DSS_COLOR_UYVY) {
6143 +               int vidrot = 0;
6144 +
6145 +               if (mirroring) {
6146 +                       switch (rotation) {
6147 +                       case 0:
6148 +                               vidrot = 2;
6149 +                               break;
6150 +                       case 1:
6151 +                               vidrot = 1;
6152 +                               break;
6153 +                       case 2:
6154 +                               vidrot = 0;
6155 +                               break;
6156 +                       case 3:
6157 +                               vidrot = 3;
6158 +                               break;
6159 +                       }
6160 +               } else {
6161 +                       switch (rotation) {
6162 +                       case 0:
6163 +                               vidrot = 0;
6164 +                               break;
6165 +                       case 1:
6166 +                               vidrot = 1;
6167 +                               break;
6168 +                       case 2:
6169 +                               vidrot = 2;
6170 +                               break;
6171 +                       case 3:
6172 +                               vidrot = 3;
6173 +                               break;
6174 +                       }
6175 +               }
6176 +
6177 +               REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12);
6178 +
6179 +               if (rotation == 1 || rotation == 3)
6180 +                       REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18);
6181 +               else
6182 +                       REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18);
6183 +       } else {
6184 +               REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12);
6185 +               REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18);
6186 +       }
6187 +}
6188 +
6189 +static s32 pixinc(int pixels, u8 ps)
6190 +{
6191 +       if (pixels == 1)
6192 +               return 1;
6193 +       else if (pixels > 1)
6194 +               return 1 + (pixels - 1) * ps;
6195 +       else if (pixels < 0)
6196 +               return 1 - (-pixels + 1) * ps;
6197 +       else
6198 +               BUG();
6199 +}
6200 +
6201 +static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
6202 +               u16 screen_width,
6203 +               u16 width, u16 height,
6204 +               enum omap_color_mode color_mode, bool fieldmode,
6205 +               unsigned int field_offset,
6206 +               unsigned *offset0, unsigned *offset1,
6207 +               s32 *row_inc, s32 *pix_inc)
6208 +{
6209 +       u8 ps;
6210 +
6211 +       switch (color_mode) {
6212 +       case OMAP_DSS_COLOR_RGB16:
6213 +       case OMAP_DSS_COLOR_ARGB16:
6214 +               ps = 2;
6215 +               break;
6216 +
6217 +       case OMAP_DSS_COLOR_RGB24P:
6218 +               ps = 3;
6219 +               break;
6220 +
6221 +       case OMAP_DSS_COLOR_RGB24U:
6222 +       case OMAP_DSS_COLOR_ARGB32:
6223 +       case OMAP_DSS_COLOR_RGBA32:
6224 +       case OMAP_DSS_COLOR_RGBX32:
6225 +       case OMAP_DSS_COLOR_YUV2:
6226 +       case OMAP_DSS_COLOR_UYVY:
6227 +               ps = 4;
6228 +               break;
6229 +
6230 +       default:
6231 +               BUG();
6232 +               return;
6233 +       }
6234 +
6235 +       DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
6236 +                       width, height);
6237 +
6238 +       /*
6239 +        * field 0 = even field = bottom field
6240 +        * field 1 = odd field = top field
6241 +        */
6242 +       switch (rotation + mirror * 4) {
6243 +       case 0:
6244 +       case 2:
6245 +               /*
6246 +                * If the pixel format is YUV or UYVY divide the width
6247 +                * of the image by 2 for 0 and 180 degree rotation.
6248 +                */
6249 +               if (color_mode == OMAP_DSS_COLOR_YUV2 ||
6250 +                       color_mode == OMAP_DSS_COLOR_UYVY)
6251 +                       width = width >> 1;
6252 +       case 1:
6253 +       case 3:
6254 +               *offset1 = 0;
6255 +               if (field_offset)
6256 +                       *offset0 = field_offset * screen_width * ps;
6257 +               else
6258 +                       *offset0 = 0;
6259 +
6260 +               *row_inc = pixinc(1 + (screen_width - width) +
6261 +                               (fieldmode ? screen_width : 0),
6262 +                               ps);
6263 +               *pix_inc = pixinc(1, ps);
6264 +               break;
6265 +
6266 +       case 4:
6267 +       case 6:
6268 +               /* If the pixel format is YUV or UYVY divide the width
6269 +                * of the image by 2  for 0 degree and 180 degree
6270 +                */
6271 +               if (color_mode == OMAP_DSS_COLOR_YUV2 ||
6272 +                       color_mode == OMAP_DSS_COLOR_UYVY)
6273 +                       width = width >> 1;
6274 +       case 5:
6275 +       case 7:
6276 +               *offset1 = 0;
6277 +               if (field_offset)
6278 +                       *offset0 = field_offset * screen_width * ps;
6279 +               else
6280 +                       *offset0 = 0;
6281 +               *row_inc = pixinc(1 - (screen_width + width) -
6282 +                               (fieldmode ? screen_width : 0),
6283 +                               ps);
6284 +               *pix_inc = pixinc(1, ps);
6285 +               break;
6286 +
6287 +       default:
6288 +               BUG();
6289 +       }
6290 +}
6291 +
6292 +static void calc_dma_rotation_offset(u8 rotation, bool mirror,
6293 +               u16 screen_width,
6294 +               u16 width, u16 height,
6295 +               enum omap_color_mode color_mode, bool fieldmode,
6296 +               unsigned int field_offset,
6297 +               unsigned *offset0, unsigned *offset1,
6298 +               s32 *row_inc, s32 *pix_inc)
6299 +{
6300 +       u8 ps;
6301 +       u16 fbw, fbh;
6302 +
6303 +       switch (color_mode) {
6304 +       case OMAP_DSS_COLOR_RGB16:
6305 +       case OMAP_DSS_COLOR_ARGB16:
6306 +               ps = 2;
6307 +               break;
6308 +
6309 +       case OMAP_DSS_COLOR_RGB24P:
6310 +               ps = 3;
6311 +               break;
6312 +
6313 +       case OMAP_DSS_COLOR_RGB24U:
6314 +       case OMAP_DSS_COLOR_ARGB32:
6315 +       case OMAP_DSS_COLOR_RGBA32:
6316 +       case OMAP_DSS_COLOR_RGBX32:
6317 +               ps = 4;
6318 +               break;
6319 +
6320 +       case OMAP_DSS_COLOR_YUV2:
6321 +       case OMAP_DSS_COLOR_UYVY:
6322 +               ps = 2;
6323 +               break;
6324 +       default:
6325 +               BUG();
6326 +               return;
6327 +       }
6328 +
6329 +       DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
6330 +                       width, height);
6331 +
6332 +       /* width & height are overlay sizes, convert to fb sizes */
6333 +
6334 +       if (rotation == 0 || rotation == 2) {
6335 +               fbw = width;
6336 +               fbh = height;
6337 +       } else {
6338 +               fbw = height;
6339 +               fbh = width;
6340 +       }
6341 +
6342 +       /*
6343 +        * field 0 = even field = bottom field
6344 +        * field 1 = odd field = top field
6345 +        */
6346 +       switch (rotation + mirror * 4) {
6347 +       case 0:
6348 +               *offset1 = 0;
6349 +               if (field_offset)
6350 +                       *offset0 = *offset1 + field_offset * screen_width * ps;
6351 +               else
6352 +                       *offset0 = *offset1;
6353 +               *row_inc = pixinc(1 + (screen_width - fbw) +
6354 +                               (fieldmode ? screen_width : 0),
6355 +                               ps);
6356 +               *pix_inc = pixinc(1, ps);
6357 +               break;
6358 +       case 1:
6359 +               *offset1 = screen_width * (fbh - 1) * ps;
6360 +               if (field_offset)
6361 +                       *offset0 = *offset1 + field_offset * ps;
6362 +               else
6363 +                       *offset0 = *offset1;
6364 +               *row_inc = pixinc(screen_width * (fbh - 1) + 1 +
6365 +                               (fieldmode ? 1 : 0), ps);
6366 +               *pix_inc = pixinc(-screen_width, ps);
6367 +               break;
6368 +       case 2:
6369 +               *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
6370 +               if (field_offset)
6371 +                       *offset0 = *offset1 - field_offset * screen_width * ps;
6372 +               else
6373 +                       *offset0 = *offset1;
6374 +               *row_inc = pixinc(-1 -
6375 +                               (screen_width - fbw) -
6376 +                               (fieldmode ? screen_width : 0),
6377 +                               ps);
6378 +               *pix_inc = pixinc(-1, ps);
6379 +               break;
6380 +       case 3:
6381 +               *offset1 = (fbw - 1) * ps;
6382 +               if (field_offset)
6383 +                       *offset0 = *offset1 - field_offset * ps;
6384 +               else
6385 +                       *offset0 = *offset1;
6386 +               *row_inc = pixinc(-screen_width * (fbh - 1) - 1 -
6387 +                               (fieldmode ? 1 : 0), ps);
6388 +               *pix_inc = pixinc(screen_width, ps);
6389 +               break;
6390 +
6391 +       /* mirroring */
6392 +       case 0 + 4:
6393 +               *offset1 = (fbw - 1) * ps;
6394 +               if (field_offset)
6395 +                       *offset0 = *offset1 + field_offset * screen_width * ps;
6396 +               else
6397 +                       *offset0 = *offset1;
6398 +               *row_inc = pixinc(screen_width * 2 - 1 +
6399 +                               (fieldmode ? screen_width : 0),
6400 +                               ps);
6401 +               *pix_inc = pixinc(-1, ps);
6402 +               break;
6403 +
6404 +       case 1 + 4:
6405 +               *offset1 = 0;
6406 +               if (field_offset)
6407 +                       *offset0 = *offset1 + field_offset * ps;
6408 +               else
6409 +                       *offset0 = *offset1;
6410 +               *row_inc = pixinc(-screen_width * (fbh - 1) + 1 +
6411 +                               (fieldmode ? 1 : 0),
6412 +                               ps);
6413 +               *pix_inc = pixinc(screen_width, ps);
6414 +               break;
6415 +
6416 +       case 2 + 4:
6417 +               *offset1 = screen_width * (fbh - 1) * ps;
6418 +               if (field_offset)
6419 +                       *offset0 = *offset1 - field_offset * screen_width * ps;
6420 +               else
6421 +                       *offset0 = *offset1;
6422 +               *row_inc = pixinc(1 - screen_width * 2 -
6423 +                               (fieldmode ? screen_width : 0),
6424 +                               ps);
6425 +               *pix_inc = pixinc(1, ps);
6426 +               break;
6427 +
6428 +       case 3 + 4:
6429 +               *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
6430 +               if (field_offset)
6431 +                       *offset0 = *offset1 - field_offset * ps;
6432 +               else
6433 +                       *offset0 = *offset1;
6434 +               *row_inc = pixinc(screen_width * (fbh - 1) - 1 -
6435 +                               (fieldmode ? 1 : 0),
6436 +                               ps);
6437 +               *pix_inc = pixinc(-screen_width, ps);
6438 +               break;
6439 +
6440 +       default:
6441 +               BUG();
6442 +       }
6443 +}
6444 +
6445 +static unsigned long calc_fclk_five_taps(u16 width, u16 height,
6446 +               u16 out_width, u16 out_height, enum omap_color_mode color_mode)
6447 +{
6448 +       u32 fclk = 0;
6449 +       /* FIXME venc pclk? */
6450 +       u64 tmp, pclk = dispc_pclk_rate();
6451 +
6452 +       if (height > out_height) {
6453 +               /* FIXME get real display PPL */
6454 +               unsigned int ppl = 800;
6455 +
6456 +               tmp = pclk * height * out_width;
6457 +               do_div(tmp, 2 * out_height * ppl);
6458 +               fclk = tmp;
6459 +
6460 +               if (height > 2 * out_height && ppl != out_width) {
6461 +                       tmp = pclk * (height - 2 * out_height) * out_width;
6462 +                       do_div(tmp, 2 * out_height * (ppl - out_width));
6463 +                       fclk = max(fclk, (u32) tmp);
6464 +               }
6465 +       }
6466 +
6467 +       if (width > out_width) {
6468 +               tmp = pclk * width;
6469 +               do_div(tmp, out_width);
6470 +               fclk = max(fclk, (u32) tmp);
6471 +
6472 +               if (color_mode == OMAP_DSS_COLOR_RGB24U)
6473 +                       fclk <<= 1;
6474 +       }
6475 +
6476 +       return fclk;
6477 +}
6478 +
6479 +static unsigned long calc_fclk(u16 width, u16 height,
6480 +               u16 out_width, u16 out_height)
6481 +{
6482 +       unsigned int hf, vf;
6483 +
6484 +       /*
6485 +        * FIXME how to determine the 'A' factor
6486 +        * for the no downscaling case ?
6487 +        */
6488 +
6489 +       if (width > 3 * out_width)
6490 +               hf = 4;
6491 +       else if (width > 2 * out_width)
6492 +               hf = 3;
6493 +       else if (width > out_width)
6494 +               hf = 2;
6495 +       else
6496 +               hf = 1;
6497 +
6498 +       if (height > out_height)
6499 +               vf = 2;
6500 +       else
6501 +               vf = 1;
6502 +
6503 +       /* FIXME venc pclk? */
6504 +       return dispc_pclk_rate() * vf * hf;
6505 +}
6506 +
6507 +void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
6508 +{
6509 +       enable_clocks(1);
6510 +       _dispc_set_channel_out(plane, channel_out);
6511 +       enable_clocks(0);
6512 +}
6513 +
6514 +static int _dispc_setup_plane(enum omap_plane plane,
6515 +               u32 paddr, u16 screen_width,
6516 +               u16 pos_x, u16 pos_y,
6517 +               u16 width, u16 height,
6518 +               u16 out_width, u16 out_height,
6519 +               enum omap_color_mode color_mode,
6520 +               bool ilace,
6521 +               enum omap_dss_rotation_type rotation_type,
6522 +               u8 rotation, int mirror,
6523 +               u8 global_alpha)
6524 +{
6525 +       const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
6526 +       bool five_taps = 0;
6527 +       bool fieldmode = 0;
6528 +       int cconv = 0;
6529 +       unsigned offset0, offset1;
6530 +       s32 row_inc;
6531 +       s32 pix_inc;
6532 +       u16 frame_height = height;
6533 +       unsigned int field_offset = 0;
6534 +
6535 +       if (paddr == 0)
6536 +               return -EINVAL;
6537 +
6538 +       if (ilace && height == out_height)
6539 +               fieldmode = 1;
6540 +
6541 +       if (ilace) {
6542 +               if (fieldmode)
6543 +                       height /= 2;
6544 +               pos_y /= 2;
6545 +               out_height /= 2;
6546 +
6547 +               DSSDBG("adjusting for ilace: height %d, pos_y %d, "
6548 +                               "out_height %d\n",
6549 +                               height, pos_y, out_height);
6550 +       }
6551 +
6552 +       if (plane == OMAP_DSS_GFX) {
6553 +               if (width != out_width || height != out_height)
6554 +                       return -EINVAL;
6555 +
6556 +               switch (color_mode) {
6557 +               case OMAP_DSS_COLOR_ARGB16:
6558 +               case OMAP_DSS_COLOR_RGB16:
6559 +               case OMAP_DSS_COLOR_RGB24P:
6560 +               case OMAP_DSS_COLOR_RGB24U:
6561 +               case OMAP_DSS_COLOR_ARGB32:
6562 +               case OMAP_DSS_COLOR_RGBA32:
6563 +               case OMAP_DSS_COLOR_RGBX32:
6564 +                       break;
6565 +
6566 +               default:
6567 +                       return -EINVAL;
6568 +               }
6569 +       } else {
6570 +               /* video plane */
6571 +
6572 +               unsigned long fclk = 0;
6573 +
6574 +               if (out_width < width / maxdownscale ||
6575 +                  out_width > width * 8)
6576 +                       return -EINVAL;
6577 +
6578 +               if (out_height < height / maxdownscale ||
6579 +                  out_height > height * 8)
6580 +                       return -EINVAL;
6581 +
6582 +               switch (color_mode) {
6583 +               case OMAP_DSS_COLOR_RGB16:
6584 +               case OMAP_DSS_COLOR_RGB24P:
6585 +               case OMAP_DSS_COLOR_RGB24U:
6586 +               case OMAP_DSS_COLOR_RGBX32:
6587 +                       break;
6588 +
6589 +               case OMAP_DSS_COLOR_ARGB16:
6590 +               case OMAP_DSS_COLOR_ARGB32:
6591 +               case OMAP_DSS_COLOR_RGBA32:
6592 +                       if (plane == OMAP_DSS_VIDEO1)
6593 +                               return -EINVAL;
6594 +                       break;
6595 +
6596 +               case OMAP_DSS_COLOR_YUV2:
6597 +               case OMAP_DSS_COLOR_UYVY:
6598 +                       cconv = 1;
6599 +                       break;
6600 +
6601 +               default:
6602 +                       return -EINVAL;
6603 +               }
6604 +
6605 +               /* Must use 5-tap filter? */
6606 +               five_taps = height > out_height * 2;
6607 +
6608 +               if (!five_taps) {
6609 +                       fclk = calc_fclk(width, height,
6610 +                                       out_width, out_height);
6611 +
6612 +                       /* Try 5-tap filter if 3-tap fclk is too high */
6613 +                       if (cpu_is_omap34xx() && height > out_height &&
6614 +                                       fclk > dispc_fclk_rate())
6615 +                               five_taps = true;
6616 +               }
6617 +
6618 +               if (width > (2048 >> five_taps))
6619 +                       return -EINVAL;
6620 +
6621 +               if (five_taps)
6622 +                       fclk = calc_fclk_five_taps(width, height,
6623 +                                       out_width, out_height, color_mode);
6624 +
6625 +               DSSDBG("required fclk rate = %lu Hz\n", fclk);
6626 +               DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
6627 +
6628 +               if (fclk > dispc_fclk_rate()) {
6629 +                       DSSERR("failed to set up scaling, "
6630 +                                       "required fclk rate = %lu Hz, "
6631 +                                       "current fclk rate = %lu Hz\n",
6632 +                                       fclk, dispc_fclk_rate());
6633 +                       return -EINVAL;
6634 +               }
6635 +       }
6636 +
6637 +       if (ilace && !fieldmode) {
6638 +               /*
6639 +                * when downscaling the bottom field may have to start several
6640 +                * source lines below the top field. Unfortunately ACCUI
6641 +                * registers will only hold the fractional part of the offset
6642 +                * so the integer part must be added to the base address of the
6643 +                * bottom field.
6644 +                */
6645 +               if (!height || height == out_height)
6646 +                       field_offset = 0;
6647 +               else
6648 +                       field_offset = height / out_height / 2;
6649 +       }
6650 +
6651 +       /* Fields are independent but interleaved in memory. */
6652 +       if (fieldmode)
6653 +               field_offset = 1;
6654 +
6655 +       if (rotation_type == OMAP_DSS_ROT_DMA)
6656 +               calc_dma_rotation_offset(rotation, mirror,
6657 +                               screen_width, width, frame_height, color_mode,
6658 +                               fieldmode, field_offset,
6659 +                               &offset0, &offset1, &row_inc, &pix_inc);
6660 +       else
6661 +               calc_vrfb_rotation_offset(rotation, mirror,
6662 +                               screen_width, width, frame_height, color_mode,
6663 +                               fieldmode, field_offset,
6664 +                               &offset0, &offset1, &row_inc, &pix_inc);
6665 +
6666 +       DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
6667 +                       offset0, offset1, row_inc, pix_inc);
6668 +
6669 +       _dispc_set_color_mode(plane, color_mode);
6670 +
6671 +       _dispc_set_plane_ba0(plane, paddr + offset0);
6672 +       _dispc_set_plane_ba1(plane, paddr + offset1);
6673 +
6674 +       _dispc_set_row_inc(plane, row_inc);
6675 +       _dispc_set_pix_inc(plane, pix_inc);
6676 +
6677 +       DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height,
6678 +                       out_width, out_height);
6679 +
6680 +       _dispc_set_plane_pos(plane, pos_x, pos_y);
6681 +
6682 +       _dispc_set_pic_size(plane, width, height);
6683 +
6684 +       if (plane != OMAP_DSS_GFX) {
6685 +               _dispc_set_scaling(plane, width, height,
6686 +                                  out_width, out_height,
6687 +                                  ilace, five_taps, fieldmode);
6688 +               _dispc_set_vid_size(plane, out_width, out_height);
6689 +               _dispc_set_vid_color_conv(plane, cconv);
6690 +       }
6691 +
6692 +       _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
6693 +
6694 +       if (plane != OMAP_DSS_VIDEO1)
6695 +               _dispc_setup_global_alpha(plane, global_alpha);
6696 +
6697 +       return 0;
6698 +}
6699 +
6700 +static void _dispc_enable_plane(enum omap_plane plane, bool enable)
6701 +{
6702 +       REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0);
6703 +}
6704 +
6705 +static void dispc_disable_isr(void *data, u32 mask)
6706 +{
6707 +       struct completion *compl = data;
6708 +       complete(compl);
6709 +}
6710 +
6711 +static void _enable_lcd_out(bool enable)
6712 +{
6713 +       REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
6714 +}
6715 +
6716 +void dispc_enable_lcd_out(bool enable)
6717 +{
6718 +       struct completion frame_done_completion;
6719 +       bool is_on;
6720 +       int r;
6721 +
6722 +       enable_clocks(1);
6723 +
6724 +       /* When we disable LCD output, we need to wait until frame is done.
6725 +        * Otherwise the DSS is still working, and turning off the clocks
6726 +        * prevents DSS from going to OFF mode */
6727 +       is_on = REG_GET(DISPC_CONTROL, 0, 0);
6728 +
6729 +       if (!enable && is_on) {
6730 +               init_completion(&frame_done_completion);
6731 +
6732 +               r = omap_dispc_register_isr(dispc_disable_isr,
6733 +                               &frame_done_completion,
6734 +                               DISPC_IRQ_FRAMEDONE);
6735 +
6736 +               if (r)
6737 +                       DSSERR("failed to register FRAMEDONE isr\n");
6738 +       }
6739 +
6740 +       _enable_lcd_out(enable);
6741 +
6742 +       if (!enable && is_on) {
6743 +               if (!wait_for_completion_timeout(&frame_done_completion,
6744 +                                       msecs_to_jiffies(100)))
6745 +                       DSSERR("timeout waiting for FRAME DONE\n");
6746 +
6747 +               r = omap_dispc_unregister_isr(dispc_disable_isr,
6748 +                               &frame_done_completion,
6749 +                               DISPC_IRQ_FRAMEDONE);
6750 +
6751 +               if (r)
6752 +                       DSSERR("failed to unregister FRAMEDONE isr\n");
6753 +       }
6754 +
6755 +       enable_clocks(0);
6756 +}
6757 +
6758 +static void _enable_digit_out(bool enable)
6759 +{
6760 +       REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
6761 +}
6762 +
6763 +void dispc_enable_digit_out(bool enable)
6764 +{
6765 +       struct completion frame_done_completion;
6766 +       int r;
6767 +
6768 +       enable_clocks(1);
6769 +
6770 +       if (REG_GET(DISPC_CONTROL, 1, 1) == enable) {
6771 +               enable_clocks(0);
6772 +               return;
6773 +       }
6774 +
6775 +       if (enable) {
6776 +               unsigned long flags;
6777 +               /* When we enable digit output, we'll get an extra digit
6778 +                * sync lost interrupt, that we need to ignore */
6779 +               spin_lock_irqsave(&dispc.irq_lock, flags);
6780 +               dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
6781 +               _omap_dispc_set_irqs();
6782 +               spin_unlock_irqrestore(&dispc.irq_lock, flags);
6783 +       }
6784 +
6785 +       /* When we disable digit output, we need to wait until fields are done.
6786 +        * Otherwise the DSS is still working, and turning off the clocks
6787 +        * prevents DSS from going to OFF mode. And when enabling, we need to
6788 +        * wait for the extra sync losts */
6789 +       init_completion(&frame_done_completion);
6790 +
6791 +       r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
6792 +                       DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
6793 +       if (r)
6794 +               DSSERR("failed to register EVSYNC isr\n");
6795 +
6796 +       _enable_digit_out(enable);
6797 +
6798 +       /* XXX I understand from TRM that we should only wait for the
6799 +        * current field to complete. But it seems we have to wait
6800 +        * for both fields */
6801 +       if (!wait_for_completion_timeout(&frame_done_completion,
6802 +                               msecs_to_jiffies(100)))
6803 +               DSSERR("timeout waiting for EVSYNC\n");
6804 +
6805 +       if (!wait_for_completion_timeout(&frame_done_completion,
6806 +                               msecs_to_jiffies(100)))
6807 +               DSSERR("timeout waiting for EVSYNC\n");
6808 +
6809 +       r = omap_dispc_unregister_isr(dispc_disable_isr,
6810 +                       &frame_done_completion,
6811 +                       DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
6812 +       if (r)
6813 +               DSSERR("failed to unregister EVSYNC isr\n");
6814 +
6815 +       if (enable) {
6816 +               unsigned long flags;
6817 +               spin_lock_irqsave(&dispc.irq_lock, flags);
6818 +               dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
6819 +               dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
6820 +               _omap_dispc_set_irqs();
6821 +               spin_unlock_irqrestore(&dispc.irq_lock, flags);
6822 +       }
6823 +
6824 +       enable_clocks(0);
6825 +}
6826 +
6827 +void dispc_lcd_enable_signal_polarity(bool act_high)
6828 +{
6829 +       enable_clocks(1);
6830 +       REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
6831 +       enable_clocks(0);
6832 +}
6833 +
6834 +void dispc_lcd_enable_signal(bool enable)
6835 +{
6836 +       enable_clocks(1);
6837 +       REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
6838 +       enable_clocks(0);
6839 +}
6840 +
6841 +void dispc_pck_free_enable(bool enable)
6842 +{
6843 +       enable_clocks(1);
6844 +       REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
6845 +       enable_clocks(0);
6846 +}
6847 +
6848 +void dispc_enable_fifohandcheck(bool enable)
6849 +{
6850 +       enable_clocks(1);
6851 +       REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
6852 +       enable_clocks(0);
6853 +}
6854 +
6855 +
6856 +void dispc_set_lcd_display_type(enum omap_lcd_display_type type)
6857 +{
6858 +       int mode;
6859 +
6860 +       switch (type) {
6861 +       case OMAP_DSS_LCD_DISPLAY_STN:
6862 +               mode = 0;
6863 +               break;
6864 +
6865 +       case OMAP_DSS_LCD_DISPLAY_TFT:
6866 +               mode = 1;
6867 +               break;
6868 +
6869 +       default:
6870 +               BUG();
6871 +               return;
6872 +       }
6873 +
6874 +       enable_clocks(1);
6875 +       REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
6876 +       enable_clocks(0);
6877 +}
6878 +
6879 +void dispc_set_loadmode(enum omap_dss_load_mode mode)
6880 +{
6881 +       enable_clocks(1);
6882 +       REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
6883 +       enable_clocks(0);
6884 +}
6885 +
6886 +
6887 +void dispc_set_default_color(enum omap_channel channel, u32 color)
6888 +{
6889 +       const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
6890 +                               DISPC_DEFAULT_COLOR1 };
6891 +
6892 +       enable_clocks(1);
6893 +       dispc_write_reg(def_reg[channel], color);
6894 +       enable_clocks(0);
6895 +}
6896 +
6897 +u32 dispc_get_default_color(enum omap_channel channel)
6898 +{
6899 +       const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
6900 +                               DISPC_DEFAULT_COLOR1 };
6901 +       u32 l;
6902 +
6903 +       BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT &&
6904 +              channel != OMAP_DSS_CHANNEL_LCD);
6905 +
6906 +       enable_clocks(1);
6907 +       l = dispc_read_reg(def_reg[channel]);
6908 +       enable_clocks(0);
6909 +
6910 +       return l;
6911 +}
6912 +
6913 +void dispc_set_trans_key(enum omap_channel ch,
6914 +               enum omap_dss_trans_key_type type,
6915 +               u32 trans_key)
6916 +{
6917 +       const struct dispc_reg tr_reg[] = {
6918 +               DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
6919 +
6920 +       enable_clocks(1);
6921 +       if (ch == OMAP_DSS_CHANNEL_LCD)
6922 +               REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
6923 +       else /* OMAP_DSS_CHANNEL_DIGIT */
6924 +               REG_FLD_MOD(DISPC_CONFIG, type, 13, 13);
6925 +
6926 +       dispc_write_reg(tr_reg[ch], trans_key);
6927 +       enable_clocks(0);
6928 +}
6929 +
6930 +void dispc_get_trans_key(enum omap_channel ch,
6931 +               enum omap_dss_trans_key_type *type,
6932 +               u32 *trans_key)
6933 +{
6934 +       const struct dispc_reg tr_reg[] = {
6935 +               DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
6936 +
6937 +       enable_clocks(1);
6938 +       if (type) {
6939 +               if (ch == OMAP_DSS_CHANNEL_LCD)
6940 +                       *type = REG_GET(DISPC_CONFIG, 11, 11);
6941 +               else if (ch == OMAP_DSS_CHANNEL_DIGIT)
6942 +                       *type = REG_GET(DISPC_CONFIG, 13, 13);
6943 +               else
6944 +                       BUG();
6945 +       }
6946 +
6947 +       if (trans_key)
6948 +               *trans_key = dispc_read_reg(tr_reg[ch]);
6949 +       enable_clocks(0);
6950 +}
6951 +
6952 +void dispc_enable_trans_key(enum omap_channel ch, bool enable)
6953 +{
6954 +       enable_clocks(1);
6955 +       if (ch == OMAP_DSS_CHANNEL_LCD)
6956 +               REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
6957 +       else /* OMAP_DSS_CHANNEL_DIGIT */
6958 +               REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
6959 +       enable_clocks(0);
6960 +}
6961 +void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
6962 +{
6963 +       enable_clocks(1);
6964 +       if (ch == OMAP_DSS_CHANNEL_LCD)
6965 +               REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
6966 +       else /* OMAP_DSS_CHANNEL_DIGIT */
6967 +               REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
6968 +       enable_clocks(0);
6969 +}
6970 +bool dispc_alpha_blending_enabled(enum omap_channel ch)
6971 +{
6972 +       bool enabled;
6973 +
6974 +       enable_clocks(1);
6975 +       if (ch == OMAP_DSS_CHANNEL_LCD)
6976 +               enabled = REG_GET(DISPC_CONFIG, 18, 18);
6977 +       else if (ch == OMAP_DSS_CHANNEL_DIGIT)
6978 +               enabled = REG_GET(DISPC_CONFIG, 18, 18);
6979 +       else
6980 +               BUG();
6981 +       enable_clocks(0);
6982 +
6983 +       return enabled;
6984 +
6985 +}
6986 +
6987 +
6988 +bool dispc_trans_key_enabled(enum omap_channel ch)
6989 +{
6990 +       bool enabled;
6991 +
6992 +       enable_clocks(1);
6993 +       if (ch == OMAP_DSS_CHANNEL_LCD)
6994 +               enabled = REG_GET(DISPC_CONFIG, 10, 10);
6995 +       else if (ch == OMAP_DSS_CHANNEL_DIGIT)
6996 +               enabled = REG_GET(DISPC_CONFIG, 12, 12);
6997 +       else
6998 +               BUG();
6999 +       enable_clocks(0);
7000 +
7001 +       return enabled;
7002 +}
7003 +
7004 +
7005 +void dispc_set_tft_data_lines(u8 data_lines)
7006 +{
7007 +       int code;
7008 +
7009 +       switch (data_lines) {
7010 +       case 12:
7011 +               code = 0;
7012 +               break;
7013 +       case 16:
7014 +               code = 1;
7015 +               break;
7016 +       case 18:
7017 +               code = 2;
7018 +               break;
7019 +       case 24:
7020 +               code = 3;
7021 +               break;
7022 +       default:
7023 +               BUG();
7024 +               return;
7025 +       }
7026 +
7027 +       enable_clocks(1);
7028 +       REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
7029 +       enable_clocks(0);
7030 +}
7031 +
7032 +void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode)
7033 +{
7034 +       u32 l;
7035 +       int stallmode;
7036 +       int gpout0 = 1;
7037 +       int gpout1;
7038 +
7039 +       switch (mode) {
7040 +       case OMAP_DSS_PARALLELMODE_BYPASS:
7041 +               stallmode = 0;
7042 +               gpout1 = 1;
7043 +               break;
7044 +
7045 +       case OMAP_DSS_PARALLELMODE_RFBI:
7046 +               stallmode = 1;
7047 +               gpout1 = 0;
7048 +               break;
7049 +
7050 +       case OMAP_DSS_PARALLELMODE_DSI:
7051 +               stallmode = 1;
7052 +               gpout1 = 1;
7053 +               break;
7054 +
7055 +       default:
7056 +               BUG();
7057 +               return;
7058 +       }
7059 +
7060 +       enable_clocks(1);
7061 +
7062 +       l = dispc_read_reg(DISPC_CONTROL);
7063 +
7064 +       l = FLD_MOD(l, stallmode, 11, 11);
7065 +       l = FLD_MOD(l, gpout0, 15, 15);
7066 +       l = FLD_MOD(l, gpout1, 16, 16);
7067 +
7068 +       dispc_write_reg(DISPC_CONTROL, l);
7069 +
7070 +       enable_clocks(0);
7071 +}
7072 +
7073 +static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
7074 +               int vsw, int vfp, int vbp)
7075 +{
7076 +       if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
7077 +               if (hsw < 1 || hsw > 64 ||
7078 +                               hfp < 1 || hfp > 256 ||
7079 +                               hbp < 1 || hbp > 256 ||
7080 +                               vsw < 1 || vsw > 64 ||
7081 +                               vfp < 0 || vfp > 255 ||
7082 +                               vbp < 0 || vbp > 255)
7083 +                       return false;
7084 +       } else {
7085 +               if (hsw < 1 || hsw > 256 ||
7086 +                               hfp < 1 || hfp > 4096 ||
7087 +                               hbp < 1 || hbp > 4096 ||
7088 +                               vsw < 1 || vsw > 256 ||
7089 +                               vfp < 0 || vfp > 4095 ||
7090 +                               vbp < 0 || vbp > 4095)
7091 +                       return false;
7092 +       }
7093 +
7094 +       return true;
7095 +}
7096 +
7097 +bool dispc_lcd_timings_ok(struct omap_video_timings *timings)
7098 +{
7099 +       return _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
7100 +                       timings->hbp, timings->vsw,
7101 +                       timings->vfp, timings->vbp);
7102 +}
7103 +
7104 +static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp,
7105 +                                  int vsw, int vfp, int vbp)
7106 +{
7107 +       u32 timing_h, timing_v;
7108 +
7109 +       if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
7110 +               timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) |
7111 +                       FLD_VAL(hbp-1, 27, 20);
7112 +
7113 +               timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) |
7114 +                       FLD_VAL(vbp, 27, 20);
7115 +       } else {
7116 +               timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
7117 +                       FLD_VAL(hbp-1, 31, 20);
7118 +
7119 +               timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
7120 +                       FLD_VAL(vbp, 31, 20);
7121 +       }
7122 +
7123 +       enable_clocks(1);
7124 +       dispc_write_reg(DISPC_TIMING_H, timing_h);
7125 +       dispc_write_reg(DISPC_TIMING_V, timing_v);
7126 +       enable_clocks(0);
7127 +}
7128 +
7129 +/* change name to mode? */
7130 +void dispc_set_lcd_timings(struct omap_video_timings *timings)
7131 +{
7132 +       unsigned xtot, ytot;
7133 +       unsigned long ht, vt;
7134 +
7135 +       if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp,
7136 +                               timings->hbp, timings->vsw,
7137 +                               timings->vfp, timings->vbp))
7138 +               BUG();
7139 +
7140 +       _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp,
7141 +                       timings->vsw, timings->vfp, timings->vbp);
7142 +
7143 +       dispc_set_lcd_size(timings->x_res, timings->y_res);
7144 +
7145 +       xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
7146 +       ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
7147 +
7148 +       ht = (timings->pixel_clock * 1000) / xtot;
7149 +       vt = (timings->pixel_clock * 1000) / xtot / ytot;
7150 +
7151 +       DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res);
7152 +       DSSDBG("pck %u\n", timings->pixel_clock);
7153 +       DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
7154 +                       timings->hsw, timings->hfp, timings->hbp,
7155 +                       timings->vsw, timings->vfp, timings->vbp);
7156 +
7157 +       DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
7158 +}
7159 +
7160 +void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div)
7161 +{
7162 +       BUG_ON(lck_div < 1);
7163 +       BUG_ON(pck_div < 2);
7164 +
7165 +       enable_clocks(1);
7166 +       dispc_write_reg(DISPC_DIVISOR,
7167 +                       FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
7168 +       enable_clocks(0);
7169 +}
7170 +
7171 +static void dispc_get_lcd_divisor(int *lck_div, int *pck_div)
7172 +{
7173 +       u32 l;
7174 +       l = dispc_read_reg(DISPC_DIVISOR);
7175 +       *lck_div = FLD_GET(l, 23, 16);
7176 +       *pck_div = FLD_GET(l, 7, 0);
7177 +}
7178 +
7179 +unsigned long dispc_fclk_rate(void)
7180 +{
7181 +       unsigned long r = 0;
7182 +
7183 +       if (dss_get_dispc_clk_source() == 0)
7184 +               r = dss_clk_get_rate(DSS_CLK_FCK1);
7185 +       else
7186 +#ifdef CONFIG_OMAP2_DSS_DSI
7187 +               r = dsi_get_dsi1_pll_rate();
7188 +#else
7189 +       BUG();
7190 +#endif
7191 +       return r;
7192 +}
7193 +
7194 +unsigned long dispc_lclk_rate(void)
7195 +{
7196 +       int lcd;
7197 +       unsigned long r;
7198 +       u32 l;
7199 +
7200 +       l = dispc_read_reg(DISPC_DIVISOR);
7201 +
7202 +       lcd = FLD_GET(l, 23, 16);
7203 +
7204 +       r = dispc_fclk_rate();
7205 +
7206 +       return r / lcd;
7207 +}
7208 +
7209 +unsigned long dispc_pclk_rate(void)
7210 +{
7211 +       int lcd, pcd;
7212 +       unsigned long r;
7213 +       u32 l;
7214 +
7215 +       l = dispc_read_reg(DISPC_DIVISOR);
7216 +
7217 +       lcd = FLD_GET(l, 23, 16);
7218 +       pcd = FLD_GET(l, 7, 0);
7219 +
7220 +       r = dispc_fclk_rate();
7221 +
7222 +       return r / lcd / pcd;
7223 +}
7224 +
7225 +void dispc_dump_clocks(struct seq_file *s)
7226 +{
7227 +       int lcd, pcd;
7228 +
7229 +       enable_clocks(1);
7230 +
7231 +       dispc_get_lcd_divisor(&lcd, &pcd);
7232 +
7233 +       seq_printf(s, "- dispc -\n");
7234 +
7235 +       seq_printf(s, "dispc fclk source = %s\n",
7236 +                       dss_get_dispc_clk_source() == 0 ?
7237 +                       "dss1_alwon_fclk" : "dsi1_pll_fclk");
7238 +
7239 +       seq_printf(s, "pixel clk = %lu / %d / %d = %lu\n",
7240 +                       dispc_fclk_rate(),
7241 +                       lcd, pcd,
7242 +                       dispc_pclk_rate());
7243 +
7244 +       enable_clocks(0);
7245 +}
7246 +
7247 +void dispc_dump_regs(struct seq_file *s)
7248 +{
7249 +#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r))
7250 +
7251 +       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
7252 +
7253 +       DUMPREG(DISPC_REVISION);
7254 +       DUMPREG(DISPC_SYSCONFIG);
7255 +       DUMPREG(DISPC_SYSSTATUS);
7256 +       DUMPREG(DISPC_IRQSTATUS);
7257 +       DUMPREG(DISPC_IRQENABLE);
7258 +       DUMPREG(DISPC_CONTROL);
7259 +       DUMPREG(DISPC_CONFIG);
7260 +       DUMPREG(DISPC_CAPABLE);
7261 +       DUMPREG(DISPC_DEFAULT_COLOR0);
7262 +       DUMPREG(DISPC_DEFAULT_COLOR1);
7263 +       DUMPREG(DISPC_TRANS_COLOR0);
7264 +       DUMPREG(DISPC_TRANS_COLOR1);
7265 +       DUMPREG(DISPC_LINE_STATUS);
7266 +       DUMPREG(DISPC_LINE_NUMBER);
7267 +       DUMPREG(DISPC_TIMING_H);
7268 +       DUMPREG(DISPC_TIMING_V);
7269 +       DUMPREG(DISPC_POL_FREQ);
7270 +       DUMPREG(DISPC_DIVISOR);
7271 +       DUMPREG(DISPC_GLOBAL_ALPHA);
7272 +       DUMPREG(DISPC_SIZE_DIG);
7273 +       DUMPREG(DISPC_SIZE_LCD);
7274 +
7275 +       DUMPREG(DISPC_GFX_BA0);
7276 +       DUMPREG(DISPC_GFX_BA1);
7277 +       DUMPREG(DISPC_GFX_POSITION);
7278 +       DUMPREG(DISPC_GFX_SIZE);
7279 +       DUMPREG(DISPC_GFX_ATTRIBUTES);
7280 +       DUMPREG(DISPC_GFX_FIFO_THRESHOLD);
7281 +       DUMPREG(DISPC_GFX_FIFO_SIZE_STATUS);
7282 +       DUMPREG(DISPC_GFX_ROW_INC);
7283 +       DUMPREG(DISPC_GFX_PIXEL_INC);
7284 +       DUMPREG(DISPC_GFX_WINDOW_SKIP);
7285 +       DUMPREG(DISPC_GFX_TABLE_BA);
7286 +
7287 +       DUMPREG(DISPC_DATA_CYCLE1);
7288 +       DUMPREG(DISPC_DATA_CYCLE2);
7289 +       DUMPREG(DISPC_DATA_CYCLE3);
7290 +
7291 +       DUMPREG(DISPC_CPR_COEF_R);
7292 +       DUMPREG(DISPC_CPR_COEF_G);
7293 +       DUMPREG(DISPC_CPR_COEF_B);
7294 +
7295 +       DUMPREG(DISPC_GFX_PRELOAD);
7296 +
7297 +       DUMPREG(DISPC_VID_BA0(0));
7298 +       DUMPREG(DISPC_VID_BA1(0));
7299 +       DUMPREG(DISPC_VID_POSITION(0));
7300 +       DUMPREG(DISPC_VID_SIZE(0));
7301 +       DUMPREG(DISPC_VID_ATTRIBUTES(0));
7302 +       DUMPREG(DISPC_VID_FIFO_THRESHOLD(0));
7303 +       DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(0));
7304 +       DUMPREG(DISPC_VID_ROW_INC(0));
7305 +       DUMPREG(DISPC_VID_PIXEL_INC(0));
7306 +       DUMPREG(DISPC_VID_FIR(0));
7307 +       DUMPREG(DISPC_VID_PICTURE_SIZE(0));
7308 +       DUMPREG(DISPC_VID_ACCU0(0));
7309 +       DUMPREG(DISPC_VID_ACCU1(0));
7310 +
7311 +       DUMPREG(DISPC_VID_BA0(1));
7312 +       DUMPREG(DISPC_VID_BA1(1));
7313 +       DUMPREG(DISPC_VID_POSITION(1));
7314 +       DUMPREG(DISPC_VID_SIZE(1));
7315 +       DUMPREG(DISPC_VID_ATTRIBUTES(1));
7316 +       DUMPREG(DISPC_VID_FIFO_THRESHOLD(1));
7317 +       DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1));
7318 +       DUMPREG(DISPC_VID_ROW_INC(1));
7319 +       DUMPREG(DISPC_VID_PIXEL_INC(1));
7320 +       DUMPREG(DISPC_VID_FIR(1));
7321 +       DUMPREG(DISPC_VID_PICTURE_SIZE(1));
7322 +       DUMPREG(DISPC_VID_ACCU0(1));
7323 +       DUMPREG(DISPC_VID_ACCU1(1));
7324 +
7325 +       DUMPREG(DISPC_VID_FIR_COEF_H(0, 0));
7326 +       DUMPREG(DISPC_VID_FIR_COEF_H(0, 1));
7327 +       DUMPREG(DISPC_VID_FIR_COEF_H(0, 2));
7328 +       DUMPREG(DISPC_VID_FIR_COEF_H(0, 3));
7329 +       DUMPREG(DISPC_VID_FIR_COEF_H(0, 4));
7330 +       DUMPREG(DISPC_VID_FIR_COEF_H(0, 5));
7331 +       DUMPREG(DISPC_VID_FIR_COEF_H(0, 6));
7332 +       DUMPREG(DISPC_VID_FIR_COEF_H(0, 7));
7333 +       DUMPREG(DISPC_VID_FIR_COEF_HV(0, 0));
7334 +       DUMPREG(DISPC_VID_FIR_COEF_HV(0, 1));
7335 +       DUMPREG(DISPC_VID_FIR_COEF_HV(0, 2));
7336 +       DUMPREG(DISPC_VID_FIR_COEF_HV(0, 3));
7337 +       DUMPREG(DISPC_VID_FIR_COEF_HV(0, 4));
7338 +       DUMPREG(DISPC_VID_FIR_COEF_HV(0, 5));
7339 +       DUMPREG(DISPC_VID_FIR_COEF_HV(0, 6));
7340 +       DUMPREG(DISPC_VID_FIR_COEF_HV(0, 7));
7341 +       DUMPREG(DISPC_VID_CONV_COEF(0, 0));
7342 +       DUMPREG(DISPC_VID_CONV_COEF(0, 1));
7343 +       DUMPREG(DISPC_VID_CONV_COEF(0, 2));
7344 +       DUMPREG(DISPC_VID_CONV_COEF(0, 3));
7345 +       DUMPREG(DISPC_VID_CONV_COEF(0, 4));
7346 +       DUMPREG(DISPC_VID_FIR_COEF_V(0, 0));
7347 +       DUMPREG(DISPC_VID_FIR_COEF_V(0, 1));
7348 +       DUMPREG(DISPC_VID_FIR_COEF_V(0, 2));
7349 +       DUMPREG(DISPC_VID_FIR_COEF_V(0, 3));
7350 +       DUMPREG(DISPC_VID_FIR_COEF_V(0, 4));
7351 +       DUMPREG(DISPC_VID_FIR_COEF_V(0, 5));
7352 +       DUMPREG(DISPC_VID_FIR_COEF_V(0, 6));
7353 +       DUMPREG(DISPC_VID_FIR_COEF_V(0, 7));
7354 +
7355 +       DUMPREG(DISPC_VID_FIR_COEF_H(1, 0));
7356 +       DUMPREG(DISPC_VID_FIR_COEF_H(1, 1));
7357 +       DUMPREG(DISPC_VID_FIR_COEF_H(1, 2));
7358 +       DUMPREG(DISPC_VID_FIR_COEF_H(1, 3));
7359 +       DUMPREG(DISPC_VID_FIR_COEF_H(1, 4));
7360 +       DUMPREG(DISPC_VID_FIR_COEF_H(1, 5));
7361 +       DUMPREG(DISPC_VID_FIR_COEF_H(1, 6));
7362 +       DUMPREG(DISPC_VID_FIR_COEF_H(1, 7));
7363 +       DUMPREG(DISPC_VID_FIR_COEF_HV(1, 0));
7364 +       DUMPREG(DISPC_VID_FIR_COEF_HV(1, 1));
7365 +       DUMPREG(DISPC_VID_FIR_COEF_HV(1, 2));
7366 +       DUMPREG(DISPC_VID_FIR_COEF_HV(1, 3));
7367 +       DUMPREG(DISPC_VID_FIR_COEF_HV(1, 4));
7368 +       DUMPREG(DISPC_VID_FIR_COEF_HV(1, 5));
7369 +       DUMPREG(DISPC_VID_FIR_COEF_HV(1, 6));
7370 +       DUMPREG(DISPC_VID_FIR_COEF_HV(1, 7));
7371 +       DUMPREG(DISPC_VID_CONV_COEF(1, 0));
7372 +       DUMPREG(DISPC_VID_CONV_COEF(1, 1));
7373 +       DUMPREG(DISPC_VID_CONV_COEF(1, 2));
7374 +       DUMPREG(DISPC_VID_CONV_COEF(1, 3));
7375 +       DUMPREG(DISPC_VID_CONV_COEF(1, 4));
7376 +       DUMPREG(DISPC_VID_FIR_COEF_V(1, 0));
7377 +       DUMPREG(DISPC_VID_FIR_COEF_V(1, 1));
7378 +       DUMPREG(DISPC_VID_FIR_COEF_V(1, 2));
7379 +       DUMPREG(DISPC_VID_FIR_COEF_V(1, 3));
7380 +       DUMPREG(DISPC_VID_FIR_COEF_V(1, 4));
7381 +       DUMPREG(DISPC_VID_FIR_COEF_V(1, 5));
7382 +       DUMPREG(DISPC_VID_FIR_COEF_V(1, 6));
7383 +       DUMPREG(DISPC_VID_FIR_COEF_V(1, 7));
7384 +
7385 +       DUMPREG(DISPC_VID_PRELOAD(0));
7386 +       DUMPREG(DISPC_VID_PRELOAD(1));
7387 +
7388 +       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
7389 +#undef DUMPREG
7390 +}
7391 +
7392 +static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc,
7393 +                               bool ihs, bool ivs, u8 acbi, u8 acb)
7394 +{
7395 +       u32 l = 0;
7396 +
7397 +       DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n",
7398 +                       onoff, rf, ieo, ipc, ihs, ivs, acbi, acb);
7399 +
7400 +       l |= FLD_VAL(onoff, 17, 17);
7401 +       l |= FLD_VAL(rf, 16, 16);
7402 +       l |= FLD_VAL(ieo, 15, 15);
7403 +       l |= FLD_VAL(ipc, 14, 14);
7404 +       l |= FLD_VAL(ihs, 13, 13);
7405 +       l |= FLD_VAL(ivs, 12, 12);
7406 +       l |= FLD_VAL(acbi, 11, 8);
7407 +       l |= FLD_VAL(acb, 7, 0);
7408 +
7409 +       enable_clocks(1);
7410 +       dispc_write_reg(DISPC_POL_FREQ, l);
7411 +       enable_clocks(0);
7412 +}
7413 +
7414 +void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb)
7415 +{
7416 +       _dispc_set_pol_freq((config & OMAP_DSS_LCD_ONOFF) != 0,
7417 +                       (config & OMAP_DSS_LCD_RF) != 0,
7418 +                       (config & OMAP_DSS_LCD_IEO) != 0,
7419 +                       (config & OMAP_DSS_LCD_IPC) != 0,
7420 +                       (config & OMAP_DSS_LCD_IHS) != 0,
7421 +                       (config & OMAP_DSS_LCD_IVS) != 0,
7422 +                       acbi, acb);
7423 +}
7424 +
7425 +void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
7426 +               u16 *lck_div, u16 *pck_div)
7427 +{
7428 +       u16 pcd_min = is_tft ? 2 : 3;
7429 +       unsigned long best_pck;
7430 +       u16 best_ld, cur_ld;
7431 +       u16 best_pd, cur_pd;
7432 +
7433 +       best_pck = 0;
7434 +       best_ld = 0;
7435 +       best_pd = 0;
7436 +
7437 +       for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
7438 +               unsigned long lck = fck / cur_ld;
7439 +
7440 +               for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) {
7441 +                       unsigned long pck = lck / cur_pd;
7442 +                       long old_delta = abs(best_pck - req_pck);
7443 +                       long new_delta = abs(pck - req_pck);
7444 +
7445 +                       if (best_pck == 0 || new_delta < old_delta) {
7446 +                               best_pck = pck;
7447 +                               best_ld = cur_ld;
7448 +                               best_pd = cur_pd;
7449 +
7450 +                               if (pck == req_pck)
7451 +                                       goto found;
7452 +                       }
7453 +
7454 +                       if (pck < req_pck)
7455 +                               break;
7456 +               }
7457 +
7458 +               if (lck / pcd_min < req_pck)
7459 +                       break;
7460 +       }
7461 +
7462 +found:
7463 +       *lck_div = best_ld;
7464 +       *pck_div = best_pd;
7465 +}
7466 +
7467 +int dispc_calc_clock_div(bool is_tft, unsigned long req_pck,
7468 +               struct dispc_clock_info *cinfo)
7469 +{
7470 +       unsigned long prate;
7471 +       struct dispc_clock_info cur, best;
7472 +       int match = 0;
7473 +       int min_fck_per_pck;
7474 +       unsigned long fck_rate = dss_clk_get_rate(DSS_CLK_FCK1);
7475 +
7476 +       if (cpu_is_omap34xx())
7477 +               prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
7478 +       else
7479 +               prate = 0;
7480 +
7481 +       if (req_pck == dispc.cache_req_pck &&
7482 +                       ((cpu_is_omap34xx() && prate == dispc.cache_prate) ||
7483 +                        dispc.cache_cinfo.fck == fck_rate)) {
7484 +               DSSDBG("dispc clock info found from cache.\n");
7485 +               *cinfo = dispc.cache_cinfo;
7486 +               return 0;
7487 +       }
7488 +
7489 +       min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
7490 +
7491 +       if (min_fck_per_pck &&
7492 +               req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
7493 +               DSSERR("Requested pixel clock not possible with the current "
7494 +                               "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
7495 +                               "the constraint off.\n");
7496 +               min_fck_per_pck = 0;
7497 +       }
7498 +
7499 +retry:
7500 +       memset(&cur, 0, sizeof(cur));
7501 +       memset(&best, 0, sizeof(best));
7502 +
7503 +       if (cpu_is_omap24xx()) {
7504 +               /* XXX can we change the clock on omap2? */
7505 +               cur.fck = dss_clk_get_rate(DSS_CLK_FCK1);
7506 +               cur.fck_div = 1;
7507 +
7508 +               match = 1;
7509 +
7510 +               find_lck_pck_divs(is_tft, req_pck, cur.fck,
7511 +                               &cur.lck_div, &cur.pck_div);
7512 +
7513 +               cur.lck = cur.fck / cur.lck_div;
7514 +               cur.pck = cur.lck / cur.pck_div;
7515 +
7516 +               best = cur;
7517 +
7518 +               goto found;
7519 +       } else if (cpu_is_omap34xx()) {
7520 +               for (cur.fck_div = 16; cur.fck_div > 0; --cur.fck_div) {
7521 +                       cur.fck = prate / cur.fck_div * 2;
7522 +
7523 +                       if (cur.fck > DISPC_MAX_FCK)
7524 +                               continue;
7525 +
7526 +                       if (min_fck_per_pck &&
7527 +                                       cur.fck < req_pck * min_fck_per_pck)
7528 +                               continue;
7529 +
7530 +                       match = 1;
7531 +
7532 +                       find_lck_pck_divs(is_tft, req_pck, cur.fck,
7533 +                                       &cur.lck_div, &cur.pck_div);
7534 +
7535 +                       cur.lck = cur.fck / cur.lck_div;
7536 +                       cur.pck = cur.lck / cur.pck_div;
7537 +
7538 +                       if (abs(cur.pck - req_pck) < abs(best.pck - req_pck)) {
7539 +                               best = cur;
7540 +
7541 +                               if (cur.pck == req_pck)
7542 +                                       goto found;
7543 +                       }
7544 +               }
7545 +       } else {
7546 +               BUG();
7547 +       }
7548 +
7549 +found:
7550 +       if (!match) {
7551 +               if (min_fck_per_pck) {
7552 +                       DSSERR("Could not find suitable clock settings.\n"
7553 +                                       "Turning FCK/PCK constraint off and"
7554 +                                       "trying again.\n");
7555 +                       min_fck_per_pck = 0;
7556 +                       goto retry;
7557 +               }
7558 +
7559 +               DSSERR("Could not find suitable clock settings.\n");
7560 +
7561 +               return -EINVAL;
7562 +       }
7563 +
7564 +       if (cinfo)
7565 +               *cinfo = best;
7566 +
7567 +       dispc.cache_req_pck = req_pck;
7568 +       dispc.cache_prate = prate;
7569 +       dispc.cache_cinfo = best;
7570 +
7571 +       return 0;
7572 +}
7573 +
7574 +int dispc_set_clock_div(struct dispc_clock_info *cinfo)
7575 +{
7576 +       unsigned long prate;
7577 +       int r;
7578 +
7579 +       if (cpu_is_omap34xx()) {
7580 +               prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
7581 +               DSSDBG("dpll4_m4 = %ld\n", prate);
7582 +       }
7583 +
7584 +       DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
7585 +       DSSDBG("lck = %ld (%d)\n", cinfo->lck, cinfo->lck_div);
7586 +       DSSDBG("pck = %ld (%d)\n", cinfo->pck, cinfo->pck_div);
7587 +
7588 +       if (cpu_is_omap34xx()) {
7589 +               r = clk_set_rate(dispc.dpll4_m4_ck, prate / cinfo->fck_div);
7590 +               if (r)
7591 +                       return r;
7592 +       }
7593 +
7594 +       dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div);
7595 +
7596 +       return 0;
7597 +}
7598 +
7599 +int dispc_get_clock_div(struct dispc_clock_info *cinfo)
7600 +{
7601 +       cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1);
7602 +
7603 +       if (cpu_is_omap34xx()) {
7604 +               unsigned long prate;
7605 +               prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
7606 +               cinfo->fck_div = prate / (cinfo->fck / 2);
7607 +       } else {
7608 +               cinfo->fck_div = 0;
7609 +       }
7610 +
7611 +       cinfo->lck_div = REG_GET(DISPC_DIVISOR, 23, 16);
7612 +       cinfo->pck_div = REG_GET(DISPC_DIVISOR, 7, 0);
7613 +
7614 +       cinfo->lck = cinfo->fck / cinfo->lck_div;
7615 +       cinfo->pck = cinfo->lck / cinfo->pck_div;
7616 +
7617 +       return 0;
7618 +}
7619 +
7620 +/* dispc.irq_lock has to be locked by the caller */
7621 +static void _omap_dispc_set_irqs(void)
7622 +{
7623 +       u32 mask;
7624 +       u32 old_mask;
7625 +       int i;
7626 +       struct omap_dispc_isr_data *isr_data;
7627 +
7628 +       mask = dispc.irq_error_mask;
7629 +
7630 +       for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
7631 +               isr_data = &dispc.registered_isr[i];
7632 +
7633 +               if (isr_data->isr == NULL)
7634 +                       continue;
7635 +
7636 +               mask |= isr_data->mask;
7637 +       }
7638 +
7639 +       enable_clocks(1);
7640 +
7641 +       old_mask = dispc_read_reg(DISPC_IRQENABLE);
7642 +       /* clear the irqstatus for newly enabled irqs */
7643 +       dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
7644 +
7645 +       dispc_write_reg(DISPC_IRQENABLE, mask);
7646 +
7647 +       enable_clocks(0);
7648 +}
7649 +
7650 +int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
7651 +{
7652 +       int i;
7653 +       int ret;
7654 +       unsigned long flags;
7655 +       struct omap_dispc_isr_data *isr_data;
7656 +
7657 +       if (isr == NULL)
7658 +               return -EINVAL;
7659 +
7660 +       spin_lock_irqsave(&dispc.irq_lock, flags);
7661 +
7662 +       /* check for duplicate entry */
7663 +       for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
7664 +               isr_data = &dispc.registered_isr[i];
7665 +               if (isr_data->isr == isr && isr_data->arg == arg &&
7666 +                               isr_data->mask == mask) {
7667 +                       ret = -EINVAL;
7668 +                       goto err;
7669 +               }
7670 +       }
7671 +
7672 +       isr_data = NULL;
7673 +       ret = -EBUSY;
7674 +
7675 +       for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
7676 +               isr_data = &dispc.registered_isr[i];
7677 +
7678 +               if (isr_data->isr != NULL)
7679 +                       continue;
7680 +
7681 +               isr_data->isr = isr;
7682 +               isr_data->arg = arg;
7683 +               isr_data->mask = mask;
7684 +               ret = 0;
7685 +
7686 +               break;
7687 +       }
7688 +
7689 +       _omap_dispc_set_irqs();
7690 +
7691 +       spin_unlock_irqrestore(&dispc.irq_lock, flags);
7692 +
7693 +       return 0;
7694 +err:
7695 +       spin_unlock_irqrestore(&dispc.irq_lock, flags);
7696 +
7697 +       return ret;
7698 +}
7699 +EXPORT_SYMBOL(omap_dispc_register_isr);
7700 +
7701 +int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
7702 +{
7703 +       int i;
7704 +       unsigned long flags;
7705 +       int ret = -EINVAL;
7706 +       struct omap_dispc_isr_data *isr_data;
7707 +
7708 +       spin_lock_irqsave(&dispc.irq_lock, flags);
7709 +
7710 +       for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
7711 +               isr_data = &dispc.registered_isr[i];
7712 +               if (isr_data->isr != isr || isr_data->arg != arg ||
7713 +                               isr_data->mask != mask)
7714 +                       continue;
7715 +
7716 +               /* found the correct isr */
7717 +
7718 +               isr_data->isr = NULL;
7719 +               isr_data->arg = NULL;
7720 +               isr_data->mask = 0;
7721 +
7722 +               ret = 0;
7723 +               break;
7724 +       }
7725 +
7726 +       if (ret == 0)
7727 +               _omap_dispc_set_irqs();
7728 +
7729 +       spin_unlock_irqrestore(&dispc.irq_lock, flags);
7730 +
7731 +       return ret;
7732 +}
7733 +EXPORT_SYMBOL(omap_dispc_unregister_isr);
7734 +
7735 +#ifdef DEBUG
7736 +static void print_irq_status(u32 status)
7737 +{
7738 +       if ((status & dispc.irq_error_mask) == 0)
7739 +               return;
7740 +
7741 +       printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status);
7742 +
7743 +#define PIS(x) \
7744 +       if (status & DISPC_IRQ_##x) \
7745 +               printk(#x " ");
7746 +       PIS(GFX_FIFO_UNDERFLOW);
7747 +       PIS(OCP_ERR);
7748 +       PIS(VID1_FIFO_UNDERFLOW);
7749 +       PIS(VID2_FIFO_UNDERFLOW);
7750 +       PIS(SYNC_LOST);
7751 +       PIS(SYNC_LOST_DIGIT);
7752 +#undef PIS
7753 +
7754 +       printk("\n");
7755 +}
7756 +#endif
7757 +
7758 +/* Called from dss.c. Note that we don't touch clocks here,
7759 + * but we presume they are on because we got an IRQ. However,
7760 + * an irq handler may turn the clocks off, so we may not have
7761 + * clock later in the function. */
7762 +void dispc_irq_handler(void)
7763 +{
7764 +       int i;
7765 +       u32 irqstatus;
7766 +       u32 handledirqs = 0;
7767 +       u32 unhandled_errors;
7768 +       struct omap_dispc_isr_data *isr_data;
7769 +       struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
7770 +
7771 +       spin_lock(&dispc.irq_lock);
7772 +
7773 +       irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
7774 +
7775 +#ifdef DEBUG
7776 +       if (dss_debug)
7777 +               print_irq_status(irqstatus);
7778 +#endif
7779 +       /* Ack the interrupt. Do it here before clocks are possibly turned
7780 +        * off */
7781 +       dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
7782 +
7783 +       /* make a copy and unlock, so that isrs can unregister
7784 +        * themselves */
7785 +       memcpy(registered_isr, dispc.registered_isr,
7786 +                       sizeof(registered_isr));
7787 +
7788 +       spin_unlock(&dispc.irq_lock);
7789 +
7790 +       for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
7791 +               isr_data = &registered_isr[i];
7792 +
7793 +               if (!isr_data->isr)
7794 +                       continue;
7795 +
7796 +               if (isr_data->mask & irqstatus) {
7797 +                       isr_data->isr(isr_data->arg, irqstatus);
7798 +                       handledirqs |= isr_data->mask;
7799 +               }
7800 +       }
7801 +
7802 +       spin_lock(&dispc.irq_lock);
7803 +
7804 +       unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
7805 +
7806 +       if (unhandled_errors) {
7807 +               dispc.error_irqs |= unhandled_errors;
7808 +
7809 +               dispc.irq_error_mask &= ~unhandled_errors;
7810 +               _omap_dispc_set_irqs();
7811 +
7812 +               schedule_work(&dispc.error_work);
7813 +       }
7814 +
7815 +       spin_unlock(&dispc.irq_lock);
7816 +}
7817 +
7818 +static void dispc_error_worker(struct work_struct *work)
7819 +{
7820 +       int i;
7821 +       u32 errors;
7822 +       unsigned long flags;
7823 +
7824 +       spin_lock_irqsave(&dispc.irq_lock, flags);
7825 +       errors = dispc.error_irqs;
7826 +       dispc.error_irqs = 0;
7827 +       spin_unlock_irqrestore(&dispc.irq_lock, flags);
7828 +
7829 +       if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) {
7830 +               DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n");
7831 +               for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
7832 +                       struct omap_overlay *ovl;
7833 +                       ovl = omap_dss_get_overlay(i);
7834 +
7835 +                       if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
7836 +                               continue;
7837 +
7838 +                       if (ovl->id == 0) {
7839 +                               dispc_enable_plane(ovl->id, 0);
7840 +                               dispc_go(ovl->manager->id);
7841 +                               mdelay(50);
7842 +                               break;
7843 +                       }
7844 +               }
7845 +       }
7846 +
7847 +       if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) {
7848 +               DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n");
7849 +               for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
7850 +                       struct omap_overlay *ovl;
7851 +                       ovl = omap_dss_get_overlay(i);
7852 +
7853 +                       if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
7854 +                               continue;
7855 +
7856 +                       if (ovl->id == 1) {
7857 +                               dispc_enable_plane(ovl->id, 0);
7858 +                               dispc_go(ovl->manager->id);
7859 +                               mdelay(50);
7860 +                               break;
7861 +                       }
7862 +               }
7863 +       }
7864 +
7865 +       if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) {
7866 +               DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n");
7867 +               for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
7868 +                       struct omap_overlay *ovl;
7869 +                       ovl = omap_dss_get_overlay(i);
7870 +
7871 +                       if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
7872 +                               continue;
7873 +
7874 +                       if (ovl->id == 2) {
7875 +                               dispc_enable_plane(ovl->id, 0);
7876 +                               dispc_go(ovl->manager->id);
7877 +                               mdelay(50);
7878 +                               break;
7879 +                       }
7880 +               }
7881 +       }
7882 +
7883 +       if (errors & DISPC_IRQ_SYNC_LOST) {
7884 +               struct omap_overlay_manager *manager = NULL;
7885 +               bool enable = false;
7886 +
7887 +               DSSERR("SYNC_LOST, disabling LCD\n");
7888 +
7889 +               for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
7890 +                       struct omap_overlay_manager *mgr;
7891 +                       mgr = omap_dss_get_overlay_manager(i);
7892 +
7893 +                       if (mgr->id == OMAP_DSS_CHANNEL_LCD) {
7894 +                               manager = mgr;
7895 +                               enable = mgr->device->state ==
7896 +                                               OMAP_DSS_DISPLAY_ACTIVE;
7897 +                               mgr->device->disable(mgr->device);
7898 +                               break;
7899 +                       }
7900 +               }
7901 +
7902 +               if (manager) {
7903 +                       for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
7904 +                               struct omap_overlay *ovl;
7905 +                               ovl = omap_dss_get_overlay(i);
7906 +
7907 +                               if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
7908 +                                       continue;
7909 +
7910 +                               if (ovl->id != 0 && ovl->manager == manager)
7911 +                                       dispc_enable_plane(ovl->id, 0);
7912 +                       }
7913 +
7914 +                       dispc_go(manager->id);
7915 +                       mdelay(50);
7916 +                       if (enable)
7917 +                               manager->device->enable(manager->device);
7918 +               }
7919 +       }
7920 +
7921 +       if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) {
7922 +               struct omap_overlay_manager *manager = NULL;
7923 +               bool enable = false;
7924 +
7925 +               DSSERR("SYNC_LOST_DIGIT, disabling TV\n");
7926 +
7927 +               for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
7928 +                       struct omap_overlay_manager *mgr;
7929 +                       mgr = omap_dss_get_overlay_manager(i);
7930 +
7931 +                       if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) {
7932 +                               manager = mgr;
7933 +                               enable = mgr->device->state ==
7934 +                                               OMAP_DSS_DISPLAY_ACTIVE;
7935 +                               mgr->device->disable(mgr->device);
7936 +                               break;
7937 +                       }
7938 +               }
7939 +
7940 +               if (manager) {
7941 +                       for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
7942 +                               struct omap_overlay *ovl;
7943 +                               ovl = omap_dss_get_overlay(i);
7944 +
7945 +                               if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
7946 +                                       continue;
7947 +
7948 +                               if (ovl->id != 0 && ovl->manager == manager)
7949 +                                       dispc_enable_plane(ovl->id, 0);
7950 +                       }
7951 +
7952 +                       dispc_go(manager->id);
7953 +                       mdelay(50);
7954 +                       if (enable)
7955 +                               manager->device->enable(manager->device);
7956 +               }
7957 +       }
7958 +
7959 +       if (errors & DISPC_IRQ_OCP_ERR) {
7960 +               DSSERR("OCP_ERR\n");
7961 +               for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
7962 +                       struct omap_overlay_manager *mgr;
7963 +                       mgr = omap_dss_get_overlay_manager(i);
7964 +
7965 +                       if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC)
7966 +                               mgr->device->disable(mgr->device);
7967 +               }
7968 +       }
7969 +
7970 +       spin_lock_irqsave(&dispc.irq_lock, flags);
7971 +       dispc.irq_error_mask |= errors;
7972 +       _omap_dispc_set_irqs();
7973 +       spin_unlock_irqrestore(&dispc.irq_lock, flags);
7974 +}
7975 +
7976 +int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
7977 +{
7978 +       void dispc_irq_wait_handler(void *data, u32 mask)
7979 +       {
7980 +               complete((struct completion *)data);
7981 +       }
7982 +
7983 +       int r;
7984 +       DECLARE_COMPLETION_ONSTACK(completion);
7985 +
7986 +       r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
7987 +                       irqmask);
7988 +
7989 +       if (r)
7990 +               return r;
7991 +
7992 +       timeout = wait_for_completion_timeout(&completion, timeout);
7993 +
7994 +       omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
7995 +
7996 +       if (timeout == 0)
7997 +               return -ETIMEDOUT;
7998 +
7999 +       if (timeout == -ERESTARTSYS)
8000 +               return -ERESTARTSYS;
8001 +
8002 +       return 0;
8003 +}
8004 +
8005 +int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
8006 +               unsigned long timeout)
8007 +{
8008 +       void dispc_irq_wait_handler(void *data, u32 mask)
8009 +       {
8010 +               complete((struct completion *)data);
8011 +       }
8012 +
8013 +       int r;
8014 +       DECLARE_COMPLETION_ONSTACK(completion);
8015 +
8016 +       r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
8017 +                       irqmask);
8018 +
8019 +       if (r)
8020 +               return r;
8021 +
8022 +       timeout = wait_for_completion_interruptible_timeout(&completion,
8023 +                       timeout);
8024 +
8025 +       omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
8026 +
8027 +       if (timeout == 0)
8028 +               return -ETIMEDOUT;
8029 +
8030 +       if (timeout == -ERESTARTSYS)
8031 +               return -ERESTARTSYS;
8032 +
8033 +       return 0;
8034 +}
8035 +
8036 +#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
8037 +void dispc_fake_vsync_irq(void)
8038 +{
8039 +       u32 irqstatus = DISPC_IRQ_VSYNC;
8040 +       int i;
8041 +
8042 +       for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
8043 +               struct omap_dispc_isr_data *isr_data;
8044 +               isr_data = &dispc.registered_isr[i];
8045 +
8046 +               if (!isr_data->isr)
8047 +                       continue;
8048 +
8049 +               if (isr_data->mask & irqstatus)
8050 +                       isr_data->isr(isr_data->arg, irqstatus);
8051 +       }
8052 +}
8053 +#endif
8054 +
8055 +static void _omap_dispc_initialize_irq(void)
8056 +{
8057 +       unsigned long flags;
8058 +
8059 +       spin_lock_irqsave(&dispc.irq_lock, flags);
8060 +
8061 +       memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
8062 +
8063 +       dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
8064 +
8065 +       /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
8066 +        * so clear it */
8067 +       dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
8068 +
8069 +       _omap_dispc_set_irqs();
8070 +
8071 +       spin_unlock_irqrestore(&dispc.irq_lock, flags);
8072 +}
8073 +
8074 +void dispc_enable_sidle(void)
8075 +{
8076 +       REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3);  /* SIDLEMODE: smart idle */
8077 +}
8078 +
8079 +void dispc_disable_sidle(void)
8080 +{
8081 +       REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3);  /* SIDLEMODE: no idle */
8082 +}
8083 +
8084 +static void _omap_dispc_initial_config(void)
8085 +{
8086 +       u32 l;
8087 +
8088 +       l = dispc_read_reg(DISPC_SYSCONFIG);
8089 +       l = FLD_MOD(l, 2, 13, 12);      /* MIDLEMODE: smart standby */
8090 +       l = FLD_MOD(l, 2, 4, 3);        /* SIDLEMODE: smart idle */
8091 +       l = FLD_MOD(l, 1, 2, 2);        /* ENWAKEUP */
8092 +       l = FLD_MOD(l, 1, 0, 0);        /* AUTOIDLE */
8093 +       dispc_write_reg(DISPC_SYSCONFIG, l);
8094 +
8095 +       /* FUNCGATED */
8096 +       REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
8097 +
8098 +       /* L3 firewall setting: enable access to OCM RAM */
8099 +       if (cpu_is_omap24xx())
8100 +               __raw_writel(0x402000b0, OMAP2_IO_ADDRESS(0x680050a0));
8101 +
8102 +       _dispc_setup_color_conv_coef();
8103 +
8104 +       dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
8105 +
8106 +       dispc_read_plane_fifo_sizes();
8107 +}
8108 +
8109 +int dispc_init(void)
8110 +{
8111 +       u32 rev;
8112 +
8113 +       spin_lock_init(&dispc.irq_lock);
8114 +
8115 +       INIT_WORK(&dispc.error_work, dispc_error_worker);
8116 +
8117 +       dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS);
8118 +       if (!dispc.base) {
8119 +               DSSERR("can't ioremap DISPC\n");
8120 +               return -ENOMEM;
8121 +       }
8122 +
8123 +       if (cpu_is_omap34xx()) {
8124 +               dispc.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
8125 +               if (IS_ERR(dispc.dpll4_m4_ck)) {
8126 +                       DSSERR("Failed to get dpll4_m4_ck\n");
8127 +                       return -ENODEV;
8128 +               }
8129 +       }
8130 +
8131 +       enable_clocks(1);
8132 +
8133 +       _omap_dispc_initial_config();
8134 +
8135 +       _omap_dispc_initialize_irq();
8136 +
8137 +       dispc_save_context();
8138 +
8139 +       rev = dispc_read_reg(DISPC_REVISION);
8140 +       printk(KERN_INFO "OMAP DISPC rev %d.%d\n",
8141 +              FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
8142 +
8143 +       enable_clocks(0);
8144 +
8145 +       return 0;
8146 +}
8147 +
8148 +void dispc_exit(void)
8149 +{
8150 +       if (cpu_is_omap34xx())
8151 +               clk_put(dispc.dpll4_m4_ck);
8152 +       iounmap(dispc.base);
8153 +}
8154 +
8155 +int dispc_enable_plane(enum omap_plane plane, bool enable)
8156 +{
8157 +       DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
8158 +
8159 +       enable_clocks(1);
8160 +       _dispc_enable_plane(plane, enable);
8161 +       enable_clocks(0);
8162 +
8163 +       return 0;
8164 +}
8165 +
8166 +int dispc_setup_plane(enum omap_plane plane,
8167 +                      u32 paddr, u16 screen_width,
8168 +                      u16 pos_x, u16 pos_y,
8169 +                      u16 width, u16 height,
8170 +                      u16 out_width, u16 out_height,
8171 +                      enum omap_color_mode color_mode,
8172 +                      bool ilace,
8173 +                      enum omap_dss_rotation_type rotation_type,
8174 +                      u8 rotation, bool mirror, u8 global_alpha)
8175 +{
8176 +       int r = 0;
8177 +
8178 +       DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
8179 +              "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n",
8180 +              plane, paddr, screen_width, pos_x, pos_y,
8181 +              width, height,
8182 +              out_width, out_height,
8183 +              ilace, color_mode,
8184 +              rotation, mirror);
8185 +
8186 +       enable_clocks(1);
8187 +
8188 +       r = _dispc_setup_plane(plane,
8189 +                          paddr, screen_width,
8190 +                          pos_x, pos_y,
8191 +                          width, height,
8192 +                          out_width, out_height,
8193 +                          color_mode, ilace,
8194 +                          rotation_type,
8195 +                          rotation, mirror,
8196 +                          global_alpha);
8197 +
8198 +       enable_clocks(0);
8199 +
8200 +       return r;
8201 +}
8202 diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
8203 new file mode 100644
8204 index 0000000..6b5d0cf
8205 --- /dev/null
8206 +++ b/drivers/video/omap2/dss/display.c
8207 @@ -0,0 +1,658 @@
8208 +/*
8209 + * linux/drivers/video/omap2/dss/display.c
8210 + *
8211 + * Copyright (C) 2009 Nokia Corporation
8212 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
8213 + *
8214 + * Some code and ideas taken from drivers/video/omap/ driver
8215 + * by Imre Deak.
8216 + *
8217 + * This program is free software; you can redistribute it and/or modify it
8218 + * under the terms of the GNU General Public License version 2 as published by
8219 + * the Free Software Foundation.
8220 + *
8221 + * This program is distributed in the hope that it will be useful, but WITHOUT
8222 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8223 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
8224 + * more details.
8225 + *
8226 + * You should have received a copy of the GNU General Public License along with
8227 + * this program.  If not, see <http://www.gnu.org/licenses/>.
8228 + */
8229 +
8230 +#define DSS_SUBSYS_NAME "DISPLAY"
8231 +
8232 +#include <linux/kernel.h>
8233 +#include <linux/module.h>
8234 +#include <linux/jiffies.h>
8235 +#include <linux/list.h>
8236 +#include <linux/platform_device.h>
8237 +
8238 +#include <mach/display.h>
8239 +#include "dss.h"
8240 +
8241 +static LIST_HEAD(display_list);
8242 +
8243 +static ssize_t display_enabled_show(struct device *dev,
8244 +               struct device_attribute *attr, char *buf)
8245 +{
8246 +       struct omap_dss_device *dssdev = to_dss_device(dev);
8247 +       bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
8248 +
8249 +       return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
8250 +}
8251 +
8252 +static ssize_t display_enabled_store(struct device *dev,
8253 +               struct device_attribute *attr,
8254 +               const char *buf, size_t size)
8255 +{
8256 +       struct omap_dss_device *dssdev = to_dss_device(dev);
8257 +       bool enabled, r;
8258 +
8259 +       enabled = simple_strtoul(buf, NULL, 10);
8260 +
8261 +       if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
8262 +               if (enabled) {
8263 +                       r = dssdev->enable(dssdev);
8264 +                       if (r)
8265 +                               return r;
8266 +               } else {
8267 +                       dssdev->disable(dssdev);
8268 +               }
8269 +       }
8270 +
8271 +       return size;
8272 +}
8273 +
8274 +static ssize_t display_upd_mode_show(struct device *dev,
8275 +               struct device_attribute *attr, char *buf)
8276 +{
8277 +       struct omap_dss_device *dssdev = to_dss_device(dev);
8278 +       enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO;
8279 +       if (dssdev->get_update_mode)
8280 +               mode = dssdev->get_update_mode(dssdev);
8281 +       return snprintf(buf, PAGE_SIZE, "%d\n", mode);
8282 +}
8283 +
8284 +static ssize_t display_upd_mode_store(struct device *dev,
8285 +               struct device_attribute *attr,
8286 +               const char *buf, size_t size)
8287 +{
8288 +       struct omap_dss_device *dssdev = to_dss_device(dev);
8289 +       int val, r;
8290 +       enum omap_dss_update_mode mode;
8291 +
8292 +       val = simple_strtoul(buf, NULL, 10);
8293 +
8294 +       switch (val) {
8295 +       case OMAP_DSS_UPDATE_DISABLED:
8296 +       case OMAP_DSS_UPDATE_AUTO:
8297 +       case OMAP_DSS_UPDATE_MANUAL:
8298 +               mode = (enum omap_dss_update_mode)val;
8299 +               break;
8300 +       default:
8301 +               return -EINVAL;
8302 +       }
8303 +
8304 +       r = dssdev->set_update_mode(dssdev, mode);
8305 +       if (r)
8306 +               return r;
8307 +
8308 +       return size;
8309 +}
8310 +
8311 +static ssize_t display_tear_show(struct device *dev,
8312 +               struct device_attribute *attr, char *buf)
8313 +{
8314 +       struct omap_dss_device *dssdev = to_dss_device(dev);
8315 +       return snprintf(buf, PAGE_SIZE, "%d\n",
8316 +                       dssdev->get_te ? dssdev->get_te(dssdev) : 0);
8317 +}
8318 +
8319 +static ssize_t display_tear_store(struct device *dev,
8320 +               struct device_attribute *attr, const char *buf, size_t size)
8321 +{
8322 +       struct omap_dss_device *dssdev = to_dss_device(dev);
8323 +       unsigned long te;
8324 +       int r;
8325 +
8326 +       if (!dssdev->enable_te || !dssdev->get_te)
8327 +               return -ENOENT;
8328 +
8329 +       te = simple_strtoul(buf, NULL, 0);
8330 +
8331 +       r = dssdev->enable_te(dssdev, te);
8332 +       if (r)
8333 +               return r;
8334 +
8335 +       return size;
8336 +}
8337 +
8338 +static ssize_t display_timings_show(struct device *dev,
8339 +               struct device_attribute *attr, char *buf)
8340 +{
8341 +       struct omap_dss_device *dssdev = to_dss_device(dev);
8342 +       struct omap_video_timings t;
8343 +
8344 +       if (!dssdev->get_timings)
8345 +               return -ENOENT;
8346 +
8347 +       dssdev->get_timings(dssdev, &t);
8348 +
8349 +       return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
8350 +                       t.pixel_clock,
8351 +                       t.x_res, t.hfp, t.hbp, t.hsw,
8352 +                       t.y_res, t.vfp, t.vbp, t.vsw);
8353 +}
8354 +
8355 +static ssize_t display_timings_store(struct device *dev,
8356 +               struct device_attribute *attr, const char *buf, size_t size)
8357 +{
8358 +       struct omap_dss_device *dssdev = to_dss_device(dev);
8359 +       struct omap_video_timings t;
8360 +       int r, found;
8361 +
8362 +       if (!dssdev->set_timings || !dssdev->check_timings)
8363 +               return -ENOENT;
8364 +
8365 +       found = 0;
8366 +#ifdef CONFIG_OMAP2_DSS_VENC
8367 +       if (strncmp("pal", buf, 3) == 0) {
8368 +               t = omap_dss_pal_timings;
8369 +               found = 1;
8370 +       } else if (strncmp("ntsc", buf, 4) == 0) {
8371 +               t = omap_dss_ntsc_timings;
8372 +               found = 1;
8373 +       }
8374 +#endif
8375 +       if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
8376 +                               &t.pixel_clock,
8377 +                               &t.x_res, &t.hfp, &t.hbp, &t.hsw,
8378 +                               &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
8379 +               return -EINVAL;
8380 +
8381 +       r = dssdev->check_timings(dssdev, &t);
8382 +       if (r)
8383 +               return r;
8384 +
8385 +       dssdev->set_timings(dssdev, &t);
8386 +
8387 +       return size;
8388 +}
8389 +
8390 +static ssize_t display_rotate_show(struct device *dev,
8391 +               struct device_attribute *attr, char *buf)
8392 +{
8393 +       struct omap_dss_device *dssdev = to_dss_device(dev);
8394 +       int rotate;
8395 +       if (!dssdev->get_rotate)
8396 +               return -ENOENT;
8397 +       rotate = dssdev->get_rotate(dssdev);
8398 +       return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
8399 +}
8400 +
8401 +static ssize_t display_rotate_store(struct device *dev,
8402 +               struct device_attribute *attr, const char *buf, size_t size)
8403 +{
8404 +       struct omap_dss_device *dssdev = to_dss_device(dev);
8405 +       unsigned long rot;
8406 +       int r;
8407 +
8408 +       if (!dssdev->set_rotate || !dssdev->get_rotate)
8409 +               return -ENOENT;
8410 +
8411 +       rot = simple_strtoul(buf, NULL, 0);
8412 +
8413 +       r = dssdev->set_rotate(dssdev, rot);
8414 +       if (r)
8415 +               return r;
8416 +
8417 +       return size;
8418 +}
8419 +
8420 +static ssize_t display_mirror_show(struct device *dev,
8421 +               struct device_attribute *attr, char *buf)
8422 +{
8423 +       struct omap_dss_device *dssdev = to_dss_device(dev);
8424 +       int mirror;
8425 +       if (!dssdev->get_mirror)
8426 +               return -ENOENT;
8427 +       mirror = dssdev->get_mirror(dssdev);
8428 +       return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
8429 +}
8430 +
8431 +static ssize_t display_mirror_store(struct device *dev,
8432 +               struct device_attribute *attr, const char *buf, size_t size)
8433 +{
8434 +       struct omap_dss_device *dssdev = to_dss_device(dev);
8435 +       unsigned long mirror;
8436 +       int r;
8437 +
8438 +       if (!dssdev->set_mirror || !dssdev->get_mirror)
8439 +               return -ENOENT;
8440 +
8441 +       mirror = simple_strtoul(buf, NULL, 0);
8442 +
8443 +       r = dssdev->set_mirror(dssdev, mirror);
8444 +       if (r)
8445 +               return r;
8446 +
8447 +       return size;
8448 +}
8449 +
8450 +static ssize_t display_wss_show(struct device *dev,
8451 +               struct device_attribute *attr, char *buf)
8452 +{
8453 +       struct omap_dss_device *dssdev = to_dss_device(dev);
8454 +       unsigned int wss;
8455 +
8456 +       if (!dssdev->get_wss)
8457 +               return -ENOENT;
8458 +
8459 +       wss = dssdev->get_wss(dssdev);
8460 +
8461 +       return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
8462 +}
8463 +
8464 +static ssize_t display_wss_store(struct device *dev,
8465 +               struct device_attribute *attr, const char *buf, size_t size)
8466 +{
8467 +       struct omap_dss_device *dssdev = to_dss_device(dev);
8468 +       unsigned long wss;
8469 +       int r;
8470 +
8471 +       if (!dssdev->get_wss || !dssdev->set_wss)
8472 +               return -ENOENT;
8473 +
8474 +       if (strict_strtoul(buf, 0, &wss))
8475 +               return -EINVAL;
8476 +
8477 +       if (wss > 0xfffff)
8478 +               return -EINVAL;
8479 +
8480 +       r = dssdev->set_wss(dssdev, wss);
8481 +       if (r)
8482 +               return r;
8483 +
8484 +       return size;
8485 +}
8486 +
8487 +static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
8488 +               display_enabled_show, display_enabled_store);
8489 +static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR,
8490 +               display_upd_mode_show, display_upd_mode_store);
8491 +static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
8492 +               display_tear_show, display_tear_store);
8493 +static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
8494 +               display_timings_show, display_timings_store);
8495 +static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
8496 +               display_rotate_show, display_rotate_store);
8497 +static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
8498 +               display_mirror_show, display_mirror_store);
8499 +static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
8500 +               display_wss_show, display_wss_store);
8501 +
8502 +static struct device_attribute *display_sysfs_attrs[] = {
8503 +       &dev_attr_enabled,
8504 +       &dev_attr_update_mode,
8505 +       &dev_attr_tear_elim,
8506 +       &dev_attr_timings,
8507 +       &dev_attr_rotate,
8508 +       &dev_attr_mirror,
8509 +       &dev_attr_wss,
8510 +       NULL
8511 +};
8512 +
8513 +static void default_get_resolution(struct omap_dss_device *dssdev,
8514 +                       u16 *xres, u16 *yres)
8515 +{
8516 +       *xres = dssdev->panel.timings.x_res;
8517 +       *yres = dssdev->panel.timings.y_res;
8518 +}
8519 +
8520 +void default_get_overlay_fifo_thresholds(enum omap_plane plane,
8521 +               u32 fifo_size, enum omap_burst_size *burst_size,
8522 +               u32 *fifo_low, u32 *fifo_high)
8523 +{
8524 +       unsigned burst_size_bytes;
8525 +
8526 +       *burst_size = OMAP_DSS_BURST_16x32;
8527 +       burst_size_bytes = 16 * 32 / 8;
8528 +
8529 +       *fifo_high = fifo_size - 1;
8530 +       *fifo_low = fifo_size - burst_size_bytes;
8531 +}
8532 +
8533 +static int default_wait_vsync(struct omap_dss_device *dssdev)
8534 +{
8535 +       unsigned long timeout = msecs_to_jiffies(500);
8536 +       u32 irq;
8537 +
8538 +       if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
8539 +               irq = DISPC_IRQ_EVSYNC_ODD;
8540 +       else
8541 +               irq = DISPC_IRQ_VSYNC;
8542 +
8543 +       return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
8544 +}
8545 +
8546 +static int default_get_recommended_bpp(struct omap_dss_device *dssdev)
8547 +{
8548 +       if (dssdev->panel.recommended_bpp)
8549 +               return dssdev->panel.recommended_bpp;
8550 +
8551 +       switch (dssdev->type) {
8552 +       case OMAP_DISPLAY_TYPE_DPI:
8553 +               if (dssdev->phy.dpi.data_lines == 24)
8554 +                       return 24;
8555 +               else
8556 +                       return 16;
8557 +
8558 +       case OMAP_DISPLAY_TYPE_DBI:
8559 +       case OMAP_DISPLAY_TYPE_DSI:
8560 +               if (dssdev->ctrl.pixel_size == 24)
8561 +                       return 24;
8562 +               else
8563 +                       return 16;
8564 +       case OMAP_DISPLAY_TYPE_VENC:
8565 +       case OMAP_DISPLAY_TYPE_SDI:
8566 +               return 24;
8567 +               return 24;
8568 +       default:
8569 +               BUG();
8570 +       }
8571 +}
8572 +
8573 +/* Checks if replication logic should be used. Only use for active matrix,
8574 + * when overlay is in RGB12U or RGB16 mode, and LCD interface is
8575 + * 18bpp or 24bpp */
8576 +bool dss_use_replication(struct omap_dss_device *dssdev,
8577 +               enum omap_color_mode mode)
8578 +{
8579 +       int bpp;
8580 +
8581 +       if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16)
8582 +               return false;
8583 +
8584 +       if (dssdev->type == OMAP_DISPLAY_TYPE_DPI &&
8585 +                       (dssdev->panel.config & OMAP_DSS_LCD_TFT) == 0)
8586 +               return false;
8587 +
8588 +       switch (dssdev->type) {
8589 +       case OMAP_DISPLAY_TYPE_DPI:
8590 +               bpp = dssdev->phy.dpi.data_lines;
8591 +               break;
8592 +       case OMAP_DISPLAY_TYPE_VENC:
8593 +       case OMAP_DISPLAY_TYPE_SDI:
8594 +               bpp = 24;
8595 +               break;
8596 +       case OMAP_DISPLAY_TYPE_DBI:
8597 +       case OMAP_DISPLAY_TYPE_DSI:
8598 +               bpp = dssdev->ctrl.pixel_size;
8599 +               break;
8600 +       default:
8601 +               BUG();
8602 +       }
8603 +
8604 +       return bpp > 16;
8605 +}
8606 +
8607 +void dss_init_device(struct platform_device *pdev,
8608 +               struct omap_dss_device *dssdev)
8609 +{
8610 +       struct device_attribute *attr;
8611 +       int i;
8612 +       int r;
8613 +
8614 +       switch (dssdev->type) {
8615 +       case OMAP_DISPLAY_TYPE_DPI:
8616 +#ifdef CONFIG_OMAP2_DSS_RFBI
8617 +       case OMAP_DISPLAY_TYPE_DBI:
8618 +#endif
8619 +#ifdef CONFIG_OMAP2_DSS_SDI
8620 +       case OMAP_DISPLAY_TYPE_SDI:
8621 +#endif
8622 +#ifdef CONFIG_OMAP2_DSS_DSI
8623 +       case OMAP_DISPLAY_TYPE_DSI:
8624 +#endif
8625 +#ifdef CONFIG_OMAP2_DSS_VENC
8626 +       case OMAP_DISPLAY_TYPE_VENC:
8627 +#endif
8628 +               break;
8629 +       default:
8630 +               DSSERR("Support for display '%s' not compiled in.\n",
8631 +                               dssdev->name);
8632 +               return;
8633 +       }
8634 +
8635 +       dssdev->get_resolution = default_get_resolution;
8636 +       dssdev->get_recommended_bpp = default_get_recommended_bpp;
8637 +       dssdev->wait_vsync = default_wait_vsync;
8638 +
8639 +       switch (dssdev->type) {
8640 +       case OMAP_DISPLAY_TYPE_DPI:
8641 +               r = dpi_init_display(dssdev);
8642 +               break;
8643 +#ifdef CONFIG_OMAP2_DSS_RFBI
8644 +       case OMAP_DISPLAY_TYPE_DBI:
8645 +               r = rfbi_init_display(dssdev);
8646 +               break;
8647 +#endif
8648 +#ifdef CONFIG_OMAP2_DSS_VENC
8649 +       case OMAP_DISPLAY_TYPE_VENC:
8650 +               r = venc_init_display(dssdev);
8651 +               break;
8652 +#endif
8653 +#ifdef CONFIG_OMAP2_DSS_SDI
8654 +       case OMAP_DISPLAY_TYPE_SDI:
8655 +               r = sdi_init_display(dssdev);
8656 +               break;
8657 +#endif
8658 +#ifdef CONFIG_OMAP2_DSS_DSI
8659 +       case OMAP_DISPLAY_TYPE_DSI:
8660 +               r = dsi_init_display(dssdev);
8661 +               break;
8662 +#endif
8663 +       default:
8664 +               BUG();
8665 +       }
8666 +
8667 +       if (r) {
8668 +               DSSERR("failed to init display %s\n", dssdev->name);
8669 +               return;
8670 +       }
8671 +
8672 +       /* create device sysfs files */
8673 +       i = 0;
8674 +       while ((attr = display_sysfs_attrs[i++]) != NULL) {
8675 +               r = device_create_file(&dssdev->dev, attr);
8676 +               if (r)
8677 +                       DSSERR("failed to create sysfs file\n");
8678 +       }
8679 +
8680 +       /* create display? sysfs links */
8681 +       r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
8682 +                       dev_name(&dssdev->dev));
8683 +       if (r)
8684 +               DSSERR("failed to create sysfs display link\n");
8685 +}
8686 +
8687 +void dss_uninit_device(struct platform_device *pdev,
8688 +               struct omap_dss_device *dssdev)
8689 +{
8690 +       struct device_attribute *attr;
8691 +       int i = 0;
8692 +
8693 +       sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
8694 +
8695 +       while ((attr = display_sysfs_attrs[i++]) != NULL)
8696 +               device_remove_file(&dssdev->dev, attr);
8697 +
8698 +       if (dssdev->manager)
8699 +               dssdev->manager->unset_device(dssdev->manager);
8700 +}
8701 +
8702 +static int dss_suspend_device(struct device *dev, void *data)
8703 +{
8704 +       int r;
8705 +       struct omap_dss_device *dssdev = to_dss_device(dev);
8706 +
8707 +       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
8708 +               dssdev->activate_after_resume = false;
8709 +               return 0;
8710 +       }
8711 +
8712 +       if (!dssdev->suspend) {
8713 +               DSSERR("display '%s' doesn't implement suspend\n",
8714 +                               dssdev->name);
8715 +               return -ENOSYS;
8716 +       }
8717 +
8718 +       r = dssdev->suspend(dssdev);
8719 +       if (r)
8720 +               return r;
8721 +
8722 +       dssdev->activate_after_resume = true;
8723 +
8724 +       return 0;
8725 +}
8726 +
8727 +int dss_suspend_all_devices(void)
8728 +{
8729 +       int r;
8730 +       struct bus_type *bus = dss_get_bus();
8731 +
8732 +       r = bus_for_each_dev(bus, NULL, NULL, dss_suspend_device);
8733 +       if (r) {
8734 +               /* resume all displays that were suspended */
8735 +               dss_resume_all_devices();
8736 +               return r;
8737 +       }
8738 +
8739 +       return 0;
8740 +}
8741 +
8742 +static int dss_resume_device(struct device *dev, void *data)
8743 +{
8744 +       int r;
8745 +       struct omap_dss_device *dssdev = to_dss_device(dev);
8746 +
8747 +       if (dssdev->activate_after_resume && dssdev->resume) {
8748 +               r = dssdev->resume(dssdev);
8749 +               if (r)
8750 +                       return r;
8751 +       }
8752 +
8753 +       dssdev->activate_after_resume = false;
8754 +
8755 +       return 0;
8756 +}
8757 +
8758 +int dss_resume_all_devices(void)
8759 +{
8760 +       struct bus_type *bus = dss_get_bus();
8761 +
8762 +       return bus_for_each_dev(bus, NULL, NULL, dss_resume_device);
8763 +}
8764 +
8765 +
8766 +void omap_dss_get_device(struct omap_dss_device *dssdev)
8767 +{
8768 +       get_device(&dssdev->dev);
8769 +}
8770 +EXPORT_SYMBOL(omap_dss_get_device);
8771 +
8772 +void omap_dss_put_device(struct omap_dss_device *dssdev)
8773 +{
8774 +       put_device(&dssdev->dev);
8775 +}
8776 +EXPORT_SYMBOL(omap_dss_put_device);
8777 +
8778 +/* ref count of the found device is incremented. ref count
8779 + * of from-device is decremented. */
8780 +struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
8781 +{
8782 +       struct device *dev;
8783 +       struct device *dev_start = NULL;
8784 +       struct omap_dss_device *dssdev = NULL;
8785 +
8786 +       int match(struct device *dev, void *data)
8787 +       {
8788 +               /* skip panels connected to controllers */
8789 +               if (to_dss_device(dev)->panel.ctrl)
8790 +                       return 0;
8791 +
8792 +               return 1;
8793 +       }
8794 +
8795 +       if (from)
8796 +               dev_start = &from->dev;
8797 +       dev = bus_find_device(dss_get_bus(), dev_start, NULL, match);
8798 +       if (dev)
8799 +               dssdev = to_dss_device(dev);
8800 +       if (from)
8801 +               put_device(&from->dev);
8802 +
8803 +       return dssdev;
8804 +}
8805 +EXPORT_SYMBOL(omap_dss_get_next_device);
8806 +
8807 +struct omap_dss_device *omap_dss_find_device(void *data,
8808 +               int (*match)(struct omap_dss_device *dssdev, void *data))
8809 +{
8810 +       struct omap_dss_device *dssdev = NULL;
8811 +
8812 +       while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) {
8813 +               if (match(dssdev, data))
8814 +                       return dssdev;
8815 +       }
8816 +
8817 +       return NULL;
8818 +}
8819 +EXPORT_SYMBOL(omap_dss_find_device);
8820 +
8821 +int omap_dss_start_device(struct omap_dss_device *dssdev)
8822 +{
8823 +       int r;
8824 +
8825 +       if (!dssdev->driver) {
8826 +               DSSDBG("no driver\n");
8827 +               r = -ENODEV;
8828 +               goto err0;
8829 +       }
8830 +
8831 +       if (dssdev->ctrl.panel && !dssdev->ctrl.panel->driver) {
8832 +               DSSDBG("no panel driver\n");
8833 +               r = -ENODEV;
8834 +               goto err0;
8835 +       }
8836 +
8837 +       if (!try_module_get(dssdev->dev.driver->owner)) {
8838 +               r = -ENODEV;
8839 +               goto err0;
8840 +       }
8841 +
8842 +       if (dssdev->ctrl.panel) {
8843 +               if (!try_module_get(dssdev->ctrl.panel->dev.driver->owner)) {
8844 +                       r = -ENODEV;
8845 +                       goto err1;
8846 +               }
8847 +       }
8848 +
8849 +       return 0;
8850 +err1:
8851 +       module_put(dssdev->dev.driver->owner);
8852 +err0:
8853 +       return r;
8854 +}
8855 +EXPORT_SYMBOL(omap_dss_start_device);
8856 +
8857 +void omap_dss_stop_device(struct omap_dss_device *dssdev)
8858 +{
8859 +       if (dssdev->ctrl.panel)
8860 +               module_put(dssdev->ctrl.panel->dev.driver->owner);
8861 +
8862 +       module_put(dssdev->dev.driver->owner);
8863 +}
8864 +EXPORT_SYMBOL(omap_dss_stop_device);
8865 +
8866 diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
8867 new file mode 100644
8868 index 0000000..b6543c8
8869 --- /dev/null
8870 +++ b/drivers/video/omap2/dss/dpi.c
8871 @@ -0,0 +1,388 @@
8872 +/*
8873 + * linux/drivers/video/omap2/dss/dpi.c
8874 + *
8875 + * Copyright (C) 2009 Nokia Corporation
8876 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
8877 + *
8878 + * Some code and ideas taken from drivers/video/omap/ driver
8879 + * by Imre Deak.
8880 + *
8881 + * This program is free software; you can redistribute it and/or modify it
8882 + * under the terms of the GNU General Public License version 2 as published by
8883 + * the Free Software Foundation.
8884 + *
8885 + * This program is distributed in the hope that it will be useful, but WITHOUT
8886 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8887 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
8888 + * more details.
8889 + *
8890 + * You should have received a copy of the GNU General Public License along with
8891 + * this program.  If not, see <http://www.gnu.org/licenses/>.
8892 + */
8893 +
8894 +#define DSS_SUBSYS_NAME "DPI"
8895 +
8896 +#include <linux/kernel.h>
8897 +#include <linux/clk.h>
8898 +#include <linux/delay.h>
8899 +#include <linux/errno.h>
8900 +
8901 +#include <mach/board.h>
8902 +#include <mach/display.h>
8903 +#include <mach/cpu.h>
8904 +
8905 +#include "dss.h"
8906 +
8907 +static struct {
8908 +       int update_enabled;
8909 +} dpi;
8910 +
8911 +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
8912 +static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req,
8913 +               unsigned long *fck, int *lck_div, int *pck_div)
8914 +{
8915 +       struct dsi_clock_info cinfo;
8916 +       int r;
8917 +
8918 +       r = dsi_pll_calc_pck(is_tft, pck_req, &cinfo);
8919 +       if (r)
8920 +               return r;
8921 +
8922 +       r = dsi_pll_program(&cinfo);
8923 +       if (r)
8924 +               return r;
8925 +
8926 +       dss_select_clk_source(0, 1);
8927 +
8928 +       dispc_set_lcd_divisor(cinfo.lck_div, cinfo.pck_div);
8929 +
8930 +       *fck = cinfo.dsi1_pll_fclk;
8931 +       *lck_div = cinfo.lck_div;
8932 +       *pck_div = cinfo.pck_div;
8933 +
8934 +       return 0;
8935 +}
8936 +#else
8937 +static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req,
8938 +               unsigned long *fck, int *lck_div, int *pck_div)
8939 +{
8940 +       struct dispc_clock_info cinfo;
8941 +       int r;
8942 +
8943 +       r = dispc_calc_clock_div(is_tft, pck_req, &cinfo);
8944 +       if (r)
8945 +               return r;
8946 +
8947 +       r = dispc_set_clock_div(&cinfo);
8948 +       if (r)
8949 +               return r;
8950 +
8951 +       *fck = cinfo.fck;
8952 +       *lck_div = cinfo.lck_div;
8953 +       *pck_div = cinfo.pck_div;
8954 +
8955 +       return 0;
8956 +}
8957 +#endif
8958 +
8959 +static int dpi_set_mode(struct omap_dss_device *dssdev)
8960 +{
8961 +       struct omap_video_timings *t = &dssdev->panel.timings;
8962 +       int lck_div, pck_div;
8963 +       unsigned long fck;
8964 +       unsigned long pck;
8965 +       bool is_tft;
8966 +       int r = 0;
8967 +
8968 +       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
8969 +
8970 +       dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi,
8971 +                       dssdev->panel.acb);
8972 +
8973 +       is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
8974 +
8975 +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
8976 +       r = dpi_set_dsi_clk(is_tft, t->pixel_clock * 1000,
8977 +                       &fck, &lck_div, &pck_div);
8978 +#else
8979 +       r = dpi_set_dispc_clk(is_tft, t->pixel_clock * 1000,
8980 +                       &fck, &lck_div, &pck_div);
8981 +#endif
8982 +       if (r)
8983 +               goto err0;
8984 +
8985 +       pck = fck / lck_div / pck_div / 1000;
8986 +
8987 +       if (pck != t->pixel_clock) {
8988 +               DSSWARN("Could not find exact pixel clock. "
8989 +                               "Requested %d kHz, got %lu kHz\n",
8990 +                               t->pixel_clock, pck);
8991 +
8992 +               t->pixel_clock = pck;
8993 +       }
8994 +
8995 +       dispc_set_lcd_timings(t);
8996 +
8997 +err0:
8998 +       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
8999 +       return r;
9000 +}
9001 +
9002 +static int dpi_basic_init(struct omap_dss_device *dssdev)
9003 +{
9004 +       bool is_tft;
9005 +
9006 +       is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
9007 +
9008 +       dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
9009 +       dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT :
9010 +                       OMAP_DSS_LCD_DISPLAY_STN);
9011 +       dispc_set_tft_data_lines(dssdev->phy.dpi.data_lines);
9012 +
9013 +       return 0;
9014 +}
9015 +
9016 +static int dpi_display_enable(struct omap_dss_device *dssdev)
9017 +{
9018 +       int r;
9019 +
9020 +       r = omap_dss_start_device(dssdev);
9021 +       if (r) {
9022 +               DSSERR("failed to start device\n");
9023 +               goto err0;
9024 +       }
9025 +
9026 +       if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
9027 +               DSSERR("display already enabled\n");
9028 +               r = -EINVAL;
9029 +               goto err1;
9030 +       }
9031 +
9032 +       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
9033 +
9034 +       r = dpi_basic_init(dssdev);
9035 +       if (r)
9036 +               goto err2;
9037 +
9038 +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
9039 +       dss_clk_enable(DSS_CLK_FCK2);
9040 +       r = dsi_pll_init(0, 1);
9041 +       if (r)
9042 +               goto err3;
9043 +#endif
9044 +       r = dpi_set_mode(dssdev);
9045 +       if (r)
9046 +               goto err4;
9047 +
9048 +       mdelay(2);
9049 +
9050 +       dispc_enable_lcd_out(1);
9051 +
9052 +       r = dssdev->driver->enable(dssdev);
9053 +       if (r)
9054 +               goto err5;
9055 +
9056 +       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
9057 +
9058 +       return 0;
9059 +
9060 +err5:
9061 +       dispc_enable_lcd_out(0);
9062 +err4:
9063 +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
9064 +       dsi_pll_uninit();
9065 +err3:
9066 +       dss_clk_disable(DSS_CLK_FCK2);
9067 +#endif
9068 +err2:
9069 +       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
9070 +err1:
9071 +       omap_dss_stop_device(dssdev);
9072 +err0:
9073 +       return r;
9074 +}
9075 +
9076 +static int dpi_display_resume(struct omap_dss_device *dssdev);
9077 +
9078 +static void dpi_display_disable(struct omap_dss_device *dssdev)
9079 +{
9080 +       if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
9081 +               return;
9082 +
9083 +       if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
9084 +               dpi_display_resume(dssdev);
9085 +
9086 +       dssdev->driver->disable(dssdev);
9087 +
9088 +       dispc_enable_lcd_out(0);
9089 +
9090 +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
9091 +       dss_select_clk_source(0, 0);
9092 +       dsi_pll_uninit();
9093 +       dss_clk_disable(DSS_CLK_FCK2);
9094 +#endif
9095 +
9096 +       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
9097 +
9098 +       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
9099 +
9100 +       omap_dss_stop_device(dssdev);
9101 +}
9102 +
9103 +static int dpi_display_suspend(struct omap_dss_device *dssdev)
9104 +{
9105 +       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
9106 +               return -EINVAL;
9107 +
9108 +       DSSDBG("dpi_display_suspend\n");
9109 +
9110 +       if (dssdev->driver->suspend)
9111 +               dssdev->driver->suspend(dssdev);
9112 +
9113 +       dispc_enable_lcd_out(0);
9114 +
9115 +       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
9116 +
9117 +       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
9118 +
9119 +       return 0;
9120 +}
9121 +
9122 +static int dpi_display_resume(struct omap_dss_device *dssdev)
9123 +{
9124 +       if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
9125 +               return -EINVAL;
9126 +
9127 +       DSSDBG("dpi_display_resume\n");
9128 +
9129 +       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
9130 +
9131 +       dispc_enable_lcd_out(1);
9132 +
9133 +       if (dssdev->driver->resume)
9134 +               dssdev->driver->resume(dssdev);
9135 +
9136 +       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
9137 +
9138 +       return 0;
9139 +}
9140 +
9141 +static void dpi_set_timings(struct omap_dss_device *dssdev,
9142 +                       struct omap_video_timings *timings)
9143 +{
9144 +       DSSDBG("dpi_set_timings\n");
9145 +       dssdev->panel.timings = *timings;
9146 +       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
9147 +               dpi_set_mode(dssdev);
9148 +               dispc_go(OMAP_DSS_CHANNEL_LCD);
9149 +       }
9150 +}
9151 +
9152 +static int dpi_check_timings(struct omap_dss_device *dssdev,
9153 +                       struct omap_video_timings *timings)
9154 +{
9155 +       bool is_tft;
9156 +       int r;
9157 +       int lck_div, pck_div;
9158 +       unsigned long fck;
9159 +       unsigned long pck;
9160 +
9161 +       if (!dispc_lcd_timings_ok(timings))
9162 +               return -EINVAL;
9163 +
9164 +       if (timings->pixel_clock == 0)
9165 +               return -EINVAL;
9166 +
9167 +       is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
9168 +
9169 +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
9170 +       {
9171 +               struct dsi_clock_info cinfo;
9172 +               r = dsi_pll_calc_pck(is_tft, timings->pixel_clock * 1000,
9173 +                               &cinfo);
9174 +
9175 +               if (r)
9176 +                       return r;
9177 +
9178 +               fck = cinfo.dsi1_pll_fclk;
9179 +               lck_div = cinfo.lck_div;
9180 +               pck_div = cinfo.pck_div;
9181 +       }
9182 +#else
9183 +       {
9184 +               struct dispc_clock_info cinfo;
9185 +               r = dispc_calc_clock_div(is_tft, timings->pixel_clock * 1000,
9186 +                               &cinfo);
9187 +
9188 +               if (r)
9189 +                       return r;
9190 +
9191 +               fck = cinfo.fck;
9192 +               lck_div = cinfo.lck_div;
9193 +               pck_div = cinfo.pck_div;
9194 +       }
9195 +#endif
9196 +
9197 +       pck = fck / lck_div / pck_div / 1000;
9198 +
9199 +       timings->pixel_clock = pck;
9200 +
9201 +       return 0;
9202 +}
9203 +
9204 +static void dpi_get_timings(struct omap_dss_device *dssdev,
9205 +                       struct omap_video_timings *timings)
9206 +{
9207 +       *timings = dssdev->panel.timings;
9208 +}
9209 +
9210 +static int dpi_display_set_update_mode(struct omap_dss_device *dssdev,
9211 +               enum omap_dss_update_mode mode)
9212 +{
9213 +       if (mode == OMAP_DSS_UPDATE_MANUAL)
9214 +               return -EINVAL;
9215 +
9216 +       if (mode == OMAP_DSS_UPDATE_DISABLED) {
9217 +               dispc_enable_lcd_out(0);
9218 +               dpi.update_enabled = 0;
9219 +       } else {
9220 +               dispc_enable_lcd_out(1);
9221 +               dpi.update_enabled = 1;
9222 +       }
9223 +
9224 +       return 0;
9225 +}
9226 +
9227 +static enum omap_dss_update_mode dpi_display_get_update_mode(
9228 +               struct omap_dss_device *dssdev)
9229 +{
9230 +       return dpi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
9231 +               OMAP_DSS_UPDATE_DISABLED;
9232 +}
9233 +
9234 +int dpi_init_display(struct omap_dss_device *dssdev)
9235 +{
9236 +       DSSDBG("init_display\n");
9237 +
9238 +       dssdev->enable = dpi_display_enable;
9239 +       dssdev->disable = dpi_display_disable;
9240 +       dssdev->suspend = dpi_display_suspend;
9241 +       dssdev->resume = dpi_display_resume;
9242 +       dssdev->set_timings = dpi_set_timings;
9243 +       dssdev->check_timings = dpi_check_timings;
9244 +       dssdev->get_timings = dpi_get_timings;
9245 +       dssdev->set_update_mode = dpi_display_set_update_mode;
9246 +       dssdev->get_update_mode = dpi_display_get_update_mode;
9247 +
9248 +       return 0;
9249 +}
9250 +
9251 +int dpi_init(void)
9252 +{
9253 +       return 0;
9254 +}
9255 +
9256 +void dpi_exit(void)
9257 +{
9258 +}
9259 +
9260 diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
9261 new file mode 100644
9262 index 0000000..d43b9ce
9263 --- /dev/null
9264 +++ b/drivers/video/omap2/dss/dsi.c
9265 @@ -0,0 +1,3509 @@
9266 +/*
9267 + * linux/drivers/video/omap2/dss/dsi.c
9268 + *
9269 + * Copyright (C) 2009 Nokia Corporation
9270 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
9271 + *
9272 + * This program is free software; you can redistribute it and/or modify it
9273 + * under the terms of the GNU General Public License version 2 as published by
9274 + * the Free Software Foundation.
9275 + *
9276 + * This program is distributed in the hope that it will be useful, but WITHOUT
9277 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9278 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
9279 + * more details.
9280 + *
9281 + * You should have received a copy of the GNU General Public License along with
9282 + * this program.  If not, see <http://www.gnu.org/licenses/>.
9283 + */
9284 +
9285 +#define DSS_SUBSYS_NAME "DSI"
9286 +
9287 +#include <linux/kernel.h>
9288 +#include <linux/io.h>
9289 +#include <linux/clk.h>
9290 +#include <linux/device.h>
9291 +#include <linux/err.h>
9292 +#include <linux/interrupt.h>
9293 +#include <linux/delay.h>
9294 +#include <linux/mutex.h>
9295 +#include <linux/seq_file.h>
9296 +#include <linux/platform_device.h>
9297 +#include <linux/regulator/consumer.h>
9298 +#include <linux/kthread.h>
9299 +#include <linux/wait.h>
9300 +
9301 +#include <mach/board.h>
9302 +#include <mach/display.h>
9303 +#include <mach/clock.h>
9304 +
9305 +#include "dss.h"
9306 +
9307 +/*#define VERBOSE_IRQ*/
9308 +
9309 +#define DSI_BASE               0x4804FC00
9310 +
9311 +struct dsi_reg { u16 idx; };
9312 +
9313 +#define DSI_REG(idx)           ((const struct dsi_reg) { idx })
9314 +
9315 +#define DSI_SZ_REGS            SZ_1K
9316 +/* DSI Protocol Engine */
9317 +
9318 +#define DSI_REVISION                   DSI_REG(0x0000)
9319 +#define DSI_SYSCONFIG                  DSI_REG(0x0010)
9320 +#define DSI_SYSSTATUS                  DSI_REG(0x0014)
9321 +#define DSI_IRQSTATUS                  DSI_REG(0x0018)
9322 +#define DSI_IRQENABLE                  DSI_REG(0x001C)
9323 +#define DSI_CTRL                       DSI_REG(0x0040)
9324 +#define DSI_COMPLEXIO_CFG1             DSI_REG(0x0048)
9325 +#define DSI_COMPLEXIO_IRQ_STATUS       DSI_REG(0x004C)
9326 +#define DSI_COMPLEXIO_IRQ_ENABLE       DSI_REG(0x0050)
9327 +#define DSI_CLK_CTRL                   DSI_REG(0x0054)
9328 +#define DSI_TIMING1                    DSI_REG(0x0058)
9329 +#define DSI_TIMING2                    DSI_REG(0x005C)
9330 +#define DSI_VM_TIMING1                 DSI_REG(0x0060)
9331 +#define DSI_VM_TIMING2                 DSI_REG(0x0064)
9332 +#define DSI_VM_TIMING3                 DSI_REG(0x0068)
9333 +#define DSI_CLK_TIMING                 DSI_REG(0x006C)
9334 +#define DSI_TX_FIFO_VC_SIZE            DSI_REG(0x0070)
9335 +#define DSI_RX_FIFO_VC_SIZE            DSI_REG(0x0074)
9336 +#define DSI_COMPLEXIO_CFG2             DSI_REG(0x0078)
9337 +#define DSI_RX_FIFO_VC_FULLNESS                DSI_REG(0x007C)
9338 +#define DSI_VM_TIMING4                 DSI_REG(0x0080)
9339 +#define DSI_TX_FIFO_VC_EMPTINESS       DSI_REG(0x0084)
9340 +#define DSI_VM_TIMING5                 DSI_REG(0x0088)
9341 +#define DSI_VM_TIMING6                 DSI_REG(0x008C)
9342 +#define DSI_VM_TIMING7                 DSI_REG(0x0090)
9343 +#define DSI_STOPCLK_TIMING             DSI_REG(0x0094)
9344 +#define DSI_VC_CTRL(n)                 DSI_REG(0x0100 + (n * 0x20))
9345 +#define DSI_VC_TE(n)                   DSI_REG(0x0104 + (n * 0x20))
9346 +#define DSI_VC_LONG_PACKET_HEADER(n)   DSI_REG(0x0108 + (n * 0x20))
9347 +#define DSI_VC_LONG_PACKET_PAYLOAD(n)  DSI_REG(0x010C + (n * 0x20))
9348 +#define DSI_VC_SHORT_PACKET_HEADER(n)  DSI_REG(0x0110 + (n * 0x20))
9349 +#define DSI_VC_IRQSTATUS(n)            DSI_REG(0x0118 + (n * 0x20))
9350 +#define DSI_VC_IRQENABLE(n)            DSI_REG(0x011C + (n * 0x20))
9351 +
9352 +/* DSIPHY_SCP */
9353 +
9354 +#define DSI_DSIPHY_CFG0                        DSI_REG(0x200 + 0x0000)
9355 +#define DSI_DSIPHY_CFG1                        DSI_REG(0x200 + 0x0004)
9356 +#define DSI_DSIPHY_CFG2                        DSI_REG(0x200 + 0x0008)
9357 +#define DSI_DSIPHY_CFG5                        DSI_REG(0x200 + 0x0014)
9358 +
9359 +/* DSI_PLL_CTRL_SCP */
9360 +
9361 +#define DSI_PLL_CONTROL                        DSI_REG(0x300 + 0x0000)
9362 +#define DSI_PLL_STATUS                 DSI_REG(0x300 + 0x0004)
9363 +#define DSI_PLL_GO                     DSI_REG(0x300 + 0x0008)
9364 +#define DSI_PLL_CONFIGURATION1         DSI_REG(0x300 + 0x000C)
9365 +#define DSI_PLL_CONFIGURATION2         DSI_REG(0x300 + 0x0010)
9366 +
9367 +#define REG_GET(idx, start, end) \
9368 +       FLD_GET(dsi_read_reg(idx), start, end)
9369 +
9370 +#define REG_FLD_MOD(idx, val, start, end) \
9371 +       dsi_write_reg(idx, FLD_MOD(dsi_read_reg(idx), val, start, end))
9372 +
9373 +/* Global interrupts */
9374 +#define DSI_IRQ_VC0            (1 << 0)
9375 +#define DSI_IRQ_VC1            (1 << 1)
9376 +#define DSI_IRQ_VC2            (1 << 2)
9377 +#define DSI_IRQ_VC3            (1 << 3)
9378 +#define DSI_IRQ_WAKEUP         (1 << 4)
9379 +#define DSI_IRQ_RESYNC         (1 << 5)
9380 +#define DSI_IRQ_PLL_LOCK       (1 << 7)
9381 +#define DSI_IRQ_PLL_UNLOCK     (1 << 8)
9382 +#define DSI_IRQ_PLL_RECALL     (1 << 9)
9383 +#define DSI_IRQ_COMPLEXIO_ERR  (1 << 10)
9384 +#define DSI_IRQ_HS_TX_TIMEOUT  (1 << 14)
9385 +#define DSI_IRQ_LP_RX_TIMEOUT  (1 << 15)
9386 +#define DSI_IRQ_TE_TRIGGER     (1 << 16)
9387 +#define DSI_IRQ_ACK_TRIGGER    (1 << 17)
9388 +#define DSI_IRQ_SYNC_LOST      (1 << 18)
9389 +#define DSI_IRQ_LDO_POWER_GOOD (1 << 19)
9390 +#define DSI_IRQ_TA_TIMEOUT     (1 << 20)
9391 +#define DSI_IRQ_ERROR_MASK \
9392 +       (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
9393 +       DSI_IRQ_TA_TIMEOUT)
9394 +#define DSI_IRQ_CHANNEL_MASK   0xf
9395 +
9396 +/* Virtual channel interrupts */
9397 +#define DSI_VC_IRQ_CS          (1 << 0)
9398 +#define DSI_VC_IRQ_ECC_CORR    (1 << 1)
9399 +#define DSI_VC_IRQ_PACKET_SENT (1 << 2)
9400 +#define DSI_VC_IRQ_FIFO_TX_OVF (1 << 3)
9401 +#define DSI_VC_IRQ_FIFO_RX_OVF (1 << 4)
9402 +#define DSI_VC_IRQ_BTA         (1 << 5)
9403 +#define DSI_VC_IRQ_ECC_NO_CORR (1 << 6)
9404 +#define DSI_VC_IRQ_FIFO_TX_UDF (1 << 7)
9405 +#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8)
9406 +#define DSI_VC_IRQ_ERROR_MASK \
9407 +       (DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \
9408 +       DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \
9409 +       DSI_VC_IRQ_FIFO_TX_UDF)
9410 +
9411 +/* ComplexIO interrupts */
9412 +#define DSI_CIO_IRQ_ERRSYNCESC1                (1 << 0)
9413 +#define DSI_CIO_IRQ_ERRSYNCESC2                (1 << 1)
9414 +#define DSI_CIO_IRQ_ERRSYNCESC3                (1 << 2)
9415 +#define DSI_CIO_IRQ_ERRESC1            (1 << 5)
9416 +#define DSI_CIO_IRQ_ERRESC2            (1 << 6)
9417 +#define DSI_CIO_IRQ_ERRESC3            (1 << 7)
9418 +#define DSI_CIO_IRQ_ERRCONTROL1                (1 << 10)
9419 +#define DSI_CIO_IRQ_ERRCONTROL2                (1 << 11)
9420 +#define DSI_CIO_IRQ_ERRCONTROL3                (1 << 12)
9421 +#define DSI_CIO_IRQ_STATEULPS1         (1 << 15)
9422 +#define DSI_CIO_IRQ_STATEULPS2         (1 << 16)
9423 +#define DSI_CIO_IRQ_STATEULPS3         (1 << 17)
9424 +#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20)
9425 +#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21)
9426 +#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22)
9427 +#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23)
9428 +#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24)
9429 +#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25)
9430 +#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30)
9431 +#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31)
9432 +
9433 +#define DSI_DT_DCS_SHORT_WRITE_0       0x05
9434 +#define DSI_DT_DCS_SHORT_WRITE_1       0x15
9435 +#define DSI_DT_DCS_READ                        0x06
9436 +#define DSI_DT_SET_MAX_RET_PKG_SIZE    0x37
9437 +#define DSI_DT_NULL_PACKET             0x09
9438 +#define DSI_DT_DCS_LONG_WRITE          0x39
9439 +
9440 +#define DSI_DT_RX_ACK_WITH_ERR         0x02
9441 +#define DSI_DT_RX_DCS_LONG_READ                0x1c
9442 +#define DSI_DT_RX_SHORT_READ_1         0x21
9443 +#define DSI_DT_RX_SHORT_READ_2         0x22
9444 +
9445 +#define FINT_MAX 2100000
9446 +#define FINT_MIN 750000
9447 +#define REGN_MAX (1 << 7)
9448 +#define REGM_MAX ((1 << 11) - 1)
9449 +#define REGM3_MAX (1 << 4)
9450 +#define REGM4_MAX (1 << 4)
9451 +
9452 +enum fifo_size {
9453 +       DSI_FIFO_SIZE_0         = 0,
9454 +       DSI_FIFO_SIZE_32        = 1,
9455 +       DSI_FIFO_SIZE_64        = 2,
9456 +       DSI_FIFO_SIZE_96        = 3,
9457 +       DSI_FIFO_SIZE_128       = 4,
9458 +};
9459 +
9460 +enum dsi_vc_mode {
9461 +       DSI_VC_MODE_L4 = 0,
9462 +       DSI_VC_MODE_VP,
9463 +};
9464 +
9465 +struct dsi_update_region {
9466 +       bool dirty;
9467 +       u16 x, y, w, h;
9468 +       struct omap_dss_device *device;
9469 +};
9470 +
9471 +static struct
9472 +{
9473 +       void __iomem    *base;
9474 +
9475 +       unsigned long   dsi1_pll_fclk;  /* Hz */
9476 +       unsigned long   dsi2_pll_fclk;  /* Hz */
9477 +       unsigned long   dsiphy;         /* Hz */
9478 +       unsigned long   ddr_clk;        /* Hz */
9479 +
9480 +       struct regulator *vdds_dsi_reg;
9481 +
9482 +       struct {
9483 +               enum dsi_vc_mode mode;
9484 +               struct omap_dss_device *dssdev;
9485 +               enum fifo_size fifo_size;
9486 +               int dest_per;   /* destination peripheral 0-3 */
9487 +       } vc[4];
9488 +
9489 +       struct mutex lock;
9490 +       struct mutex bus_lock;
9491 +
9492 +       unsigned pll_locked;
9493 +
9494 +       struct completion bta_completion;
9495 +
9496 +       struct task_struct *thread;
9497 +       wait_queue_head_t waitqueue;
9498 +
9499 +       spinlock_t update_lock;
9500 +       bool framedone_received;
9501 +       struct dsi_update_region update_region;
9502 +       struct dsi_update_region active_update_region;
9503 +       struct completion update_completion;
9504 +
9505 +       enum omap_dss_update_mode user_update_mode;
9506 +       enum omap_dss_update_mode update_mode;
9507 +       bool te_enabled;
9508 +       bool use_ext_te;
9509 +
9510 +       unsigned long cache_req_pck;
9511 +       unsigned long cache_clk_freq;
9512 +       struct dsi_clock_info cache_cinfo;
9513 +
9514 +       u32             errors;
9515 +       spinlock_t      errors_lock;
9516 +#ifdef DEBUG
9517 +       ktime_t perf_setup_time;
9518 +       ktime_t perf_start_time;
9519 +       ktime_t perf_start_time_auto;
9520 +       int perf_measure_frames;
9521 +#endif
9522 +       int debug_read;
9523 +       int debug_write;
9524 +} dsi;
9525 +
9526 +#ifdef DEBUG
9527 +static unsigned int dsi_perf;
9528 +module_param_named(dsi_perf, dsi_perf, bool, 0644);
9529 +#endif
9530 +
9531 +static inline void dsi_write_reg(const struct dsi_reg idx, u32 val)
9532 +{
9533 +       __raw_writel(val, dsi.base + idx.idx);
9534 +}
9535 +
9536 +static inline u32 dsi_read_reg(const struct dsi_reg idx)
9537 +{
9538 +       return __raw_readl(dsi.base + idx.idx);
9539 +}
9540 +
9541 +
9542 +void dsi_save_context(void)
9543 +{
9544 +}
9545 +
9546 +void dsi_restore_context(void)
9547 +{
9548 +}
9549 +
9550 +void dsi_bus_lock(void)
9551 +{
9552 +       mutex_lock(&dsi.bus_lock);
9553 +}
9554 +EXPORT_SYMBOL(dsi_bus_lock);
9555 +
9556 +void dsi_bus_unlock(void)
9557 +{
9558 +       mutex_unlock(&dsi.bus_lock);
9559 +}
9560 +EXPORT_SYMBOL(dsi_bus_unlock);
9561 +
9562 +static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
9563 +               int value)
9564 +{
9565 +       int t = 100000;
9566 +
9567 +       while (REG_GET(idx, bitnum, bitnum) != value) {
9568 +               if (--t == 0)
9569 +                       return !value;
9570 +       }
9571 +
9572 +       return value;
9573 +}
9574 +
9575 +#ifdef DEBUG
9576 +static void dsi_perf_mark_setup(void)
9577 +{
9578 +       dsi.perf_setup_time = ktime_get();
9579 +}
9580 +
9581 +static void dsi_perf_mark_start(void)
9582 +{
9583 +       dsi.perf_start_time = ktime_get();
9584 +}
9585 +
9586 +static void dsi_perf_mark_start_auto(void)
9587 +{
9588 +       dsi.perf_measure_frames = 0;
9589 +       dsi.perf_start_time_auto = ktime_get();
9590 +}
9591 +
9592 +static void dsi_perf_show(const char *name)
9593 +{
9594 +       ktime_t t, setup_time, trans_time;
9595 +       u32 total_bytes;
9596 +       u32 setup_us, trans_us, total_us;
9597 +
9598 +       if (!dsi_perf)
9599 +               return;
9600 +
9601 +       if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED)
9602 +               return;
9603 +
9604 +       t = ktime_get();
9605 +
9606 +       setup_time = ktime_sub(dsi.perf_start_time, dsi.perf_setup_time);
9607 +       setup_us = (u32)ktime_to_us(setup_time);
9608 +       if (setup_us == 0)
9609 +               setup_us = 1;
9610 +
9611 +       trans_time = ktime_sub(t, dsi.perf_start_time);
9612 +       trans_us = (u32)ktime_to_us(trans_time);
9613 +       if (trans_us == 0)
9614 +               trans_us = 1;
9615 +
9616 +       total_us = setup_us + trans_us;
9617 +
9618 +       total_bytes = dsi.active_update_region.w *
9619 +               dsi.active_update_region.h *
9620 +               dsi.active_update_region.device->ctrl.pixel_size / 8;
9621 +
9622 +       if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
9623 +               static u32 s_total_trans_us, s_total_setup_us;
9624 +               static u32 s_min_trans_us = 0xffffffff, s_min_setup_us;
9625 +               static u32 s_max_trans_us, s_max_setup_us;
9626 +               const int numframes = 100;
9627 +               ktime_t total_time_auto;
9628 +               u32 total_time_auto_us;
9629 +
9630 +               dsi.perf_measure_frames++;
9631 +
9632 +               if (setup_us < s_min_setup_us)
9633 +                       s_min_setup_us = setup_us;
9634 +
9635 +               if (setup_us > s_max_setup_us)
9636 +                       s_max_setup_us = setup_us;
9637 +
9638 +               s_total_setup_us += setup_us;
9639 +
9640 +               if (trans_us < s_min_trans_us)
9641 +                       s_min_trans_us = trans_us;
9642 +
9643 +               if (trans_us > s_max_trans_us)
9644 +                       s_max_trans_us = trans_us;
9645 +
9646 +               s_total_trans_us += trans_us;
9647 +
9648 +               if (dsi.perf_measure_frames < numframes)
9649 +                       return;
9650 +
9651 +               total_time_auto = ktime_sub(t, dsi.perf_start_time_auto);
9652 +               total_time_auto_us = (u32)ktime_to_us(total_time_auto);
9653 +
9654 +               printk(KERN_INFO "DSI(%s): %u fps, setup %u/%u/%u, "
9655 +                               "trans %u/%u/%u\n",
9656 +                               name,
9657 +                               1000 * 1000 * numframes / total_time_auto_us,
9658 +                               s_min_setup_us,
9659 +                               s_max_setup_us,
9660 +                               s_total_setup_us / numframes,
9661 +                               s_min_trans_us,
9662 +                               s_max_trans_us,
9663 +                               s_total_trans_us / numframes);
9664 +
9665 +               s_total_setup_us = 0;
9666 +               s_min_setup_us = 0xffffffff;
9667 +               s_max_setup_us = 0;
9668 +               s_total_trans_us = 0;
9669 +               s_min_trans_us = 0xffffffff;
9670 +               s_max_trans_us = 0;
9671 +               dsi_perf_mark_start_auto();
9672 +       } else {
9673 +               printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
9674 +                               "%u bytes, %u kbytes/sec\n",
9675 +                               name,
9676 +                               setup_us,
9677 +                               trans_us,
9678 +                               total_us,
9679 +                               1000*1000 / total_us,
9680 +                               total_bytes,
9681 +                               total_bytes * 1000 / total_us);
9682 +       }
9683 +}
9684 +#else
9685 +#define dsi_perf_mark_setup()
9686 +#define dsi_perf_mark_start()
9687 +#define dsi_perf_mark_start_auto()
9688 +#define dsi_perf_show(x)
9689 +#endif
9690 +
9691 +static void print_irq_status(u32 status)
9692 +{
9693 +#ifndef VERBOSE_IRQ
9694 +       if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
9695 +               return;
9696 +#endif
9697 +       printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status);
9698 +
9699 +#define PIS(x) \
9700 +       if (status & DSI_IRQ_##x) \
9701 +               printk(#x " ");
9702 +#ifdef VERBOSE_IRQ
9703 +       PIS(VC0);
9704 +       PIS(VC1);
9705 +       PIS(VC2);
9706 +       PIS(VC3);
9707 +#endif
9708 +       PIS(WAKEUP);
9709 +       PIS(RESYNC);
9710 +       PIS(PLL_LOCK);
9711 +       PIS(PLL_UNLOCK);
9712 +       PIS(PLL_RECALL);
9713 +       PIS(COMPLEXIO_ERR);
9714 +       PIS(HS_TX_TIMEOUT);
9715 +       PIS(LP_RX_TIMEOUT);
9716 +       PIS(TE_TRIGGER);
9717 +       PIS(ACK_TRIGGER);
9718 +       PIS(SYNC_LOST);
9719 +       PIS(LDO_POWER_GOOD);
9720 +       PIS(TA_TIMEOUT);
9721 +#undef PIS
9722 +
9723 +       printk("\n");
9724 +}
9725 +
9726 +static void print_irq_status_vc(int channel, u32 status)
9727 +{
9728 +#ifndef VERBOSE_IRQ
9729 +       if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
9730 +               return;
9731 +#endif
9732 +       printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status);
9733 +
9734 +#define PIS(x) \
9735 +       if (status & DSI_VC_IRQ_##x) \
9736 +               printk(#x " ");
9737 +       PIS(CS);
9738 +       PIS(ECC_CORR);
9739 +#ifdef VERBOSE_IRQ
9740 +       PIS(PACKET_SENT);
9741 +#endif
9742 +       PIS(FIFO_TX_OVF);
9743 +       PIS(FIFO_RX_OVF);
9744 +       PIS(BTA);
9745 +       PIS(ECC_NO_CORR);
9746 +       PIS(FIFO_TX_UDF);
9747 +       PIS(PP_BUSY_CHANGE);
9748 +#undef PIS
9749 +       printk("\n");
9750 +}
9751 +
9752 +static void print_irq_status_cio(u32 status)
9753 +{
9754 +       printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
9755 +
9756 +#define PIS(x) \
9757 +       if (status & DSI_CIO_IRQ_##x) \
9758 +               printk(#x " ");
9759 +       PIS(ERRSYNCESC1);
9760 +       PIS(ERRSYNCESC2);
9761 +       PIS(ERRSYNCESC3);
9762 +       PIS(ERRESC1);
9763 +       PIS(ERRESC2);
9764 +       PIS(ERRESC3);
9765 +       PIS(ERRCONTROL1);
9766 +       PIS(ERRCONTROL2);
9767 +       PIS(ERRCONTROL3);
9768 +       PIS(STATEULPS1);
9769 +       PIS(STATEULPS2);
9770 +       PIS(STATEULPS3);
9771 +       PIS(ERRCONTENTIONLP0_1);
9772 +       PIS(ERRCONTENTIONLP1_1);
9773 +       PIS(ERRCONTENTIONLP0_2);
9774 +       PIS(ERRCONTENTIONLP1_2);
9775 +       PIS(ERRCONTENTIONLP0_3);
9776 +       PIS(ERRCONTENTIONLP1_3);
9777 +       PIS(ULPSACTIVENOT_ALL0);
9778 +       PIS(ULPSACTIVENOT_ALL1);
9779 +#undef PIS
9780 +
9781 +       printk("\n");
9782 +}
9783 +
9784 +static int debug_irq;
9785 +
9786 +/* called from dss */
9787 +void dsi_irq_handler(void)
9788 +{
9789 +       u32 irqstatus, vcstatus, ciostatus;
9790 +       int i;
9791 +
9792 +       irqstatus = dsi_read_reg(DSI_IRQSTATUS);
9793 +
9794 +       if (irqstatus & DSI_IRQ_ERROR_MASK) {
9795 +               DSSERR("DSI error, irqstatus %x\n", irqstatus);
9796 +               print_irq_status(irqstatus);
9797 +               spin_lock(&dsi.errors_lock);
9798 +               dsi.errors |= irqstatus & DSI_IRQ_ERROR_MASK;
9799 +               spin_unlock(&dsi.errors_lock);
9800 +       } else if (debug_irq) {
9801 +               print_irq_status(irqstatus);
9802 +       }
9803 +
9804 +       for (i = 0; i < 4; ++i) {
9805 +               if ((irqstatus & (1<<i)) == 0)
9806 +                       continue;
9807 +
9808 +               vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i));
9809 +
9810 +               if (vcstatus & DSI_VC_IRQ_BTA)
9811 +                       complete(&dsi.bta_completion);
9812 +
9813 +               if (vcstatus & DSI_VC_IRQ_ERROR_MASK) {
9814 +                       DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
9815 +                                      i, vcstatus);
9816 +                       print_irq_status_vc(i, vcstatus);
9817 +               } else if (debug_irq) {
9818 +                       print_irq_status_vc(i, vcstatus);
9819 +               }
9820 +
9821 +               dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus);
9822 +       }
9823 +
9824 +       if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
9825 +               ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
9826 +
9827 +               dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
9828 +
9829 +               DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
9830 +               print_irq_status_cio(ciostatus);
9831 +       }
9832 +
9833 +       dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
9834 +}
9835 +
9836 +
9837 +static void _dsi_initialize_irq(void)
9838 +{
9839 +       u32 l;
9840 +       int i;
9841 +
9842 +       /* disable all interrupts */
9843 +       dsi_write_reg(DSI_IRQENABLE, 0);
9844 +       for (i = 0; i < 4; ++i)
9845 +               dsi_write_reg(DSI_VC_IRQENABLE(i), 0);
9846 +       dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0);
9847 +
9848 +       /* clear interrupt status */
9849 +       l = dsi_read_reg(DSI_IRQSTATUS);
9850 +       dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK);
9851 +
9852 +       for (i = 0; i < 4; ++i) {
9853 +               l = dsi_read_reg(DSI_VC_IRQSTATUS(i));
9854 +               dsi_write_reg(DSI_VC_IRQSTATUS(i), l);
9855 +       }
9856 +
9857 +       l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
9858 +       dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l);
9859 +
9860 +       /* enable error irqs */
9861 +       l = DSI_IRQ_ERROR_MASK;
9862 +       dsi_write_reg(DSI_IRQENABLE, l);
9863 +
9864 +       l = DSI_VC_IRQ_ERROR_MASK;
9865 +       for (i = 0; i < 4; ++i)
9866 +               dsi_write_reg(DSI_VC_IRQENABLE(i), l);
9867 +
9868 +       /* XXX zonda responds incorrectly, causing control error:
9869 +          Exit from LP-ESC mode to LP11 uses wrong transition states on the
9870 +          data lines LP0 and LN0. */
9871 +       dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE,
9872 +                       -1 & (~DSI_CIO_IRQ_ERRCONTROL2));
9873 +}
9874 +
9875 +static u32 dsi_get_errors(void)
9876 +{
9877 +       unsigned long flags;
9878 +       u32 e;
9879 +       spin_lock_irqsave(&dsi.errors_lock, flags);
9880 +       e = dsi.errors;
9881 +       dsi.errors = 0;
9882 +       spin_unlock_irqrestore(&dsi.errors_lock, flags);
9883 +       return e;
9884 +}
9885 +
9886 +static void dsi_vc_enable_bta_irq(int channel)
9887 +{
9888 +       u32 l;
9889 +
9890 +       dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA);
9891 +
9892 +       l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
9893 +       l |= DSI_VC_IRQ_BTA;
9894 +       dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
9895 +}
9896 +
9897 +static void dsi_vc_disable_bta_irq(int channel)
9898 +{
9899 +       u32 l;
9900 +
9901 +       l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
9902 +       l &= ~DSI_VC_IRQ_BTA;
9903 +       dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
9904 +}
9905 +
9906 +/* DSI func clock. this could also be DSI2_PLL_FCLK */
9907 +static inline void enable_clocks(bool enable)
9908 +{
9909 +       if (enable)
9910 +               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
9911 +       else
9912 +               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
9913 +}
9914 +
9915 +/* source clock for DSI PLL. this could also be PCLKFREE */
9916 +static inline void dsi_enable_pll_clock(bool enable)
9917 +{
9918 +       if (enable)
9919 +               dss_clk_enable(DSS_CLK_FCK2);
9920 +       else
9921 +               dss_clk_disable(DSS_CLK_FCK2);
9922 +
9923 +       if (enable && dsi.pll_locked) {
9924 +               if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1)
9925 +                       DSSERR("cannot lock PLL when enabling clocks\n");
9926 +       }
9927 +}
9928 +
9929 +#ifdef DEBUG
9930 +static void _dsi_print_reset_status(void)
9931 +{
9932 +       u32 l;
9933 +
9934 +       if (!dss_debug)
9935 +               return;
9936 +
9937 +       /* A dummy read using the SCP interface to any DSIPHY register is
9938 +        * required after DSIPHY reset to complete the reset of the DSI complex
9939 +        * I/O. */
9940 +       l = dsi_read_reg(DSI_DSIPHY_CFG5);
9941 +
9942 +       printk(KERN_DEBUG "DSI resets: ");
9943 +
9944 +       l = dsi_read_reg(DSI_PLL_STATUS);
9945 +       printk("PLL (%d) ", FLD_GET(l, 0, 0));
9946 +
9947 +       l = dsi_read_reg(DSI_COMPLEXIO_CFG1);
9948 +       printk("CIO (%d) ", FLD_GET(l, 29, 29));
9949 +
9950 +       l = dsi_read_reg(DSI_DSIPHY_CFG5);
9951 +       printk("PHY (%x, %d, %d, %d)\n",
9952 +                       FLD_GET(l, 28, 26),
9953 +                       FLD_GET(l, 29, 29),
9954 +                       FLD_GET(l, 30, 30),
9955 +                       FLD_GET(l, 31, 31));
9956 +}
9957 +#else
9958 +#define _dsi_print_reset_status()
9959 +#endif
9960 +
9961 +static inline int dsi_if_enable(bool enable)
9962 +{
9963 +       DSSDBG("dsi_if_enable(%d)\n", enable);
9964 +
9965 +       enable = enable ? 1 : 0;
9966 +       REG_FLD_MOD(DSI_CTRL, enable, 0, 0); /* IF_EN */
9967 +
9968 +       if (wait_for_bit_change(DSI_CTRL, 0, enable) != enable) {
9969 +                       DSSERR("Failed to set dsi_if_enable to %d\n", enable);
9970 +                       return -EIO;
9971 +       }
9972 +
9973 +       return 0;
9974 +}
9975 +
9976 +static unsigned long dsi_fclk_rate(void)
9977 +{
9978 +       unsigned long r;
9979 +
9980 +       if (dss_get_dsi_clk_source() == 0) {
9981 +               /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */
9982 +               r = dss_clk_get_rate(DSS_CLK_FCK1);
9983 +       } else {
9984 +               /* DSI FCLK source is DSI2_PLL_FCLK */
9985 +               r = dsi.dsi2_pll_fclk;
9986 +       }
9987 +
9988 +       return r;
9989 +}
9990 +
9991 +static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev)
9992 +{
9993 +       unsigned n;
9994 +       unsigned long dsi_fclk;
9995 +       unsigned long lp_clk, lp_clk_req;
9996 +
9997 +       dsi_fclk = dsi_fclk_rate();
9998 +
9999 +       lp_clk_req = dssdev->phy.dsi.lp_clk_hz;
10000 +
10001 +       for (n = 1; n < (1 << 13) - 1; ++n) {
10002 +               lp_clk = dsi_fclk / 2 / n;
10003 +               if (lp_clk <= lp_clk_req)
10004 +                       break;
10005 +       }
10006 +
10007 +       if (n == (1 << 13) - 1) {
10008 +               DSSERR("Failed to find LP_CLK_DIVISOR\n");
10009 +               return -EINVAL;
10010 +       }
10011 +
10012 +       DSSDBG("LP_CLK_DIV %u, LP_CLK %lu (req %lu)\n", n, lp_clk, lp_clk_req);
10013 +
10014 +       REG_FLD_MOD(DSI_CLK_CTRL, n, 12, 0);    /* LP_CLK_DIVISOR */
10015 +       if (dsi_fclk > 30*1000*1000)
10016 +               REG_FLD_MOD(DSI_CLK_CTRL, 1, 21, 21); /* LP_RX_SYNCHRO_ENABLE */
10017 +
10018 +       return 0;
10019 +}
10020 +
10021 +
10022 +enum dsi_pll_power_state {
10023 +       DSI_PLL_POWER_OFF       = 0x0,
10024 +       DSI_PLL_POWER_ON_HSCLK  = 0x1,
10025 +       DSI_PLL_POWER_ON_ALL    = 0x2,
10026 +       DSI_PLL_POWER_ON_DIV    = 0x3,
10027 +};
10028 +
10029 +static int dsi_pll_power(enum dsi_pll_power_state state)
10030 +{
10031 +       int t = 0;
10032 +
10033 +       REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30);       /* PLL_PWR_CMD */
10034 +
10035 +       /* PLL_PWR_STATUS */
10036 +       while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) {
10037 +               udelay(1);
10038 +               if (t++ > 1000) {
10039 +                       DSSERR("Failed to set DSI PLL power mode to %d\n",
10040 +                                       state);
10041 +                       return -ENODEV;
10042 +               }
10043 +       }
10044 +
10045 +       return 0;
10046 +}
10047 +
10048 +int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck,
10049 +               struct dsi_clock_info *cinfo)
10050 +{
10051 +       struct dsi_clock_info cur, best;
10052 +       int min_fck_per_pck;
10053 +       int match = 0;
10054 +       unsigned long dss_clk_fck2;
10055 +
10056 +       dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2);
10057 +
10058 +       if (req_pck == dsi.cache_req_pck &&
10059 +                       dsi.cache_cinfo.clkin == dss_clk_fck2) {
10060 +               DSSDBG("DSI clock info found from cache\n");
10061 +               *cinfo = dsi.cache_cinfo;
10062 +               return 0;
10063 +       }
10064 +
10065 +       min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
10066 +
10067 +       if (min_fck_per_pck &&
10068 +               req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
10069 +               DSSERR("Requested pixel clock not possible with the current "
10070 +                               "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
10071 +                               "the constraint off.\n");
10072 +               min_fck_per_pck = 0;
10073 +       }
10074 +
10075 +       DSSDBG("dsi_pll_calc\n");
10076 +
10077 +retry:
10078 +       memset(&best, 0, sizeof(best));
10079 +
10080 +       memset(&cur, 0, sizeof(cur));
10081 +       cur.clkin = dss_clk_fck2;
10082 +       cur.use_dss2_fck = 1;
10083 +       cur.highfreq = 0;
10084 +
10085 +       /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
10086 +       /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
10087 +       /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
10088 +       for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
10089 +               if (cur.highfreq == 0)
10090 +                       cur.fint = cur.clkin / cur.regn;
10091 +               else
10092 +                       cur.fint = cur.clkin / (2 * cur.regn);
10093 +
10094 +               if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
10095 +                       continue;
10096 +
10097 +               /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
10098 +               for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
10099 +                       unsigned long a, b;
10100 +
10101 +                       a = 2 * cur.regm * (cur.clkin/1000);
10102 +                       b = cur.regn * (cur.highfreq + 1);
10103 +                       cur.dsiphy = a / b * 1000;
10104 +
10105 +                       if (cur.dsiphy > 1800 * 1000 * 1000)
10106 +                               break;
10107 +
10108 +                       /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3  < 173MHz */
10109 +                       for (cur.regm3 = 1; cur.regm3 < REGM3_MAX;
10110 +                                       ++cur.regm3) {
10111 +                               cur.dsi1_pll_fclk = cur.dsiphy / cur.regm3;
10112 +
10113 +                               /* this will narrow down the search a bit,
10114 +                                * but still give pixclocks below what was
10115 +                                * requested */
10116 +                               if (cur.dsi1_pll_fclk  < req_pck)
10117 +                                       break;
10118 +
10119 +                               if (cur.dsi1_pll_fclk > DISPC_MAX_FCK)
10120 +                                       continue;
10121 +
10122 +                               if (min_fck_per_pck &&
10123 +                                       cur.dsi1_pll_fclk <
10124 +                                               req_pck * min_fck_per_pck)
10125 +                                       continue;
10126 +
10127 +                               match = 1;
10128 +
10129 +                               find_lck_pck_divs(is_tft, req_pck,
10130 +                                               cur.dsi1_pll_fclk,
10131 +                                               &cur.lck_div,
10132 +                                               &cur.pck_div);
10133 +
10134 +                               cur.lck = cur.dsi1_pll_fclk / cur.lck_div;
10135 +                               cur.pck = cur.lck / cur.pck_div;
10136 +
10137 +                               if (abs(cur.pck - req_pck) <
10138 +                                               abs(best.pck - req_pck)) {
10139 +                                       best = cur;
10140 +
10141 +                                       if (cur.pck == req_pck)
10142 +                                               goto found;
10143 +                               }
10144 +                       }
10145 +               }
10146 +       }
10147 +found:
10148 +       if (!match) {
10149 +               if (min_fck_per_pck) {
10150 +                       DSSERR("Could not find suitable clock settings.\n"
10151 +                                       "Turning FCK/PCK constraint off and"
10152 +                                       "trying again.\n");
10153 +                       min_fck_per_pck = 0;
10154 +                       goto retry;
10155 +               }
10156 +
10157 +               DSSERR("Could not find suitable clock settings.\n");
10158 +
10159 +               return -EINVAL;
10160 +       }
10161 +
10162 +       /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */
10163 +       best.regm4 = best.dsiphy / 48000000;
10164 +       if (best.regm4 > REGM4_MAX)
10165 +               best.regm4 = REGM4_MAX;
10166 +       else if (best.regm4 == 0)
10167 +               best.regm4 = 1;
10168 +       best.dsi2_pll_fclk = best.dsiphy / best.regm4;
10169 +
10170 +       if (cinfo)
10171 +               *cinfo = best;
10172 +
10173 +       dsi.cache_req_pck = req_pck;
10174 +       dsi.cache_clk_freq = 0;
10175 +       dsi.cache_cinfo = best;
10176 +
10177 +       return 0;
10178 +}
10179 +
10180 +static int dsi_pll_calc_ddrfreq(unsigned long clk_freq,
10181 +               struct dsi_clock_info *cinfo)
10182 +{
10183 +       struct dsi_clock_info cur, best;
10184 +       const bool use_dss2_fck = 1;
10185 +       unsigned long datafreq;
10186 +       unsigned long dss_clk_fck2;
10187 +
10188 +       DSSDBG("dsi_pll_calc_ddrfreq\n");
10189 +
10190 +       dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2);
10191 +
10192 +       if (clk_freq == dsi.cache_clk_freq &&
10193 +                       dsi.cache_cinfo.clkin == dss_clk_fck2) {
10194 +               DSSDBG("DSI clock info found from cache\n");
10195 +               *cinfo = dsi.cache_cinfo;
10196 +               return 0;
10197 +       }
10198 +
10199 +       datafreq = clk_freq * 4;
10200 +
10201 +       memset(&best, 0, sizeof(best));
10202 +
10203 +       memset(&cur, 0, sizeof(cur));
10204 +       cur.use_dss2_fck = use_dss2_fck;
10205 +       if (use_dss2_fck) {
10206 +               cur.clkin = dss_clk_fck2;
10207 +               cur.highfreq = 0;
10208 +       } else {
10209 +               cur.clkin = dispc_pclk_rate();
10210 +               if (cur.clkin < 32000000)
10211 +                       cur.highfreq = 0;
10212 +               else
10213 +                       cur.highfreq = 1;
10214 +       }
10215 +
10216 +       /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
10217 +       /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
10218 +       /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
10219 +       for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
10220 +               if (cur.highfreq == 0)
10221 +                       cur.fint = cur.clkin / cur.regn;
10222 +               else
10223 +                       cur.fint = cur.clkin / (2 * cur.regn);
10224 +
10225 +               if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
10226 +                       continue;
10227 +
10228 +               /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
10229 +               for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
10230 +                       unsigned long a, b;
10231 +
10232 +                       a = 2 * cur.regm * (cur.clkin/1000);
10233 +                       b = cur.regn * (cur.highfreq + 1);
10234 +                       cur.dsiphy = a / b * 1000;
10235 +
10236 +                       if (cur.dsiphy > 1800 * 1000 * 1000)
10237 +                               break;
10238 +
10239 +                       if (abs(cur.dsiphy - datafreq) <
10240 +                                       abs(best.dsiphy - datafreq)) {
10241 +                               best = cur;
10242 +                               /* DSSDBG("best %ld\n", best.dsiphy); */
10243 +                       }
10244 +
10245 +                       if (cur.dsiphy == datafreq)
10246 +                               goto found;
10247 +               }
10248 +       }
10249 +found:
10250 +       /* DSI1_PLL_FCLK (regm3) is not used. Set it to something sane. */
10251 +       best.regm3 = best.dsiphy / 48000000;
10252 +       if (best.regm3 > REGM3_MAX)
10253 +               best.regm3 = REGM3_MAX;
10254 +       else if (best.regm3 == 0)
10255 +               best.regm3 = 1;
10256 +       best.dsi1_pll_fclk = best.dsiphy / best.regm3;
10257 +
10258 +       /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */
10259 +       best.regm4 = best.dsiphy / 48000000;
10260 +       if (best.regm4 > REGM4_MAX)
10261 +               best.regm4 = REGM4_MAX;
10262 +       else if (best.regm4 == 0)
10263 +               best.regm4 = 1;
10264 +       best.dsi2_pll_fclk = best.dsiphy / best.regm4;
10265 +
10266 +       if (cinfo)
10267 +               *cinfo = best;
10268 +
10269 +       dsi.cache_clk_freq = clk_freq;
10270 +       dsi.cache_req_pck = 0;
10271 +       dsi.cache_cinfo = best;
10272 +
10273 +       return 0;
10274 +}
10275 +
10276 +int dsi_pll_program(struct dsi_clock_info *cinfo)
10277 +{
10278 +       int r = 0;
10279 +       u32 l;
10280 +
10281 +       DSSDBG("dsi_pll_program\n");
10282 +
10283 +       dsi.dsiphy = cinfo->dsiphy;
10284 +       dsi.ddr_clk = dsi.dsiphy / 4;
10285 +       dsi.dsi1_pll_fclk = cinfo->dsi1_pll_fclk;
10286 +       dsi.dsi2_pll_fclk = cinfo->dsi2_pll_fclk;
10287 +
10288 +       DSSDBG("DSI Fint %ld\n", cinfo->fint);
10289 +
10290 +       DSSDBG("clkin (%s) rate %ld, highfreq %d\n",
10291 +                       cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree",
10292 +                       cinfo->clkin,
10293 +                       cinfo->highfreq);
10294 +
10295 +       /* DSIPHY == CLKIN4DDR */
10296 +       DSSDBG("DSIPHY = 2 * %d / %d * %lu / %d = %lu\n",
10297 +                       cinfo->regm,
10298 +                       cinfo->regn,
10299 +                       cinfo->clkin,
10300 +                       cinfo->highfreq + 1,
10301 +                       cinfo->dsiphy);
10302 +
10303 +       DSSDBG("Data rate on 1 DSI lane %ld Mbps\n",
10304 +                       dsi.dsiphy / 1000 / 1000 / 2);
10305 +
10306 +       DSSDBG("Clock lane freq %ld Hz\n", dsi.ddr_clk);
10307 +
10308 +       DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n",
10309 +                       cinfo->regm3, cinfo->dsi1_pll_fclk);
10310 +       DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n",
10311 +                       cinfo->regm4, cinfo->dsi2_pll_fclk);
10312 +
10313 +       REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */
10314 +
10315 +       l = dsi_read_reg(DSI_PLL_CONFIGURATION1);
10316 +       l = FLD_MOD(l, 1, 0, 0);                /* DSI_PLL_STOPMODE */
10317 +       l = FLD_MOD(l, cinfo->regn - 1, 7, 1);  /* DSI_PLL_REGN */
10318 +       l = FLD_MOD(l, cinfo->regm, 18, 8);     /* DSI_PLL_REGM */
10319 +       l = FLD_MOD(l, cinfo->regm3 - 1, 22, 19);       /* DSI_CLOCK_DIV */
10320 +       l = FLD_MOD(l, cinfo->regm4 - 1, 26, 23);       /* DSIPROTO_CLOCK_DIV */
10321 +       dsi_write_reg(DSI_PLL_CONFIGURATION1, l);
10322 +
10323 +       l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
10324 +       l = FLD_MOD(l, 7, 4, 1);                /* DSI_PLL_FREQSEL */
10325 +       /* DSI_PLL_CLKSEL */
10326 +       l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1, 11, 11);
10327 +       l = FLD_MOD(l, cinfo->highfreq, 12, 12);        /* DSI_PLL_HIGHFREQ */
10328 +       l = FLD_MOD(l, 1, 13, 13);              /* DSI_PLL_REFEN */
10329 +       l = FLD_MOD(l, 0, 14, 14);              /* DSIPHY_CLKINEN */
10330 +       l = FLD_MOD(l, 1, 20, 20);              /* DSI_HSDIVBYPASS */
10331 +       dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
10332 +
10333 +       REG_FLD_MOD(DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
10334 +
10335 +       if (wait_for_bit_change(DSI_PLL_GO, 0, 0) != 0) {
10336 +               DSSERR("dsi pll go bit not going down.\n");
10337 +               r = -EIO;
10338 +               goto err;
10339 +       }
10340 +
10341 +       if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) {
10342 +               DSSERR("cannot lock PLL\n");
10343 +               r = -EIO;
10344 +               goto err;
10345 +       }
10346 +
10347 +       dsi.pll_locked = 1;
10348 +
10349 +       l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
10350 +       l = FLD_MOD(l, 0, 0, 0);        /* DSI_PLL_IDLE */
10351 +       l = FLD_MOD(l, 0, 5, 5);        /* DSI_PLL_PLLLPMODE */
10352 +       l = FLD_MOD(l, 0, 6, 6);        /* DSI_PLL_LOWCURRSTBY */
10353 +       l = FLD_MOD(l, 0, 7, 7);        /* DSI_PLL_TIGHTPHASELOCK */
10354 +       l = FLD_MOD(l, 0, 8, 8);        /* DSI_PLL_DRIFTGUARDEN */
10355 +       l = FLD_MOD(l, 0, 10, 9);       /* DSI_PLL_LOCKSEL */
10356 +       l = FLD_MOD(l, 1, 13, 13);      /* DSI_PLL_REFEN */
10357 +       l = FLD_MOD(l, 1, 14, 14);      /* DSIPHY_CLKINEN */
10358 +       l = FLD_MOD(l, 0, 15, 15);      /* DSI_BYPASSEN */
10359 +       l = FLD_MOD(l, 1, 16, 16);      /* DSS_CLOCK_EN */
10360 +       l = FLD_MOD(l, 0, 17, 17);      /* DSS_CLOCK_PWDN */
10361 +       l = FLD_MOD(l, 1, 18, 18);      /* DSI_PROTO_CLOCK_EN */
10362 +       l = FLD_MOD(l, 0, 19, 19);      /* DSI_PROTO_CLOCK_PWDN */
10363 +       l = FLD_MOD(l, 0, 20, 20);      /* DSI_HSDIVBYPASS */
10364 +       dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
10365 +
10366 +       DSSDBG("PLL config done\n");
10367 +err:
10368 +       return r;
10369 +}
10370 +
10371 +int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv)
10372 +{
10373 +       int r = 0;
10374 +       enum dsi_pll_power_state pwstate;
10375 +       struct dispc_clock_info cinfo;
10376 +
10377 +       DSSDBG("PLL init\n");
10378 +
10379 +       enable_clocks(1);
10380 +       dsi_enable_pll_clock(1);
10381 +
10382 +       /* XXX this should be calculated depending on the screen size,
10383 +        * required framerate and DSI speed.
10384 +        * For now 48MHz is enough for 864x480@60 with 360Mbps/lane
10385 +        * with two lanes */
10386 +       r = dispc_calc_clock_div(1, 48 * 1000 * 1000, &cinfo);
10387 +       if (r)
10388 +               goto err0;
10389 +
10390 +       r = dispc_set_clock_div(&cinfo);
10391 +       if (r) {
10392 +               DSSERR("Failed to set basic clocks\n");
10393 +               goto err0;
10394 +       }
10395 +
10396 +       r = regulator_enable(dsi.vdds_dsi_reg);
10397 +       if (r)
10398 +               goto err0;
10399 +
10400 +       /* XXX PLL does not come out of reset without this... */
10401 +       dispc_pck_free_enable(1);
10402 +
10403 +       if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) {
10404 +               DSSERR("PLL not coming out of reset.\n");
10405 +               r = -ENODEV;
10406 +               goto err1;
10407 +       }
10408 +
10409 +       /* XXX ... but if left on, we get problems when planes do not
10410 +        * fill the whole display. No idea about this */
10411 +       dispc_pck_free_enable(0);
10412 +
10413 +       if (enable_hsclk && enable_hsdiv)
10414 +               pwstate = DSI_PLL_POWER_ON_ALL;
10415 +       else if (enable_hsclk)
10416 +               pwstate = DSI_PLL_POWER_ON_HSCLK;
10417 +       else if (enable_hsdiv)
10418 +               pwstate = DSI_PLL_POWER_ON_DIV;
10419 +       else
10420 +               pwstate = DSI_PLL_POWER_OFF;
10421 +
10422 +       r = dsi_pll_power(pwstate);
10423 +
10424 +       if (r)
10425 +               goto err1;
10426 +
10427 +       DSSDBG("PLL init done\n");
10428 +
10429 +       return 0;
10430 +err1:
10431 +       regulator_disable(dsi.vdds_dsi_reg);
10432 +err0:
10433 +       enable_clocks(0);
10434 +       dsi_enable_pll_clock(0);
10435 +       return r;
10436 +}
10437 +
10438 +void dsi_pll_uninit(void)
10439 +{
10440 +       enable_clocks(0);
10441 +       dsi_enable_pll_clock(0);
10442 +
10443 +       dsi.pll_locked = 0;
10444 +       dsi_pll_power(DSI_PLL_POWER_OFF);
10445 +       regulator_disable(dsi.vdds_dsi_reg);
10446 +       DSSDBG("PLL uninit done\n");
10447 +}
10448 +
10449 +unsigned long dsi_get_dsi1_pll_rate(void)
10450 +{
10451 +       return dsi.dsi1_pll_fclk;
10452 +}
10453 +
10454 +unsigned long dsi_get_dsi2_pll_rate(void)
10455 +{
10456 +       return dsi.dsi2_pll_fclk;
10457 +}
10458 +
10459 +void dsi_dump_clocks(struct seq_file *s)
10460 +{
10461 +       int clksel;
10462 +
10463 +       enable_clocks(1);
10464 +
10465 +       clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11);
10466 +
10467 +       seq_printf(s, "- dsi -\n");
10468 +
10469 +       seq_printf(s, "dsi fclk source = %s\n",
10470 +                       dss_get_dsi_clk_source() == 0 ?
10471 +                       "dss1_alwon_fclk" : "dsi2_pll_fclk");
10472 +
10473 +       seq_printf(s, "dsi pll source = %s\n",
10474 +                       clksel == 0 ?
10475 +                       "dss2_alwon_fclk" : "pclkfree");
10476 +
10477 +       seq_printf(s,   "DSIPHY\t\t%lu\nDDR_CLK\t\t%lu\n",
10478 +                       dsi.dsiphy, dsi.ddr_clk);
10479 +
10480 +       seq_printf(s,   "dsi1_pll_fck\t%lu (%s)\n"
10481 +                       "dsi2_pll_fck\t%lu (%s)\n",
10482 +                       dsi.dsi1_pll_fclk,
10483 +                       dss_get_dispc_clk_source() == 0 ? "off" : "on",
10484 +                       dsi.dsi2_pll_fclk,
10485 +                       dss_get_dsi_clk_source() == 0 ? "off" : "on");
10486 +
10487 +       enable_clocks(0);
10488 +}
10489 +
10490 +void dsi_dump_regs(struct seq_file *s)
10491 +{
10492 +#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r))
10493 +
10494 +       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
10495 +
10496 +       DUMPREG(DSI_REVISION);
10497 +       DUMPREG(DSI_SYSCONFIG);
10498 +       DUMPREG(DSI_SYSSTATUS);
10499 +       DUMPREG(DSI_IRQSTATUS);
10500 +       DUMPREG(DSI_IRQENABLE);
10501 +       DUMPREG(DSI_CTRL);
10502 +       DUMPREG(DSI_COMPLEXIO_CFG1);
10503 +       DUMPREG(DSI_COMPLEXIO_IRQ_STATUS);
10504 +       DUMPREG(DSI_COMPLEXIO_IRQ_ENABLE);
10505 +       DUMPREG(DSI_CLK_CTRL);
10506 +       DUMPREG(DSI_TIMING1);
10507 +       DUMPREG(DSI_TIMING2);
10508 +       DUMPREG(DSI_VM_TIMING1);
10509 +       DUMPREG(DSI_VM_TIMING2);
10510 +       DUMPREG(DSI_VM_TIMING3);
10511 +       DUMPREG(DSI_CLK_TIMING);
10512 +       DUMPREG(DSI_TX_FIFO_VC_SIZE);
10513 +       DUMPREG(DSI_RX_FIFO_VC_SIZE);
10514 +       DUMPREG(DSI_COMPLEXIO_CFG2);
10515 +       DUMPREG(DSI_RX_FIFO_VC_FULLNESS);
10516 +       DUMPREG(DSI_VM_TIMING4);
10517 +       DUMPREG(DSI_TX_FIFO_VC_EMPTINESS);
10518 +       DUMPREG(DSI_VM_TIMING5);
10519 +       DUMPREG(DSI_VM_TIMING6);
10520 +       DUMPREG(DSI_VM_TIMING7);
10521 +       DUMPREG(DSI_STOPCLK_TIMING);
10522 +
10523 +       DUMPREG(DSI_VC_CTRL(0));
10524 +       DUMPREG(DSI_VC_TE(0));
10525 +       DUMPREG(DSI_VC_LONG_PACKET_HEADER(0));
10526 +       DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(0));
10527 +       DUMPREG(DSI_VC_SHORT_PACKET_HEADER(0));
10528 +       DUMPREG(DSI_VC_IRQSTATUS(0));
10529 +       DUMPREG(DSI_VC_IRQENABLE(0));
10530 +
10531 +       DUMPREG(DSI_VC_CTRL(1));
10532 +       DUMPREG(DSI_VC_TE(1));
10533 +       DUMPREG(DSI_VC_LONG_PACKET_HEADER(1));
10534 +       DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(1));
10535 +       DUMPREG(DSI_VC_SHORT_PACKET_HEADER(1));
10536 +       DUMPREG(DSI_VC_IRQSTATUS(1));
10537 +       DUMPREG(DSI_VC_IRQENABLE(1));
10538 +
10539 +       DUMPREG(DSI_VC_CTRL(2));
10540 +       DUMPREG(DSI_VC_TE(2));
10541 +       DUMPREG(DSI_VC_LONG_PACKET_HEADER(2));
10542 +       DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(2));
10543 +       DUMPREG(DSI_VC_SHORT_PACKET_HEADER(2));
10544 +       DUMPREG(DSI_VC_IRQSTATUS(2));
10545 +       DUMPREG(DSI_VC_IRQENABLE(2));
10546 +
10547 +       DUMPREG(DSI_VC_CTRL(3));
10548 +       DUMPREG(DSI_VC_TE(3));
10549 +       DUMPREG(DSI_VC_LONG_PACKET_HEADER(3));
10550 +       DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(3));
10551 +       DUMPREG(DSI_VC_SHORT_PACKET_HEADER(3));
10552 +       DUMPREG(DSI_VC_IRQSTATUS(3));
10553 +       DUMPREG(DSI_VC_IRQENABLE(3));
10554 +
10555 +       DUMPREG(DSI_DSIPHY_CFG0);
10556 +       DUMPREG(DSI_DSIPHY_CFG1);
10557 +       DUMPREG(DSI_DSIPHY_CFG2);
10558 +       DUMPREG(DSI_DSIPHY_CFG5);
10559 +
10560 +       DUMPREG(DSI_PLL_CONTROL);
10561 +       DUMPREG(DSI_PLL_STATUS);
10562 +       DUMPREG(DSI_PLL_GO);
10563 +       DUMPREG(DSI_PLL_CONFIGURATION1);
10564 +       DUMPREG(DSI_PLL_CONFIGURATION2);
10565 +
10566 +       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
10567 +#undef DUMPREG
10568 +}
10569 +
10570 +enum dsi_complexio_power_state {
10571 +       DSI_COMPLEXIO_POWER_OFF         = 0x0,
10572 +       DSI_COMPLEXIO_POWER_ON          = 0x1,
10573 +       DSI_COMPLEXIO_POWER_ULPS        = 0x2,
10574 +};
10575 +
10576 +static int dsi_complexio_power(enum dsi_complexio_power_state state)
10577 +{
10578 +       int t = 0;
10579 +
10580 +       /* PWR_CMD */
10581 +       REG_FLD_MOD(DSI_COMPLEXIO_CFG1, state, 28, 27);
10582 +
10583 +       /* PWR_STATUS */
10584 +       while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) {
10585 +               udelay(1);
10586 +               if (t++ > 1000) {
10587 +                       DSSERR("failed to set complexio power state to "
10588 +                                       "%d\n", state);
10589 +                       return -ENODEV;
10590 +               }
10591 +       }
10592 +
10593 +       return 0;
10594 +}
10595 +
10596 +static void dsi_complexio_config(struct omap_dss_device *dssdev)
10597 +{
10598 +       u32 r;
10599 +
10600 +       int clk_lane   = dssdev->phy.dsi.clk_lane;
10601 +       int data1_lane = dssdev->phy.dsi.data1_lane;
10602 +       int data2_lane = dssdev->phy.dsi.data2_lane;
10603 +       int clk_pol    = dssdev->phy.dsi.clk_pol;
10604 +       int data1_pol  = dssdev->phy.dsi.data1_pol;
10605 +       int data2_pol  = dssdev->phy.dsi.data2_pol;
10606 +
10607 +       r = dsi_read_reg(DSI_COMPLEXIO_CFG1);
10608 +       r = FLD_MOD(r, clk_lane, 2, 0);
10609 +       r = FLD_MOD(r, clk_pol, 3, 3);
10610 +       r = FLD_MOD(r, data1_lane, 6, 4);
10611 +       r = FLD_MOD(r, data1_pol, 7, 7);
10612 +       r = FLD_MOD(r, data2_lane, 10, 8);
10613 +       r = FLD_MOD(r, data2_pol, 11, 11);
10614 +       dsi_write_reg(DSI_COMPLEXIO_CFG1, r);
10615 +
10616 +       /* The configuration of the DSI complex I/O (number of data lanes,
10617 +          position, differential order) should not be changed while
10618 +          DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for
10619 +          the hardware to take into account a new configuration of the complex
10620 +          I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to
10621 +          follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1,
10622 +          then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set
10623 +          DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the
10624 +          DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the
10625 +          DSI complex I/O configuration is unknown. */
10626 +
10627 +       /*
10628 +       REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
10629 +       REG_FLD_MOD(DSI_CTRL, 0, 0, 0);
10630 +       REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20);
10631 +       REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
10632 +       */
10633 +}
10634 +
10635 +static inline unsigned ns2ddr(unsigned ns)
10636 +{
10637 +       /* convert time in ns to ddr ticks, rounding up */
10638 +       return (ns * (dsi.ddr_clk/1000/1000) + 999) / 1000;
10639 +}
10640 +
10641 +static inline unsigned ddr2ns(unsigned ddr)
10642 +{
10643 +       return ddr * 1000 * 1000 / (dsi.ddr_clk / 1000);
10644 +}
10645 +
10646 +static void dsi_complexio_timings(void)
10647 +{
10648 +       u32 r;
10649 +       u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
10650 +       u32 tlpx_half, tclk_trail, tclk_zero;
10651 +       u32 tclk_prepare;
10652 +
10653 +       /* calculate timings */
10654 +
10655 +       /* 1 * DDR_CLK = 2 * UI */
10656 +
10657 +       /* min 40ns + 4*UI      max 85ns + 6*UI */
10658 +       ths_prepare = ns2ddr(70) + 2;
10659 +
10660 +       /* min 145ns + 10*UI */
10661 +       ths_prepare_ths_zero = ns2ddr(175) + 2;
10662 +
10663 +       /* min max(8*UI, 60ns+4*UI) */
10664 +       ths_trail = ns2ddr(60) + 5;
10665 +
10666 +       /* min 100ns */
10667 +       ths_exit = ns2ddr(145);
10668 +
10669 +       /* tlpx min 50n */
10670 +       tlpx_half = ns2ddr(25);
10671 +
10672 +       /* min 60ns */
10673 +       tclk_trail = ns2ddr(60) + 2;
10674 +
10675 +       /* min 38ns, max 95ns */
10676 +       tclk_prepare = ns2ddr(65);
10677 +
10678 +       /* min tclk-prepare + tclk-zero = 300ns */
10679 +       tclk_zero = ns2ddr(260);
10680 +
10681 +       DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n",
10682 +               ths_prepare, ddr2ns(ths_prepare),
10683 +               ths_prepare_ths_zero, ddr2ns(ths_prepare_ths_zero));
10684 +       DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n",
10685 +                       ths_trail, ddr2ns(ths_trail),
10686 +                       ths_exit, ddr2ns(ths_exit));
10687 +
10688 +       DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), "
10689 +                       "tclk_zero %u (%uns)\n",
10690 +                       tlpx_half, ddr2ns(tlpx_half),
10691 +                       tclk_trail, ddr2ns(tclk_trail),
10692 +                       tclk_zero, ddr2ns(tclk_zero));
10693 +       DSSDBG("tclk_prepare %u (%uns)\n",
10694 +                       tclk_prepare, ddr2ns(tclk_prepare));
10695 +
10696 +       /* program timings */
10697 +
10698 +       r = dsi_read_reg(DSI_DSIPHY_CFG0);
10699 +       r = FLD_MOD(r, ths_prepare, 31, 24);
10700 +       r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16);
10701 +       r = FLD_MOD(r, ths_trail, 15, 8);
10702 +       r = FLD_MOD(r, ths_exit, 7, 0);
10703 +       dsi_write_reg(DSI_DSIPHY_CFG0, r);
10704 +
10705 +       r = dsi_read_reg(DSI_DSIPHY_CFG1);
10706 +       r = FLD_MOD(r, tlpx_half, 22, 16);
10707 +       r = FLD_MOD(r, tclk_trail, 15, 8);
10708 +       r = FLD_MOD(r, tclk_zero, 7, 0);
10709 +       dsi_write_reg(DSI_DSIPHY_CFG1, r);
10710 +
10711 +       r = dsi_read_reg(DSI_DSIPHY_CFG2);
10712 +       r = FLD_MOD(r, tclk_prepare, 7, 0);
10713 +       dsi_write_reg(DSI_DSIPHY_CFG2, r);
10714 +}
10715 +
10716 +
10717 +static int dsi_complexio_init(struct omap_dss_device *dssdev)
10718 +{
10719 +       int r = 0;
10720 +
10721 +       DSSDBG("dsi_complexio_init\n");
10722 +
10723 +       /* CIO_CLK_ICG, enable L3 clk to CIO */
10724 +       REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
10725 +
10726 +       /* A dummy read using the SCP interface to any DSIPHY register is
10727 +        * required after DSIPHY reset to complete the reset of the DSI complex
10728 +        * I/O. */
10729 +       dsi_read_reg(DSI_DSIPHY_CFG5);
10730 +
10731 +       if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) {
10732 +               DSSERR("ComplexIO PHY not coming out of reset.\n");
10733 +               r = -ENODEV;
10734 +               goto err;
10735 +       }
10736 +
10737 +       dsi_complexio_config(dssdev);
10738 +
10739 +       r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON);
10740 +
10741 +       if (r)
10742 +               goto err;
10743 +
10744 +       if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
10745 +               DSSERR("ComplexIO not coming out of reset.\n");
10746 +               r = -ENODEV;
10747 +               goto err;
10748 +       }
10749 +
10750 +       if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
10751 +               DSSERR("ComplexIO LDO power down.\n");
10752 +               r = -ENODEV;
10753 +               goto err;
10754 +       }
10755 +
10756 +       dsi_complexio_timings();
10757 +
10758 +       /*
10759 +          The configuration of the DSI complex I/O (number of data lanes,
10760 +          position, differential order) should not be changed while
10761 +          DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the
10762 +          hardware to recognize a new configuration of the complex I/O (done
10763 +          in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow
10764 +          this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next
10765 +          reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20]
10766 +          LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN
10767 +          bit to 1. If the sequence is not followed, the DSi complex I/O
10768 +          configuration is undetermined.
10769 +          */
10770 +       dsi_if_enable(1);
10771 +       dsi_if_enable(0);
10772 +       REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
10773 +       dsi_if_enable(1);
10774 +       dsi_if_enable(0);
10775 +
10776 +       DSSDBG("CIO init done\n");
10777 +err:
10778 +       return r;
10779 +}
10780 +
10781 +static void dsi_complexio_uninit(void)
10782 +{
10783 +       dsi_complexio_power(DSI_COMPLEXIO_POWER_OFF);
10784 +}
10785 +
10786 +static int _dsi_wait_reset(void)
10787 +{
10788 +       int i = 0;
10789 +
10790 +       while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) {
10791 +               if (i++ > 5) {
10792 +                       DSSERR("soft reset failed\n");
10793 +                       return -ENODEV;
10794 +               }
10795 +               udelay(1);
10796 +       }
10797 +
10798 +       return 0;
10799 +}
10800 +
10801 +static int _dsi_reset(void)
10802 +{
10803 +       /* Soft reset */
10804 +       REG_FLD_MOD(DSI_SYSCONFIG, 1, 1, 1);
10805 +       return _dsi_wait_reset();
10806 +}
10807 +
10808 +
10809 +static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2,
10810 +               enum fifo_size size3, enum fifo_size size4)
10811 +{
10812 +       u32 r = 0;
10813 +       int add = 0;
10814 +       int i;
10815 +
10816 +       dsi.vc[0].fifo_size = size1;
10817 +       dsi.vc[1].fifo_size = size2;
10818 +       dsi.vc[2].fifo_size = size3;
10819 +       dsi.vc[3].fifo_size = size4;
10820 +
10821 +       for (i = 0; i < 4; i++) {
10822 +               u8 v;
10823 +               int size = dsi.vc[i].fifo_size;
10824 +
10825 +               if (add + size > 4) {
10826 +                       DSSERR("Illegal FIFO configuration\n");
10827 +                       BUG();
10828 +               }
10829 +
10830 +               v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
10831 +               r |= v << (8 * i);
10832 +               /*DSSDBG("TX FIFO vc %d: size %d, add %d\n", i, size, add); */
10833 +               add += size;
10834 +       }
10835 +
10836 +       dsi_write_reg(DSI_TX_FIFO_VC_SIZE, r);
10837 +}
10838 +
10839 +static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2,
10840 +               enum fifo_size size3, enum fifo_size size4)
10841 +{
10842 +       u32 r = 0;
10843 +       int add = 0;
10844 +       int i;
10845 +
10846 +       dsi.vc[0].fifo_size = size1;
10847 +       dsi.vc[1].fifo_size = size2;
10848 +       dsi.vc[2].fifo_size = size3;
10849 +       dsi.vc[3].fifo_size = size4;
10850 +
10851 +       for (i = 0; i < 4; i++) {
10852 +               u8 v;
10853 +               int size = dsi.vc[i].fifo_size;
10854 +
10855 +               if (add + size > 4) {
10856 +                       DSSERR("Illegal FIFO configuration\n");
10857 +                       BUG();
10858 +               }
10859 +
10860 +               v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
10861 +               r |= v << (8 * i);
10862 +               /*DSSDBG("RX FIFO vc %d: size %d, add %d\n", i, size, add); */
10863 +               add += size;
10864 +       }
10865 +
10866 +       dsi_write_reg(DSI_RX_FIFO_VC_SIZE, r);
10867 +}
10868 +
10869 +static int dsi_force_tx_stop_mode_io(void)
10870 +{
10871 +       u32 r;
10872 +
10873 +       r = dsi_read_reg(DSI_TIMING1);
10874 +       r = FLD_MOD(r, 1, 15, 15);      /* FORCE_TX_STOP_MODE_IO */
10875 +       dsi_write_reg(DSI_TIMING1, r);
10876 +
10877 +       if (wait_for_bit_change(DSI_TIMING1, 15, 0) != 0) {
10878 +               DSSERR("TX_STOP bit not going down\n");
10879 +               return -EIO;
10880 +       }
10881 +
10882 +       return 0;
10883 +}
10884 +
10885 +static void dsi_vc_print_status(int channel)
10886 +{
10887 +       u32 r;
10888 +
10889 +       r = dsi_read_reg(DSI_VC_CTRL(channel));
10890 +       DSSDBG("vc %d: TX_FIFO_NOT_EMPTY %d, BTA_EN %d, VC_BUSY %d, "
10891 +                       "TX_FIFO_FULL %d, RX_FIFO_NOT_EMPTY %d, ",
10892 +                       channel,
10893 +                       FLD_GET(r, 5, 5),
10894 +                       FLD_GET(r, 6, 6),
10895 +                       FLD_GET(r, 15, 15),
10896 +                       FLD_GET(r, 16, 16),
10897 +                       FLD_GET(r, 20, 20));
10898 +
10899 +       r = dsi_read_reg(DSI_TX_FIFO_VC_EMPTINESS);
10900 +       DSSDBG("EMPTINESS %d\n", (r >> (8 * channel)) & 0xff);
10901 +}
10902 +
10903 +static int dsi_vc_enable(int channel, bool enable)
10904 +{
10905 +       if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
10906 +               DSSDBG("dsi_vc_enable channel %d, enable %d\n",
10907 +                               channel, enable);
10908 +
10909 +       enable = enable ? 1 : 0;
10910 +
10911 +       REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0);
10912 +
10913 +       if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) {
10914 +                       DSSERR("Failed to set dsi_vc_enable to %d\n", enable);
10915 +                       return -EIO;
10916 +       }
10917 +
10918 +       return 0;
10919 +}
10920 +
10921 +static void dsi_vc_initial_config(int channel)
10922 +{
10923 +       u32 r;
10924 +
10925 +       DSSDBGF("%d", channel);
10926 +
10927 +       r = dsi_read_reg(DSI_VC_CTRL(channel));
10928 +
10929 +       if (FLD_GET(r, 15, 15)) /* VC_BUSY */
10930 +               DSSERR("VC(%d) busy when trying to configure it!\n",
10931 +                               channel);
10932 +
10933 +       r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */
10934 +       r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN  */
10935 +       r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
10936 +       r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
10937 +       r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
10938 +       r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
10939 +       r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
10940 +
10941 +       r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
10942 +       r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
10943 +
10944 +       dsi_write_reg(DSI_VC_CTRL(channel), r);
10945 +
10946 +       dsi.vc[channel].mode = DSI_VC_MODE_L4;
10947 +}
10948 +
10949 +static void dsi_vc_config_l4(int channel)
10950 +{
10951 +       if (dsi.vc[channel].mode == DSI_VC_MODE_L4)
10952 +               return;
10953 +
10954 +       DSSDBGF("%d", channel);
10955 +
10956 +       dsi_vc_enable(channel, 0);
10957 +
10958 +       if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */
10959 +               DSSERR("vc(%d) busy when trying to config for L4\n", channel);
10960 +
10961 +       REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
10962 +
10963 +       dsi_vc_enable(channel, 1);
10964 +
10965 +       dsi.vc[channel].mode = DSI_VC_MODE_L4;
10966 +}
10967 +
10968 +static void dsi_vc_config_vp(int channel)
10969 +{
10970 +       if (dsi.vc[channel].mode == DSI_VC_MODE_VP)
10971 +               return;
10972 +
10973 +       DSSDBGF("%d", channel);
10974 +
10975 +       dsi_vc_enable(channel, 0);
10976 +
10977 +       if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */
10978 +               DSSERR("vc(%d) busy when trying to config for VP\n", channel);
10979 +
10980 +       REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */
10981 +
10982 +       dsi_vc_enable(channel, 1);
10983 +
10984 +       dsi.vc[channel].mode = DSI_VC_MODE_VP;
10985 +}
10986 +
10987 +
10988 +static void dsi_vc_enable_hs(int channel, bool enable)
10989 +{
10990 +       DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
10991 +
10992 +       dsi_vc_enable(channel, 0);
10993 +       dsi_if_enable(0);
10994 +
10995 +       REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 9, 9);
10996 +
10997 +       dsi_vc_enable(channel, 1);
10998 +       dsi_if_enable(1);
10999 +
11000 +       dsi_force_tx_stop_mode_io();
11001 +}
11002 +
11003 +static void dsi_vc_flush_long_data(int channel)
11004 +{
11005 +       while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
11006 +               u32 val;
11007 +               val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
11008 +               DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n",
11009 +                               (val >> 0) & 0xff,
11010 +                               (val >> 8) & 0xff,
11011 +                               (val >> 16) & 0xff,
11012 +                               (val >> 24) & 0xff);
11013 +       }
11014 +}
11015 +
11016 +static void dsi_show_rx_ack_with_err(u16 err)
11017 +{
11018 +       DSSERR("\tACK with ERROR (%#x):\n", err);
11019 +       if (err & (1 << 0))
11020 +               DSSERR("\t\tSoT Error\n");
11021 +       if (err & (1 << 1))
11022 +               DSSERR("\t\tSoT Sync Error\n");
11023 +       if (err & (1 << 2))
11024 +               DSSERR("\t\tEoT Sync Error\n");
11025 +       if (err & (1 << 3))
11026 +               DSSERR("\t\tEscape Mode Entry Command Error\n");
11027 +       if (err & (1 << 4))
11028 +               DSSERR("\t\tLP Transmit Sync Error\n");
11029 +       if (err & (1 << 5))
11030 +               DSSERR("\t\tHS Receive Timeout Error\n");
11031 +       if (err & (1 << 6))
11032 +               DSSERR("\t\tFalse Control Error\n");
11033 +       if (err & (1 << 7))
11034 +               DSSERR("\t\t(reserved7)\n");
11035 +       if (err & (1 << 8))
11036 +               DSSERR("\t\tECC Error, single-bit (corrected)\n");
11037 +       if (err & (1 << 9))
11038 +               DSSERR("\t\tECC Error, multi-bit (not corrected)\n");
11039 +       if (err & (1 << 10))
11040 +               DSSERR("\t\tChecksum Error\n");
11041 +       if (err & (1 << 11))
11042 +               DSSERR("\t\tData type not recognized\n");
11043 +       if (err & (1 << 12))
11044 +               DSSERR("\t\tInvalid VC ID\n");
11045 +       if (err & (1 << 13))
11046 +               DSSERR("\t\tInvalid Transmission Length\n");
11047 +       if (err & (1 << 14))
11048 +               DSSERR("\t\t(reserved14)\n");
11049 +       if (err & (1 << 15))
11050 +               DSSERR("\t\tDSI Protocol Violation\n");
11051 +}
11052 +
11053 +static u16 dsi_vc_flush_receive_data(int channel)
11054 +{
11055 +       /* RX_FIFO_NOT_EMPTY */
11056 +       while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
11057 +               u32 val;
11058 +               u8 dt;
11059 +               val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
11060 +               DSSDBG("\trawval %#08x\n", val);
11061 +               dt = FLD_GET(val, 5, 0);
11062 +               if (dt == DSI_DT_RX_ACK_WITH_ERR) {
11063 +                       u16 err = FLD_GET(val, 23, 8);
11064 +                       dsi_show_rx_ack_with_err(err);
11065 +               } else if (dt == DSI_DT_RX_SHORT_READ_1) {
11066 +                       DSSDBG("\tDCS short response, 1 byte: %#x\n",
11067 +                                       FLD_GET(val, 23, 8));
11068 +               } else if (dt == DSI_DT_RX_SHORT_READ_2) {
11069 +                       DSSDBG("\tDCS short response, 2 byte: %#x\n",
11070 +                                       FLD_GET(val, 23, 8));
11071 +               } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
11072 +                       DSSDBG("\tDCS long response, len %d\n",
11073 +                                       FLD_GET(val, 23, 8));
11074 +                       dsi_vc_flush_long_data(channel);
11075 +               } else {
11076 +                       DSSERR("\tunknown datatype 0x%02x\n", dt);
11077 +               }
11078 +       }
11079 +       return 0;
11080 +}
11081 +
11082 +static int dsi_vc_send_bta(int channel)
11083 +{
11084 +       if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO &&
11085 +                       (dsi.debug_write || dsi.debug_read))
11086 +               DSSDBG("dsi_vc_send_bta %d\n", channel);
11087 +
11088 +       WARN_ON(!mutex_is_locked(&dsi.bus_lock));
11089 +
11090 +       if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {    /* RX_FIFO_NOT_EMPTY */
11091 +               DSSERR("rx fifo not empty when sending BTA, dumping data:\n");
11092 +               dsi_vc_flush_receive_data(channel);
11093 +       }
11094 +
11095 +       REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
11096 +
11097 +       return 0;
11098 +}
11099 +
11100 +int dsi_vc_send_bta_sync(int channel)
11101 +{
11102 +       int r = 0;
11103 +       u32 err;
11104 +
11105 +       INIT_COMPLETION(dsi.bta_completion);
11106 +
11107 +       dsi_vc_enable_bta_irq(channel);
11108 +
11109 +       r = dsi_vc_send_bta(channel);
11110 +       if (r)
11111 +               goto err;
11112 +
11113 +       if (wait_for_completion_timeout(&dsi.bta_completion,
11114 +                               msecs_to_jiffies(500)) == 0) {
11115 +               DSSERR("Failed to receive BTA\n");
11116 +               r = -EIO;
11117 +               goto err;
11118 +       }
11119 +
11120 +       err = dsi_get_errors();
11121 +       if (err) {
11122 +               DSSERR("Error while sending BTA: %x\n", err);
11123 +               r = -EIO;
11124 +               goto err;
11125 +       }
11126 +err:
11127 +       dsi_vc_disable_bta_irq(channel);
11128 +
11129 +       return r;
11130 +}
11131 +EXPORT_SYMBOL(dsi_vc_send_bta_sync);
11132 +
11133 +static inline void dsi_vc_write_long_header(int channel, u8 data_type,
11134 +               u16 len, u8 ecc)
11135 +{
11136 +       u32 val;
11137 +       u8 data_id;
11138 +
11139 +       WARN_ON(!mutex_is_locked(&dsi.bus_lock));
11140 +
11141 +       /*data_id = data_type | channel << 6; */
11142 +       data_id = data_type | dsi.vc[channel].dest_per << 6;
11143 +
11144 +       val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
11145 +               FLD_VAL(ecc, 31, 24);
11146 +
11147 +       dsi_write_reg(DSI_VC_LONG_PACKET_HEADER(channel), val);
11148 +}
11149 +
11150 +static inline void dsi_vc_write_long_payload(int channel,
11151 +               u8 b1, u8 b2, u8 b3, u8 b4)
11152 +{
11153 +       u32 val;
11154 +
11155 +       val = b4 << 24 | b3 << 16 | b2 << 8  | b1 << 0;
11156 +
11157 +/*     DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n",
11158 +                       b1, b2, b3, b4, val); */
11159 +
11160 +       dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(channel), val);
11161 +}
11162 +
11163 +static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len,
11164 +               u8 ecc)
11165 +{
11166 +       /*u32 val; */
11167 +       int i;
11168 +       u8 *p;
11169 +       int r = 0;
11170 +       u8 b1, b2, b3, b4;
11171 +
11172 +       if (dsi.debug_write)
11173 +               DSSDBG("dsi_vc_send_long, %d bytes\n", len);
11174 +
11175 +       /* len + header */
11176 +       if (dsi.vc[channel].fifo_size * 32 * 4 < len + 4) {
11177 +               DSSERR("unable to send long packet: packet too long.\n");
11178 +               return -EINVAL;
11179 +       }
11180 +
11181 +       dsi_vc_config_l4(channel);
11182 +
11183 +       dsi_vc_write_long_header(channel, data_type, len, ecc);
11184 +
11185 +       /*dsi_vc_print_status(0); */
11186 +
11187 +       p = data;
11188 +       for (i = 0; i < len >> 2; i++) {
11189 +               if (dsi.debug_write)
11190 +                       DSSDBG("\tsending full packet %d\n", i);
11191 +               /*dsi_vc_print_status(0); */
11192 +
11193 +               b1 = *p++;
11194 +               b2 = *p++;
11195 +               b3 = *p++;
11196 +               b4 = *p++;
11197 +
11198 +               dsi_vc_write_long_payload(channel, b1, b2, b3, b4);
11199 +       }
11200 +
11201 +       i = len % 4;
11202 +       if (i) {
11203 +               b1 = 0; b2 = 0; b3 = 0;
11204 +
11205 +               if (dsi.debug_write)
11206 +                       DSSDBG("\tsending remainder bytes %d\n", i);
11207 +
11208 +               switch (i) {
11209 +               case 3:
11210 +                       b1 = *p++;
11211 +                       b2 = *p++;
11212 +                       b3 = *p++;
11213 +                       break;
11214 +               case 2:
11215 +                       b1 = *p++;
11216 +                       b2 = *p++;
11217 +                       break;
11218 +               case 1:
11219 +                       b1 = *p++;
11220 +                       break;
11221 +               }
11222 +
11223 +               dsi_vc_write_long_payload(channel, b1, b2, b3, 0);
11224 +       }
11225 +
11226 +       return r;
11227 +}
11228 +
11229 +static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc)
11230 +{
11231 +       u32 r;
11232 +       u8 data_id;
11233 +
11234 +       WARN_ON(!mutex_is_locked(&dsi.bus_lock));
11235 +
11236 +       if (dsi.debug_write)
11237 +               DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
11238 +                               channel,
11239 +                               data_type, data & 0xff, (data >> 8) & 0xff);
11240 +
11241 +       dsi_vc_config_l4(channel);
11242 +
11243 +       if (FLD_GET(dsi_read_reg(DSI_VC_CTRL(channel)), 16, 16)) {
11244 +               DSSERR("ERROR FIFO FULL, aborting transfer\n");
11245 +               return -EINVAL;
11246 +       }
11247 +
11248 +       data_id = data_type | channel << 6;
11249 +
11250 +       r = (data_id << 0) | (data << 8) | (ecc << 24);
11251 +
11252 +       dsi_write_reg(DSI_VC_SHORT_PACKET_HEADER(channel), r);
11253 +
11254 +       return 0;
11255 +}
11256 +
11257 +int dsi_vc_send_null(int channel)
11258 +{
11259 +       u8 nullpkg[] = {0, 0, 0, 0};
11260 +       return dsi_vc_send_long(0, DSI_DT_NULL_PACKET, nullpkg, 4, 0);
11261 +}
11262 +EXPORT_SYMBOL(dsi_vc_send_null);
11263 +
11264 +int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len)
11265 +{
11266 +       int r;
11267 +
11268 +       BUG_ON(len == 0);
11269 +
11270 +       if (len == 1) {
11271 +               r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_0,
11272 +                               data[0], 0);
11273 +       } else if (len == 2) {
11274 +               r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_1,
11275 +                               data[0] | (data[1] << 8), 0);
11276 +       } else {
11277 +               /* 0x39 = DCS Long Write */
11278 +               r = dsi_vc_send_long(channel, DSI_DT_DCS_LONG_WRITE,
11279 +                               data, len, 0);
11280 +       }
11281 +
11282 +       return r;
11283 +}
11284 +EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
11285 +
11286 +int dsi_vc_dcs_write(int channel, u8 *data, int len)
11287 +{
11288 +       int r;
11289 +
11290 +       r = dsi_vc_dcs_write_nosync(channel, data, len);
11291 +       if (r)
11292 +               return r;
11293 +
11294 +       r = dsi_vc_send_bta_sync(channel);
11295 +
11296 +       return r;
11297 +}
11298 +EXPORT_SYMBOL(dsi_vc_dcs_write);
11299 +
11300 +int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
11301 +{
11302 +       u32 val;
11303 +       u8 dt;
11304 +       int r;
11305 +
11306 +       if (dsi.debug_read)
11307 +               DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %u)\n", channel, dcs_cmd);
11308 +
11309 +       r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0);
11310 +       if (r)
11311 +               return r;
11312 +
11313 +       r = dsi_vc_send_bta_sync(channel);
11314 +       if (r)
11315 +               return r;
11316 +
11317 +       /* RX_FIFO_NOT_EMPTY */
11318 +       if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) {
11319 +               DSSERR("RX fifo empty when trying to read.\n");
11320 +               return -EIO;
11321 +       }
11322 +
11323 +       val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
11324 +       if (dsi.debug_read)
11325 +               DSSDBG("\theader: %08x\n", val);
11326 +       dt = FLD_GET(val, 5, 0);
11327 +       if (dt == DSI_DT_RX_ACK_WITH_ERR) {
11328 +               u16 err = FLD_GET(val, 23, 8);
11329 +               dsi_show_rx_ack_with_err(err);
11330 +               return -EIO;
11331 +
11332 +       } else if (dt == DSI_DT_RX_SHORT_READ_1) {
11333 +               u8 data = FLD_GET(val, 15, 8);
11334 +               if (dsi.debug_read)
11335 +                       DSSDBG("\tDCS short response, 1 byte: %02x\n", data);
11336 +
11337 +               if (buflen < 1)
11338 +                       return -EIO;
11339 +
11340 +               buf[0] = data;
11341 +
11342 +               return 1;
11343 +       } else if (dt == DSI_DT_RX_SHORT_READ_2) {
11344 +               u16 data = FLD_GET(val, 23, 8);
11345 +               if (dsi.debug_read)
11346 +                       DSSDBG("\tDCS short response, 2 byte: %04x\n", data);
11347 +
11348 +               if (buflen < 2)
11349 +                       return -EIO;
11350 +
11351 +               buf[0] = data & 0xff;
11352 +               buf[1] = (data >> 8) & 0xff;
11353 +
11354 +               return 2;
11355 +       } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
11356 +               int w;
11357 +               int len = FLD_GET(val, 23, 8);
11358 +               if (dsi.debug_read)
11359 +                       DSSDBG("\tDCS long response, len %d\n", len);
11360 +
11361 +               if (len > buflen)
11362 +                       return -EIO;
11363 +
11364 +               /* two byte checksum ends the packet, not included in len */
11365 +               for (w = 0; w < len + 2;) {
11366 +                       int b;
11367 +                       val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
11368 +                       if (dsi.debug_read)
11369 +                               DSSDBG("\t\t%02x %02x %02x %02x\n",
11370 +                                               (val >> 0) & 0xff,
11371 +                                               (val >> 8) & 0xff,
11372 +                                               (val >> 16) & 0xff,
11373 +                                               (val >> 24) & 0xff);
11374 +
11375 +                       for (b = 0; b < 4; ++b) {
11376 +                               if (w < len)
11377 +                                       buf[w] = (val >> (b * 8)) & 0xff;
11378 +                               /* we discard the 2 byte checksum */
11379 +                               ++w;
11380 +                       }
11381 +               }
11382 +
11383 +               return len;
11384 +
11385 +       } else {
11386 +               DSSERR("\tunknown datatype 0x%02x\n", dt);
11387 +               return -EIO;
11388 +       }
11389 +}
11390 +EXPORT_SYMBOL(dsi_vc_dcs_read);
11391 +
11392 +
11393 +int dsi_vc_set_max_rx_packet_size(int channel, u16 len)
11394 +{
11395 +       return dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
11396 +                       len, 0);
11397 +}
11398 +EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
11399 +
11400 +
11401 +static int dsi_set_lp_rx_timeout(int ns, int x4, int x16)
11402 +{
11403 +       u32 r;
11404 +       unsigned long fck;
11405 +       int ticks;
11406 +
11407 +       /* ticks in DSI_FCK */
11408 +
11409 +       fck = dsi_fclk_rate();
11410 +       ticks = (fck / 1000 / 1000) * ns / 1000;
11411 +
11412 +       if (ticks > 0x1fff) {
11413 +               DSSERR("LP_TX_TO too high\n");
11414 +               return -EINVAL;
11415 +       }
11416 +
11417 +       r = dsi_read_reg(DSI_TIMING2);
11418 +       r = FLD_MOD(r, 1, 15, 15);      /* LP_RX_TO */
11419 +       r = FLD_MOD(r, x16, 14, 14);    /* LP_RX_TO_X16 */
11420 +       r = FLD_MOD(r, x4, 13, 13);     /* LP_RX_TO_X4 */
11421 +       r = FLD_MOD(r, ticks, 12, 0);   /* LP_RX_COUNTER */
11422 +       dsi_write_reg(DSI_TIMING2, r);
11423 +
11424 +       DSSDBG("LP_RX_TO %ld ns (%#x ticks)\n",
11425 +                       (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
11426 +                       (fck / 1000 / 1000),
11427 +                       ticks);
11428 +
11429 +       return 0;
11430 +}
11431 +
11432 +static int dsi_set_ta_timeout(int ns, int x8, int x16)
11433 +{
11434 +       u32 r;
11435 +       unsigned long fck;
11436 +       int ticks;
11437 +
11438 +       /* ticks in DSI_FCK */
11439 +
11440 +       fck = dsi_fclk_rate();
11441 +       ticks = (fck / 1000 / 1000) * ns / 1000;
11442 +
11443 +       if (ticks > 0x1fff) {
11444 +               DSSERR("TA_TO too high\n");
11445 +               return -EINVAL;
11446 +       }
11447 +
11448 +       r = dsi_read_reg(DSI_TIMING1);
11449 +       r = FLD_MOD(r, 1, 31, 31);      /* TA_TO */
11450 +       r = FLD_MOD(r, x16, 30, 30);    /* TA_TO_X16 */
11451 +       r = FLD_MOD(r, x8, 29, 29);     /* TA_TO_X8 */
11452 +       r = FLD_MOD(r, ticks, 28, 16);  /* TA_TO_COUNTER */
11453 +       dsi_write_reg(DSI_TIMING1, r);
11454 +
11455 +       DSSDBG("TA_TO %ld ns (%#x ticks)\n",
11456 +                       (ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1) * 1000) /
11457 +                       (fck / 1000 / 1000),
11458 +                       ticks);
11459 +
11460 +       return 0;
11461 +}
11462 +
11463 +static int dsi_set_stop_state_counter(int ns, int x4, int x16)
11464 +{
11465 +       u32 r;
11466 +       unsigned long fck;
11467 +       int ticks;
11468 +
11469 +       /* ticks in DSI_FCK */
11470 +
11471 +       fck = dsi_fclk_rate();
11472 +       ticks = (fck / 1000 / 1000) * ns / 1000;
11473 +
11474 +       if (ticks > 0x1fff) {
11475 +               DSSERR("STOP_STATE_COUNTER_IO too high\n");
11476 +               return -EINVAL;
11477 +       }
11478 +
11479 +       r = dsi_read_reg(DSI_TIMING1);
11480 +       r = FLD_MOD(r, 1, 15, 15);      /* FORCE_TX_STOP_MODE_IO */
11481 +       r = FLD_MOD(r, x16, 14, 14);    /* STOP_STATE_X16_IO */
11482 +       r = FLD_MOD(r, x4, 13, 13);     /* STOP_STATE_X4_IO */
11483 +       r = FLD_MOD(r, ticks, 12, 0);   /* STOP_STATE_COUNTER_IO */
11484 +       dsi_write_reg(DSI_TIMING1, r);
11485 +
11486 +       DSSDBG("STOP_STATE_COUNTER %ld ns (%#x ticks)\n",
11487 +                       (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
11488 +                       (fck / 1000 / 1000),
11489 +                       ticks);
11490 +
11491 +       return 0;
11492 +}
11493 +
11494 +static int dsi_set_hs_tx_timeout(int ns, int x4, int x16)
11495 +{
11496 +       u32 r;
11497 +       unsigned long fck;
11498 +       int ticks;
11499 +
11500 +       /* ticks in TxByteClkHS */
11501 +
11502 +       fck = dsi.ddr_clk / 4;
11503 +       ticks = (fck / 1000 / 1000) * ns / 1000;
11504 +
11505 +       if (ticks > 0x1fff) {
11506 +               DSSERR("HS_TX_TO too high\n");
11507 +               return -EINVAL;
11508 +       }
11509 +
11510 +       r = dsi_read_reg(DSI_TIMING2);
11511 +       r = FLD_MOD(r, 1, 31, 31);      /* HS_TX_TO */
11512 +       r = FLD_MOD(r, x16, 30, 30);    /* HS_TX_TO_X16 */
11513 +       r = FLD_MOD(r, x4, 29, 29);     /* HS_TX_TO_X8 (4 really) */
11514 +       r = FLD_MOD(r, ticks, 28, 16);  /* HS_TX_TO_COUNTER */
11515 +       dsi_write_reg(DSI_TIMING2, r);
11516 +
11517 +       DSSDBG("HS_TX_TO %ld ns (%#x ticks)\n",
11518 +                       (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
11519 +                       (fck / 1000 / 1000),
11520 +                       ticks);
11521 +
11522 +       return 0;
11523 +}
11524 +static int dsi_proto_config(struct omap_dss_device *dssdev)
11525 +{
11526 +       u32 r;
11527 +       int buswidth = 0;
11528 +       int div;
11529 +
11530 +       dsi_config_tx_fifo(DSI_FIFO_SIZE_128,
11531 +                       DSI_FIFO_SIZE_0,
11532 +                       DSI_FIFO_SIZE_0,
11533 +                       DSI_FIFO_SIZE_0);
11534 +
11535 +       dsi_config_rx_fifo(DSI_FIFO_SIZE_128,
11536 +                       DSI_FIFO_SIZE_0,
11537 +                       DSI_FIFO_SIZE_0,
11538 +                       DSI_FIFO_SIZE_0);
11539 +
11540 +       /* XXX what values for the timeouts? */
11541 +       dsi_set_stop_state_counter(1000, 0, 0);
11542 +
11543 +       dsi_set_ta_timeout(50000, 1, 1);
11544 +
11545 +       /* 3000ns * 16 */
11546 +       dsi_set_lp_rx_timeout(3000, 0, 1);
11547 +
11548 +       /* 10000ns * 4 */
11549 +       dsi_set_hs_tx_timeout(10000, 1, 0);
11550 +
11551 +       switch (dssdev->ctrl.pixel_size) {
11552 +       case 16:
11553 +               buswidth = 0;
11554 +               break;
11555 +       case 18:
11556 +               buswidth = 1;
11557 +               break;
11558 +       case 24:
11559 +               buswidth = 2;
11560 +               break;
11561 +       default:
11562 +               BUG();
11563 +       }
11564 +
11565 +       r = dsi_read_reg(DSI_CTRL);
11566 +       r = FLD_MOD(r, 1, 1, 1);        /* CS_RX_EN */
11567 +       r = FLD_MOD(r, 1, 2, 2);        /* ECC_RX_EN */
11568 +       r = FLD_MOD(r, 1, 3, 3);        /* TX_FIFO_ARBITRATION */
11569 +
11570 +       div = dispc_lclk_rate() / dispc_pclk_rate();
11571 +       r = FLD_MOD(r, div == 2 ? 0 : 1, 4, 4); /* VP_CLK_RATIO */
11572 +       r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
11573 +       r = FLD_MOD(r, 0, 8, 8);        /* VP_CLK_POL */
11574 +       r = FLD_MOD(r, 2, 13, 12);      /* LINE_BUFFER, 2 lines */
11575 +       r = FLD_MOD(r, 1, 14, 14);      /* TRIGGER_RESET_MODE */
11576 +       r = FLD_MOD(r, 1, 19, 19);      /* EOT_ENABLE */
11577 +       r = FLD_MOD(r, 1, 24, 24);      /* DCS_CMD_ENABLE */
11578 +       r = FLD_MOD(r, 0, 25, 25);      /* DCS_CMD_CODE, 1=start, 0=continue */
11579 +
11580 +       dsi_write_reg(DSI_CTRL, r);
11581 +
11582 +       dsi_vc_initial_config(0);
11583 +
11584 +       /* set all vc targets to peripheral 0 */
11585 +       dsi.vc[0].dest_per = 0;
11586 +       dsi.vc[1].dest_per = 0;
11587 +       dsi.vc[2].dest_per = 0;
11588 +       dsi.vc[3].dest_per = 0;
11589 +
11590 +       return 0;
11591 +}
11592 +
11593 +static void dsi_proto_timings(struct omap_dss_device *dssdev)
11594 +{
11595 +       unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
11596 +       unsigned tclk_pre, tclk_post;
11597 +       unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
11598 +       unsigned ths_trail, ths_exit;
11599 +       unsigned ddr_clk_pre, ddr_clk_post;
11600 +       unsigned enter_hs_mode_lat, exit_hs_mode_lat;
11601 +       unsigned ths_eot;
11602 +       u32 r;
11603 +
11604 +       r = dsi_read_reg(DSI_DSIPHY_CFG0);
11605 +       ths_prepare = FLD_GET(r, 31, 24);
11606 +       ths_prepare_ths_zero = FLD_GET(r, 23, 16);
11607 +       ths_zero = ths_prepare_ths_zero - ths_prepare;
11608 +       ths_trail = FLD_GET(r, 15, 8);
11609 +       ths_exit = FLD_GET(r, 7, 0);
11610 +
11611 +       r = dsi_read_reg(DSI_DSIPHY_CFG1);
11612 +       tlpx = FLD_GET(r, 22, 16) * 2;
11613 +       tclk_trail = FLD_GET(r, 15, 8);
11614 +       tclk_zero = FLD_GET(r, 7, 0);
11615 +
11616 +       r = dsi_read_reg(DSI_DSIPHY_CFG2);
11617 +       tclk_prepare = FLD_GET(r, 7, 0);
11618 +
11619 +       /* min 8*UI */
11620 +       tclk_pre = 20;
11621 +       /* min 60ns + 52*UI */
11622 +       tclk_post = ns2ddr(60) + 26;
11623 +
11624 +       /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */
11625 +       if (dssdev->phy.dsi.data1_lane != 0 &&
11626 +                       dssdev->phy.dsi.data2_lane != 0)
11627 +               ths_eot = 2;
11628 +       else
11629 +               ths_eot = 4;
11630 +
11631 +       ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
11632 +                       4);
11633 +       ddr_clk_post = DIV_ROUND_UP(tclk_post + tclk_trail, 4) + ths_eot;
11634 +
11635 +       BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255);
11636 +       BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255);
11637 +
11638 +       r = dsi_read_reg(DSI_CLK_TIMING);
11639 +       r = FLD_MOD(r, ddr_clk_pre, 15, 8);
11640 +       r = FLD_MOD(r, ddr_clk_post, 7, 0);
11641 +       dsi_write_reg(DSI_CLK_TIMING, r);
11642 +
11643 +       DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n",
11644 +                       ddr_clk_pre,
11645 +                       ddr_clk_post);
11646 +
11647 +       enter_hs_mode_lat = 1 + DIV_ROUND_UP(tlpx, 4) +
11648 +               DIV_ROUND_UP(ths_prepare, 4) +
11649 +               DIV_ROUND_UP(ths_zero + 3, 4);
11650 +
11651 +       exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot;
11652 +
11653 +       r = FLD_VAL(enter_hs_mode_lat, 31, 16) |
11654 +               FLD_VAL(exit_hs_mode_lat, 15, 0);
11655 +       dsi_write_reg(DSI_VM_TIMING7, r);
11656 +
11657 +       DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
11658 +                       enter_hs_mode_lat, exit_hs_mode_lat);
11659 +}
11660 +
11661 +
11662 +#define DSI_DECL_VARS \
11663 +       int __dsi_cb = 0; u32 __dsi_cv = 0;
11664 +
11665 +#define DSI_FLUSH(ch) \
11666 +       if (__dsi_cb > 0) { \
11667 +               /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \
11668 +               dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \
11669 +               __dsi_cb = __dsi_cv = 0; \
11670 +       }
11671 +
11672 +#define DSI_PUSH(ch, data) \
11673 +       do { \
11674 +               __dsi_cv |= (data) << (__dsi_cb * 8); \
11675 +               /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \
11676 +               if (++__dsi_cb > 3) \
11677 +                       DSI_FLUSH(ch); \
11678 +       } while (0)
11679 +
11680 +static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
11681 +                       int x, int y, int w, int h)
11682 +{
11683 +       /* Note: supports only 24bit colors in 32bit container */
11684 +       int first = 1;
11685 +       int fifo_stalls = 0;
11686 +       int max_dsi_packet_size;
11687 +       int max_data_per_packet;
11688 +       int max_pixels_per_packet;
11689 +       int pixels_left;
11690 +       int bytespp = dssdev->ctrl.pixel_size / 8;
11691 +       int scr_width;
11692 +       u32 __iomem *data;
11693 +       int start_offset;
11694 +       int horiz_inc;
11695 +       int current_x;
11696 +       struct omap_overlay *ovl;
11697 +
11698 +       debug_irq = 0;
11699 +
11700 +       DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n",
11701 +                       x, y, w, h);
11702 +
11703 +       ovl = dssdev->manager->overlays[0];
11704 +
11705 +       if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U)
11706 +               return -EINVAL;
11707 +
11708 +       if (dssdev->ctrl.pixel_size != 24)
11709 +               return -EINVAL;
11710 +
11711 +       scr_width = ovl->info.screen_width;
11712 +       data = ovl->info.vaddr;
11713 +
11714 +       start_offset = scr_width * y + x;
11715 +       horiz_inc = scr_width - w;
11716 +       current_x = x;
11717 +
11718 +       /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes
11719 +        * in fifo */
11720 +
11721 +       /* When using CPU, max long packet size is TX buffer size */
11722 +       max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4;
11723 +
11724 +       /* we seem to get better perf if we divide the tx fifo to half,
11725 +          and while the other half is being sent, we fill the other half
11726 +          max_dsi_packet_size /= 2; */
11727 +
11728 +       max_data_per_packet = max_dsi_packet_size - 4 - 1;
11729 +
11730 +       max_pixels_per_packet = max_data_per_packet / bytespp;
11731 +
11732 +       DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet);
11733 +
11734 +       pixels_left = w * h;
11735 +
11736 +       DSSDBG("total pixels %d\n", pixels_left);
11737 +
11738 +       data += start_offset;
11739 +
11740 +       while (pixels_left > 0) {
11741 +               /* 0x2c = write_memory_start */
11742 +               /* 0x3c = write_memory_continue */
11743 +               u8 dcs_cmd = first ? 0x2c : 0x3c;
11744 +               int pixels;
11745 +               DSI_DECL_VARS;
11746 +               first = 0;
11747 +
11748 +#if 1
11749 +               /* using fifo not empty */
11750 +               /* TX_FIFO_NOT_EMPTY */
11751 +               while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) {
11752 +                       udelay(1);
11753 +                       fifo_stalls++;
11754 +                       if (fifo_stalls > 0xfffff) {
11755 +                               DSSERR("fifo stalls overflow, pixels left %d\n",
11756 +                                               pixels_left);
11757 +                               dsi_if_enable(0);
11758 +                               return -EIO;
11759 +                       }
11760 +               }
11761 +#elif 1
11762 +               /* using fifo emptiness */
11763 +               while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 <
11764 +                               max_dsi_packet_size) {
11765 +                       fifo_stalls++;
11766 +                       if (fifo_stalls > 0xfffff) {
11767 +                               DSSERR("fifo stalls overflow, pixels left %d\n",
11768 +                                              pixels_left);
11769 +                               dsi_if_enable(0);
11770 +                               return -EIO;
11771 +                       }
11772 +               }
11773 +#else
11774 +               while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 == 0) {
11775 +                       fifo_stalls++;
11776 +                       if (fifo_stalls > 0xfffff) {
11777 +                               DSSERR("fifo stalls overflow, pixels left %d\n",
11778 +                                              pixels_left);
11779 +                               dsi_if_enable(0);
11780 +                               return -EIO;
11781 +                       }
11782 +               }
11783 +#endif
11784 +               pixels = min(max_pixels_per_packet, pixels_left);
11785 +
11786 +               pixels_left -= pixels;
11787 +
11788 +               dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE,
11789 +                               1 + pixels * bytespp, 0);
11790 +
11791 +               DSI_PUSH(0, dcs_cmd);
11792 +
11793 +               while (pixels-- > 0) {
11794 +                       u32 pix = __raw_readl(data++);
11795 +
11796 +                       DSI_PUSH(0, (pix >> 16) & 0xff);
11797 +                       DSI_PUSH(0, (pix >> 8) & 0xff);
11798 +                       DSI_PUSH(0, (pix >> 0) & 0xff);
11799 +
11800 +                       current_x++;
11801 +                       if (current_x == x+w) {
11802 +                               current_x = x;
11803 +                               data += horiz_inc;
11804 +                       }
11805 +               }
11806 +
11807 +               DSI_FLUSH(0);
11808 +       }
11809 +
11810 +       return 0;
11811 +}
11812 +
11813 +static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
11814 +               u16 x, u16 y, u16 w, u16 h)
11815 +{
11816 +       int bytespp = dssdev->ctrl.pixel_size / 8;
11817 +       int len;
11818 +       int total_len;
11819 +       int packet_payload;
11820 +       int packet_len;
11821 +       u32 l;
11822 +       bool use_te_trigger;
11823 +       const int channel = 0;
11824 +
11825 +       use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
11826 +
11827 +       if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
11828 +               DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
11829 +                               x, y, w, h);
11830 +
11831 +       len = w * h * bytespp;
11832 +
11833 +       /* XXX: one packet could be longer, I think? Line buffer is
11834 +        * 1024 x 24bits, but we have to put DCS cmd there also.
11835 +        * 1023 * 3 should work, but causes strange color effects. */
11836 +       packet_payload = min(w, (u16)1020) * bytespp;
11837 +
11838 +       packet_len = packet_payload + 1;        /* 1 byte for DCS cmd */
11839 +       total_len = (len / packet_payload) * packet_len;
11840 +
11841 +       if (len % packet_payload)
11842 +               total_len += (len % packet_payload) + 1;
11843 +
11844 +       if (0)
11845 +               dsi_vc_print_status(1);
11846 +
11847 +       l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
11848 +       dsi_write_reg(DSI_VC_TE(channel), l);
11849 +
11850 +       dsi_vc_write_long_header(channel, DSI_DT_DCS_LONG_WRITE, packet_len, 0);
11851 +
11852 +       if (use_te_trigger)
11853 +               l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
11854 +       else
11855 +               l = FLD_MOD(l, 1, 31, 31); /* TE_START */
11856 +       dsi_write_reg(DSI_VC_TE(channel), l);
11857 +
11858 +       /* We put SIDLEMODE to no-idle for the duration of the transfer,
11859 +        * because DSS interrupts are not capable of waking up the CPU and the
11860 +        * framedone interrupt could be delayed for quite a long time. I think
11861 +        * the same goes for any DSS interrupts, but for some reason I have not
11862 +        * seen the problem anywhere else than here.
11863 +        */
11864 +       dispc_disable_sidle();
11865 +
11866 +       dss_start_update(dssdev);
11867 +
11868 +       if (use_te_trigger) {
11869 +               /* disable LP_RX_TO, so that we can receive TE.  Time to wait
11870 +                * for TE is longer than the timer allows */
11871 +               REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
11872 +
11873 +               dsi_vc_send_bta(channel);
11874 +       }
11875 +}
11876 +
11877 +static void dsi_framedone_irq_callback(void *data, u32 mask)
11878 +{
11879 +       /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
11880 +        * turns itself off. However, DSI still has the pixels in its buffers,
11881 +        * and is sending the data.
11882 +        */
11883 +
11884 +       /* SIDLEMODE back to smart-idle */
11885 +       dispc_enable_sidle();
11886 +
11887 +       dsi.framedone_received = true;
11888 +       wake_up(&dsi.waitqueue);
11889 +}
11890 +
11891 +static void dsi_set_update_region(struct omap_dss_device *dssdev,
11892 +               u16 x, u16 y, u16 w, u16 h)
11893 +{
11894 +       spin_lock(&dsi.update_lock);
11895 +       if (dsi.update_region.dirty) {
11896 +               dsi.update_region.x = min(x, dsi.update_region.x);
11897 +               dsi.update_region.y = min(y, dsi.update_region.y);
11898 +               dsi.update_region.w = max(w, dsi.update_region.w);
11899 +               dsi.update_region.h = max(h, dsi.update_region.h);
11900 +       } else {
11901 +               dsi.update_region.x = x;
11902 +               dsi.update_region.y = y;
11903 +               dsi.update_region.w = w;
11904 +               dsi.update_region.h = h;
11905 +       }
11906 +
11907 +       dsi.update_region.device = dssdev;
11908 +       dsi.update_region.dirty = true;
11909 +
11910 +       spin_unlock(&dsi.update_lock);
11911 +
11912 +}
11913 +
11914 +static void dsi_start_auto_update(struct omap_dss_device *dssdev)
11915 +{
11916 +       u16 w, h;
11917 +       int i;
11918 +
11919 +       DSSDBG("starting auto update\n");
11920 +
11921 +       /* In automatic mode the overlay settings are applied like on DPI/SDI.
11922 +        * Mark the overlays dirty, so that we get the overlays configured, as
11923 +        * manual mode has left them in bad shape after config partia planes */
11924 +       for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
11925 +               struct omap_overlay *ovl;
11926 +               ovl = omap_dss_get_overlay(i);
11927 +               if (ovl->manager == dssdev->manager)
11928 +                       ovl->info_dirty = true;
11929 +       }
11930 +       dssdev->manager->apply(dssdev->manager);
11931 +
11932 +       dssdev->get_resolution(dssdev, &w, &h);
11933 +
11934 +       dsi_set_update_region(dssdev, 0, 0, w, h);
11935 +
11936 +       dsi_perf_mark_start_auto();
11937 +
11938 +       wake_up(&dsi.waitqueue);
11939 +}
11940 +
11941 +static int dsi_set_te(struct omap_dss_device *dssdev, bool enable)
11942 +{
11943 +       int r;
11944 +       r = dssdev->driver->enable_te(dssdev, enable);
11945 +       /* XXX for some reason, DSI TE breaks if we don't wait here.
11946 +        * Panel bug? Needs more studying */
11947 +       msleep(100);
11948 +       return r;
11949 +}
11950 +
11951 +static void dsi_handle_framedone(void)
11952 +{
11953 +       int r;
11954 +       const int channel = 0;
11955 +       bool use_te_trigger;
11956 +
11957 +       use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
11958 +
11959 +       if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
11960 +               DSSDBG("FRAMEDONE\n");
11961 +
11962 +       if (use_te_trigger) {
11963 +               /* enable LP_RX_TO again after the TE */
11964 +               REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
11965 +       }
11966 +
11967 +       /* Send BTA after the frame. We need this for the TE to work, as TE
11968 +        * trigger is only sent for BTAs without preceding packet. Thus we need
11969 +        * to BTA after the pixel packets so that next BTA will cause TE
11970 +        * trigger.
11971 +        *
11972 +        * This is not needed when TE is not in use, but we do it anyway to
11973 +        * make sure that the transfer has been completed. It would be more
11974 +        * optimal, but more complex, to wait only just before starting next
11975 +        * transfer. */
11976 +       r = dsi_vc_send_bta_sync(channel);
11977 +       if (r)
11978 +               DSSERR("BTA after framedone failed\n");
11979 +
11980 +#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
11981 +       dispc_fake_vsync_irq();
11982 +#endif
11983 +}
11984 +
11985 +static int dsi_update_thread(void *data)
11986 +{
11987 +       unsigned long timeout;
11988 +       struct omap_dss_device *device;
11989 +       u16 x, y, w, h;
11990 +
11991 +       while (1) {
11992 +               bool sched;
11993 +
11994 +               wait_event_interruptible(dsi.waitqueue,
11995 +                               dsi.update_mode == OMAP_DSS_UPDATE_AUTO ||
11996 +                               (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL &&
11997 +                                dsi.update_region.dirty == true) ||
11998 +                               kthread_should_stop());
11999 +
12000 +               if (kthread_should_stop())
12001 +                       break;
12002 +
12003 +               dsi_bus_lock();
12004 +
12005 +               if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED ||
12006 +                               kthread_should_stop()) {
12007 +                       dsi_bus_unlock();
12008 +                       break;
12009 +               }
12010 +
12011 +               dsi_perf_mark_setup();
12012 +
12013 +               if (dsi.update_region.dirty) {
12014 +                       spin_lock(&dsi.update_lock);
12015 +                       dsi.active_update_region = dsi.update_region;
12016 +                       dsi.update_region.dirty = false;
12017 +                       spin_unlock(&dsi.update_lock);
12018 +               }
12019 +
12020 +               device = dsi.active_update_region.device;
12021 +               x = dsi.active_update_region.x;
12022 +               y = dsi.active_update_region.y;
12023 +               w = dsi.active_update_region.w;
12024 +               h = dsi.active_update_region.h;
12025 +
12026 +               if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
12027 +
12028 +                       if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL) {
12029 +                               dss_setup_partial_planes(device,
12030 +                                               &x, &y, &w, &h);
12031 +#if 1
12032 +                               /* XXX there seems to be a bug in this driver
12033 +                                * or OMAP hardware.  Some updates with certain
12034 +                                * widths and x coordinates fail. These widths
12035 +                                * are always odd, so "fix" it here for now */
12036 +                               if (w & 1) {
12037 +                                       u16 dw, dh;
12038 +                                       device->get_resolution(device,
12039 +                                                       &dw, &dh);
12040 +                                       if (x + w == dw)
12041 +                                               x &= ~1;
12042 +                                       ++w;
12043 +
12044 +                                       dss_setup_partial_planes(device,
12045 +                                                       &x, &y, &w, &h);
12046 +                               }
12047 +#endif
12048 +                       }
12049 +
12050 +                       dispc_set_lcd_size(w, h);
12051 +               }
12052 +
12053 +               if (dsi.active_update_region.dirty) {
12054 +                       dsi.active_update_region.dirty = false;
12055 +                       /* XXX TODO we don't need to send the coords, if they
12056 +                        * are the same that are already programmed to the
12057 +                        * panel. That should speed up manual update a bit */
12058 +                       device->driver->setup_update(device, x, y, w, h);
12059 +               }
12060 +
12061 +               dsi_perf_mark_start();
12062 +
12063 +               if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
12064 +                       dsi_vc_config_vp(0);
12065 +
12066 +                       if (dsi.te_enabled && dsi.use_ext_te)
12067 +                               device->driver->wait_for_te(device);
12068 +
12069 +                       dsi.framedone_received = false;
12070 +
12071 +                       dsi_update_screen_dispc(device, x, y, w, h);
12072 +
12073 +                       /* wait for framedone */
12074 +                       timeout = msecs_to_jiffies(1000);
12075 +                       timeout = wait_event_timeout(dsi.waitqueue,
12076 +                                       dsi.framedone_received == true,
12077 +                                       timeout);
12078 +
12079 +                       if (timeout == 0) {
12080 +                               DSSERR("framedone timeout\n");
12081 +                               DSSERR("failed update %d,%d %dx%d\n",
12082 +                                               x, y, w, h);
12083 +
12084 +                               dispc_enable_sidle();
12085 +                               dispc_enable_lcd_out(0);
12086 +                       } else {
12087 +                               dsi_handle_framedone();
12088 +                               dsi_perf_show("DISPC");
12089 +                       }
12090 +               } else {
12091 +                       dsi_update_screen_l4(device, x, y, w, h);
12092 +                       dsi_perf_show("L4");
12093 +               }
12094 +
12095 +               sched = atomic_read(&dsi.bus_lock.count) < 0;
12096 +
12097 +               complete_all(&dsi.update_completion);
12098 +
12099 +               dsi_bus_unlock();
12100 +
12101 +               /* XXX We need to give others chance to get the bus lock. Is
12102 +                * there a better way for this? */
12103 +               if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO && sched)
12104 +                       schedule_timeout_interruptible(1);
12105 +       }
12106 +
12107 +       DSSDBG("update thread exiting\n");
12108 +
12109 +       return 0;
12110 +}
12111 +
12112 +
12113 +
12114 +/* Display funcs */
12115 +
12116 +static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
12117 +{
12118 +       int r;
12119 +
12120 +       r = omap_dispc_register_isr(dsi_framedone_irq_callback, NULL,
12121 +                       DISPC_IRQ_FRAMEDONE);
12122 +       if (r) {
12123 +               DSSERR("can't get FRAMEDONE irq\n");
12124 +               return r;
12125 +       }
12126 +
12127 +       dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
12128 +
12129 +       dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_DSI);
12130 +       dispc_enable_fifohandcheck(1);
12131 +
12132 +       dispc_set_tft_data_lines(dssdev->ctrl.pixel_size);
12133 +
12134 +       {
12135 +               struct omap_video_timings timings = {
12136 +                       .hsw            = 1,
12137 +                       .hfp            = 1,
12138 +                       .hbp            = 1,
12139 +                       .vsw            = 1,
12140 +                       .vfp            = 0,
12141 +                       .vbp            = 0,
12142 +               };
12143 +
12144 +               dispc_set_lcd_timings(&timings);
12145 +       }
12146 +
12147 +       return 0;
12148 +}
12149 +
12150 +static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
12151 +{
12152 +       omap_dispc_unregister_isr(dsi_framedone_irq_callback, NULL,
12153 +                       DISPC_IRQ_FRAMEDONE);
12154 +}
12155 +
12156 +static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
12157 +{
12158 +       struct dsi_clock_info cinfo;
12159 +       int r;
12160 +
12161 +       _dsi_print_reset_status();
12162 +
12163 +       r = dsi_pll_init(1, 0);
12164 +       if (r)
12165 +               goto err0;
12166 +
12167 +       r = dsi_pll_calc_ddrfreq(dssdev->phy.dsi.ddr_clk_hz, &cinfo);
12168 +       if (r)
12169 +               goto err1;
12170 +
12171 +       r = dsi_pll_program(&cinfo);
12172 +       if (r)
12173 +               goto err1;
12174 +
12175 +       DSSDBG("PLL OK\n");
12176 +
12177 +       r = dsi_complexio_init(dssdev);
12178 +       if (r)
12179 +               goto err1;
12180 +
12181 +       _dsi_print_reset_status();
12182 +
12183 +       dsi_proto_timings(dssdev);
12184 +       dsi_set_lp_clk_divisor(dssdev);
12185 +
12186 +       if (1)
12187 +               _dsi_print_reset_status();
12188 +
12189 +       r = dsi_proto_config(dssdev);
12190 +       if (r)
12191 +               goto err2;
12192 +
12193 +       /* enable interface */
12194 +       dsi_vc_enable(0, 1);
12195 +       dsi_if_enable(1);
12196 +       dsi_force_tx_stop_mode_io();
12197 +
12198 +       if (dssdev->driver->enable) {
12199 +               r = dssdev->driver->enable(dssdev);
12200 +               if (r)
12201 +                       goto err3;
12202 +       }
12203 +
12204 +       /* enable high-speed after initial config */
12205 +       dsi_vc_enable_hs(0, 1);
12206 +
12207 +       return 0;
12208 +err3:
12209 +       dsi_if_enable(0);
12210 +err2:
12211 +       dsi_complexio_uninit();
12212 +err1:
12213 +       dsi_pll_uninit();
12214 +err0:
12215 +       return r;
12216 +}
12217 +
12218 +static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
12219 +{
12220 +       if (dssdev->driver->disable)
12221 +               dssdev->driver->disable(dssdev);
12222 +
12223 +       dsi_complexio_uninit();
12224 +       dsi_pll_uninit();
12225 +}
12226 +
12227 +static int dsi_core_init(void)
12228 +{
12229 +       /* Autoidle */
12230 +       REG_FLD_MOD(DSI_SYSCONFIG, 1, 0, 0);
12231 +
12232 +       /* ENWAKEUP */
12233 +       REG_FLD_MOD(DSI_SYSCONFIG, 1, 2, 2);
12234 +
12235 +       /* SIDLEMODE smart-idle */
12236 +       REG_FLD_MOD(DSI_SYSCONFIG, 2, 4, 3);
12237 +
12238 +       _dsi_initialize_irq();
12239 +
12240 +       return 0;
12241 +}
12242 +
12243 +static int dsi_display_enable(struct omap_dss_device *dssdev)
12244 +{
12245 +       int r = 0;
12246 +
12247 +       DSSDBG("dsi_display_enable\n");
12248 +
12249 +       mutex_lock(&dsi.lock);
12250 +       dsi_bus_lock();
12251 +
12252 +       r = omap_dss_start_device(dssdev);
12253 +       if (r) {
12254 +               DSSERR("failed to start device\n");
12255 +               goto err0;
12256 +       }
12257 +
12258 +       if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
12259 +               DSSERR("dssdev already enabled\n");
12260 +               r = -EINVAL;
12261 +               goto err1;
12262 +       }
12263 +
12264 +       enable_clocks(1);
12265 +       dsi_enable_pll_clock(1);
12266 +
12267 +       r = _dsi_reset();
12268 +       if (r)
12269 +               goto err2;
12270 +
12271 +       dsi_core_init();
12272 +
12273 +       r = dsi_display_init_dispc(dssdev);
12274 +       if (r)
12275 +               goto err2;
12276 +
12277 +       r = dsi_display_init_dsi(dssdev);
12278 +       if (r)
12279 +               goto err3;
12280 +
12281 +       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
12282 +
12283 +       dsi.use_ext_te = dssdev->phy.dsi.ext_te;
12284 +       r = dsi_set_te(dssdev, dsi.te_enabled);
12285 +       if (r)
12286 +               goto err3;
12287 +
12288 +       dsi.update_mode = dsi.user_update_mode;
12289 +       if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
12290 +               dsi_start_auto_update(dssdev);
12291 +
12292 +       dsi_bus_unlock();
12293 +       mutex_unlock(&dsi.lock);
12294 +
12295 +       return 0;
12296 +
12297 +err3:
12298 +       dsi_display_uninit_dispc(dssdev);
12299 +err2:
12300 +       enable_clocks(0);
12301 +       dsi_enable_pll_clock(0);
12302 +err1:
12303 +       omap_dss_stop_device(dssdev);
12304 +err0:
12305 +       dsi_bus_unlock();
12306 +       mutex_unlock(&dsi.lock);
12307 +       DSSDBG("dsi_display_enable FAILED\n");
12308 +       return r;
12309 +}
12310 +
12311 +static void dsi_display_disable(struct omap_dss_device *dssdev)
12312 +{
12313 +       DSSDBG("dsi_display_disable\n");
12314 +
12315 +       mutex_lock(&dsi.lock);
12316 +       dsi_bus_lock();
12317 +
12318 +       if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
12319 +                       dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
12320 +               goto end;
12321 +
12322 +       dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
12323 +       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
12324 +
12325 +       dsi_display_uninit_dispc(dssdev);
12326 +
12327 +       dsi_display_uninit_dsi(dssdev);
12328 +
12329 +       enable_clocks(0);
12330 +       dsi_enable_pll_clock(0);
12331 +
12332 +       omap_dss_stop_device(dssdev);
12333 +end:
12334 +       dsi_bus_unlock();
12335 +       mutex_unlock(&dsi.lock);
12336 +}
12337 +
12338 +static int dsi_display_suspend(struct omap_dss_device *dssdev)
12339 +{
12340 +       DSSDBG("dsi_display_suspend\n");
12341 +
12342 +       mutex_lock(&dsi.lock);
12343 +       dsi_bus_lock();
12344 +
12345 +       if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
12346 +                       dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
12347 +               goto end;
12348 +
12349 +       dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
12350 +       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
12351 +
12352 +       dsi_display_uninit_dispc(dssdev);
12353 +
12354 +       dsi_display_uninit_dsi(dssdev);
12355 +
12356 +       enable_clocks(0);
12357 +       dsi_enable_pll_clock(0);
12358 +end:
12359 +       dsi_bus_unlock();
12360 +       mutex_unlock(&dsi.lock);
12361 +
12362 +       return 0;
12363 +}
12364 +
12365 +static int dsi_display_resume(struct omap_dss_device *dssdev)
12366 +{
12367 +       int r;
12368 +
12369 +       DSSDBG("dsi_display_resume\n");
12370 +
12371 +       mutex_lock(&dsi.lock);
12372 +       dsi_bus_lock();
12373 +
12374 +       if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
12375 +               DSSERR("dssdev not suspended\n");
12376 +               r = -EINVAL;
12377 +               goto err0;
12378 +       }
12379 +
12380 +       enable_clocks(1);
12381 +       dsi_enable_pll_clock(1);
12382 +
12383 +       r = _dsi_reset();
12384 +       if (r)
12385 +               goto err1;
12386 +
12387 +       dsi_core_init();
12388 +
12389 +       r = dsi_display_init_dispc(dssdev);
12390 +       if (r)
12391 +               goto err1;
12392 +
12393 +       r = dsi_display_init_dsi(dssdev);
12394 +       if (r)
12395 +               goto err2;
12396 +
12397 +       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
12398 +
12399 +       r = dsi_set_te(dssdev, dsi.te_enabled);
12400 +       if (r)
12401 +               goto err2;
12402 +
12403 +       dsi.update_mode = dsi.user_update_mode;
12404 +       if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
12405 +               dsi_start_auto_update(dssdev);
12406 +
12407 +       dsi_bus_unlock();
12408 +       mutex_unlock(&dsi.lock);
12409 +
12410 +       return 0;
12411 +
12412 +err2:
12413 +       dsi_display_uninit_dispc(dssdev);
12414 +err1:
12415 +       enable_clocks(0);
12416 +       dsi_enable_pll_clock(0);
12417 +err0:
12418 +       dsi_bus_unlock();
12419 +       mutex_unlock(&dsi.lock);
12420 +       DSSDBG("dsi_display_resume FAILED\n");
12421 +       return r;
12422 +}
12423 +
12424 +static int dsi_display_update(struct omap_dss_device *dssdev,
12425 +                       u16 x, u16 y, u16 w, u16 h)
12426 +{
12427 +       int r = 0;
12428 +       u16 dw, dh;
12429 +
12430 +       DSSDBG("dsi_display_update(%d,%d %dx%d)\n", x, y, w, h);
12431 +
12432 +       mutex_lock(&dsi.lock);
12433 +
12434 +       if (dsi.update_mode != OMAP_DSS_UPDATE_MANUAL)
12435 +               goto end;
12436 +
12437 +       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
12438 +               goto end;
12439 +
12440 +       dssdev->get_resolution(dssdev, &dw, &dh);
12441 +
12442 +       if  (x > dw || y > dh)
12443 +               goto end;
12444 +
12445 +       if (x + w > dw)
12446 +               w = dw - x;
12447 +
12448 +       if (y + h > dh)
12449 +               h = dh - y;
12450 +
12451 +       if (w == 0 || h == 0)
12452 +               goto end;
12453 +
12454 +       dsi_set_update_region(dssdev, x, y, w, h);
12455 +
12456 +       wake_up(&dsi.waitqueue);
12457 +
12458 +end:
12459 +       mutex_unlock(&dsi.lock);
12460 +
12461 +       return r;
12462 +}
12463 +
12464 +static int dsi_display_sync(struct omap_dss_device *dssdev)
12465 +{
12466 +       bool wait;
12467 +
12468 +       DSSDBG("dsi_display_sync()\n");
12469 +
12470 +       mutex_lock(&dsi.lock);
12471 +       dsi_bus_lock();
12472 +
12473 +       if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL &&
12474 +                       dsi.update_region.dirty) {
12475 +               INIT_COMPLETION(dsi.update_completion);
12476 +               wait = true;
12477 +       } else {
12478 +               wait = false;
12479 +       }
12480 +
12481 +       dsi_bus_unlock();
12482 +       mutex_unlock(&dsi.lock);
12483 +
12484 +       if (wait)
12485 +               wait_for_completion_interruptible(&dsi.update_completion);
12486 +
12487 +       DSSDBG("dsi_display_sync() done\n");
12488 +       return 0;
12489 +}
12490 +
12491 +static int dsi_display_set_update_mode(struct omap_dss_device *dssdev,
12492 +               enum omap_dss_update_mode mode)
12493 +{
12494 +       DSSDBGF("%d", mode);
12495 +
12496 +       mutex_lock(&dsi.lock);
12497 +       dsi_bus_lock();
12498 +
12499 +       if (dsi.update_mode != mode) {
12500 +               dsi.user_update_mode = mode;
12501 +               dsi.update_mode = mode;
12502 +
12503 +               if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE &&
12504 +                               mode == OMAP_DSS_UPDATE_AUTO)
12505 +                       dsi_start_auto_update(dssdev);
12506 +       }
12507 +
12508 +       dsi_bus_unlock();
12509 +       mutex_unlock(&dsi.lock);
12510 +
12511 +       return 0;
12512 +}
12513 +
12514 +static enum omap_dss_update_mode dsi_display_get_update_mode(
12515 +               struct omap_dss_device *dssdev)
12516 +{
12517 +       return dsi.update_mode;
12518 +}
12519 +
12520 +
12521 +static int dsi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
12522 +{
12523 +       int r = 0;
12524 +
12525 +       DSSDBGF("%d", enable);
12526 +
12527 +       if (!dssdev->driver->enable_te)
12528 +               return -ENOENT;
12529 +
12530 +       dsi_bus_lock();
12531 +
12532 +       dsi.te_enabled = enable;
12533 +
12534 +       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
12535 +               goto end;
12536 +
12537 +       r = dsi_set_te(dssdev, enable);
12538 +end:
12539 +       dsi_bus_unlock();
12540 +
12541 +       return r;
12542 +}
12543 +
12544 +static int dsi_display_get_te(struct omap_dss_device *dssdev)
12545 +{
12546 +       return dsi.te_enabled;
12547 +}
12548 +
12549 +static int dsi_display_set_rotate(struct omap_dss_device *dssdev, u8 rotate)
12550 +{
12551 +
12552 +       DSSDBGF("%d", rotate);
12553 +
12554 +       if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
12555 +               return -EINVAL;
12556 +
12557 +       dsi_bus_lock();
12558 +       dssdev->driver->set_rotate(dssdev, rotate);
12559 +       if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
12560 +               u16 w, h;
12561 +               /* the display dimensions may have changed, so set a new
12562 +                * update region */
12563 +               dssdev->get_resolution(dssdev, &w, &h);
12564 +               dsi_set_update_region(dssdev, 0, 0, w, h);
12565 +       }
12566 +       dsi_bus_unlock();
12567 +
12568 +       return 0;
12569 +}
12570 +
12571 +static u8 dsi_display_get_rotate(struct omap_dss_device *dssdev)
12572 +{
12573 +       if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
12574 +               return 0;
12575 +
12576 +       return dssdev->driver->get_rotate(dssdev);
12577 +}
12578 +
12579 +static int dsi_display_set_mirror(struct omap_dss_device *dssdev, bool mirror)
12580 +{
12581 +       DSSDBGF("%d", mirror);
12582 +
12583 +       if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
12584 +               return -EINVAL;
12585 +
12586 +       dsi_bus_lock();
12587 +       dssdev->driver->set_mirror(dssdev, mirror);
12588 +       dsi_bus_unlock();
12589 +
12590 +       return 0;
12591 +}
12592 +
12593 +static bool dsi_display_get_mirror(struct omap_dss_device *dssdev)
12594 +{
12595 +       if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
12596 +               return 0;
12597 +
12598 +       return dssdev->driver->get_mirror(dssdev);
12599 +}
12600 +
12601 +static int dsi_display_run_test(struct omap_dss_device *dssdev, int test_num)
12602 +{
12603 +       int r;
12604 +
12605 +       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
12606 +               return -EIO;
12607 +
12608 +       DSSDBGF("%d", test_num);
12609 +
12610 +       dsi_bus_lock();
12611 +
12612 +       /* run test first in low speed mode */
12613 +       dsi_vc_enable_hs(0, 0);
12614 +
12615 +       if (dssdev->driver->run_test) {
12616 +               r = dssdev->driver->run_test(dssdev, test_num);
12617 +               if (r)
12618 +                       goto end;
12619 +       }
12620 +
12621 +       /* then in high speed */
12622 +       dsi_vc_enable_hs(0, 1);
12623 +
12624 +       if (dssdev->driver->run_test) {
12625 +               r = dssdev->driver->run_test(dssdev, test_num);
12626 +               if (r)
12627 +                       goto end;
12628 +       }
12629 +
12630 +end:
12631 +       dsi_vc_enable_hs(0, 1);
12632 +
12633 +       dsi_bus_unlock();
12634 +
12635 +       return r;
12636 +}
12637 +
12638 +static int dsi_display_memory_read(struct omap_dss_device *dssdev,
12639 +               void *buf, size_t size,
12640 +               u16 x, u16 y, u16 w, u16 h)
12641 +{
12642 +       int r;
12643 +
12644 +       DSSDBGF("");
12645 +
12646 +       if (!dssdev->driver->memory_read)
12647 +               return -EINVAL;
12648 +
12649 +       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
12650 +               return -EIO;
12651 +
12652 +       dsi_bus_lock();
12653 +
12654 +       r = dssdev->driver->memory_read(dssdev, buf, size,
12655 +                       x, y, w, h);
12656 +
12657 +       dsi_bus_unlock();
12658 +
12659 +       return r;
12660 +}
12661 +
12662 +void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
12663 +               u32 fifo_size, enum omap_burst_size *burst_size,
12664 +               u32 *fifo_low, u32 *fifo_high)
12665 +{
12666 +       unsigned burst_size_bytes;
12667 +
12668 +       *burst_size = OMAP_DSS_BURST_16x32;
12669 +       burst_size_bytes = 16 * 32 / 8;
12670 +
12671 +       *fifo_high = fifo_size - burst_size_bytes;
12672 +       *fifo_low = 0;
12673 +}
12674 +
12675 +int dsi_init_display(struct omap_dss_device *dssdev)
12676 +{
12677 +       DSSDBG("DSI init\n");
12678 +
12679 +       dssdev->enable = dsi_display_enable;
12680 +       dssdev->disable = dsi_display_disable;
12681 +       dssdev->suspend = dsi_display_suspend;
12682 +       dssdev->resume = dsi_display_resume;
12683 +       dssdev->update = dsi_display_update;
12684 +       dssdev->sync = dsi_display_sync;
12685 +       dssdev->set_update_mode = dsi_display_set_update_mode;
12686 +       dssdev->get_update_mode = dsi_display_get_update_mode;
12687 +       dssdev->enable_te = dsi_display_enable_te;
12688 +       dssdev->get_te = dsi_display_get_te;
12689 +
12690 +       dssdev->get_rotate = dsi_display_get_rotate;
12691 +       dssdev->set_rotate = dsi_display_set_rotate;
12692 +
12693 +       dssdev->get_mirror = dsi_display_get_mirror;
12694 +       dssdev->set_mirror = dsi_display_set_mirror;
12695 +
12696 +       dssdev->run_test = dsi_display_run_test;
12697 +       dssdev->memory_read = dsi_display_memory_read;
12698 +
12699 +       dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
12700 +
12701 +       dsi.vc[0].dssdev = dssdev;
12702 +       dsi.vc[1].dssdev = dssdev;
12703 +
12704 +       return 0;
12705 +}
12706 +
12707 +int dsi_init(struct platform_device *pdev)
12708 +{
12709 +       u32 rev;
12710 +       struct sched_param param = {
12711 +               .sched_priority = MAX_USER_RT_PRIO-1
12712 +       };
12713 +
12714 +       spin_lock_init(&dsi.errors_lock);
12715 +       dsi.errors = 0;
12716 +
12717 +       /* XXX fail properly */
12718 +
12719 +       init_completion(&dsi.bta_completion);
12720 +       init_completion(&dsi.update_completion);
12721 +
12722 +       dsi.thread = kthread_create(dsi_update_thread, NULL, "dsi");
12723 +       if (IS_ERR(dsi.thread)) {
12724 +               DSSERR("cannot create kthread\n");
12725 +               return PTR_ERR(dsi.thread);
12726 +       }
12727 +       sched_setscheduler(dsi.thread, SCHED_FIFO, &param);
12728 +
12729 +       init_waitqueue_head(&dsi.waitqueue);
12730 +       spin_lock_init(&dsi.update_lock);
12731 +
12732 +       mutex_init(&dsi.lock);
12733 +       mutex_init(&dsi.bus_lock);
12734 +
12735 +       dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
12736 +       dsi.user_update_mode = OMAP_DSS_UPDATE_DISABLED;
12737 +
12738 +       dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS);
12739 +       if (!dsi.base) {
12740 +               DSSERR("can't ioremap DSI\n");
12741 +               return -ENOMEM;
12742 +       }
12743 +
12744 +       dsi.vdds_dsi_reg = regulator_get(&pdev->dev, "vdds_dsi");
12745 +       if (IS_ERR(dsi.vdds_dsi_reg)) {
12746 +               iounmap(dsi.base);
12747 +               DSSERR("can't get VDDS_DSI regulator\n");
12748 +               return PTR_ERR(dsi.vdds_dsi_reg);
12749 +       }
12750 +
12751 +       enable_clocks(1);
12752 +
12753 +       rev = dsi_read_reg(DSI_REVISION);
12754 +       printk(KERN_INFO "OMAP DSI rev %d.%d\n",
12755 +              FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
12756 +
12757 +       enable_clocks(0);
12758 +
12759 +       wake_up_process(dsi.thread);
12760 +
12761 +       return 0;
12762 +}
12763 +
12764 +void dsi_exit(void)
12765 +{
12766 +       kthread_stop(dsi.thread);
12767 +
12768 +       regulator_put(dsi.vdds_dsi_reg);
12769 +
12770 +       iounmap(dsi.base);
12771 +
12772 +       DSSDBG("omap_dsi_exit\n");
12773 +}
12774 +
12775 diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
12776 new file mode 100644
12777 index 0000000..aab9758
12778 --- /dev/null
12779 +++ b/drivers/video/omap2/dss/dss.c
12780 @@ -0,0 +1,347 @@
12781 +/*
12782 + * linux/drivers/video/omap2/dss/dss.c
12783 + *
12784 + * Copyright (C) 2009 Nokia Corporation
12785 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
12786 + *
12787 + * Some code and ideas taken from drivers/video/omap/ driver
12788 + * by Imre Deak.
12789 + *
12790 + * This program is free software; you can redistribute it and/or modify it
12791 + * under the terms of the GNU General Public License version 2 as published by
12792 + * the Free Software Foundation.
12793 + *
12794 + * This program is distributed in the hope that it will be useful, but WITHOUT
12795 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12796 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12797 + * more details.
12798 + *
12799 + * You should have received a copy of the GNU General Public License along with
12800 + * this program.  If not, see <http://www.gnu.org/licenses/>.
12801 + */
12802 +
12803 +#define DSS_SUBSYS_NAME "DSS"
12804 +
12805 +#include <linux/kernel.h>
12806 +#include <linux/io.h>
12807 +#include <linux/err.h>
12808 +#include <linux/delay.h>
12809 +#include <linux/interrupt.h>
12810 +#include <linux/seq_file.h>
12811 +
12812 +#include <mach/display.h>
12813 +#include "dss.h"
12814 +
12815 +#define DSS_BASE                       0x48050000
12816 +
12817 +#define DSS_SZ_REGS                    SZ_512
12818 +
12819 +struct dss_reg {
12820 +       u16 idx;
12821 +};
12822 +
12823 +#define DSS_REG(idx)                   ((const struct dss_reg) { idx })
12824 +
12825 +#define DSS_REVISION                   DSS_REG(0x0000)
12826 +#define DSS_SYSCONFIG                  DSS_REG(0x0010)
12827 +#define DSS_SYSSTATUS                  DSS_REG(0x0014)
12828 +#define DSS_IRQSTATUS                  DSS_REG(0x0018)
12829 +#define DSS_CONTROL                    DSS_REG(0x0040)
12830 +#define DSS_SDI_CONTROL                        DSS_REG(0x0044)
12831 +#define DSS_PLL_CONTROL                        DSS_REG(0x0048)
12832 +#define DSS_SDI_STATUS                 DSS_REG(0x005C)
12833 +
12834 +#define REG_GET(idx, start, end) \
12835 +       FLD_GET(dss_read_reg(idx), start, end)
12836 +
12837 +#define REG_FLD_MOD(idx, val, start, end) \
12838 +       dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
12839 +
12840 +static struct {
12841 +       void __iomem    *base;
12842 +
12843 +       u32             ctx[DSS_SZ_REGS / sizeof(u32)];
12844 +} dss;
12845 +
12846 +static int _omap_dss_wait_reset(void);
12847 +
12848 +static inline void dss_write_reg(const struct dss_reg idx, u32 val)
12849 +{
12850 +       __raw_writel(val, dss.base + idx.idx);
12851 +}
12852 +
12853 +static inline u32 dss_read_reg(const struct dss_reg idx)
12854 +{
12855 +       return __raw_readl(dss.base + idx.idx);
12856 +}
12857 +
12858 +#define SR(reg) \
12859 +       dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
12860 +#define RR(reg) \
12861 +       dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
12862 +
12863 +void dss_save_context(void)
12864 +{
12865 +       if (cpu_is_omap24xx())
12866 +               return;
12867 +
12868 +       SR(SYSCONFIG);
12869 +       SR(CONTROL);
12870 +
12871 +#ifdef CONFIG_OMAP2_DSS_SDI
12872 +       SR(SDI_CONTROL);
12873 +       SR(PLL_CONTROL);
12874 +#endif
12875 +}
12876 +
12877 +void dss_restore_context(void)
12878 +{
12879 +       if (_omap_dss_wait_reset())
12880 +               DSSERR("DSS not coming out of reset after sleep\n");
12881 +
12882 +       RR(SYSCONFIG);
12883 +       RR(CONTROL);
12884 +
12885 +#ifdef CONFIG_OMAP2_DSS_SDI
12886 +       RR(SDI_CONTROL);
12887 +       RR(PLL_CONTROL);
12888 +#endif
12889 +}
12890 +
12891 +#undef SR
12892 +#undef RR
12893 +
12894 +void dss_sdi_init(u8 datapairs)
12895 +{
12896 +       u32 l;
12897 +
12898 +       BUG_ON(datapairs > 3 || datapairs < 1);
12899 +
12900 +       l = dss_read_reg(DSS_SDI_CONTROL);
12901 +       l = FLD_MOD(l, 0xf, 19, 15);            /* SDI_PDIV */
12902 +       l = FLD_MOD(l, datapairs-1, 3, 2);      /* SDI_PRSEL */
12903 +       l = FLD_MOD(l, 2, 1, 0);                /* SDI_BWSEL */
12904 +       dss_write_reg(DSS_SDI_CONTROL, l);
12905 +
12906 +       l = dss_read_reg(DSS_PLL_CONTROL);
12907 +       l = FLD_MOD(l, 0x7, 25, 22);    /* SDI_PLL_FREQSEL */
12908 +       l = FLD_MOD(l, 0xb, 16, 11);    /* SDI_PLL_REGN */
12909 +       l = FLD_MOD(l, 0xb4, 10, 1);    /* SDI_PLL_REGM */
12910 +       dss_write_reg(DSS_PLL_CONTROL, l);
12911 +}
12912 +
12913 +void dss_sdi_enable(void)
12914 +{
12915 +       dispc_pck_free_enable(1);
12916 +
12917 +       /* Reset SDI PLL */
12918 +       REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
12919 +       udelay(1);      /* wait 2x PCLK */
12920 +
12921 +       /* Lock SDI PLL */
12922 +       REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
12923 +
12924 +       /* Waiting for PLL lock request to complete */
12925 +       while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6))
12926 +               ;
12927 +
12928 +       /* Clearing PLL_GO bit */
12929 +       REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
12930 +
12931 +       /* Waiting for PLL to lock */
12932 +       while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5)))
12933 +               ;
12934 +
12935 +       dispc_lcd_enable_signal(1);
12936 +
12937 +       /* Waiting for SDI reset to complete */
12938 +       while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2)))
12939 +               ;
12940 +}
12941 +
12942 +void dss_sdi_disable(void)
12943 +{
12944 +       dispc_lcd_enable_signal(0);
12945 +
12946 +       dispc_pck_free_enable(0);
12947 +
12948 +       /* Reset SDI PLL */
12949 +       REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
12950 +}
12951 +
12952 +void dss_dump_regs(struct seq_file *s)
12953 +{
12954 +#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
12955 +
12956 +       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
12957 +
12958 +       DUMPREG(DSS_REVISION);
12959 +       DUMPREG(DSS_SYSCONFIG);
12960 +       DUMPREG(DSS_SYSSTATUS);
12961 +       DUMPREG(DSS_IRQSTATUS);
12962 +       DUMPREG(DSS_CONTROL);
12963 +       DUMPREG(DSS_SDI_CONTROL);
12964 +       DUMPREG(DSS_PLL_CONTROL);
12965 +       DUMPREG(DSS_SDI_STATUS);
12966 +
12967 +       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
12968 +#undef DUMPREG
12969 +}
12970 +
12971 +void dss_select_clk_source(bool dsi, bool dispc)
12972 +{
12973 +       u32 r;
12974 +       r = dss_read_reg(DSS_CONTROL);
12975 +       r = FLD_MOD(r, dsi, 1, 1);      /* DSI_CLK_SWITCH */
12976 +       r = FLD_MOD(r, dispc, 0, 0);    /* DISPC_CLK_SWITCH */
12977 +       dss_write_reg(DSS_CONTROL, r);
12978 +}
12979 +
12980 +int dss_get_dsi_clk_source(void)
12981 +{
12982 +       return FLD_GET(dss_read_reg(DSS_CONTROL), 1, 1);
12983 +}
12984 +
12985 +int dss_get_dispc_clk_source(void)
12986 +{
12987 +       return FLD_GET(dss_read_reg(DSS_CONTROL), 0, 0);
12988 +}
12989 +
12990 +static irqreturn_t dss_irq_handler_omap2(int irq, void *arg)
12991 +{
12992 +       dispc_irq_handler();
12993 +
12994 +       return IRQ_HANDLED;
12995 +}
12996 +
12997 +static irqreturn_t dss_irq_handler_omap3(int irq, void *arg)
12998 +{
12999 +       u32 irqstatus;
13000 +
13001 +       irqstatus = dss_read_reg(DSS_IRQSTATUS);
13002 +
13003 +       if (irqstatus & (1<<0)) /* DISPC_IRQ */
13004 +               dispc_irq_handler();
13005 +#ifdef CONFIG_OMAP2_DSS_DSI
13006 +       if (irqstatus & (1<<1)) /* DSI_IRQ */
13007 +               dsi_irq_handler();
13008 +#endif
13009 +
13010 +       return IRQ_HANDLED;
13011 +}
13012 +
13013 +static int _omap_dss_wait_reset(void)
13014 +{
13015 +       unsigned timeout = 1000;
13016 +
13017 +       while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
13018 +               udelay(1);
13019 +               if (!--timeout) {
13020 +                       DSSERR("soft reset failed\n");
13021 +                       return -ENODEV;
13022 +               }
13023 +       }
13024 +
13025 +       return 0;
13026 +}
13027 +
13028 +static int _omap_dss_reset(void)
13029 +{
13030 +       /* Soft reset */
13031 +       REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
13032 +       return _omap_dss_wait_reset();
13033 +}
13034 +
13035 +void dss_set_venc_output(enum omap_dss_venc_type type)
13036 +{
13037 +       int l = 0;
13038 +
13039 +       if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
13040 +               l = 0;
13041 +       else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
13042 +               l = 1;
13043 +       else
13044 +               BUG();
13045 +
13046 +       /* venc out selection. 0 = comp, 1 = svideo */
13047 +       REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
13048 +}
13049 +
13050 +void dss_set_dac_pwrdn_bgz(bool enable)
13051 +{
13052 +       REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
13053 +}
13054 +
13055 +int dss_init(bool skip_init)
13056 +{
13057 +       int r;
13058 +       u32 rev;
13059 +
13060 +       dss.base = ioremap(DSS_BASE, DSS_SZ_REGS);
13061 +       if (!dss.base) {
13062 +               DSSERR("can't ioremap DSS\n");
13063 +               r = -ENOMEM;
13064 +               goto fail0;
13065 +       }
13066 +
13067 +       if (!skip_init) {
13068 +               /* disable LCD and DIGIT output. This seems to fix the synclost
13069 +                * problem that we get, if the bootloader starts the DSS and
13070 +                * the kernel resets it */
13071 +               omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
13072 +
13073 +               /* We need to wait here a bit, otherwise we sometimes start to
13074 +                * get synclost errors, and after that only power cycle will
13075 +                * restore DSS functionality. I have no idea why this happens.
13076 +                * And we have to wait _before_ resetting the DSS, but after
13077 +                * enabling clocks.
13078 +                */
13079 +               msleep(50);
13080 +
13081 +               _omap_dss_reset();
13082 +       }
13083 +
13084 +       /* autoidle */
13085 +       REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
13086 +
13087 +       /* Select DPLL */
13088 +       REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
13089 +
13090 +#ifdef CONFIG_OMAP2_DSS_VENC
13091 +       REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);      /* venc dac demen */
13092 +       REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);      /* venc clock 4x enable */
13093 +       REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);      /* venc clock mode = normal */
13094 +#endif
13095 +
13096 +       r = request_irq(INT_24XX_DSS_IRQ,
13097 +                       cpu_is_omap24xx()
13098 +                       ? dss_irq_handler_omap2
13099 +                       : dss_irq_handler_omap3,
13100 +                       0, "OMAP DSS", NULL);
13101 +
13102 +       if (r < 0) {
13103 +               DSSERR("omap2 dss: request_irq failed\n");
13104 +               goto fail1;
13105 +       }
13106 +
13107 +       dss_save_context();
13108 +
13109 +       rev = dss_read_reg(DSS_REVISION);
13110 +       printk(KERN_INFO "OMAP DSS rev %d.%d\n",
13111 +                       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
13112 +
13113 +       return 0;
13114 +
13115 +fail1:
13116 +       iounmap(dss.base);
13117 +fail0:
13118 +       return r;
13119 +}
13120 +
13121 +void dss_exit(void)
13122 +{
13123 +       free_irq(INT_24XX_DSS_IRQ, NULL);
13124 +
13125 +       iounmap(dss.base);
13126 +}
13127 +
13128 diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
13129 new file mode 100644
13130 index 0000000..50f7f5f
13131 --- /dev/null
13132 +++ b/drivers/video/omap2/dss/dss.h
13133 @@ -0,0 +1,356 @@
13134 +/*
13135 + * linux/drivers/video/omap2/dss/dss.h
13136 + *
13137 + * Copyright (C) 2009 Nokia Corporation
13138 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
13139 + *
13140 + * Some code and ideas taken from drivers/video/omap/ driver
13141 + * by Imre Deak.
13142 + *
13143 + * This program is free software; you can redistribute it and/or modify it
13144 + * under the terms of the GNU General Public License version 2 as published by
13145 + * the Free Software Foundation.
13146 + *
13147 + * This program is distributed in the hope that it will be useful, but WITHOUT
13148 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13149 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13150 + * more details.
13151 + *
13152 + * You should have received a copy of the GNU General Public License along with
13153 + * this program.  If not, see <http://www.gnu.org/licenses/>.
13154 + */
13155 +
13156 +#ifndef __OMAP2_DSS_H
13157 +#define __OMAP2_DSS_H
13158 +
13159 +#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT
13160 +#define DEBUG
13161 +#endif
13162 +
13163 +#ifdef DEBUG
13164 +extern unsigned int dss_debug;
13165 +#ifdef DSS_SUBSYS_NAME
13166 +#define DSSDBG(format, ...) \
13167 +       if (dss_debug) \
13168 +               printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \
13169 +               ## __VA_ARGS__)
13170 +#else
13171 +#define DSSDBG(format, ...) \
13172 +       if (dss_debug) \
13173 +               printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__)
13174 +#endif
13175 +
13176 +#ifdef DSS_SUBSYS_NAME
13177 +#define DSSDBGF(format, ...) \
13178 +       if (dss_debug) \
13179 +               printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \
13180 +                               ": %s(" format ")\n", \
13181 +                               __func__, \
13182 +                               ## __VA_ARGS__)
13183 +#else
13184 +#define DSSDBGF(format, ...) \
13185 +       if (dss_debug) \
13186 +               printk(KERN_DEBUG "omapdss: " \
13187 +                               ": %s(" format ")\n", \
13188 +                               __func__, \
13189 +                               ## __VA_ARGS__)
13190 +#endif
13191 +
13192 +#else /* DEBUG */
13193 +#define DSSDBG(format, ...)
13194 +#define DSSDBGF(format, ...)
13195 +#endif
13196 +
13197 +
13198 +#ifdef DSS_SUBSYS_NAME
13199 +#define DSSERR(format, ...) \
13200 +       printk(KERN_ERR "omapdss " DSS_SUBSYS_NAME " error: " format, \
13201 +       ## __VA_ARGS__)
13202 +#else
13203 +#define DSSERR(format, ...) \
13204 +       printk(KERN_ERR "omapdss error: " format, ## __VA_ARGS__)
13205 +#endif
13206 +
13207 +#ifdef DSS_SUBSYS_NAME
13208 +#define DSSINFO(format, ...) \
13209 +       printk(KERN_INFO "omapdss " DSS_SUBSYS_NAME ": " format, \
13210 +       ## __VA_ARGS__)
13211 +#else
13212 +#define DSSINFO(format, ...) \
13213 +       printk(KERN_INFO "omapdss: " format, ## __VA_ARGS__)
13214 +#endif
13215 +
13216 +#ifdef DSS_SUBSYS_NAME
13217 +#define DSSWARN(format, ...) \
13218 +       printk(KERN_WARNING "omapdss " DSS_SUBSYS_NAME ": " format, \
13219 +       ## __VA_ARGS__)
13220 +#else
13221 +#define DSSWARN(format, ...) \
13222 +       printk(KERN_WARNING "omapdss: " format, ## __VA_ARGS__)
13223 +#endif
13224 +
13225 +/* OMAP TRM gives bitfields as start:end, where start is the higher bit
13226 +   number. For example 7:0 */
13227 +#define FLD_MASK(start, end)   (((1 << (start - end + 1)) - 1) << (end))
13228 +#define FLD_VAL(val, start, end) (((val) << end) & FLD_MASK(start, end))
13229 +#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
13230 +#define FLD_MOD(orig, val, start, end) \
13231 +       (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
13232 +
13233 +#define DISPC_MAX_FCK 173000000
13234 +
13235 +enum omap_burst_size {
13236 +       OMAP_DSS_BURST_4x32 = 0,
13237 +       OMAP_DSS_BURST_8x32 = 1,
13238 +       OMAP_DSS_BURST_16x32 = 2,
13239 +};
13240 +
13241 +enum omap_parallel_interface_mode {
13242 +       OMAP_DSS_PARALLELMODE_BYPASS,           /* MIPI DPI */
13243 +       OMAP_DSS_PARALLELMODE_RFBI,             /* MIPI DBI */
13244 +       OMAP_DSS_PARALLELMODE_DSI,
13245 +};
13246 +
13247 +enum dss_clock {
13248 +       DSS_CLK_ICK     = 1 << 0,
13249 +       DSS_CLK_FCK1    = 1 << 1,
13250 +       DSS_CLK_FCK2    = 1 << 2,
13251 +       DSS_CLK_54M     = 1 << 3,
13252 +       DSS_CLK_96M     = 1 << 4,
13253 +};
13254 +
13255 +struct dispc_clock_info {
13256 +       /* rates that we get with dividers below */
13257 +       unsigned long fck;
13258 +       unsigned long lck;
13259 +       unsigned long pck;
13260 +
13261 +       /* dividers */
13262 +       u16 fck_div;
13263 +       u16 lck_div;
13264 +       u16 pck_div;
13265 +};
13266 +
13267 +struct dsi_clock_info {
13268 +       /* rates that we get with dividers below */
13269 +       unsigned long fint;
13270 +       unsigned long dsiphy;
13271 +       unsigned long clkin;
13272 +       unsigned long dsi1_pll_fclk;
13273 +       unsigned long dsi2_pll_fclk;
13274 +       unsigned long lck;
13275 +       unsigned long pck;
13276 +
13277 +       /* dividers */
13278 +       u16 regn;
13279 +       u16 regm;
13280 +       u16 regm3;
13281 +       u16 regm4;
13282 +
13283 +       u16 lck_div;
13284 +       u16 pck_div;
13285 +
13286 +       u8 highfreq;
13287 +       bool use_dss2_fck;
13288 +};
13289 +
13290 +struct seq_file;
13291 +struct platform_device;
13292 +
13293 +/* core */
13294 +void dss_clk_enable(enum dss_clock clks);
13295 +void dss_clk_disable(enum dss_clock clks);
13296 +unsigned long dss_clk_get_rate(enum dss_clock clk);
13297 +int dss_need_ctx_restore(void);
13298 +void dss_dump_clocks(struct seq_file *s);
13299 +struct bus_type *dss_get_bus(void);
13300 +
13301 +/* display */
13302 +int dss_suspend_all_devices(void);
13303 +int dss_resume_all_devices(void);
13304 +
13305 +void dss_init_device(struct platform_device *pdev,
13306 +               struct omap_dss_device *dssdev);
13307 +void dss_uninit_device(struct platform_device *pdev,
13308 +               struct omap_dss_device *dssdev);
13309 +bool dss_use_replication(struct omap_dss_device *dssdev,
13310 +               enum omap_color_mode mode);
13311 +void default_get_overlay_fifo_thresholds(enum omap_plane plane,
13312 +               u32 fifo_size, enum omap_burst_size *burst_size,
13313 +               u32 *fifo_low, u32 *fifo_high);
13314 +
13315 +/* manager */
13316 +int dss_init_overlay_managers(struct platform_device *pdev);
13317 +void dss_uninit_overlay_managers(struct platform_device *pdev);
13318 +int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
13319 +void dss_setup_partial_planes(struct omap_dss_device *dssdev,
13320 +                               u16 *x, u16 *y, u16 *w, u16 *h);
13321 +void dss_start_update(struct omap_dss_device *dssdev);
13322 +
13323 +/* overlay */
13324 +void dss_init_overlays(struct platform_device *pdev);
13325 +void dss_uninit_overlays(struct platform_device *pdev);
13326 +int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev);
13327 +void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
13328 +#ifdef L4_EXAMPLE
13329 +void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr);
13330 +#endif
13331 +void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
13332 +
13333 +/* DSS */
13334 +int dss_init(bool skip_init);
13335 +void dss_exit(void);
13336 +
13337 +void dss_save_context(void);
13338 +void dss_restore_context(void);
13339 +
13340 +void dss_dump_regs(struct seq_file *s);
13341 +
13342 +void dss_sdi_init(u8 datapairs);
13343 +void dss_sdi_enable(void);
13344 +void dss_sdi_disable(void);
13345 +
13346 +void dss_select_clk_source(bool dsi, bool dispc);
13347 +int dss_get_dsi_clk_source(void);
13348 +int dss_get_dispc_clk_source(void);
13349 +void dss_set_venc_output(enum omap_dss_venc_type type);
13350 +void dss_set_dac_pwrdn_bgz(bool enable);
13351 +
13352 +/* SDI */
13353 +int sdi_init(bool skip_init);
13354 +void sdi_exit(void);
13355 +int sdi_init_display(struct omap_dss_device *display);
13356 +
13357 +/* DSI */
13358 +int dsi_init(struct platform_device *pdev);
13359 +void dsi_exit(void);
13360 +
13361 +void dsi_dump_clocks(struct seq_file *s);
13362 +void dsi_dump_regs(struct seq_file *s);
13363 +
13364 +void dsi_save_context(void);
13365 +void dsi_restore_context(void);
13366 +
13367 +int dsi_init_display(struct omap_dss_device *display);
13368 +void dsi_irq_handler(void);
13369 +unsigned long dsi_get_dsi1_pll_rate(void);
13370 +unsigned long dsi_get_dsi2_pll_rate(void);
13371 +int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck,
13372 +               struct dsi_clock_info *cinfo);
13373 +int dsi_pll_program(struct dsi_clock_info *cinfo);
13374 +int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv);
13375 +void dsi_pll_uninit(void);
13376 +void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
13377 +               u32 fifo_size, enum omap_burst_size *burst_size,
13378 +               u32 *fifo_low, u32 *fifo_high);
13379 +
13380 +/* DPI */
13381 +int dpi_init(void);
13382 +void dpi_exit(void);
13383 +int dpi_init_display(struct omap_dss_device *dssdev);
13384 +
13385 +/* DISPC */
13386 +int dispc_init(void);
13387 +void dispc_exit(void);
13388 +void dispc_dump_clocks(struct seq_file *s);
13389 +void dispc_dump_regs(struct seq_file *s);
13390 +void dispc_irq_handler(void);
13391 +void dispc_fake_vsync_irq(void);
13392 +
13393 +void dispc_save_context(void);
13394 +void dispc_restore_context(void);
13395 +
13396 +void dispc_enable_sidle(void);
13397 +void dispc_disable_sidle(void);
13398 +
13399 +void dispc_lcd_enable_signal_polarity(bool act_high);
13400 +void dispc_lcd_enable_signal(bool enable);
13401 +void dispc_pck_free_enable(bool enable);
13402 +void dispc_enable_fifohandcheck(bool enable);
13403 +
13404 +void dispc_set_lcd_size(u16 width, u16 height);
13405 +void dispc_set_digit_size(u16 width, u16 height);
13406 +u32 dispc_get_plane_fifo_size(enum omap_plane plane);
13407 +void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high);
13408 +void dispc_enable_fifomerge(bool enable);
13409 +void dispc_set_burst_size(enum omap_plane plane,
13410 +               enum omap_burst_size burst_size);
13411 +
13412 +void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
13413 +void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
13414 +void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y);
13415 +void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
13416 +void dispc_set_channel_out(enum omap_plane plane,
13417 +               enum omap_channel channel_out);
13418 +
13419 +int dispc_setup_plane(enum omap_plane plane,
13420 +                     u32 paddr, u16 screen_width,
13421 +                     u16 pos_x, u16 pos_y,
13422 +                     u16 width, u16 height,
13423 +                     u16 out_width, u16 out_height,
13424 +                     enum omap_color_mode color_mode,
13425 +                     bool ilace,
13426 +                     enum omap_dss_rotation_type rotation_type,
13427 +                     u8 rotation, bool mirror,
13428 +                     u8 global_alpha);
13429 +
13430 +bool dispc_go_busy(enum omap_channel channel);
13431 +void dispc_go(enum omap_channel channel);
13432 +void dispc_enable_lcd_out(bool enable);
13433 +void dispc_enable_digit_out(bool enable);
13434 +int dispc_enable_plane(enum omap_plane plane, bool enable);
13435 +void dispc_enable_replication(enum omap_plane plane, bool enable);
13436 +
13437 +void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode);
13438 +void dispc_set_tft_data_lines(u8 data_lines);
13439 +void dispc_set_lcd_display_type(enum omap_lcd_display_type type);
13440 +void dispc_set_loadmode(enum omap_dss_load_mode mode);
13441 +
13442 +void dispc_set_default_color(enum omap_channel channel, u32 color);
13443 +u32 dispc_get_default_color(enum omap_channel channel);
13444 +void dispc_set_trans_key(enum omap_channel ch,
13445 +               enum omap_dss_trans_key_type type,
13446 +               u32 trans_key);
13447 +void dispc_get_trans_key(enum omap_channel ch,
13448 +               enum omap_dss_trans_key_type *type,
13449 +               u32 *trans_key);
13450 +void dispc_enable_trans_key(enum omap_channel ch, bool enable);
13451 +void dispc_enable_alpha_blending(enum omap_channel ch, bool enable);
13452 +bool dispc_trans_key_enabled(enum omap_channel ch);
13453 +bool dispc_alpha_blending_enabled(enum omap_channel ch);
13454 +
13455 +bool dispc_lcd_timings_ok(struct omap_video_timings *timings);
13456 +void dispc_set_lcd_timings(struct omap_video_timings *timings);
13457 +unsigned long dispc_fclk_rate(void);
13458 +unsigned long dispc_lclk_rate(void);
13459 +unsigned long dispc_pclk_rate(void);
13460 +void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb);
13461 +void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
13462 +               u16 *lck_div, u16 *pck_div);
13463 +int dispc_calc_clock_div(bool is_tft, unsigned long req_pck,
13464 +               struct dispc_clock_info *cinfo);
13465 +int dispc_set_clock_div(struct dispc_clock_info *cinfo);
13466 +int dispc_get_clock_div(struct dispc_clock_info *cinfo);
13467 +void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div);
13468 +
13469 +
13470 +/* VENC */
13471 +int venc_init(struct platform_device *pdev);
13472 +void venc_exit(void);
13473 +void venc_dump_regs(struct seq_file *s);
13474 +int venc_init_display(struct omap_dss_device *display);
13475 +
13476 +/* RFBI */
13477 +int rfbi_init(void);
13478 +void rfbi_exit(void);
13479 +void rfbi_dump_regs(struct seq_file *s);
13480 +
13481 +int rfbi_configure(int rfbi_module, int bpp, int lines);
13482 +void rfbi_enable_rfbi(bool enable);
13483 +void rfbi_transfer_area(u16 width, u16 height,
13484 +                            void (callback)(void *data), void *data);
13485 +void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
13486 +unsigned long rfbi_get_max_tx_rate(void);
13487 +int rfbi_init_display(struct omap_dss_device *display);
13488 +
13489 +#endif
13490 diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
13491 new file mode 100644
13492 index 0000000..7ee0b2b
13493 --- /dev/null
13494 +++ b/drivers/video/omap2/dss/manager.c
13495 @@ -0,0 +1,1487 @@
13496 +/*
13497 + * linux/drivers/video/omap2/dss/manager.c
13498 + *
13499 + * Copyright (C) 2009 Nokia Corporation
13500 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
13501 + *
13502 + * Some code and ideas taken from drivers/video/omap/ driver
13503 + * by Imre Deak.
13504 + *
13505 + * This program is free software; you can redistribute it and/or modify it
13506 + * under the terms of the GNU General Public License version 2 as published by
13507 + * the Free Software Foundation.
13508 + *
13509 + * This program is distributed in the hope that it will be useful, but WITHOUT
13510 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13511 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13512 + * more details.
13513 + *
13514 + * You should have received a copy of the GNU General Public License along with
13515 + * this program.  If not, see <http://www.gnu.org/licenses/>.
13516 + */
13517 +
13518 +#define DSS_SUBSYS_NAME "MANAGER"
13519 +
13520 +#include <linux/kernel.h>
13521 +#include <linux/module.h>
13522 +#include <linux/platform_device.h>
13523 +#include <linux/spinlock.h>
13524 +#include <linux/jiffies.h>
13525 +
13526 +#include <mach/display.h>
13527 +#include <mach/cpu.h>
13528 +
13529 +#include "dss.h"
13530 +
13531 +static int num_managers;
13532 +static struct list_head manager_list;
13533 +
13534 +static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
13535 +{
13536 +       return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
13537 +}
13538 +
13539 +static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
13540 +{
13541 +       return snprintf(buf, PAGE_SIZE, "%s\n",
13542 +                       mgr->device ? mgr->device->name : "<none>");
13543 +}
13544 +
13545 +static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
13546 +               const char *buf, size_t size)
13547 +{
13548 +       int r = 0;
13549 +       size_t len = size;
13550 +       struct omap_dss_device *dssdev = NULL;
13551 +
13552 +       int match(struct omap_dss_device *dssdev, void *data)
13553 +       {
13554 +               const char *str = data;
13555 +               return sysfs_streq(dssdev->name, str);
13556 +       }
13557 +
13558 +       if (buf[size-1] == '\n')
13559 +               --len;
13560 +
13561 +       if (len > 0)
13562 +               dssdev = omap_dss_find_device((void *)buf, match);
13563 +
13564 +       if (len > 0 && dssdev == NULL)
13565 +               return -EINVAL;
13566 +
13567 +       if (dssdev)
13568 +               DSSDBG("display %s found\n", dssdev->name);
13569 +
13570 +       if (mgr->device) {
13571 +               r = mgr->unset_device(mgr);
13572 +               if (r) {
13573 +                       DSSERR("failed to unset display\n");
13574 +                       goto put_device;
13575 +               }
13576 +       }
13577 +
13578 +       if (dssdev) {
13579 +               r = mgr->set_device(mgr, dssdev);
13580 +               if (r) {
13581 +                       DSSERR("failed to set manager\n");
13582 +                       goto put_device;
13583 +               }
13584 +
13585 +               r = mgr->apply(mgr);
13586 +               if (r) {
13587 +                       DSSERR("failed to apply dispc config\n");
13588 +                       goto put_device;
13589 +               }
13590 +       }
13591 +
13592 +put_device:
13593 +       if (dssdev)
13594 +               omap_dss_put_device(dssdev);
13595 +
13596 +       return r ? r : size;
13597 +}
13598 +
13599 +static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
13600 +                                         char *buf)
13601 +{
13602 +       return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color);
13603 +}
13604 +
13605 +static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
13606 +                                          const char *buf, size_t size)
13607 +{
13608 +       struct omap_overlay_manager_info info;
13609 +       u32 color;
13610 +       int r;
13611 +
13612 +       if (sscanf(buf, "%d", &color) != 1)
13613 +               return -EINVAL;
13614 +
13615 +       mgr->get_manager_info(mgr, &info);
13616 +
13617 +       info.default_color = color;
13618 +
13619 +       r = mgr->set_manager_info(mgr, &info);
13620 +       if (r)
13621 +               return r;
13622 +
13623 +       r = mgr->apply(mgr);
13624 +       if (r)
13625 +               return r;
13626 +
13627 +       return size;
13628 +}
13629 +
13630 +static const char *trans_key_type_str[] = {
13631 +       "gfx-destination",
13632 +       "video-source",
13633 +};
13634 +
13635 +static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
13636 +                                          char *buf)
13637 +{
13638 +       enum omap_dss_trans_key_type key_type;
13639 +
13640 +       key_type = mgr->info.trans_key_type;
13641 +       BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
13642 +
13643 +       return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
13644 +}
13645 +
13646 +static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
13647 +                                           const char *buf, size_t size)
13648 +{
13649 +       enum omap_dss_trans_key_type key_type;
13650 +       struct omap_overlay_manager_info info;
13651 +       int r;
13652 +
13653 +       for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
13654 +                       key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
13655 +               if (sysfs_streq(buf, trans_key_type_str[key_type]))
13656 +                       break;
13657 +       }
13658 +
13659 +       if (key_type == ARRAY_SIZE(trans_key_type_str))
13660 +               return -EINVAL;
13661 +
13662 +       mgr->get_manager_info(mgr, &info);
13663 +
13664 +       info.trans_key_type = key_type;
13665 +
13666 +       r = mgr->set_manager_info(mgr, &info);
13667 +       if (r)
13668 +               return r;
13669 +
13670 +       r = mgr->apply(mgr);
13671 +       if (r)
13672 +               return r;
13673 +
13674 +       return size;
13675 +}
13676 +
13677 +static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
13678 +                                           char *buf)
13679 +{
13680 +       return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key);
13681 +}
13682 +
13683 +static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
13684 +                                            const char *buf, size_t size)
13685 +{
13686 +       struct omap_overlay_manager_info info;
13687 +       u32 key_value;
13688 +       int r;
13689 +
13690 +       if (sscanf(buf, "%d", &key_value) != 1)
13691 +               return -EINVAL;
13692 +
13693 +       mgr->get_manager_info(mgr, &info);
13694 +
13695 +       info.trans_key = key_value;
13696 +
13697 +       r = mgr->set_manager_info(mgr, &info);
13698 +       if (r)
13699 +               return r;
13700 +
13701 +       r = mgr->apply(mgr);
13702 +       if (r)
13703 +               return r;
13704 +
13705 +       return size;
13706 +}
13707 +
13708 +static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
13709 +                                             char *buf)
13710 +{
13711 +       return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_enabled);
13712 +}
13713 +
13714 +static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
13715 +                                              const char *buf, size_t size)
13716 +{
13717 +       struct omap_overlay_manager_info info;
13718 +       int enable;
13719 +       int r;
13720 +
13721 +       if (sscanf(buf, "%d", &enable) != 1)
13722 +               return -EINVAL;
13723 +
13724 +       mgr->get_manager_info(mgr, &info);
13725 +
13726 +       info.trans_enabled = enable ? true : false;
13727 +
13728 +       r = mgr->set_manager_info(mgr, &info);
13729 +       if (r)
13730 +               return r;
13731 +
13732 +       r = mgr->apply(mgr);
13733 +       if (r)
13734 +               return r;
13735 +
13736 +       return size;
13737 +}
13738 +
13739 +static ssize_t manager_alpha_blending_enabled_show(
13740 +               struct omap_overlay_manager *mgr, char *buf)
13741 +{
13742 +       return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled);
13743 +}
13744 +
13745 +static ssize_t manager_alpha_blending_enabled_store(
13746 +               struct omap_overlay_manager *mgr,
13747 +               const char *buf, size_t size)
13748 +{
13749 +       struct omap_overlay_manager_info info;
13750 +       int enable;
13751 +       int r;
13752 +
13753 +       if (sscanf(buf, "%d", &enable) != 1)
13754 +               return -EINVAL;
13755 +
13756 +       mgr->get_manager_info(mgr, &info);
13757 +
13758 +       info.alpha_enabled = enable ? true : false;
13759 +
13760 +       r = mgr->set_manager_info(mgr, &info);
13761 +       if (r)
13762 +               return r;
13763 +
13764 +       r = mgr->apply(mgr);
13765 +       if (r)
13766 +               return r;
13767 +
13768 +       return size;
13769 +}
13770 +
13771 +struct manager_attribute {
13772 +       struct attribute attr;
13773 +       ssize_t (*show)(struct omap_overlay_manager *, char *);
13774 +       ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
13775 +};
13776 +
13777 +#define MANAGER_ATTR(_name, _mode, _show, _store) \
13778 +       struct manager_attribute manager_attr_##_name = \
13779 +       __ATTR(_name, _mode, _show, _store)
13780 +
13781 +static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
13782 +static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
13783 +               manager_display_show, manager_display_store);
13784 +static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
13785 +               manager_default_color_show, manager_default_color_store);
13786 +static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
13787 +               manager_trans_key_type_show, manager_trans_key_type_store);
13788 +static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
13789 +               manager_trans_key_value_show, manager_trans_key_value_store);
13790 +static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
13791 +               manager_trans_key_enabled_show,
13792 +               manager_trans_key_enabled_store);
13793 +static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
13794 +               manager_alpha_blending_enabled_show,
13795 +               manager_alpha_blending_enabled_store);
13796 +
13797 +
13798 +static struct attribute *manager_sysfs_attrs[] = {
13799 +       &manager_attr_name.attr,
13800 +       &manager_attr_display.attr,
13801 +       &manager_attr_default_color.attr,
13802 +       &manager_attr_trans_key_type.attr,
13803 +       &manager_attr_trans_key_value.attr,
13804 +       &manager_attr_trans_key_enabled.attr,
13805 +       &manager_attr_alpha_blending_enabled.attr,
13806 +       NULL
13807 +};
13808 +
13809 +static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
13810 +               char *buf)
13811 +{
13812 +       struct omap_overlay_manager *manager;
13813 +       struct manager_attribute *manager_attr;
13814 +
13815 +       manager = container_of(kobj, struct omap_overlay_manager, kobj);
13816 +       manager_attr = container_of(attr, struct manager_attribute, attr);
13817 +
13818 +       if (!manager_attr->show)
13819 +               return -ENOENT;
13820 +
13821 +       return manager_attr->show(manager, buf);
13822 +}
13823 +
13824 +static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
13825 +               const char *buf, size_t size)
13826 +{
13827 +       struct omap_overlay_manager *manager;
13828 +       struct manager_attribute *manager_attr;
13829 +
13830 +       manager = container_of(kobj, struct omap_overlay_manager, kobj);
13831 +       manager_attr = container_of(attr, struct manager_attribute, attr);
13832 +
13833 +       if (!manager_attr->store)
13834 +               return -ENOENT;
13835 +
13836 +       return manager_attr->store(manager, buf, size);
13837 +}
13838 +
13839 +static struct sysfs_ops manager_sysfs_ops = {
13840 +       .show = manager_attr_show,
13841 +       .store = manager_attr_store,
13842 +};
13843 +
13844 +static struct kobj_type manager_ktype = {
13845 +       .sysfs_ops = &manager_sysfs_ops,
13846 +       .default_attrs = manager_sysfs_attrs,
13847 +};
13848 +
13849 +/*
13850 + * We have 4 levels of cache for the dispc settings. First two are in SW and
13851 + * the latter two in HW.
13852 + *
13853 + * +--------------------+
13854 + * |overlay/manager_info|
13855 + * +--------------------+
13856 + *          v
13857 + *        apply()
13858 + *          v
13859 + * +--------------------+
13860 + * |     dss_cache      |
13861 + * +--------------------+
13862 + *          v
13863 + *      configure()
13864 + *          v
13865 + * +--------------------+
13866 + * |  shadow registers  |
13867 + * +--------------------+
13868 + *          v
13869 + * VFP or lcd/digit_enable
13870 + *          v
13871 + * +--------------------+
13872 + * |      registers     |
13873 + * +--------------------+
13874 + */
13875 +
13876 +struct overlay_cache_data {
13877 +       /* If true, cache changed, but not written to shadow registers. Set
13878 +        * in apply(), cleared when registers written. */
13879 +       bool dirty;
13880 +       /* If true, shadow registers contain changed values not yet in real
13881 +        * registers. Set when writing to shadow registers, cleared at
13882 +        * VSYNC/EVSYNC */
13883 +       bool shadow_dirty;
13884 +
13885 +       bool enabled;
13886 +
13887 +       u32 paddr;
13888 +       void __iomem *vaddr;
13889 +       u16 screen_width;
13890 +       u16 width;
13891 +       u16 height;
13892 +       enum omap_color_mode color_mode;
13893 +       u8 rotation;
13894 +       enum omap_dss_rotation_type rotation_type;
13895 +       bool mirror;
13896 +
13897 +       u16 pos_x;
13898 +       u16 pos_y;
13899 +       u16 out_width;  /* if 0, out_width == width */
13900 +       u16 out_height; /* if 0, out_height == height */
13901 +       u8 global_alpha;
13902 +
13903 +       enum omap_channel channel;
13904 +       bool replication;
13905 +       bool ilace;
13906 +
13907 +       enum omap_burst_size burst_size;
13908 +       u32 fifo_low;
13909 +       u32 fifo_high;
13910 +
13911 +       bool manual_update;
13912 +};
13913 +
13914 +struct manager_cache_data {
13915 +       /* If true, cache changed, but not written to shadow registers. Set
13916 +        * in apply(), cleared when registers written. */
13917 +       bool dirty;
13918 +       /* If true, shadow registers contain changed values not yet in real
13919 +        * registers. Set when writing to shadow registers, cleared at
13920 +        * VSYNC/EVSYNC */
13921 +       bool shadow_dirty;
13922 +
13923 +       u32 default_color;
13924 +
13925 +       enum omap_dss_trans_key_type trans_key_type;
13926 +       u32 trans_key;
13927 +       bool trans_enabled;
13928 +
13929 +       bool alpha_enabled;
13930 +
13931 +       bool manual_upd_display;
13932 +       bool manual_update;
13933 +       bool do_manual_update;
13934 +
13935 +       /* manual update region */
13936 +       u16 x, y, w, h;
13937 +};
13938 +
13939 +static struct {
13940 +       spinlock_t lock;
13941 +       struct overlay_cache_data overlay_cache[3];
13942 +       struct manager_cache_data manager_cache[2];
13943 +
13944 +       bool irq_enabled;
13945 +} dss_cache;
13946 +
13947 +
13948 +
13949 +static int omap_dss_set_device(struct omap_overlay_manager *mgr,
13950 +               struct omap_dss_device *dssdev)
13951 +{
13952 +       int i;
13953 +       int r;
13954 +
13955 +       if (dssdev->manager) {
13956 +               DSSERR("display '%s' already has a manager '%s'\n",
13957 +                              dssdev->name, dssdev->manager->name);
13958 +               return -EINVAL;
13959 +       }
13960 +
13961 +       if ((mgr->supported_displays & dssdev->type) == 0) {
13962 +               DSSERR("display '%s' does not support manager '%s'\n",
13963 +                              dssdev->name, mgr->name);
13964 +               return -EINVAL;
13965 +       }
13966 +
13967 +       for (i = 0; i < mgr->num_overlays; i++) {
13968 +               struct omap_overlay *ovl = mgr->overlays[i];
13969 +
13970 +               if (ovl->manager != mgr || !ovl->info.enabled)
13971 +                       continue;
13972 +
13973 +               r = dss_check_overlay(ovl, dssdev);
13974 +               if (r)
13975 +                       return r;
13976 +       }
13977 +
13978 +       dssdev->manager = mgr;
13979 +       mgr->device = dssdev;
13980 +       mgr->device_changed = true;
13981 +
13982 +       return 0;
13983 +}
13984 +
13985 +static int omap_dss_unset_device(struct omap_overlay_manager *mgr)
13986 +{
13987 +       if (!mgr->device) {
13988 +               DSSERR("failed to unset display, display not set.\n");
13989 +               return -EINVAL;
13990 +       }
13991 +
13992 +       mgr->device->manager = NULL;
13993 +       mgr->device = NULL;
13994 +       mgr->device_changed = true;
13995 +
13996 +       return 0;
13997 +}
13998 +
13999 +static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
14000 +{
14001 +       unsigned long timeout = msecs_to_jiffies(500);
14002 +       struct manager_cache_data *mc;
14003 +       enum omap_channel channel;
14004 +       u32 irq;
14005 +       int r;
14006 +       int i;
14007 +
14008 +       if (!mgr->device)
14009 +               return 0;
14010 +
14011 +       if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) {
14012 +               irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
14013 +               channel = OMAP_DSS_CHANNEL_DIGIT;
14014 +       } else {
14015 +               if (mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
14016 +                       enum omap_dss_update_mode mode;
14017 +                       mode = mgr->device->get_update_mode(mgr->device);
14018 +                       if (mode != OMAP_DSS_UPDATE_AUTO)
14019 +                               return 0;
14020 +
14021 +                       irq = DISPC_IRQ_FRAMEDONE;
14022 +               } else {
14023 +                       irq = DISPC_IRQ_VSYNC;
14024 +               }
14025 +               channel = OMAP_DSS_CHANNEL_LCD;
14026 +       }
14027 +
14028 +       mc = &dss_cache.manager_cache[mgr->id];
14029 +       i = 0;
14030 +       while (1) {
14031 +               unsigned long flags;
14032 +               bool shadow_dirty, dirty;
14033 +
14034 +               spin_lock_irqsave(&dss_cache.lock, flags);
14035 +               dirty = mc->dirty;
14036 +               shadow_dirty = mc->shadow_dirty;
14037 +               spin_unlock_irqrestore(&dss_cache.lock, flags);
14038 +
14039 +               if (!dirty && !shadow_dirty) {
14040 +                       r = 0;
14041 +                       break;
14042 +               }
14043 +
14044 +               /* 4 iterations is the worst case:
14045 +                * 1 - initial iteration, dirty = true (between VFP and VSYNC)
14046 +                * 2 - first VSYNC, dirty = true
14047 +                * 3 - dirty = false, shadow_dirty = true
14048 +                * 4 - shadow_dirty = false */
14049 +               if (i++ == 3) {
14050 +                       DSSERR("mgr(%d)->wait_for_go() not finishing\n",
14051 +                                       mgr->id);
14052 +                       r = 0;
14053 +                       break;
14054 +               }
14055 +
14056 +               r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
14057 +               if (r == -ERESTARTSYS)
14058 +                       break;
14059 +
14060 +               if (r) {
14061 +                       DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
14062 +                       break;
14063 +               }
14064 +       }
14065 +
14066 +       return r;
14067 +}
14068 +
14069 +int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
14070 +{
14071 +       unsigned long timeout = msecs_to_jiffies(500);
14072 +       enum omap_channel channel;
14073 +       struct overlay_cache_data *oc;
14074 +       struct omap_dss_device *dssdev;
14075 +       u32 irq;
14076 +       int r;
14077 +       int i;
14078 +
14079 +       if (!ovl->manager || !ovl->manager->device)
14080 +               return 0;
14081 +
14082 +       dssdev = ovl->manager->device;
14083 +
14084 +       if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
14085 +               irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
14086 +               channel = OMAP_DSS_CHANNEL_DIGIT;
14087 +       } else {
14088 +               if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
14089 +                       enum omap_dss_update_mode mode;
14090 +                       mode = dssdev->get_update_mode(dssdev);
14091 +                       if (mode != OMAP_DSS_UPDATE_AUTO)
14092 +                               return 0;
14093 +
14094 +                       irq = DISPC_IRQ_FRAMEDONE;
14095 +               } else {
14096 +                       irq = DISPC_IRQ_VSYNC;
14097 +               }
14098 +               channel = OMAP_DSS_CHANNEL_LCD;
14099 +       }
14100 +
14101 +       oc = &dss_cache.overlay_cache[ovl->id];
14102 +       i = 0;
14103 +       while (1) {
14104 +               unsigned long flags;
14105 +               bool shadow_dirty, dirty;
14106 +
14107 +               spin_lock_irqsave(&dss_cache.lock, flags);
14108 +               dirty = oc->dirty;
14109 +               shadow_dirty = oc->shadow_dirty;
14110 +               spin_unlock_irqrestore(&dss_cache.lock, flags);
14111 +
14112 +               if (!dirty && !shadow_dirty) {
14113 +                       r = 0;
14114 +                       break;
14115 +               }
14116 +
14117 +               /* 4 iterations is the worst case:
14118 +                * 1 - initial iteration, dirty = true (between VFP and VSYNC)
14119 +                * 2 - first VSYNC, dirty = true
14120 +                * 3 - dirty = false, shadow_dirty = true
14121 +                * 4 - shadow_dirty = false */
14122 +               if (i++ == 3) {
14123 +                       DSSERR("ovl(%d)->wait_for_go() not finishing\n",
14124 +                                       ovl->id);
14125 +                       r = 0;
14126 +                       break;
14127 +               }
14128 +
14129 +               r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
14130 +               if (r == -ERESTARTSYS)
14131 +                       break;
14132 +
14133 +               if (r) {
14134 +                       DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
14135 +                       break;
14136 +               }
14137 +       }
14138 +
14139 +       return r;
14140 +}
14141 +
14142 +static int overlay_enabled(struct omap_overlay *ovl)
14143 +{
14144 +       return ovl->info.enabled && ovl->manager && ovl->manager->device;
14145 +}
14146 +
14147 +/* Is rect1 a subset of rect2? */
14148 +static bool rectangle_subset(int x1, int y1, int w1, int h1,
14149 +               int x2, int y2, int w2, int h2)
14150 +{
14151 +       if (x1 < x2 || y1 < y2)
14152 +               return false;
14153 +
14154 +       if (x1 + w1 > x2 + w2)
14155 +               return false;
14156 +
14157 +       if (y1 + h1 > y2 + h2)
14158 +               return false;
14159 +
14160 +       return true;
14161 +}
14162 +
14163 +/* Do rect1 and rect2 overlap? */
14164 +static bool rectangle_intersects(int x1, int y1, int w1, int h1,
14165 +               int x2, int y2, int w2, int h2)
14166 +{
14167 +       if (x1 >= x2 + w2)
14168 +               return false;
14169 +
14170 +       if (x2 >= x1 + w1)
14171 +               return false;
14172 +
14173 +       if (y1 >= y2 + h2)
14174 +               return false;
14175 +
14176 +       if (y2 >= y1 + h1)
14177 +               return false;
14178 +
14179 +       return true;
14180 +}
14181 +
14182 +static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc)
14183 +{
14184 +       if (oc->out_width != 0 && oc->width != oc->out_width)
14185 +               return true;
14186 +
14187 +       if (oc->out_height != 0 && oc->height != oc->out_height)
14188 +               return true;
14189 +
14190 +       return false;
14191 +}
14192 +
14193 +static int configure_overlay(enum omap_plane plane)
14194 +{
14195 +       struct overlay_cache_data *c;
14196 +       struct manager_cache_data *mc;
14197 +       u16 outw, outh;
14198 +       u16 x, y, w, h;
14199 +       u32 paddr;
14200 +       int r;
14201 +
14202 +       DSSDBGF("%d", plane);
14203 +
14204 +       c = &dss_cache.overlay_cache[plane];
14205 +
14206 +       if (!c->enabled) {
14207 +               dispc_enable_plane(plane, 0);
14208 +               return 0;
14209 +       }
14210 +
14211 +       mc = &dss_cache.manager_cache[c->channel];
14212 +
14213 +       x = c->pos_x;
14214 +       y = c->pos_y;
14215 +       w = c->width;
14216 +       h = c->height;
14217 +       outw = c->out_width == 0 ? c->width : c->out_width;
14218 +       outh = c->out_height == 0 ? c->height : c->out_height;
14219 +       paddr = c->paddr;
14220 +
14221 +       if (c->manual_update && mc->do_manual_update) {
14222 +               unsigned bpp;
14223 +               /* If the overlay is outside the update region, disable it */
14224 +               if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
14225 +                                       x, y, outw, outh)) {
14226 +                       dispc_enable_plane(plane, 0);
14227 +                       return 0;
14228 +               }
14229 +
14230 +               switch (c->color_mode) {
14231 +               case OMAP_DSS_COLOR_RGB16:
14232 +               case OMAP_DSS_COLOR_ARGB16:
14233 +               case OMAP_DSS_COLOR_YUV2:
14234 +               case OMAP_DSS_COLOR_UYVY:
14235 +                       bpp = 16;
14236 +                       break;
14237 +
14238 +               case OMAP_DSS_COLOR_RGB24P:
14239 +                       bpp = 24;
14240 +                       break;
14241 +
14242 +               case OMAP_DSS_COLOR_RGB24U:
14243 +               case OMAP_DSS_COLOR_ARGB32:
14244 +               case OMAP_DSS_COLOR_RGBA32:
14245 +               case OMAP_DSS_COLOR_RGBX32:
14246 +                       bpp = 32;
14247 +                       break;
14248 +
14249 +               default:
14250 +                       BUG();
14251 +               }
14252 +
14253 +               if (dispc_is_overlay_scaled(c)) {
14254 +                       /* If the overlay is scaled, the update area has
14255 +                        * already been enlarged to cover the whole overlay. We
14256 +                        * only need to adjust x/y here */
14257 +                       x = c->pos_x - mc->x;
14258 +                       y = c->pos_y - mc->y;
14259 +               } else {
14260 +                       if (mc->x > c->pos_x) {
14261 +                               x = 0;
14262 +                               w -= (mc->x - c->pos_x);
14263 +                               paddr += (mc->x - c->pos_x) * bpp / 8;
14264 +                       } else {
14265 +                               x = c->pos_x - mc->x;
14266 +                       }
14267 +
14268 +                       if (mc->y > c->pos_y) {
14269 +                               y = 0;
14270 +                               h -= (mc->y - c->pos_y);
14271 +                               paddr += (mc->y - c->pos_y) * c->screen_width *
14272 +                                       bpp / 8;
14273 +                       } else {
14274 +                               y = c->pos_y - mc->y;
14275 +                       }
14276 +
14277 +                       if (mc->w < (x+w))
14278 +                               w -= (x+w) - (mc->w);
14279 +
14280 +                       if (mc->h < (y+h))
14281 +                               h -= (y+h) - (mc->h);
14282 +
14283 +                       outw = w;
14284 +                       outh = h;
14285 +               }
14286 +       }
14287 +
14288 +       r = dispc_setup_plane(plane,
14289 +                       paddr,
14290 +                       c->screen_width,
14291 +                       x, y,
14292 +                       w, h,
14293 +                       outw, outh,
14294 +                       c->color_mode,
14295 +                       c->ilace,
14296 +                       c->rotation_type,
14297 +                       c->rotation,
14298 +                       c->mirror,
14299 +                       c->global_alpha);
14300 +
14301 +       if (r) {
14302 +               /* this shouldn't happen */
14303 +               DSSERR("dispc_setup_plane failed for ovl %d\n", plane);
14304 +               dispc_enable_plane(plane, 0);
14305 +               return r;
14306 +       }
14307 +
14308 +       dispc_enable_replication(plane, c->replication);
14309 +
14310 +       dispc_set_burst_size(plane, c->burst_size);
14311 +       dispc_setup_plane_fifo(plane, c->fifo_low, c->fifo_high);
14312 +
14313 +       dispc_enable_plane(plane, 1);
14314 +
14315 +       return 0;
14316 +}
14317 +
14318 +static void configure_manager(enum omap_channel channel)
14319 +{
14320 +       struct manager_cache_data *c;
14321 +
14322 +       DSSDBGF("%d", channel);
14323 +
14324 +       c = &dss_cache.manager_cache[channel];
14325 +
14326 +       dispc_set_trans_key(channel, c->trans_key_type, c->trans_key);
14327 +       dispc_enable_trans_key(channel, c->trans_enabled);
14328 +       dispc_enable_alpha_blending(channel, c->alpha_enabled);
14329 +}
14330 +
14331 +/* configure_dispc() tries to write values from cache to shadow registers.
14332 + * It writes only to those managers/overlays that are not busy.
14333 + * returns 0 if everything could be written to shadow registers.
14334 + * returns 1 if not everything could be written to shadow registers. */
14335 +static int configure_dispc(void)
14336 +{
14337 +       struct overlay_cache_data *oc;
14338 +       struct manager_cache_data *mc;
14339 +       const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
14340 +       const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
14341 +       int i;
14342 +       int r;
14343 +       bool mgr_busy[2];
14344 +       bool mgr_go[2];
14345 +       bool busy;
14346 +
14347 +       r = 0;
14348 +       busy = false;
14349 +
14350 +       mgr_busy[0] = dispc_go_busy(0);
14351 +       mgr_busy[1] = dispc_go_busy(1);
14352 +       mgr_go[0] = false;
14353 +       mgr_go[1] = false;
14354 +
14355 +       /* Commit overlay settings */
14356 +       for (i = 0; i < num_ovls; ++i) {
14357 +               oc = &dss_cache.overlay_cache[i];
14358 +               mc = &dss_cache.manager_cache[oc->channel];
14359 +
14360 +               if (!oc->dirty)
14361 +                       continue;
14362 +
14363 +               if (oc->manual_update && !mc->do_manual_update)
14364 +                       continue;
14365 +
14366 +               if (mgr_busy[oc->channel]) {
14367 +                       busy = true;
14368 +                       continue;
14369 +               }
14370 +
14371 +               r = configure_overlay(i);
14372 +               if (r)
14373 +                       DSSERR("configure_overlay %d failed\n", i);
14374 +
14375 +               oc->dirty = false;
14376 +               oc->shadow_dirty = true;
14377 +               mgr_go[oc->channel] = true;
14378 +       }
14379 +
14380 +       /* Commit manager settings */
14381 +       for (i = 0; i < num_mgrs; ++i) {
14382 +               mc = &dss_cache.manager_cache[i];
14383 +
14384 +               if (!mc->dirty)
14385 +                       continue;
14386 +
14387 +               if (mc->manual_update && !mc->do_manual_update)
14388 +                       continue;
14389 +
14390 +               if (mgr_busy[i]) {
14391 +                       busy = true;
14392 +                       continue;
14393 +               }
14394 +
14395 +               configure_manager(i);
14396 +               mc->dirty = false;
14397 +               mc->shadow_dirty = true;
14398 +               mgr_go[i] = true;
14399 +       }
14400 +
14401 +       /* set GO */
14402 +       for (i = 0; i < num_mgrs; ++i) {
14403 +               mc = &dss_cache.manager_cache[i];
14404 +
14405 +               if (!mgr_go[i])
14406 +                       continue;
14407 +
14408 +               /* We don't need GO with manual update display. LCD iface will
14409 +                * always be turned off after frame, and new settings will be
14410 +                * taken in to use at next update */
14411 +               if (!mc->manual_upd_display)
14412 +                       dispc_go(i);
14413 +       }
14414 +
14415 +       if (busy)
14416 +               r = 1;
14417 +       else
14418 +               r = 0;
14419 +
14420 +       return r;
14421 +}
14422 +
14423 +/* Configure dispc for partial update. Return possibly modified update
14424 + * area */
14425 +void dss_setup_partial_planes(struct omap_dss_device *dssdev,
14426 +               u16 *xi, u16 *yi, u16 *wi, u16 *hi)
14427 +{
14428 +       struct overlay_cache_data *oc;
14429 +       struct manager_cache_data *mc;
14430 +       const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
14431 +       struct omap_overlay_manager *mgr;
14432 +       int i;
14433 +       u16 x, y, w, h;
14434 +       unsigned long flags;
14435 +
14436 +       x = *xi;
14437 +       y = *yi;
14438 +       w = *wi;
14439 +       h = *hi;
14440 +
14441 +       DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n",
14442 +               *xi, *yi, *wi, *hi);
14443 +
14444 +       mgr = dssdev->manager;
14445 +
14446 +       if (!mgr) {
14447 +               DSSDBG("no manager\n");
14448 +               return;
14449 +       }
14450 +
14451 +       spin_lock_irqsave(&dss_cache.lock, flags);
14452 +
14453 +       /* We need to show the whole overlay if it is scaled. So look for
14454 +        * those, and make the update area larger if found.
14455 +        * Also mark the overlay cache dirty */
14456 +       for (i = 0; i < num_ovls; ++i) {
14457 +               unsigned x1, y1, x2, y2;
14458 +               unsigned outw, outh;
14459 +
14460 +               oc = &dss_cache.overlay_cache[i];
14461 +
14462 +               if (oc->channel != mgr->id)
14463 +                       continue;
14464 +
14465 +               oc->dirty = true;
14466 +
14467 +               if (!oc->enabled)
14468 +                       continue;
14469 +
14470 +               if (!dispc_is_overlay_scaled(oc))
14471 +                       continue;
14472 +
14473 +               outw = oc->out_width == 0 ? oc->width : oc->out_width;
14474 +               outh = oc->out_height == 0 ? oc->height : oc->out_height;
14475 +
14476 +               /* is the overlay outside the update region? */
14477 +               if (!rectangle_intersects(x, y, w, h,
14478 +                                       oc->pos_x, oc->pos_y,
14479 +                                       outw, outh))
14480 +                       continue;
14481 +
14482 +               /* if the overlay totally inside the update region? */
14483 +               if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
14484 +                                       x, y, w, h))
14485 +                       continue;
14486 +
14487 +               if (x > oc->pos_x)
14488 +                       x1 = oc->pos_x;
14489 +               else
14490 +                       x1 = x;
14491 +
14492 +               if (y > oc->pos_y)
14493 +                       y1 = oc->pos_y;
14494 +               else
14495 +                       y1 = y;
14496 +
14497 +               if ((x + w) < (oc->pos_x + outw))
14498 +                       x2 = oc->pos_x + outw;
14499 +               else
14500 +                       x2 = x + w;
14501 +
14502 +               if ((y + h) < (oc->pos_y + outh))
14503 +                       y2 = oc->pos_y + outh;
14504 +               else
14505 +                       y2 = y + h;
14506 +
14507 +               x = x1;
14508 +               y = y1;
14509 +               w = x2 - x1;
14510 +               h = y2 - y1;
14511 +
14512 +               DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n",
14513 +                               i, x, y, w, h);
14514 +       }
14515 +
14516 +       mc = &dss_cache.manager_cache[mgr->id];
14517 +       mc->do_manual_update = true;
14518 +       mc->x = x;
14519 +       mc->y = y;
14520 +       mc->w = w;
14521 +       mc->h = h;
14522 +
14523 +       configure_dispc();
14524 +
14525 +       mc->do_manual_update = false;
14526 +
14527 +       spin_unlock_irqrestore(&dss_cache.lock, flags);
14528 +
14529 +       *xi = x;
14530 +       *yi = y;
14531 +       *wi = w;
14532 +       *hi = h;
14533 +}
14534 +
14535 +void dss_start_update(struct omap_dss_device *dssdev)
14536 +{
14537 +       struct manager_cache_data *mc;
14538 +       struct overlay_cache_data *oc;
14539 +       const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
14540 +       const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
14541 +       struct omap_overlay_manager *mgr;
14542 +       int i;
14543 +
14544 +       mgr = dssdev->manager;
14545 +
14546 +       for (i = 0; i < num_ovls; ++i) {
14547 +               oc = &dss_cache.overlay_cache[i];
14548 +               if (oc->channel != mgr->id)
14549 +                       continue;
14550 +
14551 +               oc->shadow_dirty = false;
14552 +       }
14553 +
14554 +       for (i = 0; i < num_mgrs; ++i) {
14555 +               mc = &dss_cache.manager_cache[i];
14556 +               if (mgr->id != i)
14557 +                       continue;
14558 +
14559 +               mc->shadow_dirty = false;
14560 +       }
14561 +
14562 +       dispc_enable_lcd_out(1);
14563 +}
14564 +
14565 +static void dss_apply_irq_handler(void *data, u32 mask)
14566 +{
14567 +       struct manager_cache_data *mc;
14568 +       struct overlay_cache_data *oc;
14569 +       const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
14570 +       const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
14571 +       int i, r;
14572 +       bool mgr_busy[2];
14573 +
14574 +       mgr_busy[0] = dispc_go_busy(0);
14575 +       mgr_busy[1] = dispc_go_busy(1);
14576 +
14577 +       spin_lock(&dss_cache.lock);
14578 +
14579 +       for (i = 0; i < num_ovls; ++i) {
14580 +               oc = &dss_cache.overlay_cache[i];
14581 +               if (!mgr_busy[oc->channel])
14582 +                       oc->shadow_dirty = false;
14583 +       }
14584 +
14585 +       for (i = 0; i < num_mgrs; ++i) {
14586 +               mc = &dss_cache.manager_cache[i];
14587 +               if (!mgr_busy[i])
14588 +                       mc->shadow_dirty = false;
14589 +       }
14590 +
14591 +       r = configure_dispc();
14592 +       if (r == 1)
14593 +               goto end;
14594 +
14595 +       /* re-read busy flags */
14596 +       mgr_busy[0] = dispc_go_busy(0);
14597 +       mgr_busy[1] = dispc_go_busy(1);
14598 +
14599 +       /* keep running as long as there are busy managers, so that
14600 +        * we can collect overlay-applied information */
14601 +       for (i = 0; i < num_mgrs; ++i) {
14602 +               if (mgr_busy[i])
14603 +                       goto end;
14604 +       }
14605 +
14606 +       omap_dispc_unregister_isr(dss_apply_irq_handler, NULL,
14607 +                       DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
14608 +                       DISPC_IRQ_EVSYNC_EVEN);
14609 +       dss_cache.irq_enabled = false;
14610 +
14611 +end:
14612 +       spin_unlock(&dss_cache.lock);
14613 +}
14614 +
14615 +static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
14616 +{
14617 +       struct overlay_cache_data *oc;
14618 +       struct manager_cache_data *mc;
14619 +       int i;
14620 +       struct omap_overlay *ovl;
14621 +       int num_planes_enabled = 0;
14622 +       bool use_fifomerge;
14623 +       unsigned long flags;
14624 +       int r;
14625 +
14626 +       DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
14627 +
14628 +       spin_lock_irqsave(&dss_cache.lock, flags);
14629 +
14630 +       /* Configure overlays */
14631 +       for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
14632 +               struct omap_dss_device *dssdev;
14633 +
14634 +               ovl = omap_dss_get_overlay(i);
14635 +
14636 +               if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
14637 +                       continue;
14638 +
14639 +               oc = &dss_cache.overlay_cache[ovl->id];
14640 +
14641 +               if (!overlay_enabled(ovl)) {
14642 +                       if (oc->enabled) {
14643 +                               oc->enabled = false;
14644 +                               oc->dirty = true;
14645 +                       }
14646 +                       continue;
14647 +               }
14648 +
14649 +               if (!ovl->info_dirty) {
14650 +                       if (oc->enabled)
14651 +                               ++num_planes_enabled;
14652 +                       continue;
14653 +               }
14654 +
14655 +               dssdev = ovl->manager->device;
14656 +
14657 +               if (dss_check_overlay(ovl, dssdev)) {
14658 +                       if (oc->enabled) {
14659 +                               oc->enabled = false;
14660 +                               oc->dirty = true;
14661 +                       }
14662 +                       continue;
14663 +               }
14664 +
14665 +               ovl->info_dirty = false;
14666 +               oc->dirty = true;
14667 +
14668 +               oc->paddr = ovl->info.paddr;
14669 +               oc->vaddr = ovl->info.vaddr;
14670 +               oc->screen_width = ovl->info.screen_width;
14671 +               oc->width = ovl->info.width;
14672 +               oc->height = ovl->info.height;
14673 +               oc->color_mode = ovl->info.color_mode;
14674 +               oc->rotation = ovl->info.rotation;
14675 +               oc->rotation_type = ovl->info.rotation_type;
14676 +               oc->mirror = ovl->info.mirror;
14677 +               oc->pos_x = ovl->info.pos_x;
14678 +               oc->pos_y = ovl->info.pos_y;
14679 +               oc->out_width = ovl->info.out_width;
14680 +               oc->out_height = ovl->info.out_height;
14681 +               oc->global_alpha = ovl->info.global_alpha;
14682 +
14683 +               oc->replication =
14684 +                       dss_use_replication(dssdev, ovl->info.color_mode);
14685 +
14686 +               oc->ilace = dssdev->type == OMAP_DISPLAY_TYPE_VENC;
14687 +
14688 +               oc->channel = ovl->manager->id;
14689 +
14690 +               oc->enabled = true;
14691 +
14692 +               oc->manual_update =
14693 +                       dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
14694 +                       dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO;
14695 +
14696 +               ++num_planes_enabled;
14697 +       }
14698 +
14699 +       /* Configure managers */
14700 +       list_for_each_entry(mgr, &manager_list, list) {
14701 +               struct omap_dss_device *dssdev;
14702 +
14703 +               if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
14704 +                       continue;
14705 +
14706 +               mc = &dss_cache.manager_cache[mgr->id];
14707 +
14708 +               if (mgr->device_changed) {
14709 +                       mgr->device_changed = false;
14710 +                       mgr->info_dirty  = true;
14711 +               }
14712 +
14713 +               if (!mgr->info_dirty)
14714 +                       continue;
14715 +
14716 +               if (!mgr->device)
14717 +                       continue;
14718 +
14719 +               dssdev = mgr->device;
14720 +
14721 +               mgr->info_dirty = false;
14722 +               mc->dirty = true;
14723 +
14724 +               mc->default_color = mgr->info.default_color;
14725 +               mc->trans_key_type = mgr->info.trans_key_type;
14726 +               mc->trans_key = mgr->info.trans_key;
14727 +               mc->trans_enabled = mgr->info.trans_enabled;
14728 +               mc->alpha_enabled = mgr->info.alpha_enabled;
14729 +
14730 +               mc->manual_upd_display =
14731 +                       dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
14732 +
14733 +               mc->manual_update =
14734 +                       dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
14735 +                       dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO;
14736 +       }
14737 +
14738 +       /* XXX TODO: Try to get fifomerge working. The problem is that it
14739 +        * affects both managers, not individually but at the same time. This
14740 +        * means the change has to be well synchronized. I guess the proper way
14741 +        * is to have a two step process for fifo merge:
14742 +        *        fifomerge enable:
14743 +        *             1. disable other planes, leaving one plane enabled
14744 +        *             2. wait until the planes are disabled on HW
14745 +        *             3. config merged fifo thresholds, enable fifomerge
14746 +        *        fifomerge disable:
14747 +        *             1. config unmerged fifo thresholds, disable fifomerge
14748 +        *             2. wait until fifo changes are in HW
14749 +        *             3. enable planes
14750 +        */
14751 +       use_fifomerge = false;
14752 +
14753 +       /* Configure overlay fifos */
14754 +       for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
14755 +               struct omap_dss_device *dssdev;
14756 +               u32 size;
14757 +
14758 +               ovl = omap_dss_get_overlay(i);
14759 +
14760 +               if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
14761 +                       continue;
14762 +
14763 +               oc = &dss_cache.overlay_cache[ovl->id];
14764 +
14765 +               if (!oc->enabled)
14766 +                       continue;
14767 +
14768 +               dssdev = ovl->manager->device;
14769 +
14770 +               size = dispc_get_plane_fifo_size(ovl->id);
14771 +               if (use_fifomerge)
14772 +                       size *= 3;
14773 +
14774 +               switch (dssdev->type) {
14775 +               case OMAP_DISPLAY_TYPE_DPI:
14776 +               case OMAP_DISPLAY_TYPE_DBI:
14777 +               case OMAP_DISPLAY_TYPE_SDI:
14778 +               case OMAP_DISPLAY_TYPE_VENC:
14779 +                       default_get_overlay_fifo_thresholds(ovl->id, size,
14780 +                                       &oc->burst_size, &oc->fifo_low,
14781 +                                       &oc->fifo_high);
14782 +                       break;
14783 +#ifdef CONFIG_OMAP2_DSS_DSI
14784 +               case OMAP_DISPLAY_TYPE_DSI:
14785 +                       dsi_get_overlay_fifo_thresholds(ovl->id, size,
14786 +                                       &oc->burst_size, &oc->fifo_low,
14787 +                                       &oc->fifo_high);
14788 +                       break;
14789 +#endif
14790 +               default:
14791 +                       BUG();
14792 +               }
14793 +       }
14794 +
14795 +       r = 0;
14796 +       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
14797 +       if (!dss_cache.irq_enabled) {
14798 +               r = omap_dispc_register_isr(dss_apply_irq_handler, NULL,
14799 +                               DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
14800 +                               DISPC_IRQ_EVSYNC_EVEN);
14801 +               dss_cache.irq_enabled = true;
14802 +       }
14803 +       configure_dispc();
14804 +       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
14805 +
14806 +       spin_unlock_irqrestore(&dss_cache.lock, flags);
14807 +
14808 +       return r;
14809 +}
14810 +
14811 +static int dss_check_manager(struct omap_overlay_manager *mgr)
14812 +{
14813 +       /* OMAP supports only graphics source transparency color key and alpha
14814 +        * blending simultaneously. See TRM 15.4.2.4.2.2 Alpha Mode */
14815 +
14816 +       if (mgr->info.alpha_enabled && mgr->info.trans_enabled &&
14817 +                       mgr->info.trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST)
14818 +               return -EINVAL;
14819 +
14820 +       return 0;
14821 +}
14822 +
14823 +static int omap_dss_mgr_set_info(struct omap_overlay_manager *mgr,
14824 +               struct omap_overlay_manager_info *info)
14825 +{
14826 +       int r;
14827 +       struct omap_overlay_manager_info old_info;
14828 +
14829 +       old_info = mgr->info;
14830 +       mgr->info = *info;
14831 +
14832 +       r = dss_check_manager(mgr);
14833 +       if (r) {
14834 +               mgr->info = old_info;
14835 +               return r;
14836 +       }
14837 +
14838 +       mgr->info_dirty = true;
14839 +
14840 +       return 0;
14841 +}
14842 +
14843 +static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,
14844 +               struct omap_overlay_manager_info *info)
14845 +{
14846 +       *info = mgr->info;
14847 +}
14848 +
14849 +static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
14850 +{
14851 +       ++num_managers;
14852 +       list_add_tail(&manager->list, &manager_list);
14853 +}
14854 +
14855 +int dss_init_overlay_managers(struct platform_device *pdev)
14856 +{
14857 +       int i, r;
14858 +
14859 +       spin_lock_init(&dss_cache.lock);
14860 +
14861 +       INIT_LIST_HEAD(&manager_list);
14862 +
14863 +       num_managers = 0;
14864 +
14865 +       for (i = 0; i < 2; ++i) {
14866 +               struct omap_overlay_manager *mgr;
14867 +               mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
14868 +
14869 +               BUG_ON(mgr == NULL);
14870 +
14871 +               switch (i) {
14872 +               case 0:
14873 +                       mgr->name = "lcd";
14874 +                       mgr->id = OMAP_DSS_CHANNEL_LCD;
14875 +                       mgr->supported_displays =
14876 +                               OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
14877 +                               OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI;
14878 +                       break;
14879 +               case 1:
14880 +                       mgr->name = "tv";
14881 +                       mgr->id = OMAP_DSS_CHANNEL_DIGIT;
14882 +                       mgr->supported_displays = OMAP_DISPLAY_TYPE_VENC;
14883 +                       break;
14884 +               }
14885 +
14886 +               mgr->set_device = &omap_dss_set_device;
14887 +               mgr->unset_device = &omap_dss_unset_device;
14888 +               mgr->apply = &omap_dss_mgr_apply;
14889 +               mgr->set_manager_info = &omap_dss_mgr_set_info;
14890 +               mgr->get_manager_info = &omap_dss_mgr_get_info;
14891 +               mgr->wait_for_go = &dss_mgr_wait_for_go;
14892 +
14893 +               mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
14894 +
14895 +               dss_overlay_setup_dispc_manager(mgr);
14896 +
14897 +               omap_dss_add_overlay_manager(mgr);
14898 +
14899 +               r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
14900 +                               &pdev->dev.kobj, "manager%d", i);
14901 +
14902 +               if (r) {
14903 +                       DSSERR("failed to create sysfs file\n");
14904 +                       continue;
14905 +               }
14906 +       }
14907 +
14908 +#ifdef L4_EXAMPLE
14909 +       {
14910 +               int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr)
14911 +               {
14912 +                       DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);
14913 +
14914 +                       return 0;
14915 +               }
14916 +
14917 +               struct omap_overlay_manager *mgr;
14918 +               mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
14919 +
14920 +               BUG_ON(mgr == NULL);
14921 +
14922 +               mgr->name = "l4";
14923 +               mgr->supported_displays =
14924 +                       OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI;
14925 +
14926 +               mgr->set_device = &omap_dss_set_device;
14927 +               mgr->unset_device = &omap_dss_unset_device;
14928 +               mgr->apply = &omap_dss_mgr_apply_l4;
14929 +               mgr->set_manager_info = &omap_dss_mgr_set_info;
14930 +               mgr->get_manager_info = &omap_dss_mgr_get_info;
14931 +
14932 +               dss_overlay_setup_l4_manager(mgr);
14933 +
14934 +               omap_dss_add_overlay_manager(mgr);
14935 +
14936 +               r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
14937 +                               &pdev->dev.kobj, "managerl4");
14938 +
14939 +               if (r)
14940 +                       DSSERR("failed to create sysfs file\n");
14941 +       }
14942 +#endif
14943 +
14944 +       return 0;
14945 +}
14946 +
14947 +void dss_uninit_overlay_managers(struct platform_device *pdev)
14948 +{
14949 +       struct omap_overlay_manager *mgr;
14950 +
14951 +       while (!list_empty(&manager_list)) {
14952 +               mgr = list_first_entry(&manager_list,
14953 +                               struct omap_overlay_manager, list);
14954 +               list_del(&mgr->list);
14955 +               kobject_del(&mgr->kobj);
14956 +               kobject_put(&mgr->kobj);
14957 +               kfree(mgr);
14958 +       }
14959 +
14960 +       num_managers = 0;
14961 +}
14962 +
14963 +int omap_dss_get_num_overlay_managers(void)
14964 +{
14965 +       return num_managers;
14966 +}
14967 +EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
14968 +
14969 +struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
14970 +{
14971 +       int i = 0;
14972 +       struct omap_overlay_manager *mgr;
14973 +
14974 +       list_for_each_entry(mgr, &manager_list, list) {
14975 +               if (i++ == num)
14976 +                       return mgr;
14977 +       }
14978 +
14979 +       return NULL;
14980 +}
14981 +EXPORT_SYMBOL(omap_dss_get_overlay_manager);
14982 +
14983 diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
14984 new file mode 100644
14985 index 0000000..c7cb81b
14986 --- /dev/null
14987 +++ b/drivers/video/omap2/dss/overlay.c
14988 @@ -0,0 +1,673 @@
14989 +/*
14990 + * linux/drivers/video/omap2/dss/overlay.c
14991 + *
14992 + * Copyright (C) 2009 Nokia Corporation
14993 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
14994 + *
14995 + * Some code and ideas taken from drivers/video/omap/ driver
14996 + * by Imre Deak.
14997 + *
14998 + * This program is free software; you can redistribute it and/or modify it
14999 + * under the terms of the GNU General Public License version 2 as published by
15000 + * the Free Software Foundation.
15001 + *
15002 + * This program is distributed in the hope that it will be useful, but WITHOUT
15003 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15004 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15005 + * more details.
15006 + *
15007 + * You should have received a copy of the GNU General Public License along with
15008 + * this program.  If not, see <http://www.gnu.org/licenses/>.
15009 + */
15010 +
15011 +#define DSS_SUBSYS_NAME "OVERLAY"
15012 +
15013 +#include <linux/kernel.h>
15014 +#include <linux/module.h>
15015 +#include <linux/err.h>
15016 +#include <linux/sysfs.h>
15017 +#include <linux/kobject.h>
15018 +#include <linux/platform_device.h>
15019 +#include <linux/delay.h>
15020 +
15021 +#include <mach/display.h>
15022 +
15023 +#include "dss.h"
15024 +
15025 +static int num_overlays;
15026 +static struct list_head overlay_list;
15027 +
15028 +static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
15029 +{
15030 +       return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
15031 +}
15032 +
15033 +static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
15034 +{
15035 +       return snprintf(buf, PAGE_SIZE, "%s\n",
15036 +                       ovl->manager ? ovl->manager->name : "<none>");
15037 +}
15038 +
15039 +static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
15040 +               size_t size)
15041 +{
15042 +       int i, r;
15043 +       struct omap_overlay_manager *mgr = NULL;
15044 +       struct omap_overlay_manager *old_mgr;
15045 +       int len = size;
15046 +
15047 +       if (buf[size-1] == '\n')
15048 +               --len;
15049 +
15050 +       if (len > 0) {
15051 +               for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
15052 +                       mgr = omap_dss_get_overlay_manager(i);
15053 +
15054 +                       if (strncmp(buf, mgr->name, len) == 0)
15055 +                               break;
15056 +
15057 +                       mgr = NULL;
15058 +               }
15059 +       }
15060 +
15061 +       if (len > 0 && mgr == NULL)
15062 +               return -EINVAL;
15063 +
15064 +       if (mgr)
15065 +               DSSDBG("manager %s found\n", mgr->name);
15066 +
15067 +       if (mgr == ovl->manager)
15068 +               return size;
15069 +
15070 +       old_mgr = ovl->manager;
15071 +
15072 +       /* detach old manager */
15073 +       if (old_mgr) {
15074 +               r = ovl->unset_manager(ovl);
15075 +               if (r) {
15076 +                       DSSERR("detach failed\n");
15077 +                       return r;
15078 +               }
15079 +
15080 +               r = old_mgr->apply(old_mgr);
15081 +               if (r)
15082 +                       return r;
15083 +       }
15084 +
15085 +       if (mgr) {
15086 +               r = ovl->set_manager(ovl, mgr);
15087 +               if (r) {
15088 +                       DSSERR("Failed to attach overlay\n");
15089 +                       return r;
15090 +               }
15091 +
15092 +               r = mgr->apply(mgr);
15093 +               if (r)
15094 +                       return r;
15095 +       }
15096 +
15097 +       return size;
15098 +}
15099 +
15100 +static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
15101 +{
15102 +       return snprintf(buf, PAGE_SIZE, "%d,%d\n",
15103 +                       ovl->info.width, ovl->info.height);
15104 +}
15105 +
15106 +static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
15107 +{
15108 +       return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.screen_width);
15109 +}
15110 +
15111 +static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
15112 +{
15113 +       return snprintf(buf, PAGE_SIZE, "%d,%d\n",
15114 +                       ovl->info.pos_x, ovl->info.pos_y);
15115 +}
15116 +
15117 +static ssize_t overlay_position_store(struct omap_overlay *ovl,
15118 +               const char *buf, size_t size)
15119 +{
15120 +       int r;
15121 +       char *last;
15122 +       struct omap_overlay_info info;
15123 +
15124 +       ovl->get_overlay_info(ovl, &info);
15125 +
15126 +       info.pos_x = simple_strtoul(buf, &last, 10);
15127 +       ++last;
15128 +       if (last - buf >= size)
15129 +               return -EINVAL;
15130 +
15131 +       info.pos_y = simple_strtoul(last, &last, 10);
15132 +
15133 +       r = ovl->set_overlay_info(ovl, &info);
15134 +       if (r)
15135 +               return r;
15136 +
15137 +       if (ovl->manager) {
15138 +               r = ovl->manager->apply(ovl->manager);
15139 +               if (r)
15140 +                       return r;
15141 +       }
15142 +
15143 +       return size;
15144 +}
15145 +
15146 +static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
15147 +{
15148 +       return snprintf(buf, PAGE_SIZE, "%d,%d\n",
15149 +                       ovl->info.out_width, ovl->info.out_height);
15150 +}
15151 +
15152 +static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
15153 +               const char *buf, size_t size)
15154 +{
15155 +       int r;
15156 +       char *last;
15157 +       struct omap_overlay_info info;
15158 +
15159 +       ovl->get_overlay_info(ovl, &info);
15160 +
15161 +       info.out_width = simple_strtoul(buf, &last, 10);
15162 +       ++last;
15163 +       if (last - buf >= size)
15164 +               return -EINVAL;
15165 +
15166 +       info.out_height = simple_strtoul(last, &last, 10);
15167 +
15168 +       r = ovl->set_overlay_info(ovl, &info);
15169 +       if (r)
15170 +               return r;
15171 +
15172 +       if (ovl->manager) {
15173 +               r = ovl->manager->apply(ovl->manager);
15174 +               if (r)
15175 +                       return r;
15176 +       }
15177 +
15178 +       return size;
15179 +}
15180 +
15181 +static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
15182 +{
15183 +       return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled);
15184 +}
15185 +
15186 +static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
15187 +               size_t size)
15188 +{
15189 +       int r;
15190 +       struct omap_overlay_info info;
15191 +
15192 +       ovl->get_overlay_info(ovl, &info);
15193 +
15194 +       info.enabled = simple_strtoul(buf, NULL, 10);
15195 +
15196 +       r = ovl->set_overlay_info(ovl, &info);
15197 +       if (r)
15198 +               return r;
15199 +
15200 +       if (ovl->manager) {
15201 +               r = ovl->manager->apply(ovl->manager);
15202 +               if (r)
15203 +                       return r;
15204 +       }
15205 +
15206 +       return size;
15207 +}
15208 +
15209 +static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
15210 +{
15211 +       return snprintf(buf, PAGE_SIZE, "%d\n",
15212 +                       ovl->info.global_alpha);
15213 +}
15214 +
15215 +static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
15216 +               const char *buf, size_t size)
15217 +{
15218 +       int r;
15219 +       struct omap_overlay_info info;
15220 +
15221 +       ovl->get_overlay_info(ovl, &info);
15222 +
15223 +       /* Video1 plane does not support global alpha
15224 +        * to always make it 255 completely opaque
15225 +        */
15226 +       if (ovl->id == OMAP_DSS_VIDEO1)
15227 +               info.global_alpha = 255;
15228 +       else
15229 +               info.global_alpha = simple_strtoul(buf, NULL, 10);
15230 +
15231 +       r = ovl->set_overlay_info(ovl, &info);
15232 +       if (r)
15233 +               return r;
15234 +
15235 +       if (ovl->manager) {
15236 +               r = ovl->manager->apply(ovl->manager);
15237 +               if (r)
15238 +                       return r;
15239 +       }
15240 +
15241 +       return size;
15242 +}
15243 +
15244 +struct overlay_attribute {
15245 +       struct attribute attr;
15246 +       ssize_t (*show)(struct omap_overlay *, char *);
15247 +       ssize_t (*store)(struct omap_overlay *, const char *, size_t);
15248 +};
15249 +
15250 +#define OVERLAY_ATTR(_name, _mode, _show, _store) \
15251 +       struct overlay_attribute overlay_attr_##_name = \
15252 +       __ATTR(_name, _mode, _show, _store)
15253 +
15254 +static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
15255 +static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
15256 +               overlay_manager_show, overlay_manager_store);
15257 +static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
15258 +static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
15259 +static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
15260 +               overlay_position_show, overlay_position_store);
15261 +static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
15262 +               overlay_output_size_show, overlay_output_size_store);
15263 +static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
15264 +               overlay_enabled_show, overlay_enabled_store);
15265 +static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
15266 +               overlay_global_alpha_show, overlay_global_alpha_store);
15267 +
15268 +static struct attribute *overlay_sysfs_attrs[] = {
15269 +       &overlay_attr_name.attr,
15270 +       &overlay_attr_manager.attr,
15271 +       &overlay_attr_input_size.attr,
15272 +       &overlay_attr_screen_width.attr,
15273 +       &overlay_attr_position.attr,
15274 +       &overlay_attr_output_size.attr,
15275 +       &overlay_attr_enabled.attr,
15276 +       &overlay_attr_global_alpha.attr,
15277 +       NULL
15278 +};
15279 +
15280 +static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
15281 +               char *buf)
15282 +{
15283 +       struct omap_overlay *overlay;
15284 +       struct overlay_attribute *overlay_attr;
15285 +
15286 +       overlay = container_of(kobj, struct omap_overlay, kobj);
15287 +       overlay_attr = container_of(attr, struct overlay_attribute, attr);
15288 +
15289 +       if (!overlay_attr->show)
15290 +               return -ENOENT;
15291 +
15292 +       return overlay_attr->show(overlay, buf);
15293 +}
15294 +
15295 +static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
15296 +               const char *buf, size_t size)
15297 +{
15298 +       struct omap_overlay *overlay;
15299 +       struct overlay_attribute *overlay_attr;
15300 +
15301 +       overlay = container_of(kobj, struct omap_overlay, kobj);
15302 +       overlay_attr = container_of(attr, struct overlay_attribute, attr);
15303 +
15304 +       if (!overlay_attr->store)
15305 +               return -ENOENT;
15306 +
15307 +       return overlay_attr->store(overlay, buf, size);
15308 +}
15309 +
15310 +static struct sysfs_ops overlay_sysfs_ops = {
15311 +       .show = overlay_attr_show,
15312 +       .store = overlay_attr_store,
15313 +};
15314 +
15315 +static struct kobj_type overlay_ktype = {
15316 +       .sysfs_ops = &overlay_sysfs_ops,
15317 +       .default_attrs = overlay_sysfs_attrs,
15318 +};
15319 +
15320 +/* Check if overlay parameters are compatible with display */
15321 +int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
15322 +{
15323 +       struct omap_overlay_info *info;
15324 +       u16 outw, outh;
15325 +       u16 dw, dh;
15326 +
15327 +       if (!dssdev)
15328 +               return 0;
15329 +
15330 +       if (!ovl->info.enabled)
15331 +               return 0;
15332 +
15333 +       info = &ovl->info;
15334 +
15335 +       if (info->paddr == 0) {
15336 +               DSSDBG("check_overlay failed: paddr 0\n");
15337 +               return -EINVAL;
15338 +       }
15339 +
15340 +       dssdev->get_resolution(dssdev, &dw, &dh);
15341 +
15342 +       DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n",
15343 +                       ovl->id,
15344 +                       info->pos_x, info->pos_y,
15345 +                       info->width, info->height,
15346 +                       info->out_width, info->out_height,
15347 +                       dw, dh);
15348 +
15349 +       if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
15350 +               outw = info->width;
15351 +               outh = info->height;
15352 +       } else {
15353 +               if (info->out_width == 0)
15354 +                       outw = info->width;
15355 +               else
15356 +                       outw = info->out_width;
15357 +
15358 +               if (info->out_height == 0)
15359 +                       outh = info->height;
15360 +               else
15361 +                       outh = info->out_height;
15362 +       }
15363 +
15364 +       if (dw < info->pos_x + outw) {
15365 +               DSSDBG("check_overlay failed 1: %d < %d + %d\n",
15366 +                               dw, info->pos_x, outw);
15367 +               return -EINVAL;
15368 +       }
15369 +
15370 +       if (dh < info->pos_y + outh) {
15371 +               DSSDBG("check_overlay failed 2: %d < %d + %d\n",
15372 +                               dh, info->pos_y, outh);
15373 +               return -EINVAL;
15374 +       }
15375 +
15376 +       if ((ovl->supported_modes & info->color_mode) == 0) {
15377 +               DSSERR("overlay doesn't support mode %d\n", info->color_mode);
15378 +               return -EINVAL;
15379 +       }
15380 +
15381 +       return 0;
15382 +}
15383 +
15384 +static int dss_ovl_set_overlay_info(struct omap_overlay *ovl,
15385 +               struct omap_overlay_info *info)
15386 +{
15387 +       int r;
15388 +       struct omap_overlay_info old_info;
15389 +
15390 +       old_info = ovl->info;
15391 +       ovl->info = *info;
15392 +
15393 +       if (ovl->manager) {
15394 +               r = dss_check_overlay(ovl, ovl->manager->device);
15395 +               if (r) {
15396 +                       ovl->info = old_info;
15397 +                       return r;
15398 +               }
15399 +       }
15400 +
15401 +       ovl->info_dirty = true;
15402 +
15403 +       return 0;
15404 +}
15405 +
15406 +static void dss_ovl_get_overlay_info(struct omap_overlay *ovl,
15407 +               struct omap_overlay_info *info)
15408 +{
15409 +       *info = ovl->info;
15410 +}
15411 +
15412 +static int dss_ovl_wait_for_go(struct omap_overlay *ovl)
15413 +{
15414 +       return dss_mgr_wait_for_go_ovl(ovl);
15415 +}
15416 +
15417 +static int omap_dss_set_manager(struct omap_overlay *ovl,
15418 +               struct omap_overlay_manager *mgr)
15419 +{
15420 +       if (!mgr)
15421 +               return -EINVAL;
15422 +
15423 +       if (ovl->manager) {
15424 +               DSSERR("overlay '%s' already has a manager '%s'\n",
15425 +                               ovl->name, ovl->manager->name);
15426 +               return -EINVAL;
15427 +       }
15428 +
15429 +       if (ovl->info.enabled) {
15430 +               DSSERR("overlay has to be disabled to change the manager\n");
15431 +               return -EINVAL;
15432 +       }
15433 +
15434 +       ovl->manager = mgr;
15435 +
15436 +       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
15437 +       /* XXX: on manual update display, in auto update mode, a bug happens
15438 +        * here. When an overlay is first enabled on LCD, then it's disabled,
15439 +        * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT
15440 +        * errors. Waiting before changing the channel_out fixes it. I'm
15441 +        * guessing that the overlay is still somehow being used for the LCD,
15442 +        * but I don't understand how or why. */
15443 +       msleep(40);
15444 +       dispc_set_channel_out(ovl->id, mgr->id);
15445 +       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
15446 +
15447 +       return 0;
15448 +}
15449 +
15450 +static int omap_dss_unset_manager(struct omap_overlay *ovl)
15451 +{
15452 +       int r;
15453 +
15454 +       if (!ovl->manager) {
15455 +               DSSERR("failed to detach overlay: manager not set\n");
15456 +               return -EINVAL;
15457 +       }
15458 +
15459 +       if (ovl->info.enabled) {
15460 +               DSSERR("overlay has to be disabled to unset the manager\n");
15461 +               return -EINVAL;
15462 +       }
15463 +
15464 +       r = ovl->wait_for_go(ovl);
15465 +       if (r)
15466 +               return r;
15467 +
15468 +       ovl->manager = NULL;
15469 +
15470 +       return 0;
15471 +}
15472 +
15473 +int omap_dss_get_num_overlays(void)
15474 +{
15475 +       return num_overlays;
15476 +}
15477 +EXPORT_SYMBOL(omap_dss_get_num_overlays);
15478 +
15479 +struct omap_overlay *omap_dss_get_overlay(int num)
15480 +{
15481 +       int i = 0;
15482 +       struct omap_overlay *ovl;
15483 +
15484 +       list_for_each_entry(ovl, &overlay_list, list) {
15485 +               if (i++ == num)
15486 +                       return ovl;
15487 +       }
15488 +
15489 +       return NULL;
15490 +}
15491 +EXPORT_SYMBOL(omap_dss_get_overlay);
15492 +
15493 +static void omap_dss_add_overlay(struct omap_overlay *overlay)
15494 +{
15495 +       ++num_overlays;
15496 +       list_add_tail(&overlay->list, &overlay_list);
15497 +}
15498 +
15499 +static struct omap_overlay *dispc_overlays[3];
15500 +
15501 +void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
15502 +{
15503 +       mgr->num_overlays = 3;
15504 +       mgr->overlays = dispc_overlays;
15505 +}
15506 +
15507 +#ifdef L4_EXAMPLE
15508 +static struct omap_overlay *l4_overlays[1];
15509 +void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr)
15510 +{
15511 +       mgr->num_overlays = 1;
15512 +       mgr->overlays = l4_overlays;
15513 +}
15514 +#endif
15515 +
15516 +void dss_init_overlays(struct platform_device *pdev)
15517 +{
15518 +       int i, r;
15519 +
15520 +       INIT_LIST_HEAD(&overlay_list);
15521 +
15522 +       num_overlays = 0;
15523 +
15524 +       for (i = 0; i < 3; ++i) {
15525 +               struct omap_overlay *ovl;
15526 +               ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
15527 +
15528 +               BUG_ON(ovl == NULL);
15529 +
15530 +               switch (i) {
15531 +               case 0:
15532 +                       ovl->name = "gfx";
15533 +                       ovl->id = OMAP_DSS_GFX;
15534 +                       ovl->supported_modes = OMAP_DSS_COLOR_GFX_OMAP3;
15535 +                       ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
15536 +                       ovl->info.global_alpha = 255;
15537 +                       break;
15538 +               case 1:
15539 +                       ovl->name = "vid1";
15540 +                       ovl->id = OMAP_DSS_VIDEO1;
15541 +                       ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3;
15542 +                       ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
15543 +                               OMAP_DSS_OVL_CAP_DISPC;
15544 +                       ovl->info.global_alpha = 255;
15545 +                       break;
15546 +               case 2:
15547 +                       ovl->name = "vid2";
15548 +                       ovl->id = OMAP_DSS_VIDEO2;
15549 +                       ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3;
15550 +                       ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
15551 +                               OMAP_DSS_OVL_CAP_DISPC;
15552 +                       ovl->info.global_alpha = 255;
15553 +                       break;
15554 +               }
15555 +
15556 +               ovl->set_manager = &omap_dss_set_manager;
15557 +               ovl->unset_manager = &omap_dss_unset_manager;
15558 +               ovl->set_overlay_info = &dss_ovl_set_overlay_info;
15559 +               ovl->get_overlay_info = &dss_ovl_get_overlay_info;
15560 +               ovl->wait_for_go = &dss_ovl_wait_for_go;
15561 +
15562 +               omap_dss_add_overlay(ovl);
15563 +
15564 +               r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
15565 +                               &pdev->dev.kobj, "overlay%d", i);
15566 +
15567 +               if (r) {
15568 +                       DSSERR("failed to create sysfs file\n");
15569 +                       continue;
15570 +               }
15571 +
15572 +               dispc_overlays[i] = ovl;
15573 +       }
15574 +
15575 +#ifdef L4_EXAMPLE
15576 +       {
15577 +               struct omap_overlay *ovl;
15578 +               ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
15579 +
15580 +               BUG_ON(ovl == NULL);
15581 +
15582 +               ovl->name = "l4";
15583 +               ovl->supported_modes = OMAP_DSS_COLOR_RGB24U;
15584 +
15585 +               ovl->set_manager = &omap_dss_set_manager;
15586 +               ovl->unset_manager = &omap_dss_unset_manager;
15587 +               ovl->set_overlay_info = &dss_ovl_set_overlay_info;
15588 +               ovl->get_overlay_info = &dss_ovl_get_overlay_info;
15589 +
15590 +               omap_dss_add_overlay(ovl);
15591 +
15592 +               r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
15593 +                               &pdev->dev.kobj, "overlayl4");
15594 +
15595 +               if (r)
15596 +                       DSSERR("failed to create sysfs file\n");
15597 +
15598 +               l4_overlays[0] = ovl;
15599 +       }
15600 +#endif
15601 +}
15602 +
15603 +/* connect overlays to the new device, if not already connected. if force
15604 + * selected, connect always. */
15605 +void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
15606 +{
15607 +       int i;
15608 +       struct omap_overlay_manager *lcd_mgr;
15609 +       struct omap_overlay_manager *tv_mgr;
15610 +       struct omap_overlay_manager *mgr = NULL;
15611 +
15612 +       lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD);
15613 +       tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV);
15614 +
15615 +       if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) {
15616 +               if (!lcd_mgr->device || force) {
15617 +                       if (lcd_mgr->device)
15618 +                               lcd_mgr->unset_device(lcd_mgr);
15619 +                       lcd_mgr->set_device(lcd_mgr, dssdev);
15620 +                       mgr = lcd_mgr;
15621 +               }
15622 +       }
15623 +
15624 +       if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
15625 +               if (!tv_mgr->device || force) {
15626 +                       if (tv_mgr->device)
15627 +                               tv_mgr->unset_device(tv_mgr);
15628 +                       tv_mgr->set_device(tv_mgr, dssdev);
15629 +                       mgr = tv_mgr;
15630 +               }
15631 +       }
15632 +
15633 +       if (mgr) {
15634 +               for (i = 0; i < 3; i++) {
15635 +                       struct omap_overlay *ovl;
15636 +                       ovl = omap_dss_get_overlay(i);
15637 +                       if (!ovl->manager || force) {
15638 +                               if (ovl->manager)
15639 +                                       omap_dss_unset_manager(ovl);
15640 +                               omap_dss_set_manager(ovl, mgr);
15641 +                       }
15642 +               }
15643 +       }
15644 +}
15645 +
15646 +void dss_uninit_overlays(struct platform_device *pdev)
15647 +{
15648 +       struct omap_overlay *ovl;
15649 +
15650 +       while (!list_empty(&overlay_list)) {
15651 +               ovl = list_first_entry(&overlay_list,
15652 +                               struct omap_overlay, list);
15653 +               list_del(&ovl->list);
15654 +               kobject_del(&ovl->kobj);
15655 +               kobject_put(&ovl->kobj);
15656 +               kfree(ovl);
15657 +       }
15658 +
15659 +       num_overlays = 0;
15660 +}
15661 +
15662 diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
15663 new file mode 100644
15664 index 0000000..9dd2349
15665 --- /dev/null
15666 +++ b/drivers/video/omap2/dss/rfbi.c
15667 @@ -0,0 +1,1310 @@
15668 +/*
15669 + * linux/drivers/video/omap2/dss/rfbi.c
15670 + *
15671 + * Copyright (C) 2009 Nokia Corporation
15672 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
15673 + *
15674 + * Some code and ideas taken from drivers/video/omap/ driver
15675 + * by Imre Deak.
15676 + *
15677 + * This program is free software; you can redistribute it and/or modify it
15678 + * under the terms of the GNU General Public License version 2 as published by
15679 + * the Free Software Foundation.
15680 + *
15681 + * This program is distributed in the hope that it will be useful, but WITHOUT
15682 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15683 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15684 + * more details.
15685 + *
15686 + * You should have received a copy of the GNU General Public License along with
15687 + * this program.  If not, see <http://www.gnu.org/licenses/>.
15688 + */
15689 +
15690 +#define DSS_SUBSYS_NAME "RFBI"
15691 +
15692 +#include <linux/kernel.h>
15693 +#include <linux/dma-mapping.h>
15694 +#include <linux/vmalloc.h>
15695 +#include <linux/clk.h>
15696 +#include <linux/io.h>
15697 +#include <linux/delay.h>
15698 +#include <linux/kfifo.h>
15699 +#include <linux/ktime.h>
15700 +#include <linux/hrtimer.h>
15701 +#include <linux/seq_file.h>
15702 +
15703 +#include <mach/board.h>
15704 +#include <mach/display.h>
15705 +#include "dss.h"
15706 +
15707 +/*#define MEASURE_PERF*/
15708 +
15709 +#define RFBI_BASE               0x48050800
15710 +
15711 +struct rfbi_reg { u16 idx; };
15712 +
15713 +#define RFBI_REG(idx)          ((const struct rfbi_reg) { idx })
15714 +
15715 +#define RFBI_REVISION          RFBI_REG(0x0000)
15716 +#define RFBI_SYSCONFIG         RFBI_REG(0x0010)
15717 +#define RFBI_SYSSTATUS         RFBI_REG(0x0014)
15718 +#define RFBI_CONTROL           RFBI_REG(0x0040)
15719 +#define RFBI_PIXEL_CNT         RFBI_REG(0x0044)
15720 +#define RFBI_LINE_NUMBER       RFBI_REG(0x0048)
15721 +#define RFBI_CMD               RFBI_REG(0x004c)
15722 +#define RFBI_PARAM             RFBI_REG(0x0050)
15723 +#define RFBI_DATA              RFBI_REG(0x0054)
15724 +#define RFBI_READ              RFBI_REG(0x0058)
15725 +#define RFBI_STATUS            RFBI_REG(0x005c)
15726 +
15727 +#define RFBI_CONFIG(n)         RFBI_REG(0x0060 + (n)*0x18)
15728 +#define RFBI_ONOFF_TIME(n)     RFBI_REG(0x0064 + (n)*0x18)
15729 +#define RFBI_CYCLE_TIME(n)     RFBI_REG(0x0068 + (n)*0x18)
15730 +#define RFBI_DATA_CYCLE1(n)    RFBI_REG(0x006c + (n)*0x18)
15731 +#define RFBI_DATA_CYCLE2(n)    RFBI_REG(0x0070 + (n)*0x18)
15732 +#define RFBI_DATA_CYCLE3(n)    RFBI_REG(0x0074 + (n)*0x18)
15733 +
15734 +#define RFBI_VSYNC_WIDTH       RFBI_REG(0x0090)
15735 +#define RFBI_HSYNC_WIDTH       RFBI_REG(0x0094)
15736 +
15737 +#define RFBI_CMD_FIFO_LEN_BYTES (16 * sizeof(struct update_param))
15738 +
15739 +#define REG_FLD_MOD(idx, val, start, end) \
15740 +       rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
15741 +
15742 +/* To work around an RFBI transfer rate limitation */
15743 +#define OMAP_RFBI_RATE_LIMIT    1
15744 +
15745 +enum omap_rfbi_cycleformat {
15746 +       OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0,
15747 +       OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1,
15748 +       OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2,
15749 +       OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3,
15750 +};
15751 +
15752 +enum omap_rfbi_datatype {
15753 +       OMAP_DSS_RFBI_DATATYPE_12 = 0,
15754 +       OMAP_DSS_RFBI_DATATYPE_16 = 1,
15755 +       OMAP_DSS_RFBI_DATATYPE_18 = 2,
15756 +       OMAP_DSS_RFBI_DATATYPE_24 = 3,
15757 +};
15758 +
15759 +enum omap_rfbi_parallelmode {
15760 +       OMAP_DSS_RFBI_PARALLELMODE_8 = 0,
15761 +       OMAP_DSS_RFBI_PARALLELMODE_9 = 1,
15762 +       OMAP_DSS_RFBI_PARALLELMODE_12 = 2,
15763 +       OMAP_DSS_RFBI_PARALLELMODE_16 = 3,
15764 +};
15765 +
15766 +enum update_cmd {
15767 +       RFBI_CMD_UPDATE = 0,
15768 +       RFBI_CMD_SYNC   = 1,
15769 +};
15770 +
15771 +static int rfbi_convert_timings(struct rfbi_timings *t);
15772 +static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
15773 +static void process_cmd_fifo(void);
15774 +
15775 +static struct {
15776 +       void __iomem    *base;
15777 +
15778 +       unsigned long   l4_khz;
15779 +
15780 +       enum omap_rfbi_datatype datatype;
15781 +       enum omap_rfbi_parallelmode parallelmode;
15782 +
15783 +       enum omap_rfbi_te_mode te_mode;
15784 +       int te_enabled;
15785 +
15786 +       void (*framedone_callback)(void *data);
15787 +       void *framedone_callback_data;
15788 +
15789 +       struct omap_dss_device *dssdev[2];
15790 +
15791 +       struct kfifo      *cmd_fifo;
15792 +       spinlock_t        cmd_lock;
15793 +       struct completion cmd_done;
15794 +       atomic_t          cmd_fifo_full;
15795 +       atomic_t          cmd_pending;
15796 +#ifdef MEASURE_PERF
15797 +       unsigned perf_bytes;
15798 +       ktime_t perf_setup_time;
15799 +       ktime_t perf_start_time;
15800 +#endif
15801 +} rfbi;
15802 +
15803 +struct update_region {
15804 +       u16     x;
15805 +       u16     y;
15806 +       u16     w;
15807 +       u16     h;
15808 +};
15809 +
15810 +struct update_param {
15811 +       u8 rfbi_module;
15812 +       u8 cmd;
15813 +
15814 +       union {
15815 +               struct update_region r;
15816 +               struct completion *sync;
15817 +       } par;
15818 +};
15819 +
15820 +static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
15821 +{
15822 +       __raw_writel(val, rfbi.base + idx.idx);
15823 +}
15824 +
15825 +static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
15826 +{
15827 +       return __raw_readl(rfbi.base + idx.idx);
15828 +}
15829 +
15830 +static void rfbi_enable_clocks(bool enable)
15831 +{
15832 +       if (enable)
15833 +               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
15834 +       else
15835 +               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
15836 +}
15837 +
15838 +void omap_rfbi_write_command(const void *buf, u32 len)
15839 +{
15840 +       rfbi_enable_clocks(1);
15841 +       switch (rfbi.parallelmode) {
15842 +       case OMAP_DSS_RFBI_PARALLELMODE_8:
15843 +       {
15844 +               const u8 *b = buf;
15845 +               for (; len; len--)
15846 +                       rfbi_write_reg(RFBI_CMD, *b++);
15847 +               break;
15848 +       }
15849 +
15850 +       case OMAP_DSS_RFBI_PARALLELMODE_16:
15851 +       {
15852 +               const u16 *w = buf;
15853 +               BUG_ON(len & 1);
15854 +               for (; len; len -= 2)
15855 +                       rfbi_write_reg(RFBI_CMD, *w++);
15856 +               break;
15857 +       }
15858 +
15859 +       case OMAP_DSS_RFBI_PARALLELMODE_9:
15860 +       case OMAP_DSS_RFBI_PARALLELMODE_12:
15861 +       default:
15862 +               BUG();
15863 +       }
15864 +       rfbi_enable_clocks(0);
15865 +}
15866 +EXPORT_SYMBOL(omap_rfbi_write_command);
15867 +
15868 +void omap_rfbi_read_data(void *buf, u32 len)
15869 +{
15870 +       rfbi_enable_clocks(1);
15871 +       switch (rfbi.parallelmode) {
15872 +       case OMAP_DSS_RFBI_PARALLELMODE_8:
15873 +       {
15874 +               u8 *b = buf;
15875 +               for (; len; len--) {
15876 +                       rfbi_write_reg(RFBI_READ, 0);
15877 +                       *b++ = rfbi_read_reg(RFBI_READ);
15878 +               }
15879 +               break;
15880 +       }
15881 +
15882 +       case OMAP_DSS_RFBI_PARALLELMODE_16:
15883 +       {
15884 +               u16 *w = buf;
15885 +               BUG_ON(len & ~1);
15886 +               for (; len; len -= 2) {
15887 +                       rfbi_write_reg(RFBI_READ, 0);
15888 +                       *w++ = rfbi_read_reg(RFBI_READ);
15889 +               }
15890 +               break;
15891 +       }
15892 +
15893 +       case OMAP_DSS_RFBI_PARALLELMODE_9:
15894 +       case OMAP_DSS_RFBI_PARALLELMODE_12:
15895 +       default:
15896 +               BUG();
15897 +       }
15898 +       rfbi_enable_clocks(0);
15899 +}
15900 +EXPORT_SYMBOL(omap_rfbi_read_data);
15901 +
15902 +void omap_rfbi_write_data(const void *buf, u32 len)
15903 +{
15904 +       rfbi_enable_clocks(1);
15905 +       switch (rfbi.parallelmode) {
15906 +       case OMAP_DSS_RFBI_PARALLELMODE_8:
15907 +       {
15908 +               const u8 *b = buf;
15909 +               for (; len; len--)
15910 +                       rfbi_write_reg(RFBI_PARAM, *b++);
15911 +               break;
15912 +       }
15913 +
15914 +       case OMAP_DSS_RFBI_PARALLELMODE_16:
15915 +       {
15916 +               const u16 *w = buf;
15917 +               BUG_ON(len & 1);
15918 +               for (; len; len -= 2)
15919 +                       rfbi_write_reg(RFBI_PARAM, *w++);
15920 +               break;
15921 +       }
15922 +
15923 +       case OMAP_DSS_RFBI_PARALLELMODE_9:
15924 +       case OMAP_DSS_RFBI_PARALLELMODE_12:
15925 +       default:
15926 +               BUG();
15927 +
15928 +       }
15929 +       rfbi_enable_clocks(0);
15930 +}
15931 +EXPORT_SYMBOL(omap_rfbi_write_data);
15932 +
15933 +void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
15934 +               u16 x, u16 y,
15935 +               u16 w, u16 h)
15936 +{
15937 +       int start_offset = scr_width * y + x;
15938 +       int horiz_offset = scr_width - w;
15939 +       int i;
15940 +
15941 +       rfbi_enable_clocks(1);
15942 +
15943 +       if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
15944 +          rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
15945 +               const u16 __iomem *pd = buf;
15946 +               pd += start_offset;
15947 +
15948 +               for (; h; --h) {
15949 +                       for (i = 0; i < w; ++i) {
15950 +                               const u8 __iomem *b = (const u8 __iomem *)pd;
15951 +                               rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
15952 +                               rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
15953 +                               ++pd;
15954 +                       }
15955 +                       pd += horiz_offset;
15956 +               }
15957 +       } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 &&
15958 +          rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
15959 +               const u32 __iomem *pd = buf;
15960 +               pd += start_offset;
15961 +
15962 +               for (; h; --h) {
15963 +                       for (i = 0; i < w; ++i) {
15964 +                               const u8 __iomem *b = (const u8 __iomem *)pd;
15965 +                               rfbi_write_reg(RFBI_PARAM, __raw_readb(b+2));
15966 +                               rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
15967 +                               rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
15968 +                               ++pd;
15969 +                       }
15970 +                       pd += horiz_offset;
15971 +               }
15972 +       } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
15973 +          rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) {
15974 +               const u16 __iomem *pd = buf;
15975 +               pd += start_offset;
15976 +
15977 +               for (; h; --h) {
15978 +                       for (i = 0; i < w; ++i) {
15979 +                               rfbi_write_reg(RFBI_PARAM, __raw_readw(pd));
15980 +                               ++pd;
15981 +                       }
15982 +                       pd += horiz_offset;
15983 +               }
15984 +       } else {
15985 +               BUG();
15986 +       }
15987 +
15988 +       rfbi_enable_clocks(0);
15989 +}
15990 +EXPORT_SYMBOL(omap_rfbi_write_pixels);
15991 +
15992 +#ifdef MEASURE_PERF
15993 +static void perf_mark_setup(void)
15994 +{
15995 +       rfbi.perf_setup_time = ktime_get();
15996 +}
15997 +
15998 +static void perf_mark_start(void)
15999 +{
16000 +       rfbi.perf_start_time = ktime_get();
16001 +}
16002 +
16003 +static void perf_show(const char *name)
16004 +{
16005 +       ktime_t t, setup_time, trans_time;
16006 +       u32 total_bytes;
16007 +       u32 setup_us, trans_us, total_us;
16008 +
16009 +       t = ktime_get();
16010 +
16011 +       setup_time = ktime_sub(rfbi.perf_start_time, rfbi.perf_setup_time);
16012 +       setup_us = (u32)ktime_to_us(setup_time);
16013 +       if (setup_us == 0)
16014 +               setup_us = 1;
16015 +
16016 +       trans_time = ktime_sub(t, rfbi.perf_start_time);
16017 +       trans_us = (u32)ktime_to_us(trans_time);
16018 +       if (trans_us == 0)
16019 +               trans_us = 1;
16020 +
16021 +       total_us = setup_us + trans_us;
16022 +
16023 +       total_bytes = rfbi.perf_bytes;
16024 +
16025 +       DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, "
16026 +                       "%u kbytes/sec\n",
16027 +                       name,
16028 +                       setup_us,
16029 +                       trans_us,
16030 +                       total_us,
16031 +                       1000*1000 / total_us,
16032 +                       total_bytes,
16033 +                       total_bytes * 1000 / total_us);
16034 +}
16035 +#else
16036 +#define perf_mark_setup()
16037 +#define perf_mark_start()
16038 +#define perf_show(x)
16039 +#endif
16040 +
16041 +void rfbi_transfer_area(u16 width, u16 height,
16042 +                            void (callback)(void *data), void *data)
16043 +{
16044 +       u32 l;
16045 +
16046 +       /*BUG_ON(callback == 0);*/
16047 +       BUG_ON(rfbi.framedone_callback != NULL);
16048 +
16049 +       DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
16050 +
16051 +       dispc_set_lcd_size(width, height);
16052 +
16053 +       dispc_enable_lcd_out(1);
16054 +
16055 +       rfbi.framedone_callback = callback;
16056 +       rfbi.framedone_callback_data = data;
16057 +
16058 +       rfbi_enable_clocks(1);
16059 +
16060 +       rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
16061 +
16062 +       l = rfbi_read_reg(RFBI_CONTROL);
16063 +       l = FLD_MOD(l, 1, 0, 0); /* enable */
16064 +       if (!rfbi.te_enabled)
16065 +               l = FLD_MOD(l, 1, 4, 4); /* ITE */
16066 +
16067 +       perf_mark_start();
16068 +
16069 +       rfbi_write_reg(RFBI_CONTROL, l);
16070 +}
16071 +
16072 +static void framedone_callback(void *data, u32 mask)
16073 +{
16074 +       void (*callback)(void *data);
16075 +
16076 +       DSSDBG("FRAMEDONE\n");
16077 +
16078 +       perf_show("DISPC");
16079 +
16080 +       REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0);
16081 +
16082 +       rfbi_enable_clocks(0);
16083 +
16084 +       callback = rfbi.framedone_callback;
16085 +       rfbi.framedone_callback = NULL;
16086 +
16087 +       /*callback(rfbi.framedone_callback_data);*/
16088 +
16089 +       atomic_set(&rfbi.cmd_pending, 0);
16090 +
16091 +       process_cmd_fifo();
16092 +}
16093 +
16094 +#if 1 /* VERBOSE */
16095 +static void rfbi_print_timings(void)
16096 +{
16097 +       u32 l;
16098 +       u32 time;
16099 +
16100 +       l = rfbi_read_reg(RFBI_CONFIG(0));
16101 +       time = 1000000000 / rfbi.l4_khz;
16102 +       if (l & (1 << 4))
16103 +               time *= 2;
16104 +
16105 +       DSSDBG("Tick time %u ps\n", time);
16106 +       l = rfbi_read_reg(RFBI_ONOFF_TIME(0));
16107 +       DSSDBG("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
16108 +               "REONTIME %d, REOFFTIME %d\n",
16109 +               l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
16110 +               (l >> 20) & 0x0f, (l >> 24) & 0x3f);
16111 +
16112 +       l = rfbi_read_reg(RFBI_CYCLE_TIME(0));
16113 +       DSSDBG("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
16114 +               "ACCESSTIME %d\n",
16115 +               (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
16116 +               (l >> 22) & 0x3f);
16117 +}
16118 +#else
16119 +static void rfbi_print_timings(void) {}
16120 +#endif
16121 +
16122 +
16123 +
16124 +
16125 +static u32 extif_clk_period;
16126 +
16127 +static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
16128 +{
16129 +       int bus_tick = extif_clk_period * div;
16130 +       return (ps + bus_tick - 1) / bus_tick * bus_tick;
16131 +}
16132 +
16133 +static int calc_reg_timing(struct rfbi_timings *t, int div)
16134 +{
16135 +       t->clk_div = div;
16136 +
16137 +       t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div);
16138 +
16139 +       t->we_on_time = round_to_extif_ticks(t->we_on_time, div);
16140 +       t->we_off_time = round_to_extif_ticks(t->we_off_time, div);
16141 +       t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div);
16142 +
16143 +       t->re_on_time = round_to_extif_ticks(t->re_on_time, div);
16144 +       t->re_off_time = round_to_extif_ticks(t->re_off_time, div);
16145 +       t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div);
16146 +
16147 +       t->access_time = round_to_extif_ticks(t->access_time, div);
16148 +       t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div);
16149 +       t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div);
16150 +
16151 +       DSSDBG("[reg]cson %d csoff %d reon %d reoff %d\n",
16152 +              t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
16153 +       DSSDBG("[reg]weon %d weoff %d recyc %d wecyc %d\n",
16154 +              t->we_on_time, t->we_off_time, t->re_cycle_time,
16155 +              t->we_cycle_time);
16156 +       DSSDBG("[reg]rdaccess %d cspulse %d\n",
16157 +              t->access_time, t->cs_pulse_width);
16158 +
16159 +       return rfbi_convert_timings(t);
16160 +}
16161 +
16162 +static int calc_extif_timings(struct rfbi_timings *t)
16163 +{
16164 +       u32 max_clk_div;
16165 +       int div;
16166 +
16167 +       rfbi_get_clk_info(&extif_clk_period, &max_clk_div);
16168 +       for (div = 1; div <= max_clk_div; div++) {
16169 +               if (calc_reg_timing(t, div) == 0)
16170 +                       break;
16171 +       }
16172 +
16173 +       if (div <= max_clk_div)
16174 +               return 0;
16175 +
16176 +       DSSERR("can't setup timings\n");
16177 +       return -1;
16178 +}
16179 +
16180 +
16181 +void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
16182 +{
16183 +       int r;
16184 +
16185 +       if (!t->converted) {
16186 +               r = calc_extif_timings(t);
16187 +               if (r < 0)
16188 +                       DSSERR("Failed to calc timings\n");
16189 +       }
16190 +
16191 +       BUG_ON(!t->converted);
16192 +
16193 +       rfbi_enable_clocks(1);
16194 +       rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]);
16195 +       rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]);
16196 +
16197 +       /* TIMEGRANULARITY */
16198 +       REG_FLD_MOD(RFBI_CONFIG(rfbi_module),
16199 +                   (t->tim[2] ? 1 : 0), 4, 4);
16200 +
16201 +       rfbi_print_timings();
16202 +       rfbi_enable_clocks(0);
16203 +}
16204 +
16205 +static int ps_to_rfbi_ticks(int time, int div)
16206 +{
16207 +       unsigned long tick_ps;
16208 +       int ret;
16209 +
16210 +       /* Calculate in picosecs to yield more exact results */
16211 +       tick_ps = 1000000000 / (rfbi.l4_khz) * div;
16212 +
16213 +       ret = (time + tick_ps - 1) / tick_ps;
16214 +
16215 +       return ret;
16216 +}
16217 +
16218 +#ifdef OMAP_RFBI_RATE_LIMIT
16219 +unsigned long rfbi_get_max_tx_rate(void)
16220 +{
16221 +       unsigned long   l4_rate, dss1_rate;
16222 +       int             min_l4_ticks = 0;
16223 +       int             i;
16224 +
16225 +       /* According to TI this can't be calculated so make the
16226 +        * adjustments for a couple of known frequencies and warn for
16227 +        * others.
16228 +        */
16229 +       static const struct {
16230 +               unsigned long l4_clk;           /* HZ */
16231 +               unsigned long dss1_clk;         /* HZ */
16232 +               unsigned long min_l4_ticks;
16233 +       } ftab[] = {
16234 +               { 55,   132,    7, },           /* 7.86 MPix/s */
16235 +               { 110,  110,    12, },          /* 9.16 MPix/s */
16236 +               { 110,  132,    10, },          /* 11   Mpix/s */
16237 +               { 120,  120,    10, },          /* 12   Mpix/s */
16238 +               { 133,  133,    10, },          /* 13.3 Mpix/s */
16239 +       };
16240 +
16241 +       l4_rate = rfbi.l4_khz / 1000;
16242 +       dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000;
16243 +
16244 +       for (i = 0; i < ARRAY_SIZE(ftab); i++) {
16245 +               /* Use a window instead of an exact match, to account
16246 +                * for different DPLL multiplier / divider pairs.
16247 +                */
16248 +               if (abs(ftab[i].l4_clk - l4_rate) < 3 &&
16249 +                   abs(ftab[i].dss1_clk - dss1_rate) < 3) {
16250 +                       min_l4_ticks = ftab[i].min_l4_ticks;
16251 +                       break;
16252 +               }
16253 +       }
16254 +       if (i == ARRAY_SIZE(ftab)) {
16255 +               /* Can't be sure, return anyway the maximum not
16256 +                * rate-limited. This might cause a problem only for the
16257 +                * tearing synchronisation.
16258 +                */
16259 +               DSSERR("can't determine maximum RFBI transfer rate\n");
16260 +               return rfbi.l4_khz * 1000;
16261 +       }
16262 +       return rfbi.l4_khz * 1000 / min_l4_ticks;
16263 +}
16264 +#else
16265 +int rfbi_get_max_tx_rate(void)
16266 +{
16267 +       return rfbi.l4_khz * 1000;
16268 +}
16269 +#endif
16270 +
16271 +static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
16272 +{
16273 +       *clk_period = 1000000000 / rfbi.l4_khz;
16274 +       *max_clk_div = 2;
16275 +}
16276 +
16277 +static int rfbi_convert_timings(struct rfbi_timings *t)
16278 +{
16279 +       u32 l;
16280 +       int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
16281 +       int actim, recyc, wecyc;
16282 +       int div = t->clk_div;
16283 +
16284 +       if (div <= 0 || div > 2)
16285 +               return -1;
16286 +
16287 +       /* Make sure that after conversion it still holds that:
16288 +        * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
16289 +        * csoff > cson, csoff >= max(weoff, reoff), actim > reon
16290 +        */
16291 +       weon = ps_to_rfbi_ticks(t->we_on_time, div);
16292 +       weoff = ps_to_rfbi_ticks(t->we_off_time, div);
16293 +       if (weoff <= weon)
16294 +               weoff = weon + 1;
16295 +       if (weon > 0x0f)
16296 +               return -1;
16297 +       if (weoff > 0x3f)
16298 +               return -1;
16299 +
16300 +       reon = ps_to_rfbi_ticks(t->re_on_time, div);
16301 +       reoff = ps_to_rfbi_ticks(t->re_off_time, div);
16302 +       if (reoff <= reon)
16303 +               reoff = reon + 1;
16304 +       if (reon > 0x0f)
16305 +               return -1;
16306 +       if (reoff > 0x3f)
16307 +               return -1;
16308 +
16309 +       cson = ps_to_rfbi_ticks(t->cs_on_time, div);
16310 +       csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
16311 +       if (csoff <= cson)
16312 +               csoff = cson + 1;
16313 +       if (csoff < max(weoff, reoff))
16314 +               csoff = max(weoff, reoff);
16315 +       if (cson > 0x0f)
16316 +               return -1;
16317 +       if (csoff > 0x3f)
16318 +               return -1;
16319 +
16320 +       l =  cson;
16321 +       l |= csoff << 4;
16322 +       l |= weon  << 10;
16323 +       l |= weoff << 14;
16324 +       l |= reon  << 20;
16325 +       l |= reoff << 24;
16326 +
16327 +       t->tim[0] = l;
16328 +
16329 +       actim = ps_to_rfbi_ticks(t->access_time, div);
16330 +       if (actim <= reon)
16331 +               actim = reon + 1;
16332 +       if (actim > 0x3f)
16333 +               return -1;
16334 +
16335 +       wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
16336 +       if (wecyc < weoff)
16337 +               wecyc = weoff;
16338 +       if (wecyc > 0x3f)
16339 +               return -1;
16340 +
16341 +       recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
16342 +       if (recyc < reoff)
16343 +               recyc = reoff;
16344 +       if (recyc > 0x3f)
16345 +               return -1;
16346 +
16347 +       cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
16348 +       if (cs_pulse > 0x3f)
16349 +               return -1;
16350 +
16351 +       l =  wecyc;
16352 +       l |= recyc    << 6;
16353 +       l |= cs_pulse << 12;
16354 +       l |= actim    << 22;
16355 +
16356 +       t->tim[1] = l;
16357 +
16358 +       t->tim[2] = div - 1;
16359 +
16360 +       t->converted = 1;
16361 +
16362 +       return 0;
16363 +}
16364 +
16365 +/* xxx FIX module selection missing */
16366 +int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
16367 +                            unsigned hs_pulse_time, unsigned vs_pulse_time,
16368 +                            int hs_pol_inv, int vs_pol_inv, int extif_div)
16369 +{
16370 +       int hs, vs;
16371 +       int min;
16372 +       u32 l;
16373 +
16374 +       hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
16375 +       vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
16376 +       if (hs < 2)
16377 +               return -EDOM;
16378 +       if (mode == OMAP_DSS_RFBI_TE_MODE_2)
16379 +               min = 2;
16380 +       else /* OMAP_DSS_RFBI_TE_MODE_1 */
16381 +               min = 4;
16382 +       if (vs < min)
16383 +               return -EDOM;
16384 +       if (vs == hs)
16385 +               return -EINVAL;
16386 +       rfbi.te_mode = mode;
16387 +       DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n",
16388 +               mode, hs, vs, hs_pol_inv, vs_pol_inv);
16389 +
16390 +       rfbi_enable_clocks(1);
16391 +       rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
16392 +       rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
16393 +
16394 +       l = rfbi_read_reg(RFBI_CONFIG(0));
16395 +       if (hs_pol_inv)
16396 +               l &= ~(1 << 21);
16397 +       else
16398 +               l |= 1 << 21;
16399 +       if (vs_pol_inv)
16400 +               l &= ~(1 << 20);
16401 +       else
16402 +               l |= 1 << 20;
16403 +       rfbi_enable_clocks(0);
16404 +
16405 +       return 0;
16406 +}
16407 +EXPORT_SYMBOL(omap_rfbi_setup_te);
16408 +
16409 +/* xxx FIX module selection missing */
16410 +int omap_rfbi_enable_te(bool enable, unsigned line)
16411 +{
16412 +       u32 l;
16413 +
16414 +       DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode);
16415 +       if (line > (1 << 11) - 1)
16416 +               return -EINVAL;
16417 +
16418 +       rfbi_enable_clocks(1);
16419 +       l = rfbi_read_reg(RFBI_CONFIG(0));
16420 +       l &= ~(0x3 << 2);
16421 +       if (enable) {
16422 +               rfbi.te_enabled = 1;
16423 +               l |= rfbi.te_mode << 2;
16424 +       } else
16425 +               rfbi.te_enabled = 0;
16426 +       rfbi_write_reg(RFBI_CONFIG(0), l);
16427 +       rfbi_write_reg(RFBI_LINE_NUMBER, line);
16428 +       rfbi_enable_clocks(0);
16429 +
16430 +       return 0;
16431 +}
16432 +EXPORT_SYMBOL(omap_rfbi_enable_te);
16433 +
16434 +#if 0
16435 +static void rfbi_enable_config(int enable1, int enable2)
16436 +{
16437 +       u32 l;
16438 +       int cs = 0;
16439 +
16440 +       if (enable1)
16441 +               cs |= 1<<0;
16442 +       if (enable2)
16443 +               cs |= 1<<1;
16444 +
16445 +       rfbi_enable_clocks(1);
16446 +
16447 +       l = rfbi_read_reg(RFBI_CONTROL);
16448 +
16449 +       l = FLD_MOD(l, cs, 3, 2);
16450 +       l = FLD_MOD(l, 0, 1, 1);
16451 +
16452 +       rfbi_write_reg(RFBI_CONTROL, l);
16453 +
16454 +
16455 +       l = rfbi_read_reg(RFBI_CONFIG(0));
16456 +       l = FLD_MOD(l, 0, 3, 2); /* TRIGGERMODE: ITE */
16457 +       /*l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
16458 +       /*l |= FLD_VAL(0, 8, 7); */ /* L4FORMAT, 1pix/L4 */
16459 +
16460 +       l = FLD_MOD(l, 0, 16, 16); /* A0POLARITY */
16461 +       l = FLD_MOD(l, 1, 20, 20); /* TE_VSYNC_POLARITY */
16462 +       l = FLD_MOD(l, 1, 21, 21); /* HSYNCPOLARITY */
16463 +
16464 +       l = FLD_MOD(l, OMAP_DSS_RFBI_PARALLELMODE_8, 1, 0);
16465 +       rfbi_write_reg(RFBI_CONFIG(0), l);
16466 +
16467 +       rfbi_enable_clocks(0);
16468 +}
16469 +#endif
16470 +
16471 +int rfbi_configure(int rfbi_module, int bpp, int lines)
16472 +{
16473 +       u32 l;
16474 +       int cycle1 = 0, cycle2 = 0, cycle3 = 0;
16475 +       enum omap_rfbi_cycleformat cycleformat;
16476 +       enum omap_rfbi_datatype datatype;
16477 +       enum omap_rfbi_parallelmode parallelmode;
16478 +
16479 +       switch (bpp) {
16480 +       case 12:
16481 +               datatype = OMAP_DSS_RFBI_DATATYPE_12;
16482 +               break;
16483 +       case 16:
16484 +               datatype = OMAP_DSS_RFBI_DATATYPE_16;
16485 +               break;
16486 +       case 18:
16487 +               datatype = OMAP_DSS_RFBI_DATATYPE_18;
16488 +               break;
16489 +       case 24:
16490 +               datatype = OMAP_DSS_RFBI_DATATYPE_24;
16491 +               break;
16492 +       default:
16493 +               BUG();
16494 +               return 1;
16495 +       }
16496 +       rfbi.datatype = datatype;
16497 +
16498 +       switch (lines) {
16499 +       case 8:
16500 +               parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8;
16501 +               break;
16502 +       case 9:
16503 +               parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9;
16504 +               break;
16505 +       case 12:
16506 +               parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12;
16507 +               break;
16508 +       case 16:
16509 +               parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16;
16510 +               break;
16511 +       default:
16512 +               BUG();
16513 +               return 1;
16514 +       }
16515 +       rfbi.parallelmode = parallelmode;
16516 +
16517 +       if ((bpp % lines) == 0) {
16518 +               switch (bpp / lines) {
16519 +               case 1:
16520 +                       cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1;
16521 +                       break;
16522 +               case 2:
16523 +                       cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1;
16524 +                       break;
16525 +               case 3:
16526 +                       cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1;
16527 +                       break;
16528 +               default:
16529 +                       BUG();
16530 +                       return 1;
16531 +               }
16532 +       } else if ((2 * bpp % lines) == 0) {
16533 +               if ((2 * bpp / lines) == 3)
16534 +                       cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2;
16535 +               else {
16536 +                       BUG();
16537 +                       return 1;
16538 +               }
16539 +       } else {
16540 +               BUG();
16541 +               return 1;
16542 +       }
16543 +
16544 +       switch (cycleformat) {
16545 +       case OMAP_DSS_RFBI_CYCLEFORMAT_1_1:
16546 +               cycle1 = lines;
16547 +               break;
16548 +
16549 +       case OMAP_DSS_RFBI_CYCLEFORMAT_2_1:
16550 +               cycle1 = lines;
16551 +               cycle2 = lines;
16552 +               break;
16553 +
16554 +       case OMAP_DSS_RFBI_CYCLEFORMAT_3_1:
16555 +               cycle1 = lines;
16556 +               cycle2 = lines;
16557 +               cycle3 = lines;
16558 +               break;
16559 +
16560 +       case OMAP_DSS_RFBI_CYCLEFORMAT_3_2:
16561 +               cycle1 = lines;
16562 +               cycle2 = (lines / 2) | ((lines / 2) << 16);
16563 +               cycle3 = (lines << 16);
16564 +               break;
16565 +       }
16566 +
16567 +       rfbi_enable_clocks(1);
16568 +
16569 +       REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */
16570 +
16571 +       l = 0;
16572 +       l |= FLD_VAL(parallelmode, 1, 0);
16573 +       l |= FLD_VAL(0, 3, 2);          /* TRIGGERMODE: ITE */
16574 +       l |= FLD_VAL(0, 4, 4);          /* TIMEGRANULARITY */
16575 +       l |= FLD_VAL(datatype, 6, 5);
16576 +       /* l |= FLD_VAL(2, 8, 7); */    /* L4FORMAT, 2pix/L4 */
16577 +       l |= FLD_VAL(0, 8, 7);  /* L4FORMAT, 1pix/L4 */
16578 +       l |= FLD_VAL(cycleformat, 10, 9);
16579 +       l |= FLD_VAL(0, 12, 11);        /* UNUSEDBITS */
16580 +       l |= FLD_VAL(0, 16, 16);        /* A0POLARITY */
16581 +       l |= FLD_VAL(0, 17, 17);        /* REPOLARITY */
16582 +       l |= FLD_VAL(0, 18, 18);        /* WEPOLARITY */
16583 +       l |= FLD_VAL(0, 19, 19);        /* CSPOLARITY */
16584 +       l |= FLD_VAL(1, 20, 20);        /* TE_VSYNC_POLARITY */
16585 +       l |= FLD_VAL(1, 21, 21);        /* HSYNCPOLARITY */
16586 +       rfbi_write_reg(RFBI_CONFIG(rfbi_module), l);
16587 +
16588 +       rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1);
16589 +       rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2);
16590 +       rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3);
16591 +
16592 +
16593 +       l = rfbi_read_reg(RFBI_CONTROL);
16594 +       l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */
16595 +       l = FLD_MOD(l, 0, 1, 1); /* clear bypass */
16596 +       rfbi_write_reg(RFBI_CONTROL, l);
16597 +
16598 +
16599 +       DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n",
16600 +              bpp, lines, cycle1, cycle2, cycle3);
16601 +
16602 +       rfbi_enable_clocks(0);
16603 +
16604 +       return 0;
16605 +}
16606 +EXPORT_SYMBOL(rfbi_configure);
16607 +
16608 +static int rfbi_find_display(struct omap_dss_device *dssdev)
16609 +{
16610 +       if (dssdev == rfbi.dssdev[0])
16611 +               return 0;
16612 +
16613 +       if (dssdev == rfbi.dssdev[1])
16614 +               return 1;
16615 +
16616 +       BUG();
16617 +       return -1;
16618 +}
16619 +
16620 +
16621 +static void signal_fifo_waiters(void)
16622 +{
16623 +       if (atomic_read(&rfbi.cmd_fifo_full) > 0) {
16624 +               /* DSSDBG("SIGNALING: Fifo not full for waiter!\n"); */
16625 +               complete(&rfbi.cmd_done);
16626 +               atomic_dec(&rfbi.cmd_fifo_full);
16627 +       }
16628 +}
16629 +
16630 +/* returns 1 for async op, and 0 for sync op */
16631 +static int do_update(struct omap_dss_device *dssdev, struct update_region *upd)
16632 +{
16633 +       u16 x = upd->x;
16634 +       u16 y = upd->y;
16635 +       u16 w = upd->w;
16636 +       u16 h = upd->h;
16637 +
16638 +       perf_mark_setup();
16639 +
16640 +       if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
16641 +               /*dssdev->driver->enable_te(dssdev, 1); */
16642 +               dss_setup_partial_planes(dssdev, &x, &y, &w, &h);
16643 +       }
16644 +
16645 +#ifdef MEASURE_PERF
16646 +       rfbi.perf_bytes = w * h * 2; /* XXX always 16bit */
16647 +#endif
16648 +
16649 +       dssdev->driver->setup_update(dssdev, x, y, w, h);
16650 +
16651 +       if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
16652 +               rfbi_transfer_area(w, h, NULL, NULL);
16653 +               return 1;
16654 +       } else {
16655 +               struct omap_overlay *ovl;
16656 +               void __iomem *addr;
16657 +               int scr_width;
16658 +
16659 +               ovl = dssdev->manager->overlays[0];
16660 +               scr_width = ovl->info.screen_width;
16661 +               addr = ovl->info.vaddr;
16662 +
16663 +               omap_rfbi_write_pixels(addr, scr_width, x, y, w, h);
16664 +
16665 +               perf_show("L4");
16666 +
16667 +               return 0;
16668 +       }
16669 +}
16670 +
16671 +static void process_cmd_fifo(void)
16672 +{
16673 +       int len;
16674 +       struct update_param p;
16675 +       struct omap_dss_device *dssdev;
16676 +       unsigned long flags;
16677 +
16678 +       if (atomic_inc_return(&rfbi.cmd_pending) != 1)
16679 +               return;
16680 +
16681 +       while (true) {
16682 +               spin_lock_irqsave(rfbi.cmd_fifo->lock, flags);
16683 +
16684 +               len = __kfifo_get(rfbi.cmd_fifo, (unsigned char *)&p,
16685 +                                 sizeof(struct update_param));
16686 +               if (len == 0) {
16687 +                       DSSDBG("nothing more in fifo\n");
16688 +                       atomic_set(&rfbi.cmd_pending, 0);
16689 +                       spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
16690 +                       break;
16691 +               }
16692 +
16693 +               /* DSSDBG("fifo full %d\n", rfbi.cmd_fifo_full.counter);*/
16694 +
16695 +               spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
16696 +
16697 +               BUG_ON(len != sizeof(struct update_param));
16698 +               BUG_ON(p.rfbi_module > 1);
16699 +
16700 +               dssdev = rfbi.dssdev[p.rfbi_module];
16701 +
16702 +               if (p.cmd == RFBI_CMD_UPDATE) {
16703 +                       if (do_update(dssdev, &p.par.r))
16704 +                               break; /* async op */
16705 +               } else if (p.cmd == RFBI_CMD_SYNC) {
16706 +                       DSSDBG("Signaling SYNC done!\n");
16707 +                       complete(p.par.sync);
16708 +               } else
16709 +                       BUG();
16710 +       }
16711 +
16712 +       signal_fifo_waiters();
16713 +}
16714 +
16715 +static void rfbi_push_cmd(struct update_param *p)
16716 +{
16717 +       int ret;
16718 +
16719 +       while (1) {
16720 +               unsigned long flags;
16721 +               int available;
16722 +
16723 +               spin_lock_irqsave(rfbi.cmd_fifo->lock, flags);
16724 +               available = RFBI_CMD_FIFO_LEN_BYTES -
16725 +                       __kfifo_len(rfbi.cmd_fifo);
16726 +
16727 +/*             DSSDBG("%d bytes left in fifo\n", available); */
16728 +               if (available < sizeof(struct update_param)) {
16729 +                       DSSDBG("Going to wait because FIFO FULL..\n");
16730 +                       spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
16731 +                       atomic_inc(&rfbi.cmd_fifo_full);
16732 +                       wait_for_completion(&rfbi.cmd_done);
16733 +                       /*DSSDBG("Woke up because fifo not full anymore\n");*/
16734 +                       continue;
16735 +               }
16736 +
16737 +               ret = __kfifo_put(rfbi.cmd_fifo, (unsigned char *)p,
16738 +                                 sizeof(struct update_param));
16739 +/*             DSSDBG("pushed %d bytes\n", ret);*/
16740 +
16741 +               spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
16742 +
16743 +               BUG_ON(ret != sizeof(struct update_param));
16744 +
16745 +               break;
16746 +       }
16747 +}
16748 +
16749 +static void rfbi_push_update(int rfbi_module, int x, int y, int w, int h)
16750 +{
16751 +       struct update_param p;
16752 +
16753 +       p.rfbi_module = rfbi_module;
16754 +       p.cmd = RFBI_CMD_UPDATE;
16755 +
16756 +       p.par.r.x = x;
16757 +       p.par.r.y = y;
16758 +       p.par.r.w = w;
16759 +       p.par.r.h = h;
16760 +
16761 +       DSSDBG("RFBI pushed %d,%d %dx%d\n", x, y, w, h);
16762 +
16763 +       rfbi_push_cmd(&p);
16764 +
16765 +       process_cmd_fifo();
16766 +}
16767 +
16768 +static void rfbi_push_sync(int rfbi_module, struct completion *sync_comp)
16769 +{
16770 +       struct update_param p;
16771 +
16772 +       p.rfbi_module = rfbi_module;
16773 +       p.cmd = RFBI_CMD_SYNC;
16774 +       p.par.sync = sync_comp;
16775 +
16776 +       rfbi_push_cmd(&p);
16777 +
16778 +       DSSDBG("RFBI sync pushed to cmd fifo\n");
16779 +
16780 +       process_cmd_fifo();
16781 +}
16782 +
16783 +void rfbi_dump_regs(struct seq_file *s)
16784 +{
16785 +#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
16786 +
16787 +       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
16788 +
16789 +       DUMPREG(RFBI_REVISION);
16790 +       DUMPREG(RFBI_SYSCONFIG);
16791 +       DUMPREG(RFBI_SYSSTATUS);
16792 +       DUMPREG(RFBI_CONTROL);
16793 +       DUMPREG(RFBI_PIXEL_CNT);
16794 +       DUMPREG(RFBI_LINE_NUMBER);
16795 +       DUMPREG(RFBI_CMD);
16796 +       DUMPREG(RFBI_PARAM);
16797 +       DUMPREG(RFBI_DATA);
16798 +       DUMPREG(RFBI_READ);
16799 +       DUMPREG(RFBI_STATUS);
16800 +
16801 +       DUMPREG(RFBI_CONFIG(0));
16802 +       DUMPREG(RFBI_ONOFF_TIME(0));
16803 +       DUMPREG(RFBI_CYCLE_TIME(0));
16804 +       DUMPREG(RFBI_DATA_CYCLE1(0));
16805 +       DUMPREG(RFBI_DATA_CYCLE2(0));
16806 +       DUMPREG(RFBI_DATA_CYCLE3(0));
16807 +
16808 +       DUMPREG(RFBI_CONFIG(1));
16809 +       DUMPREG(RFBI_ONOFF_TIME(1));
16810 +       DUMPREG(RFBI_CYCLE_TIME(1));
16811 +       DUMPREG(RFBI_DATA_CYCLE1(1));
16812 +       DUMPREG(RFBI_DATA_CYCLE2(1));
16813 +       DUMPREG(RFBI_DATA_CYCLE3(1));
16814 +
16815 +       DUMPREG(RFBI_VSYNC_WIDTH);
16816 +       DUMPREG(RFBI_HSYNC_WIDTH);
16817 +
16818 +       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
16819 +#undef DUMPREG
16820 +}
16821 +
16822 +int rfbi_init(void)
16823 +{
16824 +       u32 rev;
16825 +       u32 l;
16826 +
16827 +       spin_lock_init(&rfbi.cmd_lock);
16828 +       rfbi.cmd_fifo = kfifo_alloc(RFBI_CMD_FIFO_LEN_BYTES, GFP_KERNEL,
16829 +                                   &rfbi.cmd_lock);
16830 +       if (IS_ERR(rfbi.cmd_fifo))
16831 +               return -ENOMEM;
16832 +
16833 +       init_completion(&rfbi.cmd_done);
16834 +       atomic_set(&rfbi.cmd_fifo_full, 0);
16835 +       atomic_set(&rfbi.cmd_pending, 0);
16836 +
16837 +       rfbi.base = ioremap(RFBI_BASE, SZ_256);
16838 +       if (!rfbi.base) {
16839 +               DSSERR("can't ioremap RFBI\n");
16840 +               return -ENOMEM;
16841 +       }
16842 +
16843 +       rfbi_enable_clocks(1);
16844 +
16845 +       msleep(10);
16846 +
16847 +       rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
16848 +
16849 +       /* Enable autoidle and smart-idle */
16850 +       l = rfbi_read_reg(RFBI_SYSCONFIG);
16851 +       l |= (1 << 0) | (2 << 3);
16852 +       rfbi_write_reg(RFBI_SYSCONFIG, l);
16853 +
16854 +       rev = rfbi_read_reg(RFBI_REVISION);
16855 +       printk(KERN_INFO "OMAP RFBI rev %d.%d\n",
16856 +              FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
16857 +
16858 +       rfbi_enable_clocks(0);
16859 +
16860 +       return 0;
16861 +}
16862 +
16863 +void rfbi_exit(void)
16864 +{
16865 +       DSSDBG("rfbi_exit\n");
16866 +
16867 +       kfifo_free(rfbi.cmd_fifo);
16868 +
16869 +       iounmap(rfbi.base);
16870 +}
16871 +
16872 +/* struct omap_display support */
16873 +static int rfbi_display_update(struct omap_dss_device *dssdev,
16874 +                       u16 x, u16 y, u16 w, u16 h)
16875 +{
16876 +       int rfbi_module;
16877 +
16878 +       if (w == 0 || h == 0)
16879 +               return 0;
16880 +
16881 +       rfbi_module = rfbi_find_display(dssdev);
16882 +
16883 +       rfbi_push_update(rfbi_module, x, y, w, h);
16884 +
16885 +       return 0;
16886 +}
16887 +
16888 +static int rfbi_display_sync(struct omap_dss_device *dssdev)
16889 +{
16890 +       struct completion sync_comp;
16891 +       int rfbi_module;
16892 +
16893 +       rfbi_module = rfbi_find_display(dssdev);
16894 +
16895 +       init_completion(&sync_comp);
16896 +       rfbi_push_sync(rfbi_module, &sync_comp);
16897 +       DSSDBG("Waiting for SYNC to happen...\n");
16898 +       wait_for_completion(&sync_comp);
16899 +       DSSDBG("Released from SYNC\n");
16900 +       return 0;
16901 +}
16902 +
16903 +static int rfbi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
16904 +{
16905 +       dssdev->driver->enable_te(dssdev, enable);
16906 +       return 0;
16907 +}
16908 +
16909 +static int rfbi_display_enable(struct omap_dss_device *dssdev)
16910 +{
16911 +       int r;
16912 +
16913 +       r = omap_dss_start_device(dssdev);
16914 +       if (r) {
16915 +               DSSERR("failed to start device\n");
16916 +               goto err0;
16917 +       }
16918 +
16919 +       r = omap_dispc_register_isr(framedone_callback, NULL,
16920 +                       DISPC_IRQ_FRAMEDONE);
16921 +       if (r) {
16922 +               DSSERR("can't get FRAMEDONE irq\n");
16923 +               goto err1;
16924 +       }
16925 +
16926 +       dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
16927 +
16928 +       dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_RFBI);
16929 +
16930 +       dispc_set_tft_data_lines(dssdev->ctrl.pixel_size);
16931 +
16932 +       rfbi_configure(dssdev->phy.rfbi.channel,
16933 +                              dssdev->ctrl.pixel_size,
16934 +                              dssdev->phy.rfbi.data_lines);
16935 +
16936 +       rfbi_set_timings(dssdev->phy.rfbi.channel,
16937 +                        &dssdev->ctrl.rfbi_timings);
16938 +
16939 +
16940 +       if (dssdev->driver->enable) {
16941 +               r = dssdev->driver->enable(dssdev);
16942 +               if (r)
16943 +                       goto err2;
16944 +       }
16945 +
16946 +       return 0;
16947 +err2:
16948 +       omap_dispc_unregister_isr(framedone_callback, NULL,
16949 +                       DISPC_IRQ_FRAMEDONE);
16950 +err1:
16951 +       omap_dss_stop_device(dssdev);
16952 +err0:
16953 +       return r;
16954 +}
16955 +
16956 +static void rfbi_display_disable(struct omap_dss_device *dssdev)
16957 +{
16958 +       dssdev->driver->disable(dssdev);
16959 +       omap_dispc_unregister_isr(framedone_callback, NULL,
16960 +                       DISPC_IRQ_FRAMEDONE);
16961 +       omap_dss_stop_device(dssdev);
16962 +}
16963 +
16964 +int rfbi_init_display(struct omap_dss_device *dssdev)
16965 +{
16966 +       dssdev->enable = rfbi_display_enable;
16967 +       dssdev->disable = rfbi_display_disable;
16968 +       dssdev->update = rfbi_display_update;
16969 +       dssdev->sync = rfbi_display_sync;
16970 +       dssdev->enable_te = rfbi_display_enable_te;
16971 +
16972 +       rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
16973 +
16974 +       dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
16975 +
16976 +       return 0;
16977 +}
16978 diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
16979 new file mode 100644
16980 index 0000000..a9c727e
16981 --- /dev/null
16982 +++ b/drivers/video/omap2/dss/sdi.c
16983 @@ -0,0 +1,261 @@
16984 +/*
16985 + * linux/drivers/video/omap2/dss/sdi.c
16986 + *
16987 + * Copyright (C) 2009 Nokia Corporation
16988 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
16989 + *
16990 + * This program is free software; you can redistribute it and/or modify it
16991 + * under the terms of the GNU General Public License version 2 as published by
16992 + * the Free Software Foundation.
16993 + *
16994 + * This program is distributed in the hope that it will be useful, but WITHOUT
16995 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16996 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16997 + * more details.
16998 + *
16999 + * You should have received a copy of the GNU General Public License along with
17000 + * this program.  If not, see <http://www.gnu.org/licenses/>.
17001 + */
17002 +
17003 +#define DSS_SUBSYS_NAME "SDI"
17004 +
17005 +#include <linux/kernel.h>
17006 +#include <linux/clk.h>
17007 +#include <linux/delay.h>
17008 +#include <linux/err.h>
17009 +
17010 +#include <mach/board.h>
17011 +#include <mach/display.h>
17012 +#include "dss.h"
17013 +
17014 +static struct {
17015 +       bool skip_init;
17016 +       bool update_enabled;
17017 +} sdi;
17018 +
17019 +static void sdi_basic_init(void)
17020 +{
17021 +       dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
17022 +
17023 +       dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
17024 +       dispc_set_tft_data_lines(24);
17025 +       dispc_lcd_enable_signal_polarity(1);
17026 +}
17027 +
17028 +static int sdi_display_enable(struct omap_dss_device *dssdev)
17029 +{
17030 +       struct omap_video_timings *t = &dssdev->panel.timings;
17031 +       struct dispc_clock_info cinfo;
17032 +       u16 lck_div, pck_div;
17033 +       unsigned long fck;
17034 +       unsigned long pck;
17035 +       int r;
17036 +
17037 +       r = omap_dss_start_device(dssdev);
17038 +       if (r) {
17039 +               DSSERR("failed to start device\n");
17040 +               goto err0;
17041 +       }
17042 +
17043 +       if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
17044 +               DSSERR("dssdev already enabled\n");
17045 +               r = -EINVAL;
17046 +               goto err1;
17047 +       }
17048 +
17049 +       /* In case of skip_init sdi_init has already enabled the clocks */
17050 +       if (!sdi.skip_init)
17051 +               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
17052 +
17053 +       sdi_basic_init();
17054 +
17055 +       /* 15.5.9.1.2 */
17056 +       dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
17057 +
17058 +       dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi,
17059 +                       dssdev->panel.acb);
17060 +
17061 +       if (!sdi.skip_init)
17062 +               r = dispc_calc_clock_div(1, t->pixel_clock * 1000,
17063 +                               &cinfo);
17064 +       else
17065 +               r = dispc_get_clock_div(&cinfo);
17066 +
17067 +       if (r)
17068 +               goto err2;
17069 +
17070 +       fck = cinfo.fck;
17071 +       lck_div = cinfo.lck_div;
17072 +       pck_div = cinfo.pck_div;
17073 +
17074 +       pck = fck / lck_div / pck_div / 1000;
17075 +
17076 +       if (pck != t->pixel_clock) {
17077 +               DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
17078 +                               "got %lu kHz\n",
17079 +                               t->pixel_clock, pck);
17080 +
17081 +               t->pixel_clock = pck;
17082 +       }
17083 +
17084 +
17085 +       dispc_set_lcd_timings(t);
17086 +
17087 +       r = dispc_set_clock_div(&cinfo);
17088 +       if (r)
17089 +               goto err2;
17090 +
17091 +       if (!sdi.skip_init) {
17092 +               dss_sdi_init(dssdev->phy.sdi.datapairs);
17093 +               dss_sdi_enable();
17094 +               mdelay(2);
17095 +       }
17096 +
17097 +       dispc_enable_lcd_out(1);
17098 +
17099 +       if (dssdev->driver->enable) {
17100 +               r = dssdev->driver->enable(dssdev);
17101 +               if (r)
17102 +                       goto err3;
17103 +       }
17104 +
17105 +       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
17106 +
17107 +       sdi.skip_init = 0;
17108 +
17109 +       return 0;
17110 +err3:
17111 +       dispc_enable_lcd_out(0);
17112 +err2:
17113 +       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
17114 +err1:
17115 +       omap_dss_stop_device(dssdev);
17116 +err0:
17117 +       return r;
17118 +}
17119 +
17120 +static int sdi_display_resume(struct omap_dss_device *dssdev);
17121 +
17122 +static void sdi_display_disable(struct omap_dss_device *dssdev)
17123 +{
17124 +       if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
17125 +               return;
17126 +
17127 +       if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
17128 +               sdi_display_resume(dssdev);
17129 +
17130 +       if (dssdev->driver->disable)
17131 +               dssdev->driver->disable(dssdev);
17132 +
17133 +       dispc_enable_lcd_out(0);
17134 +
17135 +       dss_sdi_disable();
17136 +
17137 +       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
17138 +
17139 +       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
17140 +
17141 +       omap_dss_stop_device(dssdev);
17142 +}
17143 +
17144 +static int sdi_display_suspend(struct omap_dss_device *dssdev)
17145 +{
17146 +       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
17147 +               return -EINVAL;
17148 +
17149 +       if (dssdev->driver->suspend)
17150 +               dssdev->driver->suspend(dssdev);
17151 +
17152 +       dispc_enable_lcd_out(0);
17153 +
17154 +       dss_sdi_disable();
17155 +
17156 +       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
17157 +
17158 +       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
17159 +
17160 +       return 0;
17161 +}
17162 +
17163 +static int sdi_display_resume(struct omap_dss_device *dssdev)
17164 +{
17165 +       if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
17166 +               return -EINVAL;
17167 +
17168 +       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
17169 +
17170 +       dss_sdi_enable();
17171 +       mdelay(2);
17172 +
17173 +       dispc_enable_lcd_out(1);
17174 +
17175 +       if (dssdev->driver->resume)
17176 +               dssdev->driver->resume(dssdev);
17177 +
17178 +       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
17179 +
17180 +       return 0;
17181 +}
17182 +
17183 +static int sdi_display_set_update_mode(struct omap_dss_device *dssdev,
17184 +               enum omap_dss_update_mode mode)
17185 +{
17186 +       if (mode == OMAP_DSS_UPDATE_MANUAL)
17187 +               return -EINVAL;
17188 +
17189 +       if (mode == OMAP_DSS_UPDATE_DISABLED) {
17190 +               dispc_enable_lcd_out(0);
17191 +               sdi.update_enabled = 0;
17192 +       } else {
17193 +               dispc_enable_lcd_out(1);
17194 +               sdi.update_enabled = 1;
17195 +       }
17196 +
17197 +       return 0;
17198 +}
17199 +
17200 +static enum omap_dss_update_mode sdi_display_get_update_mode(
17201 +               struct omap_dss_device *dssdev)
17202 +{
17203 +       return sdi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
17204 +               OMAP_DSS_UPDATE_DISABLED;
17205 +}
17206 +
17207 +static void sdi_get_timings(struct omap_dss_device *dssdev,
17208 +                       struct omap_video_timings *timings)
17209 +{
17210 +       *timings = dssdev->panel.timings;
17211 +}
17212 +
17213 +int sdi_init_display(struct omap_dss_device *dssdev)
17214 +{
17215 +       DSSDBG("SDI init\n");
17216 +
17217 +       dssdev->enable = sdi_display_enable;
17218 +       dssdev->disable = sdi_display_disable;
17219 +       dssdev->suspend = sdi_display_suspend;
17220 +       dssdev->resume = sdi_display_resume;
17221 +       dssdev->set_update_mode = sdi_display_set_update_mode;
17222 +       dssdev->get_update_mode = sdi_display_get_update_mode;
17223 +       dssdev->get_timings = sdi_get_timings;
17224 +
17225 +       return 0;
17226 +}
17227 +
17228 +int sdi_init(bool skip_init)
17229 +{
17230 +       /* we store this for first display enable, then clear it */
17231 +       sdi.skip_init = skip_init;
17232 +
17233 +       /*
17234 +        * Enable clocks already here, otherwise there would be a toggle
17235 +        * of them until sdi_display_enable is called.
17236 +        */
17237 +       if (skip_init)
17238 +               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
17239 +       return 0;
17240 +}
17241 +
17242 +void sdi_exit(void)
17243 +{
17244 +}
17245 diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
17246 new file mode 100644
17247 index 0000000..cf7827e
17248 --- /dev/null
17249 +++ b/drivers/video/omap2/dss/venc.c
17250 @@ -0,0 +1,797 @@
17251 +/*
17252 + * linux/drivers/video/omap2/dss/venc.c
17253 + *
17254 + * Copyright (C) 2009 Nokia Corporation
17255 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
17256 + *
17257 + * VENC settings from TI's DSS driver
17258 + *
17259 + * This program is free software; you can redistribute it and/or modify it
17260 + * under the terms of the GNU General Public License version 2 as published by
17261 + * the Free Software Foundation.
17262 + *
17263 + * This program is distributed in the hope that it will be useful, but WITHOUT
17264 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17265 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
17266 + * more details.
17267 + *
17268 + * You should have received a copy of the GNU General Public License along with
17269 + * this program.  If not, see <http://www.gnu.org/licenses/>.
17270 + */
17271 +
17272 +#define DSS_SUBSYS_NAME "VENC"
17273 +
17274 +#include <linux/kernel.h>
17275 +#include <linux/module.h>
17276 +#include <linux/clk.h>
17277 +#include <linux/err.h>
17278 +#include <linux/io.h>
17279 +#include <linux/mutex.h>
17280 +#include <linux/completion.h>
17281 +#include <linux/delay.h>
17282 +#include <linux/string.h>
17283 +#include <linux/seq_file.h>
17284 +#include <linux/platform_device.h>
17285 +#include <linux/regulator/consumer.h>
17286 +
17287 +#include <mach/display.h>
17288 +#include <mach/cpu.h>
17289 +
17290 +#include "dss.h"
17291 +
17292 +#define VENC_BASE      0x48050C00
17293 +
17294 +/* Venc registers */
17295 +#define VENC_REV_ID                            0x00
17296 +#define VENC_STATUS                            0x04
17297 +#define VENC_F_CONTROL                         0x08
17298 +#define VENC_VIDOUT_CTRL                       0x10
17299 +#define VENC_SYNC_CTRL                         0x14
17300 +#define VENC_LLEN                              0x1C
17301 +#define VENC_FLENS                             0x20
17302 +#define VENC_HFLTR_CTRL                                0x24
17303 +#define VENC_CC_CARR_WSS_CARR                  0x28
17304 +#define VENC_C_PHASE                           0x2C
17305 +#define VENC_GAIN_U                            0x30
17306 +#define VENC_GAIN_V                            0x34
17307 +#define VENC_GAIN_Y                            0x38
17308 +#define VENC_BLACK_LEVEL                       0x3C
17309 +#define VENC_BLANK_LEVEL                       0x40
17310 +#define VENC_X_COLOR                           0x44
17311 +#define VENC_M_CONTROL                         0x48
17312 +#define VENC_BSTAMP_WSS_DATA                   0x4C
17313 +#define VENC_S_CARR                            0x50
17314 +#define VENC_LINE21                            0x54
17315 +#define VENC_LN_SEL                            0x58
17316 +#define VENC_L21__WC_CTL                       0x5C
17317 +#define VENC_HTRIGGER_VTRIGGER                 0x60
17318 +#define VENC_SAVID__EAVID                      0x64
17319 +#define VENC_FLEN__FAL                         0x68
17320 +#define VENC_LAL__PHASE_RESET                  0x6C
17321 +#define VENC_HS_INT_START_STOP_X               0x70
17322 +#define VENC_HS_EXT_START_STOP_X               0x74
17323 +#define VENC_VS_INT_START_X                    0x78
17324 +#define VENC_VS_INT_STOP_X__VS_INT_START_Y     0x7C
17325 +#define VENC_VS_INT_STOP_Y__VS_EXT_START_X     0x80
17326 +#define VENC_VS_EXT_STOP_X__VS_EXT_START_Y     0x84
17327 +#define VENC_VS_EXT_STOP_Y                     0x88
17328 +#define VENC_AVID_START_STOP_X                 0x90
17329 +#define VENC_AVID_START_STOP_Y                 0x94
17330 +#define VENC_FID_INT_START_X__FID_INT_START_Y  0xA0
17331 +#define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X 0xA4
17332 +#define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y 0xA8
17333 +#define VENC_TVDETGP_INT_START_STOP_X          0xB0
17334 +#define VENC_TVDETGP_INT_START_STOP_Y          0xB4
17335 +#define VENC_GEN_CTRL                          0xB8
17336 +#define VENC_OUTPUT_CONTROL                    0xC4
17337 +#define VENC_OUTPUT_TEST                       0xC8
17338 +#define VENC_DAC_B__DAC_C                      0xC8
17339 +
17340 +struct venc_config {
17341 +       u32 f_control;
17342 +       u32 vidout_ctrl;
17343 +       u32 sync_ctrl;
17344 +       u32 llen;
17345 +       u32 flens;
17346 +       u32 hfltr_ctrl;
17347 +       u32 cc_carr_wss_carr;
17348 +       u32 c_phase;
17349 +       u32 gain_u;
17350 +       u32 gain_v;
17351 +       u32 gain_y;
17352 +       u32 black_level;
17353 +       u32 blank_level;
17354 +       u32 x_color;
17355 +       u32 m_control;
17356 +       u32 bstamp_wss_data;
17357 +       u32 s_carr;
17358 +       u32 line21;
17359 +       u32 ln_sel;
17360 +       u32 l21__wc_ctl;
17361 +       u32 htrigger_vtrigger;
17362 +       u32 savid__eavid;
17363 +       u32 flen__fal;
17364 +       u32 lal__phase_reset;
17365 +       u32 hs_int_start_stop_x;
17366 +       u32 hs_ext_start_stop_x;
17367 +       u32 vs_int_start_x;
17368 +       u32 vs_int_stop_x__vs_int_start_y;
17369 +       u32 vs_int_stop_y__vs_ext_start_x;
17370 +       u32 vs_ext_stop_x__vs_ext_start_y;
17371 +       u32 vs_ext_stop_y;
17372 +       u32 avid_start_stop_x;
17373 +       u32 avid_start_stop_y;
17374 +       u32 fid_int_start_x__fid_int_start_y;
17375 +       u32 fid_int_offset_y__fid_ext_start_x;
17376 +       u32 fid_ext_start_y__fid_ext_offset_y;
17377 +       u32 tvdetgp_int_start_stop_x;
17378 +       u32 tvdetgp_int_start_stop_y;
17379 +       u32 gen_ctrl;
17380 +};
17381 +
17382 +/* from TRM */
17383 +static const struct venc_config venc_config_pal_trm = {
17384 +       .f_control                              = 0,
17385 +       .vidout_ctrl                            = 1,
17386 +       .sync_ctrl                              = 0x40,
17387 +       .llen                                   = 0x35F, /* 863 */
17388 +       .flens                                  = 0x270, /* 624 */
17389 +       .hfltr_ctrl                             = 0,
17390 +       .cc_carr_wss_carr                       = 0x2F7225ED,
17391 +       .c_phase                                = 0,
17392 +       .gain_u                                 = 0x111,
17393 +       .gain_v                                 = 0x181,
17394 +       .gain_y                                 = 0x140,
17395 +       .black_level                            = 0x3B,
17396 +       .blank_level                            = 0x3B,
17397 +       .x_color                                = 0x7,
17398 +       .m_control                              = 0x2,
17399 +       .bstamp_wss_data                        = 0x3F,
17400 +       .s_carr                                 = 0x2A098ACB,
17401 +       .line21                                 = 0,
17402 +       .ln_sel                                 = 0x01290015,
17403 +       .l21__wc_ctl                            = 0x0000F603,
17404 +       .htrigger_vtrigger                      = 0,
17405 +
17406 +       .savid__eavid                           = 0x06A70108,
17407 +       .flen__fal                              = 0x00180270,
17408 +       .lal__phase_reset                       = 0x00040135,
17409 +       .hs_int_start_stop_x                    = 0x00880358,
17410 +       .hs_ext_start_stop_x                    = 0x000F035F,
17411 +       .vs_int_start_x                         = 0x01A70000,
17412 +       .vs_int_stop_x__vs_int_start_y          = 0x000001A7,
17413 +       .vs_int_stop_y__vs_ext_start_x          = 0x01AF0000,
17414 +       .vs_ext_stop_x__vs_ext_start_y          = 0x000101AF,
17415 +       .vs_ext_stop_y                          = 0x00000025,
17416 +       .avid_start_stop_x                      = 0x03530083,
17417 +       .avid_start_stop_y                      = 0x026C002E,
17418 +       .fid_int_start_x__fid_int_start_y       = 0x0001008A,
17419 +       .fid_int_offset_y__fid_ext_start_x      = 0x002E0138,
17420 +       .fid_ext_start_y__fid_ext_offset_y      = 0x01380001,
17421 +
17422 +       .tvdetgp_int_start_stop_x               = 0x00140001,
17423 +       .tvdetgp_int_start_stop_y               = 0x00010001,
17424 +       .gen_ctrl                               = 0x00FF0000,
17425 +};
17426 +
17427 +/* from TRM */
17428 +static const struct venc_config venc_config_ntsc_trm = {
17429 +       .f_control                              = 0,
17430 +       .vidout_ctrl                            = 1,
17431 +       .sync_ctrl                              = 0x8040,
17432 +       .llen                                   = 0x359,
17433 +       .flens                                  = 0x20C,
17434 +       .hfltr_ctrl                             = 0,
17435 +       .cc_carr_wss_carr                       = 0x043F2631,
17436 +       .c_phase                                = 0,
17437 +       .gain_u                                 = 0x102,
17438 +       .gain_v                                 = 0x16C,
17439 +       .gain_y                                 = 0x12F,
17440 +       .black_level                            = 0x43,
17441 +       .blank_level                            = 0x38,
17442 +       .x_color                                = 0x7,
17443 +       .m_control                              = 0x1,
17444 +       .bstamp_wss_data                        = 0x38,
17445 +       .s_carr                                 = 0x21F07C1F,
17446 +       .line21                                 = 0,
17447 +       .ln_sel                                 = 0x01310011,
17448 +       .l21__wc_ctl                            = 0x0000F003,
17449 +       .htrigger_vtrigger                      = 0,
17450 +
17451 +       .savid__eavid                           = 0x069300F4,
17452 +       .flen__fal                              = 0x0016020C,
17453 +       .lal__phase_reset                       = 0x00060107,
17454 +       .hs_int_start_stop_x                    = 0x008E0350,
17455 +       .hs_ext_start_stop_x                    = 0x000F0359,
17456 +       .vs_int_start_x                         = 0x01A00000,
17457 +       .vs_int_stop_x__vs_int_start_y          = 0x020701A0,
17458 +       .vs_int_stop_y__vs_ext_start_x          = 0x01AC0024,
17459 +       .vs_ext_stop_x__vs_ext_start_y          = 0x020D01AC,
17460 +       .vs_ext_stop_y                          = 0x00000006,
17461 +       .avid_start_stop_x                      = 0x03480078,
17462 +       .avid_start_stop_y                      = 0x02060024,
17463 +       .fid_int_start_x__fid_int_start_y       = 0x0001008A,
17464 +       .fid_int_offset_y__fid_ext_start_x      = 0x01AC0106,
17465 +       .fid_ext_start_y__fid_ext_offset_y      = 0x01060006,
17466 +
17467 +       .tvdetgp_int_start_stop_x               = 0x00140001,
17468 +       .tvdetgp_int_start_stop_y               = 0x00010001,
17469 +       .gen_ctrl                               = 0x00F90000,
17470 +};
17471 +
17472 +static const struct venc_config venc_config_pal_bdghi = {
17473 +       .f_control                              = 0,
17474 +       .vidout_ctrl                            = 0,
17475 +       .sync_ctrl                              = 0,
17476 +       .hfltr_ctrl                             = 0,
17477 +       .x_color                                = 0,
17478 +       .line21                                 = 0,
17479 +       .ln_sel                                 = 21,
17480 +       .htrigger_vtrigger                      = 0,
17481 +       .tvdetgp_int_start_stop_x               = 0x00140001,
17482 +       .tvdetgp_int_start_stop_y               = 0x00010001,
17483 +       .gen_ctrl                               = 0x00FB0000,
17484 +
17485 +       .llen                                   = 864-1,
17486 +       .flens                                  = 625-1,
17487 +       .cc_carr_wss_carr                       = 0x2F7625ED,
17488 +       .c_phase                                = 0xDF,
17489 +       .gain_u                                 = 0x111,
17490 +       .gain_v                                 = 0x181,
17491 +       .gain_y                                 = 0x140,
17492 +       .black_level                            = 0x3e,
17493 +       .blank_level                            = 0x3e,
17494 +       .m_control                              = 0<<2 | 1<<1,
17495 +       .bstamp_wss_data                        = 0x42,
17496 +       .s_carr                                 = 0x2a098acb,
17497 +       .l21__wc_ctl                            = 0<<13 | 0x16<<8 | 0<<0,
17498 +       .savid__eavid                           = 0x06A70108,
17499 +       .flen__fal                              = 23<<16 | 624<<0,
17500 +       .lal__phase_reset                       = 2<<17 | 310<<0,
17501 +       .hs_int_start_stop_x                    = 0x00920358,
17502 +       .hs_ext_start_stop_x                    = 0x000F035F,
17503 +       .vs_int_start_x                         = 0x1a7<<16,
17504 +       .vs_int_stop_x__vs_int_start_y          = 0x000601A7,
17505 +       .vs_int_stop_y__vs_ext_start_x          = 0x01AF0036,
17506 +       .vs_ext_stop_x__vs_ext_start_y          = 0x27101af,
17507 +       .vs_ext_stop_y                          = 0x05,
17508 +       .avid_start_stop_x                      = 0x03530082,
17509 +       .avid_start_stop_y                      = 0x0270002E,
17510 +       .fid_int_start_x__fid_int_start_y       = 0x0005008A,
17511 +       .fid_int_offset_y__fid_ext_start_x      = 0x002E0138,
17512 +       .fid_ext_start_y__fid_ext_offset_y      = 0x01380005,
17513 +};
17514 +
17515 +const struct omap_video_timings omap_dss_pal_timings = {
17516 +       .x_res          = 720,
17517 +       .y_res          = 574,
17518 +       .pixel_clock    = 13500,
17519 +       .hsw            = 64,
17520 +       .hfp            = 12,
17521 +       .hbp            = 68,
17522 +       .vsw            = 5,
17523 +       .vfp            = 5,
17524 +       .vbp            = 41,
17525 +};
17526 +EXPORT_SYMBOL(omap_dss_pal_timings);
17527 +
17528 +const struct omap_video_timings omap_dss_ntsc_timings = {
17529 +       .x_res          = 720,
17530 +       .y_res          = 482,
17531 +       .pixel_clock    = 13500,
17532 +       .hsw            = 64,
17533 +       .hfp            = 16,
17534 +       .hbp            = 58,
17535 +       .vsw            = 6,
17536 +       .vfp            = 6,
17537 +       .vbp            = 31,
17538 +};
17539 +EXPORT_SYMBOL(omap_dss_ntsc_timings);
17540 +
17541 +static struct {
17542 +       void __iomem *base;
17543 +       struct mutex venc_lock;
17544 +       u32 wss_data;
17545 +       struct regulator *vdda_dac_reg;
17546 +} venc;
17547 +
17548 +static inline void venc_write_reg(int idx, u32 val)
17549 +{
17550 +       __raw_writel(val, venc.base + idx);
17551 +}
17552 +
17553 +static inline u32 venc_read_reg(int idx)
17554 +{
17555 +       u32 l = __raw_readl(venc.base + idx);
17556 +       return l;
17557 +}
17558 +
17559 +static void venc_write_config(const struct venc_config *config)
17560 +{
17561 +       DSSDBG("write venc conf\n");
17562 +
17563 +       venc_write_reg(VENC_LLEN, config->llen);
17564 +       venc_write_reg(VENC_FLENS, config->flens);
17565 +       venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr);
17566 +       venc_write_reg(VENC_C_PHASE, config->c_phase);
17567 +       venc_write_reg(VENC_GAIN_U, config->gain_u);
17568 +       venc_write_reg(VENC_GAIN_V, config->gain_v);
17569 +       venc_write_reg(VENC_GAIN_Y, config->gain_y);
17570 +       venc_write_reg(VENC_BLACK_LEVEL, config->black_level);
17571 +       venc_write_reg(VENC_BLANK_LEVEL, config->blank_level);
17572 +       venc_write_reg(VENC_M_CONTROL, config->m_control);
17573 +       venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
17574 +                       venc.wss_data);
17575 +       venc_write_reg(VENC_S_CARR, config->s_carr);
17576 +       venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl);
17577 +       venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid);
17578 +       venc_write_reg(VENC_FLEN__FAL, config->flen__fal);
17579 +       venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset);
17580 +       venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x);
17581 +       venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x);
17582 +       venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x);
17583 +       venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y,
17584 +                      config->vs_int_stop_x__vs_int_start_y);
17585 +       venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X,
17586 +                      config->vs_int_stop_y__vs_ext_start_x);
17587 +       venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y,
17588 +                      config->vs_ext_stop_x__vs_ext_start_y);
17589 +       venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y);
17590 +       venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x);
17591 +       venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y);
17592 +       venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y,
17593 +                      config->fid_int_start_x__fid_int_start_y);
17594 +       venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X,
17595 +                      config->fid_int_offset_y__fid_ext_start_x);
17596 +       venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y,
17597 +                      config->fid_ext_start_y__fid_ext_offset_y);
17598 +
17599 +       venc_write_reg(VENC_DAC_B__DAC_C,  venc_read_reg(VENC_DAC_B__DAC_C));
17600 +       venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl);
17601 +       venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl);
17602 +       venc_write_reg(VENC_X_COLOR, config->x_color);
17603 +       venc_write_reg(VENC_LINE21, config->line21);
17604 +       venc_write_reg(VENC_LN_SEL, config->ln_sel);
17605 +       venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger);
17606 +       venc_write_reg(VENC_TVDETGP_INT_START_STOP_X,
17607 +                      config->tvdetgp_int_start_stop_x);
17608 +       venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y,
17609 +                      config->tvdetgp_int_start_stop_y);
17610 +       venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl);
17611 +       venc_write_reg(VENC_F_CONTROL, config->f_control);
17612 +       venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl);
17613 +}
17614 +
17615 +static void venc_reset(void)
17616 +{
17617 +       int t = 1000;
17618 +
17619 +       venc_write_reg(VENC_F_CONTROL, 1<<8);
17620 +       while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) {
17621 +               if (--t == 0) {
17622 +                       DSSERR("Failed to reset venc\n");
17623 +                       return;
17624 +               }
17625 +       }
17626 +
17627 +       /* the magical sleep that makes things work */
17628 +       msleep(20);
17629 +}
17630 +
17631 +static void venc_enable_clocks(int enable)
17632 +{
17633 +       if (enable)
17634 +               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
17635 +                               DSS_CLK_96M);
17636 +       else
17637 +               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
17638 +                               DSS_CLK_96M);
17639 +}
17640 +
17641 +static const struct venc_config *venc_timings_to_config(
17642 +               struct omap_video_timings *timings)
17643 +{
17644 +       if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
17645 +               return &venc_config_pal_trm;
17646 +
17647 +       if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
17648 +               return &venc_config_ntsc_trm;
17649 +
17650 +       BUG();
17651 +}
17652 +
17653 +
17654 +
17655 +
17656 +
17657 +/* driver */
17658 +static int venc_panel_probe(struct omap_dss_device *dssdev)
17659 +{
17660 +       dssdev->panel.timings = omap_dss_pal_timings;
17661 +
17662 +       return 0;
17663 +}
17664 +
17665 +static void venc_panel_remove(struct omap_dss_device *dssdev)
17666 +{
17667 +}
17668 +
17669 +static int venc_panel_enable(struct omap_dss_device *dssdev)
17670 +{
17671 +       int r = 0;
17672 +
17673 +       /* wait couple of vsyncs until enabling the LCD */
17674 +       msleep(50);
17675 +
17676 +       if (dssdev->platform_enable)
17677 +               r = dssdev->platform_enable(dssdev);
17678 +
17679 +       return r;
17680 +}
17681 +
17682 +static void venc_panel_disable(struct omap_dss_device *dssdev)
17683 +{
17684 +       if (dssdev->platform_disable)
17685 +               dssdev->platform_disable(dssdev);
17686 +
17687 +       /* wait at least 5 vsyncs after disabling the LCD */
17688 +
17689 +       msleep(100);
17690 +}
17691 +
17692 +static int venc_panel_suspend(struct omap_dss_device *dssdev)
17693 +{
17694 +       venc_panel_disable(dssdev);
17695 +       return 0;
17696 +}
17697 +
17698 +static int venc_panel_resume(struct omap_dss_device *dssdev)
17699 +{
17700 +       return venc_panel_enable(dssdev);
17701 +}
17702 +
17703 +static struct omap_dss_driver venc_driver = {
17704 +       .probe          = venc_panel_probe,
17705 +       .remove         = venc_panel_remove,
17706 +
17707 +       .enable         = venc_panel_enable,
17708 +       .disable        = venc_panel_disable,
17709 +       .suspend        = venc_panel_suspend,
17710 +       .resume         = venc_panel_resume,
17711 +
17712 +       .driver         = {
17713 +               .name   = "venc",
17714 +               .owner  = THIS_MODULE,
17715 +       },
17716 +};
17717 +/* driver end */
17718 +
17719 +
17720 +
17721 +int venc_init(struct platform_device *pdev)
17722 +{
17723 +       u8 rev_id;
17724 +
17725 +       mutex_init(&venc.venc_lock);
17726 +
17727 +       venc.wss_data = 0;
17728 +
17729 +       venc.base = ioremap(VENC_BASE, SZ_1K);
17730 +       if (!venc.base) {
17731 +               DSSERR("can't ioremap VENC\n");
17732 +               return -ENOMEM;
17733 +       }
17734 +
17735 +       venc.vdda_dac_reg = regulator_get(&pdev->dev, "vdda_dac");
17736 +       if (IS_ERR(venc.vdda_dac_reg)) {
17737 +               iounmap(venc.base);
17738 +               DSSERR("can't get VDDA_DAC regulator\n");
17739 +               return PTR_ERR(venc.vdda_dac_reg);
17740 +       }
17741 +
17742 +       venc_enable_clocks(1);
17743 +
17744 +       rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
17745 +       printk(KERN_INFO "OMAP VENC rev %d\n", rev_id);
17746 +
17747 +       venc_enable_clocks(0);
17748 +
17749 +       return omap_dss_register_driver(&venc_driver);
17750 +}
17751 +
17752 +void venc_exit(void)
17753 +{
17754 +       omap_dss_unregister_driver(&venc_driver);
17755 +
17756 +       regulator_put(venc.vdda_dac_reg);
17757 +
17758 +       iounmap(venc.base);
17759 +}
17760 +
17761 +static void venc_power_on(struct omap_dss_device *dssdev)
17762 +{
17763 +       u32 l;
17764 +
17765 +       venc_enable_clocks(1);
17766 +
17767 +       venc_reset();
17768 +       venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
17769 +
17770 +       dss_set_venc_output(dssdev->phy.venc.type);
17771 +       dss_set_dac_pwrdn_bgz(1);
17772 +
17773 +       l = 0;
17774 +
17775 +       if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
17776 +               l |= 1 << 1;
17777 +       else /* S-Video */
17778 +               l |= (1 << 0) | (1 << 2);
17779 +
17780 +       if (dssdev->phy.venc.invert_polarity == false)
17781 +               l |= 1 << 3;
17782 +
17783 +       venc_write_reg(VENC_OUTPUT_CONTROL, l);
17784 +
17785 +       dispc_set_digit_size(dssdev->panel.timings.x_res,
17786 +                       dssdev->panel.timings.y_res/2);
17787 +
17788 +       regulator_enable(venc.vdda_dac_reg);
17789 +
17790 +       if (dssdev->platform_enable)
17791 +               dssdev->platform_enable(dssdev);
17792 +
17793 +       dispc_enable_digit_out(1);
17794 +}
17795 +
17796 +static void venc_power_off(struct omap_dss_device *dssdev)
17797 +{
17798 +       venc_write_reg(VENC_OUTPUT_CONTROL, 0);
17799 +       dss_set_dac_pwrdn_bgz(0);
17800 +
17801 +       dispc_enable_digit_out(0);
17802 +
17803 +       if (dssdev->platform_disable)
17804 +               dssdev->platform_disable(dssdev);
17805 +
17806 +       regulator_disable(venc.vdda_dac_reg);
17807 +
17808 +       venc_enable_clocks(0);
17809 +}
17810 +
17811 +static int venc_enable_display(struct omap_dss_device *dssdev)
17812 +{
17813 +       int r = 0;
17814 +
17815 +       DSSDBG("venc_enable_display\n");
17816 +
17817 +       mutex_lock(&venc.venc_lock);
17818 +
17819 +       if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
17820 +               r = -EINVAL;
17821 +               goto err;
17822 +       }
17823 +
17824 +       venc_power_on(dssdev);
17825 +
17826 +       venc.wss_data = 0;
17827 +
17828 +       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
17829 +err:
17830 +       mutex_unlock(&venc.venc_lock);
17831 +
17832 +       return r;
17833 +}
17834 +
17835 +static void venc_disable_display(struct omap_dss_device *dssdev)
17836 +{
17837 +       DSSDBG("venc_disable_display\n");
17838 +
17839 +       mutex_lock(&venc.venc_lock);
17840 +
17841 +       if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
17842 +               goto end;
17843 +
17844 +       if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
17845 +               /* suspended is the same as disabled with venc */
17846 +               dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
17847 +               goto end;
17848 +       }
17849 +
17850 +       venc_power_off(dssdev);
17851 +
17852 +       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
17853 +end:
17854 +       mutex_unlock(&venc.venc_lock);
17855 +}
17856 +
17857 +static int venc_display_suspend(struct omap_dss_device *dssdev)
17858 +{
17859 +       int r = 0;
17860 +
17861 +       DSSDBG("venc_display_suspend\n");
17862 +
17863 +       mutex_lock(&venc.venc_lock);
17864 +
17865 +       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
17866 +               r = -EINVAL;
17867 +               goto err;
17868 +       }
17869 +
17870 +       venc_power_off(dssdev);
17871 +
17872 +       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
17873 +err:
17874 +       mutex_unlock(&venc.venc_lock);
17875 +
17876 +       return r;
17877 +}
17878 +
17879 +static int venc_display_resume(struct omap_dss_device *dssdev)
17880 +{
17881 +       int r = 0;
17882 +
17883 +       DSSDBG("venc_display_resume\n");
17884 +
17885 +       mutex_lock(&venc.venc_lock);
17886 +
17887 +       if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
17888 +               r = -EINVAL;
17889 +               goto err;
17890 +       }
17891 +
17892 +       venc_power_on(dssdev);
17893 +
17894 +       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
17895 +err:
17896 +       mutex_unlock(&venc.venc_lock);
17897 +
17898 +       return r;
17899 +}
17900 +
17901 +static void venc_get_timings(struct omap_dss_device *dssdev,
17902 +                       struct omap_video_timings *timings)
17903 +{
17904 +       *timings = dssdev->panel.timings;
17905 +}
17906 +
17907 +static void venc_set_timings(struct omap_dss_device *dssdev,
17908 +                       struct omap_video_timings *timings)
17909 +{
17910 +       DSSDBG("venc_set_timings\n");
17911 +
17912 +       /* Reset WSS data when the TV standard changes. */
17913 +       if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings)))
17914 +               venc.wss_data = 0;
17915 +
17916 +       dssdev->panel.timings = *timings;
17917 +       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
17918 +               /* turn the venc off and on to get new timings to use */
17919 +               venc_disable_display(dssdev);
17920 +               venc_enable_display(dssdev);
17921 +       }
17922 +}
17923 +
17924 +static int venc_check_timings(struct omap_dss_device *dssdev,
17925 +                       struct omap_video_timings *timings)
17926 +{
17927 +       DSSDBG("venc_check_timings\n");
17928 +
17929 +       if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
17930 +               return 0;
17931 +
17932 +       if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
17933 +               return 0;
17934 +
17935 +       return -EINVAL;
17936 +}
17937 +
17938 +static u32 venc_get_wss(struct omap_dss_device *dssdev)
17939 +{
17940 +       /* Invert due to VENC_L21_WC_CTL:INV=1 */
17941 +       return (venc.wss_data >> 8) ^ 0xfffff;
17942 +}
17943 +
17944 +static int venc_set_wss(struct omap_dss_device *dssdev,        u32 wss)
17945 +{
17946 +       const struct venc_config *config;
17947 +
17948 +       DSSDBG("venc_set_wss\n");
17949 +
17950 +       mutex_lock(&venc.venc_lock);
17951 +
17952 +       config = venc_timings_to_config(&dssdev->panel.timings);
17953 +
17954 +       /* Invert due to VENC_L21_WC_CTL:INV=1 */
17955 +       venc.wss_data = (wss ^ 0xfffff) << 8;
17956 +
17957 +       venc_enable_clocks(1);
17958 +
17959 +       venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
17960 +                       venc.wss_data);
17961 +
17962 +       venc_enable_clocks(0);
17963 +
17964 +       mutex_unlock(&venc.venc_lock);
17965 +
17966 +       return 0;
17967 +}
17968 +
17969 +static enum omap_dss_update_mode venc_display_get_update_mode(
17970 +               struct omap_dss_device *dssdev)
17971 +{
17972 +       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
17973 +               return OMAP_DSS_UPDATE_AUTO;
17974 +       else
17975 +               return OMAP_DSS_UPDATE_DISABLED;
17976 +}
17977 +
17978 +int venc_init_display(struct omap_dss_device *dssdev)
17979 +{
17980 +       DSSDBG("init_display\n");
17981 +
17982 +       dssdev->enable = venc_enable_display;
17983 +       dssdev->disable = venc_disable_display;
17984 +       dssdev->suspend = venc_display_suspend;
17985 +       dssdev->resume = venc_display_resume;
17986 +       dssdev->get_timings = venc_get_timings;
17987 +       dssdev->set_timings = venc_set_timings;
17988 +       dssdev->check_timings = venc_check_timings;
17989 +       dssdev->get_wss = venc_get_wss;
17990 +       dssdev->set_wss = venc_set_wss;
17991 +       dssdev->get_update_mode = venc_display_get_update_mode;
17992 +
17993 +       return 0;
17994 +}
17995 +
17996 +void venc_dump_regs(struct seq_file *s)
17997 +{
17998 +#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
17999 +
18000 +       venc_enable_clocks(1);
18001 +
18002 +       DUMPREG(VENC_F_CONTROL);
18003 +       DUMPREG(VENC_VIDOUT_CTRL);
18004 +       DUMPREG(VENC_SYNC_CTRL);
18005 +       DUMPREG(VENC_LLEN);
18006 +       DUMPREG(VENC_FLENS);
18007 +       DUMPREG(VENC_HFLTR_CTRL);
18008 +       DUMPREG(VENC_CC_CARR_WSS_CARR);
18009 +       DUMPREG(VENC_C_PHASE);
18010 +       DUMPREG(VENC_GAIN_U);
18011 +       DUMPREG(VENC_GAIN_V);
18012 +       DUMPREG(VENC_GAIN_Y);
18013 +       DUMPREG(VENC_BLACK_LEVEL);
18014 +       DUMPREG(VENC_BLANK_LEVEL);
18015 +       DUMPREG(VENC_X_COLOR);
18016 +       DUMPREG(VENC_M_CONTROL);
18017 +       DUMPREG(VENC_BSTAMP_WSS_DATA);
18018 +       DUMPREG(VENC_S_CARR);
18019 +       DUMPREG(VENC_LINE21);
18020 +       DUMPREG(VENC_LN_SEL);
18021 +       DUMPREG(VENC_L21__WC_CTL);
18022 +       DUMPREG(VENC_HTRIGGER_VTRIGGER);
18023 +       DUMPREG(VENC_SAVID__EAVID);
18024 +       DUMPREG(VENC_FLEN__FAL);
18025 +       DUMPREG(VENC_LAL__PHASE_RESET);
18026 +       DUMPREG(VENC_HS_INT_START_STOP_X);
18027 +       DUMPREG(VENC_HS_EXT_START_STOP_X);
18028 +       DUMPREG(VENC_VS_INT_START_X);
18029 +       DUMPREG(VENC_VS_INT_STOP_X__VS_INT_START_Y);
18030 +       DUMPREG(VENC_VS_INT_STOP_Y__VS_EXT_START_X);
18031 +       DUMPREG(VENC_VS_EXT_STOP_X__VS_EXT_START_Y);
18032 +       DUMPREG(VENC_VS_EXT_STOP_Y);
18033 +       DUMPREG(VENC_AVID_START_STOP_X);
18034 +       DUMPREG(VENC_AVID_START_STOP_Y);
18035 +       DUMPREG(VENC_FID_INT_START_X__FID_INT_START_Y);
18036 +       DUMPREG(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X);
18037 +       DUMPREG(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y);
18038 +       DUMPREG(VENC_TVDETGP_INT_START_STOP_X);
18039 +       DUMPREG(VENC_TVDETGP_INT_START_STOP_Y);
18040 +       DUMPREG(VENC_GEN_CTRL);
18041 +       DUMPREG(VENC_OUTPUT_CONTROL);
18042 +       DUMPREG(VENC_OUTPUT_TEST);
18043 +
18044 +       venc_enable_clocks(0);
18045 +
18046 +#undef DUMPREG
18047 +}
18048 diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
18049 new file mode 100644
18050 index 0000000..bb694cc
18051 --- /dev/null
18052 +++ b/drivers/video/omap2/omapfb/Kconfig
18053 @@ -0,0 +1,37 @@
18054 +menuconfig FB_OMAP2
18055 +        tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)"
18056 +        depends on FB && OMAP2_DSS
18057 +
18058 +       select OMAP2_VRAM
18059 +       select OMAP2_VRFB
18060 +        select FB_CFB_FILLRECT
18061 +        select FB_CFB_COPYAREA
18062 +        select FB_CFB_IMAGEBLIT
18063 +        help
18064 +          Frame buffer driver for OMAP2/3 based boards.
18065 +
18066 +config FB_OMAP2_DEBUG_SUPPORT
18067 +       bool "Debug support for OMAP2/3 FB"
18068 +       default y
18069 +       depends on FB_OMAP2
18070 +       help
18071 +         Support for debug output. You have to enable the actual printing
18072 +         with debug module parameter.
18073 +
18074 +config FB_OMAP2_FORCE_AUTO_UPDATE
18075 +       bool "Force main display to automatic update mode"
18076 +       depends on FB_OMAP2
18077 +       help
18078 +         Forces main display to automatic update mode (if possible),
18079 +         and also enables tearsync (if possible). By default
18080 +         displays that support manual update are started in manual
18081 +         update mode.
18082 +
18083 +config FB_OMAP2_NUM_FBS
18084 +       int "Number of framebuffers"
18085 +       range 1 10
18086 +       default 3
18087 +       depends on FB_OMAP2
18088 +       help
18089 +         Select the number of framebuffers created. OMAP2/3 has 3 overlays
18090 +         so normally this would be 3.
18091 diff --git a/drivers/video/omap2/omapfb/Makefile b/drivers/video/omap2/omapfb/Makefile
18092 new file mode 100644
18093 index 0000000..51c2e00
18094 --- /dev/null
18095 +++ b/drivers/video/omap2/omapfb/Makefile
18096 @@ -0,0 +1,2 @@
18097 +obj-$(CONFIG_FB_OMAP2) += omapfb.o
18098 +omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
18099 diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
18100 new file mode 100644
18101 index 0000000..70fb64e
18102 --- /dev/null
18103 +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
18104 @@ -0,0 +1,727 @@
18105 +/*
18106 + * linux/drivers/video/omap2/omapfb-ioctl.c
18107 + *
18108 + * Copyright (C) 2008 Nokia Corporation
18109 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
18110 + *
18111 + * Some code and ideas taken from drivers/video/omap/ driver
18112 + * by Imre Deak.
18113 + *
18114 + * This program is free software; you can redistribute it and/or modify it
18115 + * under the terms of the GNU General Public License version 2 as published by
18116 + * the Free Software Foundation.
18117 + *
18118 + * This program is distributed in the hope that it will be useful, but WITHOUT
18119 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18120 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18121 + * more details.
18122 + *
18123 + * You should have received a copy of the GNU General Public License along with
18124 + * this program.  If not, see <http://www.gnu.org/licenses/>.
18125 + */
18126 +
18127 +#include <linux/fb.h>
18128 +#include <linux/device.h>
18129 +#include <linux/uaccess.h>
18130 +#include <linux/platform_device.h>
18131 +#include <linux/mm.h>
18132 +#include <linux/omapfb.h>
18133 +#include <linux/vmalloc.h>
18134 +
18135 +#include <mach/display.h>
18136 +#include <mach/vrfb.h>
18137 +#include <mach/vram.h>
18138 +
18139 +#include "omapfb.h"
18140 +
18141 +static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
18142 +{
18143 +       struct omapfb_info *ofbi = FB2OFB(fbi);
18144 +       struct omapfb2_device *fbdev = ofbi->fbdev;
18145 +       struct omap_dss_device *display = fb2display(fbi);
18146 +       struct omap_overlay *ovl;
18147 +       struct omap_overlay_info info;
18148 +       int r = 0;
18149 +
18150 +       DBG("omapfb_setup_plane\n");
18151 +
18152 +       if (ofbi->num_overlays != 1) {
18153 +               r = -EINVAL;
18154 +               goto out;
18155 +       }
18156 +
18157 +       /* XXX uses only the first overlay */
18158 +       ovl = ofbi->overlays[0];
18159 +
18160 +       if (pi->enabled && !ofbi->region.size) {
18161 +               /*
18162 +                * This plane's memory was freed, can't enable it
18163 +                * until it's reallocated.
18164 +                */
18165 +               r = -EINVAL;
18166 +               goto out;
18167 +       }
18168 +
18169 +       ovl->get_overlay_info(ovl, &info);
18170 +
18171 +       info.pos_x = pi->pos_x;
18172 +       info.pos_y = pi->pos_y;
18173 +       info.out_width = pi->out_width;
18174 +       info.out_height = pi->out_height;
18175 +       info.enabled = pi->enabled;
18176 +
18177 +       r = ovl->set_overlay_info(ovl, &info);
18178 +       if (r)
18179 +               goto out;
18180 +
18181 +       if (ovl->manager) {
18182 +               r = ovl->manager->apply(ovl->manager);
18183 +               if (r)
18184 +                       goto out;
18185 +       }
18186 +
18187 +       if (display) {
18188 +               u16 w, h;
18189 +
18190 +               if (display->sync)
18191 +                       display->sync(display);
18192 +
18193 +               display->get_resolution(display, &w, &h);
18194 +
18195 +               if (display->update)
18196 +                       display->update(display, 0, 0, w, h);
18197 +       }
18198 +
18199 +out:
18200 +       if (r)
18201 +               dev_err(fbdev->dev, "setup_plane failed\n");
18202 +       return r;
18203 +}
18204 +
18205 +static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
18206 +{
18207 +       struct omapfb_info *ofbi = FB2OFB(fbi);
18208 +
18209 +       if (ofbi->num_overlays != 1) {
18210 +               memset(pi, 0, sizeof(*pi));
18211 +       } else {
18212 +               struct omap_overlay_info *ovli;
18213 +               struct omap_overlay *ovl;
18214 +
18215 +               ovl = ofbi->overlays[0];
18216 +               ovli = &ovl->info;
18217 +
18218 +               pi->pos_x = ovli->pos_x;
18219 +               pi->pos_y = ovli->pos_y;
18220 +               pi->enabled = ovli->enabled;
18221 +               pi->channel_out = 0; /* xxx */
18222 +               pi->mirror = 0;
18223 +               pi->out_width = ovli->out_width;
18224 +               pi->out_height = ovli->out_height;
18225 +       }
18226 +
18227 +       return 0;
18228 +}
18229 +
18230 +static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
18231 +{
18232 +       struct omapfb_info *ofbi = FB2OFB(fbi);
18233 +       struct omapfb2_device *fbdev = ofbi->fbdev;
18234 +       struct omapfb2_mem_region *rg;
18235 +       int r, i;
18236 +       size_t size;
18237 +
18238 +       if (mi->type > OMAPFB_MEMTYPE_MAX)
18239 +               return -EINVAL;
18240 +
18241 +       size = PAGE_ALIGN(mi->size);
18242 +
18243 +       rg = &ofbi->region;
18244 +
18245 +       for (i = 0; i < ofbi->num_overlays; i++) {
18246 +               if (ofbi->overlays[i]->info.enabled)
18247 +                       return -EBUSY;
18248 +       }
18249 +
18250 +       if (rg->size != size || rg->type != mi->type) {
18251 +               r = omapfb_realloc_fbmem(fbi, size, mi->type);
18252 +               if (r) {
18253 +                       dev_err(fbdev->dev, "realloc fbmem failed\n");
18254 +                       return r;
18255 +               }
18256 +       }
18257 +
18258 +       return 0;
18259 +}
18260 +
18261 +static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
18262 +{
18263 +       struct omapfb_info *ofbi = FB2OFB(fbi);
18264 +       struct omapfb2_mem_region *rg;
18265 +
18266 +       rg = &ofbi->region;
18267 +       memset(mi, 0, sizeof(*mi));
18268 +
18269 +       mi->size = rg->size;
18270 +       mi->type = rg->type;
18271 +
18272 +       return 0;
18273 +}
18274 +
18275 +static int omapfb_update_window(struct fb_info *fbi,
18276 +               u32 x, u32 y, u32 w, u32 h)
18277 +{
18278 +       struct omap_dss_device *display = fb2display(fbi);
18279 +       u16 dw, dh;
18280 +
18281 +       if (!display)
18282 +               return 0;
18283 +
18284 +       if (w == 0 || h == 0)
18285 +               return 0;
18286 +
18287 +       display->get_resolution(display, &dw, &dh);
18288 +
18289 +       if (x + w > dw || y + h > dh)
18290 +               return -EINVAL;
18291 +
18292 +       display->update(display, x, y, w, h);
18293 +
18294 +       return 0;
18295 +}
18296 +
18297 +static int omapfb_set_update_mode(struct fb_info *fbi,
18298 +                                  enum omapfb_update_mode mode)
18299 +{
18300 +       struct omap_dss_device *display = fb2display(fbi);
18301 +       enum omap_dss_update_mode um;
18302 +       int r;
18303 +
18304 +       if (!display || !display->set_update_mode)
18305 +               return -EINVAL;
18306 +
18307 +       switch (mode) {
18308 +       case OMAPFB_UPDATE_DISABLED:
18309 +               um = OMAP_DSS_UPDATE_DISABLED;
18310 +               break;
18311 +
18312 +       case OMAPFB_AUTO_UPDATE:
18313 +               um = OMAP_DSS_UPDATE_AUTO;
18314 +               break;
18315 +
18316 +       case OMAPFB_MANUAL_UPDATE:
18317 +               um = OMAP_DSS_UPDATE_MANUAL;
18318 +               break;
18319 +
18320 +       default:
18321 +               return -EINVAL;
18322 +       }
18323 +
18324 +       r = display->set_update_mode(display, um);
18325 +
18326 +       return r;
18327 +}
18328 +
18329 +static int omapfb_get_update_mode(struct fb_info *fbi,
18330 +               enum omapfb_update_mode *mode)
18331 +{
18332 +       struct omap_dss_device *display = fb2display(fbi);
18333 +       enum omap_dss_update_mode m;
18334 +
18335 +       if (!display || !display->get_update_mode)
18336 +               return -EINVAL;
18337 +
18338 +       m = display->get_update_mode(display);
18339 +
18340 +       switch (m) {
18341 +       case OMAP_DSS_UPDATE_DISABLED:
18342 +               *mode = OMAPFB_UPDATE_DISABLED;
18343 +               break;
18344 +       case OMAP_DSS_UPDATE_AUTO:
18345 +               *mode = OMAPFB_AUTO_UPDATE;
18346 +               break;
18347 +       case OMAP_DSS_UPDATE_MANUAL:
18348 +               *mode = OMAPFB_MANUAL_UPDATE;
18349 +               break;
18350 +       default:
18351 +               BUG();
18352 +       }
18353 +
18354 +       return 0;
18355 +}
18356 +
18357 +/* XXX this color key handling is a hack... */
18358 +static struct omapfb_color_key omapfb_color_keys[2];
18359 +
18360 +static int _omapfb_set_color_key(struct omap_overlay_manager *mgr,
18361 +               struct omapfb_color_key *ck)
18362 +{
18363 +       struct omap_overlay_manager_info info;
18364 +       enum omap_dss_trans_key_type kt;
18365 +       int r;
18366 +
18367 +       mgr->get_manager_info(mgr, &info);
18368 +
18369 +       if (ck->key_type == OMAPFB_COLOR_KEY_DISABLED) {
18370 +               info.trans_enabled = false;
18371 +               omapfb_color_keys[mgr->id] = *ck;
18372 +
18373 +               r = mgr->set_manager_info(mgr, &info);
18374 +               if (r)
18375 +                       return r;
18376 +
18377 +               r = mgr->apply(mgr);
18378 +
18379 +               return r;
18380 +       }
18381 +
18382 +       switch (ck->key_type) {
18383 +       case OMAPFB_COLOR_KEY_GFX_DST:
18384 +               kt = OMAP_DSS_COLOR_KEY_GFX_DST;
18385 +               break;
18386 +       case OMAPFB_COLOR_KEY_VID_SRC:
18387 +               kt = OMAP_DSS_COLOR_KEY_VID_SRC;
18388 +               break;
18389 +       default:
18390 +               return -EINVAL;
18391 +       }
18392 +
18393 +       info.default_color = ck->background;
18394 +       info.trans_key = ck->trans_key;
18395 +       info.trans_key_type = kt;
18396 +       info.trans_enabled = true;
18397 +
18398 +       omapfb_color_keys[mgr->id] = *ck;
18399 +
18400 +       r = mgr->set_manager_info(mgr, &info);
18401 +       if (r)
18402 +               return r;
18403 +
18404 +       r = mgr->apply(mgr);
18405 +
18406 +       return r;
18407 +}
18408 +
18409 +static int omapfb_set_color_key(struct fb_info *fbi,
18410 +               struct omapfb_color_key *ck)
18411 +{
18412 +       struct omapfb_info *ofbi = FB2OFB(fbi);
18413 +       struct omapfb2_device *fbdev = ofbi->fbdev;
18414 +       int r;
18415 +       int i;
18416 +       struct omap_overlay_manager *mgr = NULL;
18417 +
18418 +       omapfb_lock(fbdev);
18419 +
18420 +       for (i = 0; i < ofbi->num_overlays; i++) {
18421 +               if (ofbi->overlays[i]->manager) {
18422 +                       mgr = ofbi->overlays[i]->manager;
18423 +                       break;
18424 +               }
18425 +       }
18426 +
18427 +       if (!mgr) {
18428 +               r = -EINVAL;
18429 +               goto err;
18430 +       }
18431 +
18432 +       r = _omapfb_set_color_key(mgr, ck);
18433 +err:
18434 +       omapfb_unlock(fbdev);
18435 +
18436 +       return r;
18437 +}
18438 +
18439 +static int omapfb_get_color_key(struct fb_info *fbi,
18440 +               struct omapfb_color_key *ck)
18441 +{
18442 +       struct omapfb_info *ofbi = FB2OFB(fbi);
18443 +       struct omapfb2_device *fbdev = ofbi->fbdev;
18444 +       struct omap_overlay_manager *mgr = NULL;
18445 +       int r = 0;
18446 +       int i;
18447 +
18448 +       omapfb_lock(fbdev);
18449 +
18450 +       for (i = 0; i < ofbi->num_overlays; i++) {
18451 +               if (ofbi->overlays[i]->manager) {
18452 +                       mgr = ofbi->overlays[i]->manager;
18453 +                       break;
18454 +               }
18455 +       }
18456 +
18457 +       if (!mgr) {
18458 +               r = -EINVAL;
18459 +               goto err;
18460 +       }
18461 +
18462 +       *ck = omapfb_color_keys[mgr->id];
18463 +err:
18464 +       omapfb_unlock(fbdev);
18465 +
18466 +       return r;
18467 +}
18468 +
18469 +static int omapfb_memory_read(struct fb_info *fbi,
18470 +               struct omapfb_memory_read *mr)
18471 +{
18472 +       struct omap_dss_device *display = fb2display(fbi);
18473 +       void *buf;
18474 +       int r;
18475 +
18476 +       if (!display || !display->memory_read)
18477 +               return -ENOENT;
18478 +
18479 +       if (!access_ok(VERIFY_WRITE, mr->buffer, mr->buffer_size))
18480 +               return -EFAULT;
18481 +
18482 +       if (mr->w * mr->h * 3 > mr->buffer_size)
18483 +               return -EINVAL;
18484 +
18485 +       buf = vmalloc(mr->buffer_size);
18486 +       if (!buf) {
18487 +               DBG("vmalloc failed\n");
18488 +               return -ENOMEM;
18489 +       }
18490 +
18491 +       r = display->memory_read(display, buf, mr->buffer_size,
18492 +                       mr->x, mr->y, mr->w, mr->h);
18493 +
18494 +       if (r > 0) {
18495 +               if (copy_to_user(mr->buffer, buf, mr->buffer_size))
18496 +                       r = -EFAULT;
18497 +       }
18498 +
18499 +       vfree(buf);
18500 +
18501 +       return r;
18502 +}
18503 +
18504 +static int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev,
18505 +                            struct omapfb_ovl_colormode *mode)
18506 +{
18507 +       int ovl_idx = mode->overlay_idx;
18508 +       int mode_idx = mode->mode_idx;
18509 +       struct omap_overlay *ovl;
18510 +       enum omap_color_mode supported_modes;
18511 +       struct fb_var_screeninfo var;
18512 +       int i;
18513 +
18514 +       if (ovl_idx >= fbdev->num_overlays)
18515 +               return -ENODEV;
18516 +       ovl = fbdev->overlays[ovl_idx];
18517 +       supported_modes = ovl->supported_modes;
18518 +
18519 +       mode_idx = mode->mode_idx;
18520 +
18521 +       for (i = 0; i < sizeof(supported_modes) * 8; i++) {
18522 +               if (!(supported_modes & (1 << i)))
18523 +                       continue;
18524 +               /*
18525 +                * It's possible that the FB doesn't support a mode
18526 +                * that is supported by the overlay, so call the
18527 +                * following here.
18528 +                */
18529 +               if (dss_mode_to_fb_mode(1 << i, &var) < 0)
18530 +                       continue;
18531 +
18532 +               mode_idx--;
18533 +               if (mode_idx < 0)
18534 +                       break;
18535 +       }
18536 +
18537 +       if (i == sizeof(supported_modes) * 8)
18538 +               return -ENOENT;
18539 +
18540 +       mode->bits_per_pixel = var.bits_per_pixel;
18541 +       mode->nonstd = var.nonstd;
18542 +       mode->red = var.red;
18543 +       mode->green = var.green;
18544 +       mode->blue = var.blue;
18545 +       mode->transp = var.transp;
18546 +
18547 +       return 0;
18548 +}
18549 +
18550 +static int omapfb_wait_for_go(struct fb_info *fbi)
18551 +{
18552 +       struct omapfb_info *ofbi = FB2OFB(fbi);
18553 +       int r = 0;
18554 +       int i;
18555 +
18556 +       for (i = 0; i < ofbi->num_overlays; ++i) {
18557 +               struct omap_overlay *ovl = ofbi->overlays[i];
18558 +               r = ovl->wait_for_go(ovl);
18559 +               if (r)
18560 +                       break;
18561 +       }
18562 +
18563 +       return r;
18564 +}
18565 +
18566 +int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
18567 +{
18568 +       struct omapfb_info *ofbi = FB2OFB(fbi);
18569 +       struct omapfb2_device *fbdev = ofbi->fbdev;
18570 +       struct omap_dss_device *display = fb2display(fbi);
18571 +
18572 +       union {
18573 +               struct omapfb_update_window_old uwnd_o;
18574 +               struct omapfb_update_window     uwnd;
18575 +               struct omapfb_plane_info        plane_info;
18576 +               struct omapfb_caps              caps;
18577 +               struct omapfb_mem_info          mem_info;
18578 +               struct omapfb_color_key         color_key;
18579 +               struct omapfb_ovl_colormode     ovl_colormode;
18580 +               enum omapfb_update_mode         update_mode;
18581 +               int test_num;
18582 +               struct omapfb_memory_read       memory_read;
18583 +               struct omapfb_vram_info         vram_info;
18584 +       } p;
18585 +
18586 +       int r = 0;
18587 +
18588 +       switch (cmd) {
18589 +       case OMAPFB_SYNC_GFX:
18590 +               DBG("ioctl SYNC_GFX\n");
18591 +               if (!display || !display->sync) {
18592 +                       /* DSS1 never returns an error here, so we neither */
18593 +                       /*r = -EINVAL;*/
18594 +                       break;
18595 +               }
18596 +
18597 +               r = display->sync(display);
18598 +               break;
18599 +
18600 +       case OMAPFB_UPDATE_WINDOW_OLD:
18601 +               DBG("ioctl UPDATE_WINDOW_OLD\n");
18602 +               if (!display || !display->update) {
18603 +                       r = -EINVAL;
18604 +                       break;
18605 +               }
18606 +
18607 +               if (copy_from_user(&p.uwnd_o,
18608 +                                       (void __user *)arg,
18609 +                                       sizeof(p.uwnd_o))) {
18610 +                       r = -EFAULT;
18611 +                       break;
18612 +               }
18613 +
18614 +               r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y,
18615 +                               p.uwnd_o.width, p.uwnd_o.height);
18616 +               break;
18617 +
18618 +       case OMAPFB_UPDATE_WINDOW:
18619 +               DBG("ioctl UPDATE_WINDOW\n");
18620 +               if (!display || !display->update) {
18621 +                       r = -EINVAL;
18622 +                       break;
18623 +               }
18624 +
18625 +               if (copy_from_user(&p.uwnd, (void __user *)arg,
18626 +                                       sizeof(p.uwnd))) {
18627 +                       r = -EFAULT;
18628 +                       break;
18629 +               }
18630 +
18631 +               r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y,
18632 +                               p.uwnd.width, p.uwnd.height);
18633 +               break;
18634 +
18635 +       case OMAPFB_SETUP_PLANE:
18636 +               DBG("ioctl SETUP_PLANE\n");
18637 +               if (copy_from_user(&p.plane_info, (void __user *)arg,
18638 +                                       sizeof(p.plane_info)))
18639 +                       r = -EFAULT;
18640 +               else
18641 +                       r = omapfb_setup_plane(fbi, &p.plane_info);
18642 +               break;
18643 +
18644 +       case OMAPFB_QUERY_PLANE:
18645 +               DBG("ioctl QUERY_PLANE\n");
18646 +               r = omapfb_query_plane(fbi, &p.plane_info);
18647 +               if (r < 0)
18648 +                       break;
18649 +               if (copy_to_user((void __user *)arg, &p.plane_info,
18650 +                                       sizeof(p.plane_info)))
18651 +                       r = -EFAULT;
18652 +               break;
18653 +
18654 +       case OMAPFB_SETUP_MEM:
18655 +               DBG("ioctl SETUP_MEM\n");
18656 +               if (copy_from_user(&p.mem_info, (void __user *)arg,
18657 +                                       sizeof(p.mem_info)))
18658 +                       r = -EFAULT;
18659 +               else
18660 +                       r = omapfb_setup_mem(fbi, &p.mem_info);
18661 +               break;
18662 +
18663 +       case OMAPFB_QUERY_MEM:
18664 +               DBG("ioctl QUERY_MEM\n");
18665 +               r = omapfb_query_mem(fbi, &p.mem_info);
18666 +               if (r < 0)
18667 +                       break;
18668 +               if (copy_to_user((void __user *)arg, &p.mem_info,
18669 +                                       sizeof(p.mem_info)))
18670 +                       r = -EFAULT;
18671 +               break;
18672 +
18673 +       case OMAPFB_GET_CAPS:
18674 +               DBG("ioctl GET_CAPS\n");
18675 +               if (!display) {
18676 +                       r = -EINVAL;
18677 +                       break;
18678 +               }
18679 +
18680 +               memset(&p.caps, 0, sizeof(p.caps));
18681 +               p.caps.ctrl = display->caps;
18682 +
18683 +               if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
18684 +                       r = -EFAULT;
18685 +               break;
18686 +
18687 +       case OMAPFB_GET_OVERLAY_COLORMODE:
18688 +               DBG("ioctl GET_OVERLAY_COLORMODE\n");
18689 +               if (copy_from_user(&p.ovl_colormode, (void __user *)arg,
18690 +                                  sizeof(p.ovl_colormode))) {
18691 +                       r = -EFAULT;
18692 +                       break;
18693 +               }
18694 +               r = omapfb_get_ovl_colormode(fbdev, &p.ovl_colormode);
18695 +               if (r < 0)
18696 +                       break;
18697 +               if (copy_to_user((void __user *)arg, &p.ovl_colormode,
18698 +                                sizeof(p.ovl_colormode)))
18699 +                       r = -EFAULT;
18700 +               break;
18701 +
18702 +       case OMAPFB_SET_UPDATE_MODE:
18703 +               DBG("ioctl SET_UPDATE_MODE\n");
18704 +               if (get_user(p.update_mode, (int __user *)arg))
18705 +                       r = -EFAULT;
18706 +               else
18707 +                       r = omapfb_set_update_mode(fbi, p.update_mode);
18708 +               break;
18709 +
18710 +       case OMAPFB_GET_UPDATE_MODE:
18711 +               DBG("ioctl GET_UPDATE_MODE\n");
18712 +               r = omapfb_get_update_mode(fbi, &p.update_mode);
18713 +               if (r)
18714 +                       break;
18715 +               if (put_user(p.update_mode,
18716 +                                       (enum omapfb_update_mode __user *)arg))
18717 +                       r = -EFAULT;
18718 +               break;
18719 +
18720 +       case OMAPFB_SET_COLOR_KEY:
18721 +               DBG("ioctl SET_COLOR_KEY\n");
18722 +               if (copy_from_user(&p.color_key, (void __user *)arg,
18723 +                                  sizeof(p.color_key)))
18724 +                       r = -EFAULT;
18725 +               else
18726 +                       r = omapfb_set_color_key(fbi, &p.color_key);
18727 +               break;
18728 +
18729 +       case OMAPFB_GET_COLOR_KEY:
18730 +               DBG("ioctl GET_COLOR_KEY\n");
18731 +               r = omapfb_get_color_key(fbi, &p.color_key);
18732 +               if (r)
18733 +                       break;
18734 +               if (copy_to_user((void __user *)arg, &p.color_key,
18735 +                                sizeof(p.color_key)))
18736 +                       r = -EFAULT;
18737 +               break;
18738 +
18739 +       case OMAPFB_WAITFORVSYNC:
18740 +               DBG("ioctl WAITFORVSYNC\n");
18741 +               if (!display) {
18742 +                       r = -EINVAL;
18743 +                       break;
18744 +               }
18745 +
18746 +               r = display->wait_vsync(display);
18747 +               break;
18748 +
18749 +       case OMAPFB_WAITFORGO:
18750 +               DBG("ioctl WAITFORGO\n");
18751 +               if (!display) {
18752 +                       r = -EINVAL;
18753 +                       break;
18754 +               }
18755 +
18756 +               r = omapfb_wait_for_go(fbi);
18757 +               break;
18758 +
18759 +       /* LCD and CTRL tests do the same thing for backward
18760 +        * compatibility */
18761 +       case OMAPFB_LCD_TEST:
18762 +               DBG("ioctl LCD_TEST\n");
18763 +               if (get_user(p.test_num, (int __user *)arg)) {
18764 +                       r = -EFAULT;
18765 +                       break;
18766 +               }
18767 +               if (!display || !display->run_test) {
18768 +                       r = -EINVAL;
18769 +                       break;
18770 +               }
18771 +
18772 +               r = display->run_test(display, p.test_num);
18773 +
18774 +               break;
18775 +
18776 +       case OMAPFB_CTRL_TEST:
18777 +               DBG("ioctl CTRL_TEST\n");
18778 +               if (get_user(p.test_num, (int __user *)arg)) {
18779 +                       r = -EFAULT;
18780 +                       break;
18781 +               }
18782 +               if (!display || !display->run_test) {
18783 +                       r = -EINVAL;
18784 +                       break;
18785 +               }
18786 +
18787 +               r = display->run_test(display, p.test_num);
18788 +
18789 +               break;
18790 +
18791 +       case OMAPFB_MEMORY_READ:
18792 +               DBG("ioctl MEMORY_READ\n");
18793 +
18794 +               if (copy_from_user(&p.memory_read, (void __user *)arg,
18795 +                                       sizeof(p.memory_read))) {
18796 +                       r = -EFAULT;
18797 +                       break;
18798 +               }
18799 +
18800 +               r = omapfb_memory_read(fbi, &p.memory_read);
18801 +
18802 +               break;
18803 +
18804 +       case OMAPFB_GET_VRAM_INFO: {
18805 +               unsigned long vram, free, largest;
18806 +
18807 +               DBG("ioctl GET_VRAM_INFO\n");
18808 +
18809 +               omap_vram_get_info(&vram, &free, &largest);
18810 +               p.vram_info.total = vram;
18811 +               p.vram_info.free = free;
18812 +               p.vram_info.largest_free_block = largest;
18813 +
18814 +               if (copy_to_user((void __user *)arg, &p.vram_info,
18815 +                                       sizeof(p.vram_info)))
18816 +                       r = -EFAULT;
18817 +               break;
18818 +       }
18819 +
18820 +       default:
18821 +               dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd);
18822 +               r = -EINVAL;
18823 +       }
18824 +
18825 +       if (r < 0)
18826 +               DBG("ioctl failed: %d\n", r);
18827 +
18828 +       return r;
18829 +}
18830 +
18831 +
18832 diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
18833 new file mode 100644
18834 index 0000000..7f5ec3b
18835 --- /dev/null
18836 +++ b/drivers/video/omap2/omapfb/omapfb-main.c
18837 @@ -0,0 +1,2137 @@
18838 +/*
18839 + * linux/drivers/video/omap2/omapfb-main.c
18840 + *
18841 + * Copyright (C) 2008 Nokia Corporation
18842 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
18843 + *
18844 + * Some code and ideas taken from drivers/video/omap/ driver
18845 + * by Imre Deak.
18846 + *
18847 + * This program is free software; you can redistribute it and/or modify it
18848 + * under the terms of the GNU General Public License version 2 as published by
18849 + * the Free Software Foundation.
18850 + *
18851 + * This program is distributed in the hope that it will be useful, but WITHOUT
18852 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18853 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18854 + * more details.
18855 + *
18856 + * You should have received a copy of the GNU General Public License along with
18857 + * this program.  If not, see <http://www.gnu.org/licenses/>.
18858 + */
18859 +
18860 +#include <linux/module.h>
18861 +#include <linux/delay.h>
18862 +#include <linux/fb.h>
18863 +#include <linux/dma-mapping.h>
18864 +#include <linux/vmalloc.h>
18865 +#include <linux/device.h>
18866 +#include <linux/platform_device.h>
18867 +#include <linux/omapfb.h>
18868 +
18869 +#include <mach/display.h>
18870 +#include <mach/vram.h>
18871 +#include <mach/vrfb.h>
18872 +
18873 +#include "omapfb.h"
18874 +
18875 +#define MODULE_NAME     "omapfb"
18876 +
18877 +#define OMAPFB_PLANE_XRES_MIN          8
18878 +#define OMAPFB_PLANE_YRES_MIN          8
18879 +
18880 +static char *def_mode;
18881 +static char *def_vram;
18882 +static int def_vrfb;
18883 +static int def_rotate;
18884 +static int def_mirror;
18885 +
18886 +#ifdef DEBUG
18887 +unsigned int omapfb_debug;
18888 +module_param_named(debug, omapfb_debug, bool, 0644);
18889 +static unsigned int omapfb_test_pattern;
18890 +module_param_named(test, omapfb_test_pattern, bool, 0644);
18891 +#endif
18892 +
18893 +static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi);
18894 +
18895 +#ifdef DEBUG
18896 +static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color)
18897 +{
18898 +       struct fb_var_screeninfo *var = &fbi->var;
18899 +       struct fb_fix_screeninfo *fix = &fbi->fix;
18900 +       void __iomem *addr = fbi->screen_base;
18901 +       const unsigned bytespp = var->bits_per_pixel >> 3;
18902 +       const unsigned line_len = fix->line_length / bytespp;
18903 +
18904 +       int r = (color >> 16) & 0xff;
18905 +       int g = (color >> 8) & 0xff;
18906 +       int b = (color >> 0) & 0xff;
18907 +
18908 +       if (var->bits_per_pixel == 16) {
18909 +               u16 __iomem *p = (u16 __iomem *)addr;
18910 +               p += y * line_len + x;
18911 +
18912 +               r = r * 32 / 256;
18913 +               g = g * 64 / 256;
18914 +               b = b * 32 / 256;
18915 +
18916 +               __raw_writew((r << 11) | (g << 5) | (b << 0), p);
18917 +       } else if (var->bits_per_pixel == 24) {
18918 +               u8 __iomem *p = (u8 __iomem *)addr;
18919 +               p += (y * line_len + x) * 3;
18920 +
18921 +               __raw_writeb(b, p + 0);
18922 +               __raw_writeb(g, p + 1);
18923 +               __raw_writeb(r, p + 2);
18924 +       } else if (var->bits_per_pixel == 32) {
18925 +               u32 __iomem *p = (u32 __iomem *)addr;
18926 +               p += y * line_len + x;
18927 +               __raw_writel(color, p);
18928 +       }
18929 +}
18930 +
18931 +static void fill_fb(struct fb_info *fbi)
18932 +{
18933 +       struct fb_var_screeninfo *var = &fbi->var;
18934 +       const short w = var->xres_virtual;
18935 +       const short h = var->yres_virtual;
18936 +       void __iomem *addr = fbi->screen_base;
18937 +       int y, x;
18938 +
18939 +       if (!addr)
18940 +               return;
18941 +
18942 +       DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length);
18943 +
18944 +       for (y = 0; y < h; y++) {
18945 +               for (x = 0; x < w; x++) {
18946 +                       if (x < 20 && y < 20)
18947 +                               draw_pixel(fbi, x, y, 0xffffff);
18948 +                       else if (x < 20 && (y > 20 && y < h - 20))
18949 +                               draw_pixel(fbi, x, y, 0xff);
18950 +                       else if (y < 20 && (x > 20 && x < w - 20))
18951 +                               draw_pixel(fbi, x, y, 0xff00);
18952 +                       else if (x > w - 20 && (y > 20 && y < h - 20))
18953 +                               draw_pixel(fbi, x, y, 0xff0000);
18954 +                       else if (y > h - 20 && (x > 20 && x < w - 20))
18955 +                               draw_pixel(fbi, x, y, 0xffff00);
18956 +                       else if (x == 20 || x == w - 20 ||
18957 +                                       y == 20 || y == h - 20)
18958 +                               draw_pixel(fbi, x, y, 0xffffff);
18959 +                       else if (x == y || w - x == h - y)
18960 +                               draw_pixel(fbi, x, y, 0xff00ff);
18961 +                       else if (w - x == y || x == h - y)
18962 +                               draw_pixel(fbi, x, y, 0x00ffff);
18963 +                       else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) {
18964 +                               int t = x * 3 / w;
18965 +                               unsigned r = 0, g = 0, b = 0;
18966 +                               unsigned c;
18967 +                               if (var->bits_per_pixel == 16) {
18968 +                                       if (t == 0)
18969 +                                               b = (y % 32) * 256 / 32;
18970 +                                       else if (t == 1)
18971 +                                               g = (y % 64) * 256 / 64;
18972 +                                       else if (t == 2)
18973 +                                               r = (y % 32) * 256 / 32;
18974 +                               } else {
18975 +                                       if (t == 0)
18976 +                                               b = (y % 256);
18977 +                                       else if (t == 1)
18978 +                                               g = (y % 256);
18979 +                                       else if (t == 2)
18980 +                                               r = (y % 256);
18981 +                               }
18982 +                               c = (r << 16) | (g << 8) | (b << 0);
18983 +                               draw_pixel(fbi, x, y, c);
18984 +                       } else {
18985 +                               draw_pixel(fbi, x, y, 0);
18986 +                       }
18987 +               }
18988 +       }
18989 +}
18990 +#endif
18991 +
18992 +static unsigned omapfb_get_vrfb_offset(struct omapfb_info *ofbi, int rot)
18993 +{
18994 +       struct vrfb *vrfb = &ofbi->region.vrfb;
18995 +       unsigned offset;
18996 +
18997 +       switch (rot) {
18998 +       case FB_ROTATE_UR:
18999 +               offset = 0;
19000 +               break;
19001 +       case FB_ROTATE_CW:
19002 +               offset = vrfb->yoffset;
19003 +               break;
19004 +       case FB_ROTATE_UD:
19005 +               offset = vrfb->yoffset * OMAP_VRFB_LINE_LEN + vrfb->xoffset;
19006 +               break;
19007 +       case FB_ROTATE_CCW:
19008 +               offset = vrfb->xoffset * OMAP_VRFB_LINE_LEN;
19009 +               break;
19010 +       default:
19011 +               BUG();
19012 +       }
19013 +
19014 +       offset *= vrfb->bytespp;
19015 +
19016 +       return offset;
19017 +}
19018 +
19019 +static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi, int rot)
19020 +{
19021 +       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
19022 +               return ofbi->region.vrfb.paddr[rot]
19023 +                       + omapfb_get_vrfb_offset(ofbi, rot);
19024 +       } else {
19025 +               return ofbi->region.paddr;
19026 +       }
19027 +}
19028 +
19029 +static u32 omapfb_get_region_paddr(struct omapfb_info *ofbi)
19030 +{
19031 +       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
19032 +               return ofbi->region.vrfb.paddr[0];
19033 +       else
19034 +               return ofbi->region.paddr;
19035 +}
19036 +
19037 +static void __iomem *omapfb_get_region_vaddr(struct omapfb_info *ofbi)
19038 +{
19039 +       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
19040 +               return ofbi->region.vrfb.vaddr[0];
19041 +       else
19042 +               return ofbi->region.vaddr;
19043 +}
19044 +
19045 +static struct omapfb_colormode omapfb_colormodes[] = {
19046 +       {
19047 +               .dssmode = OMAP_DSS_COLOR_UYVY,
19048 +               .bits_per_pixel = 16,
19049 +               .nonstd = OMAPFB_COLOR_YUV422,
19050 +       }, {
19051 +               .dssmode = OMAP_DSS_COLOR_YUV2,
19052 +               .bits_per_pixel = 16,
19053 +               .nonstd = OMAPFB_COLOR_YUY422,
19054 +       }, {
19055 +               .dssmode = OMAP_DSS_COLOR_ARGB16,
19056 +               .bits_per_pixel = 16,
19057 +               .red    = { .length = 4, .offset = 8, .msb_right = 0 },
19058 +               .green  = { .length = 4, .offset = 4, .msb_right = 0 },
19059 +               .blue   = { .length = 4, .offset = 0, .msb_right = 0 },
19060 +               .transp = { .length = 4, .offset = 12, .msb_right = 0 },
19061 +       }, {
19062 +               .dssmode = OMAP_DSS_COLOR_RGB16,
19063 +               .bits_per_pixel = 16,
19064 +               .red    = { .length = 5, .offset = 11, .msb_right = 0 },
19065 +               .green  = { .length = 6, .offset = 5, .msb_right = 0 },
19066 +               .blue   = { .length = 5, .offset = 0, .msb_right = 0 },
19067 +               .transp = { .length = 0, .offset = 0, .msb_right = 0 },
19068 +       }, {
19069 +               .dssmode = OMAP_DSS_COLOR_RGB24P,
19070 +               .bits_per_pixel = 24,
19071 +               .red    = { .length = 8, .offset = 16, .msb_right = 0 },
19072 +               .green  = { .length = 8, .offset = 8, .msb_right = 0 },
19073 +               .blue   = { .length = 8, .offset = 0, .msb_right = 0 },
19074 +               .transp = { .length = 0, .offset = 0, .msb_right = 0 },
19075 +       }, {
19076 +               .dssmode = OMAP_DSS_COLOR_RGB24U,
19077 +               .bits_per_pixel = 32,
19078 +               .red    = { .length = 8, .offset = 16, .msb_right = 0 },
19079 +               .green  = { .length = 8, .offset = 8, .msb_right = 0 },
19080 +               .blue   = { .length = 8, .offset = 0, .msb_right = 0 },
19081 +               .transp = { .length = 0, .offset = 0, .msb_right = 0 },
19082 +       }, {
19083 +               .dssmode = OMAP_DSS_COLOR_ARGB32,
19084 +               .bits_per_pixel = 32,
19085 +               .red    = { .length = 8, .offset = 16, .msb_right = 0 },
19086 +               .green  = { .length = 8, .offset = 8, .msb_right = 0 },
19087 +               .blue   = { .length = 8, .offset = 0, .msb_right = 0 },
19088 +               .transp = { .length = 8, .offset = 24, .msb_right = 0 },
19089 +       }, {
19090 +               .dssmode = OMAP_DSS_COLOR_RGBA32,
19091 +               .bits_per_pixel = 32,
19092 +               .red    = { .length = 8, .offset = 24, .msb_right = 0 },
19093 +               .green  = { .length = 8, .offset = 16, .msb_right = 0 },
19094 +               .blue   = { .length = 8, .offset = 8, .msb_right = 0 },
19095 +               .transp = { .length = 8, .offset = 0, .msb_right = 0 },
19096 +       }, {
19097 +               .dssmode = OMAP_DSS_COLOR_RGBX32,
19098 +               .bits_per_pixel = 32,
19099 +               .red    = { .length = 8, .offset = 24, .msb_right = 0 },
19100 +               .green  = { .length = 8, .offset = 16, .msb_right = 0 },
19101 +               .blue   = { .length = 8, .offset = 8, .msb_right = 0 },
19102 +               .transp = { .length = 0, .offset = 0, .msb_right = 0 },
19103 +       },
19104 +};
19105 +
19106 +static bool cmp_var_to_colormode(struct fb_var_screeninfo *var,
19107 +               struct omapfb_colormode *color)
19108 +{
19109 +       bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2)
19110 +       {
19111 +               return f1->length == f2->length &&
19112 +                       f1->offset == f2->offset &&
19113 +                       f1->msb_right == f2->msb_right;
19114 +       }
19115 +
19116 +       if (var->bits_per_pixel == 0 ||
19117 +                       var->red.length == 0 ||
19118 +                       var->blue.length == 0 ||
19119 +                       var->green.length == 0)
19120 +               return 0;
19121 +
19122 +       return var->bits_per_pixel == color->bits_per_pixel &&
19123 +               cmp_component(&var->red, &color->red) &&
19124 +               cmp_component(&var->green, &color->green) &&
19125 +               cmp_component(&var->blue, &color->blue) &&
19126 +               cmp_component(&var->transp, &color->transp);
19127 +}
19128 +
19129 +static void assign_colormode_to_var(struct fb_var_screeninfo *var,
19130 +               struct omapfb_colormode *color)
19131 +{
19132 +       var->bits_per_pixel = color->bits_per_pixel;
19133 +       var->nonstd = color->nonstd;
19134 +       var->red = color->red;
19135 +       var->green = color->green;
19136 +       var->blue = color->blue;
19137 +       var->transp = color->transp;
19138 +}
19139 +
19140 +static enum omap_color_mode fb_mode_to_dss_mode(struct fb_var_screeninfo *var)
19141 +{
19142 +       enum omap_color_mode dssmode;
19143 +       int i;
19144 +
19145 +       /* first match with nonstd field */
19146 +       if (var->nonstd) {
19147 +               for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
19148 +                       struct omapfb_colormode *mode = &omapfb_colormodes[i];
19149 +                       if (var->nonstd == mode->nonstd) {
19150 +                               assign_colormode_to_var(var, mode);
19151 +                               return mode->dssmode;
19152 +                       }
19153 +               }
19154 +
19155 +               return -EINVAL;
19156 +       }
19157 +
19158 +       /* then try exact match of bpp and colors */
19159 +       for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
19160 +               struct omapfb_colormode *mode = &omapfb_colormodes[i];
19161 +               if (cmp_var_to_colormode(var, mode)) {
19162 +                       assign_colormode_to_var(var, mode);
19163 +                       return mode->dssmode;
19164 +               }
19165 +       }
19166 +
19167 +       /* match with bpp if user has not filled color fields
19168 +        * properly */
19169 +       switch (var->bits_per_pixel) {
19170 +       case 1:
19171 +               dssmode = OMAP_DSS_COLOR_CLUT1;
19172 +               break;
19173 +       case 2:
19174 +               dssmode = OMAP_DSS_COLOR_CLUT2;
19175 +               break;
19176 +       case 4:
19177 +               dssmode = OMAP_DSS_COLOR_CLUT4;
19178 +               break;
19179 +       case 8:
19180 +               dssmode = OMAP_DSS_COLOR_CLUT8;
19181 +               break;
19182 +       case 12:
19183 +               dssmode = OMAP_DSS_COLOR_RGB12U;
19184 +               break;
19185 +       case 16:
19186 +               dssmode = OMAP_DSS_COLOR_RGB16;
19187 +               break;
19188 +       case 24:
19189 +               dssmode = OMAP_DSS_COLOR_RGB24P;
19190 +               break;
19191 +       case 32:
19192 +               dssmode = OMAP_DSS_COLOR_RGB24U;
19193 +               break;
19194 +       default:
19195 +               return -EINVAL;
19196 +       }
19197 +
19198 +       for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
19199 +               struct omapfb_colormode *mode = &omapfb_colormodes[i];
19200 +               if (dssmode == mode->dssmode) {
19201 +                       assign_colormode_to_var(var, mode);
19202 +                       return mode->dssmode;
19203 +               }
19204 +       }
19205 +
19206 +       return -EINVAL;
19207 +}
19208 +
19209 +int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
19210 +                       struct fb_var_screeninfo *var)
19211 +{
19212 +       int i;
19213 +
19214 +       for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
19215 +               struct omapfb_colormode *mode = &omapfb_colormodes[i];
19216 +               if (dssmode == mode->dssmode) {
19217 +                       assign_colormode_to_var(var, mode);
19218 +                       return 0;
19219 +               }
19220 +       }
19221 +       return -ENOENT;
19222 +}
19223 +
19224 +void set_fb_fix(struct fb_info *fbi)
19225 +{
19226 +       struct fb_fix_screeninfo *fix = &fbi->fix;
19227 +       struct fb_var_screeninfo *var = &fbi->var;
19228 +       struct omapfb_info *ofbi = FB2OFB(fbi);
19229 +       struct omapfb2_mem_region *rg = &ofbi->region;
19230 +
19231 +       DBG("set_fb_fix\n");
19232 +
19233 +       /* used by open/write in fbmem.c */
19234 +       fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
19235 +
19236 +       DBG("changing rotation to %d\n", var->rotate);
19237 +
19238 +       /* used by mmap in fbmem.c */
19239 +       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
19240 +               switch (var->nonstd) {
19241 +               case OMAPFB_COLOR_YUV422:
19242 +               case OMAPFB_COLOR_YUY422:
19243 +                       fix->line_length =
19244 +                               (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
19245 +                       break;
19246 +               default:
19247 +                       fix->line_length =
19248 +                               (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
19249 +                       break;
19250 +               }
19251 +       } else
19252 +               fix->line_length =
19253 +                       (var->xres_virtual * var->bits_per_pixel) >> 3;
19254 +       fix->smem_start = omapfb_get_region_paddr(ofbi);
19255 +       fix->smem_len = rg->size;
19256 +
19257 +       fix->type = FB_TYPE_PACKED_PIXELS;
19258 +
19259 +       if (var->nonstd)
19260 +               fix->visual = FB_VISUAL_PSEUDOCOLOR;
19261 +       else {
19262 +               switch (var->bits_per_pixel) {
19263 +               case 32:
19264 +               case 24:
19265 +               case 16:
19266 +               case 12:
19267 +                       fix->visual = FB_VISUAL_TRUECOLOR;
19268 +                       /* 12bpp is stored in 16 bits */
19269 +                       break;
19270 +               case 1:
19271 +               case 2:
19272 +               case 4:
19273 +               case 8:
19274 +                       fix->visual = FB_VISUAL_PSEUDOCOLOR;
19275 +                       break;
19276 +               }
19277 +       }
19278 +
19279 +       fix->accel = FB_ACCEL_NONE;
19280 +
19281 +       fix->xpanstep = 1;
19282 +       fix->ypanstep = 1;
19283 +
19284 +       if (rg->size && ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
19285 +               unsigned bytespp;
19286 +               bool yuv_mode;
19287 +               enum omap_color_mode mode;
19288 +
19289 +               mode = fb_mode_to_dss_mode(var);
19290 +
19291 +               bytespp = var->bits_per_pixel >> 3;
19292 +
19293 +               if (mode == OMAP_DSS_COLOR_YUV2 || mode == OMAP_DSS_COLOR_UYVY)
19294 +                       yuv_mode = true;
19295 +               else
19296 +                       yuv_mode = false;
19297 +
19298 +               omap_vrfb_setup(&rg->vrfb, rg->paddr,
19299 +                               var->xres_virtual,
19300 +                               var->yres_virtual,
19301 +                               bytespp, yuv_mode);
19302 +       }
19303 +}
19304 +
19305 +/* check new var and possibly modify it to be ok */
19306 +int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
19307 +{
19308 +       struct omapfb_info *ofbi = FB2OFB(fbi);
19309 +       struct omap_dss_device *display = fb2display(fbi);
19310 +       unsigned long max_frame_size;
19311 +       unsigned long line_size;
19312 +       int xres_min, yres_min;
19313 +       int xres_max, yres_max;
19314 +       enum omap_color_mode mode = 0;
19315 +       int i;
19316 +       int bytespp;
19317 +
19318 +       DBG("check_fb_var %d\n", ofbi->id);
19319 +
19320 +       if (ofbi->region.size == 0)
19321 +               return 0;
19322 +
19323 +       mode = fb_mode_to_dss_mode(var);
19324 +       if (mode < 0) {
19325 +               DBG("cannot convert var to omap dss mode\n");
19326 +               return -EINVAL;
19327 +       }
19328 +
19329 +       for (i = 0; i < ofbi->num_overlays; ++i) {
19330 +               if ((ofbi->overlays[i]->supported_modes & mode) == 0) {
19331 +                       DBG("invalid mode\n");
19332 +                       return -EINVAL;
19333 +               }
19334 +       }
19335 +
19336 +       if (var->rotate < 0 || var->rotate > 3)
19337 +               return -EINVAL;
19338 +
19339 +       xres_min = OMAPFB_PLANE_XRES_MIN;
19340 +       xres_max = 2048;
19341 +       yres_min = OMAPFB_PLANE_YRES_MIN;
19342 +       yres_max = 2048;
19343 +
19344 +       bytespp = var->bits_per_pixel >> 3;
19345 +
19346 +       /* XXX: some applications seem to set virtual res to 0. */
19347 +       if (var->xres_virtual == 0)
19348 +               var->xres_virtual = var->xres;
19349 +
19350 +       if (var->yres_virtual == 0)
19351 +               var->yres_virtual = var->yres;
19352 +
19353 +       if (var->xres_virtual < xres_min || var->yres_virtual < yres_min)
19354 +               return -EINVAL;
19355 +
19356 +       if (var->xres < xres_min)
19357 +               var->xres = xres_min;
19358 +       if (var->yres < yres_min)
19359 +               var->yres = yres_min;
19360 +       if (var->xres > xres_max)
19361 +               var->xres = xres_max;
19362 +       if (var->yres > yres_max)
19363 +               var->yres = yres_max;
19364 +
19365 +       if (var->xres > var->xres_virtual)
19366 +               var->xres = var->xres_virtual;
19367 +       if (var->yres > var->yres_virtual)
19368 +               var->yres = var->yres_virtual;
19369 +
19370 +       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
19371 +               line_size = OMAP_VRFB_LINE_LEN * bytespp;
19372 +       else
19373 +               line_size = var->xres_virtual * bytespp;
19374 +
19375 +       max_frame_size = ofbi->region.size;
19376 +
19377 +       DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size);
19378 +
19379 +       if (line_size * var->yres_virtual > max_frame_size) {
19380 +               DBG("can't fit FB into memory, reducing y\n");
19381 +               var->yres_virtual = max_frame_size / line_size;
19382 +
19383 +               if (var->yres_virtual < yres_min)
19384 +                       var->yres_virtual = yres_min;
19385 +
19386 +               if (var->yres > var->yres_virtual)
19387 +                       var->yres = var->yres_virtual;
19388 +       }
19389 +
19390 +       if (line_size * var->yres_virtual > max_frame_size) {
19391 +               DBG("can't fit FB into memory, reducing x\n");
19392 +               if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
19393 +                       return -EINVAL;
19394 +
19395 +               var->xres_virtual = max_frame_size / var->yres_virtual /
19396 +                       bytespp;
19397 +
19398 +               if (var->xres_virtual < xres_min)
19399 +                       var->xres_virtual = xres_min;
19400 +
19401 +               if (var->xres > var->xres_virtual)
19402 +                       var->xres = var->xres_virtual;
19403 +
19404 +               line_size = var->xres_virtual * bytespp;
19405 +       }
19406 +
19407 +       if (line_size * var->yres_virtual > max_frame_size) {
19408 +               DBG("cannot fit FB to memory\n");
19409 +               return -EINVAL;
19410 +       }
19411 +
19412 +       if (var->xres + var->xoffset > var->xres_virtual)
19413 +               var->xoffset = var->xres_virtual - var->xres;
19414 +       if (var->yres + var->yoffset > var->yres_virtual)
19415 +               var->yoffset = var->yres_virtual - var->yres;
19416 +
19417 +       DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n",
19418 +                       var->xres, var->yres,
19419 +                       var->xres_virtual, var->yres_virtual);
19420 +
19421 +       var->height             = -1;
19422 +       var->width              = -1;
19423 +       var->grayscale          = 0;
19424 +
19425 +       if (display && display->get_timings) {
19426 +               struct omap_video_timings timings;
19427 +               display->get_timings(display, &timings);
19428 +
19429 +               /* pixclock in ps, the rest in pixclock */
19430 +               var->pixclock = timings.pixel_clock != 0 ?
19431 +                       KHZ2PICOS(timings.pixel_clock) :
19432 +                       0;
19433 +               var->left_margin = timings.hfp;
19434 +               var->right_margin = timings.hbp;
19435 +               var->upper_margin = timings.vfp;
19436 +               var->lower_margin = timings.vbp;
19437 +               var->hsync_len = timings.hsw;
19438 +               var->vsync_len = timings.vsw;
19439 +       } else {
19440 +               var->pixclock = 0;
19441 +               var->left_margin = 0;
19442 +               var->right_margin = 0;
19443 +               var->upper_margin = 0;
19444 +               var->lower_margin = 0;
19445 +               var->hsync_len = 0;
19446 +               var->vsync_len = 0;
19447 +       }
19448 +
19449 +       /* TODO: get these from panel->config */
19450 +       var->vmode              = FB_VMODE_NONINTERLACED;
19451 +       var->sync               = 0;
19452 +
19453 +       return 0;
19454 +}
19455 +
19456 +/*
19457 + * ---------------------------------------------------------------------------
19458 + * fbdev framework callbacks
19459 + * ---------------------------------------------------------------------------
19460 + */
19461 +static int omapfb_open(struct fb_info *fbi, int user)
19462 +{
19463 +       return 0;
19464 +}
19465 +
19466 +static int omapfb_release(struct fb_info *fbi, int user)
19467 +{
19468 +#if 0
19469 +       struct omapfb_info *ofbi = FB2OFB(fbi);
19470 +       struct omapfb2_device *fbdev = ofbi->fbdev;
19471 +       struct omap_dss_device *display = fb2display(fbi);
19472 +
19473 +       DBG("Closing fb with plane index %d\n", ofbi->id);
19474 +
19475 +       omapfb_lock(fbdev);
19476 +
19477 +       if (display && display->get_update_mode && display->update) {
19478 +               /* XXX this update should be removed, I think. But it's
19479 +                * good for debugging */
19480 +               if (display->get_update_mode(display) ==
19481 +                               OMAP_DSS_UPDATE_MANUAL) {
19482 +                       u16 w, h;
19483 +
19484 +                       if (display->sync)
19485 +                               display->sync(display);
19486 +
19487 +                       display->get_resolution(display, &w, &h);
19488 +                       display->update(display, 0, 0, w, h);
19489 +               }
19490 +       }
19491 +
19492 +       if (display && display->sync)
19493 +               display->sync(display);
19494 +
19495 +       omapfb_unlock(fbdev);
19496 +#endif
19497 +       return 0;
19498 +}
19499 +
19500 +/* setup overlay according to the fb */
19501 +static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
19502 +               u16 posx, u16 posy, u16 outw, u16 outh)
19503 +{
19504 +       int r = 0;
19505 +       struct omapfb_info *ofbi = FB2OFB(fbi);
19506 +       struct fb_var_screeninfo *var = &fbi->var;
19507 +       struct fb_fix_screeninfo *fix = &fbi->fix;
19508 +       enum omap_color_mode mode = 0;
19509 +       int offset;
19510 +       u32 data_start_p;
19511 +       void __iomem *data_start_v;
19512 +       struct omap_overlay_info info;
19513 +       int xres, yres;
19514 +       int screen_width;
19515 +       int mirror;
19516 +       int rotation = var->rotate;
19517 +       int i;
19518 +
19519 +       for (i = 0; i < ofbi->num_overlays; i++) {
19520 +               if (ovl != ofbi->overlays[i])
19521 +                       continue;
19522 +
19523 +               rotation = (rotation + ofbi->rotation[i]) % 4;
19524 +               break;
19525 +       }
19526 +
19527 +       DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
19528 +                       posx, posy, outw, outh);
19529 +
19530 +       if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW) {
19531 +               xres = var->yres;
19532 +               yres = var->xres;
19533 +       } else {
19534 +               xres = var->xres;
19535 +               yres = var->yres;
19536 +       }
19537 +
19538 +       offset = ((var->yoffset * var->xres_virtual +
19539 +                               var->xoffset) * var->bits_per_pixel) >> 3;
19540 +
19541 +       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
19542 +               data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
19543 +               data_start_v = NULL;
19544 +       } else {
19545 +               data_start_p = omapfb_get_region_paddr(ofbi);
19546 +               data_start_v = omapfb_get_region_vaddr(ofbi);
19547 +       }
19548 +
19549 +       data_start_p += offset;
19550 +       data_start_v += offset;
19551 +
19552 +       mode = fb_mode_to_dss_mode(var);
19553 +
19554 +       if (mode == -EINVAL) {
19555 +               DBG("fb_mode_to_dss_mode failed");
19556 +               r = -EINVAL;
19557 +               goto err;
19558 +       }
19559 +
19560 +       switch (var->nonstd) {
19561 +       case OMAPFB_COLOR_YUV422:
19562 +       case OMAPFB_COLOR_YUY422:
19563 +               if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
19564 +                       screen_width = fix->line_length
19565 +                               / (var->bits_per_pixel >> 2);
19566 +                       break;
19567 +               }
19568 +       default:
19569 +               screen_width = fix->line_length / (var->bits_per_pixel >> 3);
19570 +               break;
19571 +       }
19572 +
19573 +       ovl->get_overlay_info(ovl, &info);
19574 +
19575 +       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
19576 +               mirror = 0;
19577 +       else
19578 +               mirror = ofbi->mirror;
19579 +
19580 +       info.paddr = data_start_p;
19581 +       info.vaddr = data_start_v;
19582 +       info.screen_width = screen_width;
19583 +       info.width = xres;
19584 +       info.height = yres;
19585 +       info.color_mode = mode;
19586 +       info.rotation_type = ofbi->rotation_type;
19587 +       info.rotation = rotation;
19588 +       info.mirror = mirror;
19589 +
19590 +       info.pos_x = posx;
19591 +       info.pos_y = posy;
19592 +       info.out_width = outw;
19593 +       info.out_height = outh;
19594 +
19595 +       r = ovl->set_overlay_info(ovl, &info);
19596 +       if (r) {
19597 +               DBG("ovl->setup_overlay_info failed\n");
19598 +               goto err;
19599 +       }
19600 +
19601 +       return 0;
19602 +
19603 +err:
19604 +       DBG("setup_overlay failed\n");
19605 +       return r;
19606 +}
19607 +
19608 +/* apply var to the overlay */
19609 +int omapfb_apply_changes(struct fb_info *fbi, int init)
19610 +{
19611 +       int r = 0;
19612 +       struct omapfb_info *ofbi = FB2OFB(fbi);
19613 +       struct fb_var_screeninfo *var = &fbi->var;
19614 +       struct omap_overlay *ovl;
19615 +       u16 posx, posy;
19616 +       u16 outw, outh;
19617 +       int i;
19618 +
19619 +#ifdef DEBUG
19620 +       if (omapfb_test_pattern)
19621 +               fill_fb(fbi);
19622 +#endif
19623 +
19624 +       for (i = 0; i < ofbi->num_overlays; i++) {
19625 +               ovl = ofbi->overlays[i];
19626 +
19627 +               DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
19628 +
19629 +               if (ofbi->region.size == 0) {
19630 +                       /* the fb is not available. disable the overlay */
19631 +                       omapfb_overlay_enable(ovl, 0);
19632 +                       if (!init && ovl->manager)
19633 +                               ovl->manager->apply(ovl->manager);
19634 +                       continue;
19635 +               }
19636 +
19637 +               if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
19638 +                       int rotation = (var->rotate + ofbi->rotation[i]) % 4;
19639 +                       if (rotation == FB_ROTATE_CW ||
19640 +                                       rotation == FB_ROTATE_CCW) {
19641 +                               outw = var->yres;
19642 +                               outh = var->xres;
19643 +                       } else {
19644 +                               outw = var->xres;
19645 +                               outh = var->yres;
19646 +                       }
19647 +               } else {
19648 +                       outw = ovl->info.out_width;
19649 +                       outh = ovl->info.out_height;
19650 +               }
19651 +
19652 +               if (init) {
19653 +                       posx = 0;
19654 +                       posy = 0;
19655 +               } else {
19656 +                       posx = ovl->info.pos_x;
19657 +                       posy = ovl->info.pos_y;
19658 +               }
19659 +
19660 +               r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
19661 +               if (r)
19662 +                       goto err;
19663 +
19664 +               if (!init && ovl->manager)
19665 +                       ovl->manager->apply(ovl->manager);
19666 +       }
19667 +       return 0;
19668 +err:
19669 +       DBG("apply_changes failed\n");
19670 +       return r;
19671 +}
19672 +
19673 +/* checks var and eventually tweaks it to something supported,
19674 + * DO NOT MODIFY PAR */
19675 +static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
19676 +{
19677 +       int r;
19678 +
19679 +       DBG("check_var(%d)\n", FB2OFB(fbi)->id);
19680 +
19681 +       r = check_fb_var(fbi, var);
19682 +
19683 +       return r;
19684 +}
19685 +
19686 +/* set the video mode according to info->var */
19687 +static int omapfb_set_par(struct fb_info *fbi)
19688 +{
19689 +       int r;
19690 +
19691 +       DBG("set_par(%d)\n", FB2OFB(fbi)->id);
19692 +
19693 +       set_fb_fix(fbi);
19694 +       r = omapfb_apply_changes(fbi, 0);
19695 +
19696 +       return r;
19697 +}
19698 +
19699 +static int omapfb_pan_display(struct fb_var_screeninfo *var,
19700 +               struct fb_info *fbi)
19701 +{
19702 +       struct omapfb_info *ofbi = FB2OFB(fbi);
19703 +       int r = 0;
19704 +
19705 +       DBG("pan_display(%d)\n", ofbi->id);
19706 +
19707 +       if (var->xoffset != fbi->var.xoffset ||
19708 +           var->yoffset != fbi->var.yoffset) {
19709 +               struct fb_var_screeninfo new_var;
19710 +
19711 +               new_var = fbi->var;
19712 +               new_var.xoffset = var->xoffset;
19713 +               new_var.yoffset = var->yoffset;
19714 +
19715 +               r = check_fb_var(fbi, &new_var);
19716 +
19717 +               if (r == 0) {
19718 +                       fbi->var = new_var;
19719 +                       set_fb_fix(fbi);
19720 +                       r = omapfb_apply_changes(fbi, 0);
19721 +               }
19722 +       }
19723 +
19724 +       return r;
19725 +}
19726 +
19727 +static void mmap_user_open(struct vm_area_struct *vma)
19728 +{
19729 +       struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
19730 +
19731 +       atomic_inc(&ofbi->map_count);
19732 +}
19733 +
19734 +static void mmap_user_close(struct vm_area_struct *vma)
19735 +{
19736 +       struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
19737 +
19738 +       atomic_dec(&ofbi->map_count);
19739 +}
19740 +
19741 +static struct vm_operations_struct mmap_user_ops = {
19742 +       .open = mmap_user_open,
19743 +       .close = mmap_user_close,
19744 +};
19745 +
19746 +static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
19747 +{
19748 +       struct omapfb_info *ofbi = FB2OFB(fbi);
19749 +       struct fb_fix_screeninfo *fix = &fbi->fix;
19750 +       unsigned long off;
19751 +       unsigned long start;
19752 +       u32 len;
19753 +
19754 +       if (vma->vm_end - vma->vm_start == 0)
19755 +               return 0;
19756 +       if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
19757 +               return -EINVAL;
19758 +       off = vma->vm_pgoff << PAGE_SHIFT;
19759 +
19760 +       start = omapfb_get_region_paddr(ofbi);
19761 +       len = fix->smem_len;
19762 +       if (off >= len)
19763 +               return -EINVAL;
19764 +       if ((vma->vm_end - vma->vm_start + off) > len)
19765 +               return -EINVAL;
19766 +
19767 +       off += start;
19768 +
19769 +       DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off);
19770 +
19771 +       vma->vm_pgoff = off >> PAGE_SHIFT;
19772 +       vma->vm_flags |= VM_IO | VM_RESERVED;
19773 +       vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
19774 +       vma->vm_ops = &mmap_user_ops;
19775 +       vma->vm_private_data = ofbi;
19776 +       if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
19777 +                            vma->vm_end - vma->vm_start, vma->vm_page_prot))
19778 +               return -EAGAIN;
19779 +       /* vm_ops.open won't be called for mmap itself. */
19780 +       atomic_inc(&ofbi->map_count);
19781 +       return 0;
19782 +}
19783 +
19784 +/* Store a single color palette entry into a pseudo palette or the hardware
19785 + * palette if one is available. For now we support only 16bpp and thus store
19786 + * the entry only to the pseudo palette.
19787 + */
19788 +static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
19789 +               u_int blue, u_int transp, int update_hw_pal)
19790 +{
19791 +       /*struct omapfb_info *ofbi = FB2OFB(fbi);*/
19792 +       /*struct omapfb2_device *fbdev = ofbi->fbdev;*/
19793 +       struct fb_var_screeninfo *var = &fbi->var;
19794 +       int r = 0;
19795 +
19796 +       enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */
19797 +
19798 +       /*switch (plane->color_mode) {*/
19799 +       switch (mode) {
19800 +       case OMAPFB_COLOR_YUV422:
19801 +       case OMAPFB_COLOR_YUV420:
19802 +       case OMAPFB_COLOR_YUY422:
19803 +               r = -EINVAL;
19804 +               break;
19805 +       case OMAPFB_COLOR_CLUT_8BPP:
19806 +       case OMAPFB_COLOR_CLUT_4BPP:
19807 +       case OMAPFB_COLOR_CLUT_2BPP:
19808 +       case OMAPFB_COLOR_CLUT_1BPP:
19809 +               /*
19810 +                  if (fbdev->ctrl->setcolreg)
19811 +                  r = fbdev->ctrl->setcolreg(regno, red, green, blue,
19812 +                  transp, update_hw_pal);
19813 +                  */
19814 +               /* Fallthrough */
19815 +               r = -EINVAL;
19816 +               break;
19817 +       case OMAPFB_COLOR_RGB565:
19818 +       case OMAPFB_COLOR_RGB444:
19819 +       case OMAPFB_COLOR_RGB24P:
19820 +       case OMAPFB_COLOR_RGB24U:
19821 +               if (r != 0)
19822 +                       break;
19823 +
19824 +               if (regno < 0) {
19825 +                       r = -EINVAL;
19826 +                       break;
19827 +               }
19828 +
19829 +               if (regno < 16) {
19830 +                       u16 pal;
19831 +                       pal = ((red >> (16 - var->red.length)) <<
19832 +                                       var->red.offset) |
19833 +                               ((green >> (16 - var->green.length)) <<
19834 +                                var->green.offset) |
19835 +                               (blue >> (16 - var->blue.length));
19836 +                       ((u32 *)(fbi->pseudo_palette))[regno] = pal;
19837 +               }
19838 +               break;
19839 +       default:
19840 +               BUG();
19841 +       }
19842 +       return r;
19843 +}
19844 +
19845 +static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
19846 +               u_int transp, struct fb_info *info)
19847 +{
19848 +       DBG("setcolreg\n");
19849 +
19850 +       return _setcolreg(info, regno, red, green, blue, transp, 1);
19851 +}
19852 +
19853 +static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
19854 +{
19855 +       int count, index, r;
19856 +       u16 *red, *green, *blue, *transp;
19857 +       u16 trans = 0xffff;
19858 +
19859 +       DBG("setcmap\n");
19860 +
19861 +       red     = cmap->red;
19862 +       green   = cmap->green;
19863 +       blue    = cmap->blue;
19864 +       transp  = cmap->transp;
19865 +       index   = cmap->start;
19866 +
19867 +       for (count = 0; count < cmap->len; count++) {
19868 +               if (transp)
19869 +                       trans = *transp++;
19870 +               r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
19871 +                               count == cmap->len - 1);
19872 +               if (r != 0)
19873 +                       return r;
19874 +       }
19875 +
19876 +       return 0;
19877 +}
19878 +
19879 +static void omapfb_vrfb_suspend_all(struct omapfb2_device *fbdev)
19880 +{
19881 +       int i;
19882 +
19883 +       for (i = 0; i < fbdev->num_fbs; i++) {
19884 +               struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
19885 +
19886 +               if (ofbi->region.vrfb.vaddr[0])
19887 +                       omap_vrfb_suspend_ctx(&ofbi->region.vrfb);
19888 +       }
19889 +}
19890 +
19891 +static void omapfb_vrfb_resume_all(struct omapfb2_device *fbdev)
19892 +{
19893 +       int i;
19894 +
19895 +       for (i = 0; i < fbdev->num_fbs; i++) {
19896 +               struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
19897 +
19898 +               if (ofbi->region.vrfb.vaddr[0])
19899 +                       omap_vrfb_resume_ctx(&ofbi->region.vrfb);
19900 +       }
19901 +}
19902 +
19903 +static int omapfb_blank(int blank, struct fb_info *fbi)
19904 +{
19905 +       struct omapfb_info *ofbi = FB2OFB(fbi);
19906 +       struct omapfb2_device *fbdev = ofbi->fbdev;
19907 +       struct omap_dss_device *display = fb2display(fbi);
19908 +       int do_update = 0;
19909 +       int r = 0;
19910 +
19911 +       omapfb_lock(fbdev);
19912 +
19913 +       switch (blank) {
19914 +       case FB_BLANK_UNBLANK:
19915 +               if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
19916 +                       goto exit;
19917 +
19918 +               omapfb_vrfb_resume_all(fbdev);
19919 +
19920 +               if (display->resume)
19921 +                       r = display->resume(display);
19922 +
19923 +               if (r == 0 && display->get_update_mode &&
19924 +                               display->get_update_mode(display) ==
19925 +                               OMAP_DSS_UPDATE_MANUAL)
19926 +                       do_update = 1;
19927 +
19928 +               break;
19929 +
19930 +       case FB_BLANK_NORMAL:
19931 +               /* FB_BLANK_NORMAL could be implemented.
19932 +                * Needs DSS additions. */
19933 +       case FB_BLANK_VSYNC_SUSPEND:
19934 +       case FB_BLANK_HSYNC_SUSPEND:
19935 +       case FB_BLANK_POWERDOWN:
19936 +               if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
19937 +                       goto exit;
19938 +
19939 +               if (display->suspend)
19940 +                       r = display->suspend(display);
19941 +
19942 +               omapfb_vrfb_suspend_all(fbdev);
19943 +
19944 +               break;
19945 +
19946 +       default:
19947 +               r = -EINVAL;
19948 +       }
19949 +
19950 +exit:
19951 +       omapfb_unlock(fbdev);
19952 +
19953 +       if (r == 0 && do_update && display->update) {
19954 +               u16 w, h;
19955 +               display->get_resolution(display, &w, &h);
19956 +
19957 +               r = display->update(display, 0, 0, w, h);
19958 +       }
19959 +
19960 +       return r;
19961 +}
19962 +
19963 +#if 0
19964 +/* XXX fb_read and fb_write are needed for VRFB */
19965 +ssize_t omapfb_write(struct fb_info *info, const char __user *buf,
19966 +               size_t count, loff_t *ppos)
19967 +{
19968 +       DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos);
19969 +       /* XXX needed for VRFB */
19970 +       return count;
19971 +}
19972 +#endif
19973 +
19974 +static struct fb_ops omapfb_ops = {
19975 +       .owner          = THIS_MODULE,
19976 +       .fb_open        = omapfb_open,
19977 +       .fb_release     = omapfb_release,
19978 +       .fb_fillrect    = cfb_fillrect,
19979 +       .fb_copyarea    = cfb_copyarea,
19980 +       .fb_imageblit   = cfb_imageblit,
19981 +       .fb_blank       = omapfb_blank,
19982 +       .fb_ioctl       = omapfb_ioctl,
19983 +       .fb_check_var   = omapfb_check_var,
19984 +       .fb_set_par     = omapfb_set_par,
19985 +       .fb_pan_display = omapfb_pan_display,
19986 +       .fb_mmap        = omapfb_mmap,
19987 +       .fb_setcolreg   = omapfb_setcolreg,
19988 +       .fb_setcmap     = omapfb_setcmap,
19989 +       /*.fb_write     = omapfb_write,*/
19990 +};
19991 +
19992 +static void omapfb_free_fbmem(struct fb_info *fbi)
19993 +{
19994 +       struct omapfb_info *ofbi = FB2OFB(fbi);
19995 +       struct omapfb2_device *fbdev = ofbi->fbdev;
19996 +       struct omapfb2_mem_region *rg;
19997 +
19998 +       rg = &ofbi->region;
19999 +
20000 +       if (rg->paddr)
20001 +               if (omap_vram_free(rg->paddr, rg->size))
20002 +                       dev_err(fbdev->dev, "VRAM FREE failed\n");
20003 +
20004 +       if (rg->vaddr)
20005 +               iounmap(rg->vaddr);
20006 +
20007 +       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
20008 +               /* unmap the 0 angle rotation */
20009 +               if (rg->vrfb.vaddr[0]) {
20010 +                       iounmap(rg->vrfb.vaddr[0]);
20011 +                       omap_vrfb_release_ctx(&rg->vrfb);
20012 +               }
20013 +       }
20014 +
20015 +       rg->vaddr = NULL;
20016 +       rg->paddr = 0;
20017 +       rg->alloc = 0;
20018 +       rg->size = 0;
20019 +}
20020 +
20021 +static void clear_fb_info(struct fb_info *fbi)
20022 +{
20023 +       memset(&fbi->var, 0, sizeof(fbi->var));
20024 +       memset(&fbi->fix, 0, sizeof(fbi->fix));
20025 +       strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
20026 +}
20027 +
20028 +static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
20029 +{
20030 +       int i;
20031 +
20032 +       DBG("free all fbmem\n");
20033 +
20034 +       for (i = 0; i < fbdev->num_fbs; i++) {
20035 +               struct fb_info *fbi = fbdev->fbs[i];
20036 +               omapfb_free_fbmem(fbi);
20037 +               clear_fb_info(fbi);
20038 +       }
20039 +
20040 +       return 0;
20041 +}
20042 +
20043 +static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
20044 +               unsigned long paddr)
20045 +{
20046 +       struct omapfb_info *ofbi = FB2OFB(fbi);
20047 +       struct omapfb2_device *fbdev = ofbi->fbdev;
20048 +       struct omapfb2_mem_region *rg;
20049 +       void __iomem *vaddr;
20050 +       int r;
20051 +
20052 +       rg = &ofbi->region;
20053 +       memset(rg, 0, sizeof(*rg));
20054 +
20055 +       size = PAGE_ALIGN(size);
20056 +
20057 +       if (!paddr) {
20058 +               DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
20059 +               r = omap_vram_alloc(OMAP_VRAM_MEMTYPE_SDRAM, size, &paddr);
20060 +       } else {
20061 +               DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
20062 +                               ofbi->id);
20063 +               r = omap_vram_reserve(paddr, size);
20064 +       }
20065 +
20066 +       if (r) {
20067 +               dev_err(fbdev->dev, "failed to allocate framebuffer\n");
20068 +               return -ENOMEM;
20069 +       }
20070 +
20071 +       if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) {
20072 +               vaddr = ioremap_wc(paddr, size);
20073 +
20074 +               if (!vaddr) {
20075 +                       dev_err(fbdev->dev, "failed to ioremap framebuffer\n");
20076 +                       omap_vram_free(paddr, size);
20077 +                       return -ENOMEM;
20078 +               }
20079 +
20080 +               DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
20081 +       } else {
20082 +               void __iomem *va;
20083 +
20084 +               r = omap_vrfb_request_ctx(&rg->vrfb);
20085 +               if (r) {
20086 +                       dev_err(fbdev->dev, "vrfb create ctx failed\n");
20087 +                       return r;
20088 +               }
20089 +
20090 +               /* only ioremap the 0 angle view */
20091 +               va = ioremap_wc(rg->vrfb.paddr[0], size);
20092 +
20093 +               if (!va) {
20094 +                       printk(KERN_ERR "vrfb: ioremap failed\n");
20095 +                       omap_vrfb_release_ctx(&rg->vrfb);
20096 +                       return -ENOMEM;
20097 +               }
20098 +
20099 +               DBG("ioremapped vrfb area 0 to %p\n", va);
20100 +
20101 +               rg->vrfb.vaddr[0] = va;
20102 +
20103 +               vaddr = NULL;
20104 +       }
20105 +
20106 +       rg->paddr = paddr;
20107 +       rg->vaddr = vaddr;
20108 +       rg->size = size;
20109 +       rg->alloc = 1;
20110 +
20111 +       return 0;
20112 +}
20113 +
20114 +/* allocate fbmem using display resolution as reference */
20115 +static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
20116 +               unsigned long paddr)
20117 +{
20118 +       struct omapfb_info *ofbi = FB2OFB(fbi);
20119 +       struct omap_dss_device *display;
20120 +       int bytespp;
20121 +
20122 +       display =  fb2display(fbi);
20123 +
20124 +       if (!display)
20125 +               return 0;
20126 +
20127 +       switch (display->get_recommended_bpp(display)) {
20128 +       case 16:
20129 +               bytespp = 2;
20130 +               break;
20131 +       case 24:
20132 +               bytespp = 4;
20133 +               break;
20134 +       default:
20135 +               bytespp = 4;
20136 +               break;
20137 +       }
20138 +
20139 +       if (!size) {
20140 +               u16 w, h;
20141 +
20142 +               display->get_resolution(display, &w, &h);
20143 +
20144 +               if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
20145 +#ifdef DEBUG
20146 +                       int oldw = w, oldh = h;
20147 +#endif
20148 +
20149 +                       omap_vrfb_adjust_size(&w, &h, bytespp);
20150 +
20151 +                       /* Because we change the resolution of the 0 degree
20152 +                        * view, we need to alloc max(w, h) for height */
20153 +                       h = max(w, h);
20154 +                       w = OMAP_VRFB_LINE_LEN;
20155 +
20156 +                       DBG("adjusting fb mem size for VRFB, %dx%d -> %dx%d\n",
20157 +                                       oldw, oldh, w, h);
20158 +               }
20159 +
20160 +               size = w * h * bytespp;
20161 +       }
20162 +
20163 +       if (!size)
20164 +               return 0;
20165 +
20166 +       return omapfb_alloc_fbmem(fbi, size, paddr);
20167 +}
20168 +
20169 +static enum omap_color_mode fb_format_to_dss_mode(enum omapfb_color_format fmt)
20170 +{
20171 +       enum omap_color_mode mode;
20172 +
20173 +       switch (fmt) {
20174 +       case OMAPFB_COLOR_RGB565:
20175 +               mode = OMAP_DSS_COLOR_RGB16;
20176 +               break;
20177 +       case OMAPFB_COLOR_YUV422:
20178 +               mode = OMAP_DSS_COLOR_YUV2;
20179 +               break;
20180 +       case OMAPFB_COLOR_CLUT_8BPP:
20181 +               mode = OMAP_DSS_COLOR_CLUT8;
20182 +               break;
20183 +       case OMAPFB_COLOR_CLUT_4BPP:
20184 +               mode = OMAP_DSS_COLOR_CLUT4;
20185 +               break;
20186 +       case OMAPFB_COLOR_CLUT_2BPP:
20187 +               mode = OMAP_DSS_COLOR_CLUT2;
20188 +               break;
20189 +       case OMAPFB_COLOR_CLUT_1BPP:
20190 +               mode = OMAP_DSS_COLOR_CLUT1;
20191 +               break;
20192 +       case OMAPFB_COLOR_RGB444:
20193 +               mode = OMAP_DSS_COLOR_RGB12U;
20194 +               break;
20195 +       case OMAPFB_COLOR_YUY422:
20196 +               mode = OMAP_DSS_COLOR_UYVY;
20197 +               break;
20198 +       case OMAPFB_COLOR_ARGB16:
20199 +               mode = OMAP_DSS_COLOR_ARGB16;
20200 +               break;
20201 +       case OMAPFB_COLOR_RGB24U:
20202 +               mode = OMAP_DSS_COLOR_RGB24U;
20203 +               break;
20204 +       case OMAPFB_COLOR_RGB24P:
20205 +               mode = OMAP_DSS_COLOR_RGB24P;
20206 +               break;
20207 +       case OMAPFB_COLOR_ARGB32:
20208 +               mode = OMAP_DSS_COLOR_ARGB32;
20209 +               break;
20210 +       case OMAPFB_COLOR_RGBA32:
20211 +               mode = OMAP_DSS_COLOR_RGBA32;
20212 +               break;
20213 +       case OMAPFB_COLOR_RGBX32:
20214 +               mode = OMAP_DSS_COLOR_RGBX32;
20215 +               break;
20216 +       default:
20217 +               mode = -EINVAL;
20218 +       }
20219 +
20220 +       return mode;
20221 +}
20222 +
20223 +static int omapfb_parse_vram_param(const char *param, int max_entries,
20224 +               unsigned long *sizes, unsigned long *paddrs)
20225 +{
20226 +       int fbnum;
20227 +       unsigned long size;
20228 +       unsigned long paddr = 0;
20229 +       char *p, *start;
20230 +
20231 +       start = (char *)param;
20232 +
20233 +       while (1) {
20234 +               p = start;
20235 +
20236 +               fbnum = simple_strtoul(p, &p, 10);
20237 +
20238 +               if (p == param)
20239 +                       return -EINVAL;
20240 +
20241 +               if (*p != ':')
20242 +                       return -EINVAL;
20243 +
20244 +               if (fbnum >= max_entries)
20245 +                       return -EINVAL;
20246 +
20247 +               size = memparse(p + 1, &p);
20248 +
20249 +               if (!size)
20250 +                       return -EINVAL;
20251 +
20252 +               paddr = 0;
20253 +
20254 +               if (*p == '@') {
20255 +                       paddr = simple_strtoul(p + 1, &p, 16);
20256 +
20257 +                       if (!paddr)
20258 +                               return -EINVAL;
20259 +
20260 +               }
20261 +
20262 +               paddrs[fbnum] = paddr;
20263 +               sizes[fbnum] = size;
20264 +
20265 +               if (*p == 0)
20266 +                       break;
20267 +
20268 +               if (*p != ',')
20269 +                       return -EINVAL;
20270 +
20271 +               ++p;
20272 +
20273 +               start = p;
20274 +       }
20275 +
20276 +       return 0;
20277 +}
20278 +
20279 +static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
20280 +{
20281 +       int i, r;
20282 +       unsigned long vram_sizes[10];
20283 +       unsigned long vram_paddrs[10];
20284 +
20285 +       memset(&vram_sizes, 0, sizeof(vram_sizes));
20286 +       memset(&vram_paddrs, 0, sizeof(vram_paddrs));
20287 +
20288 +       if (def_vram && omapfb_parse_vram_param(def_vram, 10,
20289 +                               vram_sizes, vram_paddrs)) {
20290 +               dev_err(fbdev->dev, "failed to parse vram parameter\n");
20291 +
20292 +               memset(&vram_sizes, 0, sizeof(vram_sizes));
20293 +               memset(&vram_paddrs, 0, sizeof(vram_paddrs));
20294 +       }
20295 +
20296 +       if (fbdev->dev->platform_data) {
20297 +               struct omapfb_platform_data *opd;
20298 +               opd = fbdev->dev->platform_data;
20299 +               for (i = 0; i < opd->mem_desc.region_cnt; ++i) {
20300 +                       if (!vram_sizes[i]) {
20301 +                               unsigned long size;
20302 +                               unsigned long paddr;
20303 +
20304 +                               size = opd->mem_desc.region[i].size;
20305 +                               paddr = opd->mem_desc.region[i].paddr;
20306 +
20307 +                               vram_sizes[i] = size;
20308 +                               vram_paddrs[i] = paddr;
20309 +                       }
20310 +               }
20311 +       }
20312 +
20313 +       for (i = 0; i < fbdev->num_fbs; i++) {
20314 +               /* allocate memory automatically only for fb0, or if
20315 +                * excplicitly defined with vram or plat data option */
20316 +               if (i == 0 || vram_sizes[i] != 0) {
20317 +                       r = omapfb_alloc_fbmem_display(fbdev->fbs[i],
20318 +                                       vram_sizes[i], vram_paddrs[i]);
20319 +
20320 +                       if (r)
20321 +                               return r;
20322 +               }
20323 +       }
20324 +
20325 +       for (i = 0; i < fbdev->num_fbs; i++) {
20326 +               struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
20327 +               struct omapfb2_mem_region *rg;
20328 +               rg = &ofbi->region;
20329 +
20330 +               DBG("region%d phys %08x virt %p size=%lu\n",
20331 +                               i,
20332 +                               rg->paddr,
20333 +                               rg->vaddr,
20334 +                               rg->size);
20335 +       }
20336 +
20337 +       return 0;
20338 +}
20339 +
20340 +int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
20341 +{
20342 +       struct omapfb_info *ofbi = FB2OFB(fbi);
20343 +       struct omapfb2_device *fbdev = ofbi->fbdev;
20344 +       struct omap_dss_device *display = fb2display(fbi);
20345 +       struct omapfb2_mem_region *rg = &ofbi->region;
20346 +       unsigned long old_size = rg->size;
20347 +       unsigned long old_paddr = rg->paddr;
20348 +       int old_type = rg->type;
20349 +       int r;
20350 +
20351 +       if (type > OMAPFB_MEMTYPE_MAX)
20352 +               return -EINVAL;
20353 +
20354 +       size = PAGE_ALIGN(size);
20355 +
20356 +       if (old_size == size && old_type == type)
20357 +               return 0;
20358 +
20359 +       if (display && display->sync)
20360 +                       display->sync(display);
20361 +
20362 +       omapfb_free_fbmem(fbi);
20363 +
20364 +       if (size == 0) {
20365 +               clear_fb_info(fbi);
20366 +               return 0;
20367 +       }
20368 +
20369 +       r = omapfb_alloc_fbmem(fbi, size, 0);
20370 +
20371 +       if (r) {
20372 +               if (old_size)
20373 +                       omapfb_alloc_fbmem(fbi, old_size, old_paddr);
20374 +
20375 +               if (rg->size == 0)
20376 +                       clear_fb_info(fbi);
20377 +
20378 +               return r;
20379 +       }
20380 +
20381 +       if (old_size == size)
20382 +               return 0;
20383 +
20384 +       if (old_size == 0) {
20385 +               DBG("initializing fb %d\n", ofbi->id);
20386 +               r = omapfb_fb_init(fbdev, fbi);
20387 +               if (r) {
20388 +                       DBG("omapfb_fb_init failed\n");
20389 +                       goto err;
20390 +               }
20391 +               r = omapfb_apply_changes(fbi, 1);
20392 +               if (r) {
20393 +                       DBG("omapfb_apply_changes failed\n");
20394 +                       goto err;
20395 +               }
20396 +       } else {
20397 +               struct fb_var_screeninfo new_var;
20398 +               memcpy(&new_var, &fbi->var, sizeof(new_var));
20399 +               r = check_fb_var(fbi, &new_var);
20400 +               if (r)
20401 +                       goto err;
20402 +               memcpy(&fbi->var, &new_var, sizeof(fbi->var));
20403 +               set_fb_fix(fbi);
20404 +       }
20405 +
20406 +       return 0;
20407 +err:
20408 +       omapfb_free_fbmem(fbi);
20409 +       clear_fb_info(fbi);
20410 +       return r;
20411 +}
20412 +
20413 +/* initialize fb_info, var, fix to something sane based on the display */
20414 +static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
20415 +{
20416 +       struct fb_var_screeninfo *var = &fbi->var;
20417 +       struct omap_dss_device *display = fb2display(fbi);
20418 +       struct omapfb_info *ofbi = FB2OFB(fbi);
20419 +       int r = 0;
20420 +
20421 +       fbi->fbops = &omapfb_ops;
20422 +       fbi->flags = FBINFO_FLAG_DEFAULT;
20423 +       fbi->pseudo_palette = fbdev->pseudo_palette;
20424 +
20425 +       if (ofbi->region.size == 0) {
20426 +               clear_fb_info(fbi);
20427 +               return 0;
20428 +       }
20429 +
20430 +       var->nonstd = 0;
20431 +       var->bits_per_pixel = 0;
20432 +
20433 +       var->rotate = def_rotate;
20434 +
20435 +       /*
20436 +        * Check if there is a default color format set in the board file,
20437 +        * and use this format instead the default deducted from the
20438 +        * display bpp.
20439 +        */
20440 +       if (fbdev->dev->platform_data) {
20441 +               struct omapfb_platform_data *opd;
20442 +               int id = ofbi->id;
20443 +
20444 +               opd = fbdev->dev->platform_data;
20445 +               if (opd->mem_desc.region[id].format_used) {
20446 +                       enum omap_color_mode mode;
20447 +                       enum omapfb_color_format format;
20448 +
20449 +                       format = opd->mem_desc.region[id].format;
20450 +                       mode = fb_format_to_dss_mode(format);
20451 +                       if (mode < 0) {
20452 +                               r = mode;
20453 +                               goto err;
20454 +                       }
20455 +                       r = dss_mode_to_fb_mode(mode, var);
20456 +                       if (r < 0)
20457 +                               goto err;
20458 +               }
20459 +       }
20460 +
20461 +       if (display) {
20462 +               u16 w, h;
20463 +               int rotation = (var->rotate + ofbi->rotation[0]) % 4;
20464 +
20465 +               display->get_resolution(display, &w, &h);
20466 +
20467 +               if (rotation == FB_ROTATE_CW ||
20468 +                               rotation == FB_ROTATE_CCW) {
20469 +                       var->xres = h;
20470 +                       var->yres = w;
20471 +               } else {
20472 +                       var->xres = w;
20473 +                       var->yres = h;
20474 +               }
20475 +
20476 +               var->xres_virtual = var->xres;
20477 +               var->yres_virtual = var->yres;
20478 +
20479 +               if (!var->bits_per_pixel) {
20480 +                       switch (display->get_recommended_bpp(display)) {
20481 +                       case 16:
20482 +                               var->bits_per_pixel = 16;
20483 +                               break;
20484 +                       case 24:
20485 +                               var->bits_per_pixel = 32;
20486 +                               break;
20487 +                       default:
20488 +                               dev_err(fbdev->dev, "illegal display "
20489 +                                               "bpp\n");
20490 +                               return -EINVAL;
20491 +                       }
20492 +               }
20493 +       } else {
20494 +               /* if there's no display, let's just guess some basic values */
20495 +               var->xres = 320;
20496 +               var->yres = 240;
20497 +               var->xres_virtual = var->xres;
20498 +               var->yres_virtual = var->yres;
20499 +               if (!var->bits_per_pixel)
20500 +                       var->bits_per_pixel = 16;
20501 +       }
20502 +
20503 +       r = check_fb_var(fbi, var);
20504 +       if (r)
20505 +               goto err;
20506 +
20507 +       set_fb_fix(fbi);
20508 +
20509 +       r = fb_alloc_cmap(&fbi->cmap, 256, 0);
20510 +       if (r)
20511 +               dev_err(fbdev->dev, "unable to allocate color map memory\n");
20512 +
20513 +err:
20514 +       return r;
20515 +}
20516 +
20517 +static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi)
20518 +{
20519 +       fb_dealloc_cmap(&fbi->cmap);
20520 +}
20521 +
20522 +
20523 +static void omapfb_free_resources(struct omapfb2_device *fbdev)
20524 +{
20525 +       int i;
20526 +
20527 +       DBG("free_resources\n");
20528 +
20529 +       if (fbdev == NULL)
20530 +               return;
20531 +
20532 +       for (i = 0; i < fbdev->num_fbs; i++)
20533 +               unregister_framebuffer(fbdev->fbs[i]);
20534 +
20535 +       /* free the reserved fbmem */
20536 +       omapfb_free_all_fbmem(fbdev);
20537 +
20538 +       for (i = 0; i < fbdev->num_fbs; i++) {
20539 +               fbinfo_cleanup(fbdev, fbdev->fbs[i]);
20540 +               framebuffer_release(fbdev->fbs[i]);
20541 +       }
20542 +
20543 +       for (i = 0; i < fbdev->num_displays; i++) {
20544 +               if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED)
20545 +                       fbdev->displays[i]->disable(fbdev->displays[i]);
20546 +
20547 +               omap_dss_put_device(fbdev->displays[i]);
20548 +       }
20549 +
20550 +       dev_set_drvdata(fbdev->dev, NULL);
20551 +       kfree(fbdev);
20552 +}
20553 +
20554 +static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
20555 +{
20556 +       int r, i;
20557 +
20558 +       fbdev->num_fbs = 0;
20559 +
20560 +       DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS);
20561 +
20562 +       /* allocate fb_infos */
20563 +       for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
20564 +               struct fb_info *fbi;
20565 +               struct omapfb_info *ofbi;
20566 +
20567 +               fbi = framebuffer_alloc(sizeof(struct omapfb_info),
20568 +                               fbdev->dev);
20569 +
20570 +               if (fbi == NULL) {
20571 +                       dev_err(fbdev->dev,
20572 +                               "unable to allocate memory for plane info\n");
20573 +                       return -ENOMEM;
20574 +               }
20575 +
20576 +               clear_fb_info(fbi);
20577 +
20578 +               fbdev->fbs[i] = fbi;
20579 +
20580 +               ofbi = FB2OFB(fbi);
20581 +               ofbi->fbdev = fbdev;
20582 +               ofbi->id = i;
20583 +
20584 +               /* assign these early, so that fb alloc can use them */
20585 +               ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
20586 +                       OMAP_DSS_ROT_DMA;
20587 +               ofbi->mirror = def_mirror;
20588 +
20589 +               fbdev->num_fbs++;
20590 +       }
20591 +
20592 +       DBG("fb_infos allocated\n");
20593 +
20594 +       /* assign overlays for the fbs */
20595 +       for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
20596 +               struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
20597 +
20598 +               ofbi->overlays[0] = fbdev->overlays[i];
20599 +               ofbi->num_overlays = 1;
20600 +       }
20601 +
20602 +       /* allocate fb memories */
20603 +       r = omapfb_allocate_all_fbs(fbdev);
20604 +       if (r) {
20605 +               dev_err(fbdev->dev, "failed to allocate fbmem\n");
20606 +               return r;
20607 +       }
20608 +
20609 +       DBG("fbmems allocated\n");
20610 +
20611 +       /* setup fb_infos */
20612 +       for (i = 0; i < fbdev->num_fbs; i++) {
20613 +               r = omapfb_fb_init(fbdev, fbdev->fbs[i]);
20614 +               if (r) {
20615 +                       dev_err(fbdev->dev, "failed to setup fb_info\n");
20616 +                       return r;
20617 +               }
20618 +       }
20619 +
20620 +       DBG("fb_infos initialized\n");
20621 +
20622 +       for (i = 0; i < fbdev->num_fbs; i++) {
20623 +               r = register_framebuffer(fbdev->fbs[i]);
20624 +               if (r != 0) {
20625 +                       dev_err(fbdev->dev,
20626 +                               "registering framebuffer %d failed\n", i);
20627 +                       return r;
20628 +               }
20629 +       }
20630 +
20631 +       DBG("framebuffers registered\n");
20632 +
20633 +       for (i = 0; i < fbdev->num_fbs; i++) {
20634 +               r = omapfb_apply_changes(fbdev->fbs[i], 1);
20635 +               if (r) {
20636 +                       dev_err(fbdev->dev, "failed to change mode\n");
20637 +                       return r;
20638 +               }
20639 +       }
20640 +
20641 +       DBG("create sysfs for fbs\n");
20642 +       r = omapfb_create_sysfs(fbdev);
20643 +       if (r) {
20644 +               dev_err(fbdev->dev, "failed to create sysfs entries\n");
20645 +               return r;
20646 +       }
20647 +
20648 +       /* Enable fb0 */
20649 +       if (fbdev->num_fbs > 0) {
20650 +               struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
20651 +
20652 +               if (ofbi->num_overlays > 0) {
20653 +                       struct omap_overlay *ovl = ofbi->overlays[0];
20654 +
20655 +                       r = omapfb_overlay_enable(ovl, 1);
20656 +
20657 +                       if (r) {
20658 +                               dev_err(fbdev->dev,
20659 +                                               "failed to enable overlay\n");
20660 +                               return r;
20661 +                       }
20662 +               }
20663 +       }
20664 +
20665 +       DBG("create_framebuffers done\n");
20666 +
20667 +       return 0;
20668 +}
20669 +
20670 +static int omapfb_mode_to_timings(const char *mode_str,
20671 +               struct omap_video_timings *timings, u8 *bpp)
20672 +{
20673 +       struct fb_info fbi;
20674 +       struct fb_var_screeninfo var;
20675 +       struct fb_ops fbops;
20676 +       int r;
20677 +
20678 +#ifdef CONFIG_OMAP2_DSS_VENC
20679 +       if (strcmp(mode_str, "pal") == 0) {
20680 +               *timings = omap_dss_pal_timings;
20681 +               *bpp = 0;
20682 +               return 0;
20683 +       } else if (strcmp(mode_str, "ntsc") == 0) {
20684 +               *timings = omap_dss_ntsc_timings;
20685 +               *bpp = 0;
20686 +               return 0;
20687 +       }
20688 +#endif
20689 +
20690 +       /* this is quite a hack, but I wanted to use the modedb and for
20691 +        * that we need fb_info and var, so we create dummy ones */
20692 +
20693 +       memset(&fbi, 0, sizeof(fbi));
20694 +       memset(&var, 0, sizeof(var));
20695 +       memset(&fbops, 0, sizeof(fbops));
20696 +       fbi.fbops = &fbops;
20697 +
20698 +       r = fb_find_mode(&var, &fbi, mode_str, NULL, 0, NULL, 24);
20699 +
20700 +       if (r != 0) {
20701 +               timings->pixel_clock = PICOS2KHZ(var.pixclock);
20702 +               timings->hfp = var.left_margin;
20703 +               timings->hbp = var.right_margin;
20704 +               timings->vfp = var.upper_margin;
20705 +               timings->vbp = var.lower_margin;
20706 +               timings->hsw = var.hsync_len;
20707 +               timings->vsw = var.vsync_len;
20708 +               timings->x_res = var.xres;
20709 +               timings->y_res = var.yres;
20710 +
20711 +               switch (var.bits_per_pixel) {
20712 +               case 16:
20713 +                       *bpp = 16;
20714 +                       break;
20715 +               case 24:
20716 +               case 32:
20717 +               default:
20718 +                       *bpp = 24;
20719 +                       break;
20720 +               }
20721 +
20722 +               return 0;
20723 +       } else {
20724 +               return -EINVAL;
20725 +       }
20726 +}
20727 +
20728 +static int omapfb_set_def_mode(struct omap_dss_device *display, char *mode_str)
20729 +{
20730 +       int r;
20731 +       u8 bpp;
20732 +       struct omap_video_timings timings;
20733 +
20734 +       r = omapfb_mode_to_timings(mode_str, &timings, &bpp);
20735 +       if (r)
20736 +               return r;
20737 +
20738 +       display->panel.recommended_bpp = bpp;
20739 +
20740 +       if (!display->check_timings || !display->set_timings)
20741 +               return -EINVAL;
20742 +
20743 +       r = display->check_timings(display, &timings);
20744 +       if (r)
20745 +               return r;
20746 +
20747 +       display->set_timings(display, &timings);
20748 +
20749 +       return 0;
20750 +}
20751 +
20752 +static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
20753 +{
20754 +       char *str, *options, *this_opt;
20755 +       int r = 0;
20756 +
20757 +       str = kmalloc(strlen(def_mode) + 1, GFP_KERNEL);
20758 +       strcpy(str, def_mode);
20759 +       options = str;
20760 +
20761 +       while (!r && (this_opt = strsep(&options, ",")) != NULL) {
20762 +               char *p, *display_str, *mode_str;
20763 +               struct omap_dss_device *display;
20764 +               int i;
20765 +
20766 +               p = strchr(this_opt, ':');
20767 +               if (!p) {
20768 +                       r = -EINVAL;
20769 +                       break;
20770 +               }
20771 +
20772 +               *p = 0;
20773 +               display_str = this_opt;
20774 +               mode_str = p + 1;
20775 +
20776 +               display = NULL;
20777 +               for (i = 0; i < fbdev->num_displays; ++i) {
20778 +                       if (strcmp(fbdev->displays[i]->name,
20779 +                                               display_str) == 0) {
20780 +                               display = fbdev->displays[i];
20781 +                               break;
20782 +                       }
20783 +               }
20784 +
20785 +               if (!display) {
20786 +                       r = -EINVAL;
20787 +                       break;
20788 +               }
20789 +
20790 +               r = omapfb_set_def_mode(display, mode_str);
20791 +               if (r)
20792 +                       break;
20793 +       }
20794 +
20795 +       kfree(str);
20796 +
20797 +       return r;
20798 +}
20799 +
20800 +static int omapfb_probe(struct platform_device *pdev)
20801 +{
20802 +       struct omapfb2_device *fbdev = NULL;
20803 +       int r = 0;
20804 +       int i;
20805 +       struct omap_overlay *ovl;
20806 +       struct omap_dss_device *def_display;
20807 +       struct omap_dss_device *dssdev;
20808 +
20809 +       DBG("omapfb_probe\n");
20810 +
20811 +       if (pdev->num_resources != 0) {
20812 +               dev_err(&pdev->dev, "probed for an unknown device\n");
20813 +               r = -ENODEV;
20814 +               goto err0;
20815 +       }
20816 +
20817 +       fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL);
20818 +       if (fbdev == NULL) {
20819 +               r = -ENOMEM;
20820 +               goto err0;
20821 +       }
20822 +
20823 +       mutex_init(&fbdev->mtx);
20824 +
20825 +       fbdev->dev = &pdev->dev;
20826 +       platform_set_drvdata(pdev, fbdev);
20827 +
20828 +       fbdev->num_displays = 0;
20829 +       dssdev = NULL;
20830 +       for_each_dss_dev(dssdev) {
20831 +               omap_dss_get_device(dssdev);
20832 +               fbdev->displays[fbdev->num_displays++] = dssdev;
20833 +       }
20834 +
20835 +       if (fbdev->num_displays == 0) {
20836 +               dev_err(&pdev->dev, "no displays\n");
20837 +               r = -EINVAL;
20838 +               goto cleanup;
20839 +       }
20840 +
20841 +       fbdev->num_overlays = omap_dss_get_num_overlays();
20842 +       for (i = 0; i < fbdev->num_overlays; i++)
20843 +               fbdev->overlays[i] = omap_dss_get_overlay(i);
20844 +
20845 +       fbdev->num_managers = omap_dss_get_num_overlay_managers();
20846 +       for (i = 0; i < fbdev->num_managers; i++)
20847 +               fbdev->managers[i] = omap_dss_get_overlay_manager(i);
20848 +
20849 +       if (def_mode && strlen(def_mode) > 0) {
20850 +               if (omapfb_parse_def_modes(fbdev))
20851 +                       dev_warn(&pdev->dev, "cannot parse default modes\n");
20852 +       }
20853 +
20854 +       r = omapfb_create_framebuffers(fbdev);
20855 +       if (r)
20856 +               goto cleanup;
20857 +
20858 +       for (i = 0; i < fbdev->num_managers; i++) {
20859 +               struct omap_overlay_manager *mgr;
20860 +               mgr = fbdev->managers[i];
20861 +               r = mgr->apply(mgr);
20862 +               if (r)
20863 +                       dev_warn(fbdev->dev, "failed to apply dispc config\n");
20864 +       }
20865 +
20866 +       DBG("mgr->apply'ed\n");
20867 +
20868 +       /* gfx overlay should be the default one. find a display
20869 +        * connected to that, and use it as default display */
20870 +       ovl = omap_dss_get_overlay(0);
20871 +       if (ovl->manager && ovl->manager->device) {
20872 +               def_display = ovl->manager->device;
20873 +       } else {
20874 +               dev_warn(&pdev->dev, "cannot find default display\n");
20875 +               def_display = NULL;
20876 +       }
20877 +
20878 +       if (def_display) {
20879 +               u16 w, h;
20880 +               r = def_display->enable(def_display);
20881 +               if (r)
20882 +                       dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
20883 +                                       def_display->name);
20884 +
20885 +               /* set the update mode */
20886 +               if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
20887 +#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE
20888 +                       if (def_display->enable_te)
20889 +                               def_display->enable_te(def_display, 1);
20890 +                       if (def_display->set_update_mode)
20891 +                               def_display->set_update_mode(def_display,
20892 +                                               OMAP_DSS_UPDATE_AUTO);
20893 +#else /* MANUAL_UPDATE */
20894 +                       if (def_display->enable_te)
20895 +                               def_display->enable_te(def_display, 0);
20896 +                       if (def_display->set_update_mode)
20897 +                               def_display->set_update_mode(def_display,
20898 +                                               OMAP_DSS_UPDATE_MANUAL);
20899 +
20900 +                       def_display->get_resolution(def_display, &w, &h);
20901 +                       def_display->update(def_display, 0, 0, w, h);
20902 +#endif
20903 +               } else {
20904 +                       if (def_display->set_update_mode)
20905 +                               def_display->set_update_mode(def_display,
20906 +                                               OMAP_DSS_UPDATE_AUTO);
20907 +               }
20908 +       }
20909 +
20910 +       return 0;
20911 +
20912 +cleanup:
20913 +       omapfb_free_resources(fbdev);
20914 +err0:
20915 +       dev_err(&pdev->dev, "failed to setup omapfb\n");
20916 +       return r;
20917 +}
20918 +
20919 +static int omapfb_remove(struct platform_device *pdev)
20920 +{
20921 +       struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
20922 +
20923 +       /* FIXME: wait till completion of pending events */
20924 +
20925 +       omapfb_remove_sysfs(fbdev);
20926 +
20927 +       omapfb_free_resources(fbdev);
20928 +
20929 +       return 0;
20930 +}
20931 +
20932 +static struct platform_driver omapfb_driver = {
20933 +       .probe          = omapfb_probe,
20934 +       .remove         = omapfb_remove,
20935 +       .driver         = {
20936 +               .name   = "omapfb",
20937 +               .owner  = THIS_MODULE,
20938 +       },
20939 +};
20940 +
20941 +static int __init omapfb_init(void)
20942 +{
20943 +       DBG("omapfb_init\n");
20944 +
20945 +       if (platform_driver_register(&omapfb_driver)) {
20946 +               printk(KERN_ERR "failed to register omapfb driver\n");
20947 +               return -ENODEV;
20948 +       }
20949 +
20950 +       return 0;
20951 +}
20952 +
20953 +static void __exit omapfb_exit(void)
20954 +{
20955 +       DBG("omapfb_exit\n");
20956 +       platform_driver_unregister(&omapfb_driver);
20957 +}
20958 +
20959 +module_param_named(mode, def_mode, charp, 0);
20960 +module_param_named(vram, def_vram, charp, 0);
20961 +module_param_named(rotate, def_rotate, int, 0);
20962 +module_param_named(vrfb, def_vrfb, bool, 0);
20963 +module_param_named(mirror, def_mirror, bool, 0);
20964 +
20965 +/* late_initcall to let panel/ctrl drivers loaded first.
20966 + * I guess better option would be a more dynamic approach,
20967 + * so that omapfb reacts to new panels when they are loaded */
20968 +late_initcall(omapfb_init);
20969 +/*module_init(omapfb_init);*/
20970 +module_exit(omapfb_exit);
20971 +
20972 +MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
20973 +MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
20974 +MODULE_LICENSE("GPL v2");
20975 diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
20976 new file mode 100644
20977 index 0000000..ef30e0e
20978 --- /dev/null
20979 +++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
20980 @@ -0,0 +1,507 @@
20981 +/*
20982 + * linux/drivers/video/omap2/omapfb-sysfs.c
20983 + *
20984 + * Copyright (C) 2008 Nokia Corporation
20985 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
20986 + *
20987 + * Some code and ideas taken from drivers/video/omap/ driver
20988 + * by Imre Deak.
20989 + *
20990 + * This program is free software; you can redistribute it and/or modify it
20991 + * under the terms of the GNU General Public License version 2 as published by
20992 + * the Free Software Foundation.
20993 + *
20994 + * This program is distributed in the hope that it will be useful, but WITHOUT
20995 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20996 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
20997 + * more details.
20998 + *
20999 + * You should have received a copy of the GNU General Public License along with
21000 + * this program.  If not, see <http://www.gnu.org/licenses/>.
21001 + */
21002 +
21003 +#include <linux/fb.h>
21004 +#include <linux/sysfs.h>
21005 +#include <linux/device.h>
21006 +#include <linux/uaccess.h>
21007 +#include <linux/platform_device.h>
21008 +#include <linux/kernel.h>
21009 +#include <linux/mm.h>
21010 +#include <linux/omapfb.h>
21011 +
21012 +#include <mach/display.h>
21013 +#include <mach/vrfb.h>
21014 +
21015 +#include "omapfb.h"
21016 +
21017 +static ssize_t show_rotate_type(struct device *dev,
21018 +               struct device_attribute *attr, char *buf)
21019 +{
21020 +       struct fb_info *fbi = dev_get_drvdata(dev);
21021 +       struct omapfb_info *ofbi = FB2OFB(fbi);
21022 +
21023 +       return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->rotation_type);
21024 +}
21025 +
21026 +static ssize_t store_rotate_type(struct device *dev,
21027 +               struct device_attribute *attr,
21028 +               const char *buf, size_t count)
21029 +{
21030 +       struct fb_info *fbi = dev_get_drvdata(dev);
21031 +       struct omapfb_info *ofbi = FB2OFB(fbi);
21032 +       enum omap_dss_rotation_type rot_type;
21033 +       int r;
21034 +
21035 +       rot_type = simple_strtoul(buf, NULL, 0);
21036 +
21037 +       if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB)
21038 +               return -EINVAL;
21039 +
21040 +       lock_fb_info(fbi);
21041 +
21042 +       r = 0;
21043 +       if (rot_type == ofbi->rotation_type)
21044 +               goto out;
21045 +
21046 +       if (ofbi->region.size) {
21047 +               r = -EBUSY;
21048 +               goto out;
21049 +       }
21050 +
21051 +       ofbi->rotation_type = rot_type;
21052 +
21053 +       /*
21054 +        * Since the VRAM for this FB is not allocated at the moment we don't
21055 +        * need to do any further parameter checking at this point.
21056 +        */
21057 +out:
21058 +       unlock_fb_info(fbi);
21059 +
21060 +       return r ? r : count;
21061 +}
21062 +
21063 +
21064 +static ssize_t show_mirror(struct device *dev,
21065 +               struct device_attribute *attr, char *buf)
21066 +{
21067 +       struct fb_info *fbi = dev_get_drvdata(dev);
21068 +       struct omapfb_info *ofbi = FB2OFB(fbi);
21069 +
21070 +       return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->mirror);
21071 +}
21072 +
21073 +static ssize_t store_mirror(struct device *dev,
21074 +               struct device_attribute *attr,
21075 +               const char *buf, size_t count)
21076 +{
21077 +       struct fb_info *fbi = dev_get_drvdata(dev);
21078 +       struct omapfb_info *ofbi = FB2OFB(fbi);
21079 +       bool mirror;
21080 +       int r;
21081 +       struct fb_var_screeninfo new_var;
21082 +
21083 +       mirror = simple_strtoul(buf, NULL, 0);
21084 +
21085 +       if (mirror != 0 && mirror != 1)
21086 +               return -EINVAL;
21087 +
21088 +       lock_fb_info(fbi);
21089 +
21090 +       ofbi->mirror = mirror;
21091 +
21092 +       memcpy(&new_var, &fbi->var, sizeof(new_var));
21093 +       r = check_fb_var(fbi, &new_var);
21094 +       if (r)
21095 +               goto out;
21096 +       memcpy(&fbi->var, &new_var, sizeof(fbi->var));
21097 +
21098 +       set_fb_fix(fbi);
21099 +
21100 +       r = omapfb_apply_changes(fbi, 0);
21101 +       if (r)
21102 +               goto out;
21103 +
21104 +       r = count;
21105 +out:
21106 +       unlock_fb_info(fbi);
21107 +
21108 +       return r;
21109 +}
21110 +
21111 +static ssize_t show_overlays(struct device *dev,
21112 +               struct device_attribute *attr, char *buf)
21113 +{
21114 +       struct fb_info *fbi = dev_get_drvdata(dev);
21115 +       struct omapfb_info *ofbi = FB2OFB(fbi);
21116 +       struct omapfb2_device *fbdev = ofbi->fbdev;
21117 +       ssize_t l = 0;
21118 +       int t;
21119 +
21120 +       omapfb_lock(fbdev);
21121 +       lock_fb_info(fbi);
21122 +
21123 +       for (t = 0; t < ofbi->num_overlays; t++) {
21124 +               struct omap_overlay *ovl = ofbi->overlays[t];
21125 +               int ovlnum;
21126 +
21127 +               for (ovlnum = 0; ovlnum < fbdev->num_overlays; ++ovlnum)
21128 +                       if (ovl == fbdev->overlays[ovlnum])
21129 +                               break;
21130 +
21131 +               l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
21132 +                               t == 0 ? "" : ",", ovlnum);
21133 +       }
21134 +
21135 +       l += snprintf(buf + l, PAGE_SIZE - l, "\n");
21136 +
21137 +       unlock_fb_info(fbi);
21138 +       omapfb_unlock(fbdev);
21139 +
21140 +       return l;
21141 +}
21142 +
21143 +static struct omapfb_info *get_overlay_fb(struct omapfb2_device *fbdev,
21144 +               struct omap_overlay *ovl)
21145 +{
21146 +       int i, t;
21147 +
21148 +       for (i = 0; i < fbdev->num_fbs; i++) {
21149 +               struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
21150 +
21151 +               for (t = 0; t < ofbi->num_overlays; t++) {
21152 +                       if (ofbi->overlays[t] == ovl)
21153 +                               return ofbi;
21154 +               }
21155 +       }
21156 +
21157 +       return NULL;
21158 +}
21159 +
21160 +static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
21161 +               const char *buf, size_t count)
21162 +{
21163 +       struct fb_info *fbi = dev_get_drvdata(dev);
21164 +       struct omapfb_info *ofbi = FB2OFB(fbi);
21165 +       struct omapfb2_device *fbdev = ofbi->fbdev;
21166 +       struct omap_overlay *ovls[OMAPFB_MAX_OVL_PER_FB];
21167 +       struct omap_overlay *ovl;
21168 +       int num_ovls, r, i;
21169 +       int len;
21170 +       bool added = false;
21171 +
21172 +       num_ovls = 0;
21173 +
21174 +       len = strlen(buf);
21175 +       if (buf[len - 1] == '\n')
21176 +               len = len - 1;
21177 +
21178 +       omapfb_lock(fbdev);
21179 +       lock_fb_info(fbi);
21180 +
21181 +       if (len > 0) {
21182 +               char *p = (char *)buf;
21183 +               int ovlnum;
21184 +
21185 +               while (p < buf + len) {
21186 +                       int found;
21187 +                       if (num_ovls == OMAPFB_MAX_OVL_PER_FB) {
21188 +                               r = -EINVAL;
21189 +                               goto out;
21190 +                       }
21191 +
21192 +                       ovlnum = simple_strtoul(p, &p, 0);
21193 +                       if (ovlnum > fbdev->num_overlays) {
21194 +                               r = -EINVAL;
21195 +                               goto out;
21196 +                       }
21197 +
21198 +                       found = 0;
21199 +                       for (i = 0; i < num_ovls; ++i) {
21200 +                               if (ovls[i] == fbdev->overlays[ovlnum]) {
21201 +                                       found = 1;
21202 +                                       break;
21203 +                               }
21204 +                       }
21205 +
21206 +                       if (!found)
21207 +                               ovls[num_ovls++] = fbdev->overlays[ovlnum];
21208 +
21209 +                       p++;
21210 +               }
21211 +       }
21212 +
21213 +       for (i = 0; i < num_ovls; ++i) {
21214 +               struct omapfb_info *ofbi2 = get_overlay_fb(fbdev, ovls[i]);
21215 +               if (ofbi2 && ofbi2 != ofbi) {
21216 +                       dev_err(fbdev->dev, "overlay already in use\n");
21217 +                       r = -EINVAL;
21218 +                       goto out;
21219 +               }
21220 +       }
21221 +
21222 +       /* detach unused overlays */
21223 +       for (i = 0; i < ofbi->num_overlays; ++i) {
21224 +               int t, found;
21225 +
21226 +               ovl = ofbi->overlays[i];
21227 +
21228 +               found = 0;
21229 +
21230 +               for (t = 0; t < num_ovls; ++t) {
21231 +                       if (ovl == ovls[t]) {
21232 +                               found = 1;
21233 +                               break;
21234 +                       }
21235 +               }
21236 +
21237 +               if (found)
21238 +                       continue;
21239 +
21240 +               DBG("detaching %d\n", ofbi->overlays[i]->id);
21241 +
21242 +               omapfb_overlay_enable(ovl, 0);
21243 +
21244 +               if (ovl->manager)
21245 +                       ovl->manager->apply(ovl->manager);
21246 +
21247 +               for (t = i + 1; t < ofbi->num_overlays; t++) {
21248 +                       ofbi->rotation[t-1] = ofbi->rotation[t];
21249 +                       ofbi->overlays[t-1] = ofbi->overlays[t];
21250 +               }
21251 +
21252 +               ofbi->num_overlays--;
21253 +               i--;
21254 +       }
21255 +
21256 +       for (i = 0; i < num_ovls; ++i) {
21257 +               int t, found;
21258 +
21259 +               ovl = ovls[i];
21260 +
21261 +               found = 0;
21262 +
21263 +               for (t = 0; t < ofbi->num_overlays; ++t) {
21264 +                       if (ovl == ofbi->overlays[t]) {
21265 +                               found = 1;
21266 +                               break;
21267 +                       }
21268 +               }
21269 +
21270 +               if (found)
21271 +                       continue;
21272 +               ofbi->rotation[ofbi->num_overlays] = 0;
21273 +               ofbi->overlays[ofbi->num_overlays++] = ovl;
21274 +
21275 +               added = true;
21276 +       }
21277 +
21278 +       if (added) {
21279 +               r = omapfb_apply_changes(fbi, 0);
21280 +               if (r)
21281 +                       goto out;
21282 +       }
21283 +
21284 +       r = count;
21285 +out:
21286 +       unlock_fb_info(fbi);
21287 +       omapfb_unlock(fbdev);
21288 +
21289 +       return r;
21290 +}
21291 +
21292 +static ssize_t show_overlays_rotate(struct device *dev,
21293 +               struct device_attribute *attr, char *buf)
21294 +{
21295 +       struct fb_info *fbi = dev_get_drvdata(dev);
21296 +       struct omapfb_info *ofbi = FB2OFB(fbi);
21297 +       ssize_t l = 0;
21298 +       int t;
21299 +
21300 +       lock_fb_info(fbi);
21301 +
21302 +       for (t = 0; t < ofbi->num_overlays; t++) {
21303 +               l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
21304 +                               t == 0 ? "" : ",", ofbi->rotation[t]);
21305 +       }
21306 +
21307 +       l += snprintf(buf + l, PAGE_SIZE - l, "\n");
21308 +
21309 +       unlock_fb_info(fbi);
21310 +
21311 +       return l;
21312 +}
21313 +
21314 +static ssize_t store_overlays_rotate(struct device *dev,
21315 +               struct device_attribute *attr, const char *buf, size_t count)
21316 +{
21317 +       struct fb_info *fbi = dev_get_drvdata(dev);
21318 +       struct omapfb_info *ofbi = FB2OFB(fbi);
21319 +       int num_ovls = 0, r, i;
21320 +       int len;
21321 +       bool changed = false;
21322 +       u8 rotation[OMAPFB_MAX_OVL_PER_FB];
21323 +
21324 +       len = strlen(buf);
21325 +       if (buf[len - 1] == '\n')
21326 +               len = len - 1;
21327 +
21328 +       lock_fb_info(fbi);
21329 +
21330 +       if (len > 0) {
21331 +               char *p = (char *)buf;
21332 +
21333 +               while (p < buf + len) {
21334 +                       int rot;
21335 +
21336 +                       if (num_ovls == ofbi->num_overlays) {
21337 +                               r = -EINVAL;
21338 +                               goto out;
21339 +                       }
21340 +
21341 +                       rot = simple_strtoul(p, &p, 0);
21342 +                       if (rot < 0 || rot > 3) {
21343 +                               r = -EINVAL;
21344 +                               goto out;
21345 +                       }
21346 +
21347 +                       if (ofbi->rotation[num_ovls] != rot)
21348 +                               changed = true;
21349 +
21350 +                       rotation[num_ovls++] = rot;
21351 +
21352 +                       p++;
21353 +               }
21354 +       }
21355 +
21356 +       if (num_ovls != ofbi->num_overlays) {
21357 +               r = -EINVAL;
21358 +               goto out;
21359 +       }
21360 +
21361 +       if (changed) {
21362 +               for (i = 0; i < num_ovls; ++i)
21363 +                       ofbi->rotation[i] = rotation[i];
21364 +
21365 +               r = omapfb_apply_changes(fbi, 0);
21366 +               if (r)
21367 +                       goto out;
21368 +
21369 +               /* FIXME error handling? */
21370 +       }
21371 +
21372 +       r = count;
21373 +out:
21374 +       unlock_fb_info(fbi);
21375 +
21376 +       return r;
21377 +}
21378 +
21379 +static ssize_t show_size(struct device *dev,
21380 +               struct device_attribute *attr, char *buf)
21381 +{
21382 +       struct fb_info *fbi = dev_get_drvdata(dev);
21383 +       struct omapfb_info *ofbi = FB2OFB(fbi);
21384 +
21385 +       return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region.size);
21386 +}
21387 +
21388 +static ssize_t store_size(struct device *dev, struct device_attribute *attr,
21389 +               const char *buf, size_t count)
21390 +{
21391 +       struct fb_info *fbi = dev_get_drvdata(dev);
21392 +       struct omapfb_info *ofbi = FB2OFB(fbi);
21393 +       unsigned long size;
21394 +       int r;
21395 +       int i;
21396 +
21397 +       size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0));
21398 +
21399 +       lock_fb_info(fbi);
21400 +
21401 +       for (i = 0; i < ofbi->num_overlays; i++) {
21402 +               if (ofbi->overlays[i]->info.enabled) {
21403 +                       r = -EBUSY;
21404 +                       goto out;
21405 +               }
21406 +       }
21407 +
21408 +       if (size != ofbi->region.size) {
21409 +               r = omapfb_realloc_fbmem(fbi, size, ofbi->region.type);
21410 +               if (r) {
21411 +                       dev_err(dev, "realloc fbmem failed\n");
21412 +                       goto out;
21413 +               }
21414 +       }
21415 +
21416 +       r = count;
21417 +out:
21418 +       unlock_fb_info(fbi);
21419 +
21420 +       return r;
21421 +}
21422 +
21423 +static ssize_t show_phys(struct device *dev,
21424 +               struct device_attribute *attr, char *buf)
21425 +{
21426 +       struct fb_info *fbi = dev_get_drvdata(dev);
21427 +       struct omapfb_info *ofbi = FB2OFB(fbi);
21428 +
21429 +       return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region.paddr);
21430 +}
21431 +
21432 +static ssize_t show_virt(struct device *dev,
21433 +               struct device_attribute *attr, char *buf)
21434 +{
21435 +       struct fb_info *fbi = dev_get_drvdata(dev);
21436 +       struct omapfb_info *ofbi = FB2OFB(fbi);
21437 +
21438 +       return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr);
21439 +}
21440 +
21441 +static struct device_attribute omapfb_attrs[] = {
21442 +       __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type,
21443 +                       store_rotate_type),
21444 +       __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror),
21445 +       __ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size),
21446 +       __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
21447 +       __ATTR(overlays_rotate, S_IRUGO | S_IWUSR, show_overlays_rotate,
21448 +                       store_overlays_rotate),
21449 +       __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
21450 +       __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
21451 +};
21452 +
21453 +int omapfb_create_sysfs(struct omapfb2_device *fbdev)
21454 +{
21455 +       int i;
21456 +       int r;
21457 +
21458 +       DBG("create sysfs for fbs\n");
21459 +       for (i = 0; i < fbdev->num_fbs; i++) {
21460 +               int t;
21461 +               for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) {
21462 +                       r = device_create_file(fbdev->fbs[i]->dev,
21463 +                                       &omapfb_attrs[t]);
21464 +
21465 +                       if (r) {
21466 +                               dev_err(fbdev->dev, "failed to create sysfs "
21467 +                                               "file\n");
21468 +                               return r;
21469 +                       }
21470 +               }
21471 +       }
21472 +
21473 +       return 0;
21474 +}
21475 +
21476 +void omapfb_remove_sysfs(struct omapfb2_device *fbdev)
21477 +{
21478 +       int i, t;
21479 +
21480 +       DBG("remove sysfs for fbs\n");
21481 +       for (i = 0; i < fbdev->num_fbs; i++) {
21482 +               for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++)
21483 +                       device_remove_file(fbdev->fbs[i]->dev,
21484 +                                       &omapfb_attrs[t]);
21485 +       }
21486 +}
21487 +
21488 diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
21489 new file mode 100644
21490 index 0000000..d9ee986
21491 --- /dev/null
21492 +++ b/drivers/video/omap2/omapfb/omapfb.h
21493 @@ -0,0 +1,146 @@
21494 +/*
21495 + * linux/drivers/video/omap2/omapfb.h
21496 + *
21497 + * Copyright (C) 2008 Nokia Corporation
21498 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
21499 + *
21500 + * Some code and ideas taken from drivers/video/omap/ driver
21501 + * by Imre Deak.
21502 + *
21503 + * This program is free software; you can redistribute it and/or modify it
21504 + * under the terms of the GNU General Public License version 2 as published by
21505 + * the Free Software Foundation.
21506 + *
21507 + * This program is distributed in the hope that it will be useful, but WITHOUT
21508 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21509 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
21510 + * more details.
21511 + *
21512 + * You should have received a copy of the GNU General Public License along with
21513 + * this program.  If not, see <http://www.gnu.org/licenses/>.
21514 + */
21515 +
21516 +#ifndef __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
21517 +#define __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
21518 +
21519 +#ifdef CONFIG_FB_OMAP2_DEBUG_SUPPORT
21520 +#define DEBUG
21521 +#endif
21522 +
21523 +#include <mach/display.h>
21524 +
21525 +#ifdef DEBUG
21526 +extern unsigned int omapfb_debug;
21527 +#define DBG(format, ...) \
21528 +       if (omapfb_debug) \
21529 +               printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__)
21530 +#else
21531 +#define DBG(format, ...)
21532 +#endif
21533 +
21534 +#define FB2OFB(fb_info) ((struct omapfb_info *)(fb_info->par))
21535 +
21536 +/* max number of overlays to which a framebuffer data can be direct */
21537 +#define OMAPFB_MAX_OVL_PER_FB 3
21538 +
21539 +struct omapfb2_mem_region {
21540 +       u32             paddr;
21541 +       void __iomem    *vaddr;
21542 +       struct vrfb     vrfb;
21543 +       unsigned long   size;
21544 +       u8              type;           /* OMAPFB_PLANE_MEM_* */
21545 +       bool            alloc;          /* allocated by the driver */
21546 +       bool            map;            /* kernel mapped by the driver */
21547 +};
21548 +
21549 +/* appended to fb_info */
21550 +struct omapfb_info {
21551 +       int id;
21552 +       struct omapfb2_mem_region region;
21553 +       atomic_t map_count;
21554 +       int num_overlays;
21555 +       struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
21556 +       struct omapfb2_device *fbdev;
21557 +       enum omap_dss_rotation_type rotation_type;
21558 +       u8 rotation[OMAPFB_MAX_OVL_PER_FB];
21559 +       bool mirror;
21560 +};
21561 +
21562 +struct omapfb2_device {
21563 +       struct device *dev;
21564 +       struct mutex  mtx;
21565 +
21566 +       u32 pseudo_palette[17];
21567 +
21568 +       int state;
21569 +
21570 +       unsigned num_fbs;
21571 +       struct fb_info *fbs[10];
21572 +
21573 +       unsigned num_displays;
21574 +       struct omap_dss_device *displays[10];
21575 +       unsigned num_overlays;
21576 +       struct omap_overlay *overlays[10];
21577 +       unsigned num_managers;
21578 +       struct omap_overlay_manager *managers[10];
21579 +};
21580 +
21581 +struct omapfb_colormode {
21582 +       enum omap_color_mode dssmode;
21583 +       u32 bits_per_pixel;
21584 +       u32 nonstd;
21585 +       struct fb_bitfield red;
21586 +       struct fb_bitfield green;
21587 +       struct fb_bitfield blue;
21588 +       struct fb_bitfield transp;
21589 +};
21590 +
21591 +void set_fb_fix(struct fb_info *fbi);
21592 +int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var);
21593 +int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type);
21594 +int omapfb_apply_changes(struct fb_info *fbi, int init);
21595 +
21596 +int omapfb_create_sysfs(struct omapfb2_device *fbdev);
21597 +void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
21598 +
21599 +int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
21600 +
21601 +int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
21602 +                       struct fb_var_screeninfo *var);
21603 +
21604 +/* find the display connected to this fb, if any */
21605 +static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
21606 +{
21607 +       struct omapfb_info *ofbi = FB2OFB(fbi);
21608 +       int i;
21609 +
21610 +       /* XXX: returns the display connected to first attached overlay */
21611 +       for (i = 0; i < ofbi->num_overlays; i++) {
21612 +               if (ofbi->overlays[i]->manager)
21613 +                       return ofbi->overlays[i]->manager->device;
21614 +       }
21615 +
21616 +       return NULL;
21617 +}
21618 +
21619 +static inline void omapfb_lock(struct omapfb2_device *fbdev)
21620 +{
21621 +       mutex_lock(&fbdev->mtx);
21622 +}
21623 +
21624 +static inline void omapfb_unlock(struct omapfb2_device *fbdev)
21625 +{
21626 +       mutex_unlock(&fbdev->mtx);
21627 +}
21628 +
21629 +static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
21630 +               int enable)
21631 +{
21632 +       struct omap_overlay_info info;
21633 +
21634 +       ovl->get_overlay_info(ovl, &info);
21635 +       info.enabled = enable;
21636 +       return ovl->set_overlay_info(ovl, &info);
21637 +}
21638 +
21639 +#endif
21640 diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c
21641 new file mode 100644
21642 index 0000000..634ce23
21643 --- /dev/null
21644 +++ b/drivers/video/omap2/vram.c
21645 @@ -0,0 +1,655 @@
21646 +/*
21647 + * VRAM manager for OMAP
21648 + *
21649 + * Copyright (C) 2009 Nokia Corporation
21650 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
21651 + *
21652 + * This program is free software; you can redistribute it and/or modify
21653 + * it under the terms of the GNU General Public License version 2 as
21654 + * published by the Free Software Foundation.
21655 + *
21656 + * This program is distributed in the hope that it will be useful, but
21657 + * WITHOUT ANY WARRANTY; without even the implied warranty of
21658 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21659 + * General Public License for more details.
21660 + *
21661 + * You should have received a copy of the GNU General Public License along
21662 + * with this program; if not, write to the Free Software Foundation, Inc.,
21663 + * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21664 + */
21665 +
21666 +/*#define DEBUG*/
21667 +
21668 +#include <linux/kernel.h>
21669 +#include <linux/mm.h>
21670 +#include <linux/list.h>
21671 +#include <linux/seq_file.h>
21672 +#include <linux/bootmem.h>
21673 +#include <linux/completion.h>
21674 +#include <linux/debugfs.h>
21675 +#include <linux/jiffies.h>
21676 +#include <linux/module.h>
21677 +
21678 +#include <asm/setup.h>
21679 +
21680 +#include <mach/sram.h>
21681 +#include <mach/vram.h>
21682 +#include <mach/dma.h>
21683 +
21684 +#ifdef DEBUG
21685 +#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__)
21686 +#else
21687 +#define DBG(format, ...)
21688 +#endif
21689 +
21690 +#define OMAP2_SRAM_START               0x40200000
21691 +/* Maximum size, in reality this is smaller if SRAM is partially locked. */
21692 +#define OMAP2_SRAM_SIZE                        0xa0000         /* 640k */
21693 +
21694 +/* postponed regions are used to temporarily store region information at boot
21695 + * time when we cannot yet allocate the region list */
21696 +#define MAX_POSTPONED_REGIONS 10
21697 +
21698 +static bool vram_initialized;
21699 +static int postponed_cnt;
21700 +static struct {
21701 +       unsigned long paddr;
21702 +       size_t size;
21703 +} postponed_regions[MAX_POSTPONED_REGIONS];
21704 +
21705 +struct vram_alloc {
21706 +       struct list_head list;
21707 +       unsigned long paddr;
21708 +       unsigned pages;
21709 +};
21710 +
21711 +struct vram_region {
21712 +       struct list_head list;
21713 +       struct list_head alloc_list;
21714 +       unsigned long paddr;
21715 +       unsigned pages;
21716 +};
21717 +
21718 +static DEFINE_MUTEX(region_mutex);
21719 +static LIST_HEAD(region_list);
21720 +
21721 +static inline int region_mem_type(unsigned long paddr)
21722 +{
21723 +       if (paddr >= OMAP2_SRAM_START &&
21724 +           paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
21725 +               return OMAP_VRAM_MEMTYPE_SRAM;
21726 +       else
21727 +               return OMAP_VRAM_MEMTYPE_SDRAM;
21728 +}
21729 +
21730 +static struct vram_region *omap_vram_create_region(unsigned long paddr,
21731 +               unsigned pages)
21732 +{
21733 +       struct vram_region *rm;
21734 +
21735 +       rm = kzalloc(sizeof(*rm), GFP_KERNEL);
21736 +
21737 +       if (rm) {
21738 +               INIT_LIST_HEAD(&rm->alloc_list);
21739 +               rm->paddr = paddr;
21740 +               rm->pages = pages;
21741 +       }
21742 +
21743 +       return rm;
21744 +}
21745 +
21746 +#if 0
21747 +static void omap_vram_free_region(struct vram_region *vr)
21748 +{
21749 +       list_del(&vr->list);
21750 +       kfree(vr);
21751 +}
21752 +#endif
21753 +
21754 +static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr,
21755 +               unsigned long paddr, unsigned pages)
21756 +{
21757 +       struct vram_alloc *va;
21758 +       struct vram_alloc *new;
21759 +
21760 +       new = kzalloc(sizeof(*va), GFP_KERNEL);
21761 +
21762 +       if (!new)
21763 +               return NULL;
21764 +
21765 +       new->paddr = paddr;
21766 +       new->pages = pages;
21767 +
21768 +       list_for_each_entry(va, &vr->alloc_list, list) {
21769 +               if (va->paddr > new->paddr)
21770 +                       break;
21771 +       }
21772 +
21773 +       list_add_tail(&new->list, &va->list);
21774 +
21775 +       return new;
21776 +}
21777 +
21778 +static void omap_vram_free_allocation(struct vram_alloc *va)
21779 +{
21780 +       list_del(&va->list);
21781 +       kfree(va);
21782 +}
21783 +
21784 +int omap_vram_add_region(unsigned long paddr, size_t size)
21785 +{
21786 +       struct vram_region *rm;
21787 +       unsigned pages;
21788 +
21789 +       if (vram_initialized) {
21790 +               DBG("adding region paddr %08lx size %d\n",
21791 +                               paddr, size);
21792 +
21793 +               size &= PAGE_MASK;
21794 +               pages = size >> PAGE_SHIFT;
21795 +
21796 +               rm = omap_vram_create_region(paddr, pages);
21797 +               if (rm == NULL)
21798 +                       return -ENOMEM;
21799 +
21800 +               list_add(&rm->list, &region_list);
21801 +       } else {
21802 +               if (postponed_cnt == MAX_POSTPONED_REGIONS)
21803 +                       return -ENOMEM;
21804 +
21805 +               postponed_regions[postponed_cnt].paddr = paddr;
21806 +               postponed_regions[postponed_cnt].size = size;
21807 +
21808 +               ++postponed_cnt;
21809 +       }
21810 +       return 0;
21811 +}
21812 +
21813 +int omap_vram_free(unsigned long paddr, size_t size)
21814 +{
21815 +       struct vram_region *rm;
21816 +       struct vram_alloc *alloc;
21817 +       unsigned start, end;
21818 +
21819 +       DBG("free mem paddr %08lx size %d\n", paddr, size);
21820 +
21821 +       size = PAGE_ALIGN(size);
21822 +
21823 +       mutex_lock(&region_mutex);
21824 +
21825 +       list_for_each_entry(rm, &region_list, list) {
21826 +               list_for_each_entry(alloc, &rm->alloc_list, list) {
21827 +                       start = alloc->paddr;
21828 +                       end = alloc->paddr + (alloc->pages >> PAGE_SHIFT);
21829 +
21830 +                       if (start >= paddr && end < paddr + size)
21831 +                               goto found;
21832 +               }
21833 +       }
21834 +
21835 +       mutex_unlock(&region_mutex);
21836 +       return -EINVAL;
21837 +
21838 +found:
21839 +       omap_vram_free_allocation(alloc);
21840 +
21841 +       mutex_unlock(&region_mutex);
21842 +       return 0;
21843 +}
21844 +EXPORT_SYMBOL(omap_vram_free);
21845 +
21846 +static int _omap_vram_reserve(unsigned long paddr, unsigned pages)
21847 +{
21848 +       struct vram_region *rm;
21849 +       struct vram_alloc *alloc;
21850 +       size_t size;
21851 +
21852 +       size = pages << PAGE_SHIFT;
21853 +
21854 +       list_for_each_entry(rm, &region_list, list) {
21855 +               unsigned long start, end;
21856 +
21857 +               DBG("checking region %lx %d\n", rm->paddr, rm->pages);
21858 +
21859 +               if (region_mem_type(rm->paddr) != region_mem_type(paddr))
21860 +                       continue;
21861 +
21862 +               start = rm->paddr;
21863 +               end = start + (rm->pages << PAGE_SHIFT) - 1;
21864 +               if (start > paddr || end < paddr + size - 1)
21865 +                       continue;
21866 +
21867 +               DBG("block ok, checking allocs\n");
21868 +
21869 +               list_for_each_entry(alloc, &rm->alloc_list, list) {
21870 +                       end = alloc->paddr - 1;
21871 +
21872 +                       if (start <= paddr && end >= paddr + size - 1)
21873 +                               goto found;
21874 +
21875 +                       start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
21876 +               }
21877 +
21878 +               end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1;
21879 +
21880 +               if (!(start <= paddr && end >= paddr + size - 1))
21881 +                       continue;
21882 +found:
21883 +               DBG("found area start %lx, end %lx\n", start, end);
21884 +
21885 +               if (omap_vram_create_allocation(rm, paddr, pages) == NULL)
21886 +                       return -ENOMEM;
21887 +
21888 +               return 0;
21889 +       }
21890 +
21891 +       return -ENOMEM;
21892 +}
21893 +
21894 +int omap_vram_reserve(unsigned long paddr, size_t size)
21895 +{
21896 +       unsigned pages;
21897 +       int r;
21898 +
21899 +       DBG("reserve mem paddr %08lx size %d\n", paddr, size);
21900 +
21901 +       size = PAGE_ALIGN(size);
21902 +       pages = size >> PAGE_SHIFT;
21903 +
21904 +       mutex_lock(&region_mutex);
21905 +
21906 +       r = _omap_vram_reserve(paddr, pages);
21907 +
21908 +       mutex_unlock(&region_mutex);
21909 +
21910 +       return r;
21911 +}
21912 +EXPORT_SYMBOL(omap_vram_reserve);
21913 +
21914 +static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data)
21915 +{
21916 +       struct completion *compl = data;
21917 +       complete(compl);
21918 +}
21919 +
21920 +static int _omap_vram_clear(u32 paddr, unsigned pages)
21921 +{
21922 +       struct completion compl;
21923 +       unsigned elem_count;
21924 +       unsigned frame_count;
21925 +       int r;
21926 +       int lch;
21927 +
21928 +       init_completion(&compl);
21929 +
21930 +       r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA",
21931 +                       _omap_vram_dma_cb,
21932 +                       &compl, &lch);
21933 +       if (r) {
21934 +               pr_err("VRAM: request_dma failed for memory clear\n");
21935 +               return -EBUSY;
21936 +       }
21937 +
21938 +       elem_count = pages * PAGE_SIZE / 4;
21939 +       frame_count = 1;
21940 +
21941 +       omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32,
21942 +                       elem_count, frame_count,
21943 +                       OMAP_DMA_SYNC_ELEMENT,
21944 +                       0, 0);
21945 +
21946 +       omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC,
21947 +                       paddr, 0, 0);
21948 +
21949 +       omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000);
21950 +
21951 +       omap_start_dma(lch);
21952 +
21953 +       if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) {
21954 +               omap_stop_dma(lch);
21955 +               pr_err("VRAM: dma timeout while clearing memory\n");
21956 +               r = -EIO;
21957 +               goto err;
21958 +       }
21959 +
21960 +       r = 0;
21961 +err:
21962 +       omap_free_dma(lch);
21963 +
21964 +       return r;
21965 +}
21966 +
21967 +static int _omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr)
21968 +{
21969 +       struct vram_region *rm;
21970 +       struct vram_alloc *alloc;
21971 +
21972 +       list_for_each_entry(rm, &region_list, list) {
21973 +               unsigned long start, end;
21974 +
21975 +               DBG("checking region %lx %d\n", rm->paddr, rm->pages);
21976 +
21977 +               if (region_mem_type(rm->paddr) != mtype)
21978 +                       continue;
21979 +
21980 +               start = rm->paddr;
21981 +
21982 +               list_for_each_entry(alloc, &rm->alloc_list, list) {
21983 +                       end = alloc->paddr;
21984 +
21985 +                       if (end - start >= pages << PAGE_SHIFT)
21986 +                               goto found;
21987 +
21988 +                       start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
21989 +               }
21990 +
21991 +               end = rm->paddr + (rm->pages << PAGE_SHIFT);
21992 +found:
21993 +               if (end - start < pages << PAGE_SHIFT)
21994 +                       continue;
21995 +
21996 +               DBG("found %lx, end %lx\n", start, end);
21997 +
21998 +               alloc = omap_vram_create_allocation(rm, start, pages);
21999 +               if (alloc == NULL)
22000 +                       return -ENOMEM;
22001 +
22002 +               *paddr = start;
22003 +
22004 +               _omap_vram_clear(start, pages);
22005 +
22006 +               return 0;
22007 +       }
22008 +
22009 +       return -ENOMEM;
22010 +}
22011 +
22012 +int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr)
22013 +{
22014 +       unsigned pages;
22015 +       int r;
22016 +
22017 +       BUG_ON(mtype > OMAP_VRAM_MEMTYPE_MAX || !size);
22018 +
22019 +       DBG("alloc mem type %d size %d\n", mtype, size);
22020 +
22021 +       size = PAGE_ALIGN(size);
22022 +       pages = size >> PAGE_SHIFT;
22023 +
22024 +       mutex_lock(&region_mutex);
22025 +
22026 +       r = _omap_vram_alloc(mtype, pages, paddr);
22027 +
22028 +       mutex_unlock(&region_mutex);
22029 +
22030 +       return r;
22031 +}
22032 +EXPORT_SYMBOL(omap_vram_alloc);
22033 +
22034 +void omap_vram_get_info(unsigned long *vram,
22035 +               unsigned long *free_vram,
22036 +               unsigned long *largest_free_block)
22037 +{
22038 +       struct vram_region *vr;
22039 +       struct vram_alloc *va;
22040 +
22041 +       *vram = 0;
22042 +       *free_vram = 0;
22043 +       *largest_free_block = 0;
22044 +
22045 +       mutex_lock(&region_mutex);
22046 +
22047 +       list_for_each_entry(vr, &region_list, list) {
22048 +               unsigned free;
22049 +               unsigned long pa;
22050 +
22051 +               pa = vr->paddr;
22052 +               *vram += vr->pages << PAGE_SHIFT;
22053 +
22054 +               list_for_each_entry(va, &vr->alloc_list, list) {
22055 +                       free = va->paddr - pa;
22056 +                       *free_vram += free;
22057 +                       if (free > *largest_free_block)
22058 +                               *largest_free_block = free;
22059 +                       pa = va->paddr + (va->pages << PAGE_SHIFT);
22060 +               }
22061 +
22062 +               free = vr->paddr + (vr->pages << PAGE_SHIFT) - pa;
22063 +               *free_vram += free;
22064 +               if (free > *largest_free_block)
22065 +                       *largest_free_block = free;
22066 +       }
22067 +
22068 +       mutex_unlock(&region_mutex);
22069 +}
22070 +EXPORT_SYMBOL(omap_vram_get_info);
22071 +
22072 +#if defined(CONFIG_DEBUG_FS)
22073 +static int vram_debug_show(struct seq_file *s, void *unused)
22074 +{
22075 +       struct vram_region *vr;
22076 +       struct vram_alloc *va;
22077 +       unsigned size;
22078 +
22079 +       mutex_lock(&region_mutex);
22080 +
22081 +       list_for_each_entry(vr, &region_list, list) {
22082 +               size = vr->pages << PAGE_SHIFT;
22083 +               seq_printf(s, "%08lx-%08lx (%d bytes)\n",
22084 +                               vr->paddr, vr->paddr + size - 1,
22085 +                               size);
22086 +
22087 +               list_for_each_entry(va, &vr->alloc_list, list) {
22088 +                       size = va->pages << PAGE_SHIFT;
22089 +                       seq_printf(s, "    %08lx-%08lx (%d bytes)\n",
22090 +                                       va->paddr, va->paddr + size - 1,
22091 +                                       size);
22092 +               }
22093 +       }
22094 +
22095 +       mutex_unlock(&region_mutex);
22096 +
22097 +       return 0;
22098 +}
22099 +
22100 +static int vram_debug_open(struct inode *inode, struct file *file)
22101 +{
22102 +       return single_open(file, vram_debug_show, inode->i_private);
22103 +}
22104 +
22105 +static const struct file_operations vram_debug_fops = {
22106 +       .open           = vram_debug_open,
22107 +       .read           = seq_read,
22108 +       .llseek         = seq_lseek,
22109 +       .release        = single_release,
22110 +};
22111 +
22112 +static int __init omap_vram_create_debugfs(void)
22113 +{
22114 +       struct dentry *d;
22115 +
22116 +       d = debugfs_create_file("vram", S_IRUGO, NULL,
22117 +                       NULL, &vram_debug_fops);
22118 +       if (IS_ERR(d))
22119 +               return PTR_ERR(d);
22120 +
22121 +       return 0;
22122 +}
22123 +#endif
22124 +
22125 +static __init int omap_vram_init(void)
22126 +{
22127 +       int i;
22128 +
22129 +       vram_initialized = 1;
22130 +
22131 +       for (i = 0; i < postponed_cnt; i++)
22132 +               omap_vram_add_region(postponed_regions[i].paddr,
22133 +                               postponed_regions[i].size);
22134 +
22135 +#ifdef CONFIG_DEBUG_FS
22136 +       if (omap_vram_create_debugfs())
22137 +               pr_err("VRAM: Failed to create debugfs file\n");
22138 +#endif
22139 +
22140 +       return 0;
22141 +}
22142 +
22143 +arch_initcall(omap_vram_init);
22144 +
22145 +/* boottime vram alloc stuff */
22146 +
22147 +/* set from board file */
22148 +static u32 omap_vram_sram_start __initdata;
22149 +static u32 omap_vram_sram_size __initdata;
22150 +
22151 +/* set from board file */
22152 +static u32 omap_vram_sdram_start __initdata;
22153 +static u32 omap_vram_sdram_size __initdata;
22154 +
22155 +/* set from kernel cmdline */
22156 +static u32 omap_vram_def_sdram_size __initdata;
22157 +static u32 omap_vram_def_sdram_start __initdata;
22158 +
22159 +static void __init omap_vram_early_vram(char **p)
22160 +{
22161 +       omap_vram_def_sdram_size = memparse(*p, p);
22162 +       if (**p == ',')
22163 +               omap_vram_def_sdram_start = simple_strtoul((*p) + 1, p, 16);
22164 +}
22165 +__early_param("vram=", omap_vram_early_vram);
22166 +
22167 +/*
22168 + * Called from map_io. We need to call to this early enough so that we
22169 + * can reserve the fixed SDRAM regions before VM could get hold of them.
22170 + */
22171 +void __init omap_vram_reserve_sdram(void)
22172 +{
22173 +       struct bootmem_data     *bdata;
22174 +       unsigned long           sdram_start, sdram_size;
22175 +       u32 paddr;
22176 +       u32 size = 0;
22177 +
22178 +       /* cmdline arg overrides the board file definition */
22179 +       if (omap_vram_def_sdram_size) {
22180 +               size = omap_vram_def_sdram_size;
22181 +               paddr = omap_vram_def_sdram_start;
22182 +       }
22183 +
22184 +       if (!size) {
22185 +               size = omap_vram_sdram_size;
22186 +               paddr = omap_vram_sdram_start;
22187 +       }
22188 +
22189 +#ifdef CONFIG_OMAP2_VRAM_SIZE
22190 +       if (!size) {
22191 +               size = CONFIG_OMAP2_VRAM_SIZE * 1024 * 1024;
22192 +               paddr = 0;
22193 +       }
22194 +#endif
22195 +
22196 +       if (!size)
22197 +               return;
22198 +
22199 +       size = PAGE_ALIGN(size);
22200 +
22201 +       bdata = NODE_DATA(0)->bdata;
22202 +       sdram_start = bdata->node_min_pfn << PAGE_SHIFT;
22203 +       sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start;
22204 +
22205 +       if (paddr) {
22206 +               if ((paddr & ~PAGE_MASK) || paddr < sdram_start ||
22207 +                               paddr + size > sdram_start + sdram_size) {
22208 +                       pr_err("Illegal SDRAM region for VRAM\n");
22209 +                       return;
22210 +               }
22211 +
22212 +               if (reserve_bootmem(paddr, size, BOOTMEM_EXCLUSIVE) < 0) {
22213 +                       pr_err("FB: failed to reserve VRAM\n");
22214 +                       return;
22215 +               }
22216 +       } else {
22217 +               if (size > sdram_size) {
22218 +                       pr_err("Illegal SDRAM size for VRAM\n");
22219 +                       return;
22220 +               }
22221 +
22222 +               paddr = virt_to_phys(alloc_bootmem_pages(size));
22223 +               BUG_ON(paddr & ~PAGE_MASK);
22224 +       }
22225 +
22226 +       omap_vram_add_region(paddr, size);
22227 +
22228 +       pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
22229 +}
22230 +
22231 +/*
22232 + * Called at sram init time, before anything is pushed to the SRAM stack.
22233 + * Because of the stack scheme, we will allocate everything from the
22234 + * start of the lowest address region to the end of SRAM. This will also
22235 + * include padding for page alignment and possible holes between regions.
22236 + *
22237 + * As opposed to the SDRAM case, we'll also do any dynamic allocations at
22238 + * this point, since the driver built as a module would have problem with
22239 + * freeing / reallocating the regions.
22240 + */
22241 +unsigned long __init omap_vram_reserve_sram(unsigned long sram_pstart,
22242 +                                 unsigned long sram_vstart,
22243 +                                 unsigned long sram_size,
22244 +                                 unsigned long pstart_avail,
22245 +                                 unsigned long size_avail)
22246 +{
22247 +       unsigned long                   pend_avail;
22248 +       unsigned long                   reserved;
22249 +       u32 paddr;
22250 +       u32 size;
22251 +
22252 +       paddr = omap_vram_sram_start;
22253 +       size = omap_vram_sram_size;
22254 +
22255 +       if (!size)
22256 +               return 0;
22257 +
22258 +       reserved = 0;
22259 +       pend_avail = pstart_avail + size_avail;
22260 +
22261 +       if (!paddr) {
22262 +               /* Dynamic allocation */
22263 +               if ((size_avail & PAGE_MASK) < size) {
22264 +                       pr_err("Not enough SRAM for VRAM\n");
22265 +                       return 0;
22266 +               }
22267 +               size_avail = (size_avail - size) & PAGE_MASK;
22268 +               paddr = pstart_avail + size_avail;
22269 +       }
22270 +
22271 +       if (paddr < sram_pstart ||
22272 +                       paddr + size > sram_pstart + sram_size) {
22273 +               pr_err("Illegal SRAM region for VRAM\n");
22274 +               return 0;
22275 +       }
22276 +
22277 +       /* Reserve everything above the start of the region. */
22278 +       if (pend_avail - paddr > reserved)
22279 +               reserved = pend_avail - paddr;
22280 +       size_avail = pend_avail - reserved - pstart_avail;
22281 +
22282 +       omap_vram_add_region(paddr, size);
22283 +
22284 +       if (reserved)
22285 +               pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved);
22286 +
22287 +       return reserved;
22288 +}
22289 +
22290 +void __init omap_vram_set_sdram_vram(u32 size, u32 start)
22291 +{
22292 +       omap_vram_sdram_start = start;
22293 +       omap_vram_sdram_size = size;
22294 +}
22295 +
22296 +void __init omap_vram_set_sram_vram(u32 size, u32 start)
22297 +{
22298 +       omap_vram_sram_start = start;
22299 +       omap_vram_sram_size = size;
22300 +}
22301 diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c
22302 new file mode 100644
22303 index 0000000..8726689
22304 --- /dev/null
22305 +++ b/drivers/video/omap2/vrfb.c
22306 @@ -0,0 +1,277 @@
22307 +/*
22308 + * VRFB Rotation Engine
22309 + *
22310 + * Copyright (C) 2009 Nokia Corporation
22311 + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
22312 + *
22313 + * This program is free software; you can redistribute it and/or modify
22314 + * it under the terms of the GNU General Public License version 2 as
22315 + * published by the Free Software Foundation.
22316 + *
22317 + * This program is distributed in the hope that it will be useful, but
22318 + * WITHOUT ANY WARRANTY; without even the implied warranty of
22319 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22320 + * General Public License for more details.
22321 + *
22322 + * You should have received a copy of the GNU General Public License along
22323 + * with this program; if not, write to the Free Software Foundation, Inc.,
22324 + * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22325 + */
22326 +
22327 +#include <linux/kernel.h>
22328 +#include <linux/module.h>
22329 +#include <linux/ioport.h>
22330 +#include <linux/io.h>
22331 +#include <linux/bitops.h>
22332 +#include <linux/mutex.h>
22333 +
22334 +#include <mach/io.h>
22335 +#include <mach/vrfb.h>
22336 +#include <mach/sdrc.h>
22337 +/*#define DEBUG*/
22338 +
22339 +#ifdef DEBUG
22340 +#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
22341 +#else
22342 +#define DBG(format, ...)
22343 +#endif
22344 +
22345 +#define SMS_ROT_VIRT_BASE(context, rot) \
22346 +       (((context >= 4) ? 0xD0000000 : 0x70000000) \
22347 +        + (0x4000000 * (context)) \
22348 +        + (0x1000000 * (rot)))
22349 +
22350 +#define OMAP_VRFB_SIZE                 (2048 * 2048 * 4)
22351 +
22352 +#define VRFB_PAGE_WIDTH_EXP    5 /* Assuming SDRAM pagesize= 1024 */
22353 +#define VRFB_PAGE_HEIGHT_EXP   5 /* 1024 = 2^5 * 2^5 */
22354 +#define VRFB_PAGE_WIDTH                (1 << VRFB_PAGE_WIDTH_EXP)
22355 +#define VRFB_PAGE_HEIGHT       (1 << VRFB_PAGE_HEIGHT_EXP)
22356 +#define SMS_IMAGEHEIGHT_OFFSET 16
22357 +#define SMS_IMAGEWIDTH_OFFSET  0
22358 +#define SMS_PH_OFFSET          8
22359 +#define SMS_PW_OFFSET          4
22360 +#define SMS_PS_OFFSET          0
22361 +
22362 +#define VRFB_NUM_CTXS 12
22363 +/* bitmap of reserved contexts */
22364 +static unsigned long ctx_map;
22365 +/* bitmap of contexts for which we have to keep the HW context valid */
22366 +static unsigned long ctx_map_active;
22367 +
22368 +static DEFINE_MUTEX(ctx_lock);
22369 +
22370 +/*
22371 + * Access to this happens from client drivers or the PM core after wake-up.
22372 + * For the first case we require locking at the driver level, for the second
22373 + * we don't need locking, since no drivers will run until after the wake-up
22374 + * has finished.
22375 + */
22376 +static struct {
22377 +       u32 physical_ba;
22378 +       u32 control;
22379 +       u32 size;
22380 +} vrfb_hw_context[VRFB_NUM_CTXS];
22381 +
22382 +static inline void restore_hw_context(int ctx)
22383 +{
22384 +       omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx);
22385 +       omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx);
22386 +       omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx);
22387 +}
22388 +
22389 +void omap_vrfb_restore_context(void)
22390 +{
22391 +       int i;
22392 +       unsigned long map = ctx_map_active;
22393 +
22394 +       for (i = ffs(map); i; i = ffs(map)) {
22395 +               /* i=1..32 */
22396 +               i--;
22397 +               map &= ~(1 << i);
22398 +               restore_hw_context(i);
22399 +       }
22400 +}
22401 +
22402 +void omap_vrfb_adjust_size(u16 *width, u16 *height,
22403 +               u8 bytespp)
22404 +{
22405 +       *width = ALIGN(*width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
22406 +       *height = ALIGN(*height, VRFB_PAGE_HEIGHT);
22407 +}
22408 +EXPORT_SYMBOL(omap_vrfb_adjust_size);
22409 +
22410 +void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
22411 +               u16 width, u16 height,
22412 +               unsigned bytespp, bool yuv_mode)
22413 +{
22414 +       unsigned pixel_size_exp;
22415 +       u16 vrfb_width;
22416 +       u16 vrfb_height;
22417 +       u8 ctx = vrfb->context;
22418 +       u32 size;
22419 +       u32 control;
22420 +
22421 +       DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d)\n", ctx, paddr,
22422 +                       width, height, color_mode);
22423 +
22424 +       /* For YUV2 and UYVY modes VRFB needs to handle pixels a bit
22425 +        * differently. See TRM. */
22426 +       if (yuv_mode) {
22427 +               bytespp *= 2;
22428 +               width /= 2;
22429 +       }
22430 +
22431 +       if (bytespp == 4)
22432 +               pixel_size_exp = 2;
22433 +       else if (bytespp == 2)
22434 +               pixel_size_exp = 1;
22435 +       else
22436 +               BUG();
22437 +
22438 +       vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
22439 +       vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT);
22440 +
22441 +       DBG("vrfb w %u, h %u bytespp %d\n", vrfb_width, vrfb_height, bytespp);
22442 +
22443 +       size  = vrfb_width << SMS_IMAGEWIDTH_OFFSET;
22444 +       size |= vrfb_height << SMS_IMAGEHEIGHT_OFFSET;
22445 +
22446 +       control  = pixel_size_exp << SMS_PS_OFFSET;
22447 +       control |= VRFB_PAGE_WIDTH_EXP  << SMS_PW_OFFSET;
22448 +       control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
22449 +
22450 +       vrfb_hw_context[ctx].physical_ba = paddr;
22451 +       vrfb_hw_context[ctx].size = size;
22452 +       vrfb_hw_context[ctx].control = control;
22453 +
22454 +       omap2_sms_write_rot_physical_ba(paddr, ctx);
22455 +       omap2_sms_write_rot_size(size, ctx);
22456 +       omap2_sms_write_rot_control(control, ctx);
22457 +
22458 +       DBG("vrfb offset pixels %d, %d\n",
22459 +                       vrfb_width - width, vrfb_height - height);
22460 +
22461 +       vrfb->xoffset = vrfb_width - width;
22462 +       vrfb->yoffset = vrfb_height - height;
22463 +       vrfb->bytespp = bytespp;
22464 +}
22465 +EXPORT_SYMBOL(omap_vrfb_setup);
22466 +
22467 +void omap_vrfb_release_ctx(struct vrfb *vrfb)
22468 +{
22469 +       int rot;
22470 +       int ctx = vrfb->context;
22471 +
22472 +       if (ctx == 0xff)
22473 +               return;
22474 +
22475 +       DBG("release ctx %d\n", ctx);
22476 +
22477 +       mutex_lock(&ctx_lock);
22478 +
22479 +       BUG_ON(!(ctx_map & (1 << ctx)));
22480 +
22481 +       clear_bit(ctx, &ctx_map_active);
22482 +       clear_bit(ctx, &ctx_map);
22483 +
22484 +       for (rot = 0; rot < 4; ++rot) {
22485 +               if (vrfb->paddr[rot]) {
22486 +                       release_mem_region(vrfb->paddr[rot], OMAP_VRFB_SIZE);
22487 +                       vrfb->paddr[rot] = 0;
22488 +               }
22489 +       }
22490 +
22491 +       vrfb->context = 0xff;
22492 +
22493 +       mutex_unlock(&ctx_lock);
22494 +}
22495 +EXPORT_SYMBOL(omap_vrfb_release_ctx);
22496 +
22497 +int omap_vrfb_request_ctx(struct vrfb *vrfb)
22498 +{
22499 +       int rot;
22500 +       u32 paddr;
22501 +       u8 ctx;
22502 +       int r;
22503 +
22504 +       DBG("request ctx\n");
22505 +
22506 +       mutex_lock(&ctx_lock);
22507 +
22508 +       for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
22509 +               if ((ctx_map & (1 << ctx)) == 0)
22510 +                       break;
22511 +
22512 +       if (ctx == VRFB_NUM_CTXS) {
22513 +               pr_err("vrfb: no free contexts\n");
22514 +               r = -EBUSY;
22515 +               goto out;
22516 +       }
22517 +
22518 +       DBG("found free ctx %d\n", ctx);
22519 +
22520 +       set_bit(ctx, &ctx_map);
22521 +       WARN_ON(ctx_map_active & (1 << ctx));
22522 +       set_bit(ctx, &ctx_map_active);
22523 +
22524 +       memset(vrfb, 0, sizeof(*vrfb));
22525 +
22526 +       vrfb->context = ctx;
22527 +
22528 +       for (rot = 0; rot < 4; ++rot) {
22529 +               paddr = SMS_ROT_VIRT_BASE(ctx, rot);
22530 +               if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
22531 +                       pr_err("vrfb: failed to reserve VRFB "
22532 +                                       "area for ctx %d, rotation %d\n",
22533 +                                       ctx, rot * 90);
22534 +                       omap_vrfb_release_ctx(vrfb);
22535 +                       r = -ENOMEM;
22536 +                       goto out;
22537 +               }
22538 +
22539 +               vrfb->paddr[rot] = paddr;
22540 +
22541 +               DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]);
22542 +       }
22543 +
22544 +       r = 0;
22545 +out:
22546 +       mutex_unlock(&ctx_lock);
22547 +       return r;
22548 +}
22549 +EXPORT_SYMBOL(omap_vrfb_request_ctx);
22550 +
22551 +void omap_vrfb_suspend_ctx(struct vrfb *vrfb)
22552 +{
22553 +       DBG("suspend ctx %d\n", vrfb->context);
22554 +       mutex_lock(&ctx_lock);
22555 +
22556 +       BUG_ON(vrfb->context >= VRFB_NUM_CTXS);
22557 +       BUG_ON(!((1 << vrfb->context) & ctx_map_active));
22558 +
22559 +       clear_bit(vrfb->context, &ctx_map_active);
22560 +       mutex_unlock(&ctx_lock);
22561 +}
22562 +EXPORT_SYMBOL(omap_vrfb_suspend_ctx);
22563 +
22564 +void omap_vrfb_resume_ctx(struct vrfb *vrfb)
22565 +{
22566 +       DBG("resume ctx %d\n", vrfb->context);
22567 +       mutex_lock(&ctx_lock);
22568 +
22569 +       BUG_ON(vrfb->context >= VRFB_NUM_CTXS);
22570 +       BUG_ON((1 << vrfb->context) & ctx_map_active);
22571 +
22572 +       /*
22573 +        * omap_vrfb_restore_context is normally called by the core domain
22574 +        * save / restore logic, but since this VRFB context was suspended
22575 +        * those calls didn't actually restore the context and now we might
22576 +        * have an invalid context. Do an explicit restore here.
22577 +        */
22578 +       restore_hw_context(vrfb->context);
22579 +       set_bit(vrfb->context, &ctx_map_active);
22580 +       mutex_unlock(&ctx_lock);
22581 +}
22582 +EXPORT_SYMBOL(omap_vrfb_resume_ctx);
22583 +
22584 diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h
22585 new file mode 100644
22586 index 0000000..52e0987
22587 --- /dev/null
22588 +++ b/include/linux/omapfb.h
22589 @@ -0,0 +1,242 @@
22590 +/*
22591 + * File: include/linux/omapfb.h
22592 + *
22593 + * Framebuffer driver for TI OMAP boards
22594 + *
22595 + * Copyright (C) 2004 Nokia Corporation
22596 + * Author: Imre Deak <imre.deak@nokia.com>
22597 + *
22598 + * This program is free software; you can redistribute it and/or modify it
22599 + * under the terms of the GNU General Public License as published by the
22600 + * Free Software Foundation; either version 2 of the License, or (at your
22601 + * option) any later version.
22602 + *
22603 + * This program is distributed in the hope that it will be useful, but
22604 + * WITHOUT ANY WARRANTY; without even the implied warranty of
22605 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22606 + * General Public License for more details.
22607 + *
22608 + * You should have received a copy of the GNU General Public License along
22609 + * with this program; if not, write to the Free Software Foundation, Inc.,
22610 + * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22611 + */
22612 +
22613 +#ifndef __LINUX_OMAPFB_H__
22614 +#define __LINUX_OMAPFB_H__
22615 +
22616 +#include <linux/fb.h>
22617 +#include <linux/ioctl.h>
22618 +#include <linux/types.h>
22619 +
22620 +/* IOCTL commands. */
22621 +
22622 +#define OMAP_IOW(num, dtype)   _IOW('O', num, dtype)
22623 +#define OMAP_IOR(num, dtype)   _IOR('O', num, dtype)
22624 +#define OMAP_IOWR(num, dtype)  _IOWR('O', num, dtype)
22625 +#define OMAP_IO(num)           _IO('O', num)
22626 +
22627 +#define OMAPFB_MIRROR          OMAP_IOW(31, int)
22628 +#define OMAPFB_SYNC_GFX                OMAP_IO(37)
22629 +#define OMAPFB_VSYNC           OMAP_IO(38)
22630 +#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int)
22631 +#define OMAPFB_GET_CAPS                OMAP_IOR(42, struct omapfb_caps)
22632 +#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int)
22633 +#define OMAPFB_LCD_TEST                OMAP_IOW(45, int)
22634 +#define OMAPFB_CTRL_TEST       OMAP_IOW(46, int)
22635 +#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old)
22636 +#define OMAPFB_SET_COLOR_KEY   OMAP_IOW(50, struct omapfb_color_key)
22637 +#define OMAPFB_GET_COLOR_KEY   OMAP_IOW(51, struct omapfb_color_key)
22638 +#define OMAPFB_SETUP_PLANE     OMAP_IOW(52, struct omapfb_plane_info)
22639 +#define OMAPFB_QUERY_PLANE     OMAP_IOW(53, struct omapfb_plane_info)
22640 +#define OMAPFB_UPDATE_WINDOW   OMAP_IOW(54, struct omapfb_update_window)
22641 +#define OMAPFB_SETUP_MEM       OMAP_IOW(55, struct omapfb_mem_info)
22642 +#define OMAPFB_QUERY_MEM       OMAP_IOW(56, struct omapfb_mem_info)
22643 +#define OMAPFB_WAITFORVSYNC    OMAP_IO(57)
22644 +#define OMAPFB_MEMORY_READ     OMAP_IOR(58, struct omapfb_memory_read)
22645 +#define OMAPFB_GET_OVERLAY_COLORMODE OMAP_IOR(59, struct omapfb_ovl_colormode)
22646 +#define OMAPFB_WAITFORGO       OMAP_IO(60)
22647 +#define OMAPFB_GET_VRAM_INFO   OMAP_IOR(61, struct omapfb_vram_info)
22648 +
22649 +#define OMAPFB_CAPS_GENERIC_MASK       0x00000fff
22650 +#define OMAPFB_CAPS_LCDC_MASK          0x00fff000
22651 +#define OMAPFB_CAPS_PANEL_MASK         0xff000000
22652 +
22653 +#define OMAPFB_CAPS_MANUAL_UPDATE      0x00001000
22654 +#define OMAPFB_CAPS_TEARSYNC           0x00002000
22655 +#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000
22656 +#define OMAPFB_CAPS_PLANE_SCALE                0x00008000
22657 +#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE        0x00010000
22658 +#define OMAPFB_CAPS_WINDOW_SCALE       0x00020000
22659 +#define OMAPFB_CAPS_WINDOW_OVERLAY     0x00040000
22660 +#define OMAPFB_CAPS_WINDOW_ROTATE      0x00080000
22661 +#define OMAPFB_CAPS_SET_BACKLIGHT      0x01000000
22662 +
22663 +/* Values from DSP must map to lower 16-bits */
22664 +#define OMAPFB_FORMAT_MASK             0x00ff
22665 +#define OMAPFB_FORMAT_FLAG_DOUBLE      0x0100
22666 +#define OMAPFB_FORMAT_FLAG_TEARSYNC    0x0200
22667 +#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400
22668 +#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY      0x0800
22669 +#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY     0x1000
22670 +
22671 +#define OMAPFB_MEMTYPE_SDRAM           0
22672 +#define OMAPFB_MEMTYPE_SRAM            1
22673 +#define OMAPFB_MEMTYPE_MAX             1
22674 +
22675 +enum omapfb_color_format {
22676 +       OMAPFB_COLOR_RGB565 = 0,
22677 +       OMAPFB_COLOR_YUV422,
22678 +       OMAPFB_COLOR_YUV420,
22679 +       OMAPFB_COLOR_CLUT_8BPP,
22680 +       OMAPFB_COLOR_CLUT_4BPP,
22681 +       OMAPFB_COLOR_CLUT_2BPP,
22682 +       OMAPFB_COLOR_CLUT_1BPP,
22683 +       OMAPFB_COLOR_RGB444,
22684 +       OMAPFB_COLOR_YUY422,
22685 +
22686 +       OMAPFB_COLOR_ARGB16,
22687 +       OMAPFB_COLOR_RGB24U,    /* RGB24, 32-bit container */
22688 +       OMAPFB_COLOR_RGB24P,    /* RGB24, 24-bit container */
22689 +       OMAPFB_COLOR_ARGB32,
22690 +       OMAPFB_COLOR_RGBA32,
22691 +       OMAPFB_COLOR_RGBX32,
22692 +};
22693 +
22694 +struct omapfb_update_window {
22695 +       __u32 x, y;
22696 +       __u32 width, height;
22697 +       __u32 format;
22698 +       __u32 out_x, out_y;
22699 +       __u32 out_width, out_height;
22700 +       __u32 reserved[8];
22701 +};
22702 +
22703 +struct omapfb_update_window_old {
22704 +       __u32 x, y;
22705 +       __u32 width, height;
22706 +       __u32 format;
22707 +};
22708 +
22709 +enum omapfb_plane {
22710 +       OMAPFB_PLANE_GFX = 0,
22711 +       OMAPFB_PLANE_VID1,
22712 +       OMAPFB_PLANE_VID2,
22713 +};
22714 +
22715 +enum omapfb_channel_out {
22716 +       OMAPFB_CHANNEL_OUT_LCD = 0,
22717 +       OMAPFB_CHANNEL_OUT_DIGIT,
22718 +};
22719 +
22720 +struct omapfb_plane_info {
22721 +       __u32 pos_x;
22722 +       __u32 pos_y;
22723 +       __u8  enabled;
22724 +       __u8  channel_out;
22725 +       __u8  mirror;
22726 +       __u8  reserved1;
22727 +       __u32 out_width;
22728 +       __u32 out_height;
22729 +       __u32 reserved2[12];
22730 +};
22731 +
22732 +struct omapfb_mem_info {
22733 +       __u32 size;
22734 +       __u8  type;
22735 +       __u8  reserved[3];
22736 +};
22737 +
22738 +struct omapfb_caps {
22739 +       __u32 ctrl;
22740 +       __u32 plane_color;
22741 +       __u32 wnd_color;
22742 +};
22743 +
22744 +enum omapfb_color_key_type {
22745 +       OMAPFB_COLOR_KEY_DISABLED = 0,
22746 +       OMAPFB_COLOR_KEY_GFX_DST,
22747 +       OMAPFB_COLOR_KEY_VID_SRC,
22748 +};
22749 +
22750 +struct omapfb_color_key {
22751 +       __u8  channel_out;
22752 +       __u32 background;
22753 +       __u32 trans_key;
22754 +       __u8  key_type;
22755 +};
22756 +
22757 +enum omapfb_update_mode {
22758 +       OMAPFB_UPDATE_DISABLED = 0,
22759 +       OMAPFB_AUTO_UPDATE,
22760 +       OMAPFB_MANUAL_UPDATE
22761 +};
22762 +
22763 +struct omapfb_memory_read {
22764 +       __u16 x;
22765 +       __u16 y;
22766 +       __u16 w;
22767 +       __u16 h;
22768 +       size_t buffer_size;
22769 +       void __user *buffer;
22770 +};
22771 +
22772 +struct omapfb_ovl_colormode {
22773 +       __u8 overlay_idx;
22774 +       __u8 mode_idx;
22775 +       __u32 bits_per_pixel;
22776 +       __u32 nonstd;
22777 +       struct fb_bitfield red;
22778 +       struct fb_bitfield green;
22779 +       struct fb_bitfield blue;
22780 +       struct fb_bitfield transp;
22781 +};
22782 +
22783 +struct omapfb_vram_info {
22784 +       __u32 total;
22785 +       __u32 free;
22786 +       __u32 largest_free_block;
22787 +       __u32 reserved[5];
22788 +};
22789 +
22790 +#ifdef __KERNEL__
22791 +
22792 +#include <mach/board.h>
22793 +
22794 +#ifdef CONFIG_ARCH_OMAP1
22795 +#define OMAPFB_PLANE_NUM               1
22796 +#else
22797 +#define OMAPFB_PLANE_NUM               3
22798 +#endif
22799 +
22800 +struct omapfb_mem_region {
22801 +       u32             paddr;
22802 +       void __iomem    *vaddr;
22803 +       unsigned long   size;
22804 +       u8              type;           /* OMAPFB_PLANE_MEM_* */
22805 +       enum omapfb_color_format format;/* OMAPFB_COLOR_* */
22806 +       unsigned        format_used:1;  /* Must be set when format is set.
22807 +                                        * Needed b/c of the badly chosen 0
22808 +                                        * base for OMAPFB_COLOR_* values
22809 +                                        */
22810 +       unsigned        alloc:1;        /* allocated by the driver */
22811 +       unsigned        map:1;          /* kernel mapped by the driver */
22812 +};
22813 +
22814 +struct omapfb_mem_desc {
22815 +       int                             region_cnt;
22816 +       struct omapfb_mem_region        region[OMAPFB_PLANE_NUM];
22817 +};
22818 +
22819 +struct omapfb_platform_data {
22820 +       struct omap_lcd_config          lcd;
22821 +       struct omapfb_mem_desc          mem_desc;
22822 +       void                            *ctrl_platform_data;
22823 +};
22824 +
22825 +/* in arch/arm/plat-omap/fb.c */
22826 +extern void omapfb_set_ctrl_platform_data(void *pdata);
22827 +extern void omapfb_reserve_sdram(void);
22828 +
22829 +#endif
22830 +
22831 +#endif /* __OMAPFB_H */