diff options
| author | Koen Kooi <koen@openembedded.org> | 2009-01-07 15:01:21 +0100 |
|---|---|---|
| committer | Koen Kooi <koen@openembedded.org> | 2009-01-07 15:09:36 +0100 |
| commit | d45651ebb1a1ac66b850a35f16b2a58d14b56ec2 (patch) | |
| tree | a874ca98b3fc7b61dc23a49b3a3c6ecbeb00a963 /packages | |
| parent | 7c93a979f724a002033cf8a6511b0707966939b7 (diff) | |
linux-omap 2.6.28: update to newer DSS2 snapshot
Diffstat (limited to 'packages')
18 files changed, 6152 insertions, 2369 deletions
diff --git a/packages/linux/linux-omap-2.6.28/0004-DSS-New-display-subsystem-driver-for-OMAP2-3.patch b/packages/linux/linux-omap-2.6.28/0001-DSS-New-display-subsystem-driver-for-OMAP2-3.patch index 661106b4ad..fda5191421 100644 --- a/packages/linux/linux-omap-2.6.28/0004-DSS-New-display-subsystem-driver-for-OMAP2-3.patch +++ b/packages/linux/linux-omap-2.6.28/0001-DSS-New-display-subsystem-driver-for-OMAP2-3.patch @@ -1,25 +1,27 @@ -From 491d4b0389fb95e43017b7d4d07d866b114f6c7d Mon Sep 17 00:00:00 2001 +From 3128e95ff7e6a1bed47cc5c64a138cc3bbab492a Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen <tomi.valkeinen@nokia.com> -Date: Mon, 8 Dec 2008 13:43:36 +0200 +Date: Wed, 7 Jan 2009 14:30:09 +0200 Subject: [PATCH] DSS: New display subsystem driver for OMAP2/3 Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> --- + Documentation/arm/OMAP/DSS | 266 +++ arch/arm/plat-omap/Kconfig | 2 + arch/arm/plat-omap/Makefile | 2 + - arch/arm/plat-omap/dss/Kconfig | 66 + + arch/arm/plat-omap/dss/Kconfig | 69 + arch/arm/plat-omap/dss/Makefile | 6 + - arch/arm/plat-omap/dss/dispc.c | 2021 +++++++++++++++++++ - arch/arm/plat-omap/dss/display.c | 765 +++++++ - arch/arm/plat-omap/dss/dpi.c | 320 +++ - arch/arm/plat-omap/dss/dsi.c | 3135 +++++++++++++++++++++++++++++ - arch/arm/plat-omap/dss/dss.c | 789 ++++++++ - arch/arm/plat-omap/dss/dss.h | 268 +++ - arch/arm/plat-omap/dss/rfbi.c | 1225 +++++++++++ - arch/arm/plat-omap/dss/sdi.c | 150 ++ - arch/arm/plat-omap/dss/venc.c | 501 +++++ - arch/arm/plat-omap/include/mach/display.h | 463 +++++ - 14 files changed, 9713 insertions(+), 0 deletions(-) + arch/arm/plat-omap/dss/dispc.c | 2113 +++++++++++++++++++ + arch/arm/plat-omap/dss/display.c | 787 +++++++ + arch/arm/plat-omap/dss/dpi.c | 344 ++++ + arch/arm/plat-omap/dss/dsi.c | 3187 +++++++++++++++++++++++++++++ + arch/arm/plat-omap/dss/dss.c | 774 +++++++ + arch/arm/plat-omap/dss/dss.h | 274 +++ + arch/arm/plat-omap/dss/rfbi.c | 1262 ++++++++++++ + arch/arm/plat-omap/dss/sdi.c | 174 ++ + arch/arm/plat-omap/dss/venc.c | 506 +++++ + arch/arm/plat-omap/include/mach/display.h | 462 +++++ + 15 files changed, 10228 insertions(+), 0 deletions(-) + create mode 100644 Documentation/arm/OMAP/DSS create mode 100644 arch/arm/plat-omap/dss/Kconfig create mode 100644 arch/arm/plat-omap/dss/Makefile create mode 100644 arch/arm/plat-omap/dss/dispc.c @@ -33,8 +35,280 @@ Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> create mode 100644 arch/arm/plat-omap/dss/venc.c create mode 100644 arch/arm/plat-omap/include/mach/display.h +diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS +new file mode 100644 +index 0000000..a5e608c +--- /dev/null ++++ b/Documentation/arm/OMAP/DSS +@@ -0,0 +1,266 @@ ++OMAP2/3 Display Subsystem ++------------------------- ++ ++This is an almost total rewrite of the OMAP FB driver in drivers/video/omap ++(let's call it DSS1). The main differences between DSS1 and DSS2 are DSI, ++TV-out and multiple display support. ++ ++The DSS2 driver (omap-dss module) is in arch/arm/plat-omap/dss/, and the FB, ++panel and controller drivers are in drivers/video/omap2/. DSS1 and DSS2 live ++currently side by side, you can choose which one to use. ++ ++Features ++-------- ++ ++Working and tested features include: ++ ++- MIPI DPI (parallel) output ++- MIPI DSI output in command mode ++- MIPI DBI (RFBI) output (not tested for a while, might've gotten broken) ++- SDI output ++- TV output ++- All pieces can be compiled as a module or inside kernel ++- Use DISPC to update any of the outputs ++- Use CPU to update RFBI or DSI output ++- OMAP DISPC planes ++- RGB16, RGB24 packed, RGB24 unpacked ++- YUV2, UYVY ++- Scaling ++- Adjusting DSS FCK to find a good pixel clock ++- Use DSI DPLL to create DSS FCK ++ ++omap-dss driver ++------------ ++ ++The DSS driver does not itself have any support for Linux framebuffer, V4L or ++such like the current ones, but it has an internal kernel API that upper level ++drivers can use. ++ ++The DSS driver models OMAP's overlays, overlay managers and displays in a ++flexible way to enable non-common multi-display configuration. In addition to ++modelling the hardware overlays, omap-dss supports virtual overlays and overlay ++managers. These can be used when updating a display with CPU or system DMA. ++ ++Panel and controller drivers ++---------------------------- ++ ++The drivers implement panel or controller specific functionality and are not ++visible to users except through omapfb driver. They register themselves to the ++DSS driver. ++ ++omapfb driver ++------------- ++ ++The omapfb driver implements arbitrary number of standard linux framebuffers. ++These framebuffers can be routed flexibly to any overlays, thus allowing very ++dynamic display architecture. ++ ++The driver exports some omapfb specific ioctls, which are compatible with the ++ioctls in the old driver. ++ ++The rest of the non standard features are exported via sysfs. Whether the final ++implementation will use sysfs, or ioctls, is still open. ++ ++V4L2 drivers ++------------ ++ ++Currently there are no V4L2 display drivers planned, but it is possible to ++implement such either to omapfb driver, or as a separate one. From omap-dss ++point of view the V4L2 drivers should be similar to framebuffer driver. ++ ++Architecture ++-------------------- ++ ++Some clarification what the different components do: ++ ++ - Framebuffer is a memory area inside OMAP's SDRAM that contains the pixel ++ data for the image. Framebuffer has width and height and color depth. ++ - Overlay defines where the pixels are read from and where they go on the ++ screen. The overlay may be smaller than framebuffer, thus displaying only ++ part of the framebuffer. The position of the overlay may be changed if ++ the overlay is smaller than the display. ++ - Overlay manager combines the overlays in to one image and feeds them to ++ display. ++ - Display is the actual physical display device. ++ ++A framebuffer can be connected to multiple overlays to show the same pixel data ++on all of the overlays. Note that in this case the overlay input sizes must be ++the same, but, in case of video overlays, the output size can be different. Any ++framebuffer can be connected to any overlay. ++ ++An overlay can be connected to one overlay manager. Also DISPC overlays can be ++connected only to DISPC overlay managers, and virtual overlays can be only ++connected to virtual overlays. ++ ++An overlay manager can be connected to one display. There are certain ++restrictions which kinds of displays an overlay manager can be connected: ++ ++ - DISPC TV overlay manager can be only connected to TV display. ++ - Virtual overlay managers can only be connected to DBI or DSI displays. ++ - DISPC LCD overlay manager can be connected to all displays, except TV ++ display. ++ ++Sysfs ++----- ++The sysfs interface is a hack, but works for testing. I don't think sysfs ++interface is the best for this in the final version, but I don't quite know ++what would be the best interfaces for these things. ++ ++In /sys/devices/platform/omapfb we have four files: framebuffers, ++overlays, managers and displays. You can read them so see the current ++setup, and change them by writing to it in the form of ++"<item-id> <opt1>:<val1> <opt2>:<val2>..." ++ ++"framebuffers" lists all framebuffers. Its format is: ++ <fb number> ++ p:<physical address, read only> ++ v:<virtual address, read only> ++ s:<size, read only> ++ t:<target overlay> ++ ++"overlays" lists all overlays. Its format is: ++ <overlay name> ++ t:<target manager> ++ x:<xpos> ++ y:<ypos> ++ iw:<input width, read only> ++ ih:<input height, read only> ++ w:<output width> ++ h:<output height> ++ e:<enabled> ++ ++"managers" lists all overlay managers. Its format is: ++ <manager name> ++ t:<target display> ++ ++"displays" lists all displays. Its format is: ++ <display name> ++ e:<enabled> ++ u:<update mode> ++ t:<tear sync on/off> ++ h:<xres/hfp/hbp/hsw> ++ v:<yres/vfp/vbp/vsw> ++ p:<pix clock, in kHz> ++ m:<mode str, as in drivers/video/modedb.c:fb_find_mode> ++ ++There is also a debug sysfs file at /sys/devices/platform/omap-dss/clk which ++shows how DSS has configured the clocks. ++ ++Examples ++-------- ++ ++In the example scripts "omapfb" is a symlink to /sys/devices/platform/omapfb/. ++ ++Default setup on OMAP3 SDP ++-------------------------- ++ ++Here's the default setup on OMAP3 SDP board. All planes go to LCD. DVI ++and TV-out are not in use. The columns from left to right are: ++framebuffers, overlays, overlay managers, displays. Framebuffers are ++handled by omapfb, and the rest by the DSS. ++ ++FB0 --- GFX -\ DVI ++FB1 --- VID1 --+- LCD ---- LCD ++FB2 --- VID2 -/ TV ----- TV ++ ++Switch from LCD to DVI ++---------------------- ++ ++dviline=`cat omapfb/displays |grep dvi` ++w=`echo $dviline | cut -d " " -f 5 | cut -d ":" -f 2 | cut -d "/" -f 1` ++h=`echo $dviline | cut -d " " -f 6 | cut -d ":" -f 2 | cut -d "/" -f 1` ++ ++echo "lcd e:0" > omapfb/displays ++echo "lcd t:none" > omapfb/managers ++fbset -fb /dev/fb0 -xres $w -yres $h ++# at this point you have to switch the dvi/lcd dip-switch from the omap board ++echo "lcd t:dvi" > omapfb/managers ++echo "dvi e:1" > omapfb/displays ++ ++After this the configuration looks like: ++ ++FB0 --- GFX -\ -- DVI ++FB1 --- VID1 --+- LCD -/ LCD ++FB2 --- VID2 -/ TV ----- TV ++ ++Clone GFX overlay to LCD and TV ++------------------------------- ++ ++tvline=`cat /sys/devices/platform/omapfb/displays |grep tv` ++w=`echo $tvline | cut -d " " -f 5 | cut -d ":" -f 2 | cut -d "/" -f 1` ++h=`echo $tvline | cut -d " " -f 6 | cut -d ":" -f 2 | cut -d "/" -f 1` ++ ++echo "1 t:none" > omapfb/framebuffers ++echo "0 t:gfx,vid1" > omapfb/framebuffers ++echo "gfx e:1" > omapfb/overlays ++echo "vid1 t:tv w:$w h:$h e:1" > omapfb/overlays ++echo "tv e:1" > omapfb/displays ++ ++After this the configuration looks like (only relevant parts shown): ++ ++FB0 +-- GFX ---- LCD ---- LCD ++ \- VID1 ---- TV ---- TV ++ ++Misc notes ++---------- ++ ++OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator. If ++that fails, it will fall back to dma_alloc_writecombine(). ++ ++Using DSI DPLL to generate pixel clock it is possible produce the pixel clock ++of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI. ++ ++Arguments ++--------- ++ ++vram ++ - Amount of total VRAM to preallocate. For example, "10M". ++ ++omapfb.video_mode ++ - Default video mode for default display. For example, ++ "800x400MR-24@60". See drivers/video/modedb.c ++ ++omapfb.vram ++ - VRAM allocated for each framebuffer. Normally omapfb allocates vram ++ depending on the display size. With this you can manually allocate ++ more. For example "4M,3M" allocates 4M for fb0, 3M for fb1. ++ ++omapfb.debug ++ - Enable debug printing. You have to have OMAPFB debug support enabled ++ in kernel config. ++ ++omap-dss.def_disp ++ - Name of default display, to which all overlays will be connected. ++ Common examples are "lcd" or "tv". ++ ++omap-dss.debug ++ - Enable debug printing. You have to have DSS debug support enabled in ++ kernel config. ++ ++TODO ++---- ++ ++DSS locking ++ ++Error checking ++- Lots of checks are missing or implemented just as BUG() ++ ++Rotate (external FB) ++Rotate (VRFB) ++Rotate (SMS) ++ ++System DMA update for DSI ++- Can be used for RGB16 and RGB24P modes. Probably not for RGB24U (how ++ to skip the empty byte?) ++ ++Power management ++- Context saving ++ ++Resolution change ++- The x/y res of the framebuffer are not display resolutions, but the size ++ of the overlay. ++- The display resolution affects all planes on the display. ++ ++OMAP1 support ++- Not sure if needed ++ diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig -index 960c13f..4e90667 100644 +index 2465aea..cd7d9e2 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -245,6 +245,8 @@ config OMAP_SERIAL_WAKE @@ -58,10 +332,10 @@ index 1259846..2740497 100644 +obj-y += dss/ diff --git a/arch/arm/plat-omap/dss/Kconfig b/arch/arm/plat-omap/dss/Kconfig new file mode 100644 -index 0000000..ef0b5d9 +index 0000000..6b342df --- /dev/null +++ b/arch/arm/plat-omap/dss/Kconfig -@@ -0,0 +1,66 @@ +@@ -0,0 +1,69 @@ +config OMAP2_DSS + tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)" + depends on ARCH_OMAP2 || ARCH_OMAP3 @@ -70,9 +344,12 @@ index 0000000..ef0b5d9 + +if OMAP2_DSS + -+config OMAP2_DSS_DEBUG -+ bool "Debug output" -+ default n ++config OMAP2_DSS_DEBUG_SUPPORT ++ bool "Debug support" ++ default y ++ help ++ This enables debug messages. You need to enable printing ++ with 'debug' module parameter. + +config OMAP2_DSS_RFBI + bool "RFBI support" @@ -142,10 +419,10 @@ index 0000000..e98c6c1 +omap-dss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o diff --git a/arch/arm/plat-omap/dss/dispc.c b/arch/arm/plat-omap/dss/dispc.c new file mode 100644 -index 0000000..33fbd0a +index 0000000..20caa48 --- /dev/null +++ b/arch/arm/plat-omap/dss/dispc.c -@@ -0,0 +1,2021 @@ +@@ -0,0 +1,2113 @@ +/* + * linux/arch/arm/plat-omap/dss/dispc.c + * @@ -301,6 +578,10 @@ index 0000000..33fbd0a + + spinlock_t irq_lock; + ++ unsigned long cache_req_pck; ++ unsigned long cache_prate; ++ struct dispc_clock_info cache_cinfo; ++ + u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; +} dispc; + @@ -321,6 +602,9 @@ index 0000000..33fbd0a + +void dispc_save_context(void) +{ ++ if (cpu_is_omap24xx()) ++ return; ++ + SR(SYSCONFIG); + SR(IRQENABLE); + SR(CONTROL); @@ -462,7 +746,7 @@ index 0000000..33fbd0a +{ + RR(SYSCONFIG); + RR(IRQENABLE); -+ //RR(CONTROL); ++ /*RR(CONTROL);*/ + RR(CONFIG); + RR(DEFAULT_COLOR0); + RR(DEFAULT_COLOR1); @@ -914,12 +1198,14 @@ index 0000000..33fbd0a + dispc_write_reg(dispc_reg_att[plane], val); +} + -+static void _dispc_set_burst_size(enum omap_plane plane, ++void dispc_set_burst_size(enum omap_plane plane, + enum omap_burst_size burst_size) +{ + int shift; + u32 val; + ++ enable_clocks(1); ++ + switch (plane) { + case OMAP_DSS_GFX: + shift = 6; @@ -936,6 +1222,8 @@ index 0000000..33fbd0a + val = dispc_read_reg(dispc_reg_att[plane]); + val = FLD_MOD(val, burst_size, shift+1, shift); + dispc_write_reg(dispc_reg_att[plane], val); ++ ++ enable_clocks(0); +} + +static void _dispc_set_vid_color_conv(enum omap_plane plane, int enable) @@ -969,7 +1257,28 @@ index 0000000..33fbd0a + enable_clocks(0); +} + -+void dispc_setup_plane_fifo(enum omap_plane plane, int ext_mode) ++u32 dispc_get_plane_fifo_size(enum omap_plane plane) ++{ ++ const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS, ++ DISPC_VID_FIFO_SIZE_STATUS(0), ++ DISPC_VID_FIFO_SIZE_STATUS(1) }; ++ u32 size; ++ ++ enable_clocks(1); ++ ++ if (cpu_is_omap24xx()) ++ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0); ++ else if (cpu_is_omap34xx()) ++ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0); ++ else ++ BUG(); ++ ++ enable_clocks(0); ++ ++ return size; ++} ++ ++void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high) +{ + const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD, + DISPC_VID_FIFO_THRESHOLD(0), @@ -977,7 +1286,6 @@ index 0000000..33fbd0a + const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS, + DISPC_VID_FIFO_SIZE_STATUS(0), + DISPC_VID_FIFO_SIZE_STATUS(1) }; -+ int low, high; + u32 size; + + enable_clocks(1); @@ -989,13 +1297,13 @@ index 0000000..33fbd0a + else + BUG(); + -+ if (ext_mode) { -+ low = size * 3 / 4; -+ high = size; -+ } else { -+ low = size / 4; -+ high = size * 3 / 4; -+ } ++ BUG_ON(low > size || high > size); ++ ++ DSSDBG("fifo(%d) size %d, low/high old %u/%u, new %u/%u\n", ++ plane, size, ++ REG_GET(ftrs_reg[plane], 11, 0), ++ REG_GET(ftrs_reg[plane], 27, 16), ++ low, high); + + if (cpu_is_omap24xx()) + dispc_write_reg(ftrs_reg[plane], @@ -1422,10 +1730,30 @@ index 0000000..33fbd0a + enable_clocks(0); +} + ++/* change name to mode? */ +void dispc_set_lcd_timings(struct omap_video_timings *timings) +{ ++ unsigned xtot, ytot; ++ unsigned long ht, vt; ++ + _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp, -+ timings->vsw, timings->vfp, timings->vbp); ++ timings->vsw, timings->vfp, timings->vbp); ++ ++ dispc_set_lcd_size(timings->x_res, timings->y_res); ++ ++ xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; ++ ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; ++ ++ ht = (timings->pixel_clock * 1000) / xtot; ++ vt = (timings->pixel_clock * 1000) / xtot / ytot; ++ ++ DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res); ++ DSSDBG("pck %u\n", timings->pixel_clock); ++ DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", ++ timings->hsw, timings->hfp, timings->hbp, ++ timings->vsw, timings->vfp, timings->vbp); ++ ++ DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); +} + +void dispc_set_lcd_divisor(int lck_div, int pck_div) @@ -1509,7 +1837,8 @@ index 0000000..33fbd0a +{ + u32 l = 0; + -+ DSSDBG("polfreq ihs %d, ivs %d, acb %d\n", ihs, ivs, acb); ++ DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n", ++ onoff, rf, ieo, ipc, ihs, ivs, acbi, acb); + + l |= FLD_VAL(onoff, 17, 17); + l |= FLD_VAL(rf, 16, 16); @@ -1581,11 +1910,24 @@ index 0000000..33fbd0a +int dispc_calc_clock_div(int is_tft, unsigned long req_pck, + struct dispc_clock_info *cinfo) +{ -+ unsigned long prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck)); ++ unsigned long prate; + struct dispc_clock_info cur, best; + int match = 0; + int min_fck_per_pck; + ++ if (cpu_is_omap34xx()) ++ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck)); ++ else ++ prate = 0; ++ ++ if (req_pck == dispc.cache_req_pck && ++ ((cpu_is_omap34xx() && prate == dispc.cache_prate) || ++ dispc.cache_cinfo.fck == dss_clk_get_rate(DSS_CLK_FCK1))) { ++ DSSDBG("dispc clock info found from cache.\n"); ++ *cinfo = dispc.cache_cinfo; ++ return 0; ++ } ++ + min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; + + if (min_fck_per_pck && @@ -1600,15 +1942,10 @@ index 0000000..33fbd0a + memset(&cur, 0, sizeof(cur)); + memset(&best, 0, sizeof(best)); + -+ for (cur.fck_div = 16; cur.fck_div > 0; --cur.fck_div) { -+ cur.fck = prate / cur.fck_div * 2; -+ -+ if (cur.fck > DISPC_MAX_FCK) -+ continue; -+ -+ if (min_fck_per_pck && -+ cur.fck < req_pck * min_fck_per_pck) -+ continue; ++ if (cpu_is_omap24xx()) { ++ /* XXX can we change the clock on omap2? */ ++ cur.fck = dss_clk_get_rate(DSS_CLK_FCK1); ++ cur.fck_div = 1; + + match = 1; + @@ -1618,12 +1955,37 @@ index 0000000..33fbd0a + cur.lck = cur.fck / cur.lck_div; + cur.pck = cur.lck / cur.pck_div; + -+ if (abs(cur.pck - req_pck) < abs(best.pck - req_pck)) { -+ best = cur; ++ best = cur; + -+ if (cur.pck == req_pck) -+ goto found; ++ goto found; ++ } else if (cpu_is_omap34xx()) { ++ for (cur.fck_div = 16; cur.fck_div > 0; --cur.fck_div) { ++ cur.fck = prate / cur.fck_div * 2; ++ ++ if (cur.fck > DISPC_MAX_FCK) ++ continue; ++ ++ if (min_fck_per_pck && ++ cur.fck < req_pck * min_fck_per_pck) ++ continue; ++ ++ match = 1; ++ ++ find_lck_pck_divs(is_tft, req_pck, cur.fck, ++ &cur.lck_div, &cur.pck_div); ++ ++ cur.lck = cur.fck / cur.lck_div; ++ cur.pck = cur.lck / cur.pck_div; ++ ++ if (abs(cur.pck - req_pck) < abs(best.pck - req_pck)) { ++ best = cur; ++ ++ if (cur.pck == req_pck) ++ goto found; ++ } + } ++ } else { ++ BUG(); + } + +found: @@ -1644,6 +2006,10 @@ index 0000000..33fbd0a + if (cinfo) + *cinfo = best; + ++ dispc.cache_req_pck = req_pck; ++ dispc.cache_prate = prate; ++ dispc.cache_cinfo = best; ++ + return 0; +} + @@ -1652,20 +2018,23 @@ index 0000000..33fbd0a + unsigned long prate; + int r; + -+ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck)); -+ -+ r = clk_set_rate(dispc.dpll4_m4_ck, prate / cinfo->fck_div); -+ -+ if (r) -+ return r; -+ -+ dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div); ++ if (cpu_is_omap34xx()) { ++ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck)); ++ DSSDBG("dpll4_m4 = %ld\n", prate); ++ } + -+ DSSDBG("dpll4_m4 = %ld\n", prate); + DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); + DSSDBG("lck = %ld (%d)\n", cinfo->lck, cinfo->lck_div); + DSSDBG("pck = %ld (%d)\n", cinfo->pck, cinfo->pck_div); + ++ if (cpu_is_omap34xx()) { ++ r = clk_set_rate(dispc.dpll4_m4_ck, prate / cinfo->fck_div); ++ if (r) ++ return r; ++ } ++ ++ dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div); ++ + return 0; +} + @@ -1767,7 +2136,10 @@ index 0000000..33fbd0a +} +#endif + -+/* called from dss */ ++/* Called from dss.c. Note that we don't touch clocks here, ++ * but we presume they are on because we got an IRQ. However, ++ * an irq handler may turn the clocks off, so we may not have ++ * clock later in the function. */ +void dispc_irq_handler(void) +{ + int i; @@ -1776,8 +2148,12 @@ index 0000000..33fbd0a + u32 handledirqs = 0; + +#ifdef DEBUG -+ print_irq_status(irqstatus); ++ if (dss_debug) ++ print_irq_status(irqstatus); +#endif ++ /* Ack the interrupt. Do it here before clocks are possibly turned ++ * off */ ++ dispc_write_reg(DISPC_IRQSTATUS, irqstatus); + + for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { + if (!registered_isr[i].isr) @@ -1802,8 +2178,6 @@ index 0000000..33fbd0a + } + } + -+ /* ack the interrupt */ -+ dispc_write_reg(DISPC_IRQSTATUS, irqstatus); +} + +#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC @@ -1852,20 +2226,12 @@ index 0000000..33fbd0a + /* L3 firewall setting: enable access to OCM RAM */ + __raw_writel(0x402000b0, IO_ADDRESS(0x680050a0)); + -+ _dispc_set_burst_size(OMAP_DSS_GFX, OMAP_DSS_BURST_16x32); -+ _dispc_set_burst_size(OMAP_DSS_VIDEO1, OMAP_DSS_BURST_16x32); -+ _dispc_set_burst_size(OMAP_DSS_VIDEO2, OMAP_DSS_BURST_16x32); -+ + _dispc_setup_color_conv_coef(); + + dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY); + + /* Set logic clock to fck, pixel clock to fck/2 for now */ + dispc_set_lcd_divisor(1, 2); -+ -+ dispc_setup_plane_fifo(OMAP_DSS_GFX, 0); -+ dispc_setup_plane_fifo(OMAP_DSS_VIDEO1, 0); -+ dispc_setup_plane_fifo(OMAP_DSS_VIDEO2, 0); +} + +int dispc_init(void) @@ -1880,10 +2246,12 @@ index 0000000..33fbd0a + return -ENOMEM; + } + -+ dispc.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); -+ if (IS_ERR(dispc.dpll4_m4_ck)) { -+ DSSERR("Failed to get dpll4_m4_ck\n"); -+ return -ENODEV; ++ if (cpu_is_omap34xx()) { ++ dispc.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); ++ if (IS_ERR(dispc.dpll4_m4_ck)) { ++ DSSERR("Failed to get dpll4_m4_ck\n"); ++ return -ENODEV; ++ } + } + + enable_clocks(1); @@ -1905,7 +2273,8 @@ index 0000000..33fbd0a + +void dispc_exit(void) +{ -+ clk_put(dispc.dpll4_m4_ck); ++ if (cpu_is_omap34xx()) ++ clk_put(dispc.dpll4_m4_ck); + iounmap(dispc.base); +} + @@ -2169,10 +2538,10 @@ index 0000000..33fbd0a + diff --git a/arch/arm/plat-omap/dss/display.c b/arch/arm/plat-omap/dss/display.c new file mode 100644 -index 0000000..b7f7aff +index 0000000..e3ff778 --- /dev/null +++ b/arch/arm/plat-omap/dss/display.c -@@ -0,0 +1,765 @@ +@@ -0,0 +1,787 @@ +/* + * linux/arch/arm/plat-omap/dss/display.c + * @@ -2330,10 +2699,10 @@ index 0000000..b7f7aff + outh = info->out_height; + } + -+ if (display->x_res < info->pos_x + outw) ++ if (display->panel->timings.x_res < info->pos_x + outw) + return -EINVAL; + -+ if (display->y_res < info->pos_y + outh) ++ if (display->panel->timings.y_res < info->pos_y + outh) + return -EINVAL; + + return 0; @@ -2707,7 +3076,7 @@ index 0000000..b7f7aff + return 0; +} + -+void initialize_overlays(void) ++void initialize_overlays(const char *def_disp_name) +{ + int i; + struct omap_overlay_manager *lcd_mgr; @@ -2717,28 +3086,55 @@ index 0000000..b7f7aff + lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD); + tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV); + -+ /* connect lcd manager to first non-VENC display found */ -+ for (i = 0; i < num_displays; i++) { -+ if (displays[i].type != OMAP_DISPLAY_TYPE_VENC) { ++ if (def_disp_name) { ++ for (i = 0; i < num_displays; i++) { + struct omap_display *display = &displays[i]; -+ omap_dss_set_display(lcd_mgr, display); + -+ def_mgr = lcd_mgr; ++ if (strcmp(display->name, def_disp_name) == 0) { ++ if (display->type != OMAP_DISPLAY_TYPE_VENC) { ++ omap_dss_set_display(lcd_mgr, display); ++ def_mgr = lcd_mgr; ++ } else { ++ omap_dss_set_display(tv_mgr, display); ++ def_mgr = tv_mgr; ++ } + -+ break; ++ break; ++ } + } ++ ++ if (!def_mgr) ++ DSSWARN("default display %s not found\n", ++ def_disp_name); + } + -+ /* connect tv manager to first VENC display found */ -+ for (i = 0; i < num_displays; i++) { -+ if (displays[i].type == OMAP_DISPLAY_TYPE_VENC) { ++ if (def_mgr != lcd_mgr) { ++ /* connect lcd manager to first non-VENC display found */ ++ for (i = 0; i < num_displays; i++) { + struct omap_display *display = &displays[i]; -+ omap_dss_set_display(tv_mgr, display); ++ if (display->type != OMAP_DISPLAY_TYPE_VENC) { ++ omap_dss_set_display(lcd_mgr, display); + -+ if (!def_mgr) -+ def_mgr = tv_mgr; ++ if (!def_mgr) ++ def_mgr = lcd_mgr; + -+ break; ++ break; ++ } ++ } ++ } ++ ++ if (def_mgr != tv_mgr) { ++ /* connect tv manager to first VENC display found */ ++ for (i = 0; i < num_displays; i++) { ++ struct omap_display *display = &displays[i]; ++ if (display->type == OMAP_DISPLAY_TYPE_VENC) { ++ omap_dss_set_display(tv_mgr, display); ++ ++ if (!def_mgr) ++ def_mgr = tv_mgr; ++ ++ break; ++ } + } + } + @@ -2840,11 +3236,6 @@ index 0000000..b7f7aff + if (atomic_cmpxchg(&display->ref_count, 0, 1) != 0) + return 0; +*/ -+ if (display->panel) { -+ display->x_res = display->panel->x_res; -+ display->y_res = display->panel->y_res; -+ display->bpp = display->panel->bpp; -+ } + + return display; +err3: @@ -2940,10 +3331,10 @@ index 0000000..b7f7aff +EXPORT_SYMBOL(omap_dss_unregister_panel); diff --git a/arch/arm/plat-omap/dss/dpi.c b/arch/arm/plat-omap/dss/dpi.c new file mode 100644 -index 0000000..e3ad44e +index 0000000..2dd8a3b --- /dev/null +++ b/arch/arm/plat-omap/dss/dpi.c -@@ -0,0 +1,320 @@ +@@ -0,0 +1,344 @@ +/* + * linux/arch/arm/plat-omap/dss/dpi.c + * @@ -2988,9 +3379,8 @@ index 0000000..e3ad44e + unsigned long pck; + int is_tft; + -+ dispc_set_lcd_size(display->x_res, display->y_res); ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + -+ dispc_set_lcd_timings(&panel->timings); + dispc_set_pol_freq(panel); + + is_tft = (display->panel->config & OMAP_DSS_LCD_TFT) != 0; @@ -2999,7 +3389,7 @@ index 0000000..e3ad44e + { + struct dsi_clock_info cinfo; + dsi_pll_calc_pck(is_tft, -+ display->panel->timings.pixel_clock*1000, ++ display->panel->timings.pixel_clock * 1000, + &cinfo); + + dsi_pll_program(&cinfo); @@ -3015,11 +3405,12 @@ index 0000000..e3ad44e +#else + { + struct dispc_clock_info cinfo; -+ dispc_calc_clock_div(is_tft, panel->timings.pixel_clock*1000, ++ dispc_calc_clock_div(is_tft, panel->timings.pixel_clock * 1000, + &cinfo); + + if (dispc_set_clock_div(&cinfo)) { + DSSERR("Failed to set DSS clocks\n"); ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); |
