From: Tomi V. <val...@no...> - 2008-11-10 12:28:26
|
Hi, On Mon, 10 Nov 2008, ext Shah, Hardik wrote: >> > [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. 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 |
From: Shah, H. <har...@ti...> - 2008-11-10 12:04:13
|
> -----Original Message----- > From: Tomi Valkeinen [mailto:val...@no...] > Sent: Monday, November 10, 2008 5:01 PM > To: Shah, Hardik > Cc: Tomi Valkeinen; lin...@li...; linux- > om...@vg... > Subject: RE: [Linux-fbdev-devel] [REVIEW PATCH 0/9] DSS: Series description > > Hi, > > On Mon, 10 Nov 2008, ext Shah, Hardik wrote: > > >> > > [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. > > 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. > [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. > 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. > 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 > > Tomi |
From: Shah, H. <har...@ti...> - 2008-11-18 06:40:21
|
> -----Original Message----- > From: Tomi Valkeinen [mailto:tom...@no...] > Sent: Tuesday, November 04, 2008 9:40 PM > To: lin...@li... > Cc: lin...@vg... > Subject: [Linux-fbdev-devel] [REVIEW PATCH 0/9] 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. > [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 > -- > 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 > Lin...@li... > https://lists.sourceforge.net/lists/listinfo/linux-fbdev-devel |
From: Tomi V. <tom...@no...> - 2008-11-18 12:06:15
|
Hi, On Tue, 2008-11-18 at 12:10 +0530, ext Shah, Hardik wrote: > > > -----Original Message----- > > From: Tomi Valkeinen [mailto:tom...@no...] > > Sent: Tuesday, November 04, 2008 9:40 PM > > To: lin...@li... > > Cc: lin...@vg... > > Subject: [Linux-fbdev-devel] [REVIEW PATCH 0/9] DSS: Series description > > > > New Display Subsystem for OMAP2/3 > > --------------------------------- > > [snip] > > > [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. > 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. > > > Thanks and Regards, > Hardik Shah > Vaibhav Hiremath Tomi |
From: Tomi V. <tom...@no...> - 2009-01-12 12:31:01
|
You also need DSI PLL to generate pix clock for 1280x1024. Signed-off-by: Tomi Valkeinen <tom...@no...> --- drivers/video/omap2/Kconfig | 5 ++ drivers/video/omap2/Makefile | 2 + drivers/video/omap2/panel-generic.c | 97 +++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 0 deletions(-) create mode 100644 drivers/video/omap2/panel-generic.c diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig index 8be51a3..be00882 100644 --- a/drivers/video/omap2/Kconfig +++ b/drivers/video/omap2/Kconfig @@ -37,6 +37,11 @@ config FB_OMAP2_NUM_FBS menu "OMAP2/3 Display Device Drivers" depends on OMAP2_DSS +config PANEL_GENERIC + tristate "Generic Panel" + help + Generic panel driver. + Used for DVI output for Beagle and OMAP3 SDP. endmenu diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile index 51c2e00..f471a2b 100644 --- a/drivers/video/omap2/Makefile +++ b/drivers/video/omap2/Makefile @@ -1,2 +1,4 @@ obj-$(CONFIG_FB_OMAP2) += omapfb.o omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o + +obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o diff --git a/drivers/video/omap2/panel-generic.c b/drivers/video/omap2/panel-generic.c new file mode 100644 index 0000000..5c8fecd --- /dev/null +++ b/drivers/video/omap2/panel-generic.c @@ -0,0 +1,97 @@ +/* + * Generic panel support + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen <tom...@no...> + * + * 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/>. + */ + +#include <linux/module.h> +#include <linux/delay.h> + +#include <mach/display.h> + +static int generic_panel_init(struct omap_display *display) +{ + return 0; +} + +static int generic_panel_enable(struct omap_display *display) +{ + int r = 0; + + if (display->hw_config.panel_enable) + r = display->hw_config.panel_enable(display); + + return r; +} + +static void generic_panel_disable(struct omap_display *display) +{ + if (display->hw_config.panel_disable) + display->hw_config.panel_disable(display); +} + +static int generic_panel_suspend(struct omap_display *display) +{ + generic_panel_disable(display); + return 0; +} + +static int generic_panel_resume(struct omap_display *display) +{ + return generic_panel_enable(display); +} + +static struct omap_panel generic_panel = { + .owner = THIS_MODULE, + .name = "panel-generic", + .init = generic_panel_init, + .enable = generic_panel_enable, + .disable = generic_panel_disable, + .suspend = generic_panel_suspend, + .resume = generic_panel_resume, + + .timings = { + /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */ + .x_res = 640, + .y_res = 480, + .pixel_clock = 23500, + .hfp = 48, + .hsw = 32, + .hbp = 80, + .vfp = 3, + .vsw = 4, + .vbp = 7, + }, + + .bpp = 24, + .config = OMAP_DSS_LCD_TFT, +}; + + +static int __init generic_panel_drv_init(void) +{ + omap_dss_register_panel(&generic_panel); + return 0; +} + +static void __exit generic_panel_drv_exit(void) +{ + omap_dss_unregister_panel(&generic_panel); +} + +module_init(generic_panel_drv_init); +module_exit(generic_panel_drv_exit); +MODULE_LICENSE("GPL"); |
From: Tomi V. <tom...@no...> - 2009-01-12 12:31:12
|
Signed-off-by: Tomi Valkeinen <tom...@no...> --- arch/arm/plat-omap/dss/dsi.c | 3187 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 3187 insertions(+), 0 deletions(-) create mode 100644 arch/arm/plat-omap/dss/dsi.c diff --git a/arch/arm/plat-omap/dss/dsi.c b/arch/arm/plat-omap/dss/dsi.c new file mode 100644 index 0000000..e279571 --- /dev/null +++ b/arch/arm/plat-omap/dss/dsi.c @@ -0,0 +1,3187 @@ +/* + * linux/arch/arm/plat-omap/dss/dsi.c + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen <tom...@no...> + * + * 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 <mach/clock.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 }) + +#define DSI_SZ_REGS SZ_1K +/* 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 DSI_DSIPHY_CFG0 DSI_REG(0x200 + 0x0000) +#define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004) +#define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008) +#define DSI_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; + + unsigned long dsi1_pll_fclk; /* Hz */ + unsigned long dsi2_pll_fclk; /* Hz */ + unsigned long dsiphy; /* Hz */ + unsigned long ddr_clk; /* Hz */ + + u32 ctx[DSI_SZ_REGS / sizeof(u32)]; + + struct { + enum fifo_size fifo_size; + int dest_per; /* destination peripheral 0-3 */ + } vc[4]; + + struct mutex lock; + + unsigned pll_locked; + + struct completion bta_completion; + + spinlock_t update_lock; + int update_ongoing; + int update_syncers; + struct completion update_completion; + struct delayed_work framedone_work; + + enum omap_dss_update_mode user_update_mode; /* what the user wants */ + enum omap_dss_update_mode update_mode; /* current 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; + + unsigned long cache_req_pck; + unsigned long cache_clk_freq; + struct dsi_clock_info cache_cinfo; + +#ifdef MEASURE_PERF + ktime_t perf_setup_time; + ktime_t perf_start_time; + int perf_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); +} + + +#define SR(reg) \ + dsi.ctx[(DSI_##reg).idx / sizeof(u32)] = dsi_read_reg(DSI_##reg) +#define RR(reg) \ + dsi_write_reg(DSI_##reg, dsi.ctx[(DSI_##reg).idx / sizeof(u32)]) + +void dsi_save_context(void) +{ + SR(SYSCONFIG); + SR(IRQENABLE); + SR(CTRL); + SR(COMPLEXIO_CFG1); + SR(COMPLEXIO_IRQ_ENABLE); + SR(CLK_CTRL); + SR(TIMING1); + SR(TIMING2); + SR(VM_TIMING1); + SR(VM_TIMING2); + SR(VM_TIMING3); + SR(CLK_TIMING); + SR(TX_FIFO_VC_SIZE); + SR(RX_FIFO_VC_SIZE); + SR(COMPLEXIO_CFG2); + SR(VM_TIMING4); + SR(VM_TIMING5); + SR(VM_TIMING6); + SR(VM_TIMING7); + SR(STOPCLK_TIMING); + + SR(VC_CTRL(0)); + SR(VC_TE(0)); + SR(VC_IRQENABLE(0)); + + SR(VC_CTRL(1)); + SR(VC_TE(1)); + SR(VC_IRQENABLE(1)); + + SR(VC_CTRL(2)); + SR(VC_TE(2)); + SR(VC_IRQENABLE(2)); + + SR(VC_CTRL(3)); + SR(VC_TE(3)); + SR(VC_IRQENABLE(3)); + + SR(DSIPHY_CFG0); + SR(DSIPHY_CFG1); + SR(DSIPHY_CFG2); + SR(DSIPHY_CFG5); + + SR(PLL_CONTROL); + SR(PLL_CONFIGURATION1); + SR(PLL_CONFIGURATION2); +} + +void dsi_restore_context(void) +{ + RR(SYSCONFIG); + RR(IRQENABLE); + RR(CTRL); + RR(COMPLEXIO_CFG1); + RR(COMPLEXIO_IRQ_ENABLE); + RR(CLK_CTRL); + RR(TIMING1); + RR(TIMING2); + RR(VM_TIMING1); + RR(VM_TIMING2); + RR(VM_TIMING3); + RR(CLK_TIMING); + RR(TX_FIFO_VC_SIZE); + RR(RX_FIFO_VC_SIZE); + RR(COMPLEXIO_CFG2); + RR(VM_TIMING4); + RR(VM_TIMING5); + RR(VM_TIMING6); + RR(VM_TIMING7); + RR(STOPCLK_TIMING); + + RR(VC_CTRL(0)); + RR(VC_IRQENABLE(0)); + + RR(VC_CTRL(1)); + RR(VC_IRQENABLE(1)); + + RR(VC_CTRL(2)); + RR(VC_IRQENABLE(2)); + + RR(VC_CTRL(3)); + RR(VC_IRQENABLE(3)); + + RR(DSIPHY_CFG0); + RR(DSIPHY_CFG1); + RR(DSIPHY_CFG2); + RR(DSIPHY_CFG5); + + RR(PLL_CONTROL); + RR(PLL_CONFIGURATION1); + RR(PLL_CONFIGURATION2); +} + +#undef SR +#undef RR + +static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum, + int value) +{ + int t = 100000; + + while (REG_GET(idx, bitnum, bitnum) != value) { + if (--t == 0) + return !value; + } + + return value; +} + + +#ifdef MEASURE_PERF +static void perf_mark_setup(void) +{ + dsi.perf_setup_time = ktime_get(); +} + +static void perf_mark_start(void) +{ + dsi.perf_start_time = ktime_get(); +} + +static void perf_show(const char *name) +{ + ktime_t t, setup_time, trans_time; + u32 total_bytes; + u32 setup_us, trans_us, total_us; + const int numframes = 100; + static u32 s_trans_us, s_min_us = 0xffffffff, s_max_us; + + if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED) + return; + + t = ktime_get(); + + setup_time = ktime_sub(dsi.perf_start_time, dsi.perf_setup_time); + setup_us = (u32)ktime_to_us(setup_time); + if (setup_us == 0) + setup_us = 1; + + trans_time = ktime_sub(t, dsi.perf_start_time); + trans_us = (u32)ktime_to_us(trans_time); + if (trans_us == 0) + trans_us = 1; + + total_us = setup_us + trans_us; + + total_bytes = dsi.update_region.w * + dsi.update_region.h * + dsi.update_region.bytespp; + + if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) { + dsi.perf_measure_frames++; + + if (trans_us < s_min_us) + s_min_us = trans_us; + + if (trans_us > s_max_us) + s_max_us = trans_us; + + s_trans_us += trans_us; + + if (dsi.perf_measure_frames < numframes) + return; + + DSSINFO("%s update: %d frames in %u us (min/max %u/%u), " + "%u fps\n", + name, numframes, + s_trans_us, + s_min_us, + s_max_us, + 1000*1000 / (s_trans_us / numframes)); + + dsi.perf_measure_frames = 0; + s_trans_us = 0; + s_min_us = 0xffffffff; + s_max_us = 0; + } else { + DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, " + "%u kbytes/sec\n", + name, + setup_us, + trans_us, + total_us, + 1000*1000 / total_us, + total_bytes, + total_bytes * 1000 / total_us); + } +} +#else +#define perf_mark_setup() +#define perf_mark_start() +#define perf_show(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) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + else + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); +} + +/* source clock for DSI PLL. this could also be PCLKFREE */ +static inline void dsi_enable_pll_clock(int enable) +{ + if (enable) + dss_clk_enable(DSS_CLK_FCK2); + else + dss_clk_disable(DSS_CLK_FCK2); + + if (enable && dsi.pll_locked) { + if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) + DSSERR("cannot lock PLL when enabling clocks\n"); + } +} + +#ifdef DEBUG +static void _dsi_print_reset_status(void) +{ + u32 l; + + if (!dss_debug) + return; + + /* 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(DSI_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(DSI_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 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 = dss_clk_get_rate(DSS_CLK_FCK1); + } 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("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("Failed to set DSI PLL power mode to %d\n", + state); + return -ENODEV; + } + } + + return 0; +} + +int dsi_pll_calc_pck(int is_tft, unsigned long req_pck, + struct dsi_clock_info *cinfo) +{ + struct dsi_clock_info cur, best; + int min_fck_per_pck; + int match = 0; + + if (req_pck == dsi.cache_req_pck && + dsi.cache_cinfo.clkin == dss_clk_get_rate(DSS_CLK_FCK2)) { + DSSDBG("DSI clock info found from cache\n"); + *cinfo = dsi.cache_cinfo; + return 0; + } + + min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; + + if (min_fck_per_pck && + req_pck * min_fck_per_pck > DISPC_MAX_FCK) { + DSSERR("Requested pixel clock not possible with the current " + "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " + "the constraint off.\n"); + min_fck_per_pck = 0; + } + + DSSDBG("dsi_pll_calc\n"); + +retry: + memset(&best, 0, sizeof(best)); + + memset(&cur, 0, sizeof(cur)); + cur.clkin = dss_clk_get_rate(DSS_CLK_FCK2); + 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) { + 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 < req_pck) + break; + + if (cur.dispc_fck > DISPC_MAX_FCK) + continue; + + if (min_fck_per_pck && + cur.dispc_fck < + req_pck * min_fck_per_pck) + continue; + + match = 1; + + find_lck_pck_divs(is_tft, req_pck, + cur.dispc_fck, + &cur.lck_div, + &cur.pck_div); + + cur.lck = cur.dispc_fck / cur.lck_div; + cur.pck = cur.lck / cur.pck_div; + + if (abs(cur.pck - req_pck) < + abs(best.pck - req_pck)) { + best = cur; + + if (cur.pck == req_pck) + goto found; + } + } + } + } +found: + if (!match) { + if (min_fck_per_pck) { + DSSERR("Could not find suitable clock settings.\n" + "Turning FCK/PCK constraint off and" + "trying again.\n"); + min_fck_per_pck = 0; + goto retry; + } + + DSSERR("Could not find suitable clock settings.\n"); + + return -EINVAL; + } + + /* 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; + + if (cinfo) + *cinfo = best; + + dsi.cache_req_pck = req_pck; + dsi.cache_clk_freq = 0; + dsi.cache_cinfo = best; + + return 0; +} + +static int dsi_pll_calc_ddrfreq(unsigned long clk_freq, + struct dsi_clock_info *cinfo) +{ + struct dsi_clock_info cur, best; + const int use_dss2_fck = 1; + unsigned long datafreq; + + DSSDBG("dsi_pll_calc_ddrfreq\n"); + + if (clk_freq == dsi.cache_clk_freq && + dsi.cache_cinfo.clkin == dss_clk_get_rate(DSS_CLK_FCK2)) { + DSSDBG("DSI clock info found from cache\n"); + *cinfo = dsi.cache_cinfo; + return 0; + } + + datafreq = clk_freq * 4; + + memset(&best, 0, sizeof(best)); + + memset(&cur, 0, sizeof(cur)); + cur.use_dss2_fck = use_dss2_fck; + if (use_dss2_fck) { + cur.clkin = dss_clk_get_rate(DSS_CLK_FCK2); + 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; + + if (cinfo) + *cinfo = best; + + dsi.cache_clk_freq = clk_freq; + dsi.cache_req_pck = 0; + dsi.cache_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_enable_pll_clock(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("cannot lock PLL\n"); + r = -EIO; + goto err; + } + + dsi.pll_locked = 1; + + 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); + dsi_enable_pll_clock(0); + + return r; +} + +int dsi_pll_init(int enable_hsclk, int enable_hsdiv) +{ + int r = 0; + enum dsi_pll_power_state pwstate; + struct dispc_clock_info cinfo; + + DSSDBG("PLL init\n"); + + enable_clocks(1); + dsi_enable_pll_clock(1); + + /* configure dispc fck and pixel clock to something sane */ + r = dispc_calc_clock_div(1, 48 * 1000 * 1000, &cinfo); + if (r) + return r; + + r = dispc_set_clock_div(&cinfo); + if (r) { + DSSERR("Failed to set basic clocks\n"); + return r; + } + + /* 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("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); + dsi_enable_pll_clock(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_locked = 0; + dsi_pll_power(DSI_PLL_POWER_OFF); + 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("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(DSI_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(DSI_DSIPHY_CFG0, r); + + r = dsi_read_reg(DSI_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(DSI_DSIPHY_CFG1, r); + + r = dsi_read_reg(DSI_DSIPHY_CFG2); + r = FLD_MOD(r, tclk_prepare, 7, 0); + dsi_write_reg(DSI_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); + + /* 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(DSI_DSIPHY_CFG5); + + if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) { + DSSERR("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("ComplexIO not coming out of reset.\n"); + r = -ENODEV; + goto err; + } + + if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) { + DSSERR("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("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("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("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->ctrl->pixel_size) { + 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(DSI_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(DSI_DSIPHY_CFG2); + tclk_prepare = FLD_GET(r, 7, 0); + + /* min 8*UI */ + tclk_pre = 20; + /* 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->pixel_size != 24) + return -EINVAL; + + enable_clocks(1); + dsi_enable_pll_clock(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; + + perf_mark_start(); + + 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); + } + + perf_show("L4"); + + enable_clocks(0); + dsi_enable_pll_clock(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(int stop_update) +{ + unsigned long flags; + + spin_lock_irqsave(&dsi.update_lock, flags); + if (dsi.update_ongoing) { + long wait = msecs_to_jiffies(1000); + dsi.update_syncers++; + if (stop_update) + dsi.update_mode = OMAP_DSS_UPDATE_DISABLED; + 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.... [truncated message content] |
From: Tomi V. <tom...@no...> - 2009-01-12 12:32:09
|
Signed-off-by: Tomi Valkeinen <tom...@no...> --- arch/arm/configs/dss_omap3_beagle_defconfig | 1437 +++++++++++++++++++++++++++ arch/arm/mach-omap2/board-omap3beagle.c | 101 ++ 2 files changed, 1524 insertions(+), 14 deletions(-) create mode 100644 arch/arm/configs/dss_omap3_beagle_defconfig diff --git a/arch/arm/configs/dss_omap3_beagle_defconfig b/arch/arm/configs/dss_omap3_beagle_defconfig new file mode 100644 index 0000000..f39167f --- /dev/null +++ b/arch/arm/configs/dss_omap3_beagle_defconfig @@ -0,0 +1,1437 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.28-omap1 +# Wed Jan 7 15:22:00 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_CLASSIC_RCU=y +# CONFIG_FREEZER is not set + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +CONFIG_ARCH_OMAP=y +# CONFIG_ARCH_MSM is not set + +# +# TI OMAP Implementations +# +CONFIG_ARCH_OMAP_OTG=y +# CONFIG_ARCH_OMAP1 is not set +# CONFIG_ARCH_OMAP2 is not set +CONFIG_ARCH_OMAP3=y + +# +# OMAP Feature Selections +# +# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set +# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set +# CONFIG_OMAP_SMARTREFLEX is not set +# CONFIG_OMAP_RESET_CLOCKS is not set +CONFIG_OMAP_BOOT_TAG=y +CONFIG_OMAP_BOOT_REASON=y +# CONFIG_OMAP_COMPONENT_VERSION is not set +# CONFIG_OMAP_GPIO_SWITCH is not set +# CONFIG_OMAP_MUX is not set +# CONFIG_OMAP_MCBSP is not set +# CONFIG_OMAP_MMU_FWK is not set +# CONFIG_OMAP_MBOX_FWK is not set +# CONFIG_OMAP_MPU_TIMER is not set +CONFIG_OMAP_32K_TIMER=y +CONFIG_OMAP_32K_TIMER_HZ=128 +CONFIG_OMAP_DM_TIMER=y +# CONFIG_OMAP_LL_DEBUG_UART1 is not set +# CONFIG_OMAP_LL_DEBUG_UART2 is not set +CONFIG_OMAP_LL_DEBUG_UART3=y +CONFIG_OMAP2_DSS=m +CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y +# CONFIG_OMAP2_DSS_RFBI is not set +CONFIG_OMAP2_DSS_VENC=y +# CONFIG_OMAP2_DSS_SDI is not set +# CONFIG_OMAP2_DSS_DSI is not set +# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set +CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 +CONFIG_ARCH_OMAP34XX=y +CONFIG_ARCH_OMAP3430=y + +# +# OMAP Board Type +# +# CONFIG_MACH_OMAP_LDP is not set +# CONFIG_MACH_OMAP_3430SDP is not set +# CONFIG_MACH_OMAP3EVM is not set +CONFIG_MACH_OMAP3_BEAGLE=y +# CONFIG_MACH_OVERO is not set +# CONFIG_MACH_OMAP3_PANDORA is not set +CONFIG_OMAP_TICK_GPTIMER=12 + +# +# Boot options +# + +# +# Power management +# + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_V7=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_IFAR=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_HAS_TLS_REG=y +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PREEMPT is not set +CONFIG_HZ=128 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/home/user/buildroot ip=192.168.0.2:192.168.0.1:192.168.0.1:255.255.255.0:tgt:eth0:off rw console=ttyS2,115200n8" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_FREQ is not set +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +CONFIG_VFP=y +CONFIG_VFPv3=y +# CONFIG_NEON is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Power management options +# +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_SUSPEND is not set +# CONFIG_APM_EMULATION is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_OMAP2=y +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_NET_ETHERNET is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_OMAP=y +# CONFIG_I2C2_OMAP_BEAGLE is not set +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_AT24 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_TPS65010 is not set +# CONFIG_TWL4030_MADC is not set +# CONFIG_TWL4030_PWRBUTTON is not set +# CONFIG_TWL4030_POWEROFF is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_LP5521 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +CONFIG_GPIO_TWL4030=y + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +CONFIG_TWL4030_CORE=y +# CONFIG_TWL4030_POWER is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +CONFIG_DAB=y +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=m +CONFIG_FB_CFB_COPYAREA=m +CONFIG_FB_CFB_IMAGEBLIT=m +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=4 +CONFIG_FB_OMAP2=m +# CONFIG_FB_OMAP2_DEBUG is not set +# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set +CONFIG_FB_OMAP2_NUM_FBS=3 + +# +# OMAP2/3 Display Device Drivers +# +CONFIG_PANEL_GENERIC=m +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set +# CONFIG_LOGO is not set +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_SUSPEND=y +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_SOC=y + +# +# OMAP 343x high speed USB support +# +# CONFIG_USB_MUSB_HOST is not set +# CONFIG_USB_MUSB_PERIPHERAL is not set +CONFIG_USB_MUSB_OTG=y +CONFIG_USB_GADGET_MUSB_HDRC=y +CONFIG_USB_MUSB_HDRC_HCD=y +# CONFIG_MUSB_PIO_ONLY is not set +CONFIG_USB_INVENTRA_DMA=y +# CONFIG_USB_TI_CPPI_DMA is not set +# CONFIG_USB_MUSB_DEBUG is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; +# + +# +# see USB_STORAGE Help for more information +# +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_ZERO is not set +CONFIG_USB_ETH=y +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_ISP1301_OMAP is not set +CONFIG_TWL4030_USB=y +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +CONFIG_MMC_OMAP_HS=y +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +CONFIG_RTC_DRV_TWL4030=y +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_DMADEVICES is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set + +# +# CBUS support +# +# CONFIG_CBUS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +CONFIG_PRINT_QUOTA_WARNING=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +# CONFIG_SUNRPC_REGISTER_V4 is not set +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_HAVE_FUNCTION_TRACER=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index fe97bab..61f0fc9 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -43,6 +43,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" #include "mmc-twl4030.h" @@ -238,15 +240,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", @@ -300,13 +293,94 @@ 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-generic", + .u.dpi.data_lines = 24, + .panel_reset_gpio = 170, + .panel_enable = beagle_enable_dvi, + .panel_disable = beagle_disable_dvi, +}; + + +static int beagle_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 beagle_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 = beagle_panel_enable_tv, + .panel_disable = beagle_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"); + if (r < 0) + printk(KERN_ERR "Unable to get DVI reset GPIO\n"); +} + static struct omap_board_config_kernel omap3_beagle_config[] __initdata = { { OMAP_TAG_UART, &omap3_beagle_uart_config }, - { OMAP_TAG_LCD, &omap3_beagle_lcd_config }, }; static struct platform_device *omap3_beagle_devices[] __initdata = { - &omap3_beagle_lcd_device, + &beagle_dss_device, &leds_gpio, &keys_gpio, }; @@ -359,18 +433,17 @@ static void __init omap3_beagle_init(void) omap_serial_init(); 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); usb_musb_init(); usb_ehci_init(); omap3beagle_flash_init(); + beagle_display_init(); } static void __init omap3_beagle_map_io(void) { omap2_set_globals_343x(); + omap2_set_sdram_vram(1280 * 1024 * 4 * 3, 0); omap2_map_common_io(); } |
From: Tomi V. <tom...@no...> - 2009-01-12 12:32:56
|
Signed-off-by: Tomi Valkeinen <tom...@no...> --- arch/arm/plat-omap/dss/rfbi.c | 1262 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 1262 insertions(+), 0 deletions(-) create mode 100644 arch/arm/plat-omap/dss/rfbi.c diff --git a/arch/arm/plat-omap/dss/rfbi.c b/arch/arm/plat-omap/dss/rfbi.c new file mode 100644 index 0000000..b4b65e6 --- /dev/null +++ b/arch/arm/plat-omap/dss/rfbi.c @@ -0,0 +1,1262 @@ +/* + * linux/arch/arm/plat-omap/dss/rfbi.c + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen <tom...@no...> + * + * 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 <linux/hrtimer.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; + + 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 + unsigned perf_bytes; + ktime_t perf_setup_time; + ktime_t perf_start_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) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + else + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); +} + +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); + +#ifdef MEASURE_PERF +static void perf_mark_setup(void) +{ + rfbi.perf_setup_time = ktime_get(); +} + +static void perf_mark_start(void) +{ + rfbi.perf_start_time = ktime_get(); +} + +static void perf_show(const char *name) +{ + ktime_t t, setup_time, trans_time; + u32 total_bytes; + u32 setup_us, trans_us, total_us; + + t = ktime_get(); + + setup_time = ktime_sub(rfbi.perf_start_time, rfbi.perf_setup_time); + setup_us = (u32)ktime_to_us(setup_time); + if (setup_us == 0) + setup_us = 1; + + trans_time = ktime_sub(t, rfbi.perf_start_time); + trans_us = (u32)ktime_to_us(trans_time); + if (trans_us == 0) + trans_us = 1; + + total_us = setup_us + trans_us; + + total_bytes = rfbi.perf_bytes; + + DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, " + "%u kbytes/sec\n", + name, + setup_us, + trans_us, + total_us, + 1000*1000 / total_us, + total_bytes, + total_bytes * 1000 / total_us); +} +#else +#define perf_mark_setup() +#define perf_mark_start() +#define perf_show(x) +#endif + +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); + + 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 */ + + perf_mark_start(); + + rfbi_write_reg(RFBI_CONTROL, l); +} + +static void framedone_callback(void *data, u32 mask) +{ + void (*callback)(void *data); + + DSSDBG("FRAMEDONE\n"); + + perf_show("DISPC"); + + 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 = dss_clk_get_rate(DSS_CLK_FCK1) / 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; +} +EXPORT_SYMBOL(rfbi_configure); + +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; + + perf_mark_setup(); + + 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); + } + +#ifdef MEASURE_PERF + rfbi.perf_bytes = w * h * 2; /* XXX always 16bit */ +#endif + + display->ctrl->setup_update(display, x, y, w, h); + + if (display->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { + rfbi_transfer_area(w, h, NULL, NULL); + return 1; + } else { + struct omap_overlay *ovl; + void *addr; + int scr_width; + + ovl = &display->manager->overlays[0]; + scr_width = ovl->info.screen_width; + addr = ovl->info.vaddr; + + omap_rfbi_write_pixels(addr, scr_width, x, y, w, h); + + perf_show("L4"); + + 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_enable_clocks(1); + + msleep(10); + + rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_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 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); + + dispc_set_tft_data_lines(display->ctrl->pixel_size); + + rfbi_configure(display->hw_config.u.rfbi.channel, + display->ctrl->pixel_size, + display->hw_config.u.rfbi.data_lines); + + rfbi_set_timings(display->hw_config.u.rfbi.channel, + &display->ctrl->timings); + + + if (display->ctrl && display->ctrl->enable) { + r = display->ctrl->enable(display); + if (r) + goto err; + } + + if (display->panel && display->panel->enable) { + r = display->panel->enable(display); + if (r) + goto err; + } + + return 0; +err: + return -ENODEV; +} + +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->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; +} |
From: Tony L. <to...@at...> - 2009-01-12 13:19:10
|
* Tomi Valkeinen <tom...@no...> [090112 14:19]: Please add a patch description here so other people will have a clue what the patch is about. Might as well add something to the header too. The same goes for the other patches. Regards, Tony |
From: Tomi V. <tom...@no...> - 2009-01-12 12:33:09
|
Coded by Vaibhav Hiremath <hva...@ti...> Signed-off-by: Tomi Valkeinen <tom...@no...> --- arch/arm/mach-omap2/board-omap3evm.c | 203 +++++++++++++++++++++++++++++++++- 1 files changed, 196 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index e4e60e2..e7ec9e6 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -36,6 +36,7 @@ #include <mach/usb-ehci.h> #include <mach/common.h> #include <mach/mcspi.h> +#include <mach/display.h> #include "sdram-micron-mt46h32m32lf-6.h" #include "twl4030-generic-scripts.h" @@ -160,13 +161,201 @@ static int __init omap3_evm_i2c_init(void) return 0; } -static struct platform_device omap3_evm_lcd_device = { - .name = "omap3evm_lcd", - .id = -1, +#define LCD_PANEL_LR 2 +#define LCD_PANEL_UD 3 +#define LCD_PANEL_INI 152 +#define LCD_PANEL_ENABLE_GPIO 153 +#define LCD_PANEL_QVGA 154 +#define LCD_PANEL_RESB 155 + +#define ENABLE_VDAC_DEDICATED 0x03 +#define ENABLE_VDAC_DEV_GRP 0x20 +#define ENABLE_VPLL2_DEDICATED 0x05 +#define ENABLE_VPLL2_DEV_GRP 0xE0 + +#define TWL4030_GPIODATA_IN3 0x03 +#define TWL4030_GPIODATA_DIR3 0x06 +#define TWL4030_VPLL2_DEV_GRP 0x33 +#define TWL4030_VPLL2_DEDICATED 0x36 + +static int lcd_enabled; +static int dvi_enabled; + +static void __init omap3_evm_display_init(void) +{ + int r; + r = gpio_request(LCD_PANEL_LR, "lcd_panel_lr"); + if (r) { + printk(KERN_ERR "failed to get LCD_PANEL_LR\n"); + return; + } + r = gpio_request(LCD_PANEL_UD, "lcd_panel_ud"); + if (r) { + printk(KERN_ERR "failed to get LCD_PANEL_UD\n"); + goto err_1; + } + + r = gpio_request(LCD_PANEL_INI, "lcd_panel_ini"); + if (r) { + printk(KERN_ERR "failed to get LCD_PANEL_INI\n"); + goto err_2; + } + r = gpio_request(LCD_PANEL_RESB, "lcd_panel_resb"); + if (r) { + printk(KERN_ERR "failed to get LCD_PANEL_RESB\n"); + goto err_3; + } + r = gpio_request(LCD_PANEL_QVGA, "lcd_panel_qvga"); + if (r) { + printk(KERN_ERR "failed to get LCD_PANEL_QVGA\n"); + goto err_4; + } + + gpio_direction_output(LCD_PANEL_LR, 0); + gpio_direction_output(LCD_PANEL_UD, 0); + gpio_direction_output(LCD_PANEL_INI, 0); + gpio_direction_output(LCD_PANEL_RESB, 0); + gpio_direction_output(LCD_PANEL_QVGA, 0); + +#define TWL_LED_LEDEN 0x00 +#define TWL_PWMA_PWMAON 0x00 +#define TWL_PWMA_PWMAOFF 0x01 + + twl4030_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN); + twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON); + twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF); + + gpio_direction_output(LCD_PANEL_RESB, 1); + gpio_direction_output(LCD_PANEL_INI, 1); + gpio_direction_output(LCD_PANEL_QVGA, 0); + gpio_direction_output(LCD_PANEL_LR, 1); + gpio_direction_output(LCD_PANEL_UD, 1); + + return; + +err_4: + gpio_free(LCD_PANEL_RESB); +err_3: + gpio_free(LCD_PANEL_INI); +err_2: + gpio_free(LCD_PANEL_UD); +err_1: + gpio_free(LCD_PANEL_LR); + +} + +static int omap3_evm_panel_enable_lcd(struct omap_display *display) +{ + if (dvi_enabled) { + printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); + return -EINVAL; + } + if (omap_rev() > OMAP3430_REV_ES1_0) { + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + ENABLE_VPLL2_DEDICATED, TWL4030_VPLL2_DEDICATED); + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + ENABLE_VPLL2_DEV_GRP, TWL4030_VPLL2_DEV_GRP); + } + gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0); + lcd_enabled = 1; + return 0; +} + +static void omap3_evm_panel_disable_lcd(struct omap_display *display) +{ + if (omap_rev() > OMAP3430_REV_ES1_0) { + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0, + TWL4030_VPLL2_DEDICATED); + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0, + TWL4030_VPLL2_DEV_GRP); + } + gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 1); + lcd_enabled = 0; +} + +static struct omap_display_data omap3_evm_display_data = { + .type = OMAP_DISPLAY_TYPE_DPI, + .name = "lcd", + .panel_name = "sharp-ls037v7dw01", + .u.dpi.data_lines = 18, + .panel_enable = omap3_evm_panel_enable_lcd, + .panel_disable = omap3_evm_panel_disable_lcd, }; -static struct omap_lcd_config omap3_evm_lcd_config __initdata = { - .ctrl_name = "internal", +static int omap3_evm_panel_enable_tv(struct omap_display *display) +{ + 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 omap3_evm_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 omap3_evm_display_data_tv = { + .type = OMAP_DISPLAY_TYPE_VENC, + .name = "tv", + .u.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, + .panel_enable = omap3_evm_panel_enable_tv, + .panel_disable = omap3_evm_panel_disable_tv, +}; + + +static int omap3_evm_panel_enable_dvi(struct omap_display *display) +{ + if (lcd_enabled) { + printk(KERN_ERR "cannot enable DVI, LCD is enabled\n"); + return -EINVAL; + } + twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x80, + TWL4030_GPIODATA_IN3); + twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x80, + TWL4030_GPIODATA_DIR3); + dvi_enabled = 1; + + return 0; +} + +static void omap3_evm_panel_disable_dvi(struct omap_display *display) +{ + twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x00, + TWL4030_GPIODATA_IN3); + twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x00, + TWL4030_GPIODATA_DIR3); + dvi_enabled = 0; +} + + +static struct omap_display_data omap3_evm_display_data_dvi = { + .type = OMAP_DISPLAY_TYPE_DPI, + .name = "dvi", + .panel_name = "panel-generic", + .u.dpi.data_lines = 24, + .panel_enable = omap3_evm_panel_enable_dvi, + .panel_disable = omap3_evm_panel_disable_dvi, +}; + +static struct omap_dss_platform_data omap3_evm_dss_data = { + .num_displays = 3, + .displays = { + &omap3_evm_display_data, + &omap3_evm_display_data_dvi, + &omap3_evm_display_data_tv, + } +}; +static struct platform_device omap3_evm_dss_device = { + .name = "omap-dss", + .id = -1, + .dev = { + .platform_data = &omap3_evm_dss_data, + }, }; static void ads7846_dev_init(void) @@ -225,11 +414,10 @@ static void __init omap3_evm_init_irq(void) static struct omap_board_config_kernel omap3_evm_config[] __initdata = { { OMAP_TAG_UART, &omap3_evm_uart_config }, - { OMAP_TAG_LCD, &omap3_evm_lcd_config }, }; static struct platform_device *omap3_evm_devices[] __initdata = { - &omap3_evm_lcd_device, + &omap3_evm_dss_device, &omap3evm_smc911x_device, }; @@ -260,6 +448,7 @@ static void __init omap3_evm_init(void) usb_ehci_init(); omap3evm_flash_init(); ads7846_dev_init(); + omap3_evm_display_init(); } static void __init omap3_evm_map_io(void) |
From: Tomi V. <tom...@no...> - 2009-01-12 12:35:55
|
Signed-off-by: Tomi Valkeinen <tom...@no...> --- arch/arm/plat-omap/Kconfig | 2 arch/arm/plat-omap/Makefile | 2 arch/arm/plat-omap/dss/Kconfig | 71 + arch/arm/plat-omap/dss/Makefile | 6 arch/arm/plat-omap/dss/dispc.c | 2113 +++++++++++++++++++++++++++++ arch/arm/plat-omap/dss/display.c | 787 +++++++++++ arch/arm/plat-omap/dss/dpi.c | 344 +++++ arch/arm/plat-omap/dss/dss.c | 774 +++++++++++ arch/arm/plat-omap/dss/dss.h | 274 ++++ arch/arm/plat-omap/dss/sdi.c | 174 ++ arch/arm/plat-omap/include/mach/display.h | 462 ++++++ 11 files changed, 5009 insertions(+), 0 deletions(-) create mode 100644 arch/arm/plat-omap/dss/Kconfig create mode 100644 arch/arm/plat-omap/dss/Makefile create mode 100644 arch/arm/plat-omap/dss/dispc.c create mode 100644 arch/arm/plat-omap/dss/display.c create mode 100644 arch/arm/plat-omap/dss/dpi.c create mode 100644 arch/arm/plat-omap/dss/dss.c create mode 100644 arch/arm/plat-omap/dss/dss.h create mode 100644 arch/arm/plat-omap/dss/sdi.c create mode 100644 arch/arm/plat-omap/include/mach/display.h diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 6c9f092..2ae44e6 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -260,6 +260,8 @@ config OMAP_SERIAL_WAKE to data on the serial RX line. This allows you to wake the system from serial console. +source "arch/arm/plat-omap/dss/Kconfig" + endmenu endif diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index 1259846..2740497 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -29,3 +29,5 @@ obj-$(CONFIG_OMAP_MMU_FWK) += mmu.o # OMAP mailbox framework obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o +# OMAP2/3 Display Subsystem +obj-y += dss/ diff --git a/arch/arm/plat-omap/dss/Kconfig b/arch/arm/plat-omap/dss/Kconfig new file mode 100644 index 0000000..f0b1f1c --- /dev/null +++ b/arch/arm/plat-omap/dss/Kconfig @@ -0,0 +1,71 @@ +config OMAP2_DSS + tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)" + depends on ARCH_OMAP2 || ARCH_OMAP3 + help + OMAP2/3 Display Subsystem support. + +if OMAP2_DSS + +config OMAP2_DSS_DEBUG_SUPPORT + bool "Debug support" + default y + help + This enables debug messages. You need to enable printing + with 'debug' module parameter. + +config OMAP2_DSS_RFBI + bool "RFBI support" + default y + +config OMAP2_DSS_VENC + bool "VENC support" + default y + +if ARCH_OMAP3 + +config OMAP2_DSS_SDI + bool "SDI support" + default y + +config OMAP2_DSS_DSI + bool "DSI support" + default y + +endif + +config OMAP2_DSS_USE_DSI_PLL + bool "Use DSI PLL for PCLK (EXPERIMENTAL)" + default n + depends on OMAP2_DSS_DSI + help + Use DSI PLL to generate pixel clock. + Currently only for DPI output. + +config OMAP2_DSS_FAKE_VSYNC + bool "Fake VSYNC irq from manual update displays" + default n + help + If this is selected, DSI will fake a DISPC VSYNC interrupt + when DSI has sent a frame. This is only needed with DSI or + RFBI displays using manual mode, and you want VSYNC to time, + for example, animation. + +config OMAP2_DSS_MIN_FCK_PER_PCK + int "Minimum FCK/PCK ratio (for scaling)" + range 0 32 + default 0 + help + This can be used to adjust the minimum FCK/PCK ratio. + + With this you can make sure that DISPC FCK is at least + n x PCK. Video plane scaling requires higher FCK than + normally. + + If this is set to 0, there's no extra constraint on the + DISPC FCK. However, the FCK will at minimum be + 2xPCK (if active matrix) or 3xPCK (if passive matrix). + + Max FCK is 173MHz, so this doesn't work if your PCK + is very high. + +endif diff --git a/arch/arm/plat-omap/dss/Makefile b/arch/arm/plat-omap/dss/Makefile new file mode 100644 index 0000000..e98c6c1 --- /dev/null +++ b/arch/arm/plat-omap/dss/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_OMAP2_DSS) += omap-dss.o +omap-dss-y := dss.o display.o dispc.o dpi.o +omap-dss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o +omap-dss-$(CONFIG_OMAP2_DSS_VENC) += venc.o +omap-dss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o +omap-dss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o diff --git a/arch/arm/plat-omap/dss/dispc.c b/arch/arm/plat-omap/dss/dispc.c new file mode 100644 index 0000000..e695463 --- /dev/null +++ b/arch/arm/plat-omap/dss/dispc.c @@ -0,0 +1,2113 @@ +/* + * linux/arch/arm/plat-omap/dss/dispc.c + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen <tom...@no...> + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#define DSS_SUBSYS_NAME "DISPC" + +#include <linux/kernel.h> +#include <linux/dma-mapping.h> +#include <linux/vmalloc.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/jiffies.h> + +#include <mach/sram.h> +#include <mach/board.h> +#include <mach/clock.h> + +#include <mach/display.h> + +#include "dss.h" + +/* DISPC */ +#define DISPC_BASE 0x48050400 + +#define DISPC_SZ_REGS SZ_1K + +struct dispc_reg { u16 idx; }; + +#define DISPC_REG(idx) ((const struct dispc_reg) { idx }) + +/* DISPC common */ +#define DISPC_REVISION DISPC_REG(0x0000) +#define DISPC_SYSCONFIG DISPC_REG(0x0010) +#define DISPC_SYSSTATUS DISPC_REG(0x0014) +#define DISPC_IRQSTATUS DISPC_REG(0x0018) +#define DISPC_IRQENABLE DISPC_REG(0x001C) +#define DISPC_CONTROL DISPC_REG(0x0040) +#define DISPC_CONFIG DISPC_REG(0x0044) +#define DISPC_CAPABLE DISPC_REG(0x0048) +#define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C) +#define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050) +#define DISPC_TRANS_COLOR0 DISPC_REG(0x0054) +#define DISPC_TRANS_COLOR1 DISPC_REG(0x0058) +#define DISPC_LINE_STATUS DISPC_REG(0x005C) +#define DISPC_LINE_NUMBER DISPC_REG(0x0060) +#define DISPC_TIMING_H DISPC_REG(0x0064) +#define DISPC_TIMING_V DISPC_REG(0x0068) +#define DISPC_POL_FREQ DISPC_REG(0x006C) +#define DISPC_DIVISOR DISPC_REG(0x0070) +#define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074) +#define DISPC_SIZE_DIG DISPC_REG(0x0078) +#define DISPC_SIZE_LCD DISPC_REG(0x007C) + +/* DISPC GFX plane */ +#define DISPC_GFX_BA0 DISPC_REG(0x0080) +#define DISPC_GFX_BA1 DISPC_REG(0x0084) +#define DISPC_GFX_POSITION DISPC_REG(0x0088) +#define DISPC_GFX_SIZE DISPC_REG(0x008C) +#define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0) +#define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4) +#define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8) +#define DISPC_GFX_ROW_INC DISPC_REG(0x00AC) +#define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0) +#define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4) +#define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8) + +#define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4) +#define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8) +#define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC) + +#define DISPC_CPR_COEF_R DISPC_REG(0x0220) +#define DISPC_CPR_COEF_G DISPC_REG(0x0224) +#define DISPC_CPR_COEF_B DISPC_REG(0x0228) + +#define DISPC_GFX_PRELOAD DISPC_REG(0x022C) + +/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */ +#define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx) + +#define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000) +#define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004) +#define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008) +#define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C) +#define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010) +#define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014) +#define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018) +#define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C) +#define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020) +#define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024) +#define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028) +#define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C) +#define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030) + +/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ +#define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8) +/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ +#define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8) +/* coef index i = {0, 1, 2, 3, 4} */ +#define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4) +/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ +#define DISPC_VID_FIR_COEF_V(n, i) DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4) + +#define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04) + + +#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ + DISPC_IRQ_OCP_ERR | \ + DISPC_IRQ_VID1_FIFO_UNDERFLOW | \ + DISPC_IRQ_VID2_FIFO_UNDERFLOW | \ + DISPC_IRQ_SYNC_LOST | \ + DISPC_IRQ_SYNC_LOST_DIGIT) + +#define DISPC_MAX_NR_ISRS 8 + +static struct { + omap_dispc_isr_t isr; + void *arg; + u32 mask; +} registered_isr[DISPC_MAX_NR_ISRS]; + +#define REG_GET(idx, start, end) \ + FLD_GET(dispc_read_reg(idx), start, end) + +#define REG_FLD_MOD(idx, val, start, end) \ + dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end)) + +static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES, + DISPC_VID_ATTRIBUTES(0), + DISPC_VID_ATTRIBUTES(1) }; + +static struct { + void __iomem *base; + + struct clk *dpll4_m4_ck; + + spinlock_t irq_lock; + + unsigned long cache_req_pck; + unsigned long cache_prate; + struct dispc_clock_info cache_cinfo; + + u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; +} dispc; + +static inline void dispc_write_reg(const struct dispc_reg idx, u32 val) +{ + __raw_writel(val, dispc.base + idx.idx); +} + +static inline u32 dispc_read_reg(const struct dispc_reg idx) +{ + return __raw_readl(dispc.base + idx.idx); +} + +#define SR(reg) \ + dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg) +#define RR(reg) \ + dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)]) + +void dispc_save_context(void) +{ + if (cpu_is_omap24xx()) + return; + + SR(SYSCONFIG); + SR(IRQENABLE); + SR(CONTROL); + SR(CONFIG); + SR(DEFAULT_COLOR0); + SR(DEFAULT_COLOR1); + SR(TRANS_COLOR0); + SR(TRANS_COLOR1); + SR(LINE_NUMBER); + SR(TIMING_H); + SR(TIMING_V); + SR(POL_FREQ); + SR(DIVISOR); + SR(GLOBAL_ALPHA); + SR(SIZE_DIG); + SR(SIZE_LCD); + + SR(GFX_BA0); + SR(GFX_BA1); + SR(GFX_POSITION); + SR(GFX_SIZE); + SR(GFX_ATTRIBUTES); + SR(GFX_FIFO_THRESHOLD); + SR(GFX_ROW_INC); + SR(GFX_PIXEL_INC); + SR(GFX_WINDOW_SKIP); + SR(GFX_TABLE_BA); + + SR(DATA_CYCLE1); + SR(DATA_CYCLE2); + SR(DATA_CYCLE3); + + SR(CPR_COEF_R); + SR(CPR_COEF_G); + SR(CPR_COEF_B); + + SR(GFX_PRELOAD); + + /* VID1 */ + SR(VID_BA0(0)); + SR(VID_BA1(0)); + SR(VID_POSITION(0)); + SR(VID_SIZE(0)); + SR(VID_ATTRIBUTES(0)); + SR(VID_FIFO_THRESHOLD(0)); + SR(VID_ROW_INC(0)); + SR(VID_PIXEL_INC(0)); + SR(VID_FIR(0)); + SR(VID_PICTURE_SIZE(0)); + SR(VID_ACCU0(0)); + SR(VID_ACCU1(0)); + + SR(VID_FIR_COEF_H(0, 0)); + SR(VID_FIR_COEF_H(0, 1)); + SR(VID_FIR_COEF_H(0, 2)); + SR(VID_FIR_COEF_H(0, 3)); + SR(VID_FIR_COEF_H(0, 4)); + SR(VID_FIR_COEF_H(0, 5)); + SR(VID_FIR_COEF_H(0, 6)); + SR(VID_FIR_COEF_H(0, 7)); + + SR(VID_FIR_COEF_HV(0, 0)); + SR(VID_FIR_COEF_HV(0, 1)); + SR(VID_FIR_COEF_HV(0, 2)); + SR(VID_FIR_COEF_HV(0, 3)); + SR(VID_FIR_COEF_HV(0, 4)); + SR(VID_FIR_COEF_HV(0, 5)); + SR(VID_FIR_COEF_HV(0, 6)); + SR(VID_FIR_COEF_HV(0, 7)); + + SR(VID_CONV_COEF(0, 0)); + SR(VID_CONV_COEF(0, 1)); + SR(VID_CONV_COEF(0, 2)); + SR(VID_CONV_COEF(0, 3)); + SR(VID_CONV_COEF(0, 4)); + + SR(VID_FIR_COEF_V(0, 0)); + SR(VID_FIR_COEF_V(0, 1)); + SR(VID_FIR_COEF_V(0, 2)); + SR(VID_FIR_COEF_V(0, 3)); + SR(VID_FIR_COEF_V(0, 4)); + SR(VID_FIR_COEF_V(0, 5)); + SR(VID_FIR_COEF_V(0, 6)); + SR(VID_FIR_COEF_V(0, 7)); + + SR(VID_PRELOAD(0)); + + /* VID2 */ + SR(VID_BA0(1)); + SR(VID_BA1(1)); + SR(VID_POSITION(1)); + SR(VID_SIZE(1)); + SR(VID_ATTRIBUTES(1)); + SR(VID_FIFO_THRESHOLD(1)); + SR(VID_ROW_INC(1)); + SR(VID_PIXEL_INC(1)); + SR(VID_FIR(1)); + SR(VID_PICTURE_SIZE(1)); + SR(VID_ACCU0(1)); + SR(VID_ACCU1(1)); + + SR(VID_FIR_COEF_H(1, 0)); + SR(VID_FIR_COEF_H(1, 1)); + SR(VID_FIR_COEF_H(1, 2)); + SR(VID_FIR_COEF_H(1, 3)); + SR(VID_FIR_COEF_H(1, 4)); + SR(VID_FIR_COEF_H(1, 5)); + SR(VID_FIR_COEF_H(1, 6)); + SR(VID_FIR_COEF_H(1, 7)); + + SR(VID_FIR_COEF_HV(1, 0)); + SR(VID_FIR_COEF_HV(1, 1)); + SR(VID_FIR_COEF_HV(1, 2)); + SR(VID_FIR_COEF_HV(1, 3)); + SR(VID_FIR_COEF_HV(1, 4)); + SR(VID_FIR_COEF_HV(1, 5)); + SR(VID_FIR_COEF_HV(1, 6)); + SR(VID_FIR_COEF_HV(1, 7)); + + SR(VID_CONV_COEF(1, 0)); + SR(VID_CONV_COEF(1, 1)); + SR(VID_CONV_COEF(1, 2)); + SR(VID_CONV_COEF(1, 3)); + SR(VID_CONV_COEF(1, 4)); + + SR(VID_FIR_COEF_V(1, 0)); + SR(VID_FIR_COEF_V(1, 1)); + SR(VID_FIR_COEF_V(1, 2)); + SR(VID_FIR_COEF_V(1, 3)); + SR(VID_FIR_COEF_V(1, 4)); + SR(VID_FIR_COEF_V(1, 5)); + SR(VID_FIR_COEF_V(1, 6)); + SR(VID_FIR_COEF_V(1, 7)); + + SR(VID_PRELOAD(1)); +} + +void dispc_restore_context(void) +{ + RR(SYSCONFIG); + RR(IRQENABLE); + /*RR(CONTROL);*/ + RR(CONFIG); + RR(DEFAULT_COLOR0); + RR(DEFAULT_COLOR1); + RR(TRANS_COLOR0); + RR(TRANS_COLOR1); + RR(LINE_NUMBER); + RR(TIMING_H); + RR(TIMING_V); + RR(POL_FREQ); + RR(DIVISOR); + RR(GLOBAL_ALPHA); + RR(SIZE_DIG); + RR(SIZE_LCD); + + RR(GFX_BA0); + RR(GFX_BA1); + RR(GFX_POSITION); + RR(GFX_SIZE); + RR(GFX_ATTRIBUTES); + RR(GFX_FIFO_THRESHOLD); + RR(GFX_ROW_INC); + RR(GFX_PIXEL_INC); + RR(GFX_WINDOW_SKIP); + RR(GFX_TABLE_BA); + + RR(DATA_CYCLE1); + RR(DATA_CYCLE2); + RR(DATA_CYCLE3); + + RR(CPR_COEF_R); + RR(CPR_COEF_G); + RR(CPR_COEF_B); + + RR(GFX_PRELOAD); + + /* VID1 */ + RR(VID_BA0(0)); + RR(VID_BA1(0)); + RR(VID_POSITION(0)); + RR(VID_SIZE(0)); + RR(VID_ATTRIBUTES(0)); + RR(VID_FIFO_THRESHOLD(0)); + RR(VID_ROW_INC(0)); + RR(VID_PIXEL_INC(0)); + RR(VID_FIR(0)); + RR(VID_PICTURE_SIZE(0)); + RR(VID_ACCU0(0)); + RR(VID_ACCU1(0)); + + RR(VID_FIR_COEF_H(0, 0)); + RR(VID_FIR_COEF_H(0, 1)); + RR(VID_FIR_COEF_H(0, 2)); + RR(VID_FIR_COEF_H(0, 3)); + RR(VID_FIR_COEF_H(0, 4)); + RR(VID_FIR_COEF_H(0, 5)); + RR(VID_FIR_COEF_H(0, 6)); + RR(VID_FIR_COEF_H(0, 7)); + + RR(VID_FIR_COEF_HV(0, 0)); + RR(VID_FIR_COEF_HV(0, 1)); + RR(VID_FIR_COEF_HV(0, 2)); + RR(VID_FIR_COEF_HV(0, 3)); + RR(VID_FIR_COEF_HV(0, 4)); + RR(VID_FIR_COEF_HV(0, 5)); + RR(VID_FIR_COEF_HV(0, 6)); + RR(VID_FIR_COEF_HV(0, 7)); + + RR(VID_CONV_COEF(0, 0)); + RR(VID_CONV_COEF(0, 1)); + RR(VID_CONV_COEF(0, 2)); + RR(VID_CONV_COEF(0, 3)); + RR(VID_CONV_COEF(0, 4)); + + RR(VID_FIR_COEF_V(0, 0)); + RR(VID_FIR_COEF_V(0, 1)); + RR(VID_FIR_COEF_V(0, 2)); + RR(VID_FIR_COEF_V(0, 3)); + RR(VID_FIR_COEF_V(0, 4)); + RR(VID_FIR_COEF_V(0, 5)); + RR(VID_FIR_COEF_V(0, 6)); + RR(VID_FIR_COEF_V(0, 7)); + + RR(VID_PRELOAD(0)); + + /* VID2 */ + RR(VID_BA0(1)); + RR(VID_BA1(1)); + RR(VID_POSITION(1)); + RR(VID_SIZE(1)); + RR(VID_ATTRIBUTES(1)); + RR(VID_FIFO_THRESHOLD(1)); + RR(VID_ROW_INC(1)); + RR(VID_PIXEL_INC(1)); + RR(VID_FIR(1)); + RR(VID_PICTURE_SIZE(1)); + RR(VID_ACCU0(1)); + RR(VID_ACCU1(1)); + + RR(VID_FIR_COEF_H(1, 0)); + RR(VID_FIR_COEF_H(1, 1)); + RR(VID_FIR_COEF_H(1, 2)); + RR(VID_FIR_COEF_H(1, 3)); + RR(VID_FIR_COEF_H(1, 4)); + RR(VID_FIR_COEF_H(1, 5)); + RR(VID_FIR_COEF_H(1, 6)); + RR(VID_FIR_COEF_H(1, 7)); + + RR(VID_FIR_COEF_HV(1, 0)); + RR(VID_FIR_COEF_HV(1, 1)); + RR(VID_FIR_COEF_HV(1, 2)); + RR(VID_FIR_COEF_HV(1, 3)); + RR(VID_FIR_COEF_HV(1, 4)); + RR(VID_FIR_COEF_HV(1, 5)); + RR(VID_FIR_COEF_HV(1, 6)); + RR(VID_FIR_COEF_HV(1, 7)); + + RR(VID_CONV_COEF(1, 0)); + RR(VID_CONV_COEF(1, 1)); + RR(VID_CONV_COEF(1, 2)); + RR(VID_CONV_COEF(1, 3)); + RR(VID_CONV_COEF(1, 4)); + + RR(VID_FIR_COEF_V(1, 0)); + RR(VID_FIR_COEF_V(1, 1)); + RR(VID_FIR_COEF_V(1, 2)); + RR(VID_FIR_COEF_V(1, 3)); + RR(VID_FIR_COEF_V(1, 4)); + RR(VID_FIR_COEF_V(1, 5)); + RR(VID_FIR_COEF_V(1, 6)); + RR(VID_FIR_COEF_V(1, 7)); + + RR(VID_PRELOAD(1)); + + /* enable last, because LCD & DIGIT enable are here */ + RR(CONTROL); +} + +#undef SR +#undef RR + +static inline void enable_clocks(int enable) +{ + if (enable) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + else + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); +} + +void dispc_go(enum omap_channel channel) +{ + int bit; + unsigned long tmo; + + enable_clocks(1); + + if (channel == OMAP_DSS_CHANNEL_LCD) + bit = 0; /* LCDENABLE */ + else + bit = 1; /* DIGITALENABLE */ + + /* if the channel is not enabled, we don't need GO */ + if (REG_GET(DISPC_CONTROL, bit, bit) == 0) + goto end; + + if (channel == OMAP_DSS_CHANNEL_LCD) + bit = 5; /* GOLCD */ + else + bit = 6; /* GODIGIT */ + + tmo = jiffies + msecs_to_jiffies(200); + while (REG_GET(DISPC_CONTROL, bit, bit) == 1) { + if (time_after(jiffies, tmo)) { + DSSERR("timeout waiting GO flag\n"); + goto end; + } + cpu_relax(); + } + + DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT"); + + REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); +end: + enable_clocks(0); +} + +static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) +{ + BUG_ON(plane == OMAP_DSS_GFX); + + dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value); +} + +static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value) +{ + BUG_ON(plane == OMAP_DSS_GFX); + + dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value); +} + + +static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, + int vscaleup) +{ + /* Coefficients for horizontal up-sampling */ + const u32 coef_hup[8] = { + 0x00800000, + 0x0D7CF800, + 0x1E70F5FF, + 0x335FF5FE, + 0xF74949F7, + 0xF55F33FB, + 0xF5701EFE, + 0xF87C0DFF, + }; + + /* Coefficients for horizontal down-sampling */ + const u32 coef_hdown[8] = { + 0x24382400, + 0x28371FFE, + 0x2C361BFB, + 0x303516F9, + 0x11343311, + 0x1635300C, + 0x1B362C08, + 0x1F372804, + }; + + /* Coefficients for horizontal and vertical up-sampling */ + const u32 coef_hvup[8] = { + 0x00800000, + 0x037B02FF, + 0x0C6F05FE, + 0x205907FB, + 0x00404000, + 0x075920FE, + 0x056F0CFF, + 0x027B0300, + }; + + /* Coefficients for horizontal and vertical down-sampling */ + const u32 coef_hvdown[8] = { + 0x24382400, + 0x28391F04, + 0x2D381B08, + 0x3237170C, + 0x123737F7, + 0x173732F9, + 0x1B382DFB, + 0x1F3928FE, + }; + + const u32 *h_coef; + const u32 *hv_coef; + const u32 *hv_coef_mod; + int i; + + if (hscaleup) + h_coef = coef_hup; + else + h_coef = coef_hdown; + + if (vscaleup) { + hv_coef = coef_hvup; + + if (hscaleup) + hv_coef_mod = NULL; + else + hv_coef_mod = coef_hvdown; + } else { + hv_coef = coef_hvdown; + + if (hscaleup) + hv_coef_mod = coef_hvup; + else + hv_coef_mod = NULL; + } + + for (i = 0; i < 8; i++) { + u32 h, hv; + + h = h_coef[i]; + + hv = hv_coef[i]; + + if (hv_coef_mod) { + hv &= 0xffffff00; + hv |= (hv_coef_mod[i] & 0xff); + } + + _dispc_write_firh_reg(plane, i, h); + _dispc_write_firhv_reg(plane, i, hv); + } +} + +static void _dispc_setup_color_conv_coef(void) +{ + const struct color_conv_coef { + int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; + int full_range; + } ctbl_bt601_5 = { + 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, + }; + + const struct color_conv_coef *ct; + +#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0)) + + ct = &ctbl_bt601_5; + + dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry)); + dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb)); + dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr)); + dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by)); + dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb)); + + dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry)); + dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb)); + dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr)); + dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by)); + dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb)); + +#undef CVAL + + REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11); + REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11); +} + + +static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr) +{ + const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0, + DISPC_VID_BA0(0), + DISPC_VID_BA0(1) }; + + dispc_write_reg(ba0_reg[plane], paddr); +} + +static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr) +{ + const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1, + DISPC_VID_BA1(0), + DISPC_VID_BA1(1) }; + + dispc_write_reg(ba1_reg[plane], paddr); +} + +static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y) +{ + const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION, + DISPC_VID_POSITION(0), + DISPC_VID_POSITION(1) }; + + u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); + dispc_write_reg(pos_reg[plane], val); +} + +static void _dispc_set_pic_size(enum omap_plane plane, int width, int height) +{ + const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE, + DISPC_VID_PICTURE_SIZE(0), + DISPC_VID_PICTURE_SIZE(1) }; + u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); + dispc_write_reg(siz_reg[plane], val); +} + +static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) +{ + u32 val; + const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0), + DISPC_VID_SIZE(1) }; + + BUG_ON(plane == OMAP_DSS_GFX); + + val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); + dispc_write_reg(vsi_reg[plane-1], val); +} + +static void _dispc_set_row_inc(enum omap_plane plane, int inc) +{ + const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC, + DISPC_VID_ROW_INC(0), + DISPC_VID_ROW_INC(1) }; + + dispc_write_reg(ri_reg[plane], inc); +} + +static void _dispc_set_color_mode(enum omap_plane plane, + enum omap_color_mode color_mode) +{ + u32 m = 0; + + switch (color_mode) { + case OMAP_DSS_COLOR_CLUT1: + m = 0x0; break; + case OMAP_DSS_COLOR_CLUT2: + m = 0x1; break; + case OMAP_DSS_COLOR_CLUT4: + m = 0x2; break; + case OMAP_DSS_COLOR_CLUT8: + m = 0x3; break; + case OMAP_DSS_COLOR_RGB12U: + m = 0x4; break; + case OMAP_DSS_COLOR_ARGB16: + m = 0x5; break; + case OMAP_DSS_COLOR_RGB16: + m = 0x6; break; + case OMAP_DSS_COLOR_RGB24U: + m = 0x8; break; + case OMAP_DSS_COLOR_RGB24P: + m = 0x9; break; + case OMAP_DSS_COLOR_YUV2: + m = 0xa; break; + case OMAP_DSS_COLOR_UYVY: + m = 0xb; break; + case OMAP_DSS_COLOR_ARGB32: + m = 0xc; break; + case OMAP_DSS_COLOR_RGBA32: + m = 0xd; break; + case OMAP_DSS_COLOR_RGBX32: + m = 0xe; break; + default: + BUG(); break; + } + + REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1); +} + +static void _dispc_set_channel_out(enum omap_plane plane, + enum omap_channel channel) +{ + int shift; + u32 val; + + switch (plane) { + case OMAP_DSS_GFX: + shift = 8; + break; + case OMAP_DSS_VIDEO1: + case OMAP_DSS_VIDEO2: + shift = 16; + break; + default: + BUG(); + return; + } + + val = dispc_read_reg(dispc_reg_att[plane]); + val = FLD_MOD(val, channel, shift, shift); + dispc_write_reg(dispc_reg_att[plane], val); +} + +void dispc_set_burst_size(enum omap_plane plane, + enum omap_burst_size burst_size) +{ + int shift; + u32 val; + + enable_clocks(1); + + switch (plane) { + case OMAP_DSS_GFX: + shift = 6; + break; + case OMAP_DSS_VIDEO1: + case OMAP_DSS_VIDEO2: + shift = 14; + break; + default: + BUG(); + return; + } + + val = dispc_read_reg(dispc_reg_att[plane]); + val = FLD_MOD(val, burst_size, shift+1, shift); + dispc_write_reg(dispc_reg_att[plane], val); + + enable_clocks(0); +} + +static void _dispc_set_vid_color_conv(enum omap_plane plane, int enable) +{ + u32 val; + + BUG_ON(plane == OMAP_DSS_GFX); + + val = dispc_read_reg(dispc_reg_att[plane]); + val = FLD_MOD(val, enable, 9, 9); + dispc_write_reg(dispc_reg_att[plane], val); +} + +void dispc_set_lcd_size(int width, int height) +{ + u32 val; + BUG_ON((width > (1 << 11)) || (height > (1 << 11))); + val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); + enable_clocks(1); + dispc_write_reg(DISPC_SIZE_LCD, val); + enable_clocks(0); +} + +void dispc_set_digit_size(int width, int height) +{ + u32 val; + BUG_ON((width > (1 << 11)) || (height > (1 << 11))); + val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); + enable_clocks(1); + dispc_write_reg(DISPC_SIZE_DIG, val); + enable_clocks(0); +} + +u32 dispc_get_plane_fifo_size(enum omap_plane plane) +{ + const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS, + DISPC_VID_FIFO_SIZE_STATUS(0), + DISPC_VID_FIFO_SIZE_STATUS(1) }; + u32 size; + + enable_clocks(1); + + if (cpu_is_omap24xx()) + size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0); + else if (cpu_is_omap34xx()) + size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0); + else + BUG(); + + enable_clocks(0); + + return size; +} + +void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high) +{ + const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD, + DISPC_VID_FIFO_THRESHOLD(0), + DISPC_VID_FIFO_THRESHOLD(1) }; + const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS, + DISPC_VID_FIFO_SIZE_STATUS(0), + DISPC_VID_FIFO_SIZE_STATUS(1) }; + u32 size; + + enable_clocks(1); + + if (cpu_is_omap24xx()) + size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0); + else if (cpu_is_omap34xx()) + size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0); + else + BUG(); + + BUG_ON(low > size || high > size); + + DSSDBG("fifo(%d) size %d, low/high old %u/%u, new %u/%u\n", + plane, size, + REG_GET(ftrs_reg[plane], 11, 0), + REG_GET(ftrs_reg[plane], 27, 16), + low, high); + + if (cpu_is_omap24xx()) + dispc_write_reg(ftrs_reg[plane], + FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0)); + else + dispc_write_reg(ftrs_reg[plane], + FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0)); + + enable_clocks(0); +} + +static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc) +{ + u32 val; + const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0), + DISPC_VID_FIR(1) }; + + BUG_ON(plane == OMAP_DSS_GFX); + + val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0); + dispc_write_reg(fir_reg[plane-1], val); +} + +static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) +{ + u32 val; + const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0), + DISPC_VID_ACCU0(1) }; + + BUG_ON(plane == OMAP_DSS_GFX); + + val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); + dispc_write_reg(ac0_reg[plane-1], val); +} + +static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) +{ + u32 val; + const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0), + DISPC_VID_ACCU1(1) }; + + BUG_ON(plane == OMAP_DSS_GFX); + + val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); + dispc_write_reg(ac1_reg[plane-1], val); +} + + +static void _dispc_set_scaling(enum omap_plane plane, + int orig_width, int orig_height, + int out_width, int out_height, + int ilace) +{ + int fir_hinc; + int fir_vinc; + int hscaleup, vscaleup; + int fieldmode = 0; + int accu0 = 0; + int accu1 = 0; + u32 l; + + BUG_ON(plane == OMAP_DSS_GFX); + + hscaleup = orig_width <= out_width; + vscaleup = orig_height <= out_height; + + _dispc_set_scale_coef(plane, hscaleup, vscaleup); + + if (!orig_width || orig_width == out_width) + fir_hinc = 0; + else + fir_hinc = 1024 * orig_width / out_width; + + if (!orig_height || orig_height == out_height) + fir_vinc = 0; + else + fir_vinc = 1024 * orig_height / out_height; + + _dispc_set_fir(plane, fir_hinc, fir_vinc); + + l = dispc_read_reg(dispc_reg_att[plane]); + l &= ~(0x0f << 5); + + l |= fir_hinc ? (1 << 5) : 0; + l |= fir_vinc ? (1 << 6) : 0; + + l |= hscaleup ? 0 : (1 << 7); + l |= vscaleup ? 0 : (1 << 8); + + dispc_write_reg(dispc_reg_att[plane], l); + + if (ilace) { + if (fieldmode) { + accu0 = fir_vinc / 2; + accu1 = 0; + } else { + accu0 = 0; + accu1 = fir_vinc / 2; + if (accu1 >= 1024/2) { + accu0 = 1024/2; + accu1 -= accu0; + } + } + } + + _dispc_set_vid_accu0(plane, 0, accu0); + _dispc_set_vid_accu1(plane, 0, accu1); +} + +static int _dispc_setup_plane(enum omap_plane plane, + enum omap_channel channel_out, + u32 paddr, int screen_width, + int pos_x, int pos_y, + int width, int height, + int out_width, int out_height, + enum omap_color_mode color_mode, + int ilace) +{ + int fieldmode = 0; + int bpp; + int cconv; + int scaling = 0; + + if (plane == OMAP_DSS_GFX) { + if (width != out_width || height != out_height) + return -EINVAL; + } else { + /* video plane */ + if (width != out_width || height != out_height) + scaling = 1; + + if (out_width < width/2 || + out_width > width*8) + return -EINVAL; + + if (out_height < height/2 || + out_height > height*8) + return -EINVAL; + } + + + switch (color_mode) { + case OMAP_DSS_COLOR_RGB16: + bpp = 16; + cconv = 0; + break; + + case OMAP_DSS_COLOR_RGB24P: + bpp = 24; + cconv = 0; + break; + + case OMAP_DSS_COLOR_RGB24U: + bpp = 32; + cconv = 0; + break; + + case OMAP_DSS_COLOR_YUV2: + case OMAP_DSS_COLOR_UYVY: + BUG_ON(plane == OMAP_DSS_GFX); + bpp = 16; + cconv = 1; + break; + + default: + BUG(); + return 1; + } + + if (ilace) { + if (height == out_height || height > out_height) + fieldmode = 1; + } + + if (fieldmode) + height /= 2; + + if (ilace) + out_height /= 2; + + if (plane != OMAP_DSS_GFX) + _dispc_set_scaling(plane, width, height, + out_width, out_height, + ilace); + + /* attributes */ + _dispc_set_channel_out(plane, channel_out); + _dispc_set_color_mode(plane, color_mode); + if (plane != OMAP_DSS_GFX) + _dispc_set_vid_color_conv(plane, cconv); + + /* */ + + _dispc_set_plane_ba0(plane, paddr); + + if (fieldmode) + _dispc_set_plane_ba1(plane, paddr + screen_width * bpp/8); + else + _dispc_set_plane_ba1(plane, paddr); + + + _dispc_set_plane_pos(plane, pos_x, pos_y); + + _dispc_set_pic_size(plane, width, height); + + if (plane != OMAP_DSS_GFX) + _dispc_set_vid_size(plane, out_width, out_height); + + _dispc_set_row_inc(plane, + (screen_width - width) * bpp / 8 + + (fieldmode ? screen_width * bpp / 8 : 0) + + 1); + + return 0; +} + +static void _dispc_enable_plane(enum omap_plane plane, int enable) +{ + REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0); +} + + +void dispc_enable_lcd_out(int enable) +{ + enable_clocks(1); + REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); + enable_clocks(0); +} + +void dispc_enable_digit_out(int enable) +{ + enable_clocks(1); + REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1); + enable_clocks(0); +} + +void dispc_lcd_enable_signal_polarity(int act_high) +{ + enable_clocks(1); + REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29); + enable_clocks(0); +} + +void dispc_lcd_enable_signal(int enable) +{ + enable_clocks(1); + REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28); + enable_clocks(0); +} + +void dispc_pck_free_enable(int enable) +{ + enable_clocks(1); + REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); + enable_clocks(0); +} + +void dispc_enable_fifohandcheck(int enable) +{ + enable_clocks(1); + REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16); + enable_clocks(0); +} + + +void dispc_set_lcd_display_type(enum omap_lcd_display_type type) +{ + int mode; + + switch (type) { + case OMAP_DSS_LCD_DISPLAY_STN: + mode = 0; + break; + + case OMAP_DSS_LCD_DISPLAY_TFT: + mode = 1; + break; + + default: + BUG(); + return; + } + + enable_clocks(1); + REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3); + enable_clocks(0); +} + +void dispc_set_loadmode(enum omap_dss_load_mode mode) +{ + enable_clocks(1); + REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1); + enable_clocks(0); +} + + +void omap_dispc_set_default_color(enum omap_channel channel, u32 color) +{ + const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0, + DISPC_DEFAULT_COLOR1 }; + + enable_clocks(1); + dispc_write_reg(def_reg[channel], color); + enable_clocks(0); +} + +void omap_dispc_set_trans_key(enum omap_channel ch, + enum omap_dss_color_key_type type, + u32 trans_key) +{ + const struct dispc_reg tr_reg[] = { + DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 }; + + enable_clocks(1); + if (ch == OMAP_DSS_CHANNEL_LCD) + REG_FLD_MOD(DISPC_CONFIG, type, 11, 11); + else /* OMAP_DSS_CHANNEL_DIGIT */ + REG_FLD_MOD(DISPC_CONFIG, type, 13, 13); + + dispc_write_reg(tr_reg[ch], trans_key); + enable_clocks(0); +} + +void omap_dispc_enable_trans_key(enum omap_channel ch, int enable) +{ + enable_clocks(1); + if (ch == OMAP_DSS_CHANNEL_LCD) + REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); + else /* OMAP_DSS_CHANNEL_DIGIT */ + REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12); + enable_clocks(0); +} + +void dispc_set_tft_data_lines(int data_lines) +{ + int code; + + switch (data_lines) { + case 12: + code = 0; + break; + case 16: + code = 1; + break; + case 18: + code = 2; + break; + case 24: + code = 3; + break; + default: + BUG(); + return; + } + + enable_clocks(1); + REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); + enable_clocks(0); +} + +void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode) +{ + u32 l; + int stallmode; + int gpout0 = 1; + int gpout1; + + switch (mode) { + case OMAP_DSS_PARALLELMODE_BYPASS: + stallmode = 0; + gpout1 = 1; + break; + + case OMAP_DSS_PARALLELMODE_RFBI: + stallmode = 1; + gpout1 = 0; + break; + + case OMAP_DSS_PARALLELMODE_DSI: + stallmode = 1; + gpout1 = 1; + break; + + default: + BUG(); + return; + } + + enable_clocks(1); + + l = dispc_read_reg(DISPC_CONTROL); + + l = FLD_MOD(l, stallmode, 11, 11); + l = FLD_MOD(l, gpout0, 15, 15); + l = FLD_MOD(l, gpout1, 16, 16); + + dispc_write_reg(DISPC_CONTROL, l); + + enable_clocks(0); +} + +static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp, + int vsw, int vfp, int vbp) +{ + u32 timing_h, timing_v; + + BUG_ON(hsw < 1 || hsw > 64); + BUG_ON(hfp < 1 || hfp > 256); + BUG_ON(hbp < 1 || hbp > 256); + + BUG_ON(vsw < 1 || vsw > 64); + BUG_ON(vfp < 0 || vfp > 255); + BUG_ON(vbp < 0 || vbp > 255); + + timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) | + FLD_VAL(hbp-1, 27, 20); + + timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) | + FLD_VAL(vbp, 27, 20); + + enable_clocks(1); + dispc_write_reg(DISPC_TIMING_H, timing_h); + dispc_write_reg(DISPC_TIMING_V, timing_v); + enable_clocks(0); +} + +/* change name to mode? */ +void dispc_set_lcd_timings(struct omap_video_timings *timings) +{ + unsigned xtot, ytot; + unsigned long ht, vt; + + _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp, + timings->vsw, timings->vfp, timings->vbp); + + dispc_set_lcd_size(timings->x_res, timings->y_res); + + xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; + ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; + + ht = (timings->pixel_clock * 1000) / xtot; + vt = (timings->pixel_clock * 1000) / xtot / ytot; + + DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res); + DSSDBG("pck %u\n", timings->pixel_clock); + DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", + timings->hsw, timings->hfp, timings->hbp, + timings->vsw, timings->vfp, timings->vbp); + + DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); +} + +void dispc_set_lcd_divisor(int lck_div, int pck_div) +{ + BUG_ON(lck_div < 1); + BUG_ON(pck_div < 2); + + enable_clocks(1); + dispc_write_reg(DISPC_DIVISOR, + FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); + enable_clocks(0); +} + +static void dispc_get_lcd_divisor(int *lck_div, int *pck_div) +{ + u32 l; + l = dispc_read_reg(DISPC_DIVISOR); + *lck_div = FLD_GET(l, 23, 16); + *pck_div = FLD_GET(l, 7, 0); +} + +unsigned long dispc_fclk_rate(void) +{ + unsigned long r = 0; + + if (dss_get_dispc_clk_source() == 0) + r = dss_clk_get_rate(DSS_CLK_FCK1); + else +#ifdef CONFIG_OMAP2_DSS_DSI + r = dsi_get_dsi1_pll_rate(); +#else + BUG(); +#endif + return r; +} + +unsigned long dispc_pclk_rate(void) +{ + int lcd, pcd; + unsigned long r; + u32 l; + + l = dispc_read_reg(DISPC_DIVISOR); + + lcd = FLD_GET(l, 23, 16); + pcd = FLD_GET(l, 7, 0); + + r = dispc_fclk_rate(); + + return r / lcd / pcd; +} + +ssize_t dispc_print_clocks(char *buf, ssize_t size) +{ + ssize_t l = 0; + int lcd, pcd; + + enable_clocks(1); + + dispc_get_lcd_divisor(&lcd, &pcd); + + l += snprintf(buf + l, size - l, "- dispc -\n"); + + l += snprintf(buf + l, size - l, "dispc fclk source = %s\n", + dss_get_dispc_clk_source() == 0 ? + "dss1_alwon_fclk" : "dsi1_pll_fclk"); + + l += snprintf(buf + l, size - l, + "pixel clk = %lu / %d / %d = %lu\n", + dispc_fclk_rate(), + lcd, pcd, + dispc_pclk_rate()); + + enable_clocks(0); + + return l; +} + +static void _dispc_set_pol_freq(int onoff, int rf, int ieo, int ipc, + int ihs, int ivs, int acbi, int acb) +{ + u32 l = 0; + + DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n", + onoff, rf, ieo, ipc, ihs, ivs, acbi, acb); + + l |= FLD_VAL(onoff, 17, 17); + l |= FLD_VAL(rf, 16, 16); + l |= FLD_VAL(ieo, 15, 15); + l |= FLD_VAL(ipc, 14, 14); + l |= FLD_VAL(ihs, 13, 13); + l |= FLD_VAL(ivs, 12, 12); + l |= FLD_VAL(acbi, 11, 8); + l |= FLD_VAL(acb, 7, 0); + + enable_clocks(1); + dispc_write_reg(DISPC_POL_FREQ, l); + enable_clocks(0); +} + +void dispc_set_pol_freq(struct omap_panel *panel) +{ + _dispc_set_pol_freq((panel->config & OMAP_DSS_LCD_ONOFF) != 0, + (panel->config & OMAP_DSS_LCD_RF) != 0, + (panel->config & OMAP_DSS_LCD_IEO) != 0, + (panel->config & OMAP_DSS_LCD_IPC) != 0, + (panel->config & OMAP_DSS_LCD_IHS) != 0, + (panel->config & OMAP_DSS_LCD_IVS) != 0, + panel->acbi, panel->acb); +} + +void find_lck_pck_divs(int is_tft, unsigned long req_pck, unsigned long fck, + int *lck_div, int *pck_div) +{ + int pcd_min = is_tft ? 2 : 3; + unsigned long best_pck; + int best_ld, cur_ld; + int best_pd, cur_pd; + + best_pck = 0; + best_ld = 0; + best_pd = 0; + + for (cur_ld = 1; cur_ld <= 255; ++cur_ld) { + unsigned long lck = fck / cur_ld; + + for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) { + unsigned long pck = lck / cur_pd; + long old_delta = abs(best_pck - req_pck); + long new_delta = abs(pck - req_pck); + + if (best_pck == 0 || new_delta < old_delta) { + best_pck = pck; + best_ld = cur_ld; + best_pd = cur_pd; + + if (pck == req_pck) + goto found; + } + + if (pck < req_pck) + break; + } + + if (lck / pcd_min < req_pck) + break; + } + +found: + *lck_div = best_ld; + *pck_div = best_pd; +} + +int dispc_calc_clock_div(int is_tft, unsigned long req_pck, + struct dispc_clock_info *cinfo) +{ + unsigned long prate; + struct dispc_clock_info cur, best; + int match = 0; + int min_fck_per_pck; + + if (cpu_is_omap34xx()) + prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck)); + else + prate = 0; + + if (req_pck == dispc.cache_req_pck && + ((cpu_is_omap34xx() && prate == dispc.cache_prate) || + dispc.cache_cinfo.fck == dss_clk_get_rate(DSS_CLK_FCK1))) { + DSSDBG("dispc clock info found from cache.\n"); + *cinfo = dispc.cache_cinfo; + return 0; + } + + min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; + + if (min_fck_per_pck && + req_pck * min_fck_per_pck > DISPC_MAX_FCK) { + DSSERR("Requested pixel clock not possible with the current " + "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " + "the constraint off.\n"); + min_fck_per_pck = 0; + } + +retry: + memset(&cur, 0, sizeof(cur)); + memset(&best, 0, sizeof(best)); + + if (cpu_is_omap24xx()) { + /* XXX can we change the clock on omap2? */ + cur.fck = dss_clk_get_rate(DSS_CLK_FCK1); + cur.fck_div = 1; + + match = 1; + + find_lck_pck_divs(is_tft, req_pck, cur.fck, + &cur.lck_div, &cur.pck_div); + + cur.lck = cur.fck / cur.lck_div; + cur.pck = cur.lck / cur.pck_div; + + best = cur; + + goto found; + } else if (cpu_is_omap34xx()) { + for (cur.fck_div = 16; cur.fck_div > 0; --cur.fck_div) { + cur.fck = prate / cur.fck_div * 2; + + if (cur.fck > DISPC_MAX_FCK) + continue; + + if (min_fck_per_pck && + cur.fck < req_pck * min_fck_per_pck) + continue; + + match = 1; + + find_lck_pck_divs(is_tft, req_pck, cur.fck, + &cur.lck_div, &cur.pck_div); + + cur.lck = cur.fck / cur.lck_div; + cur.pck = cur.lck / cur.pck_div; + + if (abs(cur.pck - req_pck) < abs(best.pck - req_pck)) { + best = cur; + + if (cur.pck == req_pck) + goto found; + } + } + } else { + BUG(); + } + +found: + if (!match) { + if (min_fck_per_pck) { + DSSERR("Could not find suitable clock settings.\n" + "Turning FCK/PCK constraint off and" + "trying again.\n"); + min_fck_per_pck = 0; + goto retry; + } + + DSSERR("Could not find suitable clock settings.\n"); + + return -EINVAL; + } + + if (cinfo) + *cinfo = best; + + dispc.cache_req_pck = req_pck; + dispc.cache_prate = prate; + dispc.cache_cinfo = best; + + return 0; +} + +int dispc_set_clock_div(struct dispc_clock_info *cinfo) +{ + unsigned long prate; + int r; + + if (cpu_is_omap34xx()) { + prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck)); + DSSDBG("dpll4_m4 = %ld\n", prate); + } + + DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); + DSSDBG("lck = %ld (%d)\n", cinfo->lck, cinfo->lck_div); + DSSDBG("pck = %ld (%d)\n", cinfo->pck, cinfo->pck_div); + + if (cpu_is_omap34xx()) { + r = clk_set_rate(dispc.dpll4_m4_ck, prate / cinfo->fck_div); + if (r) + return r; + } + + dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div); + + return 0; +} + +int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask) +{ + int i; + int ret = -EBUSY; + unsigned long flags; + u32 new_mask = 0; + + if (isr == NULL) + return -EINVAL; + + spin_lock_irqsave(&dispc.irq_lock, flags); + + for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { + if (registered_isr[i].isr == isr) { + ret = -EINVAL; + break; + } + + if (registered_isr[i].isr != NULL) + continue; + + registered_isr[i].isr = isr; + registered_isr[i].arg = arg; + registered_isr[i].mask = mask; + + enable_clocks(1); + new_mask = dispc_read_reg(DISPC_IRQENABLE); + new_mask |= mask; + dispc_write_reg(DISPC_IRQENABLE, new_mask); + enable_clocks(0); + + ret = 0; + break; + } + + spin_unlock_irqrestore(&dispc.irq_lock, flags); + + return ret; +} +EXPORT_SYMBOL(omap_dispc_register_isr); + +int omap_dispc_unregister_isr(omap_dispc_isr_t isr) +{ + int i, j; + unsigned long flags; + u32 new_mask = DISPC_IRQ_MASK_ERROR; + int ret = -EINVAL; + + spin_lock_irqsave(&dispc.irq_lock, flags); + + for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { + if (registered_isr[i].isr != isr) + continue; + + registered_isr[i].isr = NULL; + registered_isr[i].arg = NULL; + registered_isr[i].mask = 0; + + for (j = 0; j < DISPC_MAX_NR_ISRS; j++) + new_mask |= registered_isr[j].mask; + + enable_clocks(1); + dispc_write_reg(DISPC_IRQENABLE, new_mask); + enable_clocks(0); + + ret = 0; + break; + } + + spin_unlock_irqrestore(&dispc.irq_lock, flags); + + return ret; +} +EXPORT_SYMBOL(omap_dispc_unregister_isr); + +#ifdef DEBUG +static void print_irq_status(u32 status) +{ + if ((status & DISPC_IRQ_MASK_ERROR) == 0) + return; + + printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status); + +#define PIS(x) \ + if (status & DISPC_IRQ_##x) \ + printk(#x " "); + PIS(GFX_FIFO_UNDERFLOW); + PIS(OCP_ERR); + PIS(VID1_FIFO_UNDERFLOW); + PIS(VID2_FIFO_UNDERFLOW); + PIS(SYNC_LOST); + PIS(SYNC_LOST_DIGIT); +#undef PIS + + printk("\n"); +} +#endif + +/* Called from dss.c. Note that we don't touch clocks here, + * but we presume they are on because we got an IRQ. However, + * an irq handler may turn the clocks off, so we may not have + * clock later in the function. */ +void dispc_irq_handler(void) +{ + int i; + u32 irqstatus = dispc_read_reg(DISPC_IRQSTATUS); + static int errors; + u32 handledirqs = 0; + +#ifdef DEBUG + if (dss_debug) + print_irq_status(irqstatus); +#endif + /* Ack the interrupt. Do it here before clocks are possibly turned + * off */ + dispc_write_reg(DISPC_IRQSTATUS, irqstatus); + + for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { + if (!registered_isr[i].isr) + continue; + if (registered_isr[i].mask & irqstatus) { + registered_isr[i].isr(registered_isr[i].arg, + irqstatus); + handledirqs |= registered_isr[i].mask; + } + } + + if (irqstatus & ~handledirqs & DISPC_IRQ_MASK_ERROR) { + if (printk_ratelimit()) { + DSSERR("dispc irq error status %04x\n", + irqstatus); + } + if (errors++ > 100) { + DSSERR("Excessive DISPC errors\n" + "Turning off lcd and digit\n"); + dispc_enable_lcd_out(0); + dispc_enable_digit_out(0); + } + } + +} + +#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC +void dispc_fake_vsync_irq(void) +{ + u32 irqstatus = DISPC_IRQ_VSYNC; + int i; + + for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { + if (!registered_isr[i].isr) + continue; + if (registered_isr[i].mask & irqstatus) + registered_isr[i].isr(registered_isr[i].arg, + irqstatus); + } +} +#endif + +static void _omap_dispc_initialize_irq(void) +{ + memset(registered_isr, 0, sizeof(registered_isr)); + + /* there's SYNC_LOST_DIGIT waiting after enabling the DSS, + * so clear it */ + dispc_write_reg(DISPC_IRQSTATUS, + dispc_read_reg(DISPC_IRQSTATUS)); + + /* We'll handle these always */ + dispc_write_reg(DISPC_IRQENABLE, DISPC_IRQ_MASK_ERROR); +} + +static void _omap_dispc_initial_config(void) +{ + u32 l; + + l = dispc_read_reg(DISPC_SYSCONFIG); + l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */ + l = FLD_MOD(l, 2, 4, 3); /* SIDLEMODE: smart idle */ + l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */ + l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */ + dispc_write_reg(DISPC_SYSCONFIG, l); + + /* FUNCGATED */ + REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); + + /* L3 firewall setting: enable access to OCM RAM */ + __raw_writel(0x402000b0, IO_ADDRESS(0x680050a0)); + + _dispc_setup_color_conv_coef(); + + dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY); + + /* Set logic clock to fck, pixel clock to fck/2 for now */ + dispc_set_lcd_divisor(1, 2); +} + +int dispc_init(void) +{ + u32 rev; + + spin_lock_init(&dispc.irq_lock); + + dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS); + if (!dispc.base) { + DSSERR("can't ioremap DISPC\n"); + return -ENOMEM; + } + + if (cpu_is_omap34xx()) { + dispc.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); + if (IS_ERR(dispc.dpll4_m4_ck)) { + DSSERR("Failed to get dpll4_m4_ck\n"); + return -ENODEV; + } + } + + enable_clocks(1); + + _omap_dispc_initial_config(); + + _omap_dispc_initialize_irq(); + + dispc_save_context(); + + rev = dispc_read_reg(DISPC_REVISION); + printk(KERN_INFO "OMAP DISPC rev %d.%d\n", + FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); + + enable_clocks(0); + + return 0; +} + +void dispc_exit(void) +{ + if (cpu_is_omap34xx()) + clk_put(dispc.dpll4_m4_ck); + iounmap(dispc.base); +} + +int dispc_enable_plane(enum omap_plane plane, int enable) +{ + DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); + + enable_clocks(1); + _dispc_enable_plane(plane, enable); + enable_clocks(0); + + return 0; +} + +int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out, + u32 paddr, int screen_width, + int pos_x, int pos_y, + int width, int height, + int out_width, int out_height, + enum omap_color_mode color_mode, + int ilace) +{ + int r = 0; + + DSSDBG("dispc_setup_plane %d, ch %d, pa %x, sw %d, %d,%d, %dx%d -> " + "%dx%d, ilace %d, cmode %x\n", + plane, channel_out, paddr, screen_width, pos_x, pos_y, + width, height, + out_width, out_height, + ilace, color_mode); + + enable_clocks(1); + + r = _dispc_setup_plane(plane, channel_out, + paddr, screen_width, + pos_x, pos_y, + width, height, + out_width, out_height, + color_mode, ilace); + + enable_clocks(0); + + return r; +} + +static int dispc_is_intersecting(int x1, int y1, int w1, int h1, + int x2, int y2, int w2, int h2) +{ + if (x1 >= (x2+w2)) + return 0; + + if ((x1+w1) <= x2) + return 0; + + if (y1 >= (y2+h2)) + return 0; + + if ((y1+h1) <= y2) + return 0; + + return 1; +} + +static int dispc_is_overlay_scaled(struct omap_overlay_info *pi) +{ + if (pi->width != pi->out_width) + return 1; + + if (pi->height != pi->out_height) + return 1; + + return 0; +} + +/* returns the area that needs updating */ +void dispc_setup_partial_planes(struct omap_display *display, + int *xi, int *yi, int *wi, int *hi) +{ + struct omap_overlay_manager *mgr; + int i; + + int x, y, w, h; + + x = *xi; + y = *yi; + w = *wi; + h = *hi; + + DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n", + *xi, *yi, *wi, *hi); + + + mgr = display->manager; + + if (!mgr) { + DSSDBG("no manager\n"); + return; + } + + for (i = 0; i < mgr->num_overlays; i++) { + struct omap_overlay *ovl; + struct omap_overlay_info *pi; + ovl = &mgr->overlays[i]; + + if (ovl->manager != mgr) + continue; + + if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) + continue; + + pi = &ovl->info; + + if (!pi->enabled) + continue; + /* + * If the plane is intersecting and scaled, we + * enlarge the update region to accomodate the + * whole area + */ + + if (dispc_is_intersecting(x, y, w, h, + pi->pos_x, pi->pos_y, + pi->out_width, pi->out_height)) { + if (dispc_is_overlay_scaled(pi)) { + + int x1, y1, x2, y2; + + if (x > pi->pos_x) + x1 = pi->pos_x; + else + x1 = x; + + if (y > pi->pos_y) + y1 = pi->pos_y; + else + y1 = y; + + if ((x + w) < (pi->pos_x + pi->out_width)) + x2 = pi->pos_x + pi->out_width; + else + x2 = x + w; + + if ((y + h) < (pi->pos_y + pi->out_height)) + y2 = pi->pos_y + pi->out_height; + else + y2 = y + h; + + x = x1; + y = y1; + w = x2 - x1; + h = y2 - y1; + + DSSDBG("Update area after enlarge due to " + "scaling %d, %d %dx%d\n", + x, y, w, h); + } + } + } + + for (i = 0; i < mgr->num_overlays; i++) { + struct omap_overlay *ovl = &mgr->overlays[i]; + struct omap_overlay_info *pi = &ovl->info; + + int px = pi->pos_x; + int py = pi->pos_y; + int pw = pi->width; + int ph = pi->height; + int pow = pi->out_width; + int poh = pi->out_height; + u32 pa = pi->paddr; + int psw = pi->screen_width; + int bpp; + + if (ovl->manager != mgr) + continue; + + /* + * If plane is not enabled or the update region + * does not intersect with the plane in question, + * we really disable the plane from hardware + */ + + if (!pi->enabled || + !dispc_is_intersecting(x, y, w, h, + px, py, pow, poh)) { + dispc_enable_plane(ovl->id, 0); + continue; + } + + switch (pi->color_mode) { + case OMAP_DSS_COLOR_RGB16: + bpp = 16; + break; + + case OMAP_DSS_COLOR_RGB24P: + bpp = 24; + break; + + case OMAP_DSS_COLOR_RGB24U: + bpp = 32; + break; + + case OMAP_DSS_COLOR_YUV2: + case OMAP_DSS_COLOR_UYVY: + bpp = 16; + break; + + default: + BUG(); + return; + } + + if (x > pi->pos_x) { + px = 0; + pw -= (x - pi->pos_x); + pa += (x - pi->pos_x) * bpp / 8; + } else { + px = pi->pos_x - x; + } + + if (y > pi->pos_y) { + py = 0; + ph -= (y - pi->pos_y); + pa += (y - pi->pos_y) * psw * bpp / 8; + } else { + py = pi->pos_y - y; + } + + if (w < (px+pw)) + pw -= (px+pw) - (w); + + if (h < (py+ph)) + ph -= (py+ph) - (h); + + /* Can't scale the GFX plane */ + if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0 || + dispc_is_overlay_scaled(pi) == 0) { + pow = pw; + poh = ph; + } + + DSSDBG("calc plane %d, %x, sw %d, %d,%d, %dx%d -> %dx%d\n", + ovl->id, pa, psw, px, py, pw, ph, pow, poh); + + dispc_setup_plane(ovl->id, mgr->id, + pa, psw, + px, py, + pw, ph, + pow, poh, + pi->color_mode, 0); + + dispc_enable_plane(ovl->id, 1); + } + + *xi = x; + *yi = y; + *wi = w; + *hi = h; + +} + diff --git a/arch/arm/plat-omap/dss/display.c b/arch/arm/plat-omap/dss/display.c new file mode 100644 index 0000000..e3ff778 --- /dev/null +++ b/arch/arm/plat-omap/dss/display.c @@ -0,0 +1,787 @@ +/* + * linux/arch/arm/plat-omap/dss/display.c + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen <tom...@no...> + * + * 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 "DISPLAY" + +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/sysfs.h> +#include <linux/clk.h> + +#include <mach/display.h> +#include <mach/clock.h> +#include "dss.h" + +#define DSS_MAX_DISPLAYS 8 + +static int num_displays; +static struct omap_display displays[DSS_MAX_DISPLAYS]; + +static ssize_t show_clk(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ssize_t l, size = PAGE_SIZE; + + l = 0; + + l += dss_print_clocks(buf + l, size - l); + + l += dispc_print_clocks(buf + l, size - l); +#ifdef CONFIG_OMAP2_DSS_DSI + l += dsi_print_clocks(buf + l, size - l); +#endif + return l; +} + +static DEVICE_ATTR(clk, S_IRUGO, show_clk, NULL); + +int initialize_sysfs(struct device *dev) +{ + int r; + + r = device_create_file(dev, &dev_attr_clk); + if (r) + DSSERR("failed to create sysfs clk file\n"); + + return r; +} + +void uninitialize_sysfs(struct device *dev) +{ + device_remove_file(dev, &dev_attr_clk); +} + +void initialize_displays(struct omap_dss_platform_data *pdata) +{ + int i; + + num_displays = 0; + + BUG_ON(pdata->num_displays > DSS_MAX_DISPLAYS); + + for (i = 0; i < pdata->num_displays; ++i) { + struct omap_display *display = &displays[i]; + + /*atomic_set(&display->ref_count, 0);*/ + display->ref_count = 0; + + display->hw_config = *pdata->displays[i]; + display->type = pdata->displays[i]->type; + display->name = pdata->displays[i]->name; + + switch (display->type) { + + case OMAP_DISPLAY_TYPE_DPI: + dpi_init_display(display); + break; +#ifdef CONFIG_OMAP2_DSS_RFBI + case OMAP_DISPLAY_TYPE_DBI: + rfbi_init_display(display); + break; +#endif +#ifdef CONFIG_OMAP2_DSS_VENC + case OMAP_DISPLAY_TYPE_VENC: + venc_init_display(display); + break; +#endif +#ifdef CONFIG_OMAP2_DSS_SDI + case OMAP_DISPLAY_TYPE_SDI: + sdi_init_display(display); + break; +#endif +#ifdef CONFIG_OMAP2_DSS_DSI + case OMAP_DISPLAY_TYPE_DSI: + dsi_init_display(display); + break; +#endif + + default: + DSSERR("Support for display '%s' not compiled in.\n", + display->name); + continue; + } + + num_displays++; + } +} + +static int check_overlay(struct omap_overlay *ovl, + struct omap_display *display) +{ + struct omap_overlay_info *info; + int outw, outh; + + if (!display) + return 0; + + if (!ovl->info.enabled) + return 0; + + info = &ovl->info; + + if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { + outw = info->width; + outh = info->height; + } else { + if (info->out_width == 0) + outw = info->width; + else + outw = info->out_width; + + if (info->out_height == 0) + outh = info->height; + else + outh = info->out_height; + } + + if (display->panel->timings.x_res < info->pos_x + outw) + return -EINVAL; + + if (display->panel->timings.y_res < info->pos_y + outh) + return -EINVAL; + + return 0; +} + + +static int omap_dss_set_manager(struct omap_overlay *ovl, + struct omap_overlay_manager *mgr) +{ + int r; + + if (ovl->manager) { + DSSERR("overlay '%s' already has a manager '%s'\n", + ovl->name, ovl->manager->name); + } + + r = check_overlay(ovl, mgr->display); + if (r) + return r; + + ovl->manager = mgr; + + return 0; +} + +static int omap_dss_unset_manager(struct omap_overlay *ovl) +{ + if (!ovl->manager) { + DSSERR("failed to detach overlay: manager not set\n"); + return -EINVAL; + } + + ovl->manager = NULL; + + return 0; +} + +static int omap_dss_set_display(struct omap_overlay_manager *mgr, + struct omap_display *display) +{ + int i; + int r; + + if (display->manager) { + DSSERR("display '%s' already has a manager '%s'\n", + display->name, display->manager->name); + return -EINVAL; + } + + if ((mgr->supported_displays & display->type) == 0) { + DSSERR("display '%s' does not support manager '%s'\n", + display->name, mgr->name); + return -EINVAL; + } + + for (i = 0; i < mgr->num_overlays; i++) { + struct omap_overlay *ovl = &mgr->overlays[i]; + + if (ovl->manager != mgr || !ovl->info.enabled) + continue; + + r = check_overlay(ovl, display); + if (r) + return r; + } + + display->manager = mgr; + mgr->display = display; + + return 0; +} + +static int omap_dss_unset_display(struct omap_overlay_manager *mgr) +{ + if (!mgr->display) { + DSSERR("failed to unset display, display not set.\n"); + return -EINVAL; + } + + mgr->display->manager = NULL; + mgr->display = NULL; + + return 0; +} + +static int omap_dss_setup_overlay_input(struct omap_overlay *ovl, + u32 paddr, void *vaddr, int screen_width, + int width, int height, + enum omap_color_mode color_mode) +{ + int r; + struct omap_overlay_info old_info; + + if ((ovl->supported_modes & color_mode) == 0) { + DSSERR("overlay doesn't support mode %d\n", color_mode); + return -EINVAL; + } + + old_info = ovl->info; + + ovl->info.paddr = paddr; + ovl->info.vaddr = vaddr; + ovl->info.screen_width = screen_width; + + ovl->info.width = width; + ovl->info.height = height; + ovl->info.color_mode = color_mode; + + if (ovl->manager) { + r = check_overlay(ovl, ovl->manager->display); + if (r) { + ovl->info = old_info; + return r; + } + } + + return 0; +} + +static int omap_dss_setup_overlay_output(struct omap_overlay *ovl, + int pos_x, int pos_y, + int out_width, int out_height) +{ + int r; + struct omap_overlay_info old_info; + + old_info = ovl->info; + + ovl->info.pos_x = pos_x; + ovl->info.pos_y = pos_y; + ovl->info.out_width = out_width; + ovl->info.out_height = out_height; + + if (ovl->manager) { + r = check_overlay(ovl, ovl->manager->display); + if (r) { + ovl->info = old_info; + return r; + } + } + + return 0; +} + +static int omap_dss_enable_overlay(struct omap_overlay *ovl, int enable) +{ + struct omap_overlay_info old_info; + int r; + + old_info = ovl->info; + + ovl->info.enabled = enable ? 1 : 0; + + if (ovl->manager) { + r = check_overlay(ovl, ovl->manager->display); + if (r) { + ovl->info = old_info; + return r; + } + } + + return 0; +} + + +static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) +{ + int i; + int r = 0; + + DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name); + + if (!mgr->display) { + DSSDBG("no display, aborting apply\n"); + return 0; + } + + /* on a manual update display update() handles configuring + * planes */ + if (mgr->display->get_update_mode) { + enum omap_dss_update_mode mode; + mode = mgr->display->get_update_mode(mgr->display); + if (mode == OMAP_DSS_UPDATE_MANUAL) + return 0; + } + + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + + for (i = 0; i < mgr->num_overlays; i++) { + int ilace = 0; + int outw, outh; + + struct omap_overlay *ovl = &mgr->overlays[i]; + + if (!ovl->manager) { + dispc_enable_plane(ovl->id, 0); + continue; + } + + if (ovl->manager != mgr) + continue; + + if (!ovl->info.enabled) { + dispc_enable_plane(ovl->id, 0); + continue; + } + + if (mgr->display->type == OMAP_DISPLAY_TYPE_VENC) + ilace = 1; + + if (ovl->info.out_width == 0) + outw = ovl->info.width; + else + outw = ovl->info.out_width; + + if (ovl->info.out_height == 0) + outh = ovl->info.height; + else + outh = ovl->info.out_height; + + r = dispc_setup_plane(ovl->id, ovl->manager->id, + ovl->info.paddr, + ovl->info.screen_width, + ovl->info.pos_x, + ovl->info.pos_y, + ovl->info.width, + ovl->info.height, + outw, + outh, + ovl->info.color_mode, + ilace); + + if (r) { + DSSERR("dispc_setup_plane failed\n"); + goto e... [truncated message content] |
From: Tony L. <to...@at...> - 2009-01-12 13:38:26
|
* Tomi Valkeinen <tom...@no...> [090112 14:37]: > Signed-off-by: Tomi Valkeinen <tom...@no...> > --- > > arch/arm/plat-omap/Kconfig | 2 > arch/arm/plat-omap/Makefile | 2 > arch/arm/plat-omap/dss/Kconfig | 71 + > arch/arm/plat-omap/dss/Makefile | 6 > arch/arm/plat-omap/dss/dispc.c | 2113 +++++++++++++++++++++++++++++ > arch/arm/plat-omap/dss/display.c | 787 +++++++++++ > arch/arm/plat-omap/dss/dpi.c | 344 +++++ > arch/arm/plat-omap/dss/dss.c | 774 +++++++++++ > arch/arm/plat-omap/dss/dss.h | 274 ++++ > arch/arm/plat-omap/dss/sdi.c | 174 ++ > arch/arm/plat-omap/include/mach/display.h | 462 ++++++ > 11 files changed, 5009 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 Sorry, no subdirectories allowed under arch/arm/*omap*. Please move these to live under drivers/video somewhere. Also, you should not need to use cpu_is_omapxxxx() macros under drivers, please separate out the low-level init to happen under arch/arm/*omap* and pass the necessary things to the driver in the platform_data. See how usb and mmc are doing it for example. Regards, Tony |
From: Shah, H. <har...@ti...> - 2009-01-12 13:06:53
|
> -----Original Message----- > From: lin...@vg... [mailto:linux-omap- > ow...@vg...] On Behalf Of Tony Lindgren > Sent: Monday, January 12, 2009 6:32 PM > To: Tomi Valkeinen > Cc: lin...@li...; lin...@vg... > Subject: Re: [Linux-fbdev-devel] [PATCH 02/12] DSS: Display subsystem for > OMAP2/3 > > * Tomi Valkeinen <tom...@no...> [090112 14:37]: > > Signed-off-by: Tomi Valkeinen <tom...@no...> > > --- > > > > arch/arm/plat-omap/Kconfig | 2 > > arch/arm/plat-omap/Makefile | 2 > > arch/arm/plat-omap/dss/Kconfig | 71 + > > arch/arm/plat-omap/dss/Makefile | 6 > > arch/arm/plat-omap/dss/dispc.c | 2113 > +++++++++++++++++++++++++++++ > > arch/arm/plat-omap/dss/display.c | 787 +++++++++++ > > arch/arm/plat-omap/dss/dpi.c | 344 +++++ > > arch/arm/plat-omap/dss/dss.c | 774 +++++++++++ > > arch/arm/plat-omap/dss/dss.h | 274 ++++ > > arch/arm/plat-omap/dss/sdi.c | 174 ++ > > arch/arm/plat-omap/include/mach/display.h | 462 ++++++ > > 11 files changed, 5009 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 > > Sorry, no subdirectories allowed under arch/arm/*omap*. Please move > these to live under drivers/video somewhere. > > Also, you should not need to use cpu_is_omapxxxx() macros under > drivers, please separate out the low-level init to happen under > arch/arm/*omap* and pass the necessary things to the driver in > the platform_data. See how usb and mmc are doing it for example. > [Shah, Hardik] Hi Tony, DSS library will be used by both V4L2 driver and the FBDEV driver. So will you please suggest the ideal directory for the DSS library? Moving the DSS library files under /drivers/video will break V4L2 will moving it under /drivers/media/video/ will break fbdev. Thanks and Regards, Hardik Shah > Regards, > > Tony > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to maj...@vg... > More majordomo info at http://vger.kernel.org/majordomo-info.html |
From: Tony L. <to...@at...> - 2009-01-12 13:17:15
|
* Shah, Hardik <har...@ti...> [090112 15:06]: > > > > -----Original Message----- > > From: lin...@vg... [mailto:linux-omap- > > ow...@vg...] On Behalf Of Tony Lindgren > > Sent: Monday, January 12, 2009 6:32 PM > > To: Tomi Valkeinen > > Cc: lin...@li...; lin...@vg... > > Subject: Re: [Linux-fbdev-devel] [PATCH 02/12] DSS: Display subsystem for > > OMAP2/3 > > > > * Tomi Valkeinen <tom...@no...> [090112 14:37]: > > > Signed-off-by: Tomi Valkeinen <tom...@no...> > > > --- > > > > > > arch/arm/plat-omap/Kconfig | 2 > > > arch/arm/plat-omap/Makefile | 2 > > > arch/arm/plat-omap/dss/Kconfig | 71 + > > > arch/arm/plat-omap/dss/Makefile | 6 > > > arch/arm/plat-omap/dss/dispc.c | 2113 > > +++++++++++++++++++++++++++++ > > > arch/arm/plat-omap/dss/display.c | 787 +++++++++++ > > > arch/arm/plat-omap/dss/dpi.c | 344 +++++ > > > arch/arm/plat-omap/dss/dss.c | 774 +++++++++++ > > > arch/arm/plat-omap/dss/dss.h | 274 ++++ > > > arch/arm/plat-omap/dss/sdi.c | 174 ++ > > > arch/arm/plat-omap/include/mach/display.h | 462 ++++++ > > > 11 files changed, 5009 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 > > > > Sorry, no subdirectories allowed under arch/arm/*omap*. Please move > > these to live under drivers/video somewhere. > > > > Also, you should not need to use cpu_is_omapxxxx() macros under > > drivers, please separate out the low-level init to happen under > > arch/arm/*omap* and pass the necessary things to the driver in > > the platform_data. See how usb and mmc are doing it for example. > > > [Shah, Hardik] Hi Tony, > DSS library will be used by both V4L2 driver and the FBDEV driver. So will you please suggest the ideal directory for the DSS library? Moving the DSS library files under /drivers/video will break V4L2 will moving it under /drivers/media/video/ will break fbdev. How about drivers/video/omap/dss? You should be able to compile in the common modules even if CONFIG_FB is not set. Tony |
From: Tomi V. <tom...@no...> - 2009-01-12 12:38:34
|
Signed-off-by: Tomi Valkeinen <tom...@no...> --- arch/arm/plat-omap/dss/venc.c | 506 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 506 insertions(+), 0 deletions(-) create mode 100644 arch/arm/plat-omap/dss/venc.c diff --git a/arch/arm/plat-omap/dss/venc.c b/arch/arm/plat-omap/dss/venc.c new file mode 100644 index 0000000..81319e4 --- /dev/null +++ b/arch/arm/plat-omap/dss/venc.c @@ -0,0 +1,506 @@ +/* + * linux/arch/arm/plat-omap/dss/venc.c + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen <tom...@no...> + * + * 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/err.h> +#include <linux/io.h> +#include <linux/mutex.h> +#include <linux/completion.h> +#include <linux/delay.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 + +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; + const struct venc_config *config; + struct mutex venc_lock; +} venc; + +static struct omap_panel venc_panel = { + .name = "tv-out", + .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) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | + DSS_CLK_96M); + else + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | + DSS_CLK_96M); +} + +int venc_init(void) +{ + u8 rev_id; + int use_pal = 1; /* XXX */ + + mutex_init(&venc.venc_lock); + + if (use_pal) + venc.config = &venc_config_pal_trm; + else + venc.config = &venc_config_ntsc_trm; + + venc_panel.timings.x_res = venc.config->width; + venc_panel.timings.y_res = venc.config->height; + + venc.base = ioremap(VENC_BASE, SZ_1K); + if (!venc.base) { + DSSERR("can't ioremap VENC\n"); + return -ENOMEM; + } + + /* 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 void venc_sync_lost_handler(void *arg, u32 mask) +{ + /* we just catch SYNC_LOST_DIGIT here so that + * dispc doesn't take it as an error */ +} + +static int venc_enable_display(struct omap_display *display) +{ + DSSDBG("venc_enable_display\n"); + + mutex_lock(&venc.venc_lock); + + if (display->state != OMAP_DSS_DISPLAY_DISABLED) { + mutex_unlock(&venc.venc_lock); + return -EINVAL; + } + + venc_enable_clocks(1); + + dss_set_venc_output(display->hw_config.u.venc.type); + dss_set_dac_pwrdn_bgz(1); + + 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); + } + + venc_write_config(venc.config); + + dispc_set_digit_size(venc.config->width, venc.config->height/2); + + if (display->hw_config.panel_enable) + display->hw_config.panel_enable(display); + + dispc_go(OMAP_DSS_CHANNEL_DIGIT); + + omap_dispc_register_isr(venc_sync_lost_handler, NULL, + DISPC_IRQ_SYNC_LOST_DIGIT); + + dispc_enable_digit_out(1); + + mdelay(20); + + omap_dispc_unregister_isr(venc_sync_lost_handler); + + display->state = OMAP_DSS_DISPLAY_ACTIVE; + + mutex_unlock(&venc.venc_lock); + + return 0; +} + +static void venc_disable_display(struct omap_display *display) +{ + DSSDBG("venc_disable_display\n"); + + mutex_lock(&venc.venc_lock); + + if (display->state == OMAP_DSS_DISPLAY_DISABLED) { + mutex_unlock(&venc.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; + + mutex_unlock(&venc.venc_lock); +} + +static void venc_get_timings(struct omap_display *display, + struct omap_video_timings *timings) +{ + *timings = venc_panel.timings; +} + +void venc_init_display(struct omap_display *display) +{ + display->panel = &venc_panel; + display->enable = venc_enable_display; + display->disable = venc_disable_display; + display->get_timings = venc_get_timings; +} |
From: Tomi V. <tom...@no...> - 2009-01-12 12:40:21
|
Signed-off-by: Tomi Valkeinen <tom...@no...> --- drivers/video/omap2/Kconfig | 7 +- drivers/video/omap2/Makefile | 1 drivers/video/omap2/panel-sharp-ls037v7dw01.c | 109 +++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 1 deletions(-) create mode 100644 drivers/video/omap2/panel-sharp-ls037v7dw01.c diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig index be00882..b54c955 100644 --- a/drivers/video/omap2/Kconfig +++ b/drivers/video/omap2/Kconfig @@ -43,5 +43,10 @@ config PANEL_GENERIC Generic panel driver. Used for DVI output for Beagle and OMAP3 SDP. -endmenu +config PANEL_SHARP_LS037V7DW01 + tristate "Sharp LS037V7DW01 LCD Panel" + depends on OMAP2_DSS + help + LCD Panel used in TI's SDP3430 and EVM boards +endmenu diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile index f471a2b..fe6858e 100644 --- a/drivers/video/omap2/Makefile +++ b/drivers/video/omap2/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_FB_OMAP2) += omapfb.o omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o +obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o diff --git a/drivers/video/omap2/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/panel-sharp-ls037v7dw01.c new file mode 100644 index 0000000..7d67b6d --- /dev/null +++ b/drivers/video/omap2/panel-sharp-ls037v7dw01.c @@ -0,0 +1,109 @@ +/* + * LCD panel driver for Sharp LS037V7DW01 + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen <tom...@no...> + * + * 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/>. + */ + +#include <linux/module.h> +#include <linux/delay.h> + +#include <mach/display.h> + +static int sharp_ls_panel_init(struct omap_display *display) +{ + return 0; +} + +static void sharp_ls_panel_cleanup(struct omap_display *display) +{ +} + +static int sharp_ls_panel_enable(struct omap_display *display) +{ + int r = 0; + + if (display->hw_config.panel_enable) + r = display->hw_config.panel_enable(display); + + return r; +} + +static void sharp_ls_panel_disable(struct omap_display *display) +{ + if (display->hw_config.panel_disable) + display->hw_config.panel_disable(display); +} + +static int sharp_ls_panel_suspend(struct omap_display *display) +{ + sharp_ls_panel_disable(display); + return 0; +} + +static int sharp_ls_panel_resume(struct omap_display *display) +{ + return sharp_ls_panel_enable(display); +} + +static struct omap_panel sharp_ls_panel = { + .owner = THIS_MODULE, + .name = "sharp-ls037v7dw01", + .init = sharp_ls_panel_init, + .cleanup = sharp_ls_panel_cleanup, + .enable = sharp_ls_panel_enable, + .disable = sharp_ls_panel_disable, + .suspend = sharp_ls_panel_suspend, + .resume = sharp_ls_panel_resume, + /*.set_mode = sharp_ls_set_mode, */ + + .timings = { + .x_res = 480, + .y_res = 640, + + .pixel_clock = 19200, + + .hsw = 2, + .hfp = 1, + .hbp = 28, + + .vsw = 1, + .vfp = 1, + .vbp = 1, + }, + + .acb = 0x28, + + .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | + OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC, + + .bpp = 16, +}; + + +static int __init sharp_ls_panel_drv_init(void) +{ + omap_dss_register_panel(&sharp_ls_panel); + return 0; +} + +static void __exit sharp_ls_panel_drv_exit(void) +{ + omap_dss_unregister_panel(&sharp_ls_panel); +} + +module_init(sharp_ls_panel_drv_init); +module_exit(sharp_ls_panel_drv_exit); +MODULE_LICENSE("GPL"); |
From: Tomi V. <tom...@no...> - 2009-01-12 12:40:29
|
Signed-off-by: Tomi Valkeinen <tom...@no...> --- arch/arm/plat-omap/Makefile | 2 arch/arm/plat-omap/fb-vram.c | 646 +++++++++++++ arch/arm/plat-omap/fb.c | 22 arch/arm/plat-omap/include/mach/omapfb.h | 14 drivers/video/Kconfig | 1 drivers/video/Makefile | 1 drivers/video/omap/Kconfig | 5 drivers/video/omap2/Kconfig | 42 + drivers/video/omap2/Makefile | 2 drivers/video/omap2/omapfb-ioctl.c | 460 ++++++++++ drivers/video/omap2/omapfb-main.c | 1442 ++++++++++++++++++++++++++++++ drivers/video/omap2/omapfb-sysfs.c | 901 +++++++++++++++++++ drivers/video/omap2/omapfb.h | 115 ++ 13 files changed, 3650 insertions(+), 3 deletions(-) create mode 100644 arch/arm/plat-omap/fb-vram.c 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 diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index 2740497..7d602a6 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -4,7 +4,7 @@ # Common support obj-y := common.o sram.o clock.o devices.o dma.o mux.o gpio.o \ - usb.o fb.o io.o + usb.o fb.o fb-vram.o io.o obj-m := obj-n := obj- := diff --git a/arch/arm/plat-omap/fb-vram.c b/arch/arm/plat-omap/fb-vram.c new file mode 100644 index 0000000..2994f8f --- /dev/null +++ b/arch/arm/plat-omap/fb-vram.c @@ -0,0 +1,646 @@ +/* + * linux/arch/arm/plat-omap/fb-vram.c + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen <tom...@no...> + * + * 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 DEBUG + +#include <linux/vmalloc.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/list.h> +#include <linux/dma-mapping.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#include <linux/bootmem.h> + +#include <asm/setup.h> + +#include <mach/sram.h> +#include <mach/omapfb.h> + +#ifdef DEBUG +#define DBG(format, ...) printk(KERN_DEBUG "VRAM: " format, ## __VA_ARGS__) +#else +#define DBG(format, ...) +#endif + +#define OMAP2_SRAM_START 0x40200000 +/* Maximum size, in reality this is smaller if SRAM is partially locked. */ +#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */ + +#define REG_MAP_SIZE(_page_cnt) \ + ((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8) +#define REG_MAP_PTR(_rg, _page_nr) \ + (((_rg)->map) + (_page_nr) / (sizeof(unsigned long) * 8)) +#define REG_MAP_MASK(_page_nr) \ + (1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1))) + +#if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) + +/* postponed regions are used to temporarily store region information at boot + * time when we cannot yet allocate the region list */ +#define MAX_POSTPONED_REGIONS 10 + +static int postponed_cnt __initdata; +static struct { + unsigned long paddr; + size_t size; +} postponed_regions[MAX_POSTPONED_REGIONS] __initdata; + +struct vram_alloc { + struct list_head list; + unsigned long paddr; + unsigned pages; +}; + +struct vram_region { + struct list_head list; + struct list_head alloc_list; + unsigned long paddr; + void *vaddr; + unsigned pages; + unsigned dma_alloced:1; +}; + +static DEFINE_MUTEX(region_mutex); +static LIST_HEAD(region_list); + +static inline int region_mem_type(unsigned long paddr) +{ + if (paddr >= OMAP2_SRAM_START && + paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE) + return OMAPFB_MEMTYPE_SRAM; + else + return OMAPFB_MEMTYPE_SDRAM; +} + +static struct vram_region *omap_vram_create_region(unsigned long paddr, + void *vaddr, unsigned pages) +{ + struct vram_region *rm; + + rm = kzalloc(sizeof(*rm), GFP_KERNEL); + + if (rm) { + INIT_LIST_HEAD(&rm->alloc_list); + rm->paddr = paddr; + rm->vaddr = vaddr; + rm->pages = pages; + } + + return rm; +} + +static void omap_vram_free_region(struct vram_region *vr) +{ + list_del(&vr->list); + kfree(vr); +} + +static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr, + unsigned long paddr, unsigned pages) +{ + struct vram_alloc *va; + struct vram_alloc *new; + + new = kzalloc(sizeof(*va), GFP_KERNEL); + + if (!new) + return NULL; + + new->paddr = paddr; + new->pages = pages; + + list_for_each_entry(va, &vr->alloc_list, list) { + if (va->paddr > new->paddr) + break; + } + + list_add_tail(&new->list, &va->list); + + return new; +} + +static void omap_vram_free_allocation(struct vram_alloc *va) +{ + list_del(&va->list); + kfree(va); +} + +static __init int omap_vram_add_region_postponed(unsigned long paddr, size_t size) +{ + if (postponed_cnt == MAX_POSTPONED_REGIONS) + return -ENOMEM; + + postponed_regions[postponed_cnt].paddr = paddr; + postponed_regions[postponed_cnt].size = size; + + ++postponed_cnt; + + return 0; +} + +/* add/remove_region can be exported if there's need to add/remove regions + * runtime */ +static int omap_vram_add_region(unsigned long paddr, size_t size) +{ + struct vram_region *rm; + void *vaddr; + unsigned pages; + + DBG("adding region paddr %08lx size %d\n", + paddr, size); + + size &= PAGE_MASK; + pages = size >> PAGE_SHIFT; + + vaddr = ioremap_wc(paddr, size); + if (vaddr == NULL) + return -ENOMEM; + + rm = omap_vram_create_region(paddr, vaddr, pages); + if (rm == NULL) { + iounmap(vaddr); + return -ENOMEM; + } + + list_add(&rm->list, ®ion_list); + + return 0; +} + +#if 0 +int omap_vram_remove_region(unsigned long paddr) +{ + struct region *rm; + unsigned i; + + DBG("remove region paddr %08lx\n", paddr); + list_for_each_entry(rm, ®ion_list, list) + if (rm->paddr != paddr) + continue; + + if (rm->paddr != paddr) + return -EINVAL; + + for (i = 0; i < rm->page_cnt; i++) + if (region_page_reserved(rm, i)) + return -EBUSY; + + iounmap(rm->vaddr); + + list_del(&rm->list); + + kfree(rm); + + return 0; +} +#endif + +int omap_vram_free(unsigned long paddr, void *vaddr, size_t size) +{ + struct vram_region *rm; + struct vram_alloc *alloc; + unsigned start, end; + + DBG("free mem paddr %08lx vaddr %p size %d\n", + paddr, vaddr, size); + + size = PAGE_ALIGN(size); + + mutex_lock(®ion_mutex); + + list_for_each_entry(rm, ®ion_list, list) { + list_for_each_entry(alloc, &rm->alloc_list, list) { + start = alloc->paddr; + end = alloc->paddr + (alloc->pages >> PAGE_SHIFT); + + if (start >= paddr && end < paddr + size) + goto found; + } + } + + mutex_unlock(®ion_mutex); + return -EINVAL; + +found: + if (rm->dma_alloced) { + DBG("freeing dma-alloced\n"); + dma_free_writecombine(NULL, size, vaddr, paddr); + omap_vram_free_allocation(alloc); + omap_vram_free_region(rm); + } else { + omap_vram_free_allocation(alloc); + } + + mutex_unlock(®ion_mutex); + return 0; +} +EXPORT_SYMBOL(omap_vram_free); + +#if 0 +void *omap_vram_reserve(unsigned long paddr, size_t size) +{ + + struct region *rm; + unsigned start_page; + unsigned end_page; + unsigned i; + void *vaddr; + + size = PAGE_ALIGN(size); + + rm = region_find_region(paddr, size); + + DBG("reserve mem paddr %08lx size %d\n", + paddr, size); + + BUG_ON(rm == NULL); + + start_page = (paddr - rm->paddr) >> PAGE_SHIFT; + end_page = start_page + (size >> PAGE_SHIFT); + for (i = start_page; i < end_page; i++) + region_reserve_page(rm, i); + + vaddr = rm->vaddr + (start_page << PAGE_SHIFT); + + return vaddr; +} +EXPORT_SYMBOL(omap_vram_reserve); +#endif +static void *_omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr) +{ + struct vram_region *rm; + struct vram_alloc *alloc; + void *vaddr; + + list_for_each_entry(rm, ®ion_list, list) { + unsigned long start, end; + + DBG("checking region %lx %d\n", rm->paddr, rm->pages); + + if (region_mem_type(rm->paddr) != mtype) + continue; + + start = rm->paddr; + + list_for_each_entry(alloc, &rm->alloc_list, list) { + end = alloc->paddr; + + if (end - start >= pages << PAGE_SHIFT) + goto found; + + start = alloc->paddr + (alloc->pages << PAGE_SHIFT); + } + + end = rm->paddr + (rm->pages << PAGE_SHIFT); +found: + if (end - start < pages << PAGE_SHIFT) + continue; + + DBG("FOUND %lx, end %lx\n", start, end); + + if (omap_vram_create_allocation(rm, start, pages) == NULL) + return NULL; + + *paddr = start; + vaddr = rm->vaddr + (start - rm->paddr); + + return vaddr; + } + + return NULL; +} + +static void *_omap_vram_alloc_dma(unsigned pages, unsigned long *paddr) +{ + struct vram_region *rm; + void *vaddr; + + vaddr = dma_alloc_writecombine(NULL, pages << PAGE_SHIFT, + (dma_addr_t *)paddr, GFP_KERNEL); + + if (vaddr == NULL) + return NULL; + + rm = omap_vram_create_region(*paddr, vaddr, pages); + if (rm == NULL) { + dma_free_writecombine(NULL, pages << PAGE_SHIFT, vaddr, + (dma_addr_t)*paddr); + return NULL; + } + + rm->dma_alloced = 1; + + if (omap_vram_create_allocation(rm, *paddr, pages) == NULL) { + dma_free_writecombine(NULL, pages << PAGE_SHIFT, vaddr, + (dma_addr_t)*paddr); + kfree(rm); + return NULL; + } + + list_add(&rm->list, ®ion_list); + + return vaddr; +} + +void *omap_vram_alloc(int mtype, size_t size, unsigned long *paddr) +{ + void *vaddr; + unsigned pages; + + BUG_ON(mtype > OMAPFB_MEMTYPE_MAX || !size); + + DBG("alloc mem type %d size %d\n", mtype, size); + + size = PAGE_ALIGN(size); + pages = size >> PAGE_SHIFT; + + mutex_lock(®ion_mutex); + + vaddr = _omap_vram_alloc(mtype, pages, paddr); + + if (vaddr == NULL && mtype == OMAPFB_MEMTYPE_SDRAM) { + DBG("fallback to dma_alloc\n"); + + vaddr = _omap_vram_alloc_dma(pages, paddr); + } + + mutex_unlock(®ion_mutex); + + return vaddr; +} +EXPORT_SYMBOL(omap_vram_alloc); + +#ifdef CONFIG_PROC_FS +static void *r_next(struct seq_file *m, void *v, loff_t *pos) +{ + struct list_head *l = v; + + (*pos)++; + + if (list_is_last(l, ®ion_list)) + return 0; + + return l->next; +} + +static void *r_start(struct seq_file *m, loff_t *pos) +{ + loff_t p = *pos; + struct list_head *l = ®ion_list; + + mutex_lock(®ion_mutex); + + do { + l = l->next; + if (l == ®ion_list) + return NULL; + } while (p--); + + return l; +} + +static void r_stop(struct seq_file *m, void *v) +{ + mutex_unlock(®ion_mutex); +} + +static int r_show(struct seq_file *m, void *v) +{ + struct vram_region *vr; + struct vram_alloc *va; + unsigned size; + + vr = list_entry(v, struct vram_region, list); + + size = vr->pages << PAGE_SHIFT; + seq_printf(m, "%08lx-%08lx v:%p-%p (%d bytes) %s\n", + vr->paddr, vr->paddr + size, + vr->vaddr, vr->vaddr + size, + size, + vr->dma_alloced ? "dma_alloc" : ""); + + list_for_each_entry(va, &vr->alloc_list, list) { + size = va->pages << PAGE_SHIFT; + seq_printf(m, " %08lx-%08lx (%d bytes)\n", + va->paddr, va->paddr + size, + size); + } + + + + return 0; +} + +static const struct seq_operations resource_op = { + .start = r_start, + .next = r_next, + .stop = r_stop, + .show = r_show, +}; + +static int vram_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &resource_op); +} + +static const struct file_operations proc_vram_operations = { + .open = vram_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static int __init omap_vram_create_proc(void) +{ + proc_create("omap-vram", 0, NULL, &proc_vram_operations); + + return 0; +} +#endif + +static __init int omap_vram_init(void) +{ + int i, r; + + for (i = 0; i < postponed_cnt; i++) + omap_vram_add_region(postponed_regions[i].paddr, + postponed_regions[i].size); + +#ifdef CONFIG_PROC_FS + r = omap_vram_create_proc(); + if (r) + return -ENOMEM; +#endif + + return 0; +} + +arch_initcall(omap_vram_init); + +/* boottime vram alloc stuff */ +static u32 omapfb_sram_vram_start __initdata; +static u32 omapfb_sram_vram_size __initdata; + +static u32 omapfb_sdram_vram_start __initdata; +static u32 omapfb_sdram_vram_size __initdata; + +static u32 omapfb_def_sdram_vram_size __initdata; + +static void __init omapfb_early_vram(char **p) +{ + unsigned long size; + size = memparse(*p, p); + omapfb_def_sdram_vram_size = size; +} +__early_param("vram=", omapfb_early_vram); + +/* + * Called from map_io. We need to call to this early enough so that we + * can reserve the fixed SDRAM regions before VM could get hold of them. + */ +void __init omapfb_reserve_sdram(void) +{ + struct bootmem_data *bdata; + unsigned long sdram_start, sdram_size; + unsigned long reserved; + u32 paddr; + u32 size; + + bdata = NODE_DATA(0)->bdata; + sdram_start = bdata->node_min_pfn << PAGE_SHIFT; + sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start; + reserved = 0; + + /* cmdline arg overrides the board file definition */ + if (omapfb_def_sdram_vram_size) { + size = omapfb_def_sdram_vram_size; + paddr = 0; + } else { + size = omapfb_sdram_vram_size; + paddr = omapfb_sdram_vram_start; + } + + if (size) { + if (paddr) { + if (paddr < sdram_start || + paddr + size > sdram_start + sdram_size) { + printk(KERN_ERR "Illegal SDRAM region for VRAM\n"); + return; + } + + reserve_bootmem(paddr, size, BOOTMEM_DEFAULT); + } else { + if (size > sdram_size) { + printk(KERN_ERR "Illegal SDRAM size for VRAM\n"); + return; + } + + paddr = virt_to_phys(alloc_bootmem(size)); + } + + reserved += size; + omap_vram_add_region_postponed(paddr, size); + } + + if (reserved) + pr_info("Reserving %lu bytes SDRAM for VRAM\n", reserved); +} + +/* + * Called at sram init time, before anything is pushed to the SRAM stack. + * Because of the stack scheme, we will allocate everything from the + * start of the lowest address region to the end of SRAM. This will also + * include padding for page alignment and possible holes between regions. + * + * As opposed to the SDRAM case, we'll also do any dynamic allocations at + * this point, since the driver built as a module would have problem with + * freeing / reallocating the regions. + */ +unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart, + unsigned long sram_vstart, + unsigned long sram_size, + unsigned long pstart_avail, + unsigned long size_avail) +{ + unsigned long pend_avail; + unsigned long reserved; + u32 paddr; + u32 size; + + paddr = omapfb_sram_vram_start; + size = omapfb_sram_vram_size; + + reserved = 0; + pend_avail = pstart_avail + size_avail; + + + if (!paddr) { + /* Dynamic allocation */ + if ((size_avail & PAGE_MASK) < size) { + printk(KERN_ERR "Not enough SRAM for VRAM\n"); + return 0; + } + size_avail = (size_avail - size) & PAGE_MASK; + paddr = pstart_avail + size_avail; + } + + if (paddr < sram_pstart || + paddr + size > sram_pstart + sram_size) { + printk(KERN_ERR "Illegal SRAM region for VRAM\n"); + return 0; + } + + /* Reserve everything above the start of the region. */ + if (pend_avail - paddr > reserved) + reserved = pend_avail - paddr; + size_avail = pend_avail - reserved - pstart_avail; + + /* + * We have a kernel mapping for this already, so the + * driver won't have to make one. + */ + /* XXX do we need the vaddr? */ + /* rg.vaddr = (void *)(sram_vstart + paddr - sram_pstart); */ + + omap_vram_add_region_postponed(paddr, size); + + if (reserved) + pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved); + + return reserved; +} + +void __init omap2_set_sdram_vram(u32 size, u32 start) +{ + omapfb_sdram_vram_start = start; + omapfb_sdram_vram_size = size; +} + +void __init omap2_set_sram_vram(u32 size, u32 start) +{ + omapfb_sram_vram_start = start; + omapfb_sram_vram_size = size; +} + +#endif + diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c index 3746222..ee2cc6f 100644 --- a/arch/arm/plat-omap/fb.c +++ b/arch/arm/plat-omap/fb.c @@ -327,6 +327,28 @@ static inline int omap_init_fb(void) arch_initcall(omap_init_fb); +#elif defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) + +static u64 omap_fb_dma_mask = ~(u32)0; + +static struct platform_device omap_fb_device = { + .name = "omapfb", + .id = -1, + .dev = { + .dma_mask = &omap_fb_dma_mask, + .coherent_dma_mask = ~(u32)0, + .platform_data = NULL, + }, + .num_resources = 0, +}; + +static inline int omap_init_fb(void) +{ + return platform_device_register(&omap_fb_device); +} + +arch_initcall(omap_init_fb); + #else void omapfb_reserve_sdram(void) {} diff --git a/arch/arm/plat-omap/include/mach/omapfb.h b/arch/arm/plat-omap/include/mach/omapfb.h index b226bdf..0800f92 100644 --- a/arch/arm/plat-omap/include/mach/omapfb.h +++ b/arch/arm/plat-omap/include/mach/omapfb.h @@ -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 { @@ -393,6 +400,13 @@ extern int omapfb_update_window_async(struct fb_info *fbi, /* in arch/arm/plat-omap/fb.c */ extern void omapfb_set_ctrl_platform_data(void *pdata); +/* in arch/arm/plat-omap/fb-vram */ +int omap_vram_free(unsigned long paddr, void *vaddr, size_t size); +void *omap_vram_reserve(unsigned long paddr, size_t size); +void *omap_vram_alloc(int mtype, size_t size, unsigned long *paddr); +extern void omap2_set_sdram_vram(u32 size, u32 start); +extern void omap2_set_sram_vram(u32 size, u32 start); + #endif /* __KERNEL__ */ #endif /* __OMAPFB_H */ diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 3f3ce13..689a3b1 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2116,6 +2116,7 @@ config FB_PRE_INIT_FB the bootloader. source "drivers/video/omap/Kconfig" +source "drivers/video/omap2/Kconfig" source "drivers/video/backlight/Kconfig" source "drivers/video/display/Kconfig" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index e39e33e..3d9d50e 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -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 obj-$(CONFIG_FB_MB862XX) += mb862xx/ diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index c355b59..541fab3 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig @@ -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 @@ -80,7 +81,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 diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig new file mode 100644 index 0000000..8be51a3 --- /dev/null +++ b/drivers/video/omap2/Kconfig @@ -0,0 +1,42 @@ +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 support for OMAP2/3 FB" + default y + depends on FB_OMAP2 + help + Support for debug output. You have to enable the actual printing + with debug module parameter. + +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. + +config FB_OMAP2_NUM_FBS + int "Number of framebuffers" + range 1 10 + default 3 + depends on FB_OMAP2 + help + Select the number of framebuffers created. OMAP2/3 has 3 overlays + so normally this would be 3. + +menu "OMAP2/3 Display Device Drivers" + depends on OMAP2_DSS + + +endmenu + diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile new file mode 100644 index 0000000..51c2e00 --- /dev/null +++ b/drivers/video/omap2/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_FB_OMAP2) += omapfb.o +omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o diff --git a/drivers/video/omap2/omapfb-ioctl.c b/drivers/video/omap2/omapfb-ioctl.c new file mode 100644 index 0000000..0cb0370 --- /dev/null +++ b/drivers/video/omap2/omapfb-ioctl.c @@ -0,0 +1,460 @@ +/* + * linux/drivers/video/omap2/omapfb-ioctl.c + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen <tom...@no...> + * + * 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/>. + */ + +#include <linux/fb.h> +#include <linux/device.h> +#include <linux/uaccess.h> +#include <linux/platform_device.h> +#include <linux/mm.h> + +#include <mach/display.h> +#include <mach/omapfb.h> + +#include "omapfb.h" + +static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omap_display *display = fb2display(fbi); + struct omap_overlay *ovl; + int r = 0; + + DBG("omapfb_setup_plane\n"); + + omapfb_lock(fbdev); + + if (ofbi->num_overlays != 1) { + r = -EINVAL; + goto out; + } + + /* XXX uses only the first overlay */ + ovl = ofbi->overlays[0]; + + if (pi->enabled && !ofbi->region.size) { + /* + * This plane's memory was freed, can't enable it + * until it's reallocated. + */ + r = -EINVAL; + goto out; + } + + if (pi->enabled) { + r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y, + pi->out_width, pi->out_height); + if (r) + goto out; + } + + ovl->enable(ovl, pi->enabled); + + if (ovl->manager) + ovl->manager->apply(ovl->manager); + + if (display) { + if (display->sync) + display->sync(display); + + if (display->update) + display->update(display, 0, 0, + display->panel->timings.x_res, + display->panel->timings.y_res); + } + +out: + omapfb_unlock(fbdev); + if (r) + dev_err(fbdev->dev, "setup_plane failed\n"); + return r; +} + +static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + + omapfb_lock(fbdev); + + if (ofbi->num_overlays != 1) { + memset(pi, 0, sizeof(*pi)); + } else { + struct omap_overlay_info *ovli; + struct omap_overlay *ovl; + + ovl = ofbi->overlays[0]; + ovli = &ovl->info; + + pi->pos_x = ovli->pos_x; + pi->pos_y = ovli->pos_y; + pi->enabled = ovli->enabled; + pi->channel_out = 0; /* xxx */ + pi->mirror = 0; + pi->out_width = ovli->out_width; + pi->out_height = ovli->out_height; + } + + omapfb_unlock(fbdev); + + return 0; +} + +static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omapfb_mem_region *rg; + struct omap_display *display = fb2display(fbi); + int r, i; + size_t size; + + if (mi->type > OMAPFB_MEMTYPE_MAX) + return -EINVAL; + + size = PAGE_ALIGN(mi->size); + + rg = &ofbi->region; + + omapfb_lock(fbdev); + + for (i = 0; i < ofbi->num_overlays; i++) { + if (ofbi->overlays[i]->info.enabled) { + r = -EBUSY; + goto out; + } + } + + if (rg->size != size || rg->type != mi->type) { + struct fb_var_screeninfo new_var; + unsigned long old_size = rg->size; + + if (display->sync) + display->sync(display); + + r = omapfb_realloc_fbmem(fbdev, ofbi->id, size); + if (r) + goto out; + + if (old_size != size) { + if (size) { + memcpy(&new_var, &fbi->var, sizeof(new_var)); + r = check_fb_var(fbi, &new_var); + if (r < 0) + goto out; + memcpy(&fbi->var, &new_var, sizeof(fbi->var)); + set_fb_fix(fbi); + } else { + /* + * Set these explicitly to indicate that the + * plane memory is dealloce'd, the other + * screen parameters in var / fix are invalid. + */ + fbi->fix.smem_start = 0; + fbi->fix.smem_len = 0; + } + } + } + + r = 0; +out: + omapfb_unlock(fbdev); + + return r; +} + +static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omapfb_mem_region *rg; + + rg = &ofbi->region; + memset(mi, 0, sizeof(*mi)); + + omapfb_lock(fbdev); + mi->size = rg->size; + mi->type = rg->type; + omapfb_unlock(fbdev); + + return 0; +} + +static int omapfb_update_window(struct fb_info *fbi, + u32 x, u32 y, u32 w, u32 h) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omap_display *display = fb2display(fbi); + + if (!display) + return 0; + + if (w == 0 || h == 0) + return 0; + + if (x + w > display->panel->timings.x_res || + y + h > display->panel->timings.y_res) + return -EINVAL; + + omapfb_lock(fbdev); + display->update(display, x, y, w, h); + omapfb_unlock(fbdev); + + return 0; +} + +static int omapfb_set_update_mode(struct fb_info *fbi, + enum omapfb_update_mode mode) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omap_display *display = fb2display(fbi); + enum omap_dss_update_mode um; + int r; + + if (!display || !display->set_update_mode) + return -EINVAL; + + switch (mode) { + case OMAPFB_UPDATE_DISABLED: + um = OMAP_DSS_UPDATE_DISABLED; + break; + + case OMAPFB_AUTO_UPDATE: + um = OMAP_DSS_UPDATE_AUTO; + break; + + case OMAPFB_MANUAL_UPDATE: + um = OMAP_DSS_UPDATE_MANUAL; + break; + + default: + return -EINVAL; + } + + omapfb_lock(fbdev); + r = display->set_update_mode(display, um); + omapfb_unlock(fbdev); + + return r; +} + +static int omapfb_get_update_mode(struct fb_info *fbi, + enum omapfb_update_mode *mode) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omap_display *display = fb2display(fbi); + enum omap_dss_update_mode m; + + if (!display || !display->get_update_mode) + return -EINVAL; + + omapfb_lock(fbdev); + m = display->get_update_mode(display); + omapfb_unlock(fbdev); + + switch (m) { + case OMAP_DSS_UPDATE_DISABLED: + *mode = OMAPFB_UPDATE_DISABLED; + break; + case OMAP_DSS_UPDATE_AUTO: + *mode = OMAPFB_AUTO_UPDATE; + break; + case OMAP_DSS_UPDATE_MANUAL: + *mode = OMAPFB_MANUAL_UPDATE; + break; + default: + BUG(); + } + + return 0; +} + +int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omap_display *display = fb2display(fbi); + + union { + struct omapfb_update_window_old uwnd_o; + struct omapfb_update_window uwnd; + struct omapfb_plane_info plane_info; + struct omapfb_caps caps; + struct omapfb_mem_info mem_info; + enum omapfb_update_mode update_mode; + int test_num; + } p; + + int r = 0; + + DBG("ioctl %x (%d)\n", cmd, cmd & 0xff); + + switch (cmd) { + case OMAPFB_SYNC_GFX: + if (!display || !display->sync) { + /* DSS1 never returns an error here, so we neither */ + /*r = -EINVAL;*/ + break; + } + + omapfb_lock(fbdev); + r = display->sync(display); + omapfb_unlock(fbdev); + break; + + case OMAPFB_UPDATE_WINDOW_OLD: + if (!display || !display->update) { + r = -EINVAL; + break; + } + + if (copy_from_user(&p.uwnd_o, + (void __user *)arg, + sizeof(p.uwnd_o))) { + r = -EFAULT; + break; + } + + r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y, + p.uwnd_o.width, p.uwnd_o.height); + break; + + case OMAPFB_UPDATE_WINDOW: + if (!display || !display->update) { + r = -EINVAL; + break; + } + + if (copy_from_user(&p.uwnd, (void __user *)arg, + sizeof(p.uwnd))) { + r = -EFAULT; + break; + } + + r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y, + p.uwnd.width, p.uwnd.height); + break; + + case OMAPFB_SETUP_PLANE: + if (copy_from_user(&p.plane_info, (void __user *)arg, + sizeof(p.plane_info))) + r = -EFAULT; + else + r = omapfb_setup_plane(fbi, &p.plane_info); + break; + + case OMAPFB_QUERY_PLANE: + r = omapfb_query_plane(fbi, &p.plane_info); + if (r < 0) + break; + if (copy_to_user((void __user *)arg, &p.plane_info, + sizeof(p.plane_info))) + r = -EFAULT; + break; + + case OMAPFB_SETUP_MEM: + if (copy_from_user(&p.mem_info, (void __user *)arg, + sizeof(p.mem_info))) + r = -EFAULT; + else + r = omapfb_setup_mem(fbi, &p.mem_info); + break; + + case OMAPFB_QUERY_MEM: + r = omapfb_query_mem(fbi, &p.mem_info); + if (r < 0) + break; + if (copy_to_user((void __user *)arg, &p.mem_info, + sizeof(p.mem_info))) + r = -EFAULT; + break; + + case OMAPFB_GET_CAPS: + if (!display) { + r = -EINVAL; + break; + } + + p.caps.ctrl = display->caps; + + if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps))) + r = -EFAULT; + break; + + case OMAPFB_SET_UPDATE_MODE: + if (get_user(p.update_mode, (int __user *)arg)) + r = -EFAULT; + else + r = omapfb_set_update_mode(fbi, p.update_mode); + break; + + case OMAPFB_GET_UPDATE_MODE: + r = omapfb_get_update_mode(fbi, &p.update_mode); + if (r) + break; + if (put_user(p.update_mode, + (enum omapfb_update_mode __user *)arg)) + r = -EFAULT; + break; + + /* LCD and CTRL tests do the same thing for backward + * compatibility */ + case OMAPFB_LCD_TEST: + if (get_user(p.test_num, (int __user *)arg)) { + r = -EFAULT; + break; + } + if (!display || !display->run_test) { + r = -EINVAL; + break; + } + + r = display->run_test(display, p.test_num); + + break; + + case OMAPFB_CTRL_TEST: + if (get_user(p.test_num, (int __user *)arg)) { + r = -EFAULT; + break; + } + if (!display || !display->run_test) { + r = -EINVAL; + break; + } + + r = display->run_test(display, p.test_num); + + break; + + default: + DBG("ioctl unhandled\n"); + r = -EINVAL; + } + + return r; +} + + diff --git a/drivers/video/omap2/omapfb-main.c b/drivers/video/omap2/omapfb-main.c new file mode 100644 index 0000000..d043c43 --- /dev/null +++ b/drivers/video/omap2/omapfb-main.c @@ -0,0 +1,1442 @@ +/* + * linux/drivers/video/omap2/omapfb-main.c + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen <tom...@no...> + * + * 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/>. + */ + +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/fb.h> +#include <linux/dma-mapping.h> +#include <linux/vmalloc.h> +#include <linux/device.h> +#include <linux/platform_device.h> + +#include <mach/display.h> +#include <mach/omapfb.h> + +#include "omapfb.h" + +#define MODULE_NAME "omapfb" + +static char *def_mode; +static char *def_vram; + +#ifdef DEBUG +unsigned int omapfb_debug; +module_param_named(debug, omapfb_debug, bool, 0644); +#endif + +#ifdef DEBUG +static void fill_fb(void *addr, struct fb_info *fbi) +{ + struct fb_var_screeninfo *var = &fbi->var; + + const short w = var->xres_virtual; + const short h = var->yres_virtual; + + int y, x; + u8 *p = addr; + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + if (var->bits_per_pixel == 16) { + u16 *pw = (u16 *)p; + + if (x < 20 && y < 20) + *pw = 0xffff; + else if (x == 20 || x == w - 20 || + y == 20 || y == h - 20) + *pw = 0xffff; + else if (x == y || w - x == h - y) + *pw = ((1<<5)-1)<<11; + else if (w - x == y || x == h - y) + *pw = ((1<<6)-1)<<5; + else { + int t = x / (w/3); + if (t == 0) + *pw = y % 32; + else if (t == 1) + *pw = (y % 64) << 5; + else if (t == 2) + *pw = (y % 32) << 11; + } + } else if (var->bits_per_pixel == 24) { + u8 *pb = (u8 *)p; + + int r = 0, g = 0, b = 0; + + if (x < 20 && y < 20) + r = g = b = 0xff; + else if (x == 20 || x == w - 20 || + y == 20 || y == h - 20) + r = g = b = 0xff; + else if (x == y || w - x == h - y) + r = 0xff; + else if (w - x == y || x == h - y) + g = 0xff; + else { + int q = x / (w / 3); + u8 base = 255 - (y % 256); + if (q == 0) + r = base; + else if (q == 1) + g = base; + else if (q == 2) + b = base; + } + + pb[0] = b; + pb[1] = g; + pb[2] = r; + + } else if (var->bits_per_pixel == 32) { + u32 *pd = (u32 *)p; + + if (x < 20 && y < 20) + *pd = 0xffffff; + else if (x == 20 || x == w - 20 || + y == 20 || y == h - 20) + *pd = 0xffffff; + else if (x == y || w - x == h - y) + *pd = 0xff0000; + else if (w - x == y || x == h - y) + *pd = 0x00ff00; + else { + u8 base = 255 - (y % 256); + *pd = base << ((x / (w/3)) << 3); + } + } + + p += var->bits_per_pixel >> 3; + } + } +} +#endif + +static enum omap_color_mode fb_mode_to_dss_mode(struct fb_var_screeninfo *var) +{ + switch (var->nonstd) { + case 0: + break; + case OMAPFB_COLOR_YUV422: + return OMAP_DSS_COLOR_UYVY; + + case OMAPFB_COLOR_YUY422: + return OMAP_DSS_COLOR_YUV2; + + case OMAPFB_COLOR_ARGB16: + return OMAP_DSS_COLOR_ARGB16; + + case OMAPFB_COLOR_ARGB32: + return OMAP_DSS_COLOR_ARGB32; + + case OMAPFB_COLOR_RGBA32: + return OMAP_DSS_COLOR_RGBA32; + + case OMAPFB_COLOR_RGBX32: + return OMAP_DSS_COLOR_RGBX32; + + default: + return -EINVAL; + } + + switch (var->bits_per_pixel) { + case 1: + return OMAP_DSS_COLOR_CLUT1; + case 2: + return OMAP_DSS_COLOR_CLUT2; + case 4: + return OMAP_DSS_COLOR_CLUT4; + case 8: + return OMAP_DSS_COLOR_CLUT8; + case 12: + return OMAP_DSS_COLOR_RGB12U; + case 16: + return OMAP_DSS_COLOR_RGB16; + case 24: + return OMAP_DSS_COLOR_RGB24P; + case 32: + return OMAP_DSS_COLOR_RGB24U; + default: + return -EINVAL; + } + + return -EINVAL; +} + +void set_fb_fix(struct fb_info *fbi) +{ + struct fb_fix_screeninfo *fix = &fbi->fix; + struct fb_var_screeninfo *var = &fbi->var; + struct omapfb_mem_region *rg = &FB2OFB(fbi)->region; + + DBG("set_fb_fix\n"); + + /* used by open/write in fbmem.c */ + fbi->screen_base = (char __iomem *)rg->vaddr; + + /* used by mmap in fbmem.c */ + fix->smem_start = rg->paddr; + fix->smem_len = rg->size; + + fix->type = FB_TYPE_PACKED_PIXELS; + + if (var->nonstd) + fix->visual = FB_VISUAL_PSEUDOCOLOR; + else { + switch (var->bits_per_pixel) { + case 32: + case 24: + case 16: + case 12: + fix->visual = FB_VISUAL_TRUECOLOR; + /* 12bpp is stored in 16 bits */ + break; + case 1: + case 2: + case 4: + case 8: + fix->visual = FB_VISUAL_PSEUDOCOLOR; + break; + } + } + + fix->accel = FB_ACCEL_NONE; + fix->line_length = (var->xres_virtual * var->bits_per_pixel) >> 3; + + fix->xpanstep = 1; + fix->ypanstep = 1; +} + +/* check new var and possibly modify it to be ok */ +int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omap_display *display = fb2display(fbi); + unsigned long max_frame_size; + unsigned long line_size; + int xres_min, xres_max; + int yres_min, yres_max; + enum omap_color_mode mode = 0; + struct omap_overlay *ovl; + + DBG("check_fb_var %d\n", ofbi->id); + + if (ofbi->region.size == 0) { + memset(var, 0, sizeof(*var)); + return 0; + } + + if (ofbi->num_overlays == 0) { + dev_err(ofbi->fbdev->dev, "no overlays, aborting\n"); + return -EINVAL; + } + + /* XXX: uses the first overlay */ + ovl = ofbi->overlays[0]; + + /* if we are using non standard mode, fix the bpp first */ + switch (var->nonstd) { + case 0: + break; + case OMAPFB_COLOR_YUV422: + case OMAPFB_COLOR_YUY422: + case OMAPFB_COLOR_ARGB16: + var->bits_per_pixel = 16; + break; + case OMAPFB_COLOR_ARGB32: + case OMAPFB_COLOR_RGBA32: + case OMAPFB_COLOR_RGBX32: + var->bits_per_pixel = 32; + break; + default: + DBG("invalid nonstd mode\n"); + return -EINVAL; + } + + mode = fb_mode_to_dss_mode(var); + if (mode < 0) { + DBG("cannot convert var to omap dss mode\n"); + return -EINVAL; + } + + if ((ovl->supported_modes & mode) == 0) { + DBG("invalid mode\n"); + return -EINVAL; + } + + xres_min = OMAPFB_PLANE_XRES_MIN; + xres_max = (display ? display->panel->timings.x_res : 2048) - ovl->info.pos_x; + yres_min = OMAPFB_PLANE_YRES_MIN; + yres_max = (display ? display->panel->timings.y_res : 2048) - ovl->info.pos_y; + + if (var->xres < xres_min) + var->xres = xres_min; + if (var->yres < yres_min) + var->yres = yres_min; + if (var->xres_virtual < var->xres) + var->xres_virtual = var->xres; + if (var->yres_virtual < var->yres) + var->yres_virtual = var->yres; + max_frame_size = ofbi->region.size; + line_size = (var->xres_virtual * var->bits_per_pixel) >> 3; + + if (line_size * var->yres_virtual > max_frame_size) { + /* Try to keep yres_virtual first */ + line_size = max_frame_size / var->yres_virtual; + var->xres_virtual = line_size * 8 / var->bits_per_pixel; + if (var->xres_virtual < var->xres) { + /* Still doesn't fit. Shrink yres_virtual too */ + var->xres_virtual = var->xres; + line_size = var->xres * var->bits_per_pixel / 8; + var->yres_virtual = max_frame_size / line_size; + } + /* Recheck this, as the virtual size changed. */ + if (var->xres_virtual < var->xres) + var->xres = var->xres_virtual; + if (var->yres_virtual < var->yres) + var->yres = var->yres_virtual; + if (var->xres < xres_min || var->yres < yres_min) { + DBG("Cannot fit FB to memory\n"); + return -EINVAL; + } + } + if (var->xres + var->xoffset > var->xres_virtual) + var->xoffset = var->xres_virtual - var->xres; + if (var->yres + var->yoffset > var->yres_virtual) + var->yoffset = var->yres_virtual - var->yres; + + if (var->bits_per_pixel == 16) { + var->red.offset = 11; var->red.length = 5; + var->red.msb_right = 0; + var->green.offset = 5; var->green.length = 6; + var->green.msb_right = 0; + var->blue.offset = 0; var->blue.length = 5; + var->blue.msb_right = 0; + } else if (var->bits_per_pixel == 24) { + var->red.offset = 16; var->red.length = 8; + var->red.msb_right = 0; + var->green.offset = 8; var->green.length = 8; + var->green.msb_right = 0; + var->blue.offset = 0; var->blue.length = 8; + var->blue.msb_right = 0; + var->transp.offset = 0; var->transp.length = 0; + } else if (var->bits_per_pixel == 32) { + var->red.offset = 16; var->red.length = 8; + var->red.msb_right = 0; + var->green.offset = 8; var->green.length = 8; + var->green.msb_right = 0; + var->blue.offset = 0; var->blue.length = 8; + var->blue.msb_right = 0; + var->transp.offset = 0; var->transp.length = 0; + } else { + DBG("failed to setup fb color mask\n"); + return -EINVAL; + } + + DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n", + var->xres, var->yres, + var->xres_virtual, var->yres_virtual); + + var->height = -1; + var->width = -1; + var->grayscale = 0; + + if (display && display->get_timings) { + struct omap_video_timings timings; + display->get_timings(display, &timings); + + /* pixclock in ps, the rest in pixclock */ + var->pixclock = timings.pixel_clock != 0 ? + KHZ2PICOS(timings.pixel_clock) : + 0; + var->left_margin = timings.hfp; + var->right_margin = timings.hbp; + var->upper_margin = timings.vfp; + var->lower_margin = timings.vbp; + var->hsync_len = timings.hsw; + var->vsync_len = timings.vsw; + } else { + var->pixclock = 0; + var->left_margin = 0; + var->right_margin = 0; + var->upper_margin = 0; + var->lower_margin = 0; + var->hsync_len = 0; + var->vsync_len = 0; + } + + /* TODO: get these from panel->config */ + var->vmode = FB_VMODE_NONINTERLACED; + var->sync = 0; + + return 0; +} + +/* + * --------------------------------------------------------------------------- + * fbdev framework callbacks + * --------------------------------------------------------------------------- + */ +static int omapfb_open(struct fb_info *fbi, int user) +{ + return 0; +} + +static int omapfb_release(struct fb_info *fbi, int user) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omap_display *display = fb2display(fbi); + + DBG("Closing fb with plane index %d\n", ofbi->id); + + omapfb_lock(fbdev); +#if 1 + if (display) { + /* XXX Is this really needed ? */ + if (display->sync) + display->sync(display); + + if (display->update) + display->update(display, + 0, 0, + display->panel->timings.x_res, + display->panel->timings.y_res); + } +#endif + + if (display && display->sync) + display->sync(display); + + omapfb_unlock(fbdev); + + return 0; +} + +/* setup overlay according to the fb */ +int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, + int posx, int posy, int outw, int outh) +{ + int r = 0; + struct omapfb_info *ofbi = FB2OFB(fbi); + struct fb_var_screeninfo *var = &fbi->var; + enum omap_color_mode mode = 0; + int offset; + u32 data_start_p; + void *data_start_v; + + DBG("setup_overlay %d\n", ofbi->id); + + if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0 && + (outw != var->xres || outh != var->yres)) { + r = -EINVAL; + goto err; + } + + offset = ((var->yoffset * var->xres_virtual + + var->xoffset) * var->bits_per_pixel) >> 3; + + data_start_p = ofbi->region.paddr + offset; + data_start_v = ofbi->region.vaddr + offset; + + mode = fb_mode_to_dss_mode(var); + + if (mode == -EINVAL) { + r = -EINVAL; + goto err; + } + + r = ovl->setup_input(ovl, + data_start_p, data_start_v, + var->xres_virtual, + var->xres, var->yres, + mode); + + if (r) + goto err; + + r = ovl->setup_output(ovl, + posx, posy, + outw, outh); + + if (r) + goto err; + + return 0; + +err: + DBG("setup_overlay failed\n"); + return r; +} + +/* apply var to the overlay */ +int omapfb_apply_changes(struct fb_info *fbi, int init) +{ + int r = 0; + struct omapfb_info *ofbi = FB2OFB(fbi); + struct fb_var_screeninfo *var = &fbi->var; + struct omap_overlay *ovl; + int posx, posy; + int outw, outh; + int i; + + for (i = 0; i < ofbi->num_overlays; i++) { + ovl = ofbi->overlays[i]; + + DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id); + + if (ofbi->region.size == 0) { + /* the fb is not available. disable the overlay */ + ovl->enable(ovl, 0); + if (!init && ovl->manager) + ovl->manager->apply(ovl->manager); + continue; + } + + if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { + outw = var->xres; + outh = var->yres; + } else { + outw = ovl->info.out_width; + outh = ovl->info.out_height; + } + + if (init) { + posx = 0; + posy = 0; + } else { + posx = ovl->info.pos_x; + posy = ovl->info.pos_y; + } + + r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh); + if (r) + goto err; + + if (!init && ovl->manager) + ovl->manager->apply(ovl->manager); + } + return 0; +err: + DBG("apply_changes failed\n"); + return r; +} + +/* checks var and eventually tweaks it to something supported, + * DO NOT MODIFY PAR */ +static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) +{ + int r; + + DBG("check_var(%d)\n", FB2OFB(fbi)->id); + + r = check_fb_var(fbi, var); + + return r; +} + +/* set the video mode according to info->var */ +static int omapfb_set_par(struct fb_info *fbi) +{ + int r; + + DBG("set_par(%d)\n", FB2OFB(fbi)->id); + + set_fb_fix(fbi); + r = omapfb_apply_changes(fbi, 0); + + return r; +} + +static void omapfb_rotate(struct fb_info *fbi, int rotate) +{ + DBG("rotate(%d)\n", FB2OFB(fbi)->id); + return; +} + +static int omapfb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *fbi) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + int r = 0; + + DBG("pan_display(%d)\n", ofbi->id); + + omapfb_lock(fbdev); + + if (var->xoffset != fbi->var.xoffset || + var->yoffset != fbi->var.yoffset) { + struct fb_var_screeninfo new_var; + + new_var = fbi->var; + new_var.xoffset = var->xoffset; + new_var.yoffset = var->yoffset; + + r = check_fb_var(fbi, &new_var); + + if (r == 0) { + fbi->var = new_var; + set_fb_fix(fbi); + r = omapfb_apply_changes(fbi, 0); + } + } + + omapfb_unlock(fbdev); + + return r; +} + +static void mmap_user_open(struct vm_area_struct *vma) +{ + struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; + + atomic_inc(&ofbi->map_count); +} + +static void mmap_user_close(struct vm_area_struct *vma) +{ + struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; + + atomic_dec(&ofbi->map_count); +} + +static struct vm_operations_struct mmap_user_ops = { + .open = mmap_user_open, + .close = mmap_user_close, +}; + +static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb_mem_region *rg = &ofbi->region; + unsigned long off; + unsigned long start; + u32 len; + + if (vma->vm_end - vma->vm_start == 0) + return 0; + if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) + return -EINVAL; + off = vma->vm_pgoff << PAGE_SHIFT; + + start = rg->paddr; + len = rg->size; + if (off >= len) + return -EINVAL; + if ((vma->vm_end - vma->vm_start + off) > len) + return -EINVAL; + off += start; + vma->vm_pgoff = off >> PAGE_SHIFT; + vma->vm_flags |= VM_IO | VM_RESERVED; + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + vma->vm_ops = &mmap_user_ops; + vma->vm_private_data = ofbi; + if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) + return -EAGAIN; + /* vm_ops.open won't be called for mmap itself. */ + atomic_inc(&ofbi->map_count); + return 0; +} + +/* Store a single color palette entry into a pseudo palette or the hardware + * palette if one is available. For now we support only 16bpp and thus store + * the entry only to the pseudo palette. + */ +static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green, + u_int blue, u_int transp, int update_hw_pal) +{ + /*struct omapfb_info *ofbi = FB2OFB(fbi);*/ + /*struct omapfb2_device *fbdev = ofbi->fbdev;*/ + struct fb_var_screeninfo *var = &fbi->var; + int r = 0; + + enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */ + + /*switch (plane->color_mode) {*/ + switch (mode) { + case OMAPFB_COLOR_YUV422: + case OMAPFB_COLOR_YUV420: + case OMAPFB_COLOR_YUY422: + r = -EINVAL; + break; + case OMAPFB_COLOR_CLUT_8BPP: + case OMAPFB_COLOR_CLUT_4BPP: + case OMAPFB_COLOR_CLUT_2BPP: + case OMAPFB_COLOR_CLUT_1BPP: + /* + if (fbdev->ctrl->setcolreg) + r = fbdev->ctrl->setcolreg(regno, red, green, blue, + transp, update_hw_pal); + */ + /* Fallthrough */ + r = -EINVAL; + break; + case OMAPFB_COLOR_RGB565: + case OMAPFB_COLOR_RGB444: + case OMAPFB_COLOR_RGB24P: + case OMAPFB_COLOR_RGB24U: + if (r != 0) + break; + + if (regno < 0) { + r = -EINVAL; + break; + } + + if (regno < 16) { + u16 pal; + pal = ((red >> (16 - var->red.length)) << + var->red.offset) | + ((green >> (16 - var->green.length)) << + var->green.offset) | + (blue >> (16 - var->blue.length)); + ((u32 *)(fbi->pseudo_palette))[regno] = pal; + } + break; + default: + BUG(); + } + return r; +} + +static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + DBG("setcolreg\n"); + + return _setcolreg(info, regno, red, green, blue, transp, 1); +} + +static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info) +{ + int count, index, r; + u16 *red, *green, *blue, *transp; + u16 trans = 0xffff; + + DBG("setcmap\n"); + + red = cmap->red; + green = cmap->green; + blue = cmap->blue; + transp = cmap->transp; + index = cmap->start; + + for (count = 0; count < cmap->len; count++) { + if (transp) + trans = *transp++; + r = _setcolreg(info, index++, *red++, *green++, *blue++, trans, + count == cmap->len - 1); + if (r != 0) + return r; + } + + return 0; +} + +static int omapfb_blank(int blank, struct fb_info *fbi) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omap_display *display = fb2display(fbi); + int do_update = 0; + int r = 0; + + omapfb_lock(fbdev); + + switch (blank) { + case FB_BLANK_UNBLANK: + if (display->state != OMAP_DSS_DISPLAY_SUSPENDED) { + r = -EINVAL; + goto exit; + } + + if (display->resume) + r = display->resume(display); + + if (r == 0 && display->get_update_mode && + display->get_update_mode(display) == + OMAP_DSS_UPDATE_MANUAL) + do_update = 1; + + break; + + case FB_BLANK_POWERDOWN: + if (display->state != OMAP_DSS_DISPLAY_ACTIVE) { + r = -EINVAL; + goto exit; + } + + if (display->suspend) + r = display->suspend(display); + + break; + + default: + r = -EINVAL; + } + +exit: + omapfb_unlock(fbdev); + + if (r == 0 && do_update && display->update) + r = display->update(display, + 0, 0, + display->panel->timings.x_res, + display->panel->timings.y_res); + + return r; +} + +static struct fb_ops omapfb_ops = { + .owner = THIS_MODULE, + .fb_open = omapfb_open, + .fb_release = omapfb_release, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_blank = omapfb_blank, + .fb_ioctl = omapfb_ioctl, + .fb_check_var = omapfb_check_var, + .fb_set_par = omapfb_set_par, + .fb_rotate = omapfb_rotate, + .fb_pan_display = omapfb_pan_display, + .fb_mmap = omapfb_mmap, + .fb_setcolreg = omapfb_setcolreg, + .fb_setcmap = omapfb_setcmap, +}; + +static void omapfb_free_fbmem(struct omapfb2_device *fbdev, int fbnum) +{ + struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[fbnum]); + struct omapfb_mem_region *rg; + + rg = &ofbi->region; + + if (rg->paddr) + if (omap_vram_free(rg->paddr, rg->vaddr, rg->size)) + dev_err(fbdev->dev, "VRAM FREE failed\n"); + + rg->vaddr = NULL; + rg->paddr = 0; + rg->alloc = 0; + rg->size = 0; +} + +static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev) +{ + int i; + + DBG("free all fbmem\n"); + + for (i = 0; i < fbdev->num_fbs; i++) + omapfb_free_fbmem(fbdev, i); + + return 0; +} + +static int omapfb_alloc_fbmem(struct omapfb2_device *fbdev, int fbnum, + unsigned long size) +{ + struct omapfb_info *ofbi; + struct omapfb_mem_region *rg; + unsigned long paddr; + void *vaddr; + + size = PAGE_ALIGN(size); + + ofbi = FB2OFB(fbdev->fbs[fbnum]); + rg = &ofbi->region; + memset(rg, 0, sizeof(*rg)); + + DBG("allocating %lu bytes for fb %d\n", + size, ofbi->id); + + vaddr = omap_vram_alloc(OMAPFB_MEMTYPE_SDRAM, size, &paddr); + DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr); + + if (vaddr == NULL) { + dev_err(fbdev->dev, + "failed to allocate framebuffer\n"); + return -ENOMEM; + } + + rg->paddr = paddr; + rg->vaddr = vaddr; + rg->size = size; + rg->alloc = 1; + + return 0; +} + +int omapfb_realloc_fbmem(struct omapfb2_device *fbdev, int fbnum, + unsigned long size) +{ + struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[fbnum]); + struct omapfb_mem_region *rg = &ofbi->region; + unsigned old_size = rg->size; + int r; + + size = PAGE_ALIGN(size); + + omapfb_free_fbmem(fbdev, fbnum); + + if (size == 0) + return 0; + + r = omapfb_alloc_fbmem(fbdev, fbnum, size); + + if (r) + omapfb_alloc_fbmem(fbdev, fbnum, old_size); + + return r; +} + +/* allocate fbmem using display resolution as reference */ +static int omapfb_alloc_fbmem_display(struct omapfb2_device *fbdev, int fbnum, + unsigned long def_vram) +{ + struct omapfb_info *ofbi; + struct omap_display *display; + int bytespp; + unsigned long size; + + ofbi = FB2OFB(fbdev->fbs[fbnum]); + display = fb2display(fbdev->fbs[fbnum]); + + if (!display) + return 0; + + switch (display->panel->bpp) { + case 16: + bytespp = 2; + break; + case 24: + case 32: + bytespp = 4; + break; + default: + bytespp = 4; + break; + } + + if (def_vram) + size = def_vram; + else + size = display->panel->timings.x_res * + display->panel->timings.y_res * + bytespp; + + return omapfb_alloc_fbmem(fbdev, fbnum, size); +} + +static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev) +{ + int i, r; + unsigned long vrams[10]; + + memset(vrams, 0, sizeof(vrams)); + + if (def_vram) { + char str[64]; + char *tok, *s; + + if (strlen(def_vram) > sizeof(str) - 1) { + dev_err(fbdev->dev, "Illegal vram parameters\n"); + return -EINVAL; + } + + strcpy(str, def_vram); + + s = str; + i = 0; + + while ((tok = strsep(&s, ","))) { + unsigned long size; + + size = memparse(tok, NULL); + + if (size == 0) { + dev_err(fbdev->dev, "illegal vram size\n"); + break; + } + + vrams[i++] = size; + } + } + + for (i = 0; i < fbdev->num_fbs; i++) { + /* allocate memory automatically only for fb0, or if + * excplicitly defined with vram option */ + if (i == 0 || vrams[i] != 0) { + r = omapfb_alloc_fbmem_display(fbdev, i, vrams[i]); + + if (r) + return r; + } + } + + for (i = 0; i < fbdev->num_fbs; i++) { + struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); + struct omapfb_mem_region *rg; + rg = &ofbi->region; + + DBG("region%d phys %08x virt %p size=%lu\n", + i, + rg->paddr, + rg->vaddr, + rg->size); + } + + return 0; +} + +/* initialize fb_info, var, fix to something sane based on the display */ +static int fbinfo_init(struct omapfb2_device *fbdev, struct fb_info *fbi) +{ + struct fb_var_screeninfo *var = &fbi->var; + struct fb_fix_screeninfo *fix = &fbi->fix; + struct omap_display *display = fb2display(fbi); + int r = 0; + + fbi->fbops = &omapfb_ops; + fbi->flags = FBINFO_FLAG_DEFAULT; + fbi->pseudo_palette = fbdev->pseudo_palette; + + strncpy(fix->id, MODULE_NAME, sizeof(fix->id)); + + var->nonstd = 0; + + if (display) { + var->xres = display->panel->timings.x_res; + var->yres = display->panel->timings.y_res; + var->xres_virtual = var->xres; + var->yres_virtual = var->yres; + /* var->rotate = def_rotate; */ + + switch (display->panel->bpp) { + case 16: + var->bits_per_pixel = 16; + break; + case 18: + var->bits_per_pixel = 16; + break; + case 24: + var->bits_per_pixel = 32; + break; + default: + dev_err(fbdev->dev, "illegal display bpp\n"); + return -EINVAL; + } + } + + r = check_fb_var(fbi, var); + if (r) + goto err; + + set_fb_fix(fbi); + +#ifdef DEBUG + if (omapfb_debug) + fill_fb(FB2OFB(fbi)->region.vaddr, fbi); +#endif +err: + return r; +} + +static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi) +{ + fb_dealloc_cmap(&fbi->cmap); +} + + +static void omapfb_free_resources(struct omapfb2_device *fbdev) +{ + int i; + + DBG("free_resources\n"); + + if (fbdev == NULL) + return; + + for (i = 0; i < fbdev->num_fbs; i++) + unregister_framebuffer(fbdev->fbs[i]); + + /* free the reserved fbmem */ + omapfb_free_all_fbmem(fbdev); + + for (i = 0; i < fbdev->num_fbs; i++) { + fbinfo_cleanup(fbdev, fbdev->fbs[i]); + framebuffer_release(fbdev->fbs[i]); + } + + for (i = 0; i < fbdev->num_displays; i++) { + if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED) + fbdev->displays[i]->disable(fbdev->displays[i]); + + omap_dss_put_display(fbdev->displays[i]); + } + + dev_set_drvdata(fbdev->dev, NULL); + kfree(fbdev); +} + +static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) +{ + int r, i; + + fbdev->num_fbs = 0; + + DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS); + + /* allocate fb_infos */ + for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) { + struct fb_info *fbi; + struct omapfb_info *ofbi; + + fbi = framebuffer_alloc(sizeof(struct omapfb_info), + fbdev->dev); + + if (fbi == NULL) { + dev_err(fbdev->dev, + "unable to allocate memory for plane info\n"); + return -ENOMEM; + } + + fbdev->fbs[i] = fbi; + + ofbi = FB2OFB(fbi); + ofbi->fbdev = fbdev; + ofbi->id = i; + fbdev->num_fbs++; + } + + DBG("fb_infos allocated\n"); + + /* assign overlays for the fbs */ + for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) { + struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); + + ofbi->overlays[0] = fbdev->overlays[i]; + ofbi->num_overlays = 1; + } + + /* allocate fb memories */ + r = omapfb_allocate_all_fbs(fbdev); + if (r) { + dev_err(fbdev->dev, "failed to allocate fbmem\n"); + return r; + } + + DBG("fbmems allocated\n"); + + /* setup fb_infos */ + for (i = 0; i < fbdev->num_fbs; i++) { + r = fbinfo_init(fbdev, fbdev->fbs[i]); + if (r) { + dev_err(fbdev->dev, "failed to setup fb_info\n"); + return r; + } + } + + DBG("fb_infos initialized\n"); + + for (i = 0; i < fbdev->num_fbs; i++) { + r = register_framebuffer(fbdev->fbs[i]); + if (r != 0) { + dev_err(fbdev->dev, + "registering framebuffer %d failed\n", i); + return r; + } + } + + DBG("framebuffers registered\n"); + + for (i = 0; i < fbdev->num_fbs; i++) { + r = omapfb_apply_changes(fbdev->fbs[i], 1); + if (r) + dev_err(fbdev->dev, "failed to change mode\n"); + } + + /* Enable fb0 */ + if (fbdev->num_fbs > 0) { + struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]); + + if (ofbi->num_overlays > 0 ) { + struct omap_overlay *ovl = ofbi->overlays[0]; + + ovl->enable(ovl, 1); + } + } + + DBG("create_framebuffers done\n"); + + return 0; +} + +int omapfb_mode_to_timings(const char *mode_str, + struct omap_video_timings *timings, unsigned *bpp) +{ + struct fb_info fbi; + struct fb_var_screeninfo var; + struct fb_ops fbops; + int r; + + /* this is quite a hack, but I wanted to use the modedb and for + * that we need fb_info and var, so we create dummy ones */ + + memset(&fbi, 0, sizeof(fbi)); + memset(&var, 0, sizeof(var)); + memset(&fbops, 0, sizeof(fbops)); + fbi.fbops = &fbops; + + r = fb_find_mode(&var, &fbi, mode_str, NULL, 0, NULL, 24); + + if (r != 0) { + timings->pixel_clock = PICOS2KHZ(var.pixclock); + timings->hfp = var.left_margin; + timings->hbp = var.right_margin; + timings->vfp = var.upper_margin; + timings->vbp = var.lower_margin; + timings->hsw = var.hsync_len; + timings->vsw = var.vsync_len; + timings->x_res = var.xres; + timings->y_res = var.yres; + + switch (var.bits_per_pixel) { + case 16: + *bpp = 16; + break; + case 24: + case 32: + default: + *bpp = 24; + break; + } + + return 0; + } else { + return -EINVAL; + } +} + +static int omapfb_probe(struct platform_device *pdev) +{ + struct omapfb2_device *fbdev = NULL; + int r = 0; + int i, t; + struct omap_overlay *ovl; + struct omap_display *def_display; + + DBG("omapfb_probe\n"); + + if (pdev->num_resources != 0) { + dev_err(&pdev->dev, "probed for an unknown device\n"); + r = -ENODEV; + goto err0; + } + + fbde... [truncated message content] |
From: Tomi V. <tom...@no...> - 2009-01-12 12:43:11
|
Signed-off-by: Tomi Valkeinen <tom...@no...> --- Documentation/arm/OMAP/DSS | 270 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 270 insertions(+), 0 deletions(-) create mode 100644 Documentation/arm/OMAP/DSS diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS new file mode 100644 index 0000000..011fee1 --- /dev/null +++ b/Documentation/arm/OMAP/DSS @@ -0,0 +1,270 @@ +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, but there are lots of small improvements +also. + +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 +- 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 + +Tested boards include: +- OMAP3 SDP board +- Beagle board +- N810 + +omap-dss driver +------------ + +The DSS driver does not itself have any support for Linux framebuffer, V4L or +such like the current ones, but it has an internal kernel API that upper level +drivers can use. + +The DSS driver models OMAP's overlays, overlay managers and displays in a +flexible way to enable non-common multi-display configuration. In addition to +modelling the hardware overlays, omap-dss supports virtual overlays and overlay +managers. These can be used when updating a display with CPU or system DMA. + +Panel and controller drivers +---------------------------- + +The drivers implement panel or controller specific functionality and are not +usually 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 +------------ + +V4L2 is being implemented in TI. + +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 SRAM/SDRAM that contains the + pixel data for the image. Framebuffer has width and height and color + depth. + - Overlay defines where the pixels are read from and where they go on the + screen. The overlay may be smaller than framebuffer, thus displaying only + part of the framebuffer. The position of the overlay may be changed if + the overlay is smaller than the display. + - Overlay manager combines the overlays in to one image and feeds them to + display. + - Display is the actual physical display device. + +A framebuffer can be connected to multiple overlays to show the same pixel data +on all of the overlays. Note that in this case the overlay input sizes must be +the same, but, in case of video overlays, the output size can be different. Any +framebuffer can be connected to any overlay. + +An overlay can be connected to one overlay manager. Also DISPC overlays can be +connected only to DISPC overlay managers, and virtual overlays can be only +connected to virtual overlays. + +An overlay manager can be connected to one display. There are certain +restrictions which kinds of displays an overlay manager can be connected: + + - DISPC TV overlay manager can be only connected to TV display. + - Virtual overlay managers can only be connected to DBI or DSI displays. + - DISPC LCD overlay manager can be connected to all displays, except TV + display. + +Sysfs +----- +The sysfs interface is a hack, but works for testing. I don't think sysfs +interface is the best for this in the final version, but I don't quite know +what would be the best interfaces for these things. + +In /sys/devices/platform/omapfb we have four files: framebuffers, +overlays, managers and displays. You can read them so see the current +setup, and change them by writing to it in the form of +"<item-id> <opt1>:<val1> <opt2>:<val2>..." + +"framebuffers" lists all framebuffers. Its format is: + <fb number> + p:<physical address, read only> + v:<virtual address, read only> + s:<size, read only> + t:<target overlay> + +"overlays" lists all overlays. Its format is: + <overlay name> + t:<target manager> + x:<xpos> + y:<ypos> + iw:<input width, read only> + ih:<input height, read only> + w:<output width> + h:<output height> + e:<enabled> + +"managers" lists all overlay managers. Its format is: + <manager name> + t:<target display> + +"displays" lists all displays. Its format is: + <display name> + e:<enabled> + u:<update mode> + t:<tear sync on/off> + h:<xres/hfp/hbp/hsw> + v:<yres/vfp/vbp/vsw> + p:<pix clock, in kHz> + m:<mode str, as in drivers/video/modedb.c:fb_find_mode> + +There is also a debug sysfs file at /sys/devices/platform/omap-dss/clk which +shows how DSS has configured the clocks. + +Examples +-------- + +In the example scripts "omapfb" is a symlink to /sys/devices/platform/omapfb/. + +Default setup on OMAP3 SDP +-------------------------- + +Here's the default setup on OMAP3 SDP board. All planes go to LCD. DVI +and TV-out are not in use. The columns from left to right are: +framebuffers, overlays, overlay managers, displays. Framebuffers are +handled by omapfb, and the rest by the DSS. + +FB0 --- GFX -\ DVI +FB1 --- VID1 --+- LCD ---- LCD +FB2 --- VID2 -/ TV ----- TV + +Switch from LCD to DVI +---------------------- + +dviline=`cat omapfb/displays |grep dvi` +w=`echo $dviline | cut -d " " -f 5 | cut -d ":" -f 2 | cut -d "/" -f 1` +h=`echo $dviline | cut -d " " -f 6 | cut -d ":" -f 2 | cut -d "/" -f 1` + +echo "lcd e:0" > omapfb/displays +echo "lcd t:none" > omapfb/managers +fbset -fb /dev/fb0 -xres $w -yres $h -vxres $w -vyres $h +# at this point you have to switch the dvi/lcd dip-switch from the omap board +echo "lcd t:dvi" > omapfb/managers +echo "dvi e:1" > omapfb/displays + +After this the configuration looks like: + +FB0 --- GFX -\ -- DVI +FB1 --- VID1 --+- LCD -/ LCD +FB2 --- VID2 -/ TV ----- TV + +Clone GFX overlay to LCD and TV +------------------------------- + +tvline=`cat /sys/devices/platform/omapfb/displays |grep tv` +w=`echo $tvline | cut -d " " -f 5 | cut -d ":" -f 2 | cut -d "/" -f 1` +h=`echo $tvline | cut -d " " -f 6 | cut -d ":" -f 2 | cut -d "/" -f 1` + +echo "1 t:none" > omapfb/framebuffers +echo "0 t:gfx,vid1" > omapfb/framebuffers +echo "gfx e:1" > omapfb/overlays +echo "vid1 t:tv w:$w h:$h e:1" > omapfb/overlays +echo "tv e:1" > omapfb/displays + +After this the configuration looks like (only relevant parts shown): + +FB0 +-- GFX ---- LCD ---- LCD + \- VID1 ---- TV ---- TV + +Misc notes +---------- + +OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator. If +that fails, it will fall back to dma_alloc_writecombine(). + +Using DSI DPLL to generate pixel clock it is possible produce the pixel clock +of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI. + +Arguments +--------- + +vram + - Amount of total VRAM to preallocate. For example, "10M". omapfb + allocates memory for framebuffers from VRAM. + +omapfb.video_mode + - Default video mode for default display. For example, + "800x400MR-24@60". See drivers/video/modedb.c + +omapfb.vram + - VRAM allocated for each framebuffer. Normally omapfb allocates vram + depending on the display size. With this you can manually allocate + more. For example "4M,3M" allocates 4M for fb0, 3M for fb1. + +omapfb.debug + - Enable debug printing. You have to have OMAPFB debug support enabled + in kernel config. + +omap-dss.def_disp + - Name of default display, to which all overlays will be connected. + Common examples are "lcd" or "tv". + +omap-dss.debug + - Enable debug printing. You have to have DSS debug support enabled in + kernel config. + +TODO +---- + +DSS locking + +Error checking +- Lots of checks are missing or implemented just as BUG() + +Rotate (external FB) +Rotate (VRFB) +Rotate (SMS) + +System DMA update for DSI +- Can be used for RGB16 and RGB24P modes. Probably not for RGB24U (how + to skip the empty byte?) + +Power management +- Context saving + +OMAP1 support +- Not sure if needed + |
From: Tomi V. <tom...@no...> - 2009-01-12 12:59:56
|
Signed-off-by: Tomi Valkeinen <tom...@no...> --- arch/arm/configs/dss_omap_3430sdp_defconfig | 1603 +++++++++++++++++++++++++++ arch/arm/mach-omap2/board-3430sdp.c | 215 +++- 2 files changed, 1809 insertions(+), 9 deletions(-) create mode 100644 arch/arm/configs/dss_omap_3430sdp_defconfig diff --git a/arch/arm/configs/dss_omap_3430sdp_defconfig b/arch/arm/configs/dss_omap_3430sdp_defconfig new file mode 100644 index 0000000..42d7f5e --- /dev/null +++ b/arch/arm/configs/dss_omap_3430sdp_defconfig @@ -0,0 +1,1603 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.28-omap1 +# Wed Jan 7 15:22:34 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_CLASSIC_RCU=y +CONFIG_FREEZER=y + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +CONFIG_ARCH_OMAP=y +# CONFIG_ARCH_MSM is not set + +# +# TI OMAP Implementations +# +CONFIG_ARCH_OMAP_OTG=y +# CONFIG_ARCH_OMAP1 is not set +# CONFIG_ARCH_OMAP2 is not set +CONFIG_ARCH_OMAP3=y + +# +# OMAP Feature Selections +# +# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set +# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set +CONFIG_OMAP_SMARTREFLEX=y +# CONFIG_OMAP_SMARTREFLEX_TESTING is not set +CONFIG_OMAP_RESET_CLOCKS=y +CONFIG_OMAP_BOOT_TAG=y +CONFIG_OMAP_BOOT_REASON=y +# CONFIG_OMAP_COMPONENT_VERSION is not set +# CONFIG_OMAP_GPIO_SWITCH is not set +CONFIG_OMAP_MUX=y +CONFIG_OMAP_MUX_DEBUG=y +CONFIG_OMAP_MUX_WARNINGS=y +# CONFIG_OMAP_MCBSP is not set +# CONFIG_OMAP_MMU_FWK is not set +# CONFIG_OMAP_MBOX_FWK is not set +# CONFIG_OMAP_MPU_TIMER is not set +CONFIG_OMAP_32K_TIMER=y +CONFIG_OMAP_32K_TIMER_HZ=128 +CONFIG_OMAP_DM_TIMER=y +CONFIG_OMAP_LL_DEBUG_UART1=y +# CONFIG_OMAP_LL_DEBUG_UART2 is not set +# CONFIG_OMAP_LL_DEBUG_UART3 is not set +CONFIG_OMAP_SERIAL_WAKE=y +CONFIG_OMAP2_DSS=m +CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y +# CONFIG_OMAP2_DSS_RFBI is not set +CONFIG_OMAP2_DSS_VENC=y +# CONFIG_OMAP2_DSS_SDI is not set +# CONFIG_OMAP2_DSS_DSI is not set +# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set +CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 +CONFIG_ARCH_OMAP34XX=y +CONFIG_ARCH_OMAP3430=y + +# +# OMAP Board Type +# +# CONFIG_MACH_OMAP_LDP is not set +CONFIG_MACH_OMAP_3430SDP=y +# CONFIG_MACH_OMAP3EVM is not set +# CONFIG_MACH_OMAP3_BEAGLE is not set +# CONFIG_MACH_OVERO is not set +# CONFIG_MACH_OMAP3_PANDORA is not set +CONFIG_OMAP_TICK_GPTIMER=1 + +# +# Boot options +# + +# +# Power management +# + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_V7=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_IFAR=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_HAS_TLS_REG=y +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PREEMPT is not set +CONFIG_HZ=128 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/home/user/buildroot ip=192.168.0.2:192.168.0.1:192.168.0.1:255.255.255.0:tgt:eth0:off rw console=ttyS2,115200n8" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_FREQ is not set +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +CONFIG_VFP=y +CONFIG_VFPv3=y +# CONFIG_NEON is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Power management options +# +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_SLEEP=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_APM_EMULATION is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +CONFIG_MTD_OMAP_NOR=y +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_ECC_SMC=y +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_OMAP2=y +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +CONFIG_MTD_ONENAND=y +CONFIG_MTD_ONENAND_VERIFY_WRITE=y +# CONFIG_MTD_ONENAND_GENERIC is not set +CONFIG_MTD_ONENAND_OMAP2=y +# CONFIG_MTD_ONENAND_OTP is not set +# CONFIG_MTD_ONENAND_2X_PROGRAM is not set +# CONFIG_MTD_ONENAND_SIM is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_ICS932S401 is not set +# CONFIG_OMAP_STI is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +CONFIG_SMC91X=y +# CONFIG_DM9000 is not set +# CONFIG_ENC28J60 is not set +# CONFIG_SMC911X is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +CONFIG_NETDEV_1000=y +CONFIG_NETDEV_10000=y + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +CONFIG_KEYBOARD_TWL4030=y +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=y +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC210X is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_OMAP=y +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_AT24 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_TPS65010 is not set +# CONFIG_TWL4030_MADC is not set +# CONFIG_TWL4030_PWRBUTTON is not set +# CONFIG_TWL4030_POWEROFF is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_LP5521 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_BITBANG is not set +CONFIG_SPI_OMAP24XX=y + +# +# SPI Protocol Masters +# +# CONFIG_SPI_AT25 is not set +# CONFIG_SPI_TSC210X is not set +# CONFIG_SPI_TSC2301 is not set +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +CONFIG_GPIO_TWL4030=y + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_OMAP_WATCHDOG=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +CONFIG_TWL4030_CORE=y +# CONFIG_TWL4030_POWER is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +CONFIG_DAB=y +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +CONFIG_VIDEO_OUTPUT_CONTROL=m +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=m +CONFIG_FB_CFB_COPYAREA=m +CONFIG_FB_CFB_IMAGEBLIT=m +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_OMAP_LCD_VGA is not set +CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2 +CONFIG_FB_OMAP2=m +CONFIG_FB_OMAP2_DEBUG=y +# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set +CONFIG_FB_OMAP2_NUM_FBS=3 + +# +# OMAP2/3 Display Device Drivers +# +CONFIG_PANEL_GENERIC=m +CONFIG_PANEL_SHARP_LS037V7DW01=m +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set +# CONFIG_LOGO is not set +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +CONFIG_HID_COMPAT=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_BRIGHT=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DELL=y +CONFIG_HID_EZKEY=y +CONFIG_HID_GYRATION=y +CONFIG_HID_LOGITECH=y +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +# CONFIG_PANTHERLORD_FF is not set +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SONY=y +CONFIG_HID_SUNPLUS=y +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_ZEROPLUS_FF is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +CONFIG_USB_DEBUG=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_SUSPEND=y +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_EHCI_HCD=m +CONFIG_OMAP_EHCI_PHY_MODE=y +# CONFIG_OMAP_EHCI_TLL_MODE is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_SOC=y + +# +# OMAP 343x high speed USB support +# +# CONFIG_USB_MUSB_HOST is not set +# CONFIG_USB_MUSB_PERIPHERAL is not set +CONFIG_USB_MUSB_OTG=y +CONFIG_USB_GADGET_MUSB_HDRC=y +CONFIG_USB_MUSB_HDRC_HCD=y +# CONFIG_MUSB_PIO_ONLY is not set +CONFIG_USB_INVENTRA_DMA=y +# CONFIG_USB_TI_CPPI_DMA is not set +# CONFIG_USB_MUSB_DEBUG is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; +# + +# +# see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DEBUG=y +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +CONFIG_USB_TEST=y +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DEBUG=y +CONFIG_USB_GADGET_DEBUG_FILES=y +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +CONFIG_USB_ZERO=m +# CONFIG_USB_ZERO_HNPTEST is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_ISP1301_OMAP is not set +CONFIG_TWL4030_USB=y +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +CONFIG_MMC_OMAP_HS=m +# CONFIG_MMC_SPI is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +CONFIG_RTC_DRV_TWL4030=y +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_DMADEVICES is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set + +# +# CBUS support +# +# CONFIG_CBUS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +CONFIG_PRINT_QUOTA_WARNING=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +# CONFIG_SUNRPC_REGISTER_V4 is not set +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_HAVE_FUNCTION_TRACER=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index ade186b..529322f 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -39,6 +39,7 @@ #include <mach/keypad.h> #include <mach/dma.h> #include <mach/gpmc.h> +#include <mach/display.h> #include <asm/io.h> #include <asm/delay.h> @@ -238,14 +239,214 @@ static struct spi_board_info sdp3430_spi_board_info[] __initdata = { }, }; -static struct platform_device sdp3430_lcd_device = { - .name = "sdp2430_lcd", - .id = -1, + +#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91 +#define SDP2430_LCD_PANEL_ENABLE_GPIO 154 +#if 0 +#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 24 +#define SDP3430_LCD_PANEL_ENABLE_GPIO 28 +#else +#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 8 +#define SDP3430_LCD_PANEL_ENABLE_GPIO 5 +#endif + +#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 sdp3430_display_init(void) +{ + int r; + + enable_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO; + backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO; + + r = gpio_request(enable_gpio, "LCD reset"); + if (r) { + printk(KERN_ERR "failed to get LCD reset GPIO\n"); + goto err0; + } + + r = gpio_request(backlight_gpio, "LCD Backlight"); + 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 sdp3430_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 (omap_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 sdp3430_panel_disable_lcd(struct omap_display *display) +{ + lcd_enabled = 0; + + gpio_direction_output(enable_gpio, 0); + gpio_direction_output(backlight_gpio, 0); + + if (omap_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 sdp3430_display_data = { + .type = OMAP_DISPLAY_TYPE_DPI, + .name = "lcd", + .panel_name = "sharp-ls037v7dw01", + .u.dpi.data_lines = 16, + .panel_enable = sdp3430_panel_enable_lcd, + .panel_disable = sdp3430_panel_disable_lcd, +}; + +static int sdp3430_panel_enable_dvi(struct omap_display *display) +{ + if (lcd_enabled) { + printk(KERN_ERR "cannot enable DVI, LCD is enabled\n"); + return -EINVAL; + } + + if (omap_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 sdp3430_panel_disable_dvi(struct omap_display *display) +{ + dvi_enabled = 0; + + if (omap_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 sdp3430_display_data_dvi = { + .type = OMAP_DISPLAY_TYPE_DPI, + .name = "dvi", + .panel_name = "panel-generic", + .u.dpi.data_lines = 24, + .panel_enable = sdp3430_panel_enable_dvi, + .panel_disable = sdp3430_panel_disable_dvi, }; +static int sdp3430_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 sdp3430_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 sdp3430_display_data_tv = { + .type = OMAP_DISPLAY_TYPE_VENC, + .name = "tv", + .u.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, + .panel_enable = sdp3430_panel_enable_tv, + .panel_disable = sdp3430_panel_disable_tv, +}; + +static struct omap_dss_platform_data sdp3430_dss_data = { + .num_displays = 3, + .displays = { + &sdp3430_display_data, + &sdp3430_display_data_dvi, + &sdp3430_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) @@ -292,13 +493,8 @@ 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 }, }; static int sdp3430_batt_table[] = { @@ -481,6 +677,7 @@ static void __init omap_3430sdp_init(void) usb_musb_init(); usb_ehci_init(); twl4030_mmc_init(mmc); + sdp3430_display_init(); } static void __init omap_3430sdp_map_io(void) |
From: David B. <da...@pa...> - 2009-01-13 11:15:31
|
On Monday 12 January 2009, Tomi Valkeinen wrote: > arch/arm/configs/dss_omap_3430sdp_defconfig | 1603 +++++++++++++++++++++++++++ Likewise. In fact, defconfig updates are a lot nicer as patches that don't touch source code... |
From: Tomi V. <tom...@no...> - 2009-01-12 13:06:16
|
Signed-off-by: Tomi Valkeinen <tom...@no...> --- arch/arm/mach-omap2/board-n800.c | 214 ++++++++++++++--- drivers/video/omap2/Kconfig | 10 + drivers/video/omap2/Makefile | 3 drivers/video/omap2/ctrl-blizzard.c | 279 ++++++++++++++++++++++ drivers/video/omap2/panel-n800.c | 437 +++++++++++++++++++++++++++++++++++ 5 files changed, 905 insertions(+), 38 deletions(-) create mode 100644 drivers/video/omap2/ctrl-blizzard.c create mode 100644 drivers/video/omap2/panel-n800.c diff --git a/arch/arm/mach-omap2/board-n800.c b/arch/arm/mach-omap2/board-n800.c index b38b295..ffa5aad 100644 --- a/arch/arm/mach-omap2/board-n800.c +++ b/arch/arm/mach-omap2/board-n800.c @@ -40,6 +40,7 @@ #include <mach/gpio-switch.h> #include <mach/omapfb.h> #include <mach/blizzard.h> +#include <mach/display.h> #include <../drivers/cbus/tahvo.h> #include <../drivers/media/video/tcm825x.h> @@ -156,23 +157,175 @@ static struct omap_uart_config n800_uart_config __initdata = { #include "../../../drivers/cbus/retu.h" -static struct omap_fbmem_config n800_fbmem0_config __initdata = { - .size = 752 * 1024, +static struct omap_tmp105_config n800_tmp105_config __initdata = { + .tmp105_irq_pin = 125, + .set_power = n800_tmp105_set_power, }; -static struct omap_fbmem_config n800_fbmem1_config __initdata = { - .size = 752 * 1024, -}; -static struct omap_fbmem_config n800_fbmem2_config __initdata = { - .size = 752 * 1024, + + +/* DISPLAY */ +static struct { + struct clk *sys_ck; +} blizzard; + +static int blizzard_get_clocks(void) +{ + blizzard.sys_ck = clk_get(0, "osc_ck"); + if (IS_ERR(blizzard.sys_ck)) { + printk(KERN_ERR "can't get Blizzard clock\n"); + return PTR_ERR(blizzard.sys_ck); + } + return 0; +} + +static unsigned long blizzard_get_clock_rate(void) +{ + return clk_get_rate(blizzard.sys_ck); +} + +static int n800_pn800_enable(struct omap_display *display) +{ + if (display->hw_config.panel_reset_gpio != -1) { + printk("enabling panel gpio\n"); + gpio_direction_output(display->hw_config.panel_reset_gpio, 1); + } + + return 0; +} + +static void n800_pn800_disable(struct omap_display *display) +{ + if (display->hw_config.panel_reset_gpio != -1) { + printk("disabling panel gpio\n"); + gpio_direction_output(display->hw_config.panel_reset_gpio, 0); + msleep(120); + } +} + +static int n800_blizzard_enable(struct omap_display *display) +{ + printk("enabling bliz powers\n"); + + /* Vcore to 1.475V */ + tahvo_set_clear_reg_bits(0x07, 0, 0xf); + msleep(10); + + clk_enable(blizzard.sys_ck); + + if (display->hw_config.ctrl_reset_gpio != -1) + gpio_direction_output(display->hw_config.ctrl_reset_gpio, 1); + + printk("osc_ck %lu\n", blizzard_get_clock_rate()); + + return 0; +} + +static void n800_blizzard_disable(struct omap_display *display) +{ + printk("disabling bliz powers\n"); + + if (display->hw_config.ctrl_reset_gpio != -1) + gpio_direction_output(display->hw_config.ctrl_reset_gpio, 0); + + clk_disable(blizzard.sys_ck); + + /* Vcore to 1.005V */ + tahvo_set_clear_reg_bits(0x07, 0xf, 0); +} + +static int n800_set_backlight_level(struct omap_display *display, int level) +{ + return 0; +} + +static struct omap_display_data n800_dsi_display_data = { + .type = OMAP_DISPLAY_TYPE_DBI, + .name = "lcd", + .ctrl_name = "ctrl-blizzard", + .panel_name = "panel-pn800", + .panel_reset_gpio = -1, + .ctrl_reset_gpio = N800_BLIZZARD_POWERDOWN_GPIO, + .panel_enable = n800_pn800_enable, + .panel_disable = n800_pn800_disable, + .ctrl_enable = n800_blizzard_enable, + .ctrl_disable = n800_blizzard_disable, + .set_backlight = n800_set_backlight_level, + .u.rfbi = { + .channel = 0, + /* 8 for cmd mode, 16 for pixel data. ctrl-blizzard handles switching */ + .data_lines = 8, + }, + .priv = 0, // XXX used for panel datalines +}; +static struct omap_dss_platform_data n800_dss_data = { + .num_displays = 1, + .displays = { + &n800_dsi_display_data, + }, }; -static struct omap_tmp105_config n800_tmp105_config __initdata = { - .tmp105_irq_pin = 125, - .set_power = n800_tmp105_set_power, +static struct platform_device n800_dss_device = { + .name = "omap-dss", + .id = -1, + .dev = { + .platform_data = &n800_dss_data, + }, }; +static void __init n800_display_init(void) +{ + int r; + const struct omap_lcd_config *conf; + + conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); + if (conf != NULL) { + n800_dsi_display_data.panel_reset_gpio = conf->nreset_gpio; + n800_dsi_display_data.priv = (void*)(u32)conf->data_lines; // XXX + //printk("\n\nTULI %d\n\n", conf->data_lines); + } else { + printk("\n\nEI TULLU MIOTÄÄÄ\n\n"); + } + + blizzard_get_clocks(); + clk_enable(blizzard.sys_ck); // XXX always enable + + //omapfb_set_ctrl_platform_data(&n800_blizzard_data); + // + if (n800_dsi_display_data.ctrl_reset_gpio != -1) { + r = gpio_request(n800_dsi_display_data.ctrl_reset_gpio, + "Blizzard pd"); + if (r < 0) { + n800_dsi_display_data.ctrl_reset_gpio = -1; + printk(KERN_ERR "Unable to get Blizzard GPIO\n"); + } else { + gpio_direction_output(n800_dsi_display_data.ctrl_reset_gpio, + 1); + // XXX always enable + } + } + + if (n800_dsi_display_data.panel_reset_gpio != -1) { + r = gpio_request(n800_dsi_display_data.panel_reset_gpio, + "panel reset"); + if (r < 0) { + n800_dsi_display_data.panel_reset_gpio = -1; + printk(KERN_ERR "Unable to get pn800 GPIO\n"); + } else { + gpio_direction_output(n800_dsi_display_data.panel_reset_gpio, + 1); + // XXX always enable + } + } +} + +/* DISPLAY END */ + + + + + static void mipid_shutdown(struct mipid_platform_data *pdata) { if (pdata->nreset_gpio != -1) { @@ -186,6 +339,7 @@ static struct mipid_platform_data n800_mipid_platform_data = { .shutdown = mipid_shutdown, }; +#if 0 static void __init mipid_dev_init(void) { const struct omap_lcd_config *conf; @@ -196,26 +350,9 @@ static void __init mipid_dev_init(void) n800_mipid_platform_data.data_lines = conf->data_lines; } } +#endif -static struct { - struct clk *sys_ck; -} blizzard; - -static int blizzard_get_clocks(void) -{ - blizzard.sys_ck = clk_get(0, "osc_ck"); - if (IS_ERR(blizzard.sys_ck)) { - printk(KERN_ERR "can't get Blizzard clock\n"); - return PTR_ERR(blizzard.sys_ck); - } - return 0; -} - -static unsigned long blizzard_get_clock_rate(struct device *dev) -{ - return clk_get_rate(blizzard.sys_ck); -} - +#if 0 static void blizzard_enable_clocks(int enable) { if (enable) @@ -260,14 +397,12 @@ static void __init blizzard_dev_init(void) gpio_direction_output(N800_BLIZZARD_POWERDOWN_GPIO, 1); blizzard_get_clocks(); - omapfb_set_ctrl_platform_data(&n800_blizzard_data); + //omapfb_set_ctrl_platform_data(&n800_blizzard_data); } +#endif static struct omap_board_config_kernel n800_config[] __initdata = { { OMAP_TAG_UART, &n800_uart_config }, - { OMAP_TAG_FBMEM, &n800_fbmem0_config }, - { OMAP_TAG_FBMEM, &n800_fbmem1_config }, - { OMAP_TAG_FBMEM, &n800_fbmem2_config }, { OMAP_TAG_TMP105, &n800_tmp105_config }, }; @@ -374,7 +509,7 @@ static struct omap2_mcspi_device_config tsc2005_mcspi_config = { static struct spi_board_info n800_spi_board_info[] __initdata = { { - .modalias = "lcd_mipid", + .modalias = "panel-n800", .bus_num = 1, .chip_select = 1, .max_speed_hz = 4000000, @@ -399,7 +534,7 @@ static struct spi_board_info n800_spi_board_info[] __initdata = { static struct spi_board_info n810_spi_board_info[] __initdata = { { - .modalias = "lcd_mipid", + .modalias = "panel-n800", .bus_num = 1, .chip_select = 1, .max_speed_hz = 4000000, @@ -567,6 +702,7 @@ static struct platform_device *n800_devices[] __initdata = { #if defined(CONFIG_CBUS_RETU) && defined(CONFIG_LEDS_OMAP_PWM) &n800_keypad_led_device, #endif + &n800_dss_device, }; #ifdef CONFIG_MENELAUS @@ -689,9 +825,10 @@ void __init nokia_n800_common_init(void) if (machine_is_nokia_n810()) i2c_register_board_info(2, n810_i2c_board_info_2, ARRAY_SIZE(n810_i2c_board_info_2)); - - mipid_dev_init(); - blizzard_dev_init(); + + //mipid_dev_init(); + //blizzard_dev_init(); + n800_display_init(); } static void __init nokia_n800_init(void) @@ -712,6 +849,7 @@ void __init nokia_n800_map_io(void) omap_board_config_size = ARRAY_SIZE(n800_config); omap2_set_globals_242x(); + omap2_set_sdram_vram(800 * 480 * 2 * 3, 0); omap2_map_common_io(); } diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig index b54c955..4e9211e 100644 --- a/drivers/video/omap2/Kconfig +++ b/drivers/video/omap2/Kconfig @@ -49,4 +49,14 @@ config PANEL_SHARP_LS037V7DW01 help LCD Panel used in TI's SDP3430 and EVM boards +config PANEL_N800 + tristate "panel n800" + help + N800 LCD + +config CTRL_BLIZZARD + tristate "blizzard ctrl" + help + Blizzard Ctrl + endmenu diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile index fe6858e..7727f9c 100644 --- a/drivers/video/omap2/Makefile +++ b/drivers/video/omap2/Makefile @@ -3,3 +3,6 @@ omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o + +obj-$(CONFIG_CTRL_BLIZZARD) += ctrl-blizzard.o +obj-$(CONFIG_PANEL_N800) += panel-n800.o diff --git a/drivers/video/omap2/ctrl-blizzard.c b/drivers/video/omap2/ctrl-blizzard.c new file mode 100644 index 0000000..e1e5569 --- /dev/null +++ b/drivers/video/omap2/ctrl-blizzard.c @@ -0,0 +1,279 @@ + +//#define DEBUG + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/err.h> + +#include <mach/display.h> +#include <mach/dma.h> + +#ifdef DEBUG +#define DBG(format, ...) printk(KERN_DEBUG "Blizzard: " format, ## __VA_ARGS__) +#else +#define DBG(format, ...) +#endif + +#define BLIZZARD_REV_CODE 0x00 +#define BLIZZARD_CONFIG 0x02 +#define BLIZZARD_PLL_DIV 0x04 +#define BLIZZARD_PLL_LOCK_RANGE 0x06 +#define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08 +#define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a +#define BLIZZARD_PLL_MODE 0x0c +#define BLIZZARD_CLK_SRC 0x0e +#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10 +#define BLIZZARD_MEM_BANK0_STATUS 0x14 +#define BLIZZARD_PANEL_CONFIGURATION 0x28 +#define BLIZZARD_HDISP 0x2a +#define BLIZZARD_HNDP 0x2c +#define BLIZZARD_VDISP0 0x2e +#define BLIZZARD_VDISP1 0x30 +#define BLIZZARD_VNDP 0x32 +#define BLIZZARD_HSW 0x34 +#define BLIZZARD_VSW 0x38 +#define BLIZZARD_DISPLAY_MODE 0x68 +#define BLIZZARD_INPUT_WIN_X_START_0 0x6c +#define BLIZZARD_DATA_SOURCE_SELECT 0x8e +#define BLIZZARD_DISP_MEM_DATA_PORT 0x90 +#define BLIZZARD_DISP_MEM_READ_ADDR0 0x92 +#define BLIZZARD_POWER_SAVE 0xE6 +#define BLIZZARD_NDISP_CTRL_STATUS 0xE8 + +/* Data source select */ +/* For S1D13745 */ +#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00 +#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01 +#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04 +#define BLIZZARD_SRC_DISABLE_OVERLAY 0x05 +/* For S1D13744 */ +#define BLIZZARD_SRC_WRITE_LCD 0x00 +#define BLIZZARD_SRC_BLT_LCD 0x06 + +#define BLIZZARD_COLOR_RGB565 0x01 +#define BLIZZARD_COLOR_YUV420 0x09 + +#define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */ +#define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */ + +#define BLIZZARD_AUTO_UPDATE_TIME (HZ / 20) + + + +static struct { + int version; +} blizzard; + + +static inline void blizzard_cmd(u8 cmd) +{ + omap_rfbi_write_command(&cmd, 1); +} + +static inline void blizzard_write(u8 cmd, const u8 *buf, int len) +{ + omap_rfbi_write_command(&cmd, 1); + omap_rfbi_write_data(buf, len); +} + +static inline void blizzard_read(u8 cmd, u8 *buf, int len) +{ + omap_rfbi_write_command(&cmd, 1); + omap_rfbi_read_data(buf, len); +} + +static u8 blizzard_read_reg(u8 cmd) +{ + u8 data; + blizzard_read(cmd, &data, 1); + return data; +} + +static int blizzard_ctrl_init(struct omap_display *display) +{ + DBG("blizzard_ctrl_init\n"); + + return 0; +} + + +static int blizzard_ctrl_enable(struct omap_display *display) +{ + int r = 0; + u8 rev, conf; + + DBG("blizzard_ctrl_enable\n"); + + if (display->hw_config.ctrl_enable) { + r = display->hw_config.ctrl_enable(display); + if (r) + return r; + } + + msleep(100); + + rev = blizzard_read_reg(BLIZZARD_CLK_SRC); + printk("CLK_SRC %x\n", rev); + + rev = blizzard_read_reg(BLIZZARD_PLL_DIV); + printk("PLLDIV %x\n", rev); + + rev = blizzard_read_reg(BLIZZARD_REV_CODE); + conf = blizzard_read_reg(BLIZZARD_CONFIG); + + printk("rev %x, conf %x\n", rev, conf); + + switch (rev & 0xfc) { + case 0x9c: + blizzard.version = BLIZZARD_VERSION_S1D13744; + pr_info("omapfb: s1d13744 LCD controller rev %d " + "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); + break; + case 0xa4: + blizzard.version = BLIZZARD_VERSION_S1D13745; + pr_info("omapfb: s1d13745 LCD controller rev %d " + "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); + break; + default: + printk("invalid s1d1374x revision %02x\n", + rev); + r = -ENODEV; + } + + return r; +} + +static void blizzard_ctrl_disable(struct omap_display *display) +{ + DBG("blizzard_ctrl_disable\n"); + + if (display->hw_config.ctrl_disable) + display->hw_config.ctrl_disable(display); +} + +int rfbi_configure(int rfbi_module, int bpp, int lines); + +static void blizzard_ctrl_setup_update(struct omap_display *display, + int x, int y, int w, int h) +{ + u8 tmp[18]; + int x_end, y_end; + + DBG("blizzard_ctrl_setup_update\n"); + + x_end = x + w - 1; + y_end = y + h - 1; + + tmp[0] = x; + tmp[1] = x >> 8; + tmp[2] = y; + tmp[3] = y >> 8; + tmp[4] = x_end; + tmp[5] = x_end >> 8; + tmp[6] = y_end; + tmp[7] = y_end >> 8; + + /* scaling? */ + tmp[8] = x; + tmp[9] = x >> 8; + tmp[10] = y; + tmp[11] = y >> 8; + tmp[12] = x_end; + tmp[13] = x_end >> 8; + tmp[14] = y_end; + tmp[15] = y_end >> 8; + + tmp[16] = BLIZZARD_COLOR_RGB565; //color_mode; + + if (blizzard.version == BLIZZARD_VERSION_S1D13745) + tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND; + else + tmp[17] = blizzard.version == BLIZZARD_VERSION_S1D13744 ? + BLIZZARD_SRC_WRITE_LCD : + BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE; + + rfbi_configure(display->hw_config.u.rfbi.channel, + 16, + 8); + + blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18); + + rfbi_configure(display->hw_config.u.rfbi.channel, + 16, + 16); +} + +static int blizzard_ctrl_enable_te(struct omap_display *display, int enable) +{ + return 0; +} + +static int blizzard_ctrl_rotate(struct omap_display *display, int rotate) +{ + return 0; +} + +static int blizzard_ctrl_mirror(struct omap_display *display, int enable) +{ + return 0; +} + +static int blizzard_run_test(struct omap_display *display, int test_num) +{ + return 0; +} + +static struct omap_ctrl blizzard_ctrl = { + .owner = THIS_MODULE, + .name = "ctrl-blizzard", + .init = blizzard_ctrl_init, + .enable = blizzard_ctrl_enable, + .disable = blizzard_ctrl_disable, + .setup_update = blizzard_ctrl_setup_update, + .enable_te = blizzard_ctrl_enable_te, + .rotate = blizzard_ctrl_rotate, + .mirror = blizzard_ctrl_mirror, + .run_test = blizzard_run_test, + .pixel_size = 16, + + .timings = { + .cs_on_time = 0, + + .we_on_time = 9000, + .we_off_time = 18000, + .we_cycle_time = 36000, + + .re_on_time = 9000, + .re_off_time = 27000, + .re_cycle_time = 36000, + + .access_time = 27000, + .cs_off_time = 36000, + + .cs_pulse_width = 0, + }, +}; + + +static int __init blizzard_init(void) +{ + DBG("blizzard_init\n"); + omap_dss_register_ctrl(&blizzard_ctrl); + return 0; +} + +static void __exit blizzard_exit(void) +{ + DBG("blizzard_exit\n"); + + omap_dss_unregister_ctrl(&blizzard_ctrl); +} + +module_init(blizzard_init); +module_exit(blizzard_exit); + +MODULE_AUTHOR("Tomi Valkeinen <tom...@no...>"); +MODULE_DESCRIPTION("Blizzard Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/omap2/panel-n800.c b/drivers/video/omap2/panel-n800.c new file mode 100644 index 0000000..3ae0a16 --- /dev/null +++ b/drivers/video/omap2/panel-n800.c @@ -0,0 +1,437 @@ + +/*#define DEBUG*/ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/spi/spi.h> +#include <linux/jiffies.h> +#include <linux/sched.h> +#include <linux/backlight.h> +#include <linux/fb.h> + +#include <mach/display.h> +#include <mach/dma.h> + +#define MIPID_CMD_READ_DISP_ID 0x04 +#define MIPID_CMD_READ_RED 0x06 +#define MIPID_CMD_READ_GREEN 0x07 +#define MIPID_CMD_READ_BLUE 0x08 +#define MIPID_CMD_READ_DISP_STATUS 0x09 +#define MIPID_CMD_RDDSDR 0x0F +#define MIPID_CMD_SLEEP_IN 0x10 +#define MIPID_CMD_SLEEP_OUT 0x11 +#define MIPID_CMD_DISP_OFF 0x28 +#define MIPID_CMD_DISP_ON 0x29 + +#define MIPID_VER_LPH8923 3 +#define MIPID_VER_LS041Y3 4 + +#define MIPID_ESD_CHECK_PERIOD msecs_to_jiffies(5000) + +#ifdef DEBUG +#define DBG(format, ...) printk(KERN_DEBUG "PN800: " format, ## __VA_ARGS__) +#else +#define DBG(format, ...) +#endif + +struct pn800_device { + struct backlight_device *bl_dev; + int enabled; + int model; + int revision; + u8 display_id[3]; + unsigned int saved_bklight_level; + unsigned long hw_guard_end; /* next value of jiffies + when we can issue the + next sleep in/out command */ + unsigned long hw_guard_wait; /* max guard time in jiffies */ + + struct spi_device *spi; + struct mutex mutex; + struct omap_panel panel; + struct omap_display *display; +}; + + +static void pn800_transfer(struct pn800_device *md, int cmd, + const u8 *wbuf, int wlen, u8 *rbuf, int rlen) +{ + struct spi_message m; + struct spi_transfer *x, xfer[4]; + u16 w; + int r; + + BUG_ON(md->spi == NULL); + + spi_message_init(&m); + + memset(xfer, 0, sizeof(xfer)); + x = &xfer[0]; + + cmd &= 0xff; + x->tx_buf = &cmd; + x->bits_per_word = 9; + x->len = 2; + spi_message_add_tail(x, &m); + + if (wlen) { + x++; + x->tx_buf = wbuf; + x->len = wlen; + x->bits_per_word = 9; + spi_message_add_tail(x, &m); + } + + if (rlen) { + x++; + x->rx_buf = &w; + x->len = 1; + spi_message_add_tail(x, &m); + + if (rlen > 1) { + /* Arrange for the extra clock before the first + * data bit. + */ + x->bits_per_word = 9; + x->len = 2; + + x++; + x->rx_buf = &rbuf[1]; + x->len = rlen - 1; + spi_message_add_tail(x, &m); + } + } + + r = spi_sync(md->spi, &m); + if (r < 0) + dev_dbg(&md->spi->dev, "spi_sync %d\n", r); + + if (rlen) + rbuf[0] = w & 0xff; +} + +static inline void pn800_cmd(struct pn800_device *md, int cmd) +{ + pn800_transfer(md, cmd, NULL, 0, NULL, 0); +} + +static inline void pn800_write(struct pn800_device *md, + int reg, const u8 *buf, int len) +{ + pn800_transfer(md, reg, buf, len, NULL, 0); +} + +static inline void pn800_read(struct pn800_device *md, + int reg, u8 *buf, int len) +{ + pn800_transfer(md, reg, NULL, 0, buf, len); +} + +static void set_data_lines(struct pn800_device *md, int data_lines) +{ + u16 par; + + switch (data_lines) { + case 16: + par = 0x150; + break; + case 18: + par = 0x160; + break; + case 24: + par = 0x170; + break; + } + pn800_write(md, 0x3a, (u8 *)&par, 2); +} + +static void send_init_string(struct pn800_device *md) +{ + u16 initpar[] = { 0x0102, 0x0100, 0x0100 }; + int data_lines; + + pn800_write(md, 0xc2, (u8 *)initpar, sizeof(initpar)); + + data_lines = (int)md->display->hw_config.priv; // XXX + + set_data_lines(md, data_lines); +} + +static void hw_guard_start(struct pn800_device *md, int guard_msec) +{ + md->hw_guard_wait = msecs_to_jiffies(guard_msec); + md->hw_guard_end = jiffies + md->hw_guard_wait; +} + +static void hw_guard_wait(struct pn800_device *md) +{ + unsigned long wait = md->hw_guard_end - jiffies; + + if ((long)wait > 0 && wait <= md->hw_guard_wait) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(wait); + } +} + +static void set_sleep_mode(struct pn800_device *md, int on) +{ + int cmd, sleep_time = 50; + + if (on) + cmd = MIPID_CMD_SLEEP_IN; + else + cmd = MIPID_CMD_SLEEP_OUT; + hw_guard_wait(md); + pn800_cmd(md, cmd); + hw_guard_start(md, 120); + /* + * When we enable the panel, it seems we _have_ to sleep + * 120 ms before sending the init string. When disabling the + * panel we'll sleep for the duration of 2 frames, so that the + * controller can still provide the PCLK,HS,VS signals. */ + if (!on) + sleep_time = 120; + msleep(sleep_time); +} + +static void set_display_state(struct pn800_device *md, int enabled) +{ + int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF; + + pn800_cmd(md, cmd); +} + +static int panel_enabled(struct pn800_device *md) +{ + u32 disp_status; + int enabled; + + pn800_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4); + disp_status = __be32_to_cpu(disp_status); + enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10)); + dev_dbg(&md->spi->dev, + "LCD panel %s enabled by bootloader (status 0x%04x)\n", + enabled ? "" : "not ", disp_status); + DBG("status %#08x\n", disp_status); + return enabled; +} + +static int panel_detect(struct pn800_device *md) +{ + pn800_read(md, MIPID_CMD_READ_DISP_ID, md->display_id, 3); + dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n", + md->display_id[0], md->display_id[1], md->display_id[2]); + + switch (md->display_id[0]) { + case 0x45: + md->model = MIPID_VER_LPH8923; + md->panel.name = "lph8923"; + break; + case 0x83: + md->model = MIPID_VER_LS041Y3; + md->panel.name = "ls041y3"; + //md->esd_check = ls041y3_esd_check; + break; + default: + md->panel.name = "unknown"; + dev_err(&md->spi->dev, "invalid display ID\n"); + return -ENODEV; + } + + md->revision = md->display_id[1]; + pr_info("omapfb: %s rev %02x LCD detected\n", + md->panel.name, md->revision); + + return 0; +} + + + +static int pn800_panel_enable(struct omap_display *display) +{ + int r; + struct pn800_device *md = + (struct pn800_device *)display->panel->priv; + + DBG("pn800_panel_enable\n"); + + mutex_lock(&md->mutex); + + if (display->hw_config.panel_enable) + display->hw_config.panel_enable(display); + + msleep(50); // wait for power up + + r = panel_detect(md); + if (r) { + mutex_unlock(&md->mutex); + return r; + } + + md->enabled = panel_enabled(md); + + if (md->enabled) { + DBG("panel already enabled\n"); + ; /*pn800_esd_start_check(md);*/ + } else { + ; /*md->saved_bklight_level = pn800_get_bklight_level(panel);*/ + } + + + if (md->enabled) { + mutex_unlock(&md->mutex); + return 0; + } + + set_sleep_mode(md, 0); + md->enabled = 1; + send_init_string(md); + set_display_state(md, 1); + //mipid_set_bklight_level(panel, md->saved_bklight_level); + //mipid_esd_start_check(md); + + mutex_unlock(&md->mutex); + return 0; +} + +static void pn800_panel_disable(struct omap_display *display) +{ + struct pn800_device *md = + (struct pn800_device *)display->panel->priv; + + DBG("pn800_panel_disable\n"); + + mutex_lock(&md->mutex); + + if (!md->enabled) { + mutex_unlock(&md->mutex); + return; + } + /*md->saved_bklight_level = pn800_get_bklight_level(panel);*/ + /*pn800_set_bklight_level(panel, 0);*/ + + set_display_state(md, 0); + set_sleep_mode(md, 1); + md->enabled = 0; + + + if (display->hw_config.panel_disable) + display->hw_config.panel_disable(display); + + mutex_unlock(&md->mutex); +} + +static int pn800_panel_init(struct omap_display *display) +{ + struct pn800_device *md = + (struct pn800_device *)display->panel->priv; + + DBG("pn800_panel_init\n"); + + mutex_init(&md->mutex); + md->display = display; + + return 0; +} + +static int pn800_run_test(struct omap_display *display, int test_num) +{ + return 0; +} + +static struct omap_panel pn800_panel = { + .owner = THIS_MODULE, + .name = "panel-pn800", + .init = pn800_panel_init, + /*.remove = pn800_cleanup,*/ + .enable = pn800_panel_enable, + .disable = pn800_panel_disable, + //.set_mode = pn800_set_mode, + .run_test = pn800_run_test, + + .timings = { + .x_res = 800, + .y_res = 480, + + .pixel_clock = 21940, + .hsw = 50, + .hfp = 20, + .hbp = 15, + + .vsw = 2, + .vfp = 1, + .vbp = 3, + }, + .config = OMAP_DSS_LCD_TFT, + + .bpp = 16, +}; + +static int pn800_spi_probe(struct spi_device *spi) +{ + struct pn800_device *md; + + DBG("pn800_spi_probe\n"); + + md = kzalloc(sizeof(*md), GFP_KERNEL); + if (md == NULL) { + dev_err(&spi->dev, "out of memory\n"); + return -ENOMEM; + } + + spi->mode = SPI_MODE_0; + md->spi = spi; + dev_set_drvdata(&spi->dev, md); + md->panel = pn800_panel; + pn800_panel.priv = md; + + omap_dss_register_panel(&pn800_panel); + + return 0; +} + +static int pn800_spi_remove(struct spi_device *spi) +{ + struct pn800_device *md = dev_get_drvdata(&spi->dev); + + DBG("pn800_spi_remove\n"); + + omap_dss_unregister_panel(&pn800_panel); + + /*pn800_disable(&md->panel);*/ + kfree(md); + + return 0; +} + +static struct spi_driver pn800_spi_driver = { + .driver = { + .name = "panel-n800", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = pn800_spi_probe, + .remove = __devexit_p(pn800_spi_remove), +}; + +static int __init pn800_init(void) +{ + DBG("pn800_init\n"); + return spi_register_driver(&pn800_spi_driver); +} + +static void __exit pn800_exit(void) +{ + DBG("pn800_exit\n"); + spi_unregister_driver(&pn800_spi_driver); +} + +module_init(pn800_init); +module_exit(pn800_exit); + +MODULE_AUTHOR("Tomi Valkeinen <tom...@no...>"); +MODULE_DESCRIPTION("N800 LCD Driver"); +MODULE_LICENSE("GPL"); |
From: Koen K. <k....@st...> - 2009-01-12 14:17:35
Attachments:
PGP.sig
|
Op 12 jan 2009, om 12:47 heeft Tomi Valkeinen het volgende geschreven: > 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. I've tested these patches on beagleboard and omap35x EVM. The beagleboard is fully functional with it, the EVM has some glitches with DVI, but that might be due to differences between revisions of the EVM board (or rather the PMIC + SoC daugtherboards). The internal LCD works great on the EVM, the "3 dots in the corner" problem that DSS1 had is gone. Summary: please merge this, for beagleboard and omap3evm there are no regressions, only feature additions (s-video, better pixclock, etc) over the current code. regards, Koen > This is an updated version of the patch set I sent back in november: > http://marc.info/?l=linux-fbdev-devel&m=122581504222406&w=2 > > 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/ > > --- > > Tomi Valkeinen (12): > DSS: Hacked N810 support > DSS: Support for OMAP3 EVM board > DSS: Support for OMAP3 SDP board > DSS: Sharp LS037V7DW01 LCD Panel driver > DSS: support for Beagle Board > DSS: Add generic DVI panel > DSS: OMAPFB: fb driver for new display subsystem > DSS: DSI support > DSS: VENC support > DSS: RFBI support > DSS: Display subsystem for OMAP2/3 > DSS: Documentation for DSS2 > > > Documentation/arm/OMAP/DSS | 270 ++ > arch/arm/configs/dss_omap3_beagle_defconfig | 1437 +++++++++++ > arch/arm/configs/dss_omap_3430sdp_defconfig | 1603 +++++++++++++ > arch/arm/mach-omap2/board-3430sdp.c | 215 ++ > arch/arm/mach-omap2/board-n800.c | 214 +- > arch/arm/mach-omap2/board-omap3beagle.c | 101 + > arch/arm/mach-omap2/board-omap3evm.c | 203 ++ > arch/arm/plat-omap/Kconfig | 2 > arch/arm/plat-omap/Makefile | 4 > arch/arm/plat-omap/dss/Kconfig | 71 + > arch/arm/plat-omap/dss/Makefile | 6 > arch/arm/plat-omap/dss/dispc.c | 2113 +++++++++++++++++ > arch/arm/plat-omap/dss/display.c | 787 ++++++ > arch/arm/plat-omap/dss/dpi.c | 344 +++ > arch/arm/plat-omap/dss/dsi.c | 3187 ++++++++++++++++ > +++++++++ > arch/arm/plat-omap/dss/dss.c | 774 ++++++ > arch/arm/plat-omap/dss/dss.h | 274 ++ > arch/arm/plat-omap/dss/rfbi.c | 1262 ++++++++++ > arch/arm/plat-omap/dss/sdi.c | 174 + > arch/arm/plat-omap/dss/venc.c | 506 ++++ > arch/arm/plat-omap/fb-vram.c | 646 +++++ > arch/arm/plat-omap/fb.c | 22 > arch/arm/plat-omap/include/mach/display.h | 462 ++++ > arch/arm/plat-omap/include/mach/omapfb.h | 14 > drivers/video/Kconfig | 1 > drivers/video/Makefile | 1 > drivers/video/omap/Kconfig | 5 > drivers/video/omap2/Kconfig | 62 > drivers/video/omap2/Makefile | 8 > drivers/video/omap2/ctrl-blizzard.c | 279 ++ > drivers/video/omap2/omapfb-ioctl.c | 460 ++++ > drivers/video/omap2/omapfb-main.c | 1442 +++++++++++ > drivers/video/omap2/omapfb-sysfs.c | 901 +++++++ > drivers/video/omap2/omapfb.h | 115 + > drivers/video/omap2/panel-generic.c | 97 + > drivers/video/omap2/panel-n800.c | 437 +++ > drivers/video/omap2/panel-sharp-ls037v7dw01.c | 109 + > 37 files changed, 18537 insertions(+), 71 deletions(-) > create mode 100644 Documentation/arm/OMAP/DSS > create mode 100644 arch/arm/configs/dss_omap3_beagle_defconfig > create mode 100644 arch/arm/configs/dss_omap_3430sdp_defconfig > 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/fb-vram.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/ctrl-blizzard.c > 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-generic.c > create mode 100644 drivers/video/omap2/panel-n800.c > create mode 100644 drivers/video/omap2/panel-sharp-ls037v7dw01.c > > -- > Tomi Valkeinen > > -- > To unsubscribe from this list: send the line "unsubscribe linux- > omap" in > the body of a message to maj...@vg... > More majordomo info at http://vger.kernel.org/majordomo-info.html > |
From: Hiremath, V. <hva...@ti...> - 2009-01-12 14:52:51
|
Thanks, Vaibhav Hiremath > -----Original Message----- > From: lin...@vg... [mailto:linux-omap- > ow...@vg...] On Behalf Of Koen Kooi > Sent: Monday, January 12, 2009 7:14 PM > To: Tomi Valkeinen > Cc: lin...@li...; linux- > om...@vg... > Subject: Re: [PATCH 00/12] DSS: Series description > > > Op 12 jan 2009, om 12:47 heeft Tomi Valkeinen het volgende > geschreven: > > > 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. > > I've tested these patches on beagleboard and omap35x EVM. The > beagleboard is fully functional with it, the EVM has some glitches > with DVI, but that might be due to differences between revisions of > the EVM board (or rather the PMIC + SoC daugtherboards). [Hiremath, Vaibhav] Koen, I have also tested DVI output on EVM and facing same issues but I believe they are not because of board revisions. I have validated the DVI output with our previous (TI version of DSS library) on the same board and it comes absolutely fine. I need to dig bit more to find where exactly the issue is. > The > internal > LCD works great on the EVM, the "3 dots in the corner" problem that > DSS1 had is gone. > > Summary: please merge this, for beagleboard and omap3evm there are > no > regressions, only feature additions (s-video, better pixclock, etc) > over the current code. > > regards, > > Koen > > > > > This is an updated version of the patch set I sent back in > november: > > http://marc.info/?l=linux-fbdev-devel&m=122581504222406&w=2 > > > > 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/ > > > > --- > > > > Tomi Valkeinen (12): > > DSS: Hacked N810 support > > DSS: Support for OMAP3 EVM board > > DSS: Support for OMAP3 SDP board > > DSS: Sharp LS037V7DW01 LCD Panel driver > > DSS: support for Beagle Board > > DSS: Add generic DVI panel > > DSS: OMAPFB: fb driver for new display subsystem > > DSS: DSI support > > DSS: VENC support > > DSS: RFBI support > > DSS: Display subsystem for OMAP2/3 > > DSS: Documentation for DSS2 > > > > > > Documentation/arm/OMAP/DSS | 270 ++ > > arch/arm/configs/dss_omap3_beagle_defconfig | 1437 +++++++++++ > > arch/arm/configs/dss_omap_3430sdp_defconfig | 1603 +++++++++++++ > > arch/arm/mach-omap2/board-3430sdp.c | 215 ++ > > arch/arm/mach-omap2/board-n800.c | 214 +- > > arch/arm/mach-omap2/board-omap3beagle.c | 101 + > > arch/arm/mach-omap2/board-omap3evm.c | 203 ++ > > arch/arm/plat-omap/Kconfig | 2 > > arch/arm/plat-omap/Makefile | 4 > > arch/arm/plat-omap/dss/Kconfig | 71 + > > arch/arm/plat-omap/dss/Makefile | 6 > > arch/arm/plat-omap/dss/dispc.c | 2113 > +++++++++++++++++ > > arch/arm/plat-omap/dss/display.c | 787 ++++++ > > arch/arm/plat-omap/dss/dpi.c | 344 +++ > > arch/arm/plat-omap/dss/dsi.c | 3187 > ++++++++++++++++ > > +++++++++ > > arch/arm/plat-omap/dss/dss.c | 774 ++++++ > > arch/arm/plat-omap/dss/dss.h | 274 ++ > > arch/arm/plat-omap/dss/rfbi.c | 1262 ++++++++++ > > arch/arm/plat-omap/dss/sdi.c | 174 + > > arch/arm/plat-omap/dss/venc.c | 506 ++++ > > arch/arm/plat-omap/fb-vram.c | 646 +++++ > > arch/arm/plat-omap/fb.c | 22 > > arch/arm/plat-omap/include/mach/display.h | 462 ++++ > > arch/arm/plat-omap/include/mach/omapfb.h | 14 > > drivers/video/Kconfig | 1 > > drivers/video/Makefile | 1 > > drivers/video/omap/Kconfig | 5 > > drivers/video/omap2/Kconfig | 62 > > drivers/video/omap2/Makefile | 8 > > drivers/video/omap2/ctrl-blizzard.c | 279 ++ > > drivers/video/omap2/omapfb-ioctl.c | 460 ++++ > > drivers/video/omap2/omapfb-main.c | 1442 +++++++++++ > > drivers/video/omap2/omapfb-sysfs.c | 901 +++++++ > > drivers/video/omap2/omapfb.h | 115 + > > drivers/video/omap2/panel-generic.c | 97 + > > drivers/video/omap2/panel-n800.c | 437 +++ > > drivers/video/omap2/panel-sharp-ls037v7dw01.c | 109 + > > 37 files changed, 18537 insertions(+), 71 deletions(-) > > create mode 100644 Documentation/arm/OMAP/DSS > > create mode 100644 arch/arm/configs/dss_omap3_beagle_defconfig > > create mode 100644 arch/arm/configs/dss_omap_3430sdp_defconfig > > 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/fb-vram.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/ctrl-blizzard.c > > 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-generic.c > > create mode 100644 drivers/video/omap2/panel-n800.c > > create mode 100644 drivers/video/omap2/panel-sharp-ls037v7dw01.c > > > > -- > > Tomi Valkeinen > > > > -- > > To unsubscribe from this list: send the line "unsubscribe linux- > > omap" in > > the body of a message to maj...@vg... > > More majordomo info at http://vger.kernel.org/majordomo-info.html > > |
From: Koen K. <k....@st...> - 2009-01-12 15:39:39
Attachments:
PGP.sig
|
Op 12 jan 2009, om 15:52 heeft Hiremath, Vaibhav het volgende geschreven: > > > Thanks, > Vaibhav Hiremath > >> -----Original Message----- >> From: lin...@vg... [mailto:linux-omap- >> ow...@vg...] On Behalf Of Koen Kooi >> Sent: Monday, January 12, 2009 7:14 PM >> To: Tomi Valkeinen >> Cc: lin...@li...; linux- >> om...@vg... >> Subject: Re: [PATCH 00/12] DSS: Series description >> >> >> Op 12 jan 2009, om 12:47 heeft Tomi Valkeinen het volgende >> geschreven: >> >>> 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. >> >> I've tested these patches on beagleboard and omap35x EVM. The >> beagleboard is fully functional with it, the EVM has some glitches >> with DVI, but that might be due to differences between revisions of >> the EVM board (or rather the PMIC + SoC daugtherboards). > > [Hiremath, Vaibhav] Koen, I have also tested DVI output on EVM and > facing same issues but I believe they are not because of board > revisions. I have validated the DVI output with our previous (TI > version of DSS library) on the same board and it comes absolutely > fine. I need to dig bit more to find where exactly the issue is. The LCD redtint was fixed by adding guards for OMAP3 ES >= 2.0, so I was thinking DVI would need the same :) regards, KOen >> The >> internal >> LCD works great on the EVM, the "3 dots in the corner" problem that >> DSS1 had is gone. >> >> Summary: please merge this, for beagleboard and omap3evm there are >> no >> regressions, only feature additions (s-video, better pixclock, etc) >> over the current code. >> >> regards, >> >> Koen >> >> >> >>> This is an updated version of the patch set I sent back in >> november: >>> http://marc.info/?l=linux-fbdev-devel&m=122581504222406&w=2 >>> >>> 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/ >>> >>> --- >>> >>> Tomi Valkeinen (12): >>> DSS: Hacked N810 support >>> DSS: Support for OMAP3 EVM board >>> DSS: Support for OMAP3 SDP board >>> DSS: Sharp LS037V7DW01 LCD Panel driver >>> DSS: support for Beagle Board >>> DSS: Add generic DVI panel >>> DSS: OMAPFB: fb driver for new display subsystem >>> DSS: DSI support >>> DSS: VENC support >>> DSS: RFBI support >>> DSS: Display subsystem for OMAP2/3 >>> DSS: Documentation for DSS2 >>> >>> >>> Documentation/arm/OMAP/DSS | 270 ++ >>> arch/arm/configs/dss_omap3_beagle_defconfig | 1437 +++++++++++ >>> arch/arm/configs/dss_omap_3430sdp_defconfig | 1603 +++++++++++++ >>> arch/arm/mach-omap2/board-3430sdp.c | 215 ++ >>> arch/arm/mach-omap2/board-n800.c | 214 +- >>> arch/arm/mach-omap2/board-omap3beagle.c | 101 + >>> arch/arm/mach-omap2/board-omap3evm.c | 203 ++ >>> arch/arm/plat-omap/Kconfig | 2 >>> arch/arm/plat-omap/Makefile | 4 >>> arch/arm/plat-omap/dss/Kconfig | 71 + >>> arch/arm/plat-omap/dss/Makefile | 6 >>> arch/arm/plat-omap/dss/dispc.c | 2113 >> +++++++++++++++++ >>> arch/arm/plat-omap/dss/display.c | 787 ++++++ >>> arch/arm/plat-omap/dss/dpi.c | 344 +++ >>> arch/arm/plat-omap/dss/dsi.c | 3187 >> ++++++++++++++++ >>> +++++++++ >>> arch/arm/plat-omap/dss/dss.c | 774 ++++++ >>> arch/arm/plat-omap/dss/dss.h | 274 ++ >>> arch/arm/plat-omap/dss/rfbi.c | 1262 ++++++++++ >>> arch/arm/plat-omap/dss/sdi.c | 174 + >>> arch/arm/plat-omap/dss/venc.c | 506 ++++ >>> arch/arm/plat-omap/fb-vram.c | 646 +++++ >>> arch/arm/plat-omap/fb.c | 22 >>> arch/arm/plat-omap/include/mach/display.h | 462 ++++ >>> arch/arm/plat-omap/include/mach/omapfb.h | 14 >>> drivers/video/Kconfig | 1 >>> drivers/video/Makefile | 1 >>> drivers/video/omap/Kconfig | 5 >>> drivers/video/omap2/Kconfig | 62 >>> drivers/video/omap2/Makefile | 8 >>> drivers/video/omap2/ctrl-blizzard.c | 279 ++ >>> drivers/video/omap2/omapfb-ioctl.c | 460 ++++ >>> drivers/video/omap2/omapfb-main.c | 1442 +++++++++++ >>> drivers/video/omap2/omapfb-sysfs.c | 901 +++++++ >>> drivers/video/omap2/omapfb.h | 115 + >>> drivers/video/omap2/panel-generic.c | 97 + >>> drivers/video/omap2/panel-n800.c | 437 +++ >>> drivers/video/omap2/panel-sharp-ls037v7dw01.c | 109 + >>> 37 files changed, 18537 insertions(+), 71 deletions(-) >>> create mode 100644 Documentation/arm/OMAP/DSS >>> create mode 100644 arch/arm/configs/dss_omap3_beagle_defconfig >>> create mode 100644 arch/arm/configs/dss_omap_3430sdp_defconfig >>> 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/fb-vram.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/ctrl-blizzard.c >>> 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-generic.c >>> create mode 100644 drivers/video/omap2/panel-n800.c >>> create mode 100644 drivers/video/omap2/panel-sharp-ls037v7dw01.c >>> >>> -- >>> Tomi Valkeinen >>> >>> -- >>> To unsubscribe from this list: send the line "unsubscribe linux- >>> omap" in >>> the body of a message to maj...@vg... >>> More majordomo info at http://vger.kernel.org/majordomo-info.html >>> > > |
From: David B. <da...@pa...> - 2009-01-13 11:14:10
|
On Monday 12 January 2009, Tomi Valkeinen wrote: > arch/arm/configs/dss_omap3_beagle_defconfig | 1437 +++++++++++++++++++++++++++ This is a complete replacement. The patch would be a lot more comprehensible if changed the standard config to just add support for this board's video options (DVI and S-Video). Also it'd be good to have a brief textual summary of what each board's default video config is; maybe one of those little multicolumn charts as in your first patch, with a one sentence summary. (In the board-*.c file.) Note that after this merges, some work will be needed to make the regulator framework handle the power switching. Such logic should move out of board files (except for setting up "S-Video is supplied using the twl VDAC"). It's not quite time for that yet; heads-up, that's all. - Dave |