diff options
| author | Koen Kooi <koen@openembedded.org> | 2008-11-08 09:45:37 +0100 |
|---|---|---|
| committer | Koen Kooi <koen@openembedded.org> | 2008-11-08 09:45:37 +0100 |
| commit | 78c51f10837517f20ff06026141edc73c69e5db1 (patch) | |
| tree | f7ab5df92e1659956ef2676b1167d54a8fd78ec2 /packages | |
| parent | 1303e1f35b2b86487542b700f5ed8cd0ef8d974e (diff) | |
linux-omap git: add patches for new DSS (the nokia version, not the TI one), update beagle defconfig and bump to 2.6.28rc3
Diffstat (limited to 'packages')
14 files changed, 13308 insertions, 95 deletions
diff --git a/packages/linux/linux-omap/0003-DSS-Documentation-for-OMAP2-3-display-subsystem.patch b/packages/linux/linux-omap/0003-DSS-Documentation-for-OMAP2-3-display-subsystem.patch new file mode 100644 index 0000000000..59c15cee7d --- /dev/null +++ b/packages/linux/linux-omap/0003-DSS-Documentation-for-OMAP2-3-display-subsystem.patch @@ -0,0 +1,259 @@ +From 7a7fe8f7530bf5c7f3714acbe9a5ec8cf80c3d0c Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Tue, 4 Nov 2008 15:08:07 +0200 +Subject: [PATCH] DSS: Documentation for OMAP2/3 display subsystem + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +--- + Documentation/arm/OMAP/DSS | 239 ++++++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 239 insertions(+), 0 deletions(-) + create mode 100644 Documentation/arm/OMAP/DSS + +diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS +new file mode 100644 +index 0000000..b0cc980 +--- /dev/null ++++ b/Documentation/arm/OMAP/DSS +@@ -0,0 +1,239 @@ ++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> ++ 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> ++ w:<width> ++ h:<height> ++ e:<enabled> ++ u:<update mode> ++ t:<tear sync on/off> ++ ++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 2 | cut -d ":" -f 2` ++h=`echo $dviline | cut -d " " -f 3 | cut -d ":" -f 2` ++ ++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 2 | cut -d ":" -f 2` ++h=`echo $tvline | cut -d " " -f 3 | cut -d ":" -f 2` ++ ++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 when it starts using ++dma_alloc_writecombine(). This requires large continuous physical memory areas ++and you can pre-reserve that area with "Consistent DMA memory size" Kconfig ++option. ++ ++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. ++ ++TODO ++---- ++ ++OMAP2 not tested for some time ++- DSS2 did work on OMAP2, but I haven't been able to test it for some time. ++ ++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 ++ +-- +1.5.6.3 + diff --git a/packages/linux/linux-omap/0004-DSS-New-display-subsystem-driver-for-OMAP2-3.patch b/packages/linux/linux-omap/0004-DSS-New-display-subsystem-driver-for-OMAP2-3.patch new file mode 100644 index 0000000000..febfc48c4d --- /dev/null +++ b/packages/linux/linux-omap/0004-DSS-New-display-subsystem-driver-for-OMAP2-3.patch @@ -0,0 +1,4333 @@ +From 0cd726d12358cfe8d80fc0a309bb0c0732c716f0 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Tue, 4 Nov 2008 16:52:12 +0200 +Subject: [PATCH] DSS: New display subsystem driver for OMAP2/3 + +DSI, RFBI and VENC are separate patches + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +--- + arch/arm/plat-omap/Kconfig | 2 + + arch/arm/plat-omap/Makefile | 2 + + arch/arm/plat-omap/dss/Kconfig | 66 ++ + arch/arm/plat-omap/dss/Makefile | 6 + + arch/arm/plat-omap/dss/dispc.c | 1667 +++++++++++++++++++++++++++++ + arch/arm/plat-omap/dss/display.c | 781 ++++++++++++++ + arch/arm/plat-omap/dss/dpi.c | 303 ++++++ + arch/arm/plat-omap/dss/dss.c | 547 ++++++++++ + arch/arm/plat-omap/dss/dss.h | 240 +++++ + arch/arm/plat-omap/dss/sdi.c | 154 +++ + arch/arm/plat-omap/include/mach/display.h | 458 ++++++++ + 11 files changed, 4226 insertions(+), 0 deletions(-) + 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 + create mode 100644 arch/arm/plat-omap/dss/display.c + create mode 100644 arch/arm/plat-omap/dss/dpi.c + create mode 100644 arch/arm/plat-omap/dss/dss.c + create mode 100644 arch/arm/plat-omap/dss/dss.h + create mode 100644 arch/arm/plat-omap/dss/sdi.c + create mode 100644 arch/arm/plat-omap/include/mach/display.h + +diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig +index 960c13f..4e90667 100644 +--- a/arch/arm/plat-omap/Kconfig ++++ b/arch/arm/plat-omap/Kconfig +@@ -245,6 +245,8 @@ config OMAP_SERIAL_WAKE + to data on the serial RX line. This allows you to wake the + system from serial console. + ++source "arch/arm/plat-omap/dss/Kconfig" ++ + endmenu + + endif +diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile +index 1259846..2740497 100644 +--- a/arch/arm/plat-omap/Makefile ++++ b/arch/arm/plat-omap/Makefile +@@ -29,3 +29,5 @@ obj-$(CONFIG_OMAP_MMU_FWK) += mmu.o + # OMAP mailbox framework + obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o + ++# OMAP2/3 Display Subsystem ++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..150cd24 +--- /dev/null ++++ b/arch/arm/plat-omap/dss/Kconfig +@@ -0,0 +1,66 @@ ++config OMAP2_DSS ++ tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)" ++ depends on ARCH_OMAP2 || ARCH_OMAP3 ++ help ++ OMAP2/3 Display Subsystem support. ++ ++if OMAP2_DSS ++ ++config OMAP2_DSS_DEBUG ++ bool "Debug output" ++ default n ++ ++config OMAP2_DSS_RFBI ++ bool "RFBI support" ++ default y ++ ++config OMAP2_DSS_VENC ++ bool "VENC support" ++ default y ++ ++if ARCH_OMAP3 ++ ++config OMAP2_DSS_SDI ++ bool "SDI support" ++ default y ++ ++config OMAP2_DSS_DSI ++ bool "DSI support" ++ default y ++ ++endif ++ ++config OMAP2_DSS_USE_DSI_PLL ++ bool "Use DSI PLL for PCLK (EXPERIMENTAL)" ++ default n ++ depends on OMAP2_DSS_DSI ++ help ++ Use DSI PLL to generate pixel clock. ++ Currently only for DPI output. ++ ++config OMAP2_DSS_FAKE_VSYNC ++ bool "Fake VSYNC irq from manual update displays" ++ default n ++ help ++ If this is selected, DSI will fake a DISPC VSYNC interrupt ++ when DSI has sent a frame. ++ ++config OMAP2_DSS_MIN_FCK_PER_PCK ++ int "Minimum FCK/PCK ratio (for scaling)" ++ range 1 32 ++ default 4 ++ help ++ This can be used to adjust the minimum FCK/PCK ratio. ++ ++ With this you can make sure that DISPC FCK is at least ++ n x PCK. Video plane scaling requires higher FCK than ++ normally. ++ ++ If this is set to 1, there's no extra constraint on the ++ DISPC FCK. However, the FCK will at minimum be ++ 2xPCK (if active matrix) or 3xPCK (if passive matrix). ++ ++ Max FCK is 173MHz, so this doesn't work if your PCK ++ is very high. ++ ++endif +diff --git a/arch/arm/plat-omap/dss/Makefile b/arch/arm/plat-omap/dss/Makefile +new file mode 100644 +index 0000000..e98c6c1 +--- /dev/null ++++ b/arch/arm/plat-omap/dss/Makefile +@@ -0,0 +1,6 @@ ++obj-$(CONFIG_OMAP2_DSS) += omap-dss.o ++omap-dss-y := dss.o display.o dispc.o dpi.o ++omap-dss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o ++omap-dss-$(CONFIG_OMAP2_DSS_VENC) += venc.o ++omap-dss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o ++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..8f5da2d +--- /dev/null ++++ b/arch/arm/plat-omap/dss/dispc.c +@@ -0,0 +1,1667 @@ ++/* ++ * linux/arch/arm/plat-omap/dss/dispc.c ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#define DSS_SUBSYS_NAME "DISPC" ++ ++#include <linux/kernel.h> ++#include <linux/dma-mapping.h> ++#include <linux/vmalloc.h> ++#include <linux/clk.h> ++#include <linux/io.h> ++#include <linux/jiffies.h> ++ ++#include <mach/sram.h> ++#include <mach/board.h> ++#include <mach/clock.h> ++ ++#include <mach/display.h> ++ ++#include "dss.h" ++ ++/* DISPC */ ++#define DISPC_BASE 0x48050400 ++ ++struct dispc_reg { u16 idx; }; ++ ++#define DISPC_REG(idx) ((const struct dispc_reg) { idx }) ++ ++/* DISPC common */ ++#define DISPC_REVISION DISPC_REG(0x0000) ++#define DISPC_SYSCONFIG DISPC_REG(0x0010) ++#define DISPC_SYSSTATUS DISPC_REG(0x0014) ++#define DISPC_IRQSTATUS DISPC_REG(0x0018) ++#define DISPC_IRQENABLE DISPC_REG(0x001C) ++#define DISPC_CONTROL DISPC_REG(0x0040) ++#define DISPC_CONFIG DISPC_REG(0x0044) ++#define DISPC_CAPABLE DISPC_REG(0x0048) ++#define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C) ++#define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050) ++#define DISPC_TRANS_COLOR0 DISPC_REG(0x0054) ++#define DISPC_TRANS_COLOR1 DISPC_REG(0x0058) ++#define DISPC_LINE_STATUS DISPC_REG(0x005C) ++#define DISPC_LINE_NUMBER DISPC_REG(0x0060) ++#define DISPC_TIMING_H DISPC_REG(0x0064) ++#define DISPC_TIMING_V DISPC_REG(0x0068) ++#define DISPC_POL_FREQ DISPC_REG(0x006C) ++#define DISPC_DIVISOR DISPC_REG(0x0070) ++#define DISPC_SIZE_DIG DISPC_REG(0x0078) ++#define DISPC_SIZE_LCD DISPC_REG(0x007C) ++ ++#define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4) ++#define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8) ++#define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC) ++ ++/* DISPC GFX plane */ ++#define DISPC_GFX_BA0 DISPC_REG(0x0080) ++#define DISPC_GFX_BA1 DISPC_REG(0x0084) ++#define DISPC_GFX_POSITION DISPC_REG(0x0088) ++#define DISPC_GFX_SIZE DISPC_REG(0x008C) ++#define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0) ++#define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4) ++#define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8) ++#define DISPC_GFX_ROW_INC DISPC_REG(0x00AC) ++#define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0) ++#define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4) ++#define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8) ++ ++/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */ ++#define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx) ++ ++#define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000) ++#define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004) ++#define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008) ++#define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C) ++#define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010) ++#define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014) ++#define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018) ++#define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C) ++#define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020) ++#define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024) ++#define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028) ++#define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C) ++#define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030) ++ ++/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ ++#define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8) ++/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ ++#define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8) ++/* coef index i = {0, 1, 2, 3, 4} */ ++#define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4) ++ ++#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ ++ DISPC_IRQ_OCP_ERR | \ ++ DISPC_IRQ_VID1_FIFO_UNDERFLOW | \ ++ DISPC_IRQ_VID2_FIFO_UNDERFLOW | \ ++ DISPC_IRQ_SYNC_LOST) ++/*DISPC_IRQ_SYNC_LOST_DIGIT*/ ++ ++#define DISPC_MAX_NR_ISRS 8 ++ ++static struct { ++ omap_dispc_isr_t isr; ++ void *arg; ++ u32 mask; ++} registered_isr[DISPC_MAX_NR_ISRS]; ++ ++#define REG_GET(idx, start, end) \ ++ FLD_GET(dispc_read_reg(idx), start, end) ++ ++#define REG_FLD_MOD(idx, val, start, end) \ ++ dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end)) ++ ++static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES, ++ DISPC_VID_ATTRIBUTES(0), ++ DISPC_VID_ATTRIBUTES(1) }; ++ ++static struct { ++ void __iomem *base; ++ ++ struct clk *dss_ick; ++ struct clk *dss1_fck; ++ struct clk *dss_54m_fck; ++ struct clk *dpll4_m4_ck; ++} dispc; ++ ++static spinlock_t dss_lock; ++ ++static inline void enable_clocks(int enable) ++{ ++ if (enable) { ++ clk_enable(dispc.dss_ick); ++ clk_enable(dispc.dss1_fck); ++ } else { ++ clk_disable(dispc.dss1_fck); ++ clk_disable(dispc.dss_ick); ++ } ++} ++ ++static inline void dispc_write_reg(const struct dispc_reg idx, u32 val) ++{ ++ __raw_writel(val, dispc.base + idx.idx); ++} ++ ++static inline u32 dispc_read_reg(const struct dispc_reg idx) ++{ ++ return __raw_readl(dispc.base + idx.idx); ++} ++ ++void dispc_go(enum omap_channel channel) ++{ ++ int bit; ++ unsigned long tmo; ++ ++ enable_clocks(1); ++ ++ if (channel == OMAP_DSS_CHANNEL_LCD) ++ bit = 0; /* LCDENABLE */ ++ else ++ bit = 1; /* DIGITALENABLE */ ++ ++ /* if the channel is not enabled, we don't need GO */ ++ if (REG_GET(DISPC_CONTROL, bit, bit) == 0) ++ goto end; ++ ++ if (channel == OMAP_DSS_CHANNEL_LCD) ++ bit = 5; /* GOLCD */ ++ else ++ bit = 6; /* GODIGIT */ ++ ++ tmo = jiffies + msecs_to_jiffies(200); ++ while (REG_GET(DISPC_CONTROL, bit, bit) == 1) { ++ if (time_after(jiffies, tmo)) { ++ DSSERR("timeout waiting GO flag\n"); ++ goto end; ++ } ++ cpu_relax(); ++ } ++ ++ DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT"); ++ ++ REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); ++end: ++ enable_clocks(0); ++} ++ ++static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) ++{ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value); ++} ++ ++static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value) ++{ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value); ++} ++ ++ ++static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, ++ int vscaleup) ++{ ++ /* Coefficients for horizontal up-sampling */ ++ const u32 coef_hup[8] = { ++ 0x00800000, ++ 0x0D7CF800, ++ 0x1E70F5FF, ++ 0x335FF5FE, ++ 0xF74949F7, ++ 0xF55F33FB, ++ 0xF5701EFE, ++ 0xF87C0DFF, ++ }; ++ ++ /* Coefficients for horizontal down-sampling */ ++ const u32 coef_hdown[8] = { ++ 0x24382400, ++ 0x28371FFE, ++ 0x2C361BFB, ++ 0x303516F9, ++ 0x11343311, ++ 0x1635300C, ++ 0x1B362C08, ++ 0x1F372804, ++ }; ++ ++ /* Coefficients for horizontal and vertical up-sampling */ ++ const u32 coef_hvup[8] = { ++ 0x00800000, ++ 0x037B02FF, ++ 0x0C6F05FE, ++ 0x205907FB, ++ 0x00404000, ++ 0x075920FE, ++ 0x056F0CFF, ++ 0x027B0300, ++ }; ++ ++ /* Coefficients for horizontal and vertical down-sampling */ ++ const u32 coef_hvdown[8] = { ++ 0x24382400, ++ 0x28391F04, ++ 0x2D381B08, ++ 0x3237170C, ++ 0x123737F7, ++ 0x173732F9, ++ 0x1B382DFB, ++ 0x1F3928FE, ++ }; ++ ++ const u32 *h_coef; ++ const u32 *hv_coef; ++ const u32 *hv_coef_mod; ++ int i; ++ ++ if (hscaleup) ++ h_coef = coef_hup; ++ else ++ h_coef = coef_hdown; ++ ++ if (vscaleup) { ++ hv_coef = coef_hvup; ++ ++ if (hscaleup) ++ hv_coef_mod = NULL; ++ else ++ hv_coef_mod = coef_hvdown; ++ } else { ++ hv_coef = coef_hvdown; ++ ++ if (hscaleup) ++ hv_coef_mod = coef_hvup; ++ else ++ hv_coef_mod = NULL; ++ } ++ ++ for (i = 0; i < 8; i++) { ++ u32 h, hv; ++ ++ h = h_coef[i]; ++ ++ hv = hv_coef[i]; ++ ++ if (hv_coef_mod) { ++ hv &= 0xffffff00; ++ hv |= (hv_coef_mod[i] & 0xff); ++ } ++ ++ _dispc_write_firh_reg(plane, i, h); ++ _dispc_write_firhv_reg(plane, i, hv); ++ } ++} ++ ++static void _dispc_setup_color_conv_coef(void) ++{ ++ const struct color_conv_coef { ++ int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; ++ int full_range; ++ } ctbl_bt601_5 = { ++ 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, ++ }; ++ ++ const struct color_conv_coef *ct; ++ ++#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0)) ++ ++ ct = &ctbl_bt601_5; ++ ++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb)); ++ ++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb)); ++ ++#undef CVAL ++ ++ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11); ++ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11); ++} ++ ++ ++static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr) ++{ ++ const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0, ++ DISPC_VID_BA0(0), ++ DISPC_VID_BA0(1) }; ++ ++ dispc_write_reg(ba0_reg[plane], paddr); ++} ++ ++static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr) ++{ ++ const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1, ++ DISPC_VID_BA1(0), ++ DISPC_VID_BA1(1) }; ++ ++ dispc_write_reg(ba1_reg[plane], paddr); ++} ++ ++static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y) ++{ ++ const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION, ++ DISPC_VID_POSITION(0), ++ DISPC_VID_POSITION(1) }; ++ ++ u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); ++ dispc_write_reg(pos_reg[plane], val); ++} ++ ++static void _dispc_set_pic_size(enum omap_plane plane, int width, int height) ++{ ++ const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE, ++ DISPC_VID_PICTURE_SIZE(0), ++ DISPC_VID_PICTURE_SIZE(1) }; ++ u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); ++ dispc_write_reg(siz_reg[plane], val); ++} ++ ++static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) ++{ ++ u32 val; ++ const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0), ++ DISPC_VID_SIZE(1) }; ++ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); ++ dispc_write_reg(vsi_reg[plane-1], val); ++} ++ ++static void _dispc_set_row_inc(enum omap_plane plane, int inc) ++{ ++ const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC, ++ DISPC_VID_ROW_INC(0), ++ DISPC_VID_ROW_INC(1) }; ++ ++ dispc_write_reg(ri_reg[plane], inc); ++} ++ ++static void _dispc_set_color_mode(enum omap_plane plane, ++ enum omap_color_mode color_mode) ++{ ++ u32 m = 0; ++ ++ switch (color_mode) { ++ case OMAP_DSS_COLOR_CLUT1: ++ m = 0x0; break; ++ case OMAP_DSS_COLOR_CLUT2: ++ m = 0x1; break; ++ case OMAP_DSS_COLOR_CLUT4: ++ m = 0x2; break; ++ case OMAP_DSS_COLOR_CLUT8: ++ m = 0x3; break; ++ case OMAP_DSS_COLOR_RGB12U: ++ m = 0x4; break; ++ case OMAP_DSS_COLOR_ARGB16: ++ m = 0x5; break; ++ case OMAP_DSS_COLOR_RGB16: ++ m = 0x6; break; ++ case OMAP_DSS_COLOR_RGB24U: ++ m = 0x8; break; ++ case OMAP_DSS_COLOR_RGB24P: ++ m = 0x9; break; ++ case OMAP_DSS_COLOR_YUV2: ++ m = 0xa; break; ++ case OMAP_DSS_COLOR_UYVY: ++ m = 0xb; break; ++ case OMAP_DSS_COLOR_ARGB32: ++ m = 0xc; break; ++ case OMAP_DSS_COLOR_RGBA32: ++ m = 0xd; break; ++ case OMAP_DSS_COLOR_RGBX32: ++ m = 0xe; break; ++ default: ++ BUG(); break; ++ } ++ ++ REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1); ++} ++ ++static void _dispc_set_channel_out(enum omap_plane plane, ++ enum omap_channel channel) ++{ ++ int shift; ++ u32 val; ++ ++ switch (plane) { ++ case OMAP_DSS_GFX: ++ shift = 8; ++ break; ++ case OMAP_DSS_VIDEO1: ++ case OMAP_DSS_VIDEO2: ++ shift = 16; ++ break; ++ default: ++ BUG(); ++ return; ++ } ++ ++ val = dispc_read_reg(dispc_reg_att[plane]); ++ val = FLD_MOD(val, channel, shift, shift); ++ dispc_write_reg(dispc_reg_att[plane], val); ++} ++ ++static void _dispc_set_burst_size(enum omap_plane plane, ++ enum omap_burst_size burst_size) ++{ ++ int shift; ++ u32 val; ++ ++ switch (plane) { ++ case OMAP_DSS_GFX: ++ shift = 6; ++ break; ++ case OMAP_DSS_VIDEO1: ++ case OMAP_DSS_VIDEO2: ++ shift = 14; ++ break; ++ default: ++ BUG(); ++ return; ++ } ++ ++ 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); ++} ++ ++static void _dispc_set_vid_color_conv(enum omap_plane plane, int enable) ++{ ++ u32 val; ++ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ val = dispc_read_reg(dispc_reg_att[plane]); ++ val = FLD_MOD(val, enable, 9, 9); ++ dispc_write_reg(dispc_reg_att[plane], val); ++} ++ ++void dispc_set_lcd_size(int width, int height) ++{ ++ u32 val; ++ BUG_ON((width > (1 << 11)) || (height > (1 << 11))); ++ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); ++ enable_clocks(1); ++ dispc_write_reg(DISPC_SIZE_LCD, val); ++ enable_clocks(0); ++} ++ ++void dispc_set_digit_size(int width, int height) ++{ ++ u32 val; ++ BUG_ON((width > (1 << 11)) || (height > (1 << 11))); ++ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); ++ enable_clocks(1); ++ dispc_write_reg(DISPC_SIZE_DIG, val); ++ enable_clocks(0); ++} ++ ++void dispc_setup_plane_fifo(enum omap_plane plane, int ext_mode) ++{ ++ const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD, ++ DISPC_VID_FIFO_THRESHOLD(0), ++ DISPC_VID_FIFO_THRESHOLD(1) }; ++ 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); ++ ++ 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(); ++ ++ if (ext_mode) { ++ low = size * 3 / 4; ++ high = size; ++ } else { ++ low = size / 4; ++ high = size * 3 / 4; ++ } ++ ++ if (cpu_is_omap24xx()) ++ dispc_write_reg(ftrs_reg[plane], ++ FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0)); ++ else ++ dispc_write_reg(ftrs_reg[plane], ++ FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0)); ++ ++ enable_clocks(0); ++} ++ ++static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc) ++{ ++ u32 val; ++ const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0), ++ DISPC_VID_FIR(1) }; |
