DSS: Series description
Subsystems (5)
cover DSS: Series description
New Display Subsystem for OMAP2/3
---------------------------------
This patch set implements new Display Subsystem (DSS) for OMAP2/3 processors. The DSS is still under work and these patches are for review. Note that there is also another new DSS implementation from TI.
The DSS has been tested on OMAP3 SDP board, Beagle Board and on two unreleased boards with DSI and SDI displays. The DSS used to work on OMAP2 board also, but it's been a while since I was able to test with OMAP2 board.
The first patch is a doc file that tries to explain a bit how the drivers work.
The patch set is based on the current linux-omap tree.
You can find the patches also from a git tree at
http://www.bat.org/~tomba/git/linux-omap-dss.git/
Note that you also need two patches from Mans Rullgard to make things work. These are needed to be able to reconfigure DSS functional clock.
http://git.mansr.com/?p=linux-omap;a=commit;h=e2de5e5578fbaa9b4b75074796da0608fc93e6ae
http://git.mansr.com/?p=linux-omap;a=commit;h=2b7b958dc79e51127d7a4ecf88ce12dbc6c31426
Questions/problems
------------------
Perhaps the biggest problems I have is the interface to user space. OMAP hardware doesn't quite fit in to the framebuffer framework. The problem is that a framebuffer can go to multiple overlays, and also the target display, to which a framebuffer goes, can change. In addition, the framebuffer size is used as overlay size, not display resolution. So a framebuffer != display.
I believe DRM modesetting could be of help here, at least partially, but I haven't tried that approach yet.
But DRM modesetting wouldn't solve all the problems. For example, we still need to configure overlays and overlay managers, and they don't quite belong to either the framebuffer side or the display side. Currently you configure them via a hackish sysfs interface, but I've been wondering if a /dev/omap-dss device with ioctls would be a better choice.
There's currently no V4L2 support, but I have been thinking about that. I don't want to make any hardcoded configuration for those, because sometimes you want to use framebuffer devices for video overlays. So what I'd like to have is a way, compile time or run time, to configure which overlays go to framebuffer devices and which go to V4L2 devices.
---
Tomi Valkeinen (9):
DSS: support for OMAP3 SDP board
DSS: support for Beagle Board
DSS: Add generic DVI panel
DSS: OMAPFB: fb driver for new display subsystem
DSS: DSI support for OMAP2/3 DSS
DSS: TV-out support for OMAP2/3 DSS
DSS: RFBI support for OMAP2/3 DSS
DSS: New display subsystem driver for OMAP2/3
DSS: Documentation for OMAP2/3 display subsystem
Documentation/arm/OMAP/DSS | 240 ++ arch/arm/mach-omap2/board-3430sdp.c | 234 ++ arch/arm/mach-omap2/board-omap3beagle.c | 121 + 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/dsi.c | 3027 +++++++++++++++++++++++++++++ arch/arm/plat-omap/dss/dss.c | 547 +++++ arch/arm/plat-omap/dss/dss.h | 240 ++ arch/arm/plat-omap/dss/rfbi.c | 1234 ++++++++++++ arch/arm/plat-omap/dss/sdi.c | 154 + arch/arm/plat-omap/dss/venc.c | 499 +++++ arch/arm/plat-omap/fb.c | 9 arch/arm/plat-omap/include/mach/display.h | 458 ++++ arch/arm/plat-omap/include/mach/omapfb.h | 7 drivers/video/Kconfig | 1 drivers/video/Makefile | 1 drivers/video/omap/Kconfig | 5 drivers/video/omap2/Kconfig | 54 + drivers/video/omap2/Makefile | 5 drivers/video/omap2/omapfb-ioctl.c | 428 ++++ drivers/video/omap2/omapfb-main.c | 1247 ++++++++++++ drivers/video/omap2/omapfb-sysfs.c | 833 ++++++++ drivers/video/omap2/omapfb.h | 104 + drivers/video/omap2/panel-dvi.c | 121 + drivers/video/omap2/panel-sdp3430.c | 110 + 30 files changed, 12479 insertions(+), 27 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 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/dsi.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/rfbi.c create mode 100644 arch/arm/plat-omap/dss/sdi.c create mode 100644 arch/arm/plat-omap/dss/venc.c create mode 100644 arch/arm/plat-omap/include/mach/display.h create mode 100644 drivers/video/omap2/Kconfig create mode 100644 drivers/video/omap2/Makefile create mode 100644 drivers/video/omap2/omapfb-ioctl.c create mode 100644 drivers/video/omap2/omapfb-main.c create mode 100644 drivers/video/omap2/omapfb-sysfs.c create mode 100644 drivers/video/omap2/omapfb.h create mode 100644 drivers/video/omap2/panel-dvi.c create mode 100644 drivers/video/omap2/panel-sdp3430.c
Signature · 1 line
Tomi Valkeinen
PATCH 1/9 DSS: Documentation for OMAP2/3 display subsystem
---
Documentation/arm/OMAP/DSS | 240 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 240 insertions(+), 0 deletions(-) create mode 100644 Documentation/arm/OMAP/DSS
Documentation/arm/OMAP/DSS new file +240 -0
@@ -0,0 +1,240 @@ +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, +instead of DISPC. + +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 are the +same, but, in case of scalable 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 +
Re: [Linux-fbdev-devel] [REVIEW PATCH 1/9] DSS: Documentation for OMAP2/3 display subsystem
Quoted 27 lines · Tomi Valkeinen
Documentation/arm/OMAP/DSS new file +27
-0+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:
Documentation/arm/OMAP/DSS line 140
Quoted 10 lines
Documentation/arm/OMAP/DSS new file +10
-0+ <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>
As all of these contain lists of sections (one for each fb/overlay/manager/display), what about making them directories, with each section an individual file?
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Re: [Linux-fbdev-devel] [REVIEW PATCH 1/9] DSS: Documentation for OMAP2/3 display subsystem
Quoted 34 lines · ext Geert Uytterhoeven
Quoted 33 lines · Tomi Valkeinen
Documentation/arm/OMAP/DSS new file +33
-0+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>
Quoted 8 lines
Documentation/arm/OMAP/DSS line 140
Quoted 4 lines
Documentation/arm/OMAP/DSS new file +4
-0+ h:<height> + e:<enabled> + u:<update mode> + t:<tear sync on/off>As all of these contain lists of sections (one for each fb/overlay/manager/display), what about making them directories, with each section an individual file?
I've thought that also. The reason for the current form is that it was simpler to implement, and is not meant to be in the final version. If the sysfs interface stays there, then I agree that they files have to be divided.
Quoted 4 lines
Gr{oetje,eeting}s,
Geert
Tomi
PATCH 2/9 DSS: New display subsystem driver for OMAP2/3
In reply to Tomi ValkeinenDSI, RFBI and VENC are separate patches
---
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
arch/arm/plat-omap/Kconfig +2 -0
@@ -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
arch/arm/plat-omap/Makefile +2 -0
@@ -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/
arch/arm/plat-omap/dss/Kconfig new file +66 -0
66 lines not on this page · raw message
arch/arm/plat-omap/dss/Makefile new file +6 -0
@@ -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
arch/arm/plat-omap/dss/dispc.c new file +1667 -0
1,667 lines not on this page · raw message
arch/arm/plat-omap/dss/display.c new file +781 -0
781 lines not on this page · raw message
arch/arm/plat-omap/dss/dpi.c new file +303 -0
303 lines not on this page · raw message
arch/arm/plat-omap/dss/dss.c new file +547 -0
164 lines not on this page · raw message
arch/arm/plat-omap/dss/dss.h new file +240 -0
240 lines not on this page · raw message
arch/arm/plat-omap/dss/sdi.c new file +154 -0
154 lines not on this page · raw message
arch/arm/plat-omap/include/mach/display.h new file +458 -0
458 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
Part of the diff is not shown here. View the raw message.
PATCH 3/9 DSS: RFBI support for OMAP2/3 DSS
In reply to Tomi Valkeinen---
arch/arm/plat-omap/dss/rfbi.c | 1234 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 1234 insertions(+), 0 deletions(-) create mode 100644 arch/arm/plat-omap/dss/rfbi.c
arch/arm/plat-omap/dss/rfbi.c new file +1234 -0
@@ -0,0 +1,1234 @@ +/* +* linux/arch/arm/plat-omap/dss/rfbi.c +* +* Copyright (C) 2008 Nokia Corporation +* Author: Tomi Valkeinen <[email protected]> +* +* 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 "RFBI" + +#include <linux/kernel.h> +#include <linux/dma-mapping.h> +#include <linux/vmalloc.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/kfifo.h> +#include <linux/ktime.h> + +#include <mach/board.h> +#include <mach/display.h> +#include "dss.h" + +/*#define MEASURE_PERF*/ + +#define RFBI_BASE 0x48050800 + +struct rfbi_reg {u16 idx; }; + +#define RFBI_REG (idx) ((const struct rfbi_reg) { idx }) + +#define RFBI_REVISION RFBI_REG(0x0000) +#define RFBI_SYSCONFIG RFBI_REG(0x0010) +#define RFBI_SYSSTATUS RFBI_REG(0x0014) +#define RFBI_CONTROL RFBI_REG(0x0040) +#define RFBI_PIXEL_CNT RFBI_REG(0x0044) +#define RFBI_LINE_NUMBER RFBI_REG(0x0048) +#define RFBI_CMD RFBI_REG(0x004c) +#define RFBI_PARAM RFBI_REG(0x0050) +#define RFBI_DATA RFBI_REG(0x0054) +#define RFBI_READ RFBI_REG(0x0058) +#define RFBI_STATUS RFBI_REG(0x005c) + +#define RFBI_CONFIG (n) RFBI_REG(0x0060 + (n)*0x18) +#define RFBI_ONOFF_TIME (n) RFBI_REG(0x0064 + (n)*0x18) +#define RFBI_CYCLE_TIME (n) RFBI_REG(0x0068 + (n)*0x18) +#define RFBI_DATA_CYCLE1 (n) RFBI_REG(0x006c + (n)*0x18) +#define RFBI_DATA_CYCLE2 (n) RFBI_REG(0x0070 + (n)*0x18) +#define RFBI_DATA_CYCLE3 (n) RFBI_REG(0x0074 + (n)*0x18) + +#define RFBI_VSYNC_WIDTH RFBI_REG(0x0090) +#define RFBI_HSYNC_WIDTH RFBI_REG(0x0094) + +#define RFBI_CMD_FIFO_LEN_BYTES (16 * sizeof(struct update_param)) + +#define REG_FLD_MOD (idx, val, start, end) \ + rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end)) + +/* To work around an RFBI transfer rate limitation */ +#define OMAP_RFBI_RATE_LIMIT 1 + +enum omap_rfbi_cycleformat { +OMAP_DSS_RFBI_CYCLEFORMAT_1_1 =0 , +OMAP_DSS_RFBI_CYCLEFORMAT_2_1 =1 , +OMAP_DSS_RFBI_CYCLEFORMAT_3_1 =2 , +OMAP_DSS_RFBI_CYCLEFORMAT_3_2 =3 , +}; + +enum omap_rfbi_datatype { +OMAP_DSS_RFBI_DATATYPE_12 =0 , +OMAP_DSS_RFBI_DATATYPE_16 =1 , +OMAP_DSS_RFBI_DATATYPE_18 =2 , +OMAP_DSS_RFBI_DATATYPE_24 =3 , +}; + +enum omap_rfbi_parallelmode { +OMAP_DSS_RFBI_PARALLELMODE_8 =0 , +OMAP_DSS_RFBI_PARALLELMODE_9 =1 , +OMAP_DSS_RFBI_PARALLELMODE_12 =2 , +OMAP_DSS_RFBI_PARALLELMODE_16 =3 , +}; + +enum update_cmd { +RFBI_CMD_UPDATE =0 , +RFBI_CMD_SYNC =1 , +}; + +static int rfbi_convert_timings (struct rfbi_timings *t); +static void rfbi_get_clk_info (u32 *clk_period,u32 *max_clk_div); +static void process_cmd_fifo (void ); + +static struct { +void __iomem *base; + +struct clk *dss_ick; +struct clk *dss1_fck; + +unsigned long l4_khz; + +enum omap_rfbi_datatype datatype; +enum omap_rfbi_parallelmode parallelmode; + +enum omap_rfbi_te_mode te_mode; +int te_enabled; + +void (*framedone_callback)(void *data); +void *framedone_callback_data; + +struct omap_display *display[2 ]; + +struct kfifo *cmd_fifo; +spinlock_t cmd_lock; +struct completion cmd_done; +atomic_t cmd_fifo_full; +atomic_t cmd_pending; +#ifdef MEASURE_PERF +ktime_t perf_time; +#endif +} rfbi; + +struct update_region { +u16 x; +u16 y; +u16 w; +u16 h; +}; + +struct update_param { +u8 rfbi_module; +u8 cmd; + +union { +struct update_region r; +struct completion *sync; + } par; +}; + +static inline void rfbi_write_reg (const struct rfbi_reg idx,u32 val) +{ +__raw_writel (val, rfbi.base + idx.idx); +} + +static inline u32 rfbi_read_reg (const struct rfbi_reg idx) +{ +return __raw_readl (rfbi.base + idx.idx); +} + +static void rfbi_enable_clocks (int enable) +{ +if (enable) { +clk_enable (rfbi.dss_ick); +clk_enable (rfbi.dss1_fck); + }else { +clk_disable (rfbi.dss1_fck); +clk_disable (rfbi.dss_ick); + } +} + +void omap_rfbi_write_command (const void *buf,u32 len) +{ +rfbi_enable_clocks (1 ); +switch (rfbi.parallelmode) { +case OMAP_DSS_RFBI_PARALLELMODE_8 : + { +const u8 *b = buf; +for (; len; len--) +rfbi_write_reg (RFBI_CMD , *b++); +break ; + } + +case OMAP_DSS_RFBI_PARALLELMODE_16 : + { +const u16 *w = buf; +BUG_ON (len &1 ); +for (; len; len -=2 ) +rfbi_write_reg (RFBI_CMD , *w++); +break ; + } + +case OMAP_DSS_RFBI_PARALLELMODE_9 : +case OMAP_DSS_RFBI_PARALLELMODE_12 : +default : +BUG (); + } +rfbi_enable_clocks (0 ); +} +EXPORT_SYMBOL (omap_rfbi_write_command); + +void omap_rfbi_read_data (void *buf,u32 len) +{ +rfbi_enable_clocks (1 ); +switch (rfbi.parallelmode) { +case OMAP_DSS_RFBI_PARALLELMODE_8 : + { +u8 *b = buf; +for (; len; len--) { +rfbi_write_reg (RFBI_READ ,0 ); + *b++ =rfbi_read_reg (RFBI_READ ); + } +break ; + } + +case OMAP_DSS_RFBI_PARALLELMODE_16 : + { +u16 *w = buf; +BUG_ON (len & ~1 ); +for (; len; len -=2 ) { +rfbi_write_reg (RFBI_READ ,0 ); + *w++ =rfbi_read_reg (RFBI_READ ); + } +break ; + } + +case OMAP_DSS_RFBI_PARALLELMODE_9 : +case OMAP_DSS_RFBI_PARALLELMODE_12 : +default : +BUG (); + } +rfbi_enable_clocks (0 ); +} +EXPORT_SYMBOL (omap_rfbi_read_data); + +void omap_rfbi_write_data (const void *buf,u32 len) +{ +rfbi_enable_clocks (1 ); +switch (rfbi.parallelmode) { +case OMAP_DSS_RFBI_PARALLELMODE_8 : + { +const u8 *b = buf; +for (; len; len--) +rfbi_write_reg (RFBI_PARAM , *b++); +break ; + } + +case OMAP_DSS_RFBI_PARALLELMODE_16 : + { +const u16 *w = buf; +BUG_ON (len &1 ); +for (; len; len -=2 ) +rfbi_write_reg (RFBI_PARAM , *w++); +break ; + } + +case OMAP_DSS_RFBI_PARALLELMODE_9 : +case OMAP_DSS_RFBI_PARALLELMODE_12 : +default : +BUG (); + + } +rfbi_enable_clocks (0 ); +} +EXPORT_SYMBOL (omap_rfbi_write_data); + +void omap_rfbi_write_pixels (const void *buf,int scr_width,int x,int y, +int w,int h) +{ +int start_offset = scr_width * y + x; +int horiz_offset = scr_width - w; +int i; + +rfbi_enable_clocks (1 ); + +if (rfbi.datatype ==OMAP_DSS_RFBI_DATATYPE_16 && + rfbi.parallelmode ==OMAP_DSS_RFBI_PARALLELMODE_8 ) { +const u16 *pd = buf; + pd += start_offset; + +for (; h; --h) { +for (i =0 ; i < w; ++i) { +const u8 *b = (const u8 *)pd; +rfbi_write_reg (RFBI_PARAM , *(b+1 )); +rfbi_write_reg (RFBI_PARAM , *(b+0 )); + ++pd; + } + pd += horiz_offset; + } + }else if (rfbi.datatype ==OMAP_DSS_RFBI_DATATYPE_24 && + rfbi.parallelmode ==OMAP_DSS_RFBI_PARALLELMODE_8 ) { +const u32 *pd = buf; + pd += start_offset; + +for (; h; --h) { +for (i =0 ; i < w; ++i) { +const u8 *b = (const u8 *)pd; +rfbi_write_reg (RFBI_PARAM , *(b+2 )); +rfbi_write_reg (RFBI_PARAM , *(b+1 )); +rfbi_write_reg (RFBI_PARAM , *(b+0 )); + ++pd; + } + pd += horiz_offset; + } + }else if (rfbi.datatype ==OMAP_DSS_RFBI_DATATYPE_16 && + rfbi.parallelmode ==OMAP_DSS_RFBI_PARALLELMODE_16 ) { +const u16 *pd = buf; + pd += start_offset; + +for (; h; --h) { +for (i =0 ; i < w; ++i) { +rfbi_write_reg (RFBI_PARAM , *pd); + ++pd; + } + pd += horiz_offset; + } + }else { +BUG (); + } + +rfbi_enable_clocks (0 ); +} +EXPORT_SYMBOL (omap_rfbi_write_pixels); + +void rfbi_transfer_area (int width,int height, +void (callback )(void *data),void *data) +{ +u32 l; + +/*BUG_ON(callback == 0);*/ +BUG_ON (rfbi.framedone_callback !=NULL ); + +DSSDBG ("rfbi_transfer_area %dx%d\n" , width, height); + +dispc_set_lcd_size (width, height); + +dispc_enable_lcd_out (1 ); + + rfbi.framedone_callback = callback; + rfbi.framedone_callback_data = data; + +rfbi_enable_clocks (1 ); + +#ifdef MEASURE_PERF + rfbi.perf_time =ktime_get (); +#endif +rfbi_write_reg (RFBI_PIXEL_CNT , width * height); + + l =rfbi_read_reg (RFBI_CONTROL ); + l =FLD_MOD (l,1 ,0 ,0 );/* enable */ +if (!rfbi.te_enabled) + l =FLD_MOD (l,1 ,4 ,4 );/* ITE */ + +rfbi_write_reg (RFBI_CONTROL , l); +} + +static void framedone_callback (void *data,u32 mask) +{ +void (*callback)(void *data); + +#ifdef MEASURE_PERF + { +ktime_t t =ktime_get (); + t =ktime_sub (t, rfbi.perf_time); +DSSDBG ("FRAMEDONE in %lld ns\n" ,ktime_to_ns (t)); + } +#else +DSSDBG ("FRAMEDONE\n" ); +#endif + +REG_FLD_MOD (RFBI_CONTROL ,0 ,0 ,0 ); + +rfbi_enable_clocks (0 ); + + callback = rfbi.framedone_callback; + rfbi.framedone_callback =NULL ; + +/*callback(rfbi.framedone_callback_data);*/ + +atomic_set (&rfbi.cmd_pending,0 ); + +process_cmd_fifo (); +} + +#if 1 /* VERBOSE */ +static void rfbi_print_timings (void ) +{ +u32 l; +u32 time; + + l =rfbi_read_reg (RFBI_CONFIG (0 )); + time =1000000000 / rfbi.l4_khz; +if (l & (1 <<4 )) + time *=2 ; + +DSSDBG ("Tick time %u ps\n" , time); + l =rfbi_read_reg (RFBI_ONOFF_TIME (0 )); +DSSDBG ("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, " +"REONTIME %d, REOFFTIME %d\n" , + l &0x0f , (l >>4 ) &0x3f , (l >>10 ) &0x0f , (l >>14 ) &0x3f , + (l >>20 ) &0x0f , (l >>24 ) &0x3f ); + + l =rfbi_read_reg (RFBI_CYCLE_TIME (0 )); +DSSDBG ("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, " +"ACCESSTIME %d\n" , + (l &0x3f ), (l >>6 ) &0x3f , (l >>12 ) &0x3f , + (l >>22 ) &0x3f ); +} +#else +static void rfbi_print_timings (void ) {} +#endif + + + + +static u32 extif_clk_period; + +static inline unsigned long round_to_extif_ticks (unsigned long ps,int div) +{ +int bus_tick = extif_clk_period * div; +return (ps + bus_tick -1 ) / bus_tick * bus_tick; +} + +static int calc_reg_timing (struct rfbi_timings *t,int div) +{ + t->clk_div = div; + + t->cs_on_time =round_to_extif_ticks (t->cs_on_time, div); + + t->we_on_time =round_to_extif_ticks (t->we_on_time, div); + t->we_off_time =round_to_extif_ticks (t->we_off_time, div); + t->we_cycle_time =round_to_extif_ticks (t->we_cycle_time, div); + + t->re_on_time =round_to_extif_ticks (t->re_on_time, div); + t->re_off_time =round_to_extif_ticks (t->re_off_time, div); + t->re_cycle_time =round_to_extif_ticks (t->re_cycle_time, div); + + t->access_time =round_to_extif_ticks (t->access_time, div); + t->cs_off_time =round_to_extif_ticks (t->cs_off_time, div); + t->cs_pulse_width =round_to_extif_ticks (t->cs_pulse_width, div); + +DSSDBG ("[reg]cson %d csoff %d reon %d reoff %d\n" , + t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time); +DSSDBG ("[reg]weon %d weoff %d recyc %d wecyc %d\n" , + t->we_on_time, t->we_off_time, t->re_cycle_time, + t->we_cycle_time); +DSSDBG ("[reg]rdaccess %d cspulse %d\n" , + t->access_time, t->cs_pulse_width); + +return rfbi_convert_timings (t); +} + +static int calc_extif_timings (struct rfbi_timings *t) +{ +u32 max_clk_div; +int div; + +rfbi_get_clk_info (&extif_clk_period, &max_clk_div); +for (div =1 ; div <= max_clk_div; div++) { +if (calc_reg_timing (t, div) ==0 ) +break ; + } + +if (div <= max_clk_div) +return 0 ; + +DSSERR ("can't setup timings\n" ); +return -1 ; +} + + +void rfbi_set_timings (int rfbi_module,struct rfbi_timings *t) +{ +int r; + +if (!t->converted) { + r =calc_extif_timings (t); +if (r <0 ) +DSSERR ("Failed to calc timings\n" ); + } + +BUG_ON (!t->converted); + +rfbi_enable_clocks (1 ); +rfbi_write_reg (RFBI_ONOFF_TIME (rfbi_module), t->tim[0 ]); +rfbi_write_reg (RFBI_CYCLE_TIME (rfbi_module), t->tim[1 ]); + +/* TIMEGRANULARITY */ +REG_FLD_MOD (RFBI_CONFIG (rfbi_module), + (t->tim[2 ] ?1 :0 ),4 ,4 ); + +rfbi_print_timings (); +rfbi_enable_clocks (0 ); +} + +static int ps_to_rfbi_ticks (int time,int div) +{ +unsigned long tick_ps; +int ret; + +/* Calculate in picosecs to yield more exact results */ + tick_ps =1000000000 / (rfbi.l4_khz) * div; + + ret = (time + tick_ps -1 ) / tick_ps; + +return ret; +} + +#ifdef OMAP_RFBI_RATE_LIMIT +unsigned long rfbi_get_max_tx_rate (void ) +{ +unsigned long l4_rate, dss1_rate; +int min_l4_ticks =0 ; +int i; + +/* According to TI this can't be calculated so make the +* adjustments for a couple of known frequencies and warn for +* others. +*/ +static const struct { +unsigned long l4_clk;/* HZ */ +unsigned long dss1_clk;/* HZ */ +unsigned long min_l4_ticks; + } ftab[] = { + {55 ,132 ,7 , },/* 7.86 MPix/s */ + {110 ,110 ,12 , },/* 9.16 MPix/s */ + {110 ,132 ,10 , },/* 11 Mpix/s */ + {120 ,120 ,10 , },/* 12 Mpix/s */ + {133 ,133 ,10 , },/* 13.3 Mpix/s */ + }; + + l4_rate = rfbi.l4_khz /1000 ; + dss1_rate =clk_get_rate (rfbi.dss1_fck) /1000000 ; + +for (i =0 ; i <ARRAY_SIZE (ftab); i++) { +/* Use a window instead of an exact match, to account +* for different DPLL multiplier / divider pairs. +*/ +if (abs (ftab[i].l4_clk - l4_rate) <3 && +abs (ftab[i].dss1_clk - dss1_rate) <3 ) { + min_l4_ticks = ftab[i].min_l4_ticks; +break ; + } + } +if (i ==ARRAY_SIZE (ftab)) { +/* Can't be sure, return anyway the maximum not +* rate-limited. This might cause a problem only for the +* tearing synchronisation. +*/ +DSSERR ("can't determine maximum RFBI transfer rate\n" ); +return rfbi.l4_khz *1000 ; + } +return rfbi.l4_khz *1000 / min_l4_ticks; +} +#else +int rfbi_get_max_tx_rate (void ) +{ +return rfbi.l4_khz *1000 ; +} +#endif + +static void rfbi_get_clk_info (u32 *clk_period,u32 *max_clk_div) +{ + *clk_period =1000000000 / rfbi.l4_khz; + *max_clk_div =2 ; +} + +static int rfbi_convert_timings (struct rfbi_timings *t) +{ +u32 l; +int reon, reoff, weon, weoff, cson, csoff, cs_pulse; +int actim, recyc, wecyc; +int div = t->clk_div; + +if (div <=0 || div >2 ) +return -1 ; + +/* Make sure that after conversion it still holds that: +* weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff, +* csoff > cson, csoff >= max(weoff, reoff), actim > reon +*/ + weon =ps_to_rfbi_ticks (t->we_on_time, div); + weoff =ps_to_rfbi_ticks (t->we_off_time, div); +if (weoff <= weon) + weoff = weon +1 ; +if (weon >0x0f ) +return -1 ; +if (weoff >0x3f ) +return -1 ; + + reon =ps_to_rfbi_ticks (t->re_on_time, div); + reoff =ps_to_rfbi_ticks (t->re_off_time, div); +if (reoff <= reon) + reoff = reon +1 ; +if (reon >0x0f ) +return -1 ; +if (reoff >0x3f ) +return -1 ; + + cson =ps_to_rfbi_ticks (t->cs_on_time, div); + csoff =ps_to_rfbi_ticks (t->cs_off_time, div); +if (csoff <= cson) + csoff = cson +1 ; +if (csoff <max (weoff, reoff)) + csoff =max (weoff, reoff); +if (cson >0x0f ) +return -1 ; +if (csoff >0x3f ) +return -1 ; + + l = cson; + l |= csoff <<4 ; + l |= weon <<10 ; + l |= weoff <<14 ; + l |= reon <<20 ; + l |= reoff <<24 ; + + t->tim[0 ] = l; + + actim =ps_to_rfbi_ticks (t->access_time, div); +if (actim <= reon) + actim = reon +1 ; +if (actim >0x3f ) +return -1 ; + + wecyc =ps_to_rfbi_ticks (t->we_cycle_time, div); +if (wecyc < weoff) + wecyc = weoff; +if (wecyc >0x3f ) +return -1 ; + + recyc =ps_to_rfbi_ticks (t->re_cycle_time, div); +if (recyc < reoff) + recyc = reoff; +if (recyc >0x3f ) +return -1 ; + + cs_pulse =ps_to_rfbi_ticks (t->cs_pulse_width, div); +if (cs_pulse >0x3f ) +return -1 ; + + l = wecyc; + l |= recyc <<6 ; + l |= cs_pulse <<12 ; + l |= actim <<22 ; + + t->tim[1 ] = l; + + t->tim[2 ] = div -1 ; + + t->converted =1 ; + +return 0 ; +} + +/* xxx FIX module selection missing */ +int omap_rfbi_setup_te (enum omap_rfbi_te_mode mode, +unsigned hs_pulse_time,unsigned vs_pulse_time, +int hs_pol_inv,int vs_pol_inv,int extif_div) +{ +int hs, vs; +int min; +u32 l; + + hs =ps_to_rfbi_ticks (hs_pulse_time,1 ); + vs =ps_to_rfbi_ticks (vs_pulse_time,1 ); +if (hs <2 ) +return -EDOM ; +if (mode ==OMAP_DSS_RFBI_TE_MODE_2 ) + min =2 ; +else /* OMAP_DSS_RFBI_TE_MODE_1 */ + min =4 ; +if (vs < min) +return -EDOM ; +if (vs == hs) +return -EINVAL ; + rfbi.te_mode = mode; +DSSDBG ("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n" , + mode, hs, vs, hs_pol_inv, vs_pol_inv); + +rfbi_enable_clocks (1 ); +rfbi_write_reg (RFBI_HSYNC_WIDTH , hs); +rfbi_write_reg (RFBI_VSYNC_WIDTH , vs); + + l =rfbi_read_reg (RFBI_CONFIG (0 )); +if (hs_pol_inv) + l &= ~(1 <<21 ); +else + l |=1 <<21 ; +if (vs_pol_inv) + l &= ~(1 <<20 ); +else + l |=1 <<20 ; +rfbi_enable_clocks (0 ); + +return 0 ; +} +EXPORT_SYMBOL (omap_rfbi_setup_te); + +/* xxx FIX module selection missing */ +int omap_rfbi_enable_te (int enable,unsigned line) +{ +u32 l; + +DSSDBG ("te %d line %d mode %d\n" , enable, line, rfbi.te_mode); +if (line > (1 <<11 ) -1 ) +return -EINVAL ; + +rfbi_enable_clocks (1 ); + l =rfbi_read_reg (RFBI_CONFIG (0 )); + l &= ~(0x3 <<2 ); +if (enable) { + rfbi.te_enabled =1 ; + l |= rfbi.te_mode <<2 ; + }else + rfbi.te_enabled =0 ; +rfbi_write_reg (RFBI_CONFIG (0 ), l); +rfbi_write_reg (RFBI_LINE_NUMBER , line); +rfbi_enable_clocks (0 ); + +return 0 ; +} +EXPORT_SYMBOL (omap_rfbi_enable_te); + +#if 0 +static void rfbi_enable_config (int enable1,int enable2) +{ +u32 l; +int cs =0 ; + +if (enable1) + cs |=1 <<0 ; +if (enable2) + cs |=1 <<1 ; + +rfbi_enable_clocks (1 ); + + l =rfbi_read_reg (RFBI_CONTROL ); + + l =FLD_MOD (l, cs,3 ,2 ); + l =FLD_MOD (l,0 ,1 ,1 ); + +rfbi_write_reg (RFBI_CONTROL , l); + + + l =rfbi_read_reg (RFBI_CONFIG (0 )); + l =FLD_MOD (l,0 ,3 ,2 );/* TRIGGERMODE: ITE */ +/*l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */ +/*l |= FLD_VAL(0, 8, 7); */ /* L4FORMAT, 1pix/L4 */ + + l =FLD_MOD (l,0 ,16 ,16 );/* A0POLARITY */ + l =FLD_MOD (l,1 ,20 ,20 );/* TE_VSYNC_POLARITY */ + l =FLD_MOD (l,1 ,21 ,21 );/* HSYNCPOLARITY */ + + l =FLD_MOD (l,OMAP_DSS_RFBI_PARALLELMODE_8 ,1 ,0 ); +rfbi_write_reg (RFBI_CONFIG (0 ), l); + +rfbi_enable_clocks (0 ); +} +#endif + +int rfbi_configure (int rfbi_module,int bpp,int lines) +{ +u32 l; +int cycle1 =0 , cycle2 =0 , cycle3 =0 ; +enum omap_rfbi_cycleformat cycleformat; +enum omap_rfbi_datatype datatype; +enum omap_rfbi_parallelmode parallelmode; + +switch (bpp) { +case 12 : + datatype =OMAP_DSS_RFBI_DATATYPE_12 ; +break ; +case 16 : + datatype =OMAP_DSS_RFBI_DATATYPE_16 ; +break ; +case 18 : + datatype =OMAP_DSS_RFBI_DATATYPE_18 ; +break ; +case 24 : + datatype =OMAP_DSS_RFBI_DATATYPE_24 ; +break ; +default : +BUG (); +return 1 ; + } + rfbi.datatype = datatype; + +switch (lines) { +case 8 : + parallelmode =OMAP_DSS_RFBI_PARALLELMODE_8 ; +break ; +case 9 : + parallelmode =OMAP_DSS_RFBI_PARALLELMODE_9 ; +break ; +case 12 : + parallelmode =OMAP_DSS_RFBI_PARALLELMODE_12 ; +break ; +case 16 : + parallelmode =OMAP_DSS_RFBI_PARALLELMODE_16 ; +break ; +default : +BUG (); +return 1 ; + } + rfbi.parallelmode = parallelmode; + +if ((bpp % lines) ==0 ) { +switch (bpp / lines) { +case 1 : + cycleformat =OMAP_DSS_RFBI_CYCLEFORMAT_1_1 ; +break ; +case 2 : + cycleformat =OMAP_DSS_RFBI_CYCLEFORMAT_2_1 ; +break ; +case 3 : + cycleformat =OMAP_DSS_RFBI_CYCLEFORMAT_3_1 ; +break ; +default : +BUG (); +return 1 ; + } + }else if ((2 * bpp % lines) ==0 ) { +if ((2 * bpp / lines) ==3 ) + cycleformat =OMAP_DSS_RFBI_CYCLEFORMAT_3_2 ; +else { +BUG (); +return 1 ; + } + }else { +BUG (); +return 1 ; + } + +switch (cycleformat) { +case OMAP_DSS_RFBI_CYCLEFORMAT_1_1 : + cycle1 = lines; +break ; + +case OMAP_DSS_RFBI_CYCLEFORMAT_2_1 : + cycle1 = lines; + cycle2 = lines; +break ; + +case OMAP_DSS_RFBI_CYCLEFORMAT_3_1 : + cycle1 = lines; + cycle2 = lines; + cycle3 = lines; +break ; + +case OMAP_DSS_RFBI_CYCLEFORMAT_3_2 : + cycle1 = lines; + cycle2 = (lines /2 ) | ((lines /2 ) <<16 ); + cycle3 = (lines <<16 ); +break ; + } + +rfbi_enable_clocks (1 ); + +REG_FLD_MOD (RFBI_CONTROL ,0 ,3 ,2 );/* clear CS */ + + l =0 ; + l |=FLD_VAL (parallelmode,1 ,0 ); + l |=FLD_VAL (0 ,3 ,2 );/* TRIGGERMODE: ITE */ + l |=FLD_VAL (0 ,4 ,4 );/* TIMEGRANULARITY */ + l |=FLD_VAL (datatype,6 ,5 ); +/* l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */ + l |=FLD_VAL (0 ,8 ,7 );/* L4FORMAT, 1pix/L4 */ + l |=FLD_VAL (cycleformat,10 ,9 ); + l |=FLD_VAL (0 ,12 ,11 );/* UNUSEDBITS */ + l |=FLD_VAL (0 ,16 ,16 );/* A0POLARITY */ + l |=FLD_VAL (0 ,17 ,17 );/* REPOLARITY */ + l |=FLD_VAL (0 ,18 ,18 );/* WEPOLARITY */ + l |=FLD_VAL (0 ,19 ,19 );/* CSPOLARITY */ + l |=FLD_VAL (1 ,20 ,20 );/* TE_VSYNC_POLARITY */ + l |=FLD_VAL (1 ,21 ,21 );/* HSYNCPOLARITY */ +rfbi_write_reg (RFBI_CONFIG (rfbi_module), l); + +rfbi_write_reg (RFBI_DATA_CYCLE1 (rfbi_module), cycle1); +rfbi_write_reg (RFBI_DATA_CYCLE2 (rfbi_module), cycle2); +rfbi_write_reg (RFBI_DATA_CYCLE3 (rfbi_module), cycle3); + + + l =rfbi_read_reg (RFBI_CONTROL ); + l =FLD_MOD (l, rfbi_module+1 ,3 ,2 );/* Select CSx */ + l =FLD_MOD (l,0 ,1 ,1 );/* clear bypass */ +rfbi_write_reg (RFBI_CONTROL , l); + + +DSSDBG ("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n" , + bpp, lines, cycle1, cycle2, cycle3); + +rfbi_enable_clocks (0 ); + +return 0 ; +} + +static int rfbi_find_display (struct omap_display *disp) +{ +if (disp == rfbi.display[0 ]) +return 0 ; + +if (disp == rfbi.display[1 ]) +return 1 ; + +BUG (); +return -1 ; +} + + +static void signal_fifo_waiters (void ) +{ +if (atomic_read (&rfbi.cmd_fifo_full) >0 ) { +/* DSSDBG("SIGNALING: Fifo not full for waiter!\n"); */ +complete (&rfbi.cmd_done); +atomic_dec (&rfbi.cmd_fifo_full); + } +} + +/* returns 1 for async op, and 0 for sync op */ +static int do_update (struct omap_display *display,struct update_region *upd) +{ +int x = upd->x; +int y = upd->y; +int w = upd->w; +int h = upd->h; + +if (display->manager->caps &OMAP_DSS_OVL_MGR_CAP_DISPC ) { +/*display->ctrl->enable_te(display, 1); */ + +dispc_setup_partial_planes (display, &x, &y, &w, &h); + + display->ctrl->setup_update (display, x, y, w, h); + +rfbi_transfer_area (w, h,NULL ,NULL ); + +return 1 ; + }else { +struct omap_overlay *ovl; +void *addr; +int scr_width; +#ifdef MEASURE_PERF +ktime_t t1, t2; +#endif + ovl = &display->manager->overlays[0 ]; + scr_width = ovl->info.screen_width; + addr = ovl->info.vaddr; + + display->ctrl->setup_update (display, x, y, w, h); + +#ifdef MEASURE_PERF + t1 =ktime_get (); +#endif +omap_rfbi_write_pixels (addr, scr_width, + x, y, w, h); +#ifdef MEASURE_PERF + t2 =ktime_get (); + t1 =ktime_sub (t2, t1); +DSSDBG ("L4 FRAMEDONE in %lld ns\n" , +ktime_to_ns (t1)); +#endif +return 0 ; + } +} + +static void process_cmd_fifo (void ) +{ +int len; +struct update_param p; +struct omap_display *display; +unsigned long flags; + +if (atomic_inc_return (&rfbi.cmd_pending) !=1 ) +return ; + +while (true) { +spin_lock_irqsave (rfbi.cmd_fifo->lock, flags); + + len =__kfifo_get (rfbi.cmd_fifo, (unsigned char *)&p, +sizeof (struct update_param )); +if (len ==0 ) { +DSSDBG ("nothing more in fifo\n" ); +atomic_set (&rfbi.cmd_pending,0 ); +spin_unlock_irqrestore (rfbi.cmd_fifo->lock, flags); +break ; + } + +/* DSSDBG("fifo full %d\n", rfbi.cmd_fifo_full.counter);*/ + +spin_unlock_irqrestore (rfbi.cmd_fifo->lock, flags); + +BUG_ON (len !=sizeof (struct update_param )); +BUG_ON (p.rfbi_module >1 ); + + display = rfbi.display[p.rfbi_module]; + +if (p.cmd ==RFBI_CMD_UPDATE ) { +if (do_update (display, &p.par.r)) +break ;/* async op */ + }else if (p.cmd ==RFBI_CMD_SYNC ) { +DSSDBG ("Signaling SYNC done!\n" ); +complete (p.par.sync); + }else +BUG (); + } + +signal_fifo_waiters (); +} + +static void rfbi_push_cmd (struct update_param *p) +{ +int ret; + +while (1 ) { +unsigned long flags; +int available; + +spin_lock_irqsave (rfbi.cmd_fifo->lock, flags); + available =RFBI_CMD_FIFO_LEN_BYTES - +__kfifo_len (rfbi.cmd_fifo); + +/* DSSDBG("%d bytes left in fifo\n", available); */ +if (available <sizeof (struct update_param )) { +DSSDBG ("Going to wait because FIFO FULL..\n" ); +spin_unlock_irqrestore (rfbi.cmd_fifo->lock, flags); +atomic_inc (&rfbi.cmd_fifo_full); +wait_for_completion (&rfbi.cmd_done); +/*DSSDBG("Woke up because fifo not full anymore\n");*/ +continue ; + } + + ret =__kfifo_put (rfbi.cmd_fifo, (unsigned char *)p, +sizeof (struct update_param )); +/* DSSDBG("pushed %d bytes\n", ret);*/ + +spin_unlock_irqrestore (rfbi.cmd_fifo->lock, flags); + +BUG_ON (ret !=sizeof (struct update_param )); + +break ; + } +} + +static void rfbi_push_update (int rfbi_module,int x,int y,int w,int h) +{ +struct update_param p; + + p.rfbi_module = rfbi_module; + p.cmd =RFBI_CMD_UPDATE ; + + p.par.r.x = x; + p.par.r.y = y; + p.par.r.w = w; + p.par.r.h = h; + +DSSDBG ("RFBI pushed %d,%d %dx%d\n" , x, y, w, h); + +rfbi_push_cmd (&p); + +process_cmd_fifo (); +} + +static void rfbi_push_sync (int rfbi_module,struct completion *sync_comp) +{ +struct update_param p; + + p.rfbi_module = rfbi_module; + p.cmd =RFBI_CMD_SYNC ; + p.par.sync = sync_comp; + +rfbi_push_cmd (&p); + +DSSDBG ("RFBI sync pushed to cmd fifo\n" ); + +process_cmd_fifo (); +} + +int rfbi_init (void ) +{ +u32 rev; +u32 l; + +spin_lock_init (&rfbi.cmd_lock); + rfbi.cmd_fifo =kfifo_alloc (RFBI_CMD_FIFO_LEN_BYTES ,GFP_KERNEL , + &rfbi.cmd_lock); +if (IS_ERR (rfbi.cmd_fifo)) +return -ENOMEM ; + +init_completion (&rfbi.cmd_done); +atomic_set (&rfbi.cmd_fifo_full,0 ); +atomic_set (&rfbi.cmd_pending,0 ); + + rfbi.base =ioremap (RFBI_BASE ,SZ_256 ); +if (!rfbi.base) { +DSSERR ("can't ioremap RFBI\n" ); +return -ENOMEM ; + } + + rfbi.dss_ick =get_dss_ick (); + rfbi.dss1_fck =get_dss1_fck (); + +rfbi_enable_clocks (1 ); + +msleep (10 ); + + rfbi.l4_khz =clk_get_rate (rfbi.dss_ick) /1000 ; + +/* Enable autoidle and smart-idle */ + l =rfbi_read_reg (RFBI_SYSCONFIG ); + l |= (1 <<0 ) | (2 <<3 ); +rfbi_write_reg (RFBI_SYSCONFIG , l); + + rev =rfbi_read_reg (RFBI_REVISION ); +printk (KERN_INFO "OMAP RFBI rev %d.%d\n" , +FLD_GET (rev,7 ,4 ),FLD_GET (rev,3 ,0 )); + +rfbi_enable_clocks (0 ); + +return 0 ; +} + +void rfbi_exit (void ) +{ +DSSDBG ("rfbi_exit\n" ); + +kfifo_free (rfbi.cmd_fifo); + +iounmap (rfbi.base); +} + +/* struct omap_display support */ +static void rfbi_display_set_mode (struct omap_display *display, +int x_res,int y_res,int bpp) +{ + display->bpp = bpp; + +dispc_set_tft_data_lines (display->bpp); + +if (rfbi_configure (display->hw_config.u.rfbi.channel, + display->bpp, + display->hw_config.u.rfbi.data_lines) !=0 ) { +DSSERR ("can't configure rfbi\n" ); + } + + display->ctrl->set_mode (display, x_res, y_res, bpp); +} + + +static int rfbi_display_update (struct omap_display *display, +int x,int y,int w,int h) +{ +int rfbi_module; + +if (w ==0 || h ==0 ) +return 0 ; + + rfbi_module =rfbi_find_display (display); + +rfbi_push_update (rfbi_module, x, y, w, h); + +return 0 ; +} + +static int rfbi_display_sync (struct omap_display *display) +{ +struct completion sync_comp; +int rfbi_module; + + rfbi_module =rfbi_find_display (display); + +init_completion (&sync_comp); +rfbi_push_sync (rfbi_module, &sync_comp); +DSSDBG ("Waiting for SYNC to happen...\n" ); +wait_for_completion (&sync_comp); +DSSDBG ("Released from SYNC\n" ); +return 0 ; +} + +static int rfbi_display_enable_te (struct omap_display *display,int enable) +{ + display->ctrl->enable_te (display, enable); +return 0 ; +} + +static int rfbi_display_enable (struct omap_display *display) +{ +int r; + +BUG_ON (display->panel ==NULL || display->ctrl ==NULL ); + + r =omap_dispc_register_isr (framedone_callback,NULL , +DISPC_IRQ_FRAMEDONE ); +if (r) { +DSSERR ("can't get FRAMEDONE irq\n" ); +return r; + } + +dispc_set_lcd_display_type (OMAP_DSS_LCD_DISPLAY_TFT ); + +dispc_set_parallel_interface_mode (OMAP_DSS_PARALLELMODE_RFBI ); + +/* FIX select 16bpp as default */ +rfbi_configure (display->hw_config.u.rfbi.channel, +16 , + display->hw_config.u.rfbi.data_lines); + +rfbi_set_timings (display->hw_config.u.rfbi.channel, + &display->ctrl->timings); + + display->ctrl->enable (display); + +return 0 ; +} + +static void rfbi_display_disable (struct omap_display *display) +{ + display->ctrl->disable (display); +omap_dispc_unregister_isr (framedone_callback); +} + +void rfbi_init_display (struct omap_display *display) +{ + display->enable = rfbi_display_enable; + display->disable = rfbi_display_disable; + display->set_mode = rfbi_display_set_mode; + display->update = rfbi_display_update; + display->sync = rfbi_display_sync; + display->enable_te = rfbi_display_enable_te; + + rfbi.display[display->hw_config.u.rfbi.channel] = display; + + display->caps =OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE ; +}
PATCH 4/9 DSS: TV-out support for OMAP2/3 DSS
In reply to Tomi Valkeinen---
arch/arm/plat-omap/dss/venc.c | 499 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 499 insertions(+), 0 deletions(-) create mode 100644 arch/arm/plat-omap/dss/venc.c
arch/arm/plat-omap/dss/venc.c new file +499 -0
@@ -0,0 +1,499 @@ +/* +* linux/arch/arm/plat-omap/dss/venc.c +* +* Copyright (C) 2008 Nokia Corporation +* Author: Tomi Valkeinen <[email protected]> +* +* VENC settings from TI's DSS driver +* +* 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 "VENC" + +#include <linux/kernel.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/err.h> + +#include <linux/semaphore.h> +#include <mach/board.h> +#include <mach/gpio.h> +#include <mach/display.h> +#include <mach/cpu.h> + +#include "dss.h" + +#define VENC_BASE 0x48050C00 + +/* Venc registers */ +#define VENC_REV_ID 0x00 +#define VENC_STATUS 0x04 +#define VENC_F_CONTROL 0x08 +#define VENC_VIDOUT_CTRL 0x10 +#define VENC_SYNC_CTRL 0x14 +#define VENC_LLEN 0x1C +#define VENC_FLENS 0x20 +#define VENC_HFLTR_CTRL 0x24 +#define VENC_CC_CARR_WSS_CARR 0x28 +#define VENC_C_PHASE 0x2C +#define VENC_GAIN_U 0x30 +#define VENC_GAIN_V 0x34 +#define VENC_GAIN_Y 0x38 +#define VENC_BLACK_LEVEL 0x3C +#define VENC_BLANK_LEVEL 0x40 +#define VENC_X_COLOR 0x44 +#define VENC_M_CONTROL 0x48 +#define VENC_BSTAMP_WSS_DATA 0x4C +#define VENC_S_CARR 0x50 +#define VENC_LINE21 0x54 +#define VENC_LN_SEL 0x58 +#define VENC_L21__WC_CTL 0x5C +#define VENC_HTRIGGER_VTRIGGER 0x60 +#define VENC_SAVID__EAVID 0x64 +#define VENC_FLEN__FAL 0x68 +#define VENC_LAL__PHASE_RESET 0x6C +#define VENC_HS_INT_START_STOP_X 0x70 +#define VENC_HS_EXT_START_STOP_X 0x74 +#define VENC_VS_INT_START_X 0x78 +#define VENC_VS_INT_STOP_X__VS_INT_START_Y 0x7C +#define VENC_VS_INT_STOP_Y__VS_EXT_START_X 0x80 +#define VENC_VS_EXT_STOP_X__VS_EXT_START_Y 0x84 +#define VENC_VS_EXT_STOP_Y 0x88 +#define VENC_AVID_START_STOP_X 0x90 +#define VENC_AVID_START_STOP_Y 0x94 +#define VENC_FID_INT_START_X__FID_INT_START_Y 0xA0 +#define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X 0xA4 +#define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y 0xA8 +#define VENC_TVDETGP_INT_START_STOP_X 0xB0 +#define VENC_TVDETGP_INT_START_STOP_Y 0xB4 +#define VENC_GEN_CTRL 0xB8 +#define VENC_OUTPUT_CONTROL 0xC4 +#define VENC_DAC_B__DAC_C 0xC8 + +static DECLARE_MUTEX (venc_lock); + +struct venc_config { +u32 f_control; +u32 vidout_ctrl; +u32 sync_ctrl; +u32 llen; +u32 flens; +u32 hfltr_ctrl; +u32 cc_carr_wss_carr; +u32 c_phase; +u32 gain_u; +u32 gain_v; +u32 gain_y; +u32 black_level; +u32 blank_level; +u32 x_color; +u32 m_control; +u32 bstamp_wss_data; +u32 s_carr; +u32 line21; +u32 ln_sel; +u32 l21__wc_ctl; +u32 htrigger_vtrigger; +u32 savid__eavid; +u32 flen__fal; +u32 lal__phase_reset; +u32 hs_int_start_stop_x; +u32 hs_ext_start_stop_x; +u32 vs_int_start_x; +u32 vs_int_stop_x__vs_int_start_y; +u32 vs_int_stop_y__vs_ext_start_x; +u32 vs_ext_stop_x__vs_ext_start_y; +u32 vs_ext_stop_y; +u32 avid_start_stop_x; +u32 avid_start_stop_y; +u32 fid_int_start_x__fid_int_start_y; +u32 fid_int_offset_y__fid_ext_start_x; +u32 fid_ext_start_y__fid_ext_offset_y; +u32 tvdetgp_int_start_stop_x; +u32 tvdetgp_int_start_stop_y; +u32 gen_ctrl; + +int width; +int height; +}; + +/* from TRM */ +static const struct venc_config venc_config_pal_trm = { + .f_control =0 , + .vidout_ctrl =1 , + .sync_ctrl =0x40 , + .llen =0x35F ,/* 863 */ + .flens =0x270 ,/* 624 */ + .hfltr_ctrl =0 , + .cc_carr_wss_carr =0x2F7225ED , + .c_phase =0 , + .gain_u =0x111 , + .gain_v =0x181 , + .gain_y =0x140 , + .black_level =0x3B , + .blank_level =0x3B , + .x_color =0x7 , + .m_control =0x2 , + .bstamp_wss_data =0x3F , + .s_carr =0x2A098ACB , + .line21 =0 , + .ln_sel =0x01290015 , + .l21__wc_ctl =0x0000F603 , + .htrigger_vtrigger =0 , + + .savid__eavid =0x06A70108 , + .flen__fal =0x00180270 , + .lal__phase_reset =0x00180270 , + .hs_int_start_stop_x =0x00880358 , + .hs_ext_start_stop_x =0x000F035F , + .vs_int_start_x =0x01A70000 , + .vs_int_stop_x__vs_int_start_y =0x000001A7 , + .vs_int_stop_y__vs_ext_start_x =0x01AF0000 , + .vs_ext_stop_x__vs_ext_start_y =0x000101AF , + .vs_ext_stop_y =0x00000025 , + .avid_start_stop_x =0x03530083 , + .avid_start_stop_y =0x026C002E , + .fid_int_start_x__fid_int_start_y =0x0001008A , + .fid_int_offset_y__fid_ext_start_x =0x002E0138 , + .fid_ext_start_y__fid_ext_offset_y =0x01380001 , + + .tvdetgp_int_start_stop_x =0x00140001 , + .tvdetgp_int_start_stop_y =0x00010001 , + .gen_ctrl =0x00FF0000 , + + .width =720 , + .height =574 ,/* for some reason, this isn't 576 */ +}; + +/* from TRM */ +static const struct venc_config venc_config_ntsc_trm = { + .f_control =0 , + .vidout_ctrl =1 , + .sync_ctrl =0x8040 , + .llen =0x359 , + .flens =0x20C , + .hfltr_ctrl =0 , + .cc_carr_wss_carr =0x043F2631 , + .c_phase =0 , + .gain_u =0x102 , + .gain_v =0x16C , + .gain_y =0x12F , + .black_level =0x43 , + .blank_level =0x38 , + .x_color =0x7 , + .m_control =0x1 , + .bstamp_wss_data =0x38 , + .s_carr =0x21F07C1F , + .line21 =0 , + .ln_sel =0x01310011 , + .l21__wc_ctl =0x0000F003 , + .htrigger_vtrigger =0 , + + .savid__eavid =0x069300F4 , + .flen__fal =0x0016020C , + .lal__phase_reset =0x00060107 , + .hs_int_start_stop_x =0x008E0350 , + .hs_ext_start_stop_x =0x000F0359 , + .vs_int_start_x =0x01A00000 , + .vs_int_stop_x__vs_int_start_y =0x020701A0 , + .vs_int_stop_y__vs_ext_start_x =0x01AC0024 , + .vs_ext_stop_x__vs_ext_start_y =0x020D01AC , + .vs_ext_stop_y =0x00000006 , + .avid_start_stop_x =0x03480078 , + .avid_start_stop_y =0x02060024 , + .fid_int_start_x__fid_int_start_y =0x0001008A , + .fid_int_offset_y__fid_ext_start_x =0x01AC0106 , + .fid_ext_start_y__fid_ext_offset_y =0x01060006 , + + .tvdetgp_int_start_stop_x =0x00140001 , + .tvdetgp_int_start_stop_y =0x00010001 , + .gen_ctrl =0x00F90000 , + + .width =720 , + .height =482 , +}; + +static const struct venc_config venc_config_pal_bdghi = { + .f_control =0 , + .vidout_ctrl =0 , + .sync_ctrl =0 , + .hfltr_ctrl =0 , + .x_color =0 , + .line21 =0 , + .ln_sel =21 , + .htrigger_vtrigger =0 , + .tvdetgp_int_start_stop_x =0x00140001 , + .tvdetgp_int_start_stop_y =0x00010001 , + .gen_ctrl =0x00FB0000 , + + .llen =864 -1 , + .flens =625 -1 , + .cc_carr_wss_carr =0x2F7625ED , + .c_phase =0xDF , + .gain_u =0x111 , + .gain_v =0x181 , + .gain_y =0x140 , + .black_level =0x3e , + .blank_level =0x3e , + .m_control =0 <<2 |1 <<1 , + .bstamp_wss_data =0x42 , + .s_carr =0x2a098acb , + .l21__wc_ctl =0 <<13 |0x16 <<8 |0 <<0 , + .savid__eavid =0x06A70108 , + .flen__fal =23 <<16 |624 <<0 , + .lal__phase_reset =2 <<17 |310 <<0 , + .hs_int_start_stop_x =0x00920358 , + .hs_ext_start_stop_x =0x000F035F , + .vs_int_start_x =0x1a7 <<16 , + .vs_int_stop_x__vs_int_start_y =0x000601A7 , + .vs_int_stop_y__vs_ext_start_x =0x01AF0036 , + .vs_ext_stop_x__vs_ext_start_y =0x27101af , + .vs_ext_stop_y =0x05 , + .avid_start_stop_x =0x03530082 , + .avid_start_stop_y =0x0270002E , + .fid_int_start_x__fid_int_start_y =0x0005008A , + .fid_int_offset_y__fid_ext_start_x =0x002E0138 , + .fid_ext_start_y__fid_ext_offset_y =0x01380005 , + + .width =720 , + .height =576 , +}; + +static struct { +void __iomem *base; +struct clk *dss_54m_fck; +struct clk *dss_96m_fck; +struct clk *dss_ick; +struct clk *dss1_fck; +const struct venc_config *config; +} venc; + +static struct omap_panel venc_panel = { + .name ="tv-out" , + .x_res =0 , + .y_res =0 , + .bpp =24 , +}; + +static inline void venc_write_reg (int idx,u32 val) +{ +__raw_writel (val, venc.base + idx); +} + +static inline u32 venc_read_reg (int idx) +{ +u32 l =__raw_readl (venc.base + idx); +return l; +} + +static void venc_write_config (const struct venc_config *config) +{ +DSSDBG ("write venc conf\n" ); + +venc_write_reg (VENC_LLEN , config->llen); +venc_write_reg (VENC_FLENS , config->flens); +venc_write_reg (VENC_CC_CARR_WSS_CARR , config->cc_carr_wss_carr); +venc_write_reg (VENC_C_PHASE , config->c_phase); +venc_write_reg (VENC_GAIN_U , config->gain_u); +venc_write_reg (VENC_GAIN_V , config->gain_v); +venc_write_reg (VENC_GAIN_Y , config->gain_y); +venc_write_reg (VENC_BLACK_LEVEL , config->black_level); +venc_write_reg (VENC_BLANK_LEVEL , config->blank_level); +venc_write_reg (VENC_M_CONTROL , config->m_control); +venc_write_reg (VENC_BSTAMP_WSS_DATA , config->bstamp_wss_data); +venc_write_reg (VENC_S_CARR , config->s_carr); +venc_write_reg (VENC_L21__WC_CTL , config->l21__wc_ctl); +venc_write_reg (VENC_SAVID__EAVID , config->savid__eavid); +venc_write_reg (VENC_FLEN__FAL , config->flen__fal); +venc_write_reg (VENC_LAL__PHASE_RESET , config->lal__phase_reset); +venc_write_reg (VENC_HS_INT_START_STOP_X , config->hs_int_start_stop_x); +venc_write_reg (VENC_HS_EXT_START_STOP_X , config->hs_ext_start_stop_x); +venc_write_reg (VENC_VS_INT_START_X , config->vs_int_start_x); +venc_write_reg (VENC_VS_INT_STOP_X__VS_INT_START_Y , + config->vs_int_stop_x__vs_int_start_y); +venc_write_reg (VENC_VS_INT_STOP_Y__VS_EXT_START_X , + config->vs_int_stop_y__vs_ext_start_x); +venc_write_reg (VENC_VS_EXT_STOP_X__VS_EXT_START_Y , + config->vs_ext_stop_x__vs_ext_start_y); +venc_write_reg (VENC_VS_EXT_STOP_Y , config->vs_ext_stop_y); +venc_write_reg (VENC_AVID_START_STOP_X , config->avid_start_stop_x); +venc_write_reg (VENC_AVID_START_STOP_Y , config->avid_start_stop_y); +venc_write_reg (VENC_FID_INT_START_X__FID_INT_START_Y , + config->fid_int_start_x__fid_int_start_y); +venc_write_reg (VENC_FID_INT_OFFSET_Y__FID_EXT_START_X , + config->fid_int_offset_y__fid_ext_start_x); +venc_write_reg (VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y , + config->fid_ext_start_y__fid_ext_offset_y); + +venc_write_reg (VENC_DAC_B__DAC_C ,venc_read_reg (VENC_DAC_B__DAC_C )); +venc_write_reg (VENC_VIDOUT_CTRL , config->vidout_ctrl); +venc_write_reg (VENC_HFLTR_CTRL , config->hfltr_ctrl); +venc_write_reg (VENC_X_COLOR , config->x_color); +venc_write_reg (VENC_LINE21 , config->line21); +venc_write_reg (VENC_LN_SEL , config->ln_sel); +venc_write_reg (VENC_HTRIGGER_VTRIGGER , config->htrigger_vtrigger); +venc_write_reg (VENC_TVDETGP_INT_START_STOP_X , + config->tvdetgp_int_start_stop_x); +venc_write_reg (VENC_TVDETGP_INT_START_STOP_Y , + config->tvdetgp_int_start_stop_y); +venc_write_reg (VENC_GEN_CTRL , config->gen_ctrl); +venc_write_reg (VENC_F_CONTROL , config->f_control); +venc_write_reg (VENC_SYNC_CTRL , config->sync_ctrl); +} + +static void venc_reset (void ) +{ +int t =1000 ; + +venc_write_reg (VENC_F_CONTROL ,venc_read_reg (VENC_F_CONTROL ) | (1 <<8 )); +while (venc_read_reg (VENC_F_CONTROL ) & (1 <<8 )) { +if (--t ==0 ) { +DSSERR ("Failed to reset venc\n" ); +return ; + } + } +} + +static void venc_enable_clocks (int enable) +{ +if (enable) { +clk_enable (venc.dss_ick); +clk_enable (venc.dss1_fck); +clk_enable (venc.dss_54m_fck); +clk_enable (venc.dss_96m_fck); + }else { +clk_disable (venc.dss_96m_fck); +clk_disable (venc.dss_54m_fck); +clk_disable (venc.dss1_fck); +clk_disable (venc.dss_ick); + } +} + +int venc_init (void ) +{ +u8 rev_id; +int use_pal =1 ;/* XXX */ + +if (use_pal) + venc.config = &venc_config_pal_trm; +else + venc.config = &venc_config_ntsc_trm; + + venc_panel.x_res = venc.config->width; + venc_panel.y_res = venc.config->height; + + venc.base =ioremap (VENC_BASE ,SZ_1K ); +if (!venc.base) { +DSSERR ("can't ioremap VENC\n" ); +return -ENOMEM ; + } + + venc.dss_ick =get_dss_ick (); + venc.dss1_fck =get_dss1_fck (); + venc.dss_54m_fck =get_tv_fck (); + venc.dss_96m_fck =get_96m_fck (); + +/* enable clocks */ +venc_enable_clocks (1 ); + +/* configure venc */ +venc_reset (); +venc_write_config (venc.config); + + rev_id = (u8)(venc_read_reg (VENC_REV_ID ) &0xff ); +printk (KERN_INFO "OMAP VENC rev %d\n" , rev_id); + +venc_enable_clocks (0 ); + +return 0 ; +} + +void venc_exit (void ) +{ +iounmap (venc.base); +} + +static int venc_enable_display (struct omap_display *display) +{ +DSSDBG ("venc_enable_display\n" ); + +down (&venc_lock); + +if (display->state !=OMAP_DSS_DISPLAY_DISABLED ) { +up (&venc_lock); +return -EINVAL ; + } + +venc_enable_clocks (1 ); + +dss_set_venc_output (display->hw_config.u.venc.type); +dss_set_dac_pwrdn_bgz (1 ); + +venc_write_config (venc.config); + +if (display->hw_config.u.venc.type ==OMAP_DSS_VENC_TYPE_COMPOSITE ) { +if (cpu_is_omap24xx ()) +venc_write_reg (VENC_OUTPUT_CONTROL ,0x2 ); +else +venc_write_reg (VENC_OUTPUT_CONTROL ,0xa ); + }else {/* S-Video */ +venc_write_reg (VENC_OUTPUT_CONTROL ,0xd ); + } + +dispc_set_digit_size (venc.config->width, venc.config->height/2 ); + +if (display->hw_config.panel_enable) + display->hw_config.panel_enable (display); + +dispc_enable_digit_out (1 ); + + display->state =OMAP_DSS_DISPLAY_ACTIVE ; + +up (&venc_lock); + +return 0 ; +} + +static void venc_disable_display (struct omap_display *display) +{ +DSSDBG ("venc_disable_display\n" ); + +down (&venc_lock); + +if (display->state ==OMAP_DSS_DISPLAY_DISABLED ) { +up (&venc_lock); +return ; + } + +venc_write_reg (VENC_OUTPUT_CONTROL ,0 ); +dss_set_dac_pwrdn_bgz (0 ); + +dispc_enable_digit_out (0 ); + +if (display->hw_config.panel_disable) + display->hw_config.panel_disable (display); + +venc_enable_clocks (0 ); + + display->state =OMAP_DSS_DISPLAY_DISABLED ; + +up (&venc_lock); +} + +void venc_init_display (struct omap_display *display) +{ + display->panel = &venc_panel; + display->enable = venc_enable_display; + display->disable = venc_disable_display; +}
Re: [REVIEW PATCH 4/9] DSS: TV-out support for OMAP2/3 DSS
arch/arm/plat-omap/dss/venc.c line 31
Quoted 9 lines · On Tue, 04 Nov 2008 18:10:12 +0200 "ext Tomi Valkeinen"…
Signed-off-by Tomi Valkeinen <[email protected]>---
arch/arm/plat-omap/dss/venc.c | 499 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 499 insertions(+), 0 deletions(-) create mode 100644 arch/arm/plat-omap/dss/venc.carch/arm/plat-omap/dss/venc.c new file +2
-0+#include <mach/board.h> +#include <mach/gpio.h>
Are these two includes needed?
Jarkko
PATCH 5/9 DSS: DSI support for OMAP2/3 DSS
In reply to Tomi Valkeinen---
arch/arm/plat-omap/dss/dsi.c | 3027 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 3027 insertions(+), 0 deletions(-) create mode 100644 arch/arm/plat-omap/dss/dsi.c
arch/arm/plat-omap/dss/dsi.c new file +3027 -0
@@ -0,0 +1,3027 @@ +/* +* linux/arch/arm/plat-omap/dss/dsi.c +* +* Copyright (C) 2008 Nokia Corporation +* Author: Tomi Valkeinen <[email protected]> +* +* 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 "DSI" + +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/workqueue.h> +#include <linux/mutex.h> + +#include <mach/board.h> +#include <mach/display.h> + +#include "dss.h" + +/*#define VERBOSE*/ +/*#define VERBOSE_IRQ*/ +/*#define MEASURE_PERF*/ + +#define DSI_BASE 0x4804FC00 + +struct dsi_reg {u16 idx; }; + +#define DSI_REG (idx) ((const struct dsi_reg) { idx }) + +/* DSI Protocol Engine */ + +#define DSI_REVISION DSI_REG(0x0000) +#define DSI_SYSCONFIG DSI_REG(0x0010) +#define DSI_SYSSTATUS DSI_REG(0x0014) +#define DSI_IRQSTATUS DSI_REG(0x0018) +#define DSI_IRQENABLE DSI_REG(0x001C) +#define DSI_CTRL DSI_REG(0x0040) +#define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048) +#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C) +#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050) +#define DSI_CLK_CTRL DSI_REG(0x0054) +#define DSI_TIMING1 DSI_REG(0x0058) +#define DSI_TIMING2 DSI_REG(0x005C) +#define DSI_VM_TIMING1 DSI_REG(0x0060) +#define DSI_VM_TIMING2 DSI_REG(0x0064) +#define DSI_VM_TIMING3 DSI_REG(0x0068) +#define DSI_CLK_TIMING DSI_REG(0x006C) +#define DSI_TX_FIFO_VC_SIZE DSI_REG(0x0070) +#define DSI_RX_FIFO_VC_SIZE DSI_REG(0x0074) +#define DSI_COMPLEXIO_CFG2 DSI_REG(0x0078) +#define DSI_RX_FIFO_VC_FULLNESS DSI_REG(0x007C) +#define DSI_VM_TIMING4 DSI_REG(0x0080) +#define DSI_TX_FIFO_VC_EMPTINESS DSI_REG(0x0084) +#define DSI_VM_TIMING5 DSI_REG(0x0088) +#define DSI_VM_TIMING6 DSI_REG(0x008C) +#define DSI_VM_TIMING7 DSI_REG(0x0090) +#define DSI_STOPCLK_TIMING DSI_REG(0x0094) +#define DSI_VC_CTRL (n) DSI_REG(0x0100 + (n * 0x20)) +#define DSI_VC_TE (n) DSI_REG(0x0104 + (n * 0x20)) +#define DSI_VC_LONG_PACKET_HEADER (n) DSI_REG(0x0108 + (n * 0x20)) +#define DSI_VC_LONG_PACKET_PAYLOAD (n) DSI_REG(0x010C + (n * 0x20)) +#define DSI_VC_SHORT_PACKET_HEADER (n) DSI_REG(0x0110 + (n * 0x20)) +#define DSI_VC_IRQSTATUS (n) DSI_REG(0x0118 + (n * 0x20)) +#define DSI_VC_IRQENABLE (n) DSI_REG(0x011C + (n * 0x20)) + +/* DSIPHY_SCP */ + +#define DSIPHY_CFG0 DSI_REG(0x200 + 0x0000) +#define DSIPHY_CFG1 DSI_REG(0x200 + 0x0004) +#define DSIPHY_CFG2 DSI_REG(0x200 + 0x0008) +#define DSIPHY_CFG5 DSI_REG(0x200 + 0x0014) + +/* DSI_PLL_CTRL_SCP */ + +#define DSI_PLL_CONTROL DSI_REG(0x300 + 0x0000) +#define DSI_PLL_STATUS DSI_REG(0x300 + 0x0004) +#define DSI_PLL_GO DSI_REG(0x300 + 0x0008) +#define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C) +#define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010) + +#define REG_GET (idx, start, end) \ + FLD_GET(dsi_read_reg(idx), start, end) + +#define REG_FLD_MOD (idx, val, start, end) \ + dsi_write_reg(idx, FLD_MOD(dsi_read_reg(idx), val, start, end)) + +/* Global interrupts */ +#define DSI_IRQ_VC0 (1 << 0) +#define DSI_IRQ_VC1 (1 << 1) +#define DSI_IRQ_VC2 (1 << 2) +#define DSI_IRQ_VC3 (1 << 3) +#define DSI_IRQ_WAKEUP (1 << 4) +#define DSI_IRQ_RESYNC (1 << 5) +#define DSI_IRQ_PLL_LOCK (1 << 7) +#define DSI_IRQ_PLL_UNLOCK (1 << 8) +#define DSI_IRQ_PLL_RECALL (1 << 9) +#define DSI_IRQ_COMPLEXIO_ERR (1 << 10) +#define DSI_IRQ_HS_TX_TIMEOUT (1 << 14) +#define DSI_IRQ_LP_RX_TIMEOUT (1 << 15) +#define DSI_IRQ_TE_TRIGGER (1 << 16) +#define DSI_IRQ_ACK_TRIGGER (1 << 17) +#define DSI_IRQ_SYNC_LOST (1 << 18) +#define DSI_IRQ_LDO_POWER_GOOD (1 << 19) +#define DSI_IRQ_TA_TIMEOUT (1 << 20) +#define DSI_IRQ_ERROR_MASK \ + (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ + DSI_IRQ_TA_TIMEOUT) +#define DSI_IRQ_CHANNEL_MASK 0xf + +/* Virtual channel interrupts */ +#define DSI_VC_IRQ_CS (1 << 0) +#define DSI_VC_IRQ_ECC_CORR (1 << 1) +#define DSI_VC_IRQ_PACKET_SENT (1 << 2) +#define DSI_VC_IRQ_FIFO_TX_OVF (1 << 3) +#define DSI_VC_IRQ_FIFO_RX_OVF (1 << 4) +#define DSI_VC_IRQ_BTA (1 << 5) +#define DSI_VC_IRQ_ECC_NO_CORR (1 << 6) +#define DSI_VC_IRQ_FIFO_TX_UDF (1 << 7) +#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8) +#define DSI_VC_IRQ_ERROR_MASK \ + (DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \ + DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \ + DSI_VC_IRQ_FIFO_TX_UDF) + +/* ComplexIO interrupts */ +#define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0) +#define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1) +#define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2) +#define DSI_CIO_IRQ_ERRESC1 (1 << 5) +#define DSI_CIO_IRQ_ERRESC2 (1 << 6) +#define DSI_CIO_IRQ_ERRESC3 (1 << 7) +#define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10) +#define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11) +#define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12) +#define DSI_CIO_IRQ_STATEULPS1 (1 << 15) +#define DSI_CIO_IRQ_STATEULPS2 (1 << 16) +#define DSI_CIO_IRQ_STATEULPS3 (1 << 17) +#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20) +#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21) +#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22) +#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23) +#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24) +#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25) +#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30) +#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31) + +#define DSI_DT_DCS_SHORT_WRITE_0 0x05 +#define DSI_DT_DCS_SHORT_WRITE_1 0x15 +#define DSI_DT_DCS_READ 0x06 +#define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37 +#define DSI_DT_NULL_PACKET 0x09 +#define DSI_DT_DCS_LONG_WRITE 0x39 + +#define DSI_DT_RX_ACK_WITH_ERR 0x02 +#define DSI_DT_RX_DCS_LONG_READ 0x1c +#define DSI_DT_RX_SHORT_READ_1 0x21 +#define DSI_DT_RX_SHORT_READ_2 0x22 + +#define FINT_MAX 2100000 +#define FINT_MIN 750000 +#define REGN_MAX (1 << 7) +#define REGM_MAX ((1 << 11) - 1) +#define REGM3_MAX (1 << 4) +#define REGM4_MAX (1 << 4) + +enum fifo_size { +DSI_FIFO_SIZE_0 =0 , +DSI_FIFO_SIZE_32 =1 , +DSI_FIFO_SIZE_64 =2 , +DSI_FIFO_SIZE_96 =3 , +DSI_FIFO_SIZE_128 =4 , +}; + +static struct +{ +void __iomem *base; + +struct clk *dss_ick; +struct clk *dss1_fck; +struct clk *dss2_fck; + +unsigned long dsi1_pll_fclk;/* Hz */ +unsigned long dsi2_pll_fclk;/* Hz */ +unsigned long dsiphy;/* Hz */ +unsigned long ddr_clk;/* Hz */ + +struct { +enum fifo_size fifo_size; +int dest_per;/* destination peripheral 0-3 */ + } vc[4 ]; + +struct mutex lock; + +struct completion bta_completion; + +spinlock_t update_lock; +int update_ongoing; +int update_syncers; +struct completion update_completion; +struct work_struct framedone_work; + +enum omap_dss_update_mode update_mode; +int use_te; +int framedone_scheduled;/* helps to catch strange framedone bugs */ + +struct { +struct omap_display *display; +int x, y, w, h; +int bytespp; + } update_region; + +#ifdef MEASURE_PERF +ktime_t measure_time; +int measure_frames; +#endif +} dsi; + + +static inline void dsi_write_reg (const struct dsi_reg idx,u32 val) +{ +__raw_writel (val, dsi.base + idx.idx); +} + +static inline u32 dsi_read_reg (const struct dsi_reg idx) +{ +return __raw_readl (dsi.base + idx.idx); +} + +static inline int wait_for_bit_change (const struct dsi_reg idx,int bitnum, +int value) +{ +int t =1000 ; + +while (REG_GET (idx, bitnum, bitnum) != value) { +if (--t ==0 ) +return !value; + } + +return value; +} + + +#ifdef MEASURE_PERF +static void start_measuring (void ) +{ + dsi.measure_time =ktime_get (); +} + +static void end_measuring (const char *name) +{ +ktime_t t; +u32 total_bytes; +u32 us; +const int numframes =100 ; + +if (dsi.update_mode ==OMAP_DSS_UPDATE_DISABLED ) +return ; + +if (dsi.update_mode ==OMAP_DSS_UPDATE_AUTO ) { + dsi.measure_frames++; +if (dsi.measure_frames < numframes) +return ; + dsi.measure_frames =0 ; + } + + t =ktime_get (); + t =ktime_sub (t, dsi.measure_time); + us = (u32 )ktime_to_us (t); +if (us ==0 ) + us =1 ; + + total_bytes = dsi.update_region.w * + dsi.update_region.h * + dsi.update_region.bytespp; + +if (dsi.update_mode ==OMAP_DSS_UPDATE_AUTO ) { +DSSINFO ("%s update: %d frames in %u us, %u frames/sec\n" , + name, numframes, + us, +1000 *1000 / us); + }else { +DSSINFO ("%s update in %u us (%u Hz), %u bytes, %u kbytes/sec\n" , + name, + us, +1000 *1000 / us, + total_bytes, + total_bytes *1000 / us); + } +} +#else +#define start_measuring () +#define end_measuring (x) +#endif + + + + +static void print_irq_status (u32 status) +{ +#ifndef VERBOSE_IRQ +if ((status & ~DSI_IRQ_CHANNEL_MASK ) ==0 ) +return ; +#endif +printk (KERN_DEBUG "DSI IRQ: 0x%x: " , status); + +#define PIS (x) \ + if (status & DSI_IRQ_##x) \ + printk(#x " "); +#ifdef VERBOSE_IRQ +PIS (VC0 ); +PIS (VC1 ); +PIS (VC2 ); +PIS (VC3 ); +#endif +PIS (WAKEUP ); +PIS (RESYNC ); +PIS (PLL_LOCK ); +PIS (PLL_UNLOCK ); +PIS (PLL_RECALL ); +PIS (COMPLEXIO_ERR ); +PIS (HS_TX_TIMEOUT ); +PIS (LP_RX_TIMEOUT ); +PIS (TE_TRIGGER ); +PIS (ACK_TRIGGER ); +PIS (SYNC_LOST ); +PIS (LDO_POWER_GOOD ); +PIS (TA_TIMEOUT ); +#undef PIS + +printk ("\n" ); +} + +static void print_irq_status_vc (int channel,u32 status) +{ +#ifndef VERBOSE_IRQ +if ((status & ~DSI_VC_IRQ_PACKET_SENT ) ==0 ) +return ; +#endif +printk (KERN_DEBUG "DSI VC(%d) IRQ 0x%x: " , channel, status); + +#define PIS (x) \ + if (status & DSI_VC_IRQ_##x) \ + printk(#x " "); +PIS (CS ); +PIS (ECC_CORR ); +#ifdef VERBOSE_IRQ +PIS (PACKET_SENT ); +#endif +PIS (FIFO_TX_OVF ); +PIS (FIFO_RX_OVF ); +PIS (BTA ); +PIS (ECC_NO_CORR ); +PIS (FIFO_TX_UDF ); +PIS (PP_BUSY_CHANGE ); +#undef PIS +printk ("\n" ); +} + +static void print_irq_status_cio (u32 status) +{ +printk (KERN_DEBUG "DSI CIO IRQ 0x%x: " , status); + +#define PIS (x) \ + if (status & DSI_CIO_IRQ_##x) \ + printk(#x " "); +PIS (ERRSYNCESC1 ); +PIS (ERRSYNCESC2 ); +PIS (ERRSYNCESC3 ); +PIS (ERRESC1 ); +PIS (ERRESC2 ); +PIS (ERRESC3 ); +PIS (ERRCONTROL1 ); +PIS (ERRCONTROL2 ); +PIS (ERRCONTROL3 ); +PIS (STATEULPS1 ); +PIS (STATEULPS2 ); +PIS (STATEULPS3 ); +PIS (ERRCONTENTIONLP0_1 ); +PIS (ERRCONTENTIONLP1_1 ); +PIS (ERRCONTENTIONLP0_2 ); +PIS (ERRCONTENTIONLP1_2 ); +PIS (ERRCONTENTIONLP0_3 ); +PIS (ERRCONTENTIONLP1_3 ); +PIS (ULPSACTIVENOT_ALL0 ); +PIS (ULPSACTIVENOT_ALL1 ); +#undef PIS + +printk ("\n" ); +} + +static int debug_irq; + +/* called from dss */ +void dsi_irq_handler (void ) +{ +u32 irqstatus, vcstatus, ciostatus; +int i; + + irqstatus =dsi_read_reg (DSI_IRQSTATUS ); + +if (irqstatus &DSI_IRQ_ERROR_MASK ) { +DSSERR ("DSI error, irqstatus %x\n" , irqstatus); +print_irq_status (irqstatus); + }else if (debug_irq) { +print_irq_status (irqstatus); + } + +for (i =0 ; i <4 ; ++i) { +if ((irqstatus & (1 <<i)) ==0 ) +continue ; + + vcstatus =dsi_read_reg (DSI_VC_IRQSTATUS (i)); + +if (vcstatus &DSI_VC_IRQ_BTA ) +complete (&dsi.bta_completion); + +if (vcstatus &DSI_VC_IRQ_ERROR_MASK ) { +DSSERR ("DSI VC(%d) error, vc irqstatus %x\n" , + i, vcstatus); +print_irq_status_vc (i, vcstatus); + }else if (debug_irq) { +print_irq_status_vc (i, vcstatus); + } + +dsi_write_reg (DSI_VC_IRQSTATUS (i), vcstatus); + } + +if (irqstatus &DSI_IRQ_COMPLEXIO_ERR ) { + ciostatus =dsi_read_reg (DSI_COMPLEXIO_IRQ_STATUS ); + +dsi_write_reg (DSI_COMPLEXIO_IRQ_STATUS , ciostatus); + +DSSERR ("DSI CIO error, cio irqstatus %x\n" , ciostatus); +print_irq_status_cio (ciostatus); + } + +dsi_write_reg (DSI_IRQSTATUS , irqstatus & ~DSI_IRQ_CHANNEL_MASK ); +} + + +static void _dsi_initialize_irq (void ) +{ +u32 l; +int i; + +/* disable all interrupts */ +dsi_write_reg (DSI_IRQENABLE ,0 ); +for (i =0 ; i <4 ; ++i) +dsi_write_reg (DSI_VC_IRQENABLE (i),0 ); +dsi_write_reg (DSI_COMPLEXIO_IRQ_ENABLE ,0 ); + +/* clear interrupt status */ + l =dsi_read_reg (DSI_IRQSTATUS ); +dsi_write_reg (DSI_IRQSTATUS , l & ~DSI_IRQ_CHANNEL_MASK ); + +for (i =0 ; i <4 ; ++i) { + l =dsi_read_reg (DSI_VC_IRQSTATUS (i)); +dsi_write_reg (DSI_VC_IRQSTATUS (i), l); + } + + l =dsi_read_reg (DSI_COMPLEXIO_IRQ_STATUS ); +dsi_write_reg (DSI_COMPLEXIO_IRQ_STATUS , l); + +/* enable error irqs */ + l =DSI_IRQ_ERROR_MASK ; +dsi_write_reg (DSI_IRQENABLE , l); + + l =DSI_VC_IRQ_ERROR_MASK ; +for (i =0 ; i <4 ; ++i) +dsi_write_reg (DSI_VC_IRQENABLE (i), l); + +/* XXX zonda responds incorrectly, causing control error: +Exit from LP-ESC mode to LP11 uses wrong transition states on the +data lines LP0 and LN0. */ +dsi_write_reg (DSI_COMPLEXIO_IRQ_ENABLE , +-1 & (~DSI_CIO_IRQ_ERRCONTROL2 )); +} + +static void dsi_vc_enable_bta_irq (int channel) +{ +u32 l; + + l =dsi_read_reg (DSI_VC_IRQENABLE (channel)); + l |=DSI_VC_IRQ_BTA ; +dsi_write_reg (DSI_VC_IRQENABLE (channel), l); +} + +static void dsi_vc_disable_bta_irq (int channel) +{ +u32 l; + + l =dsi_read_reg (DSI_VC_IRQENABLE (channel)); + l &= ~DSI_VC_IRQ_BTA ; +dsi_write_reg (DSI_VC_IRQENABLE (channel), l); +} + +/* DSI func clock. this could also be DSI2_PLL_FCLK */ +static inline void enable_clocks (int enable) +{ +if (enable) { +clk_enable (dsi.dss_ick); +clk_enable (dsi.dss1_fck); + }else { +clk_disable (dsi.dss1_fck); +clk_disable (dsi.dss_ick); + } +} + +/* source clock for DSI PLL. this could also be PCLKFREE */ +static inline void dsi_enable_pll_clock (int enable) +{ +if (enable) +clk_enable (dsi.dss2_fck); +else +clk_disable (dsi.dss2_fck); +} + +#if 1 + +#ifdef DEBUG +static void _dsi_print_reset_status (void ) +{ +u32 l; + +/* A dummy read using the SCP interface to any DSIPHY register is +* required after DSIPHY reset to complete the reset of the DSI complex +* I/O. */ + l =dsi_read_reg (DSIPHY_CFG5 ); + +printk (KERN_DEBUG "DSI resets: " ); + + l =dsi_read_reg (DSI_PLL_STATUS ); +printk ("PLL (%d) " ,FLD_GET (l,0 ,0 )); + + l =dsi_read_reg (DSI_COMPLEXIO_CFG1 ); +printk ("CIO (%d) " ,FLD_GET (l,29 ,29 )); + + l =dsi_read_reg (DSIPHY_CFG5 ); +printk ("PHY (%x, %d, %d, %d)\n" , +FLD_GET (l,28 ,26 ), +FLD_GET (l,29 ,29 ), +FLD_GET (l,30 ,30 ), +FLD_GET (l,31 ,31 )); +} +#else +#define _dsi_print_reset_status () +#endif + +static int _dsi_reset (void ) +{ +int r =0 ; + +/* Soft reset */ +REG_FLD_MOD (DSI_SYSCONFIG ,1 ,1 ,1 ); + +if (wait_for_bit_change (DSI_SYSSTATUS ,0 ,1 ) !=1 ) { +DSSERR ("soft reset failed\n" ); + r = -ENODEV ; + } + +/* A dummy read using the SCP interface to any DSIPHY register is +* required after DSIPHY reset to complete the reset of the DSI complex +* I/O. */ +dsi_read_reg (DSIPHY_CFG5 ); + +_dsi_print_reset_status (); + +return r; +} +#endif + +static inline int dsi_if_enable (int enable) +{ +DSSDBG ("dsi_if_enable(%d)\n" , enable); + + enable = enable ?1 :0 ; +REG_FLD_MOD (DSI_CTRL , enable,0 ,0 );/* IF_EN */ + +if (wait_for_bit_change (DSI_CTRL ,0 , enable) != enable) { +DSSERR ("Failed to set dsi_if_enable to %d\n" , enable); +return -EIO ; + } + +return 0 ; +} + +static unsigned long dsi_fclk_rate (void ) +{ +unsigned long r; + +if (dss_get_dsi_clk_source () ==0 ) { +/* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */ + r =clk_get_rate (dsi.dss1_fck); + }else { +/* DSI FCLK source is DSI2_PLL_FCLK */ + r = dsi.dsi2_pll_fclk; + } + +return r; +} + +static int dsi_set_lp_clk_divisor (void ) +{ +int n; +unsigned long dsi_fclk; +unsigned long mhz; + +/* LP_CLK_DIVISOR, DSI fclk/n, should be 20MHz - 32kHz */ + + dsi_fclk =dsi_fclk_rate (); + +for (n =1 ; n < (1 <<13 ) -1 ; ++n) { + mhz = dsi_fclk / n; +if (mhz <=20 *1000 *1000 ) +break ; + } + +if (n == (1 <<13 ) -1 ) { +DSSERR ("DSI: Failed to find LP_CLK_DIVISOR\n" ); +return -EINVAL ; + } + +DSSDBG ("LP_CLK_DIV %d, LP_CLK %ld\n" , n, mhz); + +REG_FLD_MOD (DSI_CLK_CTRL , n,12 ,0 );/* LP_CLK_DIVISOR */ +if (dsi_fclk >30 *1000 *1000 ) +REG_FLD_MOD (DSI_CLK_CTRL ,1 ,21 ,21 );/* LP_RX_SYNCHRO_ENABLE */ + +return 0 ; +} + + +enum dsi_pll_power_state { +DSI_PLL_POWER_OFF =0x0 , +DSI_PLL_POWER_ON_HSCLK =0x1 , +DSI_PLL_POWER_ON_ALL =0x2 , +DSI_PLL_POWER_ON_DIV =0x3 , +}; + +static int dsi_pll_power (enum dsi_pll_power_state state) +{ +int t =0 ; + +REG_FLD_MOD (DSI_CLK_CTRL , state,31 ,30 );/* PLL_PWR_CMD */ + +/* PLL_PWR_STATUS */ +while (FLD_GET (dsi_read_reg (DSI_CLK_CTRL ),29 ,28 ) != state) { +udelay (1 ); +if (t++ >1000 ) { +DSSERR ("DSI: Failed to set DSI PLL power mode to %d\n" , + state); +return -ENODEV ; + } + } + +return 0 ; +} + +/* return 1 for exact match */ +static int iterate_dispc_divs (int is_tft,unsigned long pck, +struct dsi_clock_info *cur,struct dsi_clock_info *best) +{ +int pcd_min = is_tft ?2 :3 ; + +for (cur->lck_div =1 ; cur->lck_div <=255 ; ++cur->lck_div) { +unsigned long lck = cur->dispc_fck / cur->lck_div; + +for (cur->pck_div = pcd_min; cur->pck_div <=255 ; + ++cur->pck_div) { + + cur->pck = lck / cur->pck_div; + +if (abs (cur->pck - pck) <abs (best->pck - pck)) { + *best = *cur; +/* +DSSDBG("best match fck %ld, pck %ld, regn %d, " +"regm %d, regm3 %d, ld %d, pd %d\n", +best->dispc_fck, +best->pck, +best->regn, best->regm, +best->regm3, +best->lck_div, best->pck_div); +*/ + } + +if (cur->pck == pck) +return 1 ; + +if (cur->pck < pck) +break ; + } + +if (lck / pcd_min < cur->pck) +break ; + } + +return 0 ; +} + +int dsi_pll_calc_pck (int is_tft,unsigned long pck, +struct dsi_clock_info *cinfo) +{ +struct dsi_clock_info cur, best; + +DSSDBG ("dsi_pll_calc\n" ); + +memset (&best,0 ,sizeof (best)); + +memset (&cur,0 ,sizeof (cur)); + cur.clkin =clk_get_rate (dsi.dss2_fck); + cur.use_dss2_fck =1 ; + cur.highfreq =0 ; + +/* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ +/* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ +/* To reduce PLL lock time, keep Fint high (around 2 MHz) */ +for (cur.regn =1 ; cur.regn <REGN_MAX ; ++cur.regn) { +if (cur.highfreq ==0 ) + cur.fint = cur.clkin / cur.regn; +else + cur.fint = cur.clkin / (2 * cur.regn); + +if (cur.fint >FINT_MAX || cur.fint <FINT_MIN ) +continue ; + +/* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ +for (cur.regm =1 ; cur.regm <REGM_MAX ; ++cur.regm) { +unsigned long a, b; + + a =2 * cur.regm * (cur.clkin/1000 ); + b = cur.regn * (cur.highfreq +1 ); + cur.dsiphy = a / b *1000 ; + +if (cur.dsiphy >1800 *1000 *1000 ) +break ; + +/* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */ +for (cur.regm3 =1 ; cur.regm3 <REGM3_MAX ; + ++cur.regm3) { +int r; + + cur.dispc_fck = cur.dsiphy / cur.regm3; + +/* this will narrow down the search a bit, +* but still give pixclocks below what was +* requested */ +if (cur.dispc_fck < pck) +break ; + +if (cur.dispc_fck >DISPC_MAX_FCK ) +continue ; + +#ifdef CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK +if (cur.dispc_fck < + pck *CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK ) +continue ; +#endif + r =iterate_dispc_divs (is_tft, pck, + &cur, &best); +if (r ==1 ) + goto found; + + } + } + } +found: + +/* DSI2_PLL_FCLK(MHz) = DSIPHY(MHz) / regm4 < 173MHz */ +/* hardcoded 48MHz for now. what should it be? */ + best.regm4 = best.dsiphy / (48000000 ); +if (best.regm4 >REGM4_MAX ) + best.regm4 =REGM4_MAX ; + best.dsi_fck = best.dsiphy / best.regm4; + + *cinfo = best; + +return 0 ; +} + +static int dsi_pll_calc_datafreq (unsigned long datafreq, +struct dsi_clock_info *cinfo) +{ +struct dsi_clock_info cur, best; +const int use_dss2_fck =1 ; + +DSSDBG ("dsi_pll_calc_datarate\n" ); + +memset (&best,0 ,sizeof (best)); + +memset (&cur,0 ,sizeof (cur)); + cur.use_dss2_fck = use_dss2_fck; +if (use_dss2_fck) { + cur.clkin =clk_get_rate (dsi.dss2_fck); + cur.highfreq =0 ; + }else { + cur.clkin =dispc_pclk_rate (); +if (cur.clkin <32000000 ) + cur.highfreq =0 ; +else + cur.highfreq =1 ; + } + +/* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ +/* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ +/* To reduce PLL lock time, keep Fint high (around 2 MHz) */ +for (cur.regn =1 ; cur.regn <REGN_MAX ; ++cur.regn) { +if (cur.highfreq ==0 ) + cur.fint = cur.clkin / cur.regn; +else + cur.fint = cur.clkin / (2 * cur.regn); + +if (cur.fint >FINT_MAX || cur.fint <FINT_MIN ) +continue ; + +/* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ +for (cur.regm =1 ; cur.regm <REGM_MAX ; ++cur.regm) { +unsigned long a, b; + + a =2 * cur.regm * (cur.clkin/1000 ); + b = cur.regn * (cur.highfreq +1 ); + cur.dsiphy = a / b *1000 ; + +if (cur.dsiphy >1800 *1000 *1000 ) +break ; + +if (abs (cur.dsiphy - datafreq) < +abs (best.dsiphy - datafreq)) { + best = cur; +/* DSSDBG("best %ld\n", best.dsiphy); */ + } + +if (cur.dsiphy == datafreq) + goto found; + } + } +found: +/* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */ +/* hardcoded 48MHz for now. what should it be? */ + best.regm3 = best.dsiphy / (48000000 ); +if (best.regm3 >REGM3_MAX ) + best.regm3 =REGM3_MAX ; + best.dispc_fck = best.dsiphy / best.regm3; + +/* DSI2_PLL_FCLK(MHz) = DSIPHY(MHz) / regm4 < 173MHz */ +/* hardcoded 48MHz for now. what should it be? */ + best.regm4 = best.dsiphy / (48000000 ); +if (best.regm4 >REGM4_MAX ) + best.regm4 =REGM4_MAX ; + best.dsi_fck = best.dsiphy / best.regm4; + + *cinfo = best; + +return 0 ; +} + +int dsi_pll_program (struct dsi_clock_info *cinfo) +{ +int r =0 ; +u32 l; + +DSSDBG ("dsi_pll_program\n" ); + +enable_clocks (1 ); + + dsi.dsiphy = cinfo->dsiphy; + dsi.ddr_clk = dsi.dsiphy /4 ; + dsi.dsi1_pll_fclk = cinfo->dispc_fck; + dsi.dsi2_pll_fclk = cinfo->dsi_fck; + +DSSDBG ("DSI Fint %ld\n" , cinfo->fint); + +DSSDBG ("clkin (%s) rate %ld, highfreq %d\n" , + cinfo->use_dss2_fck ?"dss2_fck" :"pclkfree" , + cinfo->clkin, + cinfo->highfreq); + +/* DSIPHY == CLKIN4DDR */ +DSSDBG ("DSIPHY = 2 * %d / %d * %lu / %d = %lu\n" , + cinfo->regm, + cinfo->regn, + cinfo->clkin, + cinfo->highfreq +1 , + cinfo->dsiphy); + +DSSDBG ("Data rate on 1 DSI lane %ld Mbps\n" , + dsi.dsiphy /1000 /1000 /2 ); + +DSSDBG ("Clock lane freq %ld Hz\n" , dsi.ddr_clk); + +DSSDBG ("regm3 = %d, dsi1_pll_fclk = %lu\n" , + cinfo->regm3, cinfo->dispc_fck); +DSSDBG ("regm4 = %d, dsi2_pll_fclk = %lu\n" , + cinfo->regm4, cinfo->dsi_fck); + +REG_FLD_MOD (DSI_PLL_CONTROL ,0 ,0 ,0 );/* DSI_PLL_AUTOMODE = manual */ + + l =dsi_read_reg (DSI_PLL_CONFIGURATION1 ); + l =FLD_MOD (l,1 ,0 ,0 );/* DSI_PLL_STOPMODE */ + l =FLD_MOD (l, cinfo->regn -1 ,7 ,1 );/* DSI_PLL_REGN */ + l =FLD_MOD (l, cinfo->regm,18 ,8 );/* DSI_PLL_REGM */ + l =FLD_MOD (l, cinfo->regm3 -1 ,22 ,19 );/* DSI_CLOCK_DIV */ + l =FLD_MOD (l, cinfo->regm4 -1 ,26 ,23 );/* DSIPROTO_CLOCK_DIV */ +dsi_write_reg (DSI_PLL_CONFIGURATION1 , l); + + l =dsi_read_reg (DSI_PLL_CONFIGURATION2 ); + l =FLD_MOD (l,7 ,4 ,1 );/* DSI_PLL_FREQSEL */ +/* DSI_PLL_CLKSEL */ + l =FLD_MOD (l, cinfo->use_dss2_fck ?0 :1 ,11 ,11 ); + l =FLD_MOD (l, cinfo->highfreq,12 ,12 );/* DSI_PLL_HIGHFREQ */ + l =FLD_MOD (l,1 ,13 ,13 );/* DSI_PLL_REFEN */ + l =FLD_MOD (l,0 ,14 ,14 );/* DSIPHY_CLKINEN */ + l =FLD_MOD (l,1 ,20 ,20 );/* DSI_HSDIVBYPASS */ +dsi_write_reg (DSI_PLL_CONFIGURATION2 , l); + +REG_FLD_MOD (DSI_PLL_GO ,1 ,0 ,0 );/* DSI_PLL_GO */ + +if (wait_for_bit_change (DSI_PLL_GO ,0 ,0 ) !=0 ) { +DSSERR ("dsi pll go bit not going down.\n" ); + r = -EIO ; + goto err; + } + +if (wait_for_bit_change (DSI_PLL_STATUS ,1 ,1 ) !=1 ) { +DSSERR ("DSI: cannot lock PLL\n" ); + r = -EIO ; + goto err; + } + + l =dsi_read_reg (DSI_PLL_CONFIGURATION2 ); + l =FLD_MOD (l,0 ,0 ,0 );/* DSI_PLL_IDLE */ + l =FLD_MOD (l,0 ,5 ,5 );/* DSI_PLL_PLLLPMODE */ + l =FLD_MOD (l,0 ,6 ,6 );/* DSI_PLL_LOWCURRSTBY */ + l =FLD_MOD (l,0 ,7 ,7 );/* DSI_PLL_TIGHTPHASELOCK */ + l =FLD_MOD (l,0 ,8 ,8 );/* DSI_PLL_DRIFTGUARDEN */ + l =FLD_MOD (l,0 ,10 ,9 );/* DSI_PLL_LOCKSEL */ + l =FLD_MOD (l,1 ,13 ,13 );/* DSI_PLL_REFEN */ + l =FLD_MOD (l,1 ,14 ,14 );/* DSIPHY_CLKINEN */ + l =FLD_MOD (l,0 ,15 ,15 );/* DSI_BYPASSEN */ + l =FLD_MOD (l,1 ,16 ,16 );/* DSS_CLOCK_EN */ + l =FLD_MOD (l,0 ,17 ,17 );/* DSS_CLOCK_PWDN */ + l =FLD_MOD (l,1 ,18 ,18 );/* DSI_PROTO_CLOCK_EN */ + l =FLD_MOD (l,0 ,19 ,19 );/* DSI_PROTO_CLOCK_PWDN */ + l =FLD_MOD (l,0 ,20 ,20 );/* DSI_HSDIVBYPASS */ +dsi_write_reg (DSI_PLL_CONFIGURATION2 , l); + +DSSDBG ("PLL config done\n" ); +err: +enable_clocks (0 ); + +return r; +} + +int dsi_pll_init (int enable_hsclk,int enable_hsdiv) +{ +int r =0 ; +int fck_div, lck_div, pck_div; +unsigned long fck; +enum dsi_pll_power_state pwstate; + +DSSDBG ("PLL init\n" ); + +enable_clocks (1 ); +dsi_enable_pll_clock (1 ); + +/* configure dispc fck and pixel clock to something sane */ + fck =dispc_calc_clock_div (1 ,48 *1000 *1000 , + &fck_div, &lck_div, &pck_div); +if (fck ==0 ) +return -EINVAL ; + +dispc_set_clock_div (fck_div, lck_div, pck_div); + +/* PLL does not come out of reset without this... */ +dispc_pck_free_enable (1 ); + +if (wait_for_bit_change (DSI_PLL_STATUS ,0 ,1 ) !=1 ) { +DSSERR ("DSI: PLL not coming out of reset.\n" ); + r = -ENODEV ; + goto err; + } + +/* ... but if left on, we get problems when planes do not +* fill the whole display. No idea about this XXX */ +dispc_pck_free_enable (0 ); + +if (enable_hsclk && enable_hsdiv) + pwstate =DSI_PLL_POWER_ON_ALL ; +else if (enable_hsclk) + pwstate =DSI_PLL_POWER_ON_HSCLK ; +else if (enable_hsdiv) + pwstate =DSI_PLL_POWER_ON_DIV ; +else + pwstate =DSI_PLL_POWER_OFF ; + + r =dsi_pll_power (pwstate); + +if (r) + goto err; + +enable_clocks (0 ); + +DSSDBG ("PLL init done\n" ); + +return 0 ; +err: +enable_clocks (0 ); +dsi_enable_pll_clock (0 ); +return r; +} + +void dsi_pll_uninit (void ) +{ +dsi_pll_power (DSI_PLL_POWER_OFF ); +dsi_enable_pll_clock (0 ); +DSSDBG ("PLL uninit done\n" ); +} + +unsigned long dsi_get_dsi1_pll_rate (void ) +{ +return dsi.dsi1_pll_fclk; +} + +unsigned long dsi_get_dsi2_pll_rate (void ) +{ +return dsi.dsi2_pll_fclk; +} + +ssize_t dsi_print_clocks (char *buf,ssize_t size) +{ +ssize_t l =0 ; +int clksel; + +enable_clocks (1 ); + + clksel =REG_GET (DSI_PLL_CONFIGURATION2 ,11 ,11 ); + + l +=snprintf (buf + l, size - l,"- dsi -\n" ); + + l +=snprintf (buf + l, size - l,"dsi fclk source = %s\n" , +dss_get_dsi_clk_source () ==0 ? +"dss1_alwon_fclk" :"dsi2_pll_fclk" ); + + l +=snprintf (buf + l, size - l,"dsi pll source = %s\n" , + clksel ==0 ? +"dss2_alwon_fclk" :"pclkfree" ); + + l +=snprintf (buf + l, size - l, +"DSIPHY\t\t%lu\nDDR_CLK\t\t%lu\n" , + dsi.dsiphy, dsi.ddr_clk); + + l +=snprintf (buf + l, size - l, +"dsi1_pll_fck\t%lu (%s)\n" +"dsi2_pll_fck\t%lu (%s)\n" , + dsi.dsi1_pll_fclk, +dss_get_dispc_clk_source () ==0 ?"off" :"on" , + dsi.dsi2_pll_fclk, +dss_get_dsi_clk_source () ==0 ?"off" :"on" ); + +enable_clocks (0 ); + +return l; +} + + +enum dsi_complexio_power_state { +DSI_COMPLEXIO_POWER_OFF =0x0 , +DSI_COMPLEXIO_POWER_ON =0x1 , +DSI_COMPLEXIO_POWER_ULPS =0x2 , +}; + +static int dsi_complexio_power (enum dsi_complexio_power_state state) +{ +int t =0 ; + +/* PWR_CMD */ +REG_FLD_MOD (DSI_COMPLEXIO_CFG1 , state,28 ,27 ); + +/* PWR_STATUS */ +while (FLD_GET (dsi_read_reg (DSI_COMPLEXIO_CFG1 ),26 ,25 ) != state) { +udelay (1 ); +if (t++ >1000 ) { +DSSERR ("DSI: failed to set complexio power state to " +"%d\n" , state); +return -ENODEV ; + } + } + +return 0 ; +} + +static void dsi_complexio_config (struct omap_display *display) +{ +u32 r; + +int clk_lane = display->hw_config.u.dsi.clk_lane; +int data1_lane = display->hw_config.u.dsi.data1_lane; +int data2_lane = display->hw_config.u.dsi.data2_lane; +int clk_pol = display->hw_config.u.dsi.clk_pol; +int data1_pol = display->hw_config.u.dsi.data1_pol; +int data2_pol = display->hw_config.u.dsi.data2_pol; + + r =dsi_read_reg (DSI_COMPLEXIO_CFG1 ); + r =FLD_MOD (r, clk_lane,2 ,0 ); + r =FLD_MOD (r, clk_pol,3 ,3 ); + r =FLD_MOD (r, data1_lane,6 ,4 ); + r =FLD_MOD (r, data1_pol,7 ,7 ); + r =FLD_MOD (r, data2_lane,10 ,8 ); + r =FLD_MOD (r, data2_pol,11 ,11 ); +dsi_write_reg (DSI_COMPLEXIO_CFG1 , r); + +/* The configuration of the DSI complex I/O (number of data lanes, +position, differential order) should not be changed while +DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for +the hardware to take into account a new configuration of the complex +I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to +follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, +then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set +DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the +DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the +DSI complex I/O configuration is unknown. */ + +/* +REG_FLD_MOD(DSI_CTRL, 1, 0, 0); +REG_FLD_MOD(DSI_CTRL, 0, 0, 0); +REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); +REG_FLD_MOD(DSI_CTRL, 1, 0, 0); +*/ +} + +static inline int ns2ddr (int ns) +{ +/* convert time in ns to ddr ticks, rounding up */ +return (ns * (dsi.ddr_clk/1000 /1000 ) +999 ) /1000 ; +} + +static void dsi_complexio_timings (void ) +{ +u32 r; +u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit; +u32 tlpx_half, tclk_trail, tclk_zero; +u32 tclk_prepare; + +/* calculate timings */ + +/* 1 * DDR_CLK = 2 * UI */ + +/* min 40ns + 4*UI max 85ns + 6*UI */ + ths_prepare =ns2ddr (59 ) +2 ; + +/* min 145ns + 10*UI */ + ths_prepare_ths_zero =ns2ddr (145 ) +5 ; + +/* min max(8*UI, 60ns+4*UI) */ + ths_trail =max (4 ,ns2ddr (60 ) +2 ); + +/* min 100ns */ + ths_exit =ns2ddr (100 ); + +/* tlpx min 50n */ + tlpx_half =ns2ddr (25 ); + +/* min 60ns */ + tclk_trail =ns2ddr (60 ); + +/* min 38ns, max 95ns */ + tclk_prepare =ns2ddr (38 ); + +/* min tclk-prepare + tclk-zero = 300ns */ + tclk_zero =ns2ddr (300 -38 ); + +#ifdef VERBOSE +DSSDBG ("ths_prepare %d, ths_prepare_ths_zero %d\n" , + ths_prepare, ths_prepare_ths_zero); +DSSDBG ("ths_trail %d, ths_exit %d\n" , ths_trail, ths_exit); + + +DSSDBG ("tlpx_half %d, tclk_trail %d, tclk_zero %d\n" , tlpx_half, + tclk_trail, tclk_zero); +DSSDBG ("tclk_prepare %d\n" , tclk_prepare); +#endif + +/* program timings */ + + r =dsi_read_reg (DSIPHY_CFG0 ); + r =FLD_MOD (r, ths_prepare,31 ,24 ); + r =FLD_MOD (r, ths_prepare_ths_zero,23 ,16 ); + r =FLD_MOD (r, ths_trail,15 ,8 ); + r =FLD_MOD (r, ths_exit,7 ,0 ); +dsi_write_reg (DSIPHY_CFG0 , r); + + r =dsi_read_reg (DSIPHY_CFG1 ); + r =FLD_MOD (r, tlpx_half,22 ,16 ); + r =FLD_MOD (r, tclk_trail,15 ,8 ); + r =FLD_MOD (r, tclk_zero,7 ,0 ); +dsi_write_reg (DSIPHY_CFG1 , r); + + r =dsi_read_reg (DSIPHY_CFG2 ); + r =FLD_MOD (r, tclk_prepare,7 ,0 ); +dsi_write_reg (DSIPHY_CFG2 , r); +} + + +static int dsi_complexio_init (struct omap_display *display) +{ +int r =0 ; + +DSSDBG ("dsi_complexio_init\n" ); + +/* CIO_CLK_ICG, enable L3 clk to CIO */ +REG_FLD_MOD (DSI_CLK_CTRL ,1 ,14 ,14 ); + +if (wait_for_bit_change (DSIPHY_CFG5 ,30 ,1 ) !=1 ) { +DSSERR ("DSI: ComplexIO PHY not coming out of reset.\n" ); + r = -ENODEV ; + goto err; + } + +dsi_complexio_config (display); + + r =dsi_complexio_power (DSI_COMPLEXIO_POWER_ON ); + +if (r) + goto err; + +if (wait_for_bit_change (DSI_COMPLEXIO_CFG1 ,29 ,1 ) !=1 ) { +DSSERR ("DSI: ComplexIO not coming out of reset.\n" ); + r = -ENODEV ; + goto err; + } + +if (wait_for_bit_change (DSI_COMPLEXIO_CFG1 ,21 ,1 ) !=1 ) { +DSSERR ("DSI: ComplexIO LDO power down.\n" ); + r = -ENODEV ; + goto err; + } + +dsi_complexio_timings (); + +/* +The configuration of the DSI complex I/O (number of data lanes, +position, differential order) should not be changed while +DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the +hardware to recognize a new configuration of the complex I/O (done +in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow +this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next +reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20] +LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN +bit to 1. If the sequence is not followed, the DSi complex I/O +configuration is undetermined. +*/ +dsi_if_enable (1 ); +dsi_if_enable (0 ); +REG_FLD_MOD (DSI_CLK_CTRL ,1 ,20 ,20 );/* LP_CLK_ENABLE */ +dsi_if_enable (1 ); +dsi_if_enable (0 ); + +DSSDBG ("CIO init done\n" ); +err: +return r; +} + +static void dsi_complexio_uninit (void ) +{ +dsi_complexio_power (DSI_COMPLEXIO_POWER_OFF ); +} + + + +static void dsi_config_tx_fifo (enum fifo_size size1,enum fifo_size size2, +enum fifo_size size3,enum fifo_size size4) +{ +u32 r =0 ; +int add =0 ; +int i; + + dsi.vc[0 ].fifo_size = size1; + dsi.vc[1 ].fifo_size = size2; + dsi.vc[2 ].fifo_size = size3; + dsi.vc[3 ].fifo_size = size4; + +for (i =0 ; i <4 ; i++) { +u8 v; +int size = dsi.vc[i].fifo_size; + +if (add + size >4 ) { +DSSERR ("DSI: Illegal FIFO configuration\n" ); +BUG (); + } + + v =FLD_VAL (add,2 ,0 ) |FLD_VAL (size,7 ,4 ); + r |= v << (8 * i); +/*DSSDBG("TX FIFO vc %d: size %d, add %d\n", i, size, add); */ + add += size; + } + +dsi_write_reg (DSI_TX_FIFO_VC_SIZE , r); +} + +static void dsi_config_rx_fifo (enum fifo_size size1,enum fifo_size size2, +enum fifo_size size3,enum fifo_size size4) +{ +u32 r =0 ; +int add =0 ; +int i; + + dsi.vc[0 ].fifo_size = size1; + dsi.vc[1 ].fifo_size = size2; + dsi.vc[2 ].fifo_size = size3; + dsi.vc[3 ].fifo_size = size4; + +for (i =0 ; i <4 ; i++) { +u8 v; +int size = dsi.vc[i].fifo_size; + +if (add + size >4 ) { +DSSERR ("DSI: Illegal FIFO configuration\n" ); +BUG (); + } + + v =FLD_VAL (add,2 ,0 ) |FLD_VAL (size,7 ,4 ); + r |= v << (8 * i); +/*DSSDBG("RX FIFO vc %d: size %d, add %d\n", i, size, add); */ + add += size; + } + +dsi_write_reg (DSI_RX_FIFO_VC_SIZE , r); +} + +static int dsi_force_tx_stop_mode_io (void ) +{ +u32 r; + + r =dsi_read_reg (DSI_TIMING1 ); + r =FLD_MOD (r,1 ,15 ,15 );/* FORCE_TX_STOP_MODE_IO */ +dsi_write_reg (DSI_TIMING1 , r); + +if (wait_for_bit_change (DSI_TIMING1 ,15 ,0 ) !=0 ) { +DSSERR ("TX_STOP bit not going down\n" ); +return -EIO ; + } + +return 0 ; +} + +static void dsi_vc_print_status (int channel) +{ +u32 r; + + r =dsi_read_reg (DSI_VC_CTRL (channel)); +DSSDBG ("vc %d: TX_FIFO_NOT_EMPTY %d, BTA_EN %d, VC_BUSY %d, " +"TX_FIFO_FULL %d, RX_FIFO_NOT_EMPTY %d, " , + channel, +FLD_GET (r,5 ,5 ), +FLD_GET (r,6 ,6 ), +FLD_GET (r,15 ,15 ), +FLD_GET (r,16 ,16 ), +FLD_GET (r,20 ,20 )); + + r =dsi_read_reg (DSI_TX_FIFO_VC_EMPTINESS ); +DSSDBG ("EMPTINESS %d\n" , (r >> (8 * channel)) &0xff ); +} + +static void dsi_vc_config (int channel) +{ +u32 r; + +DSSDBG ("dsi_vc_config %d\n" , channel); + + r =dsi_read_reg (DSI_VC_CTRL (channel)); + + r =FLD_MOD (r,0 ,1 ,1 );/* SOURCE, 0 = L4 */ + r =FLD_MOD (r,0 ,2 ,2 );/* BTA_SHORT_EN */ + r =FLD_MOD (r,0 ,3 ,3 );/* BTA_LONG_EN */ + r =FLD_MOD (r,0 ,4 ,4 );/* MODE, 0 = command */ + r =FLD_MOD (r,1 ,7 ,7 );/* CS_TX_EN */ + r =FLD_MOD (r,1 ,8 ,8 );/* ECC_TX_EN */ + r =FLD_MOD (r,0 ,9 ,9 );/* MODE_SPEED, high speed on/off */ + + r =FLD_MOD (r,4 ,29 ,27 );/* DMA_RX_REQ_NB = no dma */ + r =FLD_MOD (r,4 ,23 ,21 );/* DMA_TX_REQ_NB = no dma */ + +dsi_write_reg (DSI_VC_CTRL (channel), r); +} + +static void dsi_vc_config_vp (int channel) +{ +u32 r; + +DSSDBG ("dsi_vc_config_vp\n" ); + + r =dsi_read_reg (DSI_VC_CTRL (channel)); + + r =FLD_MOD (r,1 ,1 ,1 );/* SOURCE, 1 = video port */ + r =FLD_MOD (r,0 ,2 ,2 );/* BTA_SHORT_EN */ + r =FLD_MOD (r,0 ,3 ,3 );/* BTA_LONG_EN */ + r =FLD_MOD (r,0 ,4 ,4 );/* MODE, 0 = command */ + r =FLD_MOD (r,1 ,7 ,7 );/* CS_TX_EN */ + r =FLD_MOD (r,1 ,8 ,8 );/* ECC_TX_EN */ + r =FLD_MOD (r,1 ,9 ,9 );/* MODE_SPEED, high speed on/off */ + + r =FLD_MOD (r,4 ,29 ,27 );/* DMA_RX_REQ_NB = no dma */ + r =FLD_MOD (r,4 ,23 ,21 );/* DMA_TX_REQ_NB = no dma */ + +dsi_write_reg (DSI_VC_CTRL (channel), r); +} + + +static int dsi_vc_enable (int channel,int enable) +{ +DSSDBG ("dsi_vc_enable channel %d, enable %d\n" , channel, enable); + + enable = enable ?1 :0 ; + +REG_FLD_MOD (DSI_VC_CTRL (channel), enable,0 ,0 ); + +if (wait_for_bit_change (DSI_VC_CTRL (channel),0 , enable) != enable) { +DSSERR ("Failed to set dsi_vc_enable to %d\n" , enable); +return -EIO ; + } + +return 0 ; +} + +static void dsi_vc_enable_hs (int channel,int enable) +{ +DSSDBG ("dsi_vc_enable_hs(%d, %d)\n" , channel, enable); + +dsi_vc_enable (channel,0 ); +dsi_if_enable (0 ); + +REG_FLD_MOD (DSI_VC_CTRL (channel), enable,9 ,9 ); + +dsi_vc_enable (channel,1 ); +dsi_if_enable (1 ); + +dsi_force_tx_stop_mode_io (); +} + +static void dsi_vc_flush_long_data (int channel) +{ +while (REG_GET (DSI_VC_CTRL (channel),20 ,20 )) { +u32 val; + val =dsi_read_reg (DSI_VC_SHORT_PACKET_HEADER (channel)); +DSSDBG ("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n" , + (val >>0 ) &0xff , + (val >>8 ) &0xff , + (val >>16 ) &0xff , + (val >>24 ) &0xff ); + } +} + +static u16 dsi_vc_flush_receive_data (int channel) +{ +/* RX_FIFO_NOT_EMPTY */ +while (REG_GET (DSI_VC_CTRL (channel),20 ,20 )) { +u32 val; +u8 dt; + val =dsi_read_reg (DSI_VC_SHORT_PACKET_HEADER (channel)); +DSSDBG ("\trawval %#08x\n" , val); + dt =FLD_GET (val,7 ,0 ); +if (dt ==DSI_DT_RX_ACK_WITH_ERR ) { +u16 err =FLD_GET (val,23 ,8 ); +DSSERR ("\tACK with ERROR: %#x\n" , err); +if (err & (1 <<9 )) +DSSERR ("\t\tECC multibit\n" ); +if (err & (1 <<11 )) +DSSERR ("\t\tData type not recognized\n" ); +if (err & (1 <<12 )) +DSSERR ("\t\tInvalid VC ID\n" ); + + }else if (dt ==DSI_DT_RX_SHORT_READ_1 ) { +DSSDBG ("\tDCS short response, 1 byte: %#x\n" , +FLD_GET (val,23 ,8 )); +return FLD_GET (val,23 ,8 ); + }else if (dt ==DSI_DT_RX_SHORT_READ_2 ) { +DSSDBG ("\tDCS short response, 2 byte: %#x\n" , +FLD_GET (val,23 ,8 )); +return FLD_GET (val,23 ,8 ); + }else if (dt ==DSI_DT_RX_DCS_LONG_READ ) { +DSSDBG ("\tDCS long response, len %d\n" , +FLD_GET (val,23 ,8 )); +dsi_vc_flush_long_data (channel); + }else { +DSSERR ("\tunknown datatype\n" ); + } + } +return 0 ; +} + +static int dsi_vc_send_bta (int channel) +{ +unsigned long tmo; + +/*DSSDBG("dsi_vc_send_bta_sync %d\n", channel); */ + +if (REG_GET (DSI_VC_CTRL (channel),20 ,20 )) {/* RX_FIFO_NOT_EMPTY */ +DSSERR ("rx fifo not empty when sending BTA, dumping data:\n" ); +dsi_vc_flush_receive_data (channel); + } + +REG_FLD_MOD (DSI_VC_CTRL (channel),1 ,6 ,6 );/* BTA_EN */ + + tmo = jiffies +msecs_to_jiffies (10 ); +while (REG_GET (DSI_VC_CTRL (channel),6 ,6 ) ==1 ) { +if (time_after (jiffies, tmo)) { +DSSERR ("Failed to send BTA\n" ); +return -EIO ; + } + } + +return 0 ; +} + +static int dsi_vc_send_bta_sync (int channel) +{ +int r =0 ; + +init_completion (&dsi.bta_completion); + +dsi_vc_enable_bta_irq (channel); + + r =dsi_vc_send_bta (channel); +if (r) + goto err; + +if (wait_for_completion_timeout (&dsi.bta_completion, +msecs_to_jiffies (500 )) ==0 ) { +DSSERR ("Failed to receive BTA\n" ); + r = -EIO ; + goto err; + } +err: +dsi_vc_disable_bta_irq (channel); + +return r; +} + +static inline void dsi_vc_write_long_header (int channel,u8 data_type, +u16 len,u8 ecc) +{ +u32 val; +u8 data_id; + +/*data_id = data_type | channel << 6; */ + data_id = data_type | dsi.vc[channel].dest_per <<6 ; + + val =FLD_VAL (data_id,7 ,0 ) |FLD_VAL (len,23 ,8 ) | +FLD_VAL (ecc,31 ,24 ); + +dsi_write_reg (DSI_VC_LONG_PACKET_HEADER (channel), val); +} + +static inline void dsi_vc_write_long_payload (int channel, +u8 b1,u8 b2,u8 b3,u8 b4) +{ +u32 val; + + val = b4 <<24 | b3 <<16 | b2 <<8 | b1 <<0 ; + +/* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n", +b1, b2, b3, b4, val); */ + +dsi_write_reg (DSI_VC_LONG_PACKET_PAYLOAD (channel), val); +} + +static int dsi_vc_send_long (int channel,u8 data_type,u8 *data,u16 len, +u8 ecc) +{ +/*u32 val; */ +int i; +u8 *p; +int r =0 ; +u8 b1, b2, b3, b4; + +/*DSSDBG("dsi_vc_send_long, %d bytes\n", len); */ + +/* len + header */ +if (dsi.vc[channel].fifo_size *32 *4 < len +4 ) { +DSSERR ("DSI: unable to send long packet: packet too long.\n" ); +return -EINVAL ; + } + +dsi_vc_write_long_header (channel, data_type, len, ecc); + +/*dsi_vc_print_status(0); */ + + p = data; +for (i =0 ; i < len >>2 ; i++) { +/*DSSDBG("\tsending full packet %d\n", i); */ +/*dsi_vc_print_status(0); */ + + b1 = *p++; + b2 = *p++; + b3 = *p++; + b4 = *p++; + +dsi_vc_write_long_payload (channel, b1, b2, b3, b4); + } + + i = len %4 ; +if (i) { + b1 =0 ; b2 =0 ; b3 =0 ; + +/*DSSDBG("\tsending remainder bytes %d\n", i); */ + +switch (i) { +case 3 : + b1 = *p++; + b2 = *p++; + b3 = *p++; +break ; +case 2 : + b1 = *p++; + b2 = *p++; +break ; +case 1 : + b1 = *p++; +break ; + } + +dsi_vc_write_long_payload (channel, b1, b2, b3,0 ); + } + +return r; +} + +static int dsi_vc_send_short (int channel,u8 data_type,u16 data,u8 ecc) +{ +u32 r; +u8 data_id; +/* +DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n", +channel, +data_type, data & 0xff, (data >> 8) & 0xff); +*/ +if (FLD_GET (dsi_read_reg (DSI_VC_CTRL (channel)),16 ,16 )) { +DSSERR ("ERROR FIFO FULL, aborting transfer\n" ); +return -EINVAL ; + } + + data_id = data_type | channel <<6 ; + + r = (data_id <<0 ) | (data <<8 ) | (ecc <<24 ); + +dsi_write_reg (DSI_VC_SHORT_PACKET_HEADER (channel), r); + +return 0 ; +} + +int dsi_vc_send_null (int channel) +{ +u8 nullpkg[] = {0 ,0 ,0 ,0 }; +return dsi_vc_send_long (0 ,DSI_DT_NULL_PACKET , nullpkg,4 ,0 ); +} +EXPORT_SYMBOL (dsi_vc_send_null); + +int dsi_vc_dcs_write_nosync (int channel,u8 *data,int len) +{ +int r; + +BUG_ON (len ==0 ); + +if (len ==1 ) { + r =dsi_vc_send_short (channel,DSI_DT_DCS_SHORT_WRITE_0 , + data[0 ],0 ); + }else if (len ==2 ) { + r =dsi_vc_send_short (channel,DSI_DT_DCS_SHORT_WRITE_1 , + data[0 ] | (data[1 ] <<8 ),0 ); + }else { +/* 0x39 = DCS Long Write */ + r =dsi_vc_send_long (channel,DSI_DT_DCS_LONG_WRITE , + data, len,0 ); + } + +return r; +} +EXPORT_SYMBOL (dsi_vc_dcs_write_nosync); + +int dsi_vc_dcs_write (int channel,u8 *data,int len) +{ +int r; + + r =dsi_vc_dcs_write_nosync (channel, data, len); +if (r) +return r; + +/* Some devices need time to process the msg in low power mode. +This also makes the write synchronous, and checks that +the peripheral is still alive */ + r =dsi_vc_send_bta_sync (channel); + +return r; +} +EXPORT_SYMBOL (dsi_vc_dcs_write); + +int dsi_vc_dcs_read (int channel,u8 dcs_cmd,u8 *buf,int buflen) +{ +u32 val; +u8 dt; +int debug =0 ; + +if (debug) +DSSDBG ("dsi_vc_dcs_read\n" ); + +dsi_vc_send_short (channel,DSI_DT_DCS_READ , dcs_cmd,0 ); + +dsi_vc_send_bta_sync (channel); + + val =dsi_read_reg (DSI_VC_SHORT_PACKET_HEADER (channel)); +if (debug) +DSSDBG ("\trawval %#08x\n" , val); + dt =FLD_GET (val,7 ,0 ); +if (dt ==DSI_DT_RX_ACK_WITH_ERR ) { +u16 err =FLD_GET (val,23 ,8 ); +DSSERR ("\tACK with ERROR: %#x\n" , err); +if (err & (1 <<9 )) +DSSERR ("\t\tECC multibit\n" ); +if (err & (1 <<11 )) +DSSERR ("\t\tData type not recognized\n" ); +if (err & (1 <<12 )) +DSSERR ("\t\tInvalid VC ID\n" ); +return -1 ; + + }else if (dt ==DSI_DT_RX_SHORT_READ_1 ) { +u8 data =FLD_GET (val,15 ,8 ); +if (debug) +DSSDBG ("\tDCS short response, 1 byte: %#x\n" , data); + +if (buflen <1 ) +return -1 ; + + buf[0 ] = data; + +return 1 ; + }else if (dt ==DSI_DT_RX_SHORT_READ_2 ) { +u16 data =FLD_GET (val,23 ,8 ); +if (debug) +DSSDBG ("\tDCS short response, 2 byte: %#x\n" , data); + +if (buflen <2 ) +return -1 ; + + buf[0 ] = data &0xff ; + buf[1 ] = (data >>8 ) &0xff ; + +return 2 ; + }else if (dt ==DSI_DT_RX_DCS_LONG_READ ) { +int x; +int len =FLD_GET (val,23 ,8 ); +if (debug) +DSSDBG ("\tDCS long response, len %d\n" , len); + +if (len > buflen) +return -1 ; + + x =0 ; +while (x < len) { + val =dsi_read_reg (DSI_VC_SHORT_PACKET_HEADER (channel)); +if (debug) +DSSDBG ("\t\tb1 %#02x b2 %#02x b3 %#02x b4 " +"%#02x\n" , + (val >>0 ) &0xff , + (val >>8 ) &0xff , + (val >>16 ) &0xff , + (val >>24 ) &0xff ); + +if (x < len) + buf[x++] = (val >>0 ) &0xff ; +if (x < len) + buf[x++] = (val >>8 ) &0xff ; +if (x < len) + buf[x++] = (val >>16 ) &0xff ; +if (x < len) + buf[x++] = (val >>24 ) &0xff ; + } + +return len; + }else { +DSSERR ("\tunknown datatype\n" ); +return -1 ; + } +} +EXPORT_SYMBOL (dsi_vc_dcs_read); + + +int dsi_vc_set_max_rx_packet_size (int channel,u16 len) +{ +return dsi_vc_send_short (channel,DSI_DT_SET_MAX_RET_PKG_SIZE , + len,0 ); +} +EXPORT_SYMBOL (dsi_vc_set_max_rx_packet_size); + + +static int dsi_set_lp_rx_timeout (int ns,int x4,int x16) +{ +u32 r; +unsigned long fck; +int ticks; + +/* ticks in DSI_FCK */ + + fck =dsi_fclk_rate (); + ticks = (fck /1000 /1000 ) * ns /1000 ; + +if (ticks >0x1fff ) { +DSSERR ("LP_TX_TO too high\n" ); +return -EINVAL ; + } + + r =dsi_read_reg (DSI_TIMING2 ); + r =FLD_MOD (r,1 ,15 ,15 );/* LP_RX_TO */ + r =FLD_MOD (r, x16,14 ,14 );/* LP_RX_TO_X16 */ + r =FLD_MOD (r, x4,13 ,13 );/* LP_RX_TO_X4 */ + r =FLD_MOD (r, ticks,12 ,0 );/* LP_RX_COUNTER */ +dsi_write_reg (DSI_TIMING2 , r); + +DSSDBG ("LP_RX_TO %ld ns (%#x ticks)\n" , + (ticks * (x16 ?16 :1 ) * (x4 ?4 :1 ) *1000 ) / + (fck /1000 /1000 ), + ticks); + +return 0 ; +} + +static int dsi_set_ta_timeout (int ns,int x8,int x16) +{ +u32 r; +unsigned long fck; +int ticks; + +/* ticks in DSI_FCK */ + + fck =dsi_fclk_rate (); + ticks = (fck /1000 /1000 ) * ns /1000 ; + +if (ticks >0x1fff ) { +DSSERR ("TA_TO too high\n" ); +return -EINVAL ; + } + + r =dsi_read_reg (DSI_TIMING1 ); + r =FLD_MOD (r,1 ,31 ,31 );/* TA_TO */ + r =FLD_MOD (r, x16,30 ,30 );/* TA_TO_X16 */ + r =FLD_MOD (r, x8,29 ,29 );/* TA_TO_X8 */ + r =FLD_MOD (r, ticks,28 ,16 );/* TA_TO_COUNTER */ +dsi_write_reg (DSI_TIMING1 , r); + +DSSDBG ("TA_TO %ld ns (%#x ticks)\n" , + (ticks * (x16 ?16 :1 ) * (x8 ?8 :1 ) *1000 ) / + (fck /1000 /1000 ), + ticks); + +return 0 ; +} + +static int dsi_set_stop_state_counter (int ns,int x4,int x16) +{ +u32 r; +unsigned long fck; +int ticks; + +/* ticks in DSI_FCK */ + + fck =dsi_fclk_rate (); + ticks = (fck /1000 /1000 ) * ns /1000 ; + +if (ticks >0x1fff ) { +DSSERR ("STOP_STATE_COUNTER_IO too high\n" ); +return -EINVAL ; + } + + r =dsi_read_reg (DSI_TIMING1 ); + r =FLD_MOD (r,1 ,15 ,15 );/* FORCE_TX_STOP_MODE_IO */ + r =FLD_MOD (r, x16,14 ,14 );/* STOP_STATE_X16_IO */ + r =FLD_MOD (r, x4,13 ,13 );/* STOP_STATE_X4_IO */ + r =FLD_MOD (r, ticks,12 ,0 );/* STOP_STATE_COUNTER_IO */ +dsi_write_reg (DSI_TIMING1 , r); + +DSSDBG ("STOP_STATE_COUNTER %ld ns (%#x ticks)\n" , + (ticks * (x16 ?16 :1 ) * (x4 ?4 :1 ) *1000 ) / + (fck /1000 /1000 ), + ticks); + +return 0 ; +} + +static int dsi_set_hs_tx_timeout (int ns,int x4,int x16) +{ +u32 r; +unsigned long fck; +int ticks; + +/* ticks in TxByteClkHS */ + + fck = dsi.ddr_clk /4 ; + ticks = (fck /1000 /1000 ) * ns /1000 ; + +if (ticks >0x1fff ) { +DSSERR ("HS_TX_TO too high\n" ); +return -EINVAL ; + } + + r =dsi_read_reg (DSI_TIMING2 ); + r =FLD_MOD (r,1 ,31 ,31 );/* HS_TX_TO */ + r =FLD_MOD (r, x16,30 ,30 );/* HS_TX_TO_X16 */ + r =FLD_MOD (r, x4,29 ,29 );/* HS_TX_TO_X8 (4 really) */ + r =FLD_MOD (r, ticks,28 ,16 );/* HS_TX_TO_COUNTER */ +dsi_write_reg (DSI_TIMING2 , r); + +DSSDBG ("HS_TX_TO %ld ns (%#x ticks)\n" , + (ticks * (x16 ?16 :1 ) * (x4 ?4 :1 ) *1000 ) / + (fck /1000 /1000 ), + ticks); + +return 0 ; +} +static int dsi_proto_config (struct omap_display *display) +{ +u32 r; +int buswidth =0 ; + +dsi_config_tx_fifo (DSI_FIFO_SIZE_128 , +DSI_FIFO_SIZE_0 , +DSI_FIFO_SIZE_0 , +DSI_FIFO_SIZE_0 ); + +dsi_config_rx_fifo (DSI_FIFO_SIZE_128 , +DSI_FIFO_SIZE_0 , +DSI_FIFO_SIZE_0 , +DSI_FIFO_SIZE_0 ); + +/* XXX what values for the timeouts? */ +dsi_set_stop_state_counter (1000 ,0 ,0 ); + +dsi_set_ta_timeout (50000 ,1 ,1 ); + +/* 3000ns * 16 */ +dsi_set_lp_rx_timeout (3000 ,0 ,1 ); + +/* 10000ns * 4 */ +dsi_set_hs_tx_timeout (10000 ,1 ,0 ); + +switch (display->bpp) { +case 16 : + buswidth =0 ; +break ; +case 18 : + buswidth =1 ; +break ; +case 24 : + buswidth =2 ; +break ; +default : +BUG (); + } + + r =dsi_read_reg (DSI_CTRL ); + r =FLD_MOD (r,1 ,1 ,1 );/* CS_RX_EN */ + r =FLD_MOD (r,1 ,2 ,2 );/* ECC_RX_EN */ + r =FLD_MOD (r,1 ,3 ,3 );/* TX_FIFO_ARBITRATION */ +/* XXX what should the ratio be */ + r =FLD_MOD (r,0 ,4 ,4 );/* VP_CLK_RATIO, VP_PCLK = VP_CLK/2 */ + r =FLD_MOD (r, buswidth,7 ,6 );/* VP_DATA_BUS_WIDTH */ + r =FLD_MOD (r,0 ,8 ,8 );/* VP_CLK_POL */ + r =FLD_MOD (r,2 ,13 ,12 );/* LINE_BUFFER, 2 lines */ + r =FLD_MOD (r,1 ,14 ,14 );/* TRIGGER_RESET_MODE */ + r =FLD_MOD (r,1 ,19 ,19 );/* EOT_ENABLE */ + r =FLD_MOD (r,1 ,24 ,24 );/* DCS_CMD_ENABLE */ + r =FLD_MOD (r,0 ,25 ,25 );/* DCS_CMD_CODE, 1=start, 0=continue */ + +dsi_write_reg (DSI_CTRL , r); + +/* we configure vc0 for L4 communication, and +* vc1 for dispc */ +dsi_vc_config (0 ); +dsi_vc_config_vp (1 ); + +/* set all vc targets to peripheral 0 */ + dsi.vc[0 ].dest_per =0 ; + dsi.vc[1 ].dest_per =0 ; + dsi.vc[2 ].dest_per =0 ; + dsi.vc[3 ].dest_per =0 ; + +return 0 ; +} + +static void dsi_proto_timings (void ) +{ +int tlpx_half, tclk_zero, tclk_prepare, tclk_trail; +int tclk_pre, tclk_post; +int ddr_clk_pre, ddr_clk_post; +u32 r; + + r =dsi_read_reg (DSIPHY_CFG1 ); + tlpx_half =FLD_GET (r,22 ,16 ); + tclk_trail =FLD_GET (r,15 ,8 ); + tclk_zero =FLD_GET (r,7 ,0 ); + + r =dsi_read_reg (DSIPHY_CFG2 ); + tclk_prepare =FLD_GET (r,7 ,0 ); + +/* min 8*UI */ + tclk_pre =4 ; +/* min 60ns + 52*UI */ + tclk_post =ns2ddr (60 ) +26 ; + + ddr_clk_pre = (tclk_pre + tlpx_half*2 + tclk_zero + tclk_prepare) /4 ; + ddr_clk_post = (tclk_post + tclk_trail) /4 ; + + r =dsi_read_reg (DSI_CLK_TIMING ); + r =FLD_MOD (r, ddr_clk_pre,15 ,8 ); + r =FLD_MOD (r, ddr_clk_post,7 ,0 ); +dsi_write_reg (DSI_CLK_TIMING , r); + +#ifdef VERBOSE +DSSDBG ("ddr_clk_pre %d, ddr_clk_post %d\n" , + ddr_clk_pre, + ddr_clk_post); +#endif +} + + +#define DSI_DECL_VARS \ + int __dsi_cb = 0; u32 __dsi_cv = 0; + +#define DSI_FLUSH (ch) \ + if (__dsi_cb > 0) { \ +/*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \ +dsi_write_reg (DSI_VC_LONG_PACKET_PAYLOAD (ch), __dsi_cv); \ + __dsi_cb = __dsi_cv =0 ; \ + } + +#define DSI_PUSH(ch, data) \ + do { \ + __dsi_cv |= (data) << (__dsi_cb * 8); \ + /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \ + if (++__dsi_cb > 3) \ + DSI_FLUSH(ch); \ + } while (0) + +static int dsi_update_screen_l4 (struct omap_display *display, +int x,int y,int w,int h) +{ +/* Note: supports only 24bit colors in 32bit container */ +int first =1 ; +int fifo_stalls =0 ; +int max_dsi_packet_size; +int max_data_per_packet; +int max_pixels_per_packet; +int pixels_left; +int bytespp =3 ; +int scr_width; +u32 *data; +int start_offset; +int horiz_inc; +int current_x; +struct omap_overlay *ovl; + + debug_irq =0 ; + +DSSDBG ("dsi_update_screen_l4 (%d,%d %dx%d)\n" , + x, y, w, h); + + ovl = &display->manager->overlays[0 ]; + +if (ovl->info.color_mode !=OMAP_DSS_COLOR_RGB24U ) +return -EINVAL ; + +if (display->ctrl->bpp !=24 ) +return -EINVAL ; + +enable_clocks (1 ); + + scr_width = ovl->info.screen_width; + data = ovl->info.vaddr; + + start_offset = scr_width * y + x; + horiz_inc = scr_width - w; + current_x = x; + +/* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes +* in fifo */ + +/* When using CPU, max long packet size is TX buffer size */ + max_dsi_packet_size = dsi.vc[0 ].fifo_size *32 *4 ; + +/* we seem to get better perf if we divide the tx fifo to half, +and while the other half is being sent, we fill the other half +max_dsi_packet_size /= 2; */ + + max_data_per_packet = max_dsi_packet_size -4 -1 ; + + max_pixels_per_packet = max_data_per_packet / bytespp; + +DSSDBG ("max_pixels_per_packet %d\n" , max_pixels_per_packet); + + display->ctrl->setup_update (display, x, y, w, h); + + pixels_left = w * h; + +DSSDBG ("total pixels %d\n" , pixels_left); + + data += start_offset; + + dsi.update_region.x = x; + dsi.update_region.y = y; + dsi.update_region.w = w; + dsi.update_region.h = h; + dsi.update_region.bytespp = bytespp; + +start_measuring (); + +while (pixels_left >0 ) { +/* 0x2c = write_memory_start */ +/* 0x3c = write_memory_continue */ +u8 dcs_cmd = first ?0x2c :0x3c ; +int pixels; +DSI_DECL_VARS ; + first =0 ; + +#if 1 +/* using fifo not empty */ +/* TX_FIFO_NOT_EMPTY */ +while (FLD_GET (dsi_read_reg (DSI_VC_CTRL (0 )),5 ,5 )) { +udelay (1 ); + fifo_stalls++; +if (fifo_stalls >0xfffff ) { +DSSERR ("fifo stalls overflow, pixels left %d\n" , + pixels_left); +dsi_if_enable (0 ); +enable_clocks (0 ); +return -EIO ; + } + } +#elif 1 +/* using fifo emptiness */ +while ((REG_GET (DSI_TX_FIFO_VC_EMPTINESS ,7 ,0 )+1 )*4 < + max_dsi_packet_size) { + fifo_stalls++; +if (fifo_stalls >0xfffff ) { +DSSERR ("fifo stalls overflow, pixels left %d\n" , + pixels_left); +dsi_if_enable (0 ); +enable_clocks (0 ); +return -EIO ; + } + } +#else +while ((REG_GET (DSI_TX_FIFO_VC_EMPTINESS ,7 ,0 )+1 )*4 ==0 ) { + fifo_stalls++; +if (fifo_stalls >0xfffff ) { +DSSERR ("fifo stalls overflow, pixels left %d\n" , + pixels_left); +dsi_if_enable (0 ); +enable_clocks (0 ); +return -EIO ; + } + } +#endif + pixels =min (max_pixels_per_packet, pixels_left); + + pixels_left -= pixels; + +dsi_vc_write_long_header (0 ,DSI_DT_DCS_LONG_WRITE , +1 + pixels * bytespp,0 ); + +DSI_PUSH (0 , dcs_cmd); + +while (pixels-- >0 ) { +u32 pix = *data++; + +DSI_PUSH (0 , (pix >>16 ) &0xff ); +DSI_PUSH (0 , (pix >>8 ) &0xff ); +DSI_PUSH (0 , (pix >>0 ) &0xff ); + + current_x++; +if (current_x == x+w) { + current_x = x; + data += horiz_inc; + } + } + +DSI_FLUSH (0 ); + } + +end_measuring ("L4" ); + +enable_clocks (0 ); + +return 0 ; +} + +#if 0 +static void dsi_clear_screen_l4 (struct omap_display *display, +int x,int y,int w,int h) +{ +int first =1 ; +int fifo_stalls =0 ; +int max_dsi_packet_size; +int max_data_per_packet; +int max_pixels_per_packet; +int pixels_left; +int bytespp =3 ; +int pixnum; + + debug_irq =0 ; + +DSSDBG ("dsi_clear_screen_l4 (%d,%d %dx%d)\n" , + x, y, w, h); + +if (display->ctrl->bpp !=24 ) +return -EINVAL ; + +/* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) +* bytes in fifo */ + +/* When using CPU, max long packet size is TX buffer size */ + max_dsi_packet_size = dsi.vc[0 ].fifo_size *32 *4 ; + + max_data_per_packet = max_dsi_packet_size -4 -1 ; + + max_pixels_per_packet = max_data_per_packet / bytespp; + +enable_clocks (1 ); + + display->ctrl->setup_update (display, x, y, w, h); + + pixels_left = w * h; + + dsi.update_region.x = x; + dsi.update_region.y = y; + dsi.update_region.w = w; + dsi.update_region.h = h; + dsi.update_region.bytespp = bytespp; + +start_measuring (); + + pixnum =0 ; + +while (pixels_left >0 ) { +/* 0x2c = write_memory_start */ +/* 0x3c = write_memory_continue */ +u8 dcs_cmd = first ?0x2c :0x3c ; +int pixels; +DSI_DECL_VARS ; + first =0 ; + +/* TX_FIFO_NOT_EMPTY */ +while (FLD_GET (dsi_read_reg (DSI_VC_CTRL (0 )),5 ,5 )) { + fifo_stalls++; +if (fifo_stalls >0xfffff ) { +DSSERR ("fifo stalls overflow\n" ); +dsi_if_enable (0 ); +enable_clocks (0 ); +return ; + } + } + + pixels =min (max_pixels_per_packet, pixels_left); + + pixels_left -= pixels; + +dsi_vc_write_long_header (0 ,DSI_DT_DCS_LONG_WRITE , +1 + pixels * bytespp,0 ); + +DSI_PUSH (0 , dcs_cmd); + +while (pixels-- >0 ) { +u32 pix; + + pix =0x000000 ; + +DSI_PUSH (0 , (pix >>16 ) &0xff ); +DSI_PUSH (0 , (pix >>8 ) &0xff ); +DSI_PUSH (0 , (pix >>0 ) &0xff ); + } + +DSI_FLUSH (0 ); + } + +enable_clocks (0 ); + +end_measuring ("L4 CLEAR" ); +} +#endif + +static int dsi_wait_for_framedone (void ) +{ +unsigned long flags; + +spin_lock_irqsave (&dsi.update_lock, flags); +if (dsi.update_ongoing) { +long wait =msecs_to_jiffies (1000 ); + dsi.update_syncers++; +spin_unlock_irqrestore (&dsi.update_lock, flags); + wait =wait_for_completion_timeout (&dsi.update_completion, + wait); +if (wait ==0 ) { +DSSERR ("timeout waiting sync\n" ); +return -ETIME ; + } + }else { +spin_unlock_irqrestore (&dsi.update_lock, flags); + } + +return 0 ; +} + +static void dsi_setup_update_dispc (struct omap_display *display, +int x,int y,int w,int h) +{ +int bytespp =3 ; + +DSSDBG ("dsi_setup_update_dispc(%d,%d %dx%d)\n" , + x, y, w, h); + + dsi.update_region.display = display; + dsi.update_region.x = x; + dsi.update_region.y = y; + dsi.update_region.w = w; + dsi.update_region.h = h; + dsi.update_region.bytespp = bytespp; + +enable_clocks (1 ); + +dispc_setup_partial_planes (display, &x, &y, &w, &h); + +dispc_set_lcd_size (w, h); + +enable_clocks (0 ); +} + +static void dsi_update_screen_dispc (struct omap_display *display) +{ +int bytespp =3 ; +int total_len; +int line_packet_len; +int x, y, w, h; +u32 l; + + x = dsi.update_region.x; + y = dsi.update_region.y; + w = dsi.update_region.w; + h = dsi.update_region.h; + +DSSDBG ("dsi_update_screen_dispc(%d,%d %dx%d)\n" , + x, y, w, h); + +enable_clocks (1 ); + +/* TODO: one packet could be longer, I think? Max is the line buffer */ + line_packet_len = w * bytespp +1 ;/* 1 byte for DCS cmd */ + total_len = line_packet_len * h; + + display->ctrl->setup_update (display, x, y, w, h); + +if (0 ) +dsi_vc_print_status (1 ); + +start_measuring (); + + l =FLD_VAL (total_len,23 ,0 );/* TE_SIZE */ +dsi_write_reg (DSI_VC_TE (1 ), l); + +dsi_vc_write_long_header (1 ,DSI_DT_DCS_LONG_WRITE , line_packet_len,0 ); + +if (dsi.use_te) + l =FLD_MOD (l,1 ,30 ,30 );/* TE_EN */ +else + l =FLD_MOD (l,1 ,31 ,31 );/* TE_START */ +dsi_write_reg (DSI_VC_TE (1 ), l); + +dispc_enable_lcd_out (1 ); + +if (dsi.use_te) +dsi_vc_send_bta (1 ); +} + +static void framedone_callback (void *data,u32 mask) +{ +if (dsi.framedone_scheduled) { +DSSERR ("Framedone already scheduled. Bogus FRAMEDONE IRQ?\n" ); +return ; + } + + dsi.framedone_scheduled =1 ; + +/* We get FRAMEDONE when DISPC has finished sending pixels and turns +* itself off. However, DSI still has the pixels in its buffers, and +* is sending the data. Thus we have to wait until we can do a new +* transfer or turn the clocks off. We do that in a separate work +* func. */ +schedule_work (&dsi.framedone_work); +} + +static void framedone_worker (struct work_struct *work) +{ +unsigned long flags; +u32 l; +unsigned long tmo; +int i =0 ; + + l =REG_GET (DSI_VC_TE (1 ),23 ,0 );/* TE_SIZE */ + +/* There shouldn't be much stuff in DSI buffers, if any, so we'll +* just busyloop */ +if (l >0 ) { + tmo = jiffies +msecs_to_jiffies (50 ); +while (REG_GET (DSI_VC_TE (1 ),23 ,0 ) >0 ) {/* TE_SIZE */ + i++; +if (time_after (jiffies, tmo)) { +DSSERR ("timeout waiting TE_SIZE to zero\n" ); +break ; + } +cpu_relax (); + } + } + +if (REG_GET (DSI_VC_TE (1 ),30 ,30 )) +DSSERR ("TE_EN not zero\n" ); + +if (REG_GET (DSI_VC_TE (1 ),31 ,31 )) +DSSERR ("TE_START not zero\n" ); + +spin_lock_irqsave (&dsi.update_lock, flags); +if (dsi.update_ongoing ==0 ) { +spin_unlock_irqrestore (&dsi.update_lock, flags); +DSSERR ("framedone irq without update request\n" ); +return ; + } +spin_unlock_irqrestore (&dsi.update_lock, flags); + +end_measuring ("DISPC" ); + +DSSDBG ("FRAMEDONE\n" ); + +#if 0 +if (l) +DSSWARN ("FRAMEDONE irq too early, %d bytes, %d loops\n" , l, i); +#else +if (l >1024 *3 ) +DSSWARN ("FRAMEDONE irq too early, %d bytes, %d loops\n" , l, i); +#endif + +spin_lock_irqsave (&dsi.update_lock, flags); + dsi.update_ongoing =0 ; +while (dsi.update_syncers >0 ) { +complete (&dsi.update_completion); + --dsi.update_syncers; + } +spin_unlock_irqrestore (&dsi.update_lock, flags); + +#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC +dispc_fake_vsync_irq (); +#endif +enable_clocks (0 ); + + dsi.framedone_scheduled =0 ; + +if (dsi.update_mode ==OMAP_DSS_UPDATE_AUTO ) { +spin_lock_irqsave (&dsi.update_lock, flags); + dsi.update_ongoing =1 ; +spin_unlock_irqrestore (&dsi.update_lock, flags); +dsi_update_screen_dispc (dsi.update_region.display); + } +} + +static void dsi_start_auto_update (struct omap_display *display) +{ +unsigned long flags; +int bytespp =3 ; + +DSSDBG ("starting auto update\n" ); + + dsi.update_region.display = display; + dsi.update_region.x =0 ; + dsi.update_region.y =0 ; + dsi.update_region.w = display->x_res; + dsi.update_region.h = display->y_res; + dsi.update_region.bytespp = bytespp; + +enable_clocks (1 ); + +dispc_set_lcd_size (display->x_res, display->y_res); + +spin_lock_irqsave (&dsi.update_lock, flags); + dsi.update_ongoing =1 ; +spin_unlock_irqrestore (&dsi.update_lock, flags); +dsi_update_screen_dispc (display); +} + +static void dsi_stop_auto_update (void ) +{ + dsi.update_mode =OMAP_DSS_UPDATE_DISABLED ; + +DSSDBG ("waiting for display to finish.\n" ); +dsi_wait_for_framedone (); +DSSDBG ("done waiting\n" ); +enable_clocks (0 ); + + dsi.update_mode =OMAP_DSS_UPDATE_MANUAL ; +} + +static int dsi_set_update_mode (struct omap_display *display, +enum omap_dss_update_mode mode) +{ +if (mode == dsi.update_mode) +return 0 ; + +if (dsi.update_mode ==OMAP_DSS_UPDATE_AUTO ) +dsi_stop_auto_update (); +else if (dsi.update_mode ==OMAP_DSS_UPDATE_MANUAL ) +dsi_wait_for_framedone (); + + dsi.update_mode = mode; + +if (dsi.update_mode ==OMAP_DSS_UPDATE_AUTO ) +dsi_start_auto_update (display); + +return 0 ; +} + +/* Display funcs */ + +static int dsi_display_enable (struct omap_display *display) +{ +int r =0 ; +struct dsi_clock_info cinfo; + +DSSDBG ("dsi_display_enable\n" ); + +mutex_lock (&dsi.lock); + +if (display->state !=OMAP_DSS_DISPLAY_DISABLED ) { +DSSERR ("display already enabled\n" ); + r = -EINVAL ; + goto err0; + } + +enable_clocks (1 ); + + r =omap_dispc_register_isr (framedone_callback,NULL , +DISPC_IRQ_FRAMEDONE ); +if (r) { +DSSERR ("can't get FRAMEDONE irq\n" ); + goto err1; + } + +dispc_set_lcd_display_type (OMAP_DSS_LCD_DISPLAY_TFT ); + +dispc_set_parallel_interface_mode (OMAP_DSS_PARALLELMODE_DSI ); +dispc_enable_fifohandcheck (1 ); +dispc_setup_plane_fifo (OMAP_DSS_GFX ,0 ); +dispc_setup_plane_fifo (OMAP_DSS_VIDEO1 ,0 ); +dispc_setup_plane_fifo (OMAP_DSS_VIDEO2 ,0 ); +dispc_set_tft_data_lines (display->bpp); + + { +struct omap_video_timings timings = { + .hsw =1 , + .hfp =1 , + .hbp =1 , + .vsw =1 , + .vfp =0 , + .vbp =0 , + }; + +dispc_set_lcd_timings (&timings); + } + +_dsi_print_reset_status (); + + r =dsi_pll_init (1 ,0 ); +if (r) + goto err2; + +/* XXX hardcoded for 300Mbp/lane for now */ + r =dsi_pll_calc_datafreq (600 *1000 *1000 , &cinfo); +if (r) + goto err3; + + r =dsi_pll_program (&cinfo); +if (r) + goto err3; + +DSSDBG ("PLL OK\n" ); + + r =dsi_complexio_init (display); +if (r) + goto err3; + +_dsi_print_reset_status (); + +dsi_proto_timings (); +dsi_set_lp_clk_divisor (); + +if (1 ) +_dsi_print_reset_status (); + + r =dsi_proto_config (display); +if (r) + goto err4; + +/* enable interface */ +dsi_vc_enable (0 ,1 ); +dsi_vc_enable (1 ,1 ); +dsi_if_enable (1 ); +dsi_force_tx_stop_mode_io (); + + +if (display->ctrl && display->ctrl->enable) { + r = display->ctrl->enable (display); +if (r) + goto err5; + } + +if (display->panel && display->panel->enable) { + r = display->panel->enable (display); +if (r) + goto err6; + } + +if (dsi.use_te) { + r = display->ctrl->enable_te (display,1 ); +if (r) + goto err7; + } + +/* enable high-speed after initial config */ +dsi_vc_enable_hs (0 ,1 ); + + display->state =OMAP_DSS_DISPLAY_ACTIVE ; + +if (dsi.update_mode ==OMAP_DSS_UPDATE_AUTO ) +dsi_start_auto_update (display); + +enable_clocks (0 ); +mutex_unlock (&dsi.lock); + +return 0 ; +err7: +if (display->panel && display->panel->disable) + display->panel->disable (display); +err6: +if (display->ctrl && display->ctrl->disable) + display->ctrl->disable (display); +err5: +dsi_if_enable (0 ); +err4: +dsi_complexio_uninit (); +err3: +dsi_pll_uninit (); +err2: +omap_dispc_unregister_isr (framedone_callback); +err1: +enable_clocks (0 ); +err0: +mutex_unlock (&dsi.lock); +DSSDBG ("dsi_display_enable FAILED\n" ); +return r; +} + +static void dsi_display_disable (struct omap_display *display) +{ +DSSDBG ("dsi_display_disable\n" ); + +mutex_lock (&dsi.lock); + +if (display->state ==OMAP_DSS_DISPLAY_DISABLED ) + goto end; + +enable_clocks (1 ); + +if (dsi.update_mode ==OMAP_DSS_UPDATE_AUTO ) +dsi_stop_auto_update (); +else if (dsi.update_mode ==OMAP_DSS_UPDATE_MANUAL ) +dsi_wait_for_framedone (); + + display->state =OMAP_DSS_DISPLAY_DISABLED ; + +omap_dispc_unregister_isr (framedone_callback); + +if (display->panel && display->panel->disable) + display->panel->disable (display); +if (display->ctrl && display->ctrl->disable) + display->ctrl->disable (display); + +/* XXX sleep a bit to make sure all DSI buffers are sent. +* We should check it from somewhere, fifo fullness I guess */ +msleep (200 ); + +dsi_complexio_uninit (); +dsi_pll_uninit (); + +enable_clocks (0 ); + +end: +mutex_unlock (&dsi.lock); +} + +static int dsi_display_suspend (struct omap_display *display) +{ +if (display->state !=OMAP_DSS_DISPLAY_ACTIVE ) +return -EINVAL ; + +if (display->panel->suspend) + display->panel->suspend (display); + +if (display->ctrl->suspend) + display->ctrl->suspend (display); + + display->state =OMAP_DSS_DISPLAY_SUSPENDED ; + +return 0 ; +} + +static int dsi_display_resume (struct omap_display *display) +{ +if (display->state !=OMAP_DSS_DISPLAY_SUSPENDED ) +return -EINVAL ; + +if (display->panel->resume) + display->panel->resume (display); + +if (display->ctrl->resume) + display->ctrl->resume (display); + + display->state =OMAP_DSS_DISPLAY_ACTIVE ; + +return 0 ; +} + +static void dsi_display_set_mode (struct omap_display *display, +int x_res,int y_res,int bpp) +{ +DSSDBG ("dsi_display_set_mode %dx%d, %dbpp\n" , x_res, y_res, bpp); +} + +static int dsi_display_update (struct omap_display *display, +int x,int y,int w,int h) +{ +unsigned long flags; +int r =0 ; + +DSSDBG ("dsi_display_update(%d,%d %dx%d)\n" , x, y, w, h); + +if (w ==0 || h ==0 ) +return 0 ; + +mutex_lock (&dsi.lock); + +if (dsi.update_mode !=OMAP_DSS_UPDATE_MANUAL ) + goto end;/* XXX return error? */ + +spin_lock_irqsave (&dsi.update_lock, flags); + +if (dsi.update_ongoing) { +spin_unlock_irqrestore (&dsi.update_lock, flags); +DSSERR ("DSI is busy\n" ); + r = -EBUSY ; + goto end; + } + + dsi.update_ongoing =1 ; + +if (dsi.update_syncers >0 ) +DSSERR ("someone waiting for sync, and no update ongoing\n" ); + +spin_unlock_irqrestore (&dsi.update_lock, flags); + +if (display->manager->caps &OMAP_DSS_OVL_MGR_CAP_DISPC ) { +dsi_setup_update_dispc (display, x, y, w, h); +dsi_update_screen_dispc (display); + }else { + r =dsi_update_screen_l4 (display, x, y, w, h); +if (r) + goto end; + +spin_lock_irqsave (&dsi.update_lock, flags); + dsi.update_ongoing =0 ; +while (dsi.update_syncers >0 ) { +complete (&dsi.update_completion); + --dsi.update_syncers; + } +spin_unlock_irqrestore (&dsi.update_lock, flags); + } + +end: +mutex_unlock (&dsi.lock); +return r; +} + +static int dsi_display_sync (struct omap_display *display) +{ +int r =0 ; + +DSSDBG ("dsi_display_sync\n" ); + +mutex_lock (&dsi.lock); + +if (dsi.update_mode !=OMAP_DSS_UPDATE_MANUAL ) + goto end; + + r =dsi_wait_for_framedone (); + +end: +mutex_unlock (&dsi.lock); +return r; +} + +static int dsi_display_set_update_mode (struct omap_display *display, +enum omap_dss_update_mode mode) +{ +int r; + +DSSDBG ("dsi_display_set_update_mode\n" ); + +mutex_lock (&dsi.lock); + + r =dsi_set_update_mode (display, mode); + +mutex_unlock (&dsi.lock); + +return r; +} + +static enum omap_dss_update_mode dsi_display_get_update_mode ( +struct omap_display *display) +{ +return dsi.update_mode; +} + +static int dsi_display_enable_te (struct omap_display *display,int enable) +{ +enum omap_dss_update_mode mode; + +DSSDBG ("dsi_display_enable_te\n" ); + +mutex_lock (&dsi.lock); + +enable_clocks (1 ); + + mode = dsi.update_mode; + +/* XXX perhaps suspend or something would be better here */ +if (dsi.update_mode ==OMAP_DSS_UPDATE_AUTO ) +dsi_stop_auto_update (); +else if (dsi.update_mode ==OMAP_DSS_UPDATE_MANUAL ) +dsi_wait_for_framedone (); + + dsi.use_te = enable; + display->ctrl->enable_te (display, enable); +if (enable) { +/* disable LP_RX_TO, so that we can receive TE. +* Time to wait for TE is longer than the timer allows */ +REG_FLD_MOD (DSI_TIMING2 ,0 ,15 ,15 );/* LP_RX_TO */ + }else { +REG_FLD_MOD (DSI_TIMING2 ,1 ,15 ,15 );/* LP_RX_TO */ + } + +/* restore the old update mode */ +dsi_set_update_mode (display, mode); + +enable_clocks (0 ); + +mutex_unlock (&dsi.lock); + +return 0 ; +} + +static int dsi_display_get_te (struct omap_display *display) +{ +return dsi.use_te; +} + +static int dsi_display_run_test (struct omap_display *display,int test_num) +{ +enum omap_dss_update_mode mode; +int r =0 ; + +DSSDBG ("dsi_display_run_test %d\n" , test_num); + +mutex_lock (&dsi.lock); + +enable_clocks (1 ); + + mode = dsi.update_mode; + +/* XXX perhaps suspend or something would be better here */ +if (dsi.update_mode ==OMAP_DSS_UPDATE_AUTO ) +dsi_stop_auto_update (); +else if (dsi.update_mode ==OMAP_DSS_UPDATE_MANUAL ) +dsi_wait_for_framedone (); + +/* run test first in low speed mode */ +dsi_vc_enable_hs (0 ,0 ); + +if (display->ctrl->run_test) { + r = display->ctrl->run_test (display, test_num); +if (r) + goto fail; + } + +if (display->panel->run_test) { + r = display->panel->run_test (display, test_num); +if (r) + goto fail; + } + +/* then in high speed */ +dsi_vc_enable_hs (0 ,1 ); + +if (display->ctrl->run_test) { + r = display->ctrl->run_test (display, test_num); +if (r) + goto fail; + } + +if (display->panel->run_test) + r = display->panel->run_test (display, test_num); + +fail: +dsi_vc_enable_hs (0 ,1 ); + +/* restore the old update mode */ +dsi_set_update_mode (display, mode); + +enable_clocks (0 ); + +mutex_unlock (&dsi.lock); + +return r; +} + +void dsi_init_display (struct omap_display *display) +{ +DSSDBG ("DSI init\n" ); + + display->enable = dsi_display_enable; + display->disable = dsi_display_disable; + display->suspend = dsi_display_suspend; + display->resume = dsi_display_resume; + display->set_mode = dsi_display_set_mode; + display->update = dsi_display_update; + display->sync = dsi_display_sync; + display->set_update_mode = dsi_display_set_update_mode; + display->get_update_mode = dsi_display_get_update_mode; + display->enable_te = dsi_display_enable_te; + display->get_te = dsi_display_get_te; + display->run_test = dsi_display_run_test; + + display->caps =OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE ; +} + +int dsi_init (void ) +{ +u32 rev; + +init_completion (&dsi.bta_completion); +INIT_WORK (&dsi.framedone_work, framedone_worker); + +init_completion (&dsi.update_completion); +spin_lock_init (&dsi.update_lock); + dsi.update_ongoing =0 ; + dsi.update_syncers =0 ; + +mutex_init (&dsi.lock); + + dsi.base =ioremap (DSI_BASE ,SZ_1K ); +if (!dsi.base) { +DSSERR ("can't ioremap DSI\n" ); +return -ENOMEM ; + } + + dsi.dss_ick =get_dss_ick (); + dsi.dss1_fck =get_dss1_fck (); + dsi.dss2_fck =get_dss2_fck (); + +enable_clocks (1 ); + +/* Autoidle */ +REG_FLD_MOD (DSI_SYSCONFIG ,1 ,0 ,0 ); +
Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.
PATCH 6/9 DSS: OMAPFB: fb driver for new display subsystem
In reply to Tomi Valkeinen---
arch/arm/plat-omap/fb.c | 9 arch/arm/plat-omap/include/mach/omapfb.h | 7 drivers/video/Kconfig | 1 drivers/video/Makefile | 1 drivers/video/omap/Kconfig | 5 drivers/video/omap2/Kconfig | 29 + drivers/video/omap2/Makefile | 2 drivers/video/omap2/omapfb-ioctl.c | 428 ++++++++++ drivers/video/omap2/omapfb-main.c | 1247 ++++++++++++++++++++++++++++++ drivers/video/omap2/omapfb-sysfs.c | 833 ++++++++++++++++++++ drivers/video/omap2/omapfb.h | 104 +++ 11 files changed, 2663 insertions(+), 3 deletions(-) create mode 100644 drivers/video/omap2/Kconfig create mode 100644 drivers/video/omap2/Makefile create mode 100644 drivers/video/omap2/omapfb-ioctl.c create mode 100644 drivers/video/omap2/omapfb-main.c create mode 100644 drivers/video/omap2/omapfb-sysfs.c create mode 100644 drivers/video/omap2/omapfb.h
arch/arm/plat-omap/fb.c +8 -1
@@ -36,7 +36,8 @@#include <mach/sram.h> #include <mach/omapfb.h> -#if defined(CONFIG_FB_OMAP ) || defined(CONFIG_FB_OMAP_MODULE ) +#if defined(CONFIG_FB_OMAP ) || defined(CONFIG_FB_OMAP_MODULE ) \ + || defined(CONFIG_FB_OMAP2 ) || defined(CONFIG_FB_OMAP2_MODULE )static struct omapfb_platform_data omapfb_config;static int config_invalid;
@@ -298,14 +299,18 @@ unsigned long omapfb_reserve_sram(unsigned long sram_pstart,return reserved; } +#if defined(CONFIG_FB_OMAP ) || defined(CONFIG_FB_OMAP_MODULE )void omapfb_set_ctrl_platform_data (void *data) { omapfb_config.ctrl_platform_data = data; } +#endif static inline int omap_init_fb (void ) { +#if defined(CONFIG_FB_OMAP ) || defined(CONFIG_FB_OMAP_MODULE )const struct omap_lcd_config *conf; +#endif if (config_invalid)return 0 ;
@@ -313,6 +318,7 @@ static inline int omap_init_fb(void)printk (KERN_ERR "Invalid FB mem configuration entries\n" );return 0 ; } +#if defined(CONFIG_FB_OMAP ) || defined(CONFIG_FB_OMAP_MODULE ) conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);if (conf ==NULL ) {if (configured_regions)
@@ -321,6 +327,7 @@ static inline int omap_init_fb(void) return 0; } omapfb_config.lcd = *conf; +#endif return platform_device_register (&omap_fb_device); }
arch/arm/plat-omap/include/mach/omapfb.h +7 -0
@@ -90,6 +90,13 @@ enum omapfb_color_format {OMAPFB_COLOR_CLUT_1BPP ,OMAPFB_COLOR_RGB444 ,OMAPFB_COLOR_YUY422 , + +OMAPFB_COLOR_ARGB16 , +OMAPFB_COLOR_RGB24U ,/* RGB24, 32-bit container */ +OMAPFB_COLOR_RGB24P ,/* RGB24, 24-bit container */ +OMAPFB_COLOR_ARGB32 , +OMAPFB_COLOR_RGBA32 , + OMAPFB_COLOR_RGBX32, }; struct omapfb_update_window {
drivers/video/Kconfig +1 -0
@@ -2084,6 +2084,7 @@ config FB_METRONOME and could also have been called by some vendors as PVI-nnnn. source "drivers/video/omap/Kconfig" +source "drivers/video/omap2/Kconfig" source "drivers/video/backlight/Kconfig" source "drivers/video/display/Kconfig"
drivers/video/Makefile +1 -0
@@ -120,6 +120,7 @@ obj-$(CONFIG_FB_SM501) += sm501fb.o obj-$(CONFIG_FB_XILINX) += xilinxfb.o obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o obj-$(CONFIG_FB_OMAP) += omap/ +obj-$(CONFIG_OMAP2_DSS) += omap2/ obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o obj-$(CONFIG_FB_CARMINE) += carminefb.o
drivers/video/omap/Kconfig +3 -2
@@ -1,6 +1,7 @@ config FB_OMAP tristate "OMAP frame buffer support (EXPERIMENTAL)" - depends on FB && ARCH_OMAP + depends on FB && ARCH_OMAP && (OMAP2_DSS = "n") + select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT
@@ -76,7 +77,7 @@ config FB_OMAP_BOOTLOADER_INIT config FB_OMAP_CONSISTENT_DMA_SIZE int "Consistent DMA memory size (MB)" - depends on FB_OMAP + depends on FB && ARCH_OMAP range 1 14 default 2 help
drivers/video/omap2/Kconfig new file +29 -0
@@ -0,0 +1,29 @@ +config FB_OMAP2 + tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)" + depends on FB && OMAP2_DSS + + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Frame buffer driver for OMAP2/3 based boards. + +config FB_OMAP2_DEBUG + bool "Debug output for OMAP2/3 FB" + depends on FB_OMAP2 + +config FB_OMAP2_FORCE_AUTO_UPDATE + bool "Force main display to automatic update mode" + depends on FB_OMAP2 + help + Forces main display to automatic update mode (if possible), + and also enables tearsync (if possible). By default + displays that support manual update are started in manual + update mode. + +menu "OMAP2/3 Display Device Drivers" + depends on OMAP2_DSS + + +endmenu +
drivers/video/omap2/Makefile new file +2 -0
@@ -0,0 +1,2 @@ +obj-$(CONFIG_FB_OMAP2) += omapfb.o +omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
drivers/video/omap2/omapfb-ioctl.c new file +428 -0
428 lines not on this page · raw message
drivers/video/omap2/omapfb-main.c new file +1247 -0
1,247 lines not on this page · raw message
drivers/video/omap2/omapfb-sysfs.c new file +833 -0
833 lines not on this page · raw message
drivers/video/omap2/omapfb.h new file +104 -0
104 lines not on this page · raw message
PATCH 7/9 DSS: Add generic DVI panel
In reply to Tomi ValkeinenFor some reason we can't allocate enough mem for 1280x1024x24bpp, even if there should be enough continuous mem. So 1280x1024 mode defaults to 16bpp for now.
You also need DSI PLL to generate pix clock for 1280x1024.
---
drivers/video/omap2/Kconfig | 20 ++++++ drivers/video/omap2/Makefile | 2 + drivers/video/omap2/panel-dvi.c | 121 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 0 deletions(-) create mode 100644 drivers/video/omap2/panel-dvi.c
drivers/video/omap2/Kconfig +20 -0
@@ -24,6 +24,26 @@ config FB_OMAP2_FORCE_AUTO_UPDATE menu "OMAP2/3 Display Device Drivers" depends on OMAP2_DSS +config PANEL_DVI + tristate "DVI Panel" + help + DVI output, for Beagle and OMAP3 SDP + +choice + prompt "Default DVI Mode" + depends on PANEL_DVI + default PANEL_DVI_HIGHRES + +config PANEL_DVI_LOWRES + bool "800 x 600 @ 60" + +config PANEL_DVI_HIGHRES + bool "1024 x 768 @ 60" + +config PANEL_DVI_VERYHIGHRES + bool "1280 x 1024 @ 57" + +endchoice endmenu
drivers/video/omap2/Makefile +2 -0
@@ -1,2 +1,4 @@ obj-$(CONFIG_FB_OMAP2) += omapfb.o omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o + +obj-$(CONFIG_PANEL_DVI) += panel-dvi.o
drivers/video/omap2/panel-dvi.c new file +121 -0
121 lines not on this page · raw message
PATCH 8/9 DSS: support for Beagle Board
In reply to Tomi Valkeinen---
arch/arm/mach-omap2/board-omap3beagle.c | 121 ++++++++++++++++++++++++++++--- 1 files changed, 108 insertions(+), 13 deletions(-)
arch/arm/mach-omap2/board-omap3beagle.c +108 -13
@@ -42,6 +42,8 @@#include <mach/gpmc.h> #include <mach/nand.h> #include <mach/mux.h> +#include <mach/omapfb.h> +#include <mach/display.h> #include "twl4030-generic-scripts.h"
@@ -186,15 +188,6 @@ static void __init omap3_beagle_init_irq(void)omap_gpio_init (); } -static struct platform_device omap3_beagle_lcd_device = { - .name ="omap3beagle_lcd" , - .id =-1 , -}; - -static struct omap_lcd_config omap3_beagle_lcd_config__initdata = { - .ctrl_name ="internal" , -}; -static struct gpio_led gpio_leds[] = { { .name ="beagleboard::usr0" ,
@@ -248,13 +241,114 @@ static struct platform_device keys_gpio = { }, }; +/* DSS */ + +static int beagle_enable_dvi (struct omap_display *display) +{ +if (display->hw_config.panel_reset_gpio !=-1 ) +gpio_direction_output (display->hw_config.panel_reset_gpio,1 ); + +return 0 ; +} + +static void beagle_disable_dvi (struct omap_display *display) +{ +if (display->hw_config.panel_reset_gpio !=-1 ) +gpio_direction_output (display->hw_config.panel_reset_gpio,0 ); +} + +static struct omap_display_data beagle_display_data_dvi = { + .type =OMAP_DISPLAY_TYPE_DPI , + .name ="dvi" , + .panel_name ="panel-dvi" , + .u.dpi.data_lines =24 , + .panel_reset_gpio =170 , + .panel_enable = beagle_enable_dvi, + .panel_disable = beagle_disable_dvi, +}; + + +static int panel_enable_tv (struct omap_display *display) +{ +#define ENABLE_VDAC_DEDICATED 0x03 +#define ENABLE_VDAC_DEV_GRP 0x20 + +twl4030_i2c_write_u8 (TWL4030_MODULE_PM_RECEIVER , +ENABLE_VDAC_DEDICATED , +TWL4030_VDAC_DEDICATED ); +twl4030_i2c_write_u8 (TWL4030_MODULE_PM_RECEIVER , +ENABLE_VDAC_DEV_GRP ,TWL4030_VDAC_DEV_GRP ); + +return 0 ; +} + +static void panel_disable_tv (struct omap_display *display) +{ +twl4030_i2c_write_u8 (TWL4030_MODULE_PM_RECEIVER ,0x00 , +TWL4030_VDAC_DEDICATED ); +twl4030_i2c_write_u8 (TWL4030_MODULE_PM_RECEIVER ,0x00 , +TWL4030_VDAC_DEV_GRP ); +} + +static struct omap_display_data beagle_display_data_tv = { + .type =OMAP_DISPLAY_TYPE_VENC , + .name ="tv" , + .u.venc.type =OMAP_DSS_VENC_TYPE_SVIDEO , + .panel_enable = panel_enable_tv, + .panel_disable = panel_disable_tv, +}; + +static struct omap_dss_platform_data beagle_dss_data = { + .num_displays =2 , + .displays = { + &beagle_display_data_dvi, + &beagle_display_data_tv, + } +}; + +static struct platform_device beagle_dss_device = { + .name ="omap-dss" , + .id =-1 , + .dev = { + .platform_data = &beagle_dss_data, + }, +}; + +static void __init beagle_display_init (void ) +{ +int r; + + r =gpio_request (beagle_display_data_dvi.panel_reset_gpio,"DVI reset GPIO" ); +if (r <0 ) { +printk (KERN_ERR "Unable to get DVI reset GPIO\n" ); + } +} + +static struct omap_fbmem_config beagle_fbmem0_config = { + .size =1024 *768 *4 , + .start =OMAPFB_MEMTYPE_SDRAM , +}; + +static struct omap_fbmem_config beagle_fbmem1_config = { + .size =1024 *768 *4 , + .start =OMAPFB_MEMTYPE_SDRAM , +}; + +static struct omap_fbmem_config beagle_fbmem2_config = { + .size =1024 *768 *4 , + .start =OMAPFB_MEMTYPE_SDRAM , +}; + +static struct omap_board_config_kernel omap3_beagle_config[]__initdata = { {OMAP_TAG_UART , &omap3_beagle_uart_config }, - {OMAP_TAG_LCD , &omap3_beagle_lcd_config }, + {OMAP_TAG_FBMEM , &beagle_fbmem0_config }, + {OMAP_TAG_FBMEM , &beagle_fbmem1_config }, + {OMAP_TAG_FBMEM , &beagle_fbmem2_config }, };static struct platform_device *omap3_beagle_devices[]__initdata = { - &omap3_beagle_lcd_device, + &beagle_dss_device, &leds_gpio, &keys_gpio, };
@@ -302,8 +396,6 @@ static void __init omap3_beagle_init(void)omap3_beagle_i2c_init ();platform_add_devices (omap3_beagle_devices,ARRAY_SIZE (omap3_beagle_devices)); - omap_board_config = omap3_beagle_config; - omap_board_config_size =ARRAY_SIZE (omap3_beagle_config);omap_serial_init ();omap_cfg_reg (AH8_34XX_GPIO29 );
@@ -319,10 +411,13 @@ static void __init omap3_beagle_init(void)usb_musb_init ();usb_ehci_init ();omap3beagle_flash_init (); +beagle_display_init (); }static void __init omap3_beagle_map_io (void ) { + omap_board_config = omap3_beagle_config; + omap_board_config_size =ARRAY_SIZE (omap3_beagle_config);omap2_set_globals_343x ();omap2_map_common_io (); }
Re: [REVIEW PATCH 8/9] DSS: support for Beagle Board
Op 4 nov 2008, om 17:10 heeft Tomi Valkeinen het volgende geschreven:
Quoted 7 lines
Signed-off-by Tomi Valkeinen <[email protected]>---
arch/arm/mach-omap2/board-omap3beagle.c| 121 ++++++++++++++++++++++
++++++---1 files changed, 108 insertions(+), 13 deletions(-)
arch/arm/mach-omap2/board-omap3beagle.c static struct platform_device keys_gpio = { · line 267
Quoted 8 lines
arch/arm/mach-omap2/board-omap3beagle.c +8
-0+static struct omap_display_data beagle_display_data_dvi = { + .type =OMAP_DISPLAY_TYPE_DPI , + .name ="dvi" , + .panel_name ="panel-dvi" , + .u.dpi.data_lines =24 , + .panel_reset_gpio =170 , + .panel_enable = beagle_enable_dvi, + .panel_disable = beagle_disable_dvi,
gpio 170 is the enable (or disable, I forget which) for the DVI framer (TFP410), not a reset gpio. It would be nice to have a way to enable/disable the framer from userspace since it burns 60-100mA.
regards,
Koen
Re: [REVIEW PATCH 8/9] DSS: support for Beagle Board
Quoted 9 lines · ext Koen Kooi
Op 4 nov 2008, om 17:10 heeft Tomi Valkeinen het volgende geschreven:
Quoted 7 lines
Signed-off-by Tomi Valkeinen <[email protected]>---
arch/arm/mach-omap2/board-omap3beagle.c| 121 ++++++++++++++++++++++
++++++---1 files changed, 108 insertions(+), 13 deletions(-)
Quoted 12 lines
arch/arm/mach-omap2/board-omap3beagle.c static struct platform_device keys_gpio = { · line 267
Quoted 8 lines
arch/arm/mach-omap2/board-omap3beagle.c +8
-0+static struct omap_display_data beagle_display_data_dvi = { + .type =OMAP_DISPLAY_TYPE_DPI , + .name ="dvi" , + .panel_name ="panel-dvi" , + .u.dpi.data_lines =24 , + .panel_reset_gpio =170 , + .panel_enable = beagle_enable_dvi, + .panel_disable = beagle_disable_dvi,gpio 170 is the enable (or disable, I forget which) for the DVI framer (TFP410), not a reset gpio. It would be nice to have a way to enable/ disable the framer from userspace since it burns 60-100mA.
Well, is there a big difference between reset and enable? Anyway, you can do
echo "dvi e:0" > /sys/devices/platform/omapfb/displays
and it will turn off the power.
Or, alternatively, use the framebuffer blanking, although that has not been implemented to the panel-dvi.c (it's in panel-sdp3430.c).
Quoted 3 lines
regards,
Koen
Tom
Re: [REVIEW PATCH 8/9] DSS: support for Beagle Board
Op 5 nov 2008, om 11:05 heeft Tomi Valkeinen het volgende geschreven:
Quoted 24 lines · ext Koen Kooi
Quoted 10 lines
Op 4 nov 2008, om 17:10 heeft Tomi Valkeinen het volgende geschreven:
Quoted 8 lines
Signed-off-by Tomi Valkeinen <[email protected]>---
arch/arm/mach-omap2/board-omap3beagle.c| 121 ++++++++++++++++++++ ++
++++++---1 files changed, 108 insertions(+), 13 deletions(-)Quoted 12 lines
arch/arm/mach-omap2/board-omap3beagle.c static struct platform_device keys_gpio = { · line 267
Quoted 8 lines
arch/arm/mach-omap2/board-omap3beagle.c +8
-0+static struct omap_display_data beagle_display_data_dvi = { + .type =OMAP_DISPLAY_TYPE_DPI , + .name ="dvi" , + .panel_name ="panel-dvi" , + .u.dpi.data_lines =24 , + .panel_reset_gpio =170 , + .panel_enable = beagle_enable_dvi, + .panel_disable = beagle_disable_dvi,gpio 170 is the enable (or disable, I forget which) for the DVI framer (TFP410), not a reset gpio. It would be nice to have a way to enable/ disable the framer from userspace since it burns 60-100mA.
Quoted 1 line
Well, is there a big difference between reset and enable?
Reset implies that power stays on (like the reset button on a desktop), while enable and disable imply power on and power off. Maybe that's just me :)
regards,
Koen
Quoted 21 lines
Anyway, you
can doecho "dvi e:0" >
/sys/devices/platform/omapfb/displaysand it will turn off the power.
Or, alternatively, use the framebuffer blanking, although that has not been implemented to the
panel-dvi.c(it's inpanel-sdp3430.c).Quoted 3 lines
regards,
Koen
Tom
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Tony Lindgren
maintainerRe: [Linux-fbdev-devel] [REVIEW PATCH 8/9] DSS: support for Beagle Board
In reply to Tomi ValkeinenHi,
One comment below.
Quoted 10 lines · Tomi Valkeinen
Signed-off-by Tomi Valkeinen <[email protected]>---
arch/arm/mach-omap2/board-omap3beagle.c | 121 ++++++++++++++++++++++++++++--- 1 files changed, 108 insertions(+), 13 deletions(-)arch/arm/mach-omap2/board-omap3beagle.c +0
-0
<snip>
Quoted 14 lines
arch/arm/mach-omap2/board-omap3beagle.c +13
-0+static struct omap_fbmem_config beagle_fbmem0_config = { + .size =1024 *768 *4 , + .start =OMAPFB_MEMTYPE_SDRAM , +}; + +static struct omap_fbmem_config beagle_fbmem1_config = { + .size =1024 *768 *4 , + .start =OMAPFB_MEMTYPE_SDRAM , +}; + +static struct omap_fbmem_config beagle_fbmem2_config = { + .size =1024 *768 *4 , + .start =OMAPFB_MEMTYPE_SDRAM ,
arch/arm/mach-omap2/board-omap3beagle.c static struct platform_device keys_gpio = { · line 348
Quoted 10 lines
arch/arm/mach-omap2/board-omap3beagle.c +6
-1+}; + +static struct omap_board_config_kernel omap3_beagle_config[]__initdata = { {OMAP_TAG_UART , &omap3_beagle_uart_config }, - {OMAP_TAG_LCD , &omap3_beagle_lcd_config }, + {OMAP_TAG_FBMEM , &beagle_fbmem0_config }, + {OMAP_TAG_FBMEM , &beagle_fbmem1_config }, + {OMAP_TAG_FBMEM , &beagle_fbmem2_config }, };
NAK for adding new OMAP_TAGs. We are in process of removing those. You should be able to use just board specific platform_data.
If there are ATAGs that are needed, they must be ARM generic. They also need to be acked by Russell King on the linux-arm-kernel mailing list. I doubt that you'll need those though.
Regards,
Tony
Re: [Linux-fbdev-devel] [REVIEW PATCH 8/9] DSS: support for Beagle Board
Quoted 46 lines · ext Tony Lindgren
Hi,
One comment below.
Quoted 10 lines · Tomi Valkeinen
Signed-off-by Tomi Valkeinen <[email protected]>---
arch/arm/mach-omap2/board-omap3beagle.c | 121 ++++++++++++++++++++++++++++--- 1 files changed, 108 insertions(+), 13 deletions(-)arch/arm/mach-omap2/board-omap3beagle.c +0
-0<snip>
Quoted 14 lines
arch/arm/mach-omap2/board-omap3beagle.c +13
-0+static struct omap_fbmem_config beagle_fbmem0_config = { + .size =1024 *768 *4 , + .start =OMAPFB_MEMTYPE_SDRAM , +}; + +static struct omap_fbmem_config beagle_fbmem1_config = { + .size =1024 *768 *4 , + .start =OMAPFB_MEMTYPE_SDRAM , +}; + +static struct omap_fbmem_config beagle_fbmem2_config = { + .size =1024 *768 *4 , + .start =OMAPFB_MEMTYPE_SDRAM ,arch/arm/mach-omap2/board-omap3beagle.c static struct platform_device keys_gpio = { · line 348
Quoted 10 lines
arch/arm/mach-omap2/board-omap3beagle.c +6
-1+}; + +static struct omap_board_config_kernel omap3_beagle_config[]__initdata = { {OMAP_TAG_UART , &omap3_beagle_uart_config }, - {OMAP_TAG_LCD , &omap3_beagle_lcd_config }, + {OMAP_TAG_FBMEM , &beagle_fbmem0_config }, + {OMAP_TAG_FBMEM , &beagle_fbmem1_config }, + {OMAP_TAG_FBMEM , &beagle_fbmem2_config }, };NAK for adding new
OMAP_TAGs. We are in process of removing those. You should be able to use just board specificplatform_data.
Quoted 3 lines
If there are ATAGs that are needed, they must be ARM generic. They also need to be acked by Russell King on the linux-arm-kernel mailing list. I doubt that you'll need those though.
Okay. But in this case, I think, it's not enough to have the board specific data in board.c's platform_data. It would be good that the bootloader can setup the display, and tell the relevant information to the kernel, so that there are no glitches on the display (although not currently implemented in my driver).
But there may be an ATAG that can be used for that, I'll have to check.
Quoted 3 lines
Regards,
Tony
Tomi
FSUSB Register access
In reply to Tomi ValkeinenHello,
I am using Montavista Mobilinux 5 on OMAP2430 and I am trying to access the FSUSB register set and the kernel halts upon any attempt to access any of the registers in the FSUSB.
Note, under the Mobilinux distribution, the HSUSB controller is used by default, not the FSUSB controller. I am trying to access both so that I can have USB port 0 controlled by the HSUSB and port 1 controlled by the FSUSB controller.
Per the TI spec, the host and device register sets within the FSUSB controller can only be accessed if the OTG register set is correctly configured. However, the OTG register set should be accessible as long as there is a 48MHz clock.
I have tried reading the OTG_REVISION register (0x4805e300) and the OTG_SYSCON_1_REG (0x4805e304) within arch/arm/plat-omap/usb.c. Upon either read, the kernel halts and I do not see any logs at startup after the
"Uncompressing Linux............................................................. ........................................... done, booting the kernel." message.
If I comment out the register accesses, I do see the startup log and I see the following log statements within arch/arm/plat-omap/usb.c "Timeout enabling clock usb_l4_ick"
"Timeout enabling clock usb_fck"
In addition I have printed out various register values and they are as follows.
Various register values:
CM_FCLKEN2_CORE - Address:0x49006204 - value 0x001B07BF,bit 0 is 0x1, should be 1
CM_ICLKEN2_CORE - Address:0x49006214 - value 0x00000FFF,bit 0 is 0x1, should be 1
CM_IDLEST2_CORE - Address:0x49006224 - value 0x00000FFE,bit 0 is 0x0, should be 1 --- Possibly this is causing my problem but it is not clear to me what I need to do to have this set to a '1'.
CM_AUTOIDLE2_CORE - Address:0x49006234 - value 0x00000000,bit 0 is 0x0, should be 0
CM_CLKSEL1_CORE - Address:0x49006240 - value 0x02102946,bits 27-25 is 0x1, should be 1 for L3_CLK/1 (boot mode only), 2 for L3_CLK/2, or 4 for L3_CLK/4
PM_WKEN2_CORE - Address:0x490062A4 - value 0x00000000,bit 0 is 0x0, should be 0 for disabled, 1 for enabled -- Per TI, this does not need to be enabled...
PM_WKST2_CORE - Address:0x490062B4 - value 0x00000000,bit 0 is 0x0, should be 0 for not occurred, 1 for occurred
CM_IDLEST_CKGEN - Address:0x49006520 - value 0x00000336,bit 4 is 0x1, should be 0x1 for active 48M_CLK
Any ideas as to what the register settings need to be to enable access to the FSUSB OTG registers?
Thanks,
Jeff
Re: FSUSB Register access
Quoted 1 line · On Tue, Nov 04, 2008 at 02:35:50PM -0700, York, Jeffrey-P56387 wrote:
I am using Montavista Mobilinux 5 on OMAP2430 and I am trying to access
is it 2430sdp ? Which board are you using ??
Quoted 7 lines
the FSUSB register set and the kernel halts upon any attempt to access any of the registers in the FSUSB.
Note, under the Mobilinux distribution, the HSUSB controller is used by default, not the FSUSB controller. I am trying to access both so that I can have USB port 0 controlled by the HSUSB and port 1 controlled by the FSUSB controller.
in practice this shouldn't be needed actualy. upon attaching a FS device to ehci port, ehci would handoff the port to ohci. I'm not sure if that's working fine currently.
Quoted 5 lines
Per the TI spec, the host and device register sets within the FSUSB controller can only be accessed if the OTG register set is correctly configured. However, the OTG register set should be accessible as long as there is a 48MHz clock.
Quoted 8 lines
I have tried reading the
OTG_REVISIONregister (0x4805e300) and theOTG_SYSCON_1_REG(0x4805e304) withinarch/arm/plat-omap/usb.c. Upon either read, the kernel halts and I do not see any logs at startup after the
"Uncompressing Linux............................................................. ........................................... done, booting the kernel." message.
enable CONFIG_DEBUG_LL and you might see something. I'm guessing you're gonna get unhandled page fault request (or something similar, can't remember the correct error message) which most likely means you have to enable certain clocks before reading the registers.
btw, this list is for the open linux-omap.git tree. If your montavista distribution is not using the current git tree, you should probably contact montavista's support.
Quoted 4 lines
If I comment out the register accesses, I do see the startup log and I see the following log statements within
arch/arm/plat-omap/usb.c"Timeout enabling clockusb_l4_ick"
"Timeout enabling clockusb_fck"
what's the kernel version ?? This should be fixed a long time ago.
Quoted 29 lines
In addition I have printed out various register values and they are as follows.
Various register values:
CM_FCLKEN2_CORE- Address:0x49006204 - value 0x001B07BF,bit 0 is0x1, should be 1
CM_ICLKEN2_CORE- Address:0x49006214 - value 0x00000FFF,bit 0 is0x1, should be 1
CM_IDLEST2_CORE- Address:0x49006224 - value 0x00000FFE,bit 0 is0x0, should be 1 --- Possibly this is causing my problem but it is not clear to me what I need to do to have this set to a '1'.
CM_AUTOIDLE2_CORE- Address:0x49006234 - value 0x00000000,bit 0 is0x0, should be 0
CM_CLKSEL1_CORE- Address:0x49006240 - value 0x02102946,bits 27-25 is0x1, should be 1 for L3_CLK/1 (boot mode only), 2 for L3_CLK/2, or 4 for L3_CLK/4
PM_WKEN2_CORE- Address:0x490062A4 - value 0x00000000,bit 0 is0x0, should be 0 for disabled, 1 for enabled -- Per TI, this does not need to be enabled...
PM_WKST2_CORE- Address:0x490062B4 - value 0x00000000,bit 0 is0x0, should be 0 for not occurred, 1 for occurred
Quoted 6 lines
CM_IDLEST_CKGEN- Address:0x49006520 - value 0x00000336,bit 4 is0x1, should be0x1for active 48M_CLKAny ideas as to what the register settings need to be to enable access to the FSUSB OTG registers?
I'm guessing you only need to enable some clock(s). But also, please, reply with low level debug output and kernel version. Also, try out the current omap git tree. There's a defconfig for 2430sdp (omap_2430sdp_defconfig) that you might want to try.
Signature · 1 line
balbi
RE: FSUSB Register access
Balbi,
Thanks for your reply. My comments are below.
- Jeff
-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Felipe Balbi
Sent: Tuesday, November 04, 2008 3:21 PM
To: York, Jeffrey-P56387
Cc: [email protected]
Subject: Re: FSUSB Register access
Quoted 1 line · On Tue, Nov 04, 2008 at 02:35:50PM -0700, York, Jeffrey-P56387 wrote:
I am using Montavista Mobilinux 5 on OMAP2430 and I am trying to
access
is it 2430sdp ? Which board are you using ??
<JEFF SAYS: OMAP2430 SDP>
Quoted 4 lines
the FSUSB register set and the kernel halts upon any attempt to access any of the registers in the FSUSB.
Note, under the Mobilinux distribution, the HSUSB controller is used
by
Quoted 1 line
default, not the FSUSB controller. I am trying to access both so that
I
Quoted 1 line
can have USB port 0 controlled by the HSUSB and port 1 controlled by
the
Quoted 1 line
FSUSB controller.
in practice this shouldn't be needed actualy. upon attaching a FS device to ehci port, ehci would handoff the port to ohci. I'm not sure if that's working fine currently.
<JEFF SAYS: Not sure what you mean here. I will be using the HS controller for port 0 and the FS controller for port 1. The FS USB port 1 HW only support OHCI.>
Quoted 3 lines
Per the TI spec, the host and device register sets within the FSUSB controller can only be accessed if the OTG register set is correctly configured. However, the OTG register set should be accessible as
long
Quoted 5 lines
as there is a 48MHz clock.
I have tried reading the
OTG_REVISIONregister (0x4805e300) and theOTG_SYSCON_1_REG(0x4805e304) withinarch/arm/plat-omap/usb.c. Upon either read, the kernel halts and I do not see any logs at startup
after
Quoted 5 lines
the
"Uncompressing Linux............................................................. ........................................... done, booting the kernel." message.
enable CONFIG_DEBUG_LL and you might see something. I'm guessing you're gonna get unhandled page fault request (or something similar, can't remember the correct error message) which most likely means you have to enable certain clocks before reading the registers.
<JEFF SAYS: I did this and I do see logging now. It shows as expected an external abort on non-linefetch when it tries to read from an FSUSB register. As far as I can tell from the TI spec, I should only have to enable the 48 MHz clock... And I know it is enabled via a read from the CM_IDLEST_CKGEN register.>
btw, this list is for the open linux-omap.git tree. If your montavista distribution is not using the current git tree, you should probably contact montavista's support.
Quoted 4 lines
If I comment out the register accesses, I do see the startup log and I see the following log statements within
arch/arm/plat-omap/usb.c"Timeout enabling clockusb_l4_ick"
"Timeout enabling clockusb_fck"
what's the kernel version ?? This should be fixed a long time ago. <JEFF SAYS: 2.6.21>
Quoted 5 lines
In addition I have printed out various register values and they are as follows.
Various register values:
Quoted 8 lines
CM_FCLKEN2_CORE- Address:0x49006204 - value 0x001B07BF,bit 0 is0x1, should be 1
CM_ICLKEN2_CORE- Address:0x49006214 - value 0x00000FFF,bit 0 is0x1, should be 1
CM_IDLEST2_CORE- Address:0x49006224 - value 0x00000FFE,bit 0 is0x0, should be 1 --- Possibly this is causing my problem but it is not
clear
Quoted 3 lines
to me what I need to do to have this set to a '1'.
CM_AUTOIDLE2_CORE- Address:0x49006234 - value 0x00000000,bit 0 is
0x0,
Quoted 4 lines
should be 0
CM_CLKSEL1_CORE- Address:0x49006240 - value 0x02102946,bits 27-25 is0x1, should be 1 for L3_CLK/1 (boot mode only), 2 for L3_CLK/2, or 4
for
Quoted 9 lines
L3_CLK/4
PM_WKEN2_CORE- Address:0x490062A4 - value 0x00000000,bit 0 is0x0, should be 0 for disabled, 1 for enabled -- Per TI, this does not need to be enabled...
PM_WKST2_CORE- Address:0x490062B4 - value 0x00000000,bit 0 is0x0, should be 0 for not occurred, 1 for occurred
Quoted 6 lines
CM_IDLEST_CKGEN- Address:0x49006520 - value 0x00000336,bit 4 is0x1, should be0x1for active 48M_CLKAny ideas as to what the register settings need to be to enable access to the FSUSB OTG registers?
I'm guessing you only need to enable some clock(s). But also, please, reply with low level debug output and kernel version. Also, try out the current omap git tree. There's a defconfig for 2430sdp (omap_2430sdp_defconfig) that you might want to try.
Signature · 5 lines
balbi -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: FSUSB Register access
Hi,
Quoted 5 lines · On Tue, Nov 04, 2008 at 05:38:28PM -0700, York, Jeffrey-P56387 wrote:
<JEFF SAYS: I did this and I do see logging now. It shows as expected an external abort on non-linefetch when it tries to read from an FSUSB register. As far as I can tell from the TI spec, I should only have to enable the 48 MHz clock... And I know it is enabled via a read from the
CM_IDLEST_CKGENregister.>
hmm.. yeah, looks like it's clock issue. Do you call:
clk_get();clk_enable();
before reading the register ?? Although, if CM_IDLEST_CKGEN says it's on, it should be.
Anyways, try to clk_get() the correct clock and clk_enable() it before reading the register.
Remember, also, to clk_disable() when you're not reading the register and clk_put() when you don't need it anymore.
Quoted 2 lines
what's the kernel version ?? This should be fixed a long time ago. <JEFF SAYS: 2.6.21>
If you can try the current linux-omap git tree, I'd be glad. Also, when you post bug. Please, send the console output. It really helps us finding issues and suggesting you what to do.
Signature · 1 line
balbi
RE: FSUSB Register access
Balbi,
Thanks for your help.
See below for the answers.
-----Original Message-----
From: Felipe Balbi [mailto:[email protected]]
Sent: Tuesday, November 04, 2008 5:55 PM
To: York, Jeffrey-P56387
Cc: [email protected]; [email protected]
Subject: Re: FSUSB Register access
Hi,
Quoted 1 line · On Tue, Nov 04, 2008 at 05:38:28PM -0700, York, Jeffrey-P56387 wrote:
<JEFF SAYS: I did this and I do see logging now. It shows as
expected
Quoted 2 lines
an external abort on non-linefetch when it tries to read from an FSUSB register. As far as I can tell from the TI spec, I should only have
to
Quoted 1 line
enable the 48 MHz clock... And I know it is enabled via a read from
the
Quoted 1 line
CM_IDLEST_CKGENregister.>
hmm.. yeah, looks like it's clock issue. Do you call:
clk_get();clk_enable();
before reading the register ?? Although, if CM_IDLEST_CKGEN says it's on, it should be.
<JEFF SAYS: I do when trying to request the "usb_fck" and "usb_l4_ick". Not sure what the code is doing for the 48 MHz clock. That's done somewhere else in the Mobilinux kernel. Given that the register says its on, I was assuming that clock was good.>
Anyways, try to clk_get() the correct clock and clk_enable() it before reading the register.
Remember, also, to clk_disable() when you're not reading the register and clk_put() when you don't need it anymore.
Quoted 2 lines
what's the kernel version ?? This should be fixed a long time ago. <JEFF SAYS: 2.6.21>
If you can try the current linux-omap git tree, I'd be glad. Also, when you post bug. Please, send the console output. It really helps us finding issues and suggesting you what to do.
Signature · 1 line
balbi
Re: FSUSB Register access
Quoted 30 lines · On Tue, Nov 04, 2008 at 06:03:05PM -0700, York, Jeffrey-P56387 wrote:
Balbi,
Thanks for your help.
See below for the answers.
-----Original Message-----
From: Felipe Balbi [mailto:[email protected]]
Sent: Tuesday, November 04, 2008 5:55 PM
To: York, Jeffrey-P56387
Cc: [email protected]; [email protected]
Subject: Re: FSUSB Register accessHi,
Quoted 1 line · On Tue, Nov 04, 2008 at 05:38:28PM -0700, York, Jeffrey-P56387 wrote:
<JEFF SAYS: I did this and I do see logging now. It shows as
expected
Quoted 2 lines
an external abort on non-linefetch when it tries to read from an FSUSB register. As far as I can tell from the TI spec, I should only have
to
Quoted 1 line
enable the 48 MHz clock... And I know it is enabled via a read from
the
Quoted 1 line
CM_IDLEST_CKGENregister.>hmm.. yeah, looks like it's clock issue. Do you call:
clk_get();clk_enable();
Quoted 7 lines
before reading the register ?? Although, if
CM_IDLEST_CKGENsays it's on, it should be.<JEFF SAYS: I do when trying to request the "
usb_fck" and "usb_l4_ick". Not sure what the code is doing for the 48 MHz clock. That's done somewhere else in the Mobilinux kernel. Given that the register says its on, I was assuming that clock was good.>
still, you were getting the "unable to enable clock usb_fck after 1000000 tries" message, right ? But then again, the register says it's good.
So might be something elsewhere. Could you share your code ? It'd be much simpler to say what's going on by looking at your code.
Signature · 1 line
balbi
RE: FSUSB Register access
In reply to York, Jeffrey-P56387Quoted 7 lines
From: [email protected] [mailto:linux-omap- [email protected]] On Behalf Of York, Jeffrey-P56387
I am using Montavista Mobilinux 5 on OMAP2430 and I am trying to access the FSUSB register set and the kernel halts upon any attempt to access any of the registers in the FSUSB.
I seem to recall this mixed MUSB + FUSB was functional in ML4.1. If you have access you might check the older code.
Regards,
Richard W.
Re: [REVIEW PATCH 8/9] DSS: support for Beagle Board
In reply to Tomi Valkeinenarch/arm/mach-omap2/board-omap3beagle.c static struct platform_device keys_gpio = { · line 322
Quoted 12 lines · On Tue, 04 Nov 2008 18:10:38 +0200 "ext Tomi Valkeinen"…
Signed-off-by Tomi Valkeinen <[email protected]>---
arch/arm/mach-omap2/board-omap3beagle.c | 121 ++++++++++++++++++++++++++++--- 1 files changed, 108 insertions(+), 13 deletions(-)arch/arm/mach-omap2/board-omap3beagle.c +6
-0+static void __init beagle_display_init (void ) +{ +int r; + + r =gpio_request (beagle_display_data_dvi.panel_reset_gpio,"DVI reset GPIO" ); +if (r <0 ) {
GPIO label "DVI reset" is enough.
Jarkko
Re: [REVIEW PATCH 8/9] DSS: support for Beagle Board
Quoted 4 lines · Jarkko Nikula
Quoted 2 lines
+ r =
gpio_request(beagle_display_data_dvi.panel_reset_gpio, "DVI reset GPIO"); + if(r < 0) {GPIO label "DVI reset" is enough.
Surely this ** doesn't work ** at least against the OMAP git tree which already has:
omap_cfg_reg(J25_34XX_GPIO170);
gpio_request(170, "DVI_nPD");
/* REVISIT leave DVI powered down until it's needed ... */
gpio_direction_output(170, true);Label matches the DVI chip, not board schematics. Agreed, it's not a reset.
I'd like to see any FB/DSS/... updates have the property that the TFP410 chip is powered down *unless* both (a) the frame buffer/DSS/... driver is active, and (b) the DVI channel is in use.
So for example a kernel without FB/DSS/... configured, that DVI chip is never powered up. And when only the S-Video channel is used, DVI isn't powered up either.
- Dave
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [REVIEW PATCH 8/9] DSS: support for Beagle Board
Quoted 9 lines · ext David Brownell
Quoted 1 line · Jarkko Nikula
Quoted 1 line
+ r = gpio_request(beagle_display_data_dvi.panel_reset_gpio,
"DVI reset GPIO");
Quoted 3 lines
Quoted 1 line
+ if(r < 0) {
GPIO label "DVI reset" is enough.
Surely this ** doesn't work ** at least against the OMAP git tree which already has:
Well, it surely does! =)
But good catch, I'll fix it. There's probably a warning on kernel log about "can't get a gpio".
Quoted 9 lines
omap_cfg_reg(J25_34XX_GPIO170); gpio_request(170, "DVI_nPD"); /* REVISIT leave DVI powered down until it's needed ... */ gpio_direction_output(170, true);Label matches the DVI chip, not board schematics. Agreed, it's not a reset.
Quoted 9 lines
I'd like to see any FB/DSS/... updates have the property that the TFP410 chip is powered down *unless* both (a) the frame buffer/DSS/... driver is active, and (b) the DVI channel is in use.
So for example a kernel without FB/DSS/... configured, that DVI chip is never powered up. And when only the S-Video channel is used, DVI isn't powered up either.
Well, my drivers do not enable the DVI chip unless DVI is in use. It is in use by default, but you can turn it off. And if the whole DSS is not compiled in, then no body will turn the DVI chip on.
However, the bootloader turns the DVI chip on (at least the default beagle board u-boot). If the kernel by default turns the DVI chip off, and then later on when the DSS starts, we'll have a glitch on the display. Not that there currently is support for glitchless transition from bootloader display to kernel display, but still...
Quoted 2 lines
- Dave
Tomi
Re: [REVIEW PATCH 8/9] DSS: support for Beagle Board
Op 6 nov 2008, om 09:23 heeft Tomi Valkeinen het volgende geschreven:
Quoted 3 lines
However, the bootloader turns the DVI chip on (at least the default beagle board u-boot).
Only the old and broken TI u-boots do that, recent ones (2008.10) with the patches that are going upstream don't touch the DVI chip (nor the audio chips for that matter.
regards,
Koen
PATCH 9/9 DSS: support for OMAP3 SDP board
In reply to Tomi Valkeinen---
arch/arm/mach-omap2/board-3430sdp.c | 234 +++++++++++++++++++++++++++++++++-- drivers/video/omap2/Kconfig | 7 + drivers/video/omap2/Makefile | 1 drivers/video/omap2/panel-sdp3430.c | 110 ++++++++++++++++ 4 files changed, 340 insertions(+), 12 deletions(-) create mode 100644 drivers/video/omap2/panel-sdp3430.c
arch/arm/mach-omap2/board-3430sdp.c +223 -11
@@ -40,6 +40,8 @@#include <mach/keypad.h> #include <mach/dma.h> #include <mach/gpmc.h> +#include <mach/omapfb.h> +#include <mach/display.h> #include <asm/io.h> #include <asm/delay.h>
@@ -239,14 +241,224 @@ static struct spi_board_info sdp3430_spi_board_info[] __initdata = { }, }; -static struct platform_device sdp3430_lcd_device = { - .name ="sdp2430_lcd" , - .id =-1 , +static struct omap_fbmem_config sdp3430_fbmem0_config = { + .size =1024 *768 *4 , + .start =OMAPFB_MEMTYPE_SDRAM , +}; + +static struct omap_fbmem_config sdp3430_fbmem1_config = { + .size =640 *480 *4 , + .start =OMAPFB_MEMTYPE_SDRAM , }; +static struct omap_fbmem_config sdp3430_fbmem2_config = { + .size =640 *480 *4 , + .start =OMAPFB_MEMTYPE_SDRAM , +}; + + +#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91 +#define SDP2430_LCD_PANEL_ENABLE_GPIO 154 +#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 24 +#define SDP3430_LCD_PANEL_ENABLE_GPIO 28 + +#define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER +#define ENABLE_VAUX2_DEDICATED 0x09 +#define ENABLE_VAUX2_DEV_GRP 0x20 +#define ENABLE_VAUX3_DEDICATED 0x03 +#define ENABLE_VAUX3_DEV_GRP 0x20 + +#define ENABLE_VPLL2_DEDICATED 0x05 +#define ENABLE_VPLL2_DEV_GRP 0xE0 +#define TWL4030_VPLL2_DEV_GRP 0x33 +#define TWL4030_VPLL2_DEDICATED 0x36 + +#define t2_out (c, r, v) twl4030_i2c_write_u8(c, r, v) + +static unsigned backlight_gpio; +static unsigned enable_gpio; +static int lcd_enabled; +static int dvi_enabled; + +static void __init display_init (void ) +{ +int r; + + enable_gpio =SDP3430_LCD_PANEL_ENABLE_GPIO ; + backlight_gpio =SDP3430_LCD_PANEL_BACKLIGHT_GPIO ; + + r =gpio_request (enable_gpio,"OMAP SDP LCD Reset GPIO" ); +if (r) { +printk (KERN_ERR "failed to get LCD reset GPIO\n" ); + goto err0; + } + + r =gpio_request (backlight_gpio,"OMAP SDP LCD Backlight GPIO" ); +if (r) { +printk (KERN_ERR "failed to get LCD backlight GPIO\n" ); + goto err1; + } + +gpio_direction_output (enable_gpio,0 ); +gpio_direction_output (backlight_gpio,0 ); + +return ; +err1: +gpio_free (enable_gpio); +err0: +return ; +} + + +static int panel_enable_lcd (struct omap_display *display) +{ +u8 ded_val, ded_reg; +u8 grp_val, grp_reg; + +if (dvi_enabled) { +printk (KERN_ERR "cannot enable LCD, DVI is enabled\n" ); +return -EINVAL ; + } + +if (system_rev >OMAP3430_REV_ES1_0 ) { +t2_out (PM_RECEIVER ,ENABLE_VPLL2_DEDICATED , +TWL4030_VPLL2_DEDICATED ); +t2_out (PM_RECEIVER ,ENABLE_VPLL2_DEV_GRP , +TWL4030_VPLL2_DEV_GRP ); + } + + ded_reg =TWL4030_VAUX3_DEDICATED ; + ded_val =ENABLE_VAUX3_DEDICATED ; + grp_reg =TWL4030_VAUX3_DEV_GRP ; + grp_val =ENABLE_VAUX3_DEV_GRP ; + +gpio_direction_output (enable_gpio,1 ); +gpio_direction_output (backlight_gpio,1 ); + +if (0 !=t2_out (PM_RECEIVER , ded_val, ded_reg)) +return -EIO ; +if (0 !=t2_out (PM_RECEIVER , grp_val, grp_reg)) +return -EIO ; + + lcd_enabled =1 ; + +return 0 ; +} + +static void panel_disable_lcd (struct omap_display *display) +{ + lcd_enabled =0 ; + +gpio_direction_output (enable_gpio,0 ); +gpio_direction_output (backlight_gpio,0 ); + +if (system_rev >OMAP3430_REV_ES1_0 ) { +t2_out (PM_RECEIVER ,0x0 ,TWL4030_VPLL2_DEDICATED ); +t2_out (PM_RECEIVER ,0x0 ,TWL4030_VPLL2_DEV_GRP ); +mdelay (4 ); + } +} + +static struct omap_display_data sdp_display_data = { + .type =OMAP_DISPLAY_TYPE_DPI , + .name ="lcd" , + .panel_name ="panel-sdp3430" , + .u.dpi.data_lines =16 , + .panel_enable = panel_enable_lcd, + .panel_disable = panel_disable_lcd, +}; + +static int panel_enable_dvi (struct omap_display *display) +{ +if (lcd_enabled) { +printk (KERN_ERR "cannot enable DVI, LCD is enabled\n" ); +return -EINVAL ; + } + +if (system_rev >OMAP3430_REV_ES1_0 ) { +t2_out (PM_RECEIVER ,ENABLE_VPLL2_DEDICATED , +TWL4030_VPLL2_DEDICATED ); +t2_out (PM_RECEIVER ,ENABLE_VPLL2_DEV_GRP , +TWL4030_VPLL2_DEV_GRP ); + } + + dvi_enabled =1 ; + +return 0 ; +} + +static void panel_disable_dvi (struct omap_display *display) +{ + dvi_enabled =0 ; + +if (system_rev >OMAP3430_REV_ES1_0 ) { +t2_out (PM_RECEIVER ,0x0 ,TWL4030_VPLL2_DEDICATED ); +t2_out (PM_RECEIVER ,0x0 ,TWL4030_VPLL2_DEV_GRP ); +mdelay (4 ); + } +} + + +static struct omap_display_data sdp_display_data_dvi = { + .type =OMAP_DISPLAY_TYPE_DPI , + .name ="dvi" , + .panel_name ="panel-dvi" , + .u.dpi.data_lines =24 , + .panel_enable = panel_enable_dvi, + .panel_disable = panel_disable_dvi, +}; + +static int panel_enable_tv (struct omap_display *display) +{ +#define ENABLE_VDAC_DEDICATED 0x03 +#define ENABLE_VDAC_DEV_GRP 0x20 + +twl4030_i2c_write_u8 (TWL4030_MODULE_PM_RECEIVER , +ENABLE_VDAC_DEDICATED , +TWL4030_VDAC_DEDICATED ); +twl4030_i2c_write_u8 (TWL4030_MODULE_PM_RECEIVER , +ENABLE_VDAC_DEV_GRP ,TWL4030_VDAC_DEV_GRP ); + +return 0 ; +} + +static void panel_disable_tv (struct omap_display *display) +{ +twl4030_i2c_write_u8 (TWL4030_MODULE_PM_RECEIVER ,0x00 , +TWL4030_VDAC_DEDICATED ); +twl4030_i2c_write_u8 (TWL4030_MODULE_PM_RECEIVER ,0x00 , +TWL4030_VDAC_DEV_GRP ); +} + +static struct omap_display_data sdp_display_data_tv = { + .type =OMAP_DISPLAY_TYPE_VENC , + .name ="tv" , + .u.venc.type =OMAP_DSS_VENC_TYPE_SVIDEO , + .panel_enable = panel_enable_tv, + .panel_disable = panel_disable_tv, +}; + +static struct omap_dss_platform_data sdp3430_dss_data = { + .num_displays =3 , + .displays = { + &sdp_display_data, + &sdp_display_data_dvi, + &sdp_display_data_tv, + } +}; + +static struct platform_device sdp3430_dss_device = { + .name ="omap-dss" , + .id =-1 , + .dev = { + .platform_data = &sdp3430_dss_data, + }, +}; + +static struct platform_device *sdp3430_devices[]__initdata = { &sdp3430_smc91x_device, - &sdp3430_lcd_device, + &sdp3430_dss_device, };static inline void __init sdp3430_init_smc91x (void )
@@ -293,13 +505,11 @@ static struct omap_uart_config sdp3430_uart_config __initdata = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), }; -static struct omap_lcd_config sdp3430_lcd_config__initdata = { - .ctrl_name ="internal" , -}; -static struct omap_board_config_kernel sdp3430_config[]__initdata = { {OMAP_TAG_UART , &sdp3430_uart_config }, - {OMAP_TAG_LCD , &sdp3430_lcd_config }, + {OMAP_TAG_FBMEM , &sdp3430_fbmem0_config }, + {OMAP_TAG_FBMEM , &sdp3430_fbmem1_config }, + {OMAP_TAG_FBMEM , &sdp3430_fbmem2_config }, };static int sdp3430_batt_table[] = {
@@ -450,8 +660,6 @@ static void __init omap_3430sdp_init(void) {omap3430_i2c_init ();platform_add_devices (sdp3430_devices,ARRAY_SIZE (sdp3430_devices)); - omap_board_config = sdp3430_config; - omap_board_config_size =ARRAY_SIZE (sdp3430_config);if (system_rev >OMAP3430_REV_ES1_0 ) ts_gpio =OMAP34XX_TS_GPIO_IRQ_SDPV2 ;else
@@ -466,10 +674,14 @@ static void __init omap_3430sdp_init(void)usb_musb_init ();usb_ehci_init ();hsmmc_init (); +display_init (); }static void __init omap_3430sdp_map_io (void ) { + omap_board_config = sdp3430_config; + omap_board_config_size =ARRAY_SIZE (sdp3430_config); +omap2_set_globals_343x ();omap2_map_common_io (); }
drivers/video/omap2/Kconfig +6 -1
@@ -45,5 +45,10 @@ config PANEL_DVI_VERYHIGHRES endchoice -endmenu +config PANEL_SDP3430 + tristate "SDP3430 Panel" + depends on OMAP2_DSS + help + SDP3430 LCD +endmenu
drivers/video/omap2/Makefile +1 -0
@@ -2,3 +2,4 @@ obj-$(CONFIG_FB_OMAP2) += omapfb.o omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o obj-$(CONFIG_PANEL_DVI) += panel-dvi.o +obj-$(CONFIG_PANEL_SDP3430) += panel-sdp3430.o
drivers/video/omap2/panel-sdp3430.c new file +110 -0
110 lines not on this page · raw message
Re: [REVIEW PATCH 9/9] DSS: support for OMAP3 SDP board
Quoted 11 lines · On Tue, 04 Nov 2008 18:10:45 +0200 "ext Tomi Valkeinen"…
Signed-off-by Tomi Valkeinen <[email protected]>---
arch/arm/mach-omap2/board-3430sdp.c | 234 +++++++++++++++++++++++++++++++++-- drivers/video/omap2/Kconfig | 7 + drivers/video/omap2/Makefile | 1 drivers/video/omap2/panel-sdp3430.c | 110 ++++++++++++++++ 4 files changed, 340 insertions(+), 12 deletions(-) create mode 100644 drivers/video/omap2/panel-sdp3430.c
Quoted 2 lines
+static void
__initdisplay_init(void)
I would use unique 3430sdp_display_init even the function is static. Cleaner symbol names and cleaner oops dumps.
Quoted 4 lines
arch/arm/mach-omap2/board-3430sdp.c +4
-0+{ +int r; + + enable_gpio =SDP3430_LCD_PANEL_ENABLE_GPIO ;
arch/arm/mach-omap2/board-3430sdp.c static struct spi_board_info sdp3430_spi_board_info[] __initdata = { · line 297
Quoted 10 lines
arch/arm/mach-omap2/board-3430sdp.c +10
-0+ backlight_gpio =SDP3430_LCD_PANEL_BACKLIGHT_GPIO ; + + r =gpio_request (enable_gpio,"OMAP SDP LCD Reset GPIO" ); +if (r) { +printk (KERN_ERR "failed to get LCD reset GPIO\n" ); + goto err0; + } + + r =gpio_request (backlight_gpio,"OMAP SDP LCD Backlight GPIO" ); +if (r) {
How about labels "LCD reset" and "LCD backlight" (actually bit too long).
arch/arm/mach-omap2/board-3430sdp.c static struct spi_board_info sdp3430_spi_board_info[] __initdata = { · line 371
Quoted 3 lines
arch/arm/mach-omap2/board-3430sdp.c +3
-0+static int panel_enable_lcd(struct omap_display *display) +static void panel_disable_lcd(struct omap_display *display) +static int panel_enable_dvi(struct omap_display *display)
Would it better to rename these as sdp3430_enable_lcd etc since otherwise looks somewhat confusing to see them in board-3430sdp.c where there is also panel-sdp3430.c?
Jarkko
Quoted 66 lines
-----Original Message-----
From: Tomi Valkeinen [mailto:[email protected]]
Sent: Tuesday, November 04, 2008 9:40 PM
To: [email protected]
Cc: [email protected]
Subject: [Linux-fbdev-devel] [REVIEW PATCH 0/9] DSS: Series descriptionNew Display Subsystem for OMAP2/3
---------------------------------This patch set implements new Display Subsystem (DSS) for OMAP2/3 processors. The DSS is still under work and these patches are for review. Note that there is also another new DSS implementation from TI.
The DSS has been tested on OMAP3 SDP board, Beagle Board and on two unreleased boards with DSI and SDI displays. The DSS used to work on OMAP2 board also, but
it's been a while since I was able to test with OMAP2 board.The first patch is a doc file that tries to explain a bit how the drivers work.
The patch set is based on the current linux-omap tree.
You can find the patches also from a git tree at
http://www.bat.org/~tomba/git/linux-omap-dss.git/Note that you also need two patches from Mans Rullgard to make things work. These
are needed to be able to reconfigure DSS functional clock.
http://git.mansr.com/?p=linux-
omap;a=commit;h=e2de5e5578fbaa9b4b75074796da0608fc93e6ae
http://git.mansr.com/?p=linux-
omap;a=commit;h=2b7b958dc79e51127d7a4ecf88ce12dbc6c31426Questions/problems
------------------Perhaps the biggest problems I have is the interface to user space. OMAP hardware doesn't quite fit in to the framebuffer framework. The problem is that
a framebuffer can go to multiple overlays, and also the target display, to which a framebuffer goes, can change. In addition, the framebuffer size is used as overlay size, not display resolution. So a framebuffer != display.I believe DRM modesetting could be of help here, at least partially, but I haven't tried that approach yet.
But DRM modesetting wouldn't solve all the problems. For example, we still need
to configure overlays and overlay managers, and they don't quite belong to either the framebuffer side or the display side. Currently you configure them via a hackish sysfs interface, but I've been wondering if a/dev/omap-dssdevice with ioctls would be a better choice.There's currently no V4L2 support, but I have been thinking about that. I don't
want to make any hardcoded configuration for those, because sometimes you want to use framebuffer devices for video overlays. So what I'd like to have is a way, compile time or run time, to configure which overlays go to framebuffer devices and which go to V4L2 devices.---
Quoted 11 lines
Tomi Valkeinen (9):
DSS: support for OMAP3 SDP board
DSS: support for Beagle Board
DSS: Add generic DVI panel
DSS: OMAPFB: fb driver for new display subsystem
DSS: DSI support for OMAP2/3 DSS
DSS: TV-out support for OMAP2/3 DSS
DSS: RFBI support for OMAP2/3 DSS
DSS: New display subsystem driver for OMAP2/3
DSS: Documentation for OMAP2/3 display subsystem
[Shah, Hardik] We have reviewed the patches in detail and even made modifications to make it work on the OMAP3EVM. Here are our observations:
1) The overall implementation is very much in line with our earlier proposal to provide generic API that supports both V4L2 and FBDEV.
2) The implementation supports multiple output interfaces e.g. RFBI, SDI, DSI, ... that we did not have in our plans
3) You have also validated it on lot many platforms that we do not have access.
We believe patches are a good step in right direction.
We plan to use this patchset as base for supporting these additional use cases:
a) Adding the V4L2 user interface to the video pipelines (I believe video pipelines are natural fit for the V4L2 frame work. If use case is there for FBDEV interface we can have compile time option to expose the video pipelines as the either FBDEV or v4L2 interface).
b) Modification of the DSS/DISPC library for supporting V4L2 user interface.
c) Supporting the functionality like alpha blending, global alpha blending, setting of various TV standards etc.
d) Supporting the mirroring and rotation in both FBDEV and V4L2 driver.
Do let us know if you aren't already working on any of these.
BTW, patch for supporting omap3evm will be submitted shortly.
Regards,
Vaibhav Hiremath <[email protected]>
Hardik Shah <[email protected]>
Quoted 15 lines
--
Tomi Valkeinen-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Linux-fbdev-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/linux-fbdev-devel
Hi,
Quoted 9 lines · Hardik
Quoted 1 line
[Shah, Hardik] We have reviewed the patches in detail and even made modifications to make it work on the OMAP3EVM. Here are our observations:
1) The overall implementation is very much in line with our earlier proposal to provide generic API that supports both V4L2 and FBDEV.
2) The implementation supports multiple output interfaces e.g. RFBI, SDI, DSI, ... that we did not have in our plans
3) You have also validated it on lot many platforms that we do not have access.We believe patches are a good step in right direction.
Quoted 8 lines
We plan to use this patchset as base for supporting these additional use cases:
a) Adding the V4L2 user interface to the video pipelines (I believe video pipelines are natural fit for the V4L2 frame work. If use case is there for FBDEV interface we can have compile time option to expose the video pipelines as the either FBDEV or v4L2 interface).
b) Modification of the DSS/DISPC library for supporting V4L2 user interface.
c) Supporting the functionality like alpha blending, global alpha blending, setting of various TV standards etc.
d) Supporting the mirroring and rotation in both FBDEV and V4L2 driver.Do let us know if you aren't already working on any of these.
This sounds very good. I am not currently working on any of those items you mentioned. A couple of comments/thoughts about them:
a) Yes, V4L2 interface would be nice. But there are use cases for FB devices also, and sometimes you don't want V4L2 devices at all. So as you suggested, a compile time option to select this is necessary. Or, better yet, a runtime option.
One way to implement simultaneous FB and V4L2 devices is to have to separate drivers. But then this needs more locking support to DSS, and pobably some kind of event mechanism. For example, if both FB and V4L2 have overlays on the same display, and one of them changes the screen resolution, the other one needs to know about this also.
So what I have been thinking is to have both FB and V4L2 in the same driver. This would make things easier. But then again, I don't know how much code V4L2 needs, and if the combined driver would get too complex.
b) Do you already have ideas what features V4L2 needs that are not present in DSS currently?
c) Yes, these would be nice.
d) These would be nice also. About rotation, I think there are three kinds of rotation that are handled by different entities:
- DMA rotation, for framebuffers in SRAM. Handled by DSS.
- External framebuffer rotation, handled by the external framebuffer controller.
- VRFB rotation. This is basically a memory handling configuration, and is transparent to the end user (in this case, DSS) of the memory. Should be handled by the entity that allocates the memory, ie. omapfb.
Tomi
Quoted 55 lines
-----Original Message-----
From: Tomi Valkeinen [mailto:[email protected]]
Sent: Monday, November 10, 2008 5:01 PM
To: Shah, Hardik
Cc: Tomi Valkeinen; [email protected]; linux- [email protected]
Subject: RE: [Linux-fbdev-devel] [REVIEW PATCH 0/9] DSS: Series descriptionHi,
Quoted 2 lines · Hardik
Quoted 1 line
[Shah, Hardik] We have reviewed the patches in detail and even made
modifications to make it work on the OMAP3EVM. Here are our observations:
Quoted 2 lines
1) The overall implementation is very much in line with our earlier proposal
to provide generic API that supports both V4L2 and FBDEV.
Quoted 1 line
2) The implementation supports multiple output interfaces e.g. RFBI, SDI,
DSI, ... that we did not have in our plans
Quoted 1 line
3) You have also validated it on lot many platforms that we do not have
access.
Quoted 4 lines
We believe patches are a good step in right direction.
We plan to use this patchset as base for supporting these additional use
cases:
Quoted 2 lines
a) Adding the V4L2 user interface to the video pipelines (I believe video
pipelines are natural fit for the V4L2 frame work. If use case is there for FBDEV interface we can have compile time option to expose the video pipelines as the either FBDEV or v4L2 interface).
Quoted 2 lines
b) Modification of the DSS/DISPC library for supporting V4L2 user interface.
c) Supporting the functionality like alpha blending, global alpha blending,setting of various TV standards etc.
Quoted 3 lines
d) Supporting the mirroring and rotation in both FBDEV and V4L2 driver.
Do let us know if you aren't already working on any of these.
This sounds very good. I am not currently working on any of those items you mentioned. A couple of comments/thoughts about them:
a) Yes, V4L2 interface would be nice. But there are use cases for FB devices also, and sometimes you don't want V4L2 devices at all. So as you suggested, a compile time option to select this is necessary. Or, better yet, a runtime option.
One way to implement simultaneous FB and V4L2 devices is to have to separate drivers. But then this needs more locking support to DSS, and pobably some kind of event mechanism. For example, if both FB and V4L2 have overlays on the same display, and one of them changes the screen resolution, the other one needs to know about this also.
Quoted 4 lines
So what I have been thinking is to have both FB and V4L2 in the same driver. This would make things easier. But then again, I don't know how much code V4L2 needs, and if the combined driver would get too complex.
[Shah, Hardik] As long as the screen resolutions and timings are concerned, V4L2 driver will always take into account resolution before setting the format. Same is true for frame buffer driver before panning the display it should get the fscreen info and vscreen info and then start panning. While panning/streaming is going on any of the V4L2/FBDEV driver application has to take care of not changing the screen resolution/timing.
Quoted 3 lines
b) Do you already have ideas what features V4L2 needs that are not present in DSS currently?
[Shah, Hardik] We are working on that. We will be providing the comments on changes/modification in the DSS/DISPC in next two/three days.
Quoted 10 lines
c) Yes, these would be nice.
d) These would be nice also. About rotation, I think there are three kinds of rotation that are handled by different entities:
- DMA rotation, for framebuffers in SRAM. Handled by DSS.
- External framebuffer rotation, handled by the external framebuffer controller.
- VRFB rotation. This is basically a memory handling configuration, and is transparent to the end user (in this case, DSS) of the memory. Should be handled by the entity that allocates the memory, ie. omapfb.
[Shah, Hardik] so how are you planning to take care of rotation/mirroring. We have board that only supports VRFB rotation.
Hardik
Vaibhav
Quoted 2 lines
Tomi
Quoted 57 lines
-----Original Message-----
From: Tomi Valkeinen [mailto:[email protected]]
Sent: Tuesday, November 04, 2008 9:40 PM
To: [email protected]
Cc: [email protected]
Subject: [Linux-fbdev-devel] [REVIEW PATCH 0/9] DSS: Series descriptionNew Display Subsystem for OMAP2/3
---------------------------------This patch set implements new Display Subsystem (DSS) for OMAP2/3 processors. The DSS is still under work and these patches are for review. Note that there is also another new DSS implementation from TI.
The DSS has been tested on OMAP3 SDP board, Beagle Board and on two unreleased boards with DSI and SDI displays. The DSS used to work on OMAP2 board also, but
it's been a while since I was able to test with OMAP2 board.The first patch is a doc file that tries to explain a bit how the drivers work.
The patch set is based on the current linux-omap tree.
You can find the patches also from a git tree at
http://www.bat.org/~tomba/git/linux-omap-dss.git/Note that you also need two patches from Mans Rullgard to make things work. These
are needed to be able to reconfigure DSS functional clock.
http://git.mansr.com/?p=linux-
omap;a=commit;h=e2de5e5578fbaa9b4b75074796da0608fc93e6ae
http://git.mansr.com/?p=linux-
omap;a=commit;h=2b7b958dc79e51127d7a4ecf88ce12dbc6c31426Questions/problems
------------------Perhaps the biggest problems I have is the interface to user space. OMAP hardware doesn't quite fit in to the framebuffer framework. The problem is that
a framebuffer can go to multiple overlays, and also the target display, to which a framebuffer goes, can change. In addition, the framebuffer size is used as overlay size, not display resolution. So a framebuffer != display.I believe DRM modesetting could be of help here, at least partially, but I haven't tried that approach yet.
But DRM modesetting wouldn't solve all the problems. For example, we still need
to configure overlays and overlay managers, and they don't quite belong to either the framebuffer side or the display side. Currently you configure them via a hackish sysfs interface, but I've been wondering if a/dev/omap-dssdevice with ioctls would be a better choice.
Quoted 7 lines
There's currently no V4L2 support, but I have been thinking about that. I don't
want to make any hardcoded configuration for those, because sometimes you want to use framebuffer devices for video overlays. So what I'd like to have is a way, compile time or run time, to configure which overlays go to framebuffer devices and which go to V4L2 devices.
[Shah, Hardik] Hi Tomi,
We are successful to bring up the basic functionality of the V4L2 driver onto your patches. We will be posting those patches in a day or two. Based on our V4L2 driver development we have few questions/suggestions on DSS patches you submitted.
1. Display enable function is returning false if the display is already enabled. Instead it should just return without error if display is already enabled as V4L2 and fbdev both may be enabling it without each other's knowledge.
2. Second display enable/disable should maintain the reference count as disabling of the display by one driver will leave other driver without display.
3. I think the row increment value should not be calculate inside the dispc.c file instead high level driver will pass the value it requires based on his buffer requirement and dispc.c should program it dumbly. This is mainly due to the odd row_inc_value requirement for the VRFB space.
4. There is API in dispc.c file to change pixel increment value.
5. We need separate API to enable the plane and enable the clocks. Once the clock is enabled driver can directly go and program registers through low level dispc APIs instead of dispc APIs enabling the clock for each register programming and then disabling it.
This will avoid the enabling and disabling of the clocks for each frame displayed. As for V4L2 interface driver will enable planes and clocks during VIDIOC_STREAMON ioctls and during the streaming it will just change the buffer address for displaying frames. This way delay between the enabling/disabling of the clocks can also be saved. It would be driver's responsibility to enable the clocks before programming any registers. Same may be true for setting the GO bit of the respective overlay managers.
6. We also need a public API to program the color conversion values. Some application may need to program it differently than standard values.
Thanks and Regards,
Hardik Shah
Vaibhav Hiremath
Quoted 13 lines
--
Tomi Valkeinen-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Linux-fbdev-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/linux-fbdev-devel
Hi,
Quoted 11 lines · Hardik
Quoted 11 lines
-----Original Message-----
From: Tomi Valkeinen [mailto:[email protected]]
Sent: Tuesday, November 04, 2008 9:40 PM
To: [email protected]
Cc: [email protected]
Subject: [Linux-fbdev-devel] [REVIEW PATCH 0/9] DSS: Series descriptionNew Display Subsystem for OMAP2/3
---------------------------------
[snip]
Quoted 9 lines
Quoted 1 line
[Shah, Hardik] Hi Tomi,
We are successful to bring up the basic functionality of the V4L2 driver onto your patches. We will be posting those patches in a day or two. Based on our V4L2 driver development we have few questions/suggestions on DSS patches you submitted.
1. Display enable function is returning false if the display is already enabled. Instead it should just return without error if display is already enabled as V4L2 and fbdev both may be enabling it without each other's knowledge.2. Second display enable/disable should maintain the reference count as disabling of the display by one driver will leave other driver without display.
3. I think the row increment value should not be calculate inside the
dispc.cfile instead high level driver will pass the value it requires based on his buffer requirement anddispc.cshould program it dumbly. This is mainly due to the oddrow_inc_valuerequirement for the VRFB space.
Quoted 8 lines
4. There is API in
dispc.cfile to change pixel increment value.5. We need separate API to enable the plane and enable the clocks. Once the clock is enabled driver can directly go and program registers through low level dispc APIs instead of dispc APIs enabling the clock for each register programming and then disabling it.
This will avoid the enabling and disabling of the clocks for each frame displayed. As for V4L2 interface driver will enable planes and clocks during
VIDIOC_STREAMONioctls and during the streaming it will just change the buffer address for displaying frames. This way delay between the enabling/disabling of the clocks can also be saved. It would be driver's responsibility to enable the clocks before programming any registers. Same may be true for setting the GO bit of the respective overlay managers.6. We also need a public API to program the color conversion values. Some application may need to program it differently than standard values.
These all sound valid changes to me, I will see to them. For the time being, just make whatever hacks you need to get the V4L2 running. And preferably mark these hacks with a comment, so it's easy to find them.
As for the 5. issue, I've been thinking the same thing. However, usually the clocks are always on when the LCD is on. So even if there are clk_enable() calls, all they do is increment the ref count.
Quoted 5 lines
Thanks and Regards,
Hardik Shah
Vaibhav Hiremath
Tomi
Quoted 114 lines · Tomi Valkeinen
New Display Subsystem for OMAP2/3
---------------------------------This patch set implements new Display Subsystem (DSS) for OMAP2/3 processors. The DSS is still under work and these patches are for review. Note that there is also another new DSS implementation from TI.
The DSS has been tested on OMAP3 SDP board, Beagle Board and on two unreleased boards with DSI and SDI displays. The DSS used to work on OMAP2 board also, but it's been a while since I was able to test with OMAP2 board.
The first patch is a doc file that tries to explain a bit how the drivers work.
The patch set is based on the current linux-omap tree.
You can find the patches also from a git tree at
http://www.bat.org/~tomba/git/linux-omap-dss.git/Note that you also need two patches from Mans Rullgard to make things work. These are needed to be able to reconfigure DSS functional clock.
http://git.mansr.com/?p=linux-omap;a=commit;h=e2de5e5578fbaa9b4b75074796da0608fc93e6ae
http://git.mansr.com/?p=linux-omap;a=commit;h=2b7b958dc79e51127d7a4ecf88ce12dbc6c31426Questions/problems
------------------Perhaps the biggest problems I have is the interface to user space. OMAP hardware doesn't quite fit in to the framebuffer framework. The problem is that a framebuffer can go to multiple overlays, and also the target display, to which a framebuffer goes, can change. In addition, the framebuffer size is used as overlay size, not display resolution. So a framebuffer != display.
I believe DRM modesetting could be of help here, at least partially, but I haven't tried that approach yet.
But DRM modesetting wouldn't solve all the problems. For example, we still need to configure overlays and overlay managers, and they don't quite belong to either the framebuffer side or the display side. Currently you configure them via a hackish sysfs interface, but I've been wondering if a
/dev/omap-dssdevice with ioctls would be a better choice.There's currently no V4L2 support, but I have been thinking about that. I don't want to make any hardcoded configuration for those, because sometimes you want to use framebuffer devices for video overlays. So what I'd like to have is a way, compile time or run time, to configure which overlays go to framebuffer devices and which go to V4L2 devices.
---
Tomi Valkeinen (9):
DSS: support for OMAP3 SDP board
DSS: support for Beagle Board
DSS: Add generic DVI panel
DSS: OMAPFB: fb driver for new display subsystem
DSS: DSI support for OMAP2/3 DSS
DSS: TV-out support for OMAP2/3 DSS
DSS: RFBI support for OMAP2/3 DSS
DSS: New display subsystem driver for OMAP2/3
DSS: Documentation for OMAP2/3 display subsystemDocumentation/arm/OMAP/DSS | 240 ++ arch/arm/mach-omap2/board-3430sdp.c | 234 ++ arch/arm/mach-omap2/board-omap3beagle.c | 121 + 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/dsi.c | 3027 +++++++++++++++++++++++++++++ arch/arm/plat-omap/dss/dss.c | 547 +++++ arch/arm/plat-omap/dss/dss.h | 240 ++ arch/arm/plat-omap/dss/rfbi.c | 1234 ++++++++++++ arch/arm/plat-omap/dss/sdi.c | 154 + arch/arm/plat-omap/dss/venc.c | 499 +++++ arch/arm/plat-omap/fb.c | 9 arch/arm/plat-omap/include/mach/display.h | 458 ++++ arch/arm/plat-omap/include/mach/omapfb.h | 7 drivers/video/Kconfig | 1 drivers/video/Makefile | 1 drivers/video/omap/Kconfig | 5 drivers/video/omap2/Kconfig | 54 + drivers/video/omap2/Makefile | 5 drivers/video/omap2/omapfb-ioctl.c | 428 ++++ drivers/video/omap2/omapfb-main.c | 1247 ++++++++++++ drivers/video/omap2/omapfb-sysfs.c | 833 ++++++++ drivers/video/omap2/omapfb.h | 104 + drivers/video/omap2/panel-dvi.c | 121 + drivers/video/omap2/panel-sdp3430.c | 110 + 30 files changed, 12479 insertions(+), 27 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 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/dsi.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/rfbi.c create mode 100644 arch/arm/plat-omap/dss/sdi.c create mode 100644 arch/arm/plat-omap/dss/venc.c create mode 100644 arch/arm/plat-omap/include/mach/display.h create mode 100644 drivers/video/omap2/Kconfig create mode 100644 drivers/video/omap2/Makefile create mode 100644 drivers/video/omap2/omapfb-ioctl.c create mode 100644 drivers/video/omap2/omapfb-main.c create mode 100644 drivers/video/omap2/omapfb-sysfs.c create mode 100644 drivers/video/omap2/omapfb.h create mode 100644 drivers/video/omap2/panel-dvi.c create mode 100644 drivers/video/omap2/panel-sdp3430.c
Quoted 8 lines
--
Tomi Valkeinen--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Is [REVIEW PATCH 2/9] missing?
Regards,
Arun
Thanks,
Vaibhav Hiremath
Quoted 150 lines
-----Original Message-----
From: [email protected] [mailto:linux-omap- [email protected]] On Behalf Of Arun KS
Sent: Monday, November 24, 2008 11:57 AM
To: Tomi Valkeinen
Cc: [email protected]
Subject: Re: [REVIEW PATCH 0/9] DSS: Series descriptionQuoted 4 lines · Tomi Valkeinen
New Display Subsystem for OMAP2/3
---------------------------------This patch set implements new Display Subsystem (DSS) for OMAP2/3
processors.
Quoted 1 line
The DSS is still under work and these patches are for review. Note
that there
Quoted 3 lines
is also another new DSS implementation from TI.
The DSS has been tested on OMAP3 SDP board, Beagle Board and on
two unreleased
Quoted 1 line
boards with DSI and SDI displays. The DSS used to work on OMAP2
board also, but
Quoted 3 lines
it's been a while since I was able to test with OMAP2 board.
The first patch is a doc file that tries to explain a bit how the
drivers work.
Quoted 7 lines
The patch set is based on the current linux-omap tree.
You can find the patches also from a git tree at
http://www.bat.org/~tomba/git/linux-omap-dss.git/Note that you also need two patches from Mans Rullgard to make
things work. These
Quoted 2 lines
are needed to be able to reconfigure DSS functional clock.
http://git.mansr.com/?p=linux-omap;a=commit;h=e2de5e5578fbaa9b4b75074796da0608fc93e6ae
Quoted 1 line
omap;a=commit;h=2b7b958dc79e51127d7a4ecf88ce12dbc6c31426
Quoted 5 lines
Questions/problems
------------------Perhaps the biggest problems I have is the interface to user
space. OMAP
Quoted 1 line
hardware doesn't quite fit in to the framebuffer framework. The
problem is that
Quoted 1 line
a framebuffer can go to multiple overlays, and also the target
display, to
Quoted 1 line
which a framebuffer goes, can change. In addition, the
framebuffer size is
Quoted 1 line
used as overlay size, not display resolution. So a framebuffer !=
display.
Quoted 2 lines
I believe DRM modesetting could be of help here, at least
partially, but I
Quoted 3 lines
haven't tried that approach yet.
But DRM modesetting wouldn't solve all the problems. For example,
we still need
Quoted 1 line
to configure overlays and overlay managers, and they don't quite
belong to
Quoted 1 line
either the framebuffer side or the display side. Currently you
configure them
Quoted 1 line
via a hackish sysfs interface, but I've been wondering if a
/dev/omap-dssQuoted 3 lines
device with ioctls would be a better choice.
There's currently no V4L2 support, but I have been thinking about
that. I don't
Quoted 1 line
want to make any hardcoded configuration for those, because
sometimes you want
Quoted 1 line
to use framebuffer devices for video overlays. So what I'd like to
have is a
Quoted 1 line
way, compile time or run time, to configure which overlays go to
framebuffer
Quoted 16 lines
devices and which go to V4L2 devices.
---
Tomi Valkeinen (9):
DSS: support for OMAP3 SDP board
DSS: support for Beagle Board
DSS: Add generic DVI panel
DSS: OMAPFB: fb driver for new display subsystem
DSS: DSI support for OMAP2/3 DSS
DSS: TV-out support for OMAP2/3 DSS
DSS: RFBI support for OMAP2/3 DSS
DSS: New display subsystem driver for OMAP2/3
DSS: Documentation for OMAP2/3 display subsystemQuoted 11 lines
Documentation/arm/OMAP/DSS | 240 ++ arch/arm/mach-omap2/board-3430sdp.c | 234 ++ arch/arm/mach-omap2/board-omap3beagle.c | 121 + 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/dsi.c | 3027+++++++++++++++++++++++++++++
Quoted 45 lines
arch/arm/plat-omap/dss/dss.c | 547 +++++ arch/arm/plat-omap/dss/dss.h | 240 ++ arch/arm/plat-omap/dss/rfbi.c | 1234 ++++++++++++ arch/arm/plat-omap/dss/sdi.c | 154 + arch/arm/plat-omap/dss/venc.c | 499 +++++ arch/arm/plat-omap/fb.c | 9 arch/arm/plat-omap/include/mach/display.h | 458 ++++ arch/arm/plat-omap/include/mach/omapfb.h | 7 drivers/video/Kconfig | 1 drivers/video/Makefile | 1 drivers/video/omap/Kconfig | 5 drivers/video/omap2/Kconfig | 54 + drivers/video/omap2/Makefile | 5 drivers/video/omap2/omapfb-ioctl.c | 428 ++++ drivers/video/omap2/omapfb-main.c | 1247 ++++++++++++ drivers/video/omap2/omapfb-sysfs.c | 833 ++++++++ drivers/video/omap2/omapfb.h | 104 + drivers/video/omap2/panel-dvi.c | 121 + drivers/video/omap2/panel-sdp3430.c | 110 + 30 files changed, 12479 insertions(+), 27 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 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/dsi.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/rfbi.c create mode 100644 arch/arm/plat-omap/dss/sdi.c create mode 100644 arch/arm/plat-omap/dss/venc.c create mode 100644 arch/arm/plat-omap/include/mach/display.h create mode 100644 drivers/video/omap2/Kconfig create mode 100644 drivers/video/omap2/Makefile create mode 100644 drivers/video/omap2/omapfb-ioctl.c create mode 100644 drivers/video/omap2/omapfb-main.c create mode 100644 drivers/video/omap2/omapfb-sysfs.c create mode 100644 drivers/video/omap2/omapfb.h create mode 100644 drivers/video/omap2/panel-dvi.c create mode 100644 drivers/video/omap2/panel-sdp3430.c--
Tomi Valkeinen
Quoted 8 lines
Quoted 2 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
Quoted 3 lines
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.htmlIs [REVIEW PATCH 2/9] missing?
[Hiremath, Vaibhav] No, below is the link -
http://marc.info/?l=linux-fbdev-devel&m=122581507722475&w=2
Quoted 7 lines
Regards,
Arun
--
To unsubscribe from this list: send the line "unsubscribe linux- omap" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html