aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/arm/OMAP/DSS10
-rw-r--r--arch/arm/mach-omap2/board-rx51-video.c14
-rw-r--r--arch/arm/mach-omap2/board-rx51.c3
-rw-r--r--arch/arm/mach-omap2/display.c53
-rw-r--r--arch/arm/mach-omap2/sdrc.c16
-rw-r--r--arch/arm/plat-omap/common.c2
-rw-r--r--arch/arm/plat-omap/fb.c66
-rw-r--r--arch/arm/plat-omap/include/plat/sdrc.h7
-rw-r--r--arch/arm/plat-omap/include/plat/vram.h43
-rw-r--r--drivers/media/platform/omap/omap_vout.c23
-rw-r--r--drivers/media/platform/omap/omap_vout_vrfb.c2
-rw-r--r--drivers/media/platform/omap/omap_voutdef.h2
-rw-r--r--drivers/media/platform/omap/omap_voutlib.c38
-rw-r--r--drivers/media/platform/omap/omap_voutlib.h3
-rw-r--r--drivers/staging/omapdrm/omap_drv.c11
-rw-r--r--drivers/video/omap2/Kconfig3
-rw-r--r--drivers/video/omap2/Makefile1
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c23
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c36
-rw-r--r--drivers/video/omap2/displays/panel-lgphilips-lb035q02.c34
-rw-r--r--drivers/video/omap2/displays/panel-n8x0.c89
-rw-r--r--drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c24
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.c45
-rw-r--r--drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c17
-rw-r--r--drivers/video/omap2/displays/panel-taal.c72
-rw-r--r--drivers/video/omap2/displays/panel-tfp410.c33
-rw-r--r--drivers/video/omap2/displays/panel-tpo-td043mtea1.c20
-rw-r--r--drivers/video/omap2/dss/Kconfig35
-rw-r--r--drivers/video/omap2/dss/Makefile7
-rw-r--r--drivers/video/omap2/dss/apply.c331
-rw-r--r--drivers/video/omap2/dss/core.c72
-rw-r--r--drivers/video/omap2/dss/dispc-compat.c667
-rw-r--r--drivers/video/omap2/dss/dispc-compat.h30
-rw-r--r--drivers/video/omap2/dss/dispc.c1102
-rw-r--r--drivers/video/omap2/dss/display-sysfs.c321
-rw-r--r--drivers/video/omap2/dss/display.c386
-rw-r--r--drivers/video/omap2/dss/dpi.c126
-rw-r--r--drivers/video/omap2/dss/dsi.c247
-rw-r--r--drivers/video/omap2/dss/dss.c138
-rw-r--r--drivers/video/omap2/dss/dss.h124
-rw-r--r--drivers/video/omap2/dss/dss_features.c79
-rw-r--r--drivers/video/omap2/dss/dss_features.h12
-rw-r--r--drivers/video/omap2/dss/hdmi.c158
-rw-r--r--drivers/video/omap2/dss/hdmi_panel.c82
-rw-r--r--drivers/video/omap2/dss/manager.c39
-rw-r--r--drivers/video/omap2/dss/output.c90
-rw-r--r--drivers/video/omap2/dss/overlay.c17
-rw-r--r--drivers/video/omap2/dss/rfbi.c23
-rw-r--r--drivers/video/omap2/dss/sdi.c11
-rw-r--r--drivers/video/omap2/dss/ti_hdmi.h3
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c11
-rw-r--r--drivers/video/omap2/dss/venc.c11
-rw-r--r--drivers/video/omap2/dss/venc_panel.c19
-rw-r--r--drivers/video/omap2/omapfb/Kconfig1
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c48
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c212
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c6
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h20
-rw-r--r--drivers/video/omap2/vram.c514
-rw-r--r--drivers/video/omap2/vrfb.c142
-rw-r--r--include/video/omapdss.h105
-rw-r--r--include/video/omapvrfb.h (renamed from arch/arm/plat-omap/include/plat/vrfb.h)2
62 files changed, 2860 insertions, 3021 deletions
diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
index a564ceea9e98..4484e021290e 100644
--- a/Documentation/arm/OMAP/DSS
+++ b/Documentation/arm/OMAP/DSS
@@ -285,7 +285,10 @@ FB0 +-- GFX ---- LCD ---- LCD
285Misc notes 285Misc notes
286---------- 286----------
287 287
288OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator. 288OMAP FB allocates the framebuffer memory using the standard dma allocator. You
289can enable Contiguous Memory Allocator (CONFIG_CMA) to improve the dma
290allocator, and if CMA is enabled, you use "cma=" kernel parameter to increase
291the global memory area for CMA.
289 292
290Using DSI DPLL to generate pixel clock it is possible produce the pixel clock 293Using DSI DPLL to generate pixel clock it is possible produce the pixel clock
291of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI. 294of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI.
@@ -301,11 +304,6 @@ framebuffer parameters.
301Kernel boot arguments 304Kernel boot arguments
302--------------------- 305---------------------
303 306
304vram=<size>[,<physaddr>]
305 - Amount of total VRAM to preallocate and optionally a physical start
306 memory address. For example, "10M". omapfb allocates memory for
307 framebuffers from VRAM.
308
309omapfb.mode=<display>:<mode>[,...] 307omapfb.mode=<display>:<mode>[,...]
310 - Default video mode for specified displays. For example, 308 - Default video mode for specified displays. For example,
311 "dvi:800x400MR-24@60". See drivers/video/modedb.c. 309 "dvi:800x400MR-24@60". See drivers/video/modedb.c.
diff --git a/arch/arm/mach-omap2/board-rx51-video.c b/arch/arm/mach-omap2/board-rx51-video.c
index c22e111bcd00..46f4fc982766 100644
--- a/arch/arm/mach-omap2/board-rx51-video.c
+++ b/arch/arm/mach-omap2/board-rx51-video.c
@@ -16,7 +16,6 @@
16#include <linux/mm.h> 16#include <linux/mm.h>
17#include <asm/mach-types.h> 17#include <asm/mach-types.h>
18#include <video/omapdss.h> 18#include <video/omapdss.h>
19#include <plat/vram.h>
20#include <linux/platform_data/spi-omap2-mcspi.h> 19#include <linux/platform_data/spi-omap2-mcspi.h>
21 20
22#include "board-rx51.h" 21#include "board-rx51.h"
@@ -87,17 +86,4 @@ static int __init rx51_video_init(void)
87} 86}
88 87
89subsys_initcall(rx51_video_init); 88subsys_initcall(rx51_video_init);
90
91void __init rx51_video_mem_init(void)
92{
93 /*
94 * GFX 864x480x32bpp
95 * VID1/2 1280x720x32bpp double buffered
96 */
97 omap_vram_set_sdram_vram(PAGE_ALIGN(864 * 480 * 4) +
98 2 * PAGE_ALIGN(1280 * 720 * 4 * 2), 0);
99}
100
101#else
102void __init rx51_video_mem_init(void) { }
103#endif /* defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) */ 89#endif /* defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) */
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index 7bbb05d9689b..6e0de6f83278 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -34,8 +34,6 @@
34 34
35#define RX51_GPIO_SLEEP_IND 162 35#define RX51_GPIO_SLEEP_IND 162
36 36
37extern void rx51_video_mem_init(void);
38
39static struct gpio_led gpio_leds[] = { 37static struct gpio_led gpio_leds[] = {
40 { 38 {
41 .name = "sleep_ind", 39 .name = "sleep_ind",
@@ -112,7 +110,6 @@ static void __init rx51_init(void)
112 110
113static void __init rx51_reserve(void) 111static void __init rx51_reserve(void)
114{ 112{
115 rx51_video_mem_init();
116 omap_reserve(); 113 omap_reserve();
117} 114}
118 115
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 1011995f150a..282c814ea2e2 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -100,17 +100,20 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initconst = {
100 { "dss_hdmi", "omapdss_hdmi", -1 }, 100 { "dss_hdmi", "omapdss_hdmi", -1 },
101}; 101};
102 102
103static void __init omap4_hdmi_mux_pads(enum omap_hdmi_flags flags) 103static void __init omap4_tpd12s015_mux_pads(void)
104{ 104{
105 u32 reg;
106 u16 control_i2c_1;
107
108 omap_mux_init_signal("hdmi_cec", 105 omap_mux_init_signal("hdmi_cec",
109 OMAP_PIN_INPUT_PULLUP); 106 OMAP_PIN_INPUT_PULLUP);
110 omap_mux_init_signal("hdmi_ddc_scl", 107 omap_mux_init_signal("hdmi_ddc_scl",
111 OMAP_PIN_INPUT_PULLUP); 108 OMAP_PIN_INPUT_PULLUP);
112 omap_mux_init_signal("hdmi_ddc_sda", 109 omap_mux_init_signal("hdmi_ddc_sda",
113 OMAP_PIN_INPUT_PULLUP); 110 OMAP_PIN_INPUT_PULLUP);
111}
112
113static void __init omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
114{
115 u32 reg;
116 u16 control_i2c_1;
114 117
115 /* 118 /*
116 * CONTROL_I2C_1: HDMI_DDC_SDA_PULLUPRESX (bit 28) and 119 * CONTROL_I2C_1: HDMI_DDC_SDA_PULLUPRESX (bit 28) and
@@ -161,8 +164,10 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
161 164
162int __init omap_hdmi_init(enum omap_hdmi_flags flags) 165int __init omap_hdmi_init(enum omap_hdmi_flags flags)
163{ 166{
164 if (cpu_is_omap44xx()) 167 if (cpu_is_omap44xx()) {
165 omap4_hdmi_mux_pads(flags); 168 omap4_hdmi_mux_pads(flags);
169 omap4_tpd12s015_mux_pads();
170 }
166 171
167 return 0; 172 return 0;
168} 173}
@@ -284,6 +289,35 @@ err:
284 return ERR_PTR(r); 289 return ERR_PTR(r);
285} 290}
286 291
292static enum omapdss_version __init omap_display_get_version(void)
293{
294 if (cpu_is_omap24xx())
295 return OMAPDSS_VER_OMAP24xx;
296 else if (cpu_is_omap3630())
297 return OMAPDSS_VER_OMAP3630;
298 else if (cpu_is_omap34xx()) {
299 if (soc_is_am35xx()) {
300 return OMAPDSS_VER_AM35xx;
301 } else {
302 if (omap_rev() < OMAP3430_REV_ES3_0)
303 return OMAPDSS_VER_OMAP34xx_ES1;
304 else
305 return OMAPDSS_VER_OMAP34xx_ES3;
306 }
307 } else if (omap_rev() == OMAP4430_REV_ES1_0)
308 return OMAPDSS_VER_OMAP4430_ES1;
309 else if (omap_rev() == OMAP4430_REV_ES2_0 ||
310 omap_rev() == OMAP4430_REV_ES2_1 ||
311 omap_rev() == OMAP4430_REV_ES2_2)
312 return OMAPDSS_VER_OMAP4430_ES2;
313 else if (cpu_is_omap44xx())
314 return OMAPDSS_VER_OMAP4;
315 else if (soc_is_omap54xx())
316 return OMAPDSS_VER_OMAP5;
317 else
318 return OMAPDSS_VER_UNKNOWN;
319}
320
287int __init omap_display_init(struct omap_dss_board_info *board_data) 321int __init omap_display_init(struct omap_dss_board_info *board_data)
288{ 322{
289 int r = 0; 323 int r = 0;
@@ -291,9 +325,18 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
291 int i, oh_count; 325 int i, oh_count;
292 const struct omap_dss_hwmod_data *curr_dss_hwmod; 326 const struct omap_dss_hwmod_data *curr_dss_hwmod;
293 struct platform_device *dss_pdev; 327 struct platform_device *dss_pdev;
328 enum omapdss_version ver;
294 329
295 /* create omapdss device */ 330 /* create omapdss device */
296 331
332 ver = omap_display_get_version();
333
334 if (ver == OMAPDSS_VER_UNKNOWN) {
335 pr_err("DSS not supported on this SoC\n");
336 return -ENODEV;
337 }
338
339 board_data->version = ver;
297 board_data->dsi_enable_pads = omap_dsi_enable_pads; 340 board_data->dsi_enable_pads = omap_dsi_enable_pads;
298 board_data->dsi_disable_pads = omap_dsi_disable_pads; 341 board_data->dsi_disable_pads = omap_dsi_disable_pads;
299 board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count; 342 board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count;
diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c
index e3d345f46409..4282e6e967d6 100644
--- a/arch/arm/mach-omap2/sdrc.c
+++ b/arch/arm/mach-omap2/sdrc.c
@@ -160,19 +160,3 @@ void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
160 sdrc_write_reg(l, SDRC_POWER); 160 sdrc_write_reg(l, SDRC_POWER);
161 omap2_sms_save_context(); 161 omap2_sms_save_context();
162} 162}
163
164void omap2_sms_write_rot_control(u32 val, unsigned ctx)
165{
166 sms_write_reg(val, SMS_ROT_CONTROL(ctx));
167}
168
169void omap2_sms_write_rot_size(u32 val, unsigned ctx)
170{
171 sms_write_reg(val, SMS_ROT_SIZE(ctx));
172}
173
174void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
175{
176 sms_write_reg(val, SMS_ROT_PHYSICAL_BA(ctx));
177}
178
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index 111315a69354..d21ed18355ae 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -17,7 +17,6 @@
17#include <linux/dma-mapping.h> 17#include <linux/dma-mapping.h>
18 18
19#include <plat/common.h> 19#include <plat/common.h>
20#include <plat/vram.h>
21#include <linux/platform_data/dsp-omap.h> 20#include <linux/platform_data/dsp-omap.h>
22#include <plat/dma.h> 21#include <plat/dma.h>
23 22
@@ -25,7 +24,6 @@
25 24
26void __init omap_reserve(void) 25void __init omap_reserve(void)
27{ 26{
28 omap_vram_reserve_sdram_memblock();
29 omap_dsp_reserve_sdram_memblock(); 27 omap_dsp_reserve_sdram_memblock();
30 omap_secure_ram_reserve_memblock(); 28 omap_secure_ram_reserve_memblock();
31 omap_barrier_reserve_memblock(); 29 omap_barrier_reserve_memblock();
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
index bcbb9d5dc293..6df0c215fdb4 100644
--- a/arch/arm/plat-omap/fb.c
+++ b/arch/arm/plat-omap/fb.c
@@ -29,10 +29,72 @@
29#include <linux/memblock.h> 29#include <linux/memblock.h>
30#include <linux/io.h> 30#include <linux/io.h>
31#include <linux/omapfb.h> 31#include <linux/omapfb.h>
32#include <linux/dma-mapping.h>
32 33
33#include <mach/hardware.h> 34#include <mach/hardware.h>
34#include <asm/mach/map.h> 35#include <asm/mach/map.h>
35 36
37#include <plat/cpu.h>
38
39#ifdef CONFIG_OMAP2_VRFB
40
41/*
42 * The first memory resource is the register region for VRFB,
43 * the rest are VRFB virtual memory areas for each VRFB context.
44 */
45
46static const struct resource omap2_vrfb_resources[] = {
47 DEFINE_RES_MEM_NAMED(0x68008000u, 0x40, "vrfb-regs"),
48 DEFINE_RES_MEM_NAMED(0x70000000u, 0x4000000, "vrfb-area-0"),
49 DEFINE_RES_MEM_NAMED(0x74000000u, 0x4000000, "vrfb-area-1"),
50 DEFINE_RES_MEM_NAMED(0x78000000u, 0x4000000, "vrfb-area-2"),
51 DEFINE_RES_MEM_NAMED(0x7c000000u, 0x4000000, "vrfb-area-3"),
52};
53
54static const struct resource omap3_vrfb_resources[] = {
55 DEFINE_RES_MEM_NAMED(0x6C000180u, 0xc0, "vrfb-regs"),
56 DEFINE_RES_MEM_NAMED(0x70000000u, 0x4000000, "vrfb-area-0"),
57 DEFINE_RES_MEM_NAMED(0x74000000u, 0x4000000, "vrfb-area-1"),
58 DEFINE_RES_MEM_NAMED(0x78000000u, 0x4000000, "vrfb-area-2"),
59 DEFINE_RES_MEM_NAMED(0x7c000000u, 0x4000000, "vrfb-area-3"),
60 DEFINE_RES_MEM_NAMED(0xe0000000u, 0x4000000, "vrfb-area-4"),
61 DEFINE_RES_MEM_NAMED(0xe4000000u, 0x4000000, "vrfb-area-5"),
62 DEFINE_RES_MEM_NAMED(0xe8000000u, 0x4000000, "vrfb-area-6"),
63 DEFINE_RES_MEM_NAMED(0xec000000u, 0x4000000, "vrfb-area-7"),
64 DEFINE_RES_MEM_NAMED(0xf0000000u, 0x4000000, "vrfb-area-8"),
65 DEFINE_RES_MEM_NAMED(0xf4000000u, 0x4000000, "vrfb-area-9"),
66 DEFINE_RES_MEM_NAMED(0xf8000000u, 0x4000000, "vrfb-area-10"),
67 DEFINE_RES_MEM_NAMED(0xfc000000u, 0x4000000, "vrfb-area-11"),
68};
69
70static int __init omap_init_vrfb(void)
71{
72 struct platform_device *pdev;
73 const struct resource *res;
74 unsigned int num_res;
75
76 if (cpu_is_omap24xx()) {
77 res = omap2_vrfb_resources;
78 num_res = ARRAY_SIZE(omap2_vrfb_resources);
79 } else if (cpu_is_omap34xx()) {
80 res = omap3_vrfb_resources;
81 num_res = ARRAY_SIZE(omap3_vrfb_resources);
82 } else {
83 return 0;
84 }
85
86 pdev = platform_device_register_resndata(NULL, "omapvrfb", -1,
87 res, num_res, NULL, 0);
88
89 if (IS_ERR(pdev))
90 return PTR_ERR(pdev);
91 else
92 return 0;
93}
94
95arch_initcall(omap_init_vrfb);
96#endif
97
36#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) 98#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
37 99
38static bool omapfb_lcd_configured; 100static bool omapfb_lcd_configured;
@@ -45,7 +107,7 @@ static struct platform_device omap_fb_device = {
45 .id = -1, 107 .id = -1,
46 .dev = { 108 .dev = {
47 .dma_mask = &omap_fb_dma_mask, 109 .dma_mask = &omap_fb_dma_mask,
48 .coherent_dma_mask = ~(u32)0, 110 .coherent_dma_mask = DMA_BIT_MASK(32),
49 .platform_data = &omapfb_config, 111 .platform_data = &omapfb_config,
50 }, 112 },
51 .num_resources = 0, 113 .num_resources = 0,
@@ -81,7 +143,7 @@ static struct platform_device omap_fb_device = {
81 .id = -1, 143 .id = -1,
82 .dev = { 144 .dev = {
83 .dma_mask = &omap_fb_dma_mask, 145 .dma_mask = &omap_fb_dma_mask,
84 .coherent_dma_mask = ~(u32)0, 146 .coherent_dma_mask = DMA_BIT_MASK(32),
85 .platform_data = &omapfb_config, 147 .platform_data = &omapfb_config,
86 }, 148 },
87 .num_resources = 0, 149 .num_resources = 0,
diff --git a/arch/arm/plat-omap/include/plat/sdrc.h b/arch/arm/plat-omap/include/plat/sdrc.h
index 36d6a7666216..c68bab29cfc5 100644
--- a/arch/arm/plat-omap/include/plat/sdrc.h
+++ b/arch/arm/plat-omap/include/plat/sdrc.h
@@ -94,9 +94,6 @@
94/* SMS register offsets - read/write with sms_{read,write}_reg() */ 94/* SMS register offsets - read/write with sms_{read,write}_reg() */
95 95
96#define SMS_SYSCONFIG 0x010 96#define SMS_SYSCONFIG 0x010
97#define SMS_ROT_CONTROL(context) (0x180 + 0x10 * context)
98#define SMS_ROT_SIZE(context) (0x184 + 0x10 * context)
99#define SMS_ROT_PHYSICAL_BA(context) (0x188 + 0x10 * context)
100/* REVISIT: fill in other SMS registers here */ 97/* REVISIT: fill in other SMS registers here */
101 98
102 99
@@ -137,10 +134,6 @@ int omap2_sdrc_get_params(unsigned long r,
137void omap2_sms_save_context(void); 134void omap2_sms_save_context(void);
138void omap2_sms_restore_context(void); 135void omap2_sms_restore_context(void);
139 136
140void omap2_sms_write_rot_control(u32 val, unsigned ctx);
141void omap2_sms_write_rot_size(u32 val, unsigned ctx);
142void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx);
143
144#ifdef CONFIG_ARCH_OMAP2 137#ifdef CONFIG_ARCH_OMAP2
145 138
146struct memory_timings { 139struct memory_timings {
diff --git a/arch/arm/plat-omap/include/plat/vram.h b/arch/arm/plat-omap/include/plat/vram.h
deleted file mode 100644
index 4d65b7d06e6c..000000000000
--- a/arch/arm/plat-omap/include/plat/vram.h
+++ /dev/null
@@ -1,43 +0,0 @@
1/*
2 * VRAM manager for OMAP
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#ifndef __OMAP_VRAM_H__
22#define __OMAP_VRAM_H__
23
24#include <linux/types.h>
25
26extern int omap_vram_add_region(unsigned long paddr, size_t size);
27extern int omap_vram_free(unsigned long paddr, size_t size);
28extern int omap_vram_alloc(size_t size, unsigned long *paddr);
29extern int omap_vram_reserve(unsigned long paddr, size_t size);
30extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram,
31 unsigned long *largest_free_block);
32
33#ifdef CONFIG_OMAP2_VRAM
34extern void omap_vram_set_sdram_vram(u32 size, u32 start);
35
36extern void omap_vram_reserve_sdram_memblock(void);
37#else
38static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { }
39
40static inline void omap_vram_reserve_sdram_memblock(void) { }
41#endif
42
43#endif
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
index a3b1a34c896d..e8cac9e55bc9 100644
--- a/drivers/media/platform/omap/omap_vout.c
+++ b/drivers/media/platform/omap/omap_vout.c
@@ -44,9 +44,7 @@
44#include <media/v4l2-device.h> 44#include <media/v4l2-device.h>
45#include <media/v4l2-ioctl.h> 45#include <media/v4l2-ioctl.h>
46 46
47#include <plat/cpu.h> 47#include <video/omapvrfb.h>
48#include <plat/dma.h>
49#include <plat/vrfb.h>
50#include <video/omapdss.h> 48#include <video/omapdss.h>
51 49
52#include "omap_voutlib.h" 50#include "omap_voutlib.h"
@@ -2064,7 +2062,7 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
2064 vout->vid_info.id = k + 1; 2062 vout->vid_info.id = k + 1;
2065 2063
2066 /* Set VRFB as rotation_type for omap2 and omap3 */ 2064 /* Set VRFB as rotation_type for omap2 and omap3 */
2067 if (cpu_is_omap24xx() || cpu_is_omap34xx()) 2065 if (omap_vout_dss_omap24xx() || omap_vout_dss_omap34xx())
2068 vout->vid_info.rotation_type = VOUT_ROT_VRFB; 2066 vout->vid_info.rotation_type = VOUT_ROT_VRFB;
2069 2067
2070 /* Setup the default configuration for the video devices 2068 /* Setup the default configuration for the video devices
@@ -2186,14 +2184,23 @@ static int __init omap_vout_probe(struct platform_device *pdev)
2186 struct omap_dss_device *def_display; 2184 struct omap_dss_device *def_display;
2187 struct omap2video_device *vid_dev = NULL; 2185 struct omap2video_device *vid_dev = NULL;
2188 2186
2187 ret = omapdss_compat_init();
2188 if (ret) {
2189 dev_err(&pdev->dev, "failed to init dss\n");
2190 return ret;
2191 }
2192
2189 if (pdev->num_resources == 0) { 2193 if (pdev->num_resources == 0) {
2190 dev_err(&pdev->dev, "probed for an unknown device\n"); 2194 dev_err(&pdev->dev, "probed for an unknown device\n");
2191 return -ENODEV; 2195 ret = -ENODEV;
2196 goto err_dss_init;
2192 } 2197 }
2193 2198
2194 vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL); 2199 vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL);
2195 if (vid_dev == NULL) 2200 if (vid_dev == NULL) {
2196 return -ENOMEM; 2201 ret = -ENOMEM;
2202 goto err_dss_init;
2203 }
2197 2204
2198 vid_dev->num_displays = 0; 2205 vid_dev->num_displays = 0;
2199 for_each_dss_dev(dssdev) { 2206 for_each_dss_dev(dssdev) {
@@ -2288,6 +2295,8 @@ probe_err1:
2288 } 2295 }
2289probe_err0: 2296probe_err0:
2290 kfree(vid_dev); 2297 kfree(vid_dev);
2298err_dss_init:
2299 omapdss_compat_uninit();
2291 return ret; 2300 return ret;
2292} 2301}
2293 2302
diff --git a/drivers/media/platform/omap/omap_vout_vrfb.c b/drivers/media/platform/omap/omap_vout_vrfb.c
index 4be26abf6cea..6c37f9240ddf 100644
--- a/drivers/media/platform/omap/omap_vout_vrfb.c
+++ b/drivers/media/platform/omap/omap_vout_vrfb.c
@@ -17,7 +17,7 @@
17#include <media/v4l2-device.h> 17#include <media/v4l2-device.h>
18 18
19#include <plat/dma.h> 19#include <plat/dma.h>
20#include <plat/vrfb.h> 20#include <video/omapvrfb.h>
21 21
22#include "omap_voutdef.h" 22#include "omap_voutdef.h"
23#include "omap_voutlib.h" 23#include "omap_voutlib.h"
diff --git a/drivers/media/platform/omap/omap_voutdef.h b/drivers/media/platform/omap/omap_voutdef.h
index 27a95d23b913..9ccfe1f475a4 100644
--- a/drivers/media/platform/omap/omap_voutdef.h
+++ b/drivers/media/platform/omap/omap_voutdef.h
@@ -12,7 +12,7 @@
12#define OMAP_VOUTDEF_H 12#define OMAP_VOUTDEF_H
13 13
14#include <video/omapdss.h> 14#include <video/omapdss.h>
15#include <plat/vrfb.h> 15#include <video/omapvrfb.h>
16 16
17#define YUYV_BPP 2 17#define YUYV_BPP 2
18#define RGB565_BPP 2 18#define RGB565_BPP 2
diff --git a/drivers/media/platform/omap/omap_voutlib.c b/drivers/media/platform/omap/omap_voutlib.c
index 115408b9274f..80b0d88f125c 100644
--- a/drivers/media/platform/omap/omap_voutlib.c
+++ b/drivers/media/platform/omap/omap_voutlib.c
@@ -26,7 +26,7 @@
26 26
27#include <linux/dma-mapping.h> 27#include <linux/dma-mapping.h>
28 28
29#include <plat/cpu.h> 29#include <video/omapdss.h>
30 30
31#include "omap_voutlib.h" 31#include "omap_voutlib.h"
32 32
@@ -124,7 +124,7 @@ int omap_vout_new_window(struct v4l2_rect *crop,
124 win->chromakey = new_win->chromakey; 124 win->chromakey = new_win->chromakey;
125 125
126 /* Adjust the cropping window to allow for resizing limitation */ 126 /* Adjust the cropping window to allow for resizing limitation */
127 if (cpu_is_omap24xx()) { 127 if (omap_vout_dss_omap24xx()) {
128 /* For 24xx limit is 8x to 1/2x scaling. */ 128 /* For 24xx limit is 8x to 1/2x scaling. */
129 if ((crop->height/win->w.height) >= 2) 129 if ((crop->height/win->w.height) >= 2)
130 crop->height = win->w.height * 2; 130 crop->height = win->w.height * 2;
@@ -140,7 +140,7 @@ int omap_vout_new_window(struct v4l2_rect *crop,
140 if (crop->height != win->w.height) 140 if (crop->height != win->w.height)
141 crop->width = 768; 141 crop->width = 768;
142 } 142 }
143 } else if (cpu_is_omap34xx()) { 143 } else if (omap_vout_dss_omap34xx()) {
144 /* For 34xx limit is 8x to 1/4x scaling. */ 144 /* For 34xx limit is 8x to 1/4x scaling. */
145 if ((crop->height/win->w.height) >= 4) 145 if ((crop->height/win->w.height) >= 4)
146 crop->height = win->w.height * 4; 146 crop->height = win->w.height * 4;
@@ -196,7 +196,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
196 if (try_crop.width <= 0 || try_crop.height <= 0) 196 if (try_crop.width <= 0 || try_crop.height <= 0)
197 return -EINVAL; 197 return -EINVAL;
198 198
199 if (cpu_is_omap24xx()) { 199 if (omap_vout_dss_omap24xx()) {
200 if (try_crop.height != win->w.height) { 200 if (try_crop.height != win->w.height) {
201 /* If we're resizing vertically, we can't support a 201 /* If we're resizing vertically, we can't support a
202 * crop width wider than 768 pixels. 202 * crop width wider than 768 pixels.
@@ -207,9 +207,9 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
207 } 207 }
208 /* vertical resizing */ 208 /* vertical resizing */
209 vresize = (1024 * try_crop.height) / win->w.height; 209 vresize = (1024 * try_crop.height) / win->w.height;
210 if (cpu_is_omap24xx() && (vresize > 2048)) 210 if (omap_vout_dss_omap24xx() && (vresize > 2048))
211 vresize = 2048; 211 vresize = 2048;
212 else if (cpu_is_omap34xx() && (vresize > 4096)) 212 else if (omap_vout_dss_omap34xx() && (vresize > 4096))
213 vresize = 4096; 213 vresize = 4096;
214 214
215 win->w.height = ((1024 * try_crop.height) / vresize) & ~1; 215 win->w.height = ((1024 * try_crop.height) / vresize) & ~1;
@@ -226,9 +226,9 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
226 } 226 }
227 /* horizontal resizing */ 227 /* horizontal resizing */
228 hresize = (1024 * try_crop.width) / win->w.width; 228 hresize = (1024 * try_crop.width) / win->w.width;
229 if (cpu_is_omap24xx() && (hresize > 2048)) 229 if (omap_vout_dss_omap24xx() && (hresize > 2048))
230 hresize = 2048; 230 hresize = 2048;
231 else if (cpu_is_omap34xx() && (hresize > 4096)) 231 else if (omap_vout_dss_omap34xx() && (hresize > 4096))
232 hresize = 4096; 232 hresize = 4096;
233 233
234 win->w.width = ((1024 * try_crop.width) / hresize) & ~1; 234 win->w.width = ((1024 * try_crop.width) / hresize) & ~1;
@@ -243,7 +243,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
243 if (try_crop.width == 0) 243 if (try_crop.width == 0)
244 try_crop.width = 2; 244 try_crop.width = 2;
245 } 245 }
246 if (cpu_is_omap24xx()) { 246 if (omap_vout_dss_omap24xx()) {
247 if ((try_crop.height/win->w.height) >= 2) 247 if ((try_crop.height/win->w.height) >= 2)
248 try_crop.height = win->w.height * 2; 248 try_crop.height = win->w.height * 2;
249 249
@@ -258,7 +258,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
258 if (try_crop.height != win->w.height) 258 if (try_crop.height != win->w.height)
259 try_crop.width = 768; 259 try_crop.width = 768;
260 } 260 }
261 } else if (cpu_is_omap34xx()) { 261 } else if (omap_vout_dss_omap34xx()) {
262 if ((try_crop.height/win->w.height) >= 4) 262 if ((try_crop.height/win->w.height) >= 4)
263 try_crop.height = win->w.height * 4; 263 try_crop.height = win->w.height * 4;
264 264
@@ -337,3 +337,21 @@ void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size)
337 } 337 }
338 free_pages((unsigned long) virtaddr, order); 338 free_pages((unsigned long) virtaddr, order);
339} 339}
340
341bool omap_vout_dss_omap24xx(void)
342{
343 return omapdss_get_version() == OMAPDSS_VER_OMAP24xx;
344}
345
346bool omap_vout_dss_omap34xx(void)
347{
348 switch (omapdss_get_version()) {
349 case OMAPDSS_VER_OMAP34xx_ES1:
350 case OMAPDSS_VER_OMAP34xx_ES3:
351 case OMAPDSS_VER_OMAP3630:
352 case OMAPDSS_VER_AM35xx:
353 return true;
354 default:
355 return false;
356 }
357}
diff --git a/drivers/media/platform/omap/omap_voutlib.h b/drivers/media/platform/omap/omap_voutlib.h
index e51750a597e3..f9d1c0779f33 100644
--- a/drivers/media/platform/omap/omap_voutlib.h
+++ b/drivers/media/platform/omap/omap_voutlib.h
@@ -32,5 +32,8 @@ void omap_vout_new_format(struct v4l2_pix_format *pix,
32 struct v4l2_window *win); 32 struct v4l2_window *win);
33unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr); 33unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr);
34void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size); 34void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size);
35
36bool omap_vout_dss_omap24xx(void);
37bool omap_vout_dss_omap34xx(void);
35#endif /* #ifndef OMAP_VOUTLIB_H */ 38#endif /* #ifndef OMAP_VOUTLIB_H */
36 39
diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c
index ebdb0b676737..2bf72591817a 100644
--- a/drivers/staging/omapdrm/omap_drv.c
+++ b/drivers/staging/omapdrm/omap_drv.c
@@ -572,6 +572,14 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
572 572
573 dev->dev_private = priv; 573 dev->dev_private = priv;
574 574
575 ret = omapdss_compat_init();
576 if (ret) {
577 dev_err(dev->dev, "coult not init omapdss\n");
578 dev->dev_private = NULL;
579 kfree(priv);
580 return ret;
581 }
582
575 priv->wq = alloc_ordered_workqueue("omapdrm", 0); 583 priv->wq = alloc_ordered_workqueue("omapdrm", 0);
576 584
577 INIT_LIST_HEAD(&priv->obj_list); 585 INIT_LIST_HEAD(&priv->obj_list);
@@ -583,6 +591,7 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
583 dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret); 591 dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret);
584 dev->dev_private = NULL; 592 dev->dev_private = NULL;
585 kfree(priv); 593 kfree(priv);
594 omapdss_compat_uninit();
586 return ret; 595 return ret;
587 } 596 }
588 597
@@ -618,6 +627,8 @@ static int dev_unload(struct drm_device *dev)
618 flush_workqueue(priv->wq); 627 flush_workqueue(priv->wq);
619 destroy_workqueue(priv->wq); 628 destroy_workqueue(priv->wq);
620 629
630 omapdss_compat_uninit();
631
621 kfree(dev->dev_private); 632 kfree(dev->dev_private);
622 dev->dev_private = NULL; 633 dev->dev_private = NULL;
623 634
diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
index d877c361abda..346d67d6cf4d 100644
--- a/drivers/video/omap2/Kconfig
+++ b/drivers/video/omap2/Kconfig
@@ -1,6 +1,3 @@
1config OMAP2_VRAM
2 bool
3
4config OMAP2_VRFB 1config OMAP2_VRFB
5 bool 2 bool
6 3
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
index 5ddef129f798..5ea7cb9aed17 100644
--- a/drivers/video/omap2/Makefile
+++ b/drivers/video/omap2/Makefile
@@ -1,4 +1,3 @@
1obj-$(CONFIG_OMAP2_VRAM) += vram.o
2obj-$(CONFIG_OMAP2_VRFB) += vrfb.o 1obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
3 2
4obj-$(CONFIG_OMAP2_DSS) += dss/ 3obj-$(CONFIG_OMAP2_DSS) += dss/
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index c835aa70f96f..65eb76c840a1 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -710,27 +710,6 @@ static void acx_panel_disable(struct omap_dss_device *dssdev)
710 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 710 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
711} 711}
712 712
713static int acx_panel_suspend(struct omap_dss_device *dssdev)
714{
715 dev_dbg(&dssdev->dev, "%s\n", __func__);
716 acx_panel_power_off(dssdev);
717 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
718 return 0;
719}
720
721static int acx_panel_resume(struct omap_dss_device *dssdev)
722{
723 int r;
724
725 dev_dbg(&dssdev->dev, "%s\n", __func__);
726 r = acx_panel_power_on(dssdev);
727 if (r)
728 return r;
729
730 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
731 return 0;
732}
733
734static void acx_panel_set_timings(struct omap_dss_device *dssdev, 713static void acx_panel_set_timings(struct omap_dss_device *dssdev,
735 struct omap_video_timings *timings) 714 struct omap_video_timings *timings)
736{ 715{
@@ -752,8 +731,6 @@ static struct omap_dss_driver acx_panel_driver = {
752 731
753 .enable = acx_panel_enable, 732 .enable = acx_panel_enable,
754 .disable = acx_panel_disable, 733 .disable = acx_panel_disable,
755 .suspend = acx_panel_suspend,
756 .resume = acx_panel_resume,
757 734
758 .set_timings = acx_panel_set_timings, 735 .set_timings = acx_panel_set_timings,
759 .check_timings = acx_panel_check_timings, 736 .check_timings = acx_panel_check_timings,
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 88295c526815..54ca8ae21078 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -688,40 +688,6 @@ static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
688 mutex_unlock(&drv_data->lock); 688 mutex_unlock(&drv_data->lock);
689} 689}
690 690
691static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)
692{
693 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
694
695 mutex_lock(&drv_data->lock);
696
697 generic_dpi_panel_power_off(dssdev);
698
699 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
700
701 mutex_unlock(&drv_data->lock);
702
703 return 0;
704}
705
706static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
707{
708 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
709 int r;
710
711 mutex_lock(&drv_data->lock);
712
713 r = generic_dpi_panel_power_on(dssdev);
714 if (r)
715 goto err;
716
717 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
718
719err:
720 mutex_unlock(&drv_data->lock);
721
722 return r;
723}
724
725static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev, 691static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
726 struct omap_video_timings *timings) 692 struct omap_video_timings *timings)
727{ 693{
@@ -769,8 +735,6 @@ static struct omap_dss_driver dpi_driver = {
769 735
770 .enable = generic_dpi_panel_enable, 736 .enable = generic_dpi_panel_enable,
771 .disable = generic_dpi_panel_disable, 737 .disable = generic_dpi_panel_disable,
772 .suspend = generic_dpi_panel_suspend,
773 .resume = generic_dpi_panel_resume,
774 738
775 .set_timings = generic_dpi_panel_set_timings, 739 .set_timings = generic_dpi_panel_set_timings,
776 .get_timings = generic_dpi_panel_get_timings, 740 .get_timings = generic_dpi_panel_get_timings,
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
index 90c1cabf244e..ace419b801eb 100644
--- a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
+++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
@@ -143,46 +143,12 @@ static void lb035q02_panel_disable(struct omap_dss_device *dssdev)
143 mutex_unlock(&ld->lock); 143 mutex_unlock(&ld->lock);
144} 144}
145 145
146static int lb035q02_panel_suspend(struct omap_dss_device *dssdev)
147{
148 struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
149
150 mutex_lock(&ld->lock);
151
152 lb035q02_panel_power_off(dssdev);
153 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
154
155 mutex_unlock(&ld->lock);
156 return 0;
157}
158
159static int lb035q02_panel_resume(struct omap_dss_device *dssdev)
160{
161 struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
162 int r;
163
164 mutex_lock(&ld->lock);
165
166 r = lb035q02_panel_power_on(dssdev);
167 if (r)
168 goto err;
169 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
170
171 mutex_unlock(&ld->lock);
172 return 0;
173err:
174 mutex_unlock(&ld->lock);
175 return r;
176}
177
178static struct omap_dss_driver lb035q02_driver = { 146static struct omap_dss_driver lb035q02_driver = {
179 .probe = lb035q02_panel_probe, 147 .probe = lb035q02_panel_probe,
180 .remove = lb035q02_panel_remove, 148 .remove = lb035q02_panel_remove,
181 149
182 .enable = lb035q02_panel_enable, 150 .enable = lb035q02_panel_enable,
183 .disable = lb035q02_panel_disable, 151 .disable = lb035q02_panel_disable,
184 .suspend = lb035q02_panel_suspend,
185 .resume = lb035q02_panel_resume,
186 152
187 .driver = { 153 .driver = {
188 .name = "lgphilips_lb035q02_panel", 154 .name = "lgphilips_lb035q02_panel",
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
index 3fc5ad081a21..d1cb722fcdbc 100644
--- a/drivers/video/omap2/displays/panel-n8x0.c
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -574,54 +574,6 @@ static void n8x0_panel_disable(struct omap_dss_device *dssdev)
574 mutex_unlock(&ddata->lock); 574 mutex_unlock(&ddata->lock);
575} 575}
576 576
577static int n8x0_panel_suspend(struct omap_dss_device *dssdev)
578{
579 struct panel_drv_data *ddata = get_drv_data(dssdev);
580
581 dev_dbg(&dssdev->dev, "suspend\n");
582
583 mutex_lock(&ddata->lock);
584
585 rfbi_bus_lock();
586
587 n8x0_panel_power_off(dssdev);
588
589 rfbi_bus_unlock();
590
591 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
592
593 mutex_unlock(&ddata->lock);
594
595 return 0;
596}
597
598static int n8x0_panel_resume(struct omap_dss_device *dssdev)
599{
600 struct panel_drv_data *ddata = get_drv_data(dssdev);
601 int r;
602
603 dev_dbg(&dssdev->dev, "resume\n");
604
605 mutex_lock(&ddata->lock);
606
607 rfbi_bus_lock();
608
609 r = n8x0_panel_power_on(dssdev);
610
611 rfbi_bus_unlock();
612
613 if (r) {
614 mutex_unlock(&ddata->lock);
615 return r;
616 }
617
618 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
619
620 mutex_unlock(&ddata->lock);
621
622 return 0;
623}
624
625static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev, 577static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
626 u16 *xres, u16 *yres) 578 u16 *xres, u16 *yres)
627{ 579{
@@ -683,8 +635,6 @@ static struct omap_dss_driver n8x0_panel_driver = {
683 635
684 .enable = n8x0_panel_enable, 636 .enable = n8x0_panel_enable,
685 .disable = n8x0_panel_disable, 637 .disable = n8x0_panel_disable,
686 .suspend = n8x0_panel_suspend,
687 .resume = n8x0_panel_resume,
688 638
689 .update = n8x0_panel_update, 639 .update = n8x0_panel_update,
690 .sync = n8x0_panel_sync, 640 .sync = n8x0_panel_sync,
@@ -702,18 +652,25 @@ static struct omap_dss_driver n8x0_panel_driver = {
702 652
703static int mipid_spi_probe(struct spi_device *spi) 653static int mipid_spi_probe(struct spi_device *spi)
704{ 654{
655 int r;
656
705 dev_dbg(&spi->dev, "mipid_spi_probe\n"); 657 dev_dbg(&spi->dev, "mipid_spi_probe\n");
706 658
707 spi->mode = SPI_MODE_0; 659 spi->mode = SPI_MODE_0;
708 660
709 s_drv_data.spidev = spi; 661 s_drv_data.spidev = spi;
710 662
711 return 0; 663 r = omap_dss_register_driver(&n8x0_panel_driver);
664 if (r)
665 pr_err("n8x0_panel: dss driver registration failed\n");
666
667 return r;
712} 668}
713 669
714static int mipid_spi_remove(struct spi_device *spi) 670static int mipid_spi_remove(struct spi_device *spi)
715{ 671{
716 dev_dbg(&spi->dev, "mipid_spi_remove\n"); 672 dev_dbg(&spi->dev, "mipid_spi_remove\n");
673 omap_dss_unregister_driver(&n8x0_panel_driver);
717 return 0; 674 return 0;
718} 675}
719 676
@@ -725,34 +682,6 @@ static struct spi_driver mipid_spi_driver = {
725 .probe = mipid_spi_probe, 682 .probe = mipid_spi_probe,
726 .remove = __devexit_p(mipid_spi_remove), 683 .remove = __devexit_p(mipid_spi_remove),
727}; 684};
685module_spi_driver(mipid_spi_driver);
728 686
729static int __init n8x0_panel_drv_init(void)
730{
731 int r;
732
733 r = spi_register_driver(&mipid_spi_driver);
734 if (r) {
735 pr_err("n8x0_panel: spi driver registration failed\n");
736 return r;
737 }
738
739 r = omap_dss_register_driver(&n8x0_panel_driver);
740 if (r) {
741 pr_err("n8x0_panel: dss driver registration failed\n");
742 spi_unregister_driver(&mipid_spi_driver);
743 return r;
744 }
745
746 return 0;
747}
748
749static void __exit n8x0_panel_drv_exit(void)
750{
751 spi_unregister_driver(&mipid_spi_driver);
752
753 omap_dss_unregister_driver(&n8x0_panel_driver);
754}
755
756module_init(n8x0_panel_drv_init);
757module_exit(n8x0_panel_drv_exit);
758MODULE_LICENSE("GPL"); 687MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
index 908fd268f3dc..2a79c283bebe 100644
--- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
@@ -236,28 +236,6 @@ static void nec_8048_panel_disable(struct omap_dss_device *dssdev)
236 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 236 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
237} 237}
238 238
239static int nec_8048_panel_suspend(struct omap_dss_device *dssdev)
240{
241 nec_8048_panel_power_off(dssdev);
242
243 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
244
245 return 0;
246}
247
248static int nec_8048_panel_resume(struct omap_dss_device *dssdev)
249{
250 int r;
251
252 r = nec_8048_panel_power_on(dssdev);
253 if (r)
254 return r;
255
256 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
257
258 return 0;
259}
260
261static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev) 239static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev)
262{ 240{
263 return 16; 241 return 16;
@@ -268,8 +246,6 @@ static struct omap_dss_driver nec_8048_driver = {
268 .remove = nec_8048_panel_remove, 246 .remove = nec_8048_panel_remove,
269 .enable = nec_8048_panel_enable, 247 .enable = nec_8048_panel_enable,
270 .disable = nec_8048_panel_disable, 248 .disable = nec_8048_panel_disable,
271 .suspend = nec_8048_panel_suspend,
272 .resume = nec_8048_panel_resume,
273 .get_recommended_bpp = nec_8048_recommended_bpp, 249 .get_recommended_bpp = nec_8048_recommended_bpp,
274 250
275 .driver = { 251 .driver = {
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c
index 9df87640ddd2..1b94018aac3e 100644
--- a/drivers/video/omap2/displays/panel-picodlp.c
+++ b/drivers/video/omap2/displays/panel-picodlp.c
@@ -50,6 +50,7 @@ struct picodlp_i2c_data {
50 50
51static struct i2c_device_id picodlp_i2c_id[] = { 51static struct i2c_device_id picodlp_i2c_id[] = {
52 { "picodlp_i2c_driver", 0 }, 52 { "picodlp_i2c_driver", 0 },
53 { }
53}; 54};
54 55
55struct picodlp_i2c_command { 56struct picodlp_i2c_command {
@@ -503,47 +504,6 @@ static void picodlp_panel_disable(struct omap_dss_device *dssdev)
503 dev_dbg(&dssdev->dev, "disabling picodlp panel\n"); 504 dev_dbg(&dssdev->dev, "disabling picodlp panel\n");
504} 505}
505 506
506static int picodlp_panel_suspend(struct omap_dss_device *dssdev)
507{
508 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
509
510 mutex_lock(&picod->lock);
511 /* Turn off DLP Power */
512 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
513 mutex_unlock(&picod->lock);
514 dev_err(&dssdev->dev, "unable to suspend picodlp panel,"
515 " panel is not ACTIVE\n");
516 return -EINVAL;
517 }
518
519 picodlp_panel_power_off(dssdev);
520
521 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
522 mutex_unlock(&picod->lock);
523
524 dev_dbg(&dssdev->dev, "suspending picodlp panel\n");
525 return 0;
526}
527
528static int picodlp_panel_resume(struct omap_dss_device *dssdev)
529{
530 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
531 int r;
532
533 mutex_lock(&picod->lock);
534 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
535 mutex_unlock(&picod->lock);
536 dev_err(&dssdev->dev, "unable to resume picodlp panel,"
537 " panel is not ACTIVE\n");
538 return -EINVAL;
539 }
540
541 r = picodlp_panel_power_on(dssdev);
542 mutex_unlock(&picod->lock);
543 dev_dbg(&dssdev->dev, "resuming picodlp panel\n");
544 return r;
545}
546
547static void picodlp_get_resolution(struct omap_dss_device *dssdev, 507static void picodlp_get_resolution(struct omap_dss_device *dssdev,
548 u16 *xres, u16 *yres) 508 u16 *xres, u16 *yres)
549{ 509{
@@ -560,9 +520,6 @@ static struct omap_dss_driver picodlp_driver = {
560 520
561 .get_resolution = picodlp_get_resolution, 521 .get_resolution = picodlp_get_resolution,
562 522
563 .suspend = picodlp_panel_suspend,
564 .resume = picodlp_panel_resume,
565
566 .driver = { 523 .driver = {
567 .name = "picodlp_panel", 524 .name = "picodlp_panel",
568 .owner = THIS_MODULE, 525 .owner = THIS_MODULE,
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
index 1ec3b277ff15..cada8c621e01 100644
--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -194,29 +194,12 @@ static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
194 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 194 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
195} 195}
196 196
197static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev)
198{
199 sharp_ls_power_off(dssdev);
200 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
201 return 0;
202}
203
204static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
205{
206 int r;
207 r = sharp_ls_power_on(dssdev);
208 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
209 return r;
210}
211
212static struct omap_dss_driver sharp_ls_driver = { 197static struct omap_dss_driver sharp_ls_driver = {
213 .probe = sharp_ls_panel_probe, 198 .probe = sharp_ls_panel_probe,
214 .remove = __exit_p(sharp_ls_panel_remove), 199 .remove = __exit_p(sharp_ls_panel_remove),
215 200
216 .enable = sharp_ls_panel_enable, 201 .enable = sharp_ls_panel_enable,
217 .disable = sharp_ls_panel_disable, 202 .disable = sharp_ls_panel_disable,
218 .suspend = sharp_ls_panel_suspend,
219 .resume = sharp_ls_panel_resume,
220 203
221 .driver = { 204 .driver = {
222 .name = "sharp_ls_panel", 205 .name = "sharp_ls_panel",
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index f2f644680ca8..a32407a5735a 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -1245,76 +1245,6 @@ static void taal_disable(struct omap_dss_device *dssdev)
1245 mutex_unlock(&td->lock); 1245 mutex_unlock(&td->lock);
1246} 1246}
1247 1247
1248static int taal_suspend(struct omap_dss_device *dssdev)
1249{
1250 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1251 int r;
1252
1253 dev_dbg(&dssdev->dev, "suspend\n");
1254
1255 mutex_lock(&td->lock);
1256
1257 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
1258 r = -EINVAL;
1259 goto err;
1260 }
1261
1262 taal_cancel_ulps_work(dssdev);
1263 taal_cancel_esd_work(dssdev);
1264
1265 dsi_bus_lock(dssdev);
1266
1267 r = taal_wake_up(dssdev);
1268 if (!r)
1269 taal_power_off(dssdev);
1270
1271 dsi_bus_unlock(dssdev);
1272
1273 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
1274
1275 mutex_unlock(&td->lock);
1276
1277 return 0;
1278err:
1279 mutex_unlock(&td->lock);
1280 return r;
1281}
1282
1283static int taal_resume(struct omap_dss_device *dssdev)
1284{
1285 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1286 int r;
1287
1288 dev_dbg(&dssdev->dev, "resume\n");
1289
1290 mutex_lock(&td->lock);
1291
1292 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
1293 r = -EINVAL;
1294 goto err;
1295 }
1296
1297 dsi_bus_lock(dssdev);
1298
1299 r = taal_power_on(dssdev);
1300
1301 dsi_bus_unlock(dssdev);
1302
1303 if (r) {
1304 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
1305 } else {
1306 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
1307 taal_queue_esd_work(dssdev);
1308 }
1309
1310 mutex_unlock(&td->lock);
1311
1312 return r;
1313err:
1314 mutex_unlock(&td->lock);
1315 return r;
1316}
1317
1318static void taal_framedone_cb(int err, void *data) 1248static void taal_framedone_cb(int err, void *data)
1319{ 1249{
1320 struct omap_dss_device *dssdev = data; 1250 struct omap_dss_device *dssdev = data;
@@ -1818,8 +1748,6 @@ static struct omap_dss_driver taal_driver = {
1818 1748
1819 .enable = taal_enable, 1749 .enable = taal_enable,
1820 .disable = taal_disable, 1750 .disable = taal_disable,
1821 .suspend = taal_suspend,
1822 .resume = taal_resume,
1823 1751
1824 .update = taal_update, 1752 .update = taal_update,
1825 .sync = taal_sync, 1753 .sync = taal_sync,
diff --git a/drivers/video/omap2/displays/panel-tfp410.c b/drivers/video/omap2/displays/panel-tfp410.c
index 383811cf8648..8281baafe1ef 100644
--- a/drivers/video/omap2/displays/panel-tfp410.c
+++ b/drivers/video/omap2/displays/panel-tfp410.c
@@ -189,37 +189,6 @@ static void tfp410_disable(struct omap_dss_device *dssdev)
189 mutex_unlock(&ddata->lock); 189 mutex_unlock(&ddata->lock);
190} 190}
191 191
192static int tfp410_suspend(struct omap_dss_device *dssdev)
193{
194 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
195
196 mutex_lock(&ddata->lock);
197
198 tfp410_power_off(dssdev);
199
200 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
201
202 mutex_unlock(&ddata->lock);
203
204 return 0;
205}
206
207static int tfp410_resume(struct omap_dss_device *dssdev)
208{
209 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
210 int r;
211
212 mutex_lock(&ddata->lock);
213
214 r = tfp410_power_on(dssdev);
215 if (r == 0)
216 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
217
218 mutex_unlock(&ddata->lock);
219
220 return r;
221}
222
223static void tfp410_set_timings(struct omap_dss_device *dssdev, 192static void tfp410_set_timings(struct omap_dss_device *dssdev,
224 struct omap_video_timings *timings) 193 struct omap_video_timings *timings)
225{ 194{
@@ -355,8 +324,6 @@ static struct omap_dss_driver tfp410_driver = {
355 324
356 .enable = tfp410_enable, 325 .enable = tfp410_enable,
357 .disable = tfp410_disable, 326 .disable = tfp410_disable,
358 .suspend = tfp410_suspend,
359 .resume = tfp410_resume,
360 327
361 .set_timings = tfp410_set_timings, 328 .set_timings = tfp410_set_timings,
362 .get_timings = tfp410_get_timings, 329 .get_timings = tfp410_get_timings,
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index b5e6dbc59f0a..316b3da6d2cb 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -401,24 +401,6 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev)
401 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 401 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
402} 402}
403 403
404static int tpo_td043_suspend(struct omap_dss_device *dssdev)
405{
406 dev_dbg(&dssdev->dev, "suspend\n");
407
408 tpo_td043_disable_dss(dssdev);
409
410 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
411
412 return 0;
413}
414
415static int tpo_td043_resume(struct omap_dss_device *dssdev)
416{
417 dev_dbg(&dssdev->dev, "resume\n");
418
419 return tpo_td043_enable_dss(dssdev);
420}
421
422static int tpo_td043_probe(struct omap_dss_device *dssdev) 404static int tpo_td043_probe(struct omap_dss_device *dssdev)
423{ 405{
424 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev); 406 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
@@ -500,8 +482,6 @@ static struct omap_dss_driver tpo_td043_driver = {
500 482
501 .enable = tpo_td043_enable, 483 .enable = tpo_td043_enable,
502 .disable = tpo_td043_disable, 484 .disable = tpo_td043_disable,
503 .suspend = tpo_td043_suspend,
504 .resume = tpo_td043_resume,
505 .set_mirror = tpo_td043_set_hmirror, 485 .set_mirror = tpo_td043_set_hmirror,
506 .get_mirror = tpo_td043_get_hmirror, 486 .get_mirror = tpo_td043_get_hmirror,
507 487
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 80f5390aa136..cb0f145c7077 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -1,33 +1,30 @@
1menuconfig OMAP2_DSS 1menuconfig OMAP2_DSS
2 tristate "OMAP2+ Display Subsystem support" 2 tristate "OMAP2+ Display Subsystem support"
3 depends on ARCH_OMAP2PLUS
4 help 3 help
5 OMAP2+ Display Subsystem support. 4 OMAP2+ Display Subsystem support.
6 5
7if OMAP2_DSS 6if OMAP2_DSS
8 7
9config OMAP2_VRAM_SIZE 8config OMAP2_DSS_DEBUG
10 int "VRAM size (MB)" 9 bool "Debug support"
11 range 0 32 10 default n
12 default 0
13 help 11 help
14 The amount of SDRAM to reserve at boot time for video RAM use. 12 This enables printing of debug messages. Alternatively, debug messages
15 This VRAM will be used by omapfb and other drivers that need 13 can also be enabled by setting CONFIG_DYNAMIC_DEBUG and then setting
16 large continuous RAM area for video use. 14 appropriate flags in <debugfs>/dynamic_debug/control.
17 15
18 You can also set this with "vram=<bytes>" kernel argument, or 16config OMAP2_DSS_DEBUGFS
19 in the board file. 17 bool "Debugfs filesystem support"
20 18 depends on DEBUG_FS
21config OMAP2_DSS_DEBUG_SUPPORT 19 default n
22 bool "Debug support"
23 default y
24 help 20 help
25 This enables debug messages. You need to enable printing 21 This enables debugfs for OMAPDSS at <debugfs>/omapdss. This enables
26 with 'debug' module parameter. 22 querying about clock configuration and register configuration of dss,
23 dispc, dsi, hdmi and rfbi.
27 24
28config OMAP2_DSS_COLLECT_IRQ_STATS 25config OMAP2_DSS_COLLECT_IRQ_STATS
29 bool "Collect DSS IRQ statistics" 26 bool "Collect DSS IRQ statistics"
30 depends on OMAP2_DSS_DEBUG_SUPPORT 27 depends on OMAP2_DSS_DEBUGFS
31 default n 28 default n
32 help 29 help
33 Collect DSS IRQ statistics, printable via debugfs. 30 Collect DSS IRQ statistics, printable via debugfs.
@@ -62,7 +59,6 @@ config OMAP2_DSS_VENC
62 59
63config OMAP4_DSS_HDMI 60config OMAP4_DSS_HDMI
64 bool "HDMI support" 61 bool "HDMI support"
65 depends on ARCH_OMAP4
66 default y 62 default y
67 help 63 help
68 HDMI Interface. This adds the High Definition Multimedia Interface. 64 HDMI Interface. This adds the High Definition Multimedia Interface.
@@ -70,11 +66,9 @@ config OMAP4_DSS_HDMI
70 66
71config OMAP4_DSS_HDMI_AUDIO 67config OMAP4_DSS_HDMI_AUDIO
72 bool 68 bool
73 depends on OMAP4_DSS_HDMI
74 69
75config OMAP2_DSS_SDI 70config OMAP2_DSS_SDI
76 bool "SDI support" 71 bool "SDI support"
77 depends on ARCH_OMAP3
78 default n 72 default n
79 help 73 help
80 SDI (Serial Display Interface) support. 74 SDI (Serial Display Interface) support.
@@ -84,7 +78,6 @@ config OMAP2_DSS_SDI
84 78
85config OMAP2_DSS_DSI 79config OMAP2_DSS_DSI
86 bool "DSI support" 80 bool "DSI support"
87 depends on ARCH_OMAP3 || ARCH_OMAP4 || ARCH_OMAP5
88 default n 81 default n
89 help 82 help
90 MIPI DSI (Display Serial Interface) support. 83 MIPI DSI (Display Serial Interface) support.
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index 4549869bfe1a..61949ff7940c 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -1,6 +1,10 @@
1obj-$(CONFIG_OMAP2_DSS) += omapdss.o 1obj-$(CONFIG_OMAP2_DSS) += omapdss.o
2# Core DSS files
2omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ 3omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
3 manager.o manager-sysfs.o overlay.o overlay-sysfs.o output.o apply.o 4 output.o
5# DSS compat layer files
6omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \
7 dispc-compat.o display-sysfs.o
4omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o 8omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
5omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o 9omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
6omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o 10omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
@@ -8,3 +12,4 @@ omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
8omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o 12omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
9omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ 13omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
10 hdmi_panel.o ti_hdmi_4xxx_ip.o 14 hdmi_panel.o ti_hdmi_4xxx_ip.o
15ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 19d66f471b4b..d446bdfc4c82 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -18,6 +18,7 @@
18#define DSS_SUBSYS_NAME "APPLY" 18#define DSS_SUBSYS_NAME "APPLY"
19 19
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <linux/module.h>
21#include <linux/slab.h> 22#include <linux/slab.h>
22#include <linux/spinlock.h> 23#include <linux/spinlock.h>
23#include <linux/jiffies.h> 24#include <linux/jiffies.h>
@@ -26,6 +27,7 @@
26 27
27#include "dss.h" 28#include "dss.h"
28#include "dss_features.h" 29#include "dss_features.h"
30#include "dispc-compat.h"
29 31
30/* 32/*
31 * We have 4 levels of cache for the dispc settings. First two are in SW and 33 * We have 4 levels of cache for the dispc settings. First two are in SW and
@@ -70,7 +72,6 @@ struct ovl_priv_data {
70 bool shadow_extra_info_dirty; 72 bool shadow_extra_info_dirty;
71 73
72 bool enabled; 74 bool enabled;
73 enum omap_channel channel;
74 u32 fifo_low, fifo_high; 75 u32 fifo_low, fifo_high;
75 76
76 /* 77 /*
@@ -105,6 +106,9 @@ struct mgr_priv_data {
105 106
106 struct omap_video_timings timings; 107 struct omap_video_timings timings;
107 struct dss_lcd_mgr_config lcd_config; 108 struct dss_lcd_mgr_config lcd_config;
109
110 void (*framedone_handler)(void *);
111 void *framedone_handler_data;
108}; 112};
109 113
110static struct { 114static struct {
@@ -132,7 +136,7 @@ static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
132 return &dss_data.mgr_priv_data_array[mgr->id]; 136 return &dss_data.mgr_priv_data_array[mgr->id];
133} 137}
134 138
135void dss_apply_init(void) 139static void apply_init_priv(void)
136{ 140{
137 const int num_ovls = dss_feat_get_num_ovls(); 141 const int num_ovls = dss_feat_get_num_ovls();
138 struct mgr_priv_data *mp; 142 struct mgr_priv_data *mp;
@@ -414,11 +418,46 @@ static void wait_pending_extra_info_updates(void)
414 r = wait_for_completion_timeout(&extra_updated_completion, t); 418 r = wait_for_completion_timeout(&extra_updated_completion, t);
415 if (r == 0) 419 if (r == 0)
416 DSSWARN("timeout in wait_pending_extra_info_updates\n"); 420 DSSWARN("timeout in wait_pending_extra_info_updates\n");
417 else if (r < 0)
418 DSSERR("wait_pending_extra_info_updates failed: %d\n", r);
419} 421}
420 422
421int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) 423static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
424{
425 return ovl->manager ?
426 (ovl->manager->output ? ovl->manager->output->device : NULL) :
427 NULL;
428}
429
430static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
431{
432 return mgr->output ? mgr->output->device : NULL;
433}
434
435static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
436{
437 unsigned long timeout = msecs_to_jiffies(500);
438 struct omap_dss_device *dssdev = mgr->get_device(mgr);
439 u32 irq;
440 int r;
441
442 r = dispc_runtime_get();
443 if (r)
444 return r;
445
446 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
447 irq = DISPC_IRQ_EVSYNC_ODD;
448 else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
449 irq = DISPC_IRQ_EVSYNC_EVEN;
450 else
451 irq = dispc_mgr_get_vsync_irq(mgr->id);
452
453 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
454
455 dispc_runtime_put();
456
457 return r;
458}
459
460static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
422{ 461{
423 unsigned long timeout = msecs_to_jiffies(500); 462 unsigned long timeout = msecs_to_jiffies(500);
424 struct mgr_priv_data *mp = get_mgr_priv(mgr); 463 struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -488,7 +527,7 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
488 return r; 527 return r;
489} 528}
490 529
491int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) 530static int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
492{ 531{
493 unsigned long timeout = msecs_to_jiffies(500); 532 unsigned long timeout = msecs_to_jiffies(500);
494 struct ovl_priv_data *op; 533 struct ovl_priv_data *op;
@@ -573,7 +612,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
573 struct mgr_priv_data *mp; 612 struct mgr_priv_data *mp;
574 int r; 613 int r;
575 614
576 DSSDBGF("%d", ovl->id); 615 DSSDBG("writing ovl %d regs", ovl->id);
577 616
578 if (!op->enabled || !op->info_dirty) 617 if (!op->enabled || !op->info_dirty)
579 return; 618 return;
@@ -608,7 +647,7 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
608 struct ovl_priv_data *op = get_ovl_priv(ovl); 647 struct ovl_priv_data *op = get_ovl_priv(ovl);
609 struct mgr_priv_data *mp; 648 struct mgr_priv_data *mp;
610 649
611 DSSDBGF("%d", ovl->id); 650 DSSDBG("writing ovl %d regs extra", ovl->id);
612 651
613 if (!op->extra_info_dirty) 652 if (!op->extra_info_dirty)
614 return; 653 return;
@@ -617,7 +656,6 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
617 * disabled */ 656 * disabled */
618 657
619 dispc_ovl_enable(ovl->id, op->enabled); 658 dispc_ovl_enable(ovl->id, op->enabled);
620 dispc_ovl_set_channel_out(ovl->id, op->channel);
621 dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high); 659 dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
622 660
623 mp = get_mgr_priv(ovl->manager); 661 mp = get_mgr_priv(ovl->manager);
@@ -632,7 +670,7 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
632 struct mgr_priv_data *mp = get_mgr_priv(mgr); 670 struct mgr_priv_data *mp = get_mgr_priv(mgr);
633 struct omap_overlay *ovl; 671 struct omap_overlay *ovl;
634 672
635 DSSDBGF("%d", mgr->id); 673 DSSDBG("writing mgr %d regs", mgr->id);
636 674
637 if (!mp->enabled) 675 if (!mp->enabled)
638 return; 676 return;
@@ -658,7 +696,7 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
658{ 696{
659 struct mgr_priv_data *mp = get_mgr_priv(mgr); 697 struct mgr_priv_data *mp = get_mgr_priv(mgr);
660 698
661 DSSDBGF("%d", mgr->id); 699 DSSDBG("writing mgr %d regs extra", mgr->id);
662 700
663 if (!mp->extra_info_dirty) 701 if (!mp->extra_info_dirty)
664 return; 702 return;
@@ -666,22 +704,8 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
666 dispc_mgr_set_timings(mgr->id, &mp->timings); 704 dispc_mgr_set_timings(mgr->id, &mp->timings);
667 705
668 /* lcd_config parameters */ 706 /* lcd_config parameters */
669 if (dss_mgr_is_lcd(mgr->id)) { 707 if (dss_mgr_is_lcd(mgr->id))
670 dispc_mgr_set_io_pad_mode(mp->lcd_config.io_pad_mode); 708 dispc_mgr_set_lcd_config(mgr->id, &mp->lcd_config);
671
672 dispc_mgr_enable_stallmode(mgr->id, mp->lcd_config.stallmode);
673 dispc_mgr_enable_fifohandcheck(mgr->id,
674 mp->lcd_config.fifohandcheck);
675
676 dispc_mgr_set_clock_div(mgr->id, &mp->lcd_config.clock_info);
677
678 dispc_mgr_set_tft_data_lines(mgr->id,
679 mp->lcd_config.video_port_width);
680
681 dispc_lcd_enable_signal_polarity(mp->lcd_config.lcden_sig_polarity);
682
683 dispc_mgr_set_lcd_type_tft(mgr->id);
684 }
685 709
686 mp->extra_info_dirty = false; 710 mp->extra_info_dirty = false;
687 if (mp->updating) 711 if (mp->updating)
@@ -761,7 +785,7 @@ static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
761 } 785 }
762} 786}
763 787
764void dss_mgr_start_update(struct omap_overlay_manager *mgr) 788static void dss_mgr_start_update_compat(struct omap_overlay_manager *mgr)
765{ 789{
766 struct mgr_priv_data *mp = get_mgr_priv(mgr); 790 struct mgr_priv_data *mp = get_mgr_priv(mgr);
767 unsigned long flags; 791 unsigned long flags;
@@ -786,9 +810,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
786 if (!dss_data.irq_enabled && need_isr()) 810 if (!dss_data.irq_enabled && need_isr())
787 dss_register_vsync_isr(); 811 dss_register_vsync_isr();
788 812
789 dispc_mgr_enable(mgr->id, true); 813 dispc_mgr_enable_sync(mgr->id);
790
791 mgr_clear_shadow_dirty(mgr);
792 814
793 spin_unlock_irqrestore(&data_lock, flags); 815 spin_unlock_irqrestore(&data_lock, flags);
794} 816}
@@ -845,7 +867,6 @@ static void dss_apply_irq_handler(void *data, u32 mask)
845 for (i = 0; i < num_mgrs; i++) { 867 for (i = 0; i < num_mgrs; i++) {
846 struct omap_overlay_manager *mgr; 868 struct omap_overlay_manager *mgr;
847 struct mgr_priv_data *mp; 869 struct mgr_priv_data *mp;
848 bool was_updating;
849 870
850 mgr = omap_dss_get_overlay_manager(i); 871 mgr = omap_dss_get_overlay_manager(i);
851 mp = get_mgr_priv(mgr); 872 mp = get_mgr_priv(mgr);
@@ -853,7 +874,6 @@ static void dss_apply_irq_handler(void *data, u32 mask)
853 if (!mp->enabled) 874 if (!mp->enabled)
854 continue; 875 continue;
855 876
856 was_updating = mp->updating;
857 mp->updating = dispc_mgr_is_enabled(i); 877 mp->updating = dispc_mgr_is_enabled(i);
858 878
859 if (!mgr_manual_update(mgr)) { 879 if (!mgr_manual_update(mgr)) {
@@ -872,6 +892,21 @@ static void dss_apply_irq_handler(void *data, u32 mask)
872 if (!extra_updating) 892 if (!extra_updating)
873 complete_all(&extra_updated_completion); 893 complete_all(&extra_updated_completion);
874 894
895 /* call framedone handlers for manual update displays */
896 for (i = 0; i < num_mgrs; i++) {
897 struct omap_overlay_manager *mgr;
898 struct mgr_priv_data *mp;
899
900 mgr = omap_dss_get_overlay_manager(i);
901 mp = get_mgr_priv(mgr);
902
903 if (!mgr_manual_update(mgr) || !mp->framedone_handler)
904 continue;
905
906 if (mask & dispc_mgr_get_framedone_irq(i))
907 mp->framedone_handler(mp->framedone_handler_data);
908 }
909
875 if (!need_isr()) 910 if (!need_isr())
876 dss_unregister_vsync_isr(); 911 dss_unregister_vsync_isr();
877 912
@@ -906,7 +941,7 @@ static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
906 mp->info = mp->user_info; 941 mp->info = mp->user_info;
907} 942}
908 943
909int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) 944static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
910{ 945{
911 unsigned long flags; 946 unsigned long flags;
912 struct omap_overlay *ovl; 947 struct omap_overlay *ovl;
@@ -1005,7 +1040,7 @@ static void dss_setup_fifos(void)
1005 } 1040 }
1006} 1041}
1007 1042
1008int dss_mgr_enable(struct omap_overlay_manager *mgr) 1043static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr)
1009{ 1044{
1010 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1045 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1011 unsigned long flags; 1046 unsigned long flags;
@@ -1035,10 +1070,13 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
1035 if (!mgr_manual_update(mgr)) 1070 if (!mgr_manual_update(mgr))
1036 mp->updating = true; 1071 mp->updating = true;
1037 1072
1073 if (!dss_data.irq_enabled && need_isr())
1074 dss_register_vsync_isr();
1075
1038 spin_unlock_irqrestore(&data_lock, flags); 1076 spin_unlock_irqrestore(&data_lock, flags);
1039 1077
1040 if (!mgr_manual_update(mgr)) 1078 if (!mgr_manual_update(mgr))
1041 dispc_mgr_enable(mgr->id, true); 1079 dispc_mgr_enable_sync(mgr->id);
1042 1080
1043out: 1081out:
1044 mutex_unlock(&apply_lock); 1082 mutex_unlock(&apply_lock);
@@ -1052,7 +1090,7 @@ err:
1052 return r; 1090 return r;
1053} 1091}
1054 1092
1055void dss_mgr_disable(struct omap_overlay_manager *mgr) 1093static void dss_mgr_disable_compat(struct omap_overlay_manager *mgr)
1056{ 1094{
1057 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1095 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1058 unsigned long flags; 1096 unsigned long flags;
@@ -1063,7 +1101,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
1063 goto out; 1101 goto out;
1064 1102
1065 if (!mgr_manual_update(mgr)) 1103 if (!mgr_manual_update(mgr))
1066 dispc_mgr_enable(mgr->id, false); 1104 dispc_mgr_disable_sync(mgr->id);
1067 1105
1068 spin_lock_irqsave(&data_lock, flags); 1106 spin_lock_irqsave(&data_lock, flags);
1069 1107
@@ -1076,7 +1114,7 @@ out:
1076 mutex_unlock(&apply_lock); 1114 mutex_unlock(&apply_lock);
1077} 1115}
1078 1116
1079int dss_mgr_set_info(struct omap_overlay_manager *mgr, 1117static int dss_mgr_set_info(struct omap_overlay_manager *mgr,
1080 struct omap_overlay_manager_info *info) 1118 struct omap_overlay_manager_info *info)
1081{ 1119{
1082 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1120 struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -1097,7 +1135,7 @@ int dss_mgr_set_info(struct omap_overlay_manager *mgr,
1097 return 0; 1135 return 0;
1098} 1136}
1099 1137
1100void dss_mgr_get_info(struct omap_overlay_manager *mgr, 1138static void dss_mgr_get_info(struct omap_overlay_manager *mgr,
1101 struct omap_overlay_manager_info *info) 1139 struct omap_overlay_manager_info *info)
1102{ 1140{
1103 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1141 struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -1110,7 +1148,7 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
1110 spin_unlock_irqrestore(&data_lock, flags); 1148 spin_unlock_irqrestore(&data_lock, flags);
1111} 1149}
1112 1150
1113int dss_mgr_set_output(struct omap_overlay_manager *mgr, 1151static int dss_mgr_set_output(struct omap_overlay_manager *mgr,
1114 struct omap_dss_output *output) 1152 struct omap_dss_output *output)
1115{ 1153{
1116 int r; 1154 int r;
@@ -1142,7 +1180,7 @@ err:
1142 return r; 1180 return r;
1143} 1181}
1144 1182
1145int dss_mgr_unset_output(struct omap_overlay_manager *mgr) 1183static int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
1146{ 1184{
1147 int r; 1185 int r;
1148 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1186 struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -1189,7 +1227,7 @@ static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
1189 mp->extra_info_dirty = true; 1227 mp->extra_info_dirty = true;
1190} 1228}
1191 1229
1192void dss_mgr_set_timings(struct omap_overlay_manager *mgr, 1230static void dss_mgr_set_timings_compat(struct omap_overlay_manager *mgr,
1193 const struct omap_video_timings *timings) 1231 const struct omap_video_timings *timings)
1194{ 1232{
1195 unsigned long flags; 1233 unsigned long flags;
@@ -1217,7 +1255,7 @@ static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
1217 mp->extra_info_dirty = true; 1255 mp->extra_info_dirty = true;
1218} 1256}
1219 1257
1220void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr, 1258static void dss_mgr_set_lcd_config_compat(struct omap_overlay_manager *mgr,
1221 const struct dss_lcd_mgr_config *config) 1259 const struct dss_lcd_mgr_config *config)
1222{ 1260{
1223 unsigned long flags; 1261 unsigned long flags;
@@ -1236,7 +1274,7 @@ out:
1236 spin_unlock_irqrestore(&data_lock, flags); 1274 spin_unlock_irqrestore(&data_lock, flags);
1237} 1275}
1238 1276
1239int dss_ovl_set_info(struct omap_overlay *ovl, 1277static int dss_ovl_set_info(struct omap_overlay *ovl,
1240 struct omap_overlay_info *info) 1278 struct omap_overlay_info *info)
1241{ 1279{
1242 struct ovl_priv_data *op = get_ovl_priv(ovl); 1280 struct ovl_priv_data *op = get_ovl_priv(ovl);
@@ -1257,7 +1295,7 @@ int dss_ovl_set_info(struct omap_overlay *ovl,
1257 return 0; 1295 return 0;
1258} 1296}
1259 1297
1260void dss_ovl_get_info(struct omap_overlay *ovl, 1298static void dss_ovl_get_info(struct omap_overlay *ovl,
1261 struct omap_overlay_info *info) 1299 struct omap_overlay_info *info)
1262{ 1300{
1263 struct ovl_priv_data *op = get_ovl_priv(ovl); 1301 struct ovl_priv_data *op = get_ovl_priv(ovl);
@@ -1270,7 +1308,7 @@ void dss_ovl_get_info(struct omap_overlay *ovl,
1270 spin_unlock_irqrestore(&data_lock, flags); 1308 spin_unlock_irqrestore(&data_lock, flags);
1271} 1309}
1272 1310
1273int dss_ovl_set_manager(struct omap_overlay *ovl, 1311static int dss_ovl_set_manager(struct omap_overlay *ovl,
1274 struct omap_overlay_manager *mgr) 1312 struct omap_overlay_manager *mgr)
1275{ 1313{
1276 struct ovl_priv_data *op = get_ovl_priv(ovl); 1314 struct ovl_priv_data *op = get_ovl_priv(ovl);
@@ -1289,45 +1327,40 @@ int dss_ovl_set_manager(struct omap_overlay *ovl,
1289 goto err; 1327 goto err;
1290 } 1328 }
1291 1329
1330 r = dispc_runtime_get();
1331 if (r)
1332 goto err;
1333
1292 spin_lock_irqsave(&data_lock, flags); 1334 spin_lock_irqsave(&data_lock, flags);
1293 1335
1294 if (op->enabled) { 1336 if (op->enabled) {
1295 spin_unlock_irqrestore(&data_lock, flags); 1337 spin_unlock_irqrestore(&data_lock, flags);
1296 DSSERR("overlay has to be disabled to change the manager\n"); 1338 DSSERR("overlay has to be disabled to change the manager\n");
1297 r = -EINVAL; 1339 r = -EINVAL;
1298 goto err; 1340 goto err1;
1299 } 1341 }
1300 1342
1301 op->channel = mgr->id; 1343 dispc_ovl_set_channel_out(ovl->id, mgr->id);
1302 op->extra_info_dirty = true;
1303 1344
1304 ovl->manager = mgr; 1345 ovl->manager = mgr;
1305 list_add_tail(&ovl->list, &mgr->overlays); 1346 list_add_tail(&ovl->list, &mgr->overlays);
1306 1347
1307 spin_unlock_irqrestore(&data_lock, flags); 1348 spin_unlock_irqrestore(&data_lock, flags);
1308 1349
1309 /* XXX: When there is an overlay on a DSI manual update display, and 1350 dispc_runtime_put();
1310 * the overlay is first disabled, then moved to tv, and enabled, we
1311 * seem to get SYNC_LOST_DIGIT error.
1312 *
1313 * Waiting doesn't seem to help, but updating the manual update display
1314 * after disabling the overlay seems to fix this. This hints that the
1315 * overlay is perhaps somehow tied to the LCD output until the output
1316 * is updated.
1317 *
1318 * Userspace workaround for this is to update the LCD after disabling
1319 * the overlay, but before moving the overlay to TV.
1320 */
1321 1351
1322 mutex_unlock(&apply_lock); 1352 mutex_unlock(&apply_lock);
1323 1353
1324 return 0; 1354 return 0;
1355
1356err1:
1357 dispc_runtime_put();
1325err: 1358err:
1326 mutex_unlock(&apply_lock); 1359 mutex_unlock(&apply_lock);
1327 return r; 1360 return r;
1328} 1361}
1329 1362
1330int dss_ovl_unset_manager(struct omap_overlay *ovl) 1363static int dss_ovl_unset_manager(struct omap_overlay *ovl)
1331{ 1364{
1332 struct ovl_priv_data *op = get_ovl_priv(ovl); 1365 struct ovl_priv_data *op = get_ovl_priv(ovl);
1333 unsigned long flags; 1366 unsigned long flags;
@@ -1355,9 +1388,24 @@ int dss_ovl_unset_manager(struct omap_overlay *ovl)
1355 /* wait for pending extra_info updates to ensure the ovl is disabled */ 1388 /* wait for pending extra_info updates to ensure the ovl is disabled */
1356 wait_pending_extra_info_updates(); 1389 wait_pending_extra_info_updates();
1357 1390
1391 /*
1392 * For a manual update display, there is no guarantee that the overlay
1393 * is really disabled in HW, we may need an extra update from this
1394 * manager before the configurations can go in. Return an error if the
1395 * overlay needed an update from the manager.
1396 *
1397 * TODO: Instead of returning an error, try to do a dummy manager update
1398 * here to disable the overlay in hardware. Use the *GATED fields in
1399 * the DISPC_CONFIG registers to do a dummy update.
1400 */
1358 spin_lock_irqsave(&data_lock, flags); 1401 spin_lock_irqsave(&data_lock, flags);
1359 1402
1360 op->channel = -1; 1403 if (ovl_manual_update(ovl) && op->extra_info_dirty) {
1404 spin_unlock_irqrestore(&data_lock, flags);
1405 DSSERR("need an update to change the manager\n");
1406 r = -EINVAL;
1407 goto err;
1408 }
1361 1409
1362 ovl->manager = NULL; 1410 ovl->manager = NULL;
1363 list_del(&ovl->list); 1411 list_del(&ovl->list);
@@ -1372,7 +1420,7 @@ err:
1372 return r; 1420 return r;
1373} 1421}
1374 1422
1375bool dss_ovl_is_enabled(struct omap_overlay *ovl) 1423static bool dss_ovl_is_enabled(struct omap_overlay *ovl)
1376{ 1424{
1377 struct ovl_priv_data *op = get_ovl_priv(ovl); 1425 struct ovl_priv_data *op = get_ovl_priv(ovl);
1378 unsigned long flags; 1426 unsigned long flags;
@@ -1387,7 +1435,7 @@ bool dss_ovl_is_enabled(struct omap_overlay *ovl)
1387 return e; 1435 return e;
1388} 1436}
1389 1437
1390int dss_ovl_enable(struct omap_overlay *ovl) 1438static int dss_ovl_enable(struct omap_overlay *ovl)
1391{ 1439{
1392 struct ovl_priv_data *op = get_ovl_priv(ovl); 1440 struct ovl_priv_data *op = get_ovl_priv(ovl);
1393 unsigned long flags; 1441 unsigned long flags;
@@ -1437,7 +1485,7 @@ err1:
1437 return r; 1485 return r;
1438} 1486}
1439 1487
1440int dss_ovl_disable(struct omap_overlay *ovl) 1488static int dss_ovl_disable(struct omap_overlay *ovl)
1441{ 1489{
1442 struct ovl_priv_data *op = get_ovl_priv(ovl); 1490 struct ovl_priv_data *op = get_ovl_priv(ovl);
1443 unsigned long flags; 1491 unsigned long flags;
@@ -1472,3 +1520,152 @@ err:
1472 return r; 1520 return r;
1473} 1521}
1474 1522
1523static int dss_mgr_register_framedone_handler_compat(struct omap_overlay_manager *mgr,
1524 void (*handler)(void *), void *data)
1525{
1526 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1527
1528 if (mp->framedone_handler)
1529 return -EBUSY;
1530
1531 mp->framedone_handler = handler;
1532 mp->framedone_handler_data = data;
1533
1534 return 0;
1535}
1536
1537static void dss_mgr_unregister_framedone_handler_compat(struct omap_overlay_manager *mgr,
1538 void (*handler)(void *), void *data)
1539{
1540 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1541
1542 WARN_ON(mp->framedone_handler != handler ||
1543 mp->framedone_handler_data != data);
1544
1545 mp->framedone_handler = NULL;
1546 mp->framedone_handler_data = NULL;
1547}
1548
1549static const struct dss_mgr_ops apply_mgr_ops = {
1550 .start_update = dss_mgr_start_update_compat,
1551 .enable = dss_mgr_enable_compat,
1552 .disable = dss_mgr_disable_compat,
1553 .set_timings = dss_mgr_set_timings_compat,
1554 .set_lcd_config = dss_mgr_set_lcd_config_compat,
1555 .register_framedone_handler = dss_mgr_register_framedone_handler_compat,
1556 .unregister_framedone_handler = dss_mgr_unregister_framedone_handler_compat,
1557};
1558
1559static int compat_refcnt;
1560static DEFINE_MUTEX(compat_init_lock);
1561
1562int omapdss_compat_init(void)
1563{
1564 struct platform_device *pdev = dss_get_core_pdev();
1565 struct omap_dss_device *dssdev = NULL;
1566 int i, r;
1567
1568 mutex_lock(&compat_init_lock);
1569
1570 if (compat_refcnt++ > 0)
1571 goto out;
1572
1573 apply_init_priv();
1574
1575 dss_init_overlay_managers(pdev);
1576 dss_init_overlays(pdev);
1577
1578 for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
1579 struct omap_overlay_manager *mgr;
1580
1581 mgr = omap_dss_get_overlay_manager(i);
1582
1583 mgr->set_output = &dss_mgr_set_output;
1584 mgr->unset_output = &dss_mgr_unset_output;
1585 mgr->apply = &omap_dss_mgr_apply;
1586 mgr->set_manager_info = &dss_mgr_set_info;
1587 mgr->get_manager_info = &dss_mgr_get_info;
1588 mgr->wait_for_go = &dss_mgr_wait_for_go;
1589 mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
1590 mgr->get_device = &dss_mgr_get_device;
1591 }
1592
1593 for (i = 0; i < omap_dss_get_num_overlays(); i++) {
1594 struct omap_overlay *ovl = omap_dss_get_overlay(i);
1595
1596 ovl->is_enabled = &dss_ovl_is_enabled;
1597 ovl->enable = &dss_ovl_enable;
1598 ovl->disable = &dss_ovl_disable;
1599 ovl->set_manager = &dss_ovl_set_manager;
1600 ovl->unset_manager = &dss_ovl_unset_manager;
1601 ovl->set_overlay_info = &dss_ovl_set_info;
1602 ovl->get_overlay_info = &dss_ovl_get_info;
1603 ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
1604 ovl->get_device = &dss_ovl_get_device;
1605 }
1606
1607 r = dss_install_mgr_ops(&apply_mgr_ops);
1608 if (r)
1609 goto err_mgr_ops;
1610
1611 for_each_dss_dev(dssdev) {
1612 r = display_init_sysfs(pdev, dssdev);
1613 /* XXX uninit sysfs files on error */
1614 if (r)
1615 goto err_disp_sysfs;
1616 }
1617
1618 dispc_runtime_get();
1619
1620 r = dss_dispc_initialize_irq();
1621 if (r)
1622 goto err_init_irq;
1623
1624 dispc_runtime_put();
1625
1626out:
1627 mutex_unlock(&compat_init_lock);
1628
1629 return 0;
1630
1631err_init_irq:
1632 dispc_runtime_put();
1633
1634err_disp_sysfs:
1635 dss_uninstall_mgr_ops();
1636
1637err_mgr_ops:
1638 dss_uninit_overlay_managers(pdev);
1639 dss_uninit_overlays(pdev);
1640
1641 compat_refcnt--;
1642
1643 mutex_unlock(&compat_init_lock);
1644
1645 return r;
1646}
1647EXPORT_SYMBOL(omapdss_compat_init);
1648
1649void omapdss_compat_uninit(void)
1650{
1651 struct platform_device *pdev = dss_get_core_pdev();
1652 struct omap_dss_device *dssdev = NULL;
1653
1654 mutex_lock(&compat_init_lock);
1655
1656 if (--compat_refcnt > 0)
1657 goto out;
1658
1659 dss_dispc_uninitialize_irq();
1660
1661 for_each_dss_dev(dssdev)
1662 display_uninit_sysfs(pdev, dssdev);
1663
1664 dss_uninstall_mgr_ops();
1665
1666 dss_uninit_overlay_managers(pdev);
1667 dss_uninit_overlays(pdev);
1668out:
1669 mutex_unlock(&compat_init_lock);
1670}
1671EXPORT_SYMBOL(omapdss_compat_uninit);
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index b2af72dc20bd..f8779d4750ba 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -53,15 +53,23 @@ static char *def_disp_name;
53module_param_named(def_disp, def_disp_name, charp, 0); 53module_param_named(def_disp, def_disp_name, charp, 0);
54MODULE_PARM_DESC(def_disp, "default display name"); 54MODULE_PARM_DESC(def_disp, "default display name");
55 55
56#ifdef DEBUG 56const char *omapdss_get_default_display_name(void)
57bool dss_debug;
58module_param_named(debug, dss_debug, bool, 0644);
59#endif
60
61const char *dss_get_default_display_name(void)
62{ 57{
63 return core.default_display_name; 58 return core.default_display_name;
64} 59}
60EXPORT_SYMBOL(omapdss_get_default_display_name);
61
62enum omapdss_version omapdss_get_version(void)
63{
64 struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
65 return pdata->version;
66}
67EXPORT_SYMBOL(omapdss_get_version);
68
69struct platform_device *dss_get_core_pdev(void)
70{
71 return core.pdev;
72}
65 73
66/* REGULATORS */ 74/* REGULATORS */
67 75
@@ -93,21 +101,6 @@ struct regulator *dss_get_vdds_sdi(void)
93 return reg; 101 return reg;
94} 102}
95 103
96int dss_get_ctx_loss_count(struct device *dev)
97{
98 struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
99 int cnt;
100
101 if (!board_data->get_context_loss_count)
102 return -ENOENT;
103
104 cnt = board_data->get_context_loss_count(dev);
105
106 WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
107
108 return cnt;
109}
110
111int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask) 104int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask)
112{ 105{
113 struct omap_dss_board_info *board_data = core.pdev->dev.platform_data; 106 struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
@@ -122,7 +115,7 @@ void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask)
122{ 115{
123 struct omap_dss_board_info *board_data = core.pdev->dev.platform_data; 116 struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
124 117
125 if (!board_data->dsi_enable_pads) 118 if (!board_data->dsi_disable_pads)
126 return; 119 return;
127 120
128 return board_data->dsi_disable_pads(dsi_id, lane_mask); 121 return board_data->dsi_disable_pads(dsi_id, lane_mask);
@@ -138,7 +131,7 @@ int dss_set_min_bus_tput(struct device *dev, unsigned long tput)
138 return 0; 131 return 0;
139} 132}
140 133
141#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) 134#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
142static int dss_debug_show(struct seq_file *s, void *unused) 135static int dss_debug_show(struct seq_file *s, void *unused)
143{ 136{
144 void (*func)(struct seq_file *) = s->private; 137 void (*func)(struct seq_file *) = s->private;
@@ -193,7 +186,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
193 186
194 return 0; 187 return 0;
195} 188}
196#else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ 189#else /* CONFIG_OMAP2_DSS_DEBUGFS */
197static inline int dss_initialize_debugfs(void) 190static inline int dss_initialize_debugfs(void)
198{ 191{
199 return 0; 192 return 0;
@@ -205,7 +198,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
205{ 198{
206 return 0; 199 return 0;
207} 200}
208#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ 201#endif /* CONFIG_OMAP2_DSS_DEBUGFS */
209 202
210/* PLATFORM DEVICE */ 203/* PLATFORM DEVICE */
211static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d) 204static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d)
@@ -237,12 +230,7 @@ static int __init omap_dss_probe(struct platform_device *pdev)
237 230
238 core.pdev = pdev; 231 core.pdev = pdev;
239 232
240 dss_features_init(); 233 dss_features_init(omapdss_get_version());
241
242 dss_apply_init();
243
244 dss_init_overlay_managers(pdev);
245 dss_init_overlays(pdev);
246 234
247 r = dss_initialize_debugfs(); 235 r = dss_initialize_debugfs();
248 if (r) 236 if (r)
@@ -268,9 +256,6 @@ static int omap_dss_remove(struct platform_device *pdev)
268 256
269 dss_uninitialize_debugfs(); 257 dss_uninitialize_debugfs();
270 258
271 dss_uninit_overlays(pdev);
272 dss_uninit_overlay_managers(pdev);
273
274 return 0; 259 return 0;
275} 260}
276 261
@@ -358,15 +343,10 @@ static int dss_driver_probe(struct device *dev)
358 dev_name(dev), dssdev->driver_name, 343 dev_name(dev), dssdev->driver_name,
359 dssdrv->driver.name); 344 dssdrv->driver.name);
360 345
361 r = dss_init_device(core.pdev, dssdev);
362 if (r)
363 return r;
364
365 r = dssdrv->probe(dssdev); 346 r = dssdrv->probe(dssdev);
366 347
367 if (r) { 348 if (r) {
368 DSSERR("driver probe failed: %d\n", r); 349 DSSERR("driver probe failed: %d\n", r);
369 dss_uninit_device(core.pdev, dssdev);
370 return r; 350 return r;
371 } 351 }
372 352
@@ -387,8 +367,6 @@ static int dss_driver_remove(struct device *dev)
387 367
388 dssdrv->remove(dssdev); 368 dssdrv->remove(dssdev);
389 369
390 dss_uninit_device(core.pdev, dssdev);
391
392 dssdev->driver = NULL; 370 dssdev->driver = NULL;
393 371
394 return 0; 372 return 0;
@@ -507,6 +485,9 @@ static int __init omap_dss_bus_register(void)
507 485
508/* INIT */ 486/* INIT */
509static int (*dss_output_drv_reg_funcs[])(void) __initdata = { 487static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
488#ifdef CONFIG_OMAP2_DSS_DSI
489 dsi_init_platform_driver,
490#endif
510#ifdef CONFIG_OMAP2_DSS_DPI 491#ifdef CONFIG_OMAP2_DSS_DPI
511 dpi_init_platform_driver, 492 dpi_init_platform_driver,
512#endif 493#endif
@@ -519,15 +500,15 @@ static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
519#ifdef CONFIG_OMAP2_DSS_VENC 500#ifdef CONFIG_OMAP2_DSS_VENC
520 venc_init_platform_driver, 501 venc_init_platform_driver,
521#endif 502#endif
522#ifdef CONFIG_OMAP2_DSS_DSI
523 dsi_init_platform_driver,
524#endif
525#ifdef CONFIG_OMAP4_DSS_HDMI 503#ifdef CONFIG_OMAP4_DSS_HDMI
526 hdmi_init_platform_driver, 504 hdmi_init_platform_driver,
527#endif 505#endif
528}; 506};
529 507
530static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = { 508static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
509#ifdef CONFIG_OMAP2_DSS_DSI
510 dsi_uninit_platform_driver,
511#endif
531#ifdef CONFIG_OMAP2_DSS_DPI 512#ifdef CONFIG_OMAP2_DSS_DPI
532 dpi_uninit_platform_driver, 513 dpi_uninit_platform_driver,
533#endif 514#endif
@@ -540,9 +521,6 @@ static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
540#ifdef CONFIG_OMAP2_DSS_VENC 521#ifdef CONFIG_OMAP2_DSS_VENC
541 venc_uninit_platform_driver, 522 venc_uninit_platform_driver,
542#endif 523#endif
543#ifdef CONFIG_OMAP2_DSS_DSI
544 dsi_uninit_platform_driver,
545#endif
546#ifdef CONFIG_OMAP4_DSS_HDMI 524#ifdef CONFIG_OMAP4_DSS_HDMI
547 hdmi_uninit_platform_driver, 525 hdmi_uninit_platform_driver,
548#endif 526#endif
diff --git a/drivers/video/omap2/dss/dispc-compat.c b/drivers/video/omap2/dss/dispc-compat.c
new file mode 100644
index 000000000000..928884c9a0a9
--- /dev/null
+++ b/drivers/video/omap2/dss/dispc-compat.c
@@ -0,0 +1,667 @@
1/*
2 * Copyright (C) 2012 Texas Instruments
3 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#define DSS_SUBSYS_NAME "APPLY"
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/slab.h>
23#include <linux/spinlock.h>
24#include <linux/jiffies.h>
25#include <linux/delay.h>
26#include <linux/interrupt.h>
27#include <linux/seq_file.h>
28
29#include <video/omapdss.h>
30
31#include "dss.h"
32#include "dss_features.h"
33#include "dispc-compat.h"
34
35#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
36 DISPC_IRQ_OCP_ERR | \
37 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
38 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
39 DISPC_IRQ_SYNC_LOST | \
40 DISPC_IRQ_SYNC_LOST_DIGIT)
41
42#define DISPC_MAX_NR_ISRS 8
43
44struct omap_dispc_isr_data {
45 omap_dispc_isr_t isr;
46 void *arg;
47 u32 mask;
48};
49
50struct dispc_irq_stats {
51 unsigned long last_reset;
52 unsigned irq_count;
53 unsigned irqs[32];
54};
55
56static struct {
57 spinlock_t irq_lock;
58 u32 irq_error_mask;
59 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
60 u32 error_irqs;
61 struct work_struct error_work;
62
63#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
64 spinlock_t irq_stats_lock;
65 struct dispc_irq_stats irq_stats;
66#endif
67} dispc_compat;
68
69
70#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
71static void dispc_dump_irqs(struct seq_file *s)
72{
73 unsigned long flags;
74 struct dispc_irq_stats stats;
75
76 spin_lock_irqsave(&dispc_compat.irq_stats_lock, flags);
77
78 stats = dispc_compat.irq_stats;
79 memset(&dispc_compat.irq_stats, 0, sizeof(dispc_compat.irq_stats));
80 dispc_compat.irq_stats.last_reset = jiffies;
81
82 spin_unlock_irqrestore(&dispc_compat.irq_stats_lock, flags);
83
84 seq_printf(s, "period %u ms\n",
85 jiffies_to_msecs(jiffies - stats.last_reset));
86
87 seq_printf(s, "irqs %d\n", stats.irq_count);
88#define PIS(x) \
89 seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
90
91 PIS(FRAMEDONE);
92 PIS(VSYNC);
93 PIS(EVSYNC_EVEN);
94 PIS(EVSYNC_ODD);
95 PIS(ACBIAS_COUNT_STAT);
96 PIS(PROG_LINE_NUM);
97 PIS(GFX_FIFO_UNDERFLOW);
98 PIS(GFX_END_WIN);
99 PIS(PAL_GAMMA_MASK);
100 PIS(OCP_ERR);
101 PIS(VID1_FIFO_UNDERFLOW);
102 PIS(VID1_END_WIN);
103 PIS(VID2_FIFO_UNDERFLOW);
104 PIS(VID2_END_WIN);
105 if (dss_feat_get_num_ovls() > 3) {
106 PIS(VID3_FIFO_UNDERFLOW);
107 PIS(VID3_END_WIN);
108 }
109 PIS(SYNC_LOST);
110 PIS(SYNC_LOST_DIGIT);
111 PIS(WAKEUP);
112 if (dss_has_feature(FEAT_MGR_LCD2)) {
113 PIS(FRAMEDONE2);
114 PIS(VSYNC2);
115 PIS(ACBIAS_COUNT_STAT2);
116 PIS(SYNC_LOST2);
117 }
118 if (dss_has_feature(FEAT_MGR_LCD3)) {
119 PIS(FRAMEDONE3);
120 PIS(VSYNC3);
121 PIS(ACBIAS_COUNT_STAT3);
122 PIS(SYNC_LOST3);
123 }
124#undef PIS
125}
126#endif
127
128/* dispc.irq_lock has to be locked by the caller */
129static void _omap_dispc_set_irqs(void)
130{
131 u32 mask;
132 int i;
133 struct omap_dispc_isr_data *isr_data;
134
135 mask = dispc_compat.irq_error_mask;
136
137 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
138 isr_data = &dispc_compat.registered_isr[i];
139
140 if (isr_data->isr == NULL)
141 continue;
142
143 mask |= isr_data->mask;
144 }
145
146 dispc_write_irqenable(mask);
147}
148
149int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
150{
151 int i;
152 int ret;
153 unsigned long flags;
154 struct omap_dispc_isr_data *isr_data;
155
156 if (isr == NULL)
157 return -EINVAL;
158
159 spin_lock_irqsave(&dispc_compat.irq_lock, flags);
160
161 /* check for duplicate entry */
162 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
163 isr_data = &dispc_compat.registered_isr[i];
164 if (isr_data->isr == isr && isr_data->arg == arg &&
165 isr_data->mask == mask) {
166 ret = -EINVAL;
167 goto err;
168 }
169 }
170
171 isr_data = NULL;
172 ret = -EBUSY;
173
174 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
175 isr_data = &dispc_compat.registered_isr[i];
176
177 if (isr_data->isr != NULL)
178 continue;
179
180 isr_data->isr = isr;
181 isr_data->arg = arg;
182 isr_data->mask = mask;
183 ret = 0;
184
185 break;
186 }
187
188 if (ret)
189 goto err;
190
191 _omap_dispc_set_irqs();
192
193 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
194
195 return 0;
196err:
197 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
198
199 return ret;
200}
201EXPORT_SYMBOL(omap_dispc_register_isr);
202
203int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
204{
205 int i;
206 unsigned long flags;
207 int ret = -EINVAL;
208 struct omap_dispc_isr_data *isr_data;
209
210 spin_lock_irqsave(&dispc_compat.irq_lock, flags);
211
212 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
213 isr_data = &dispc_compat.registered_isr[i];
214 if (isr_data->isr != isr || isr_data->arg != arg ||
215 isr_data->mask != mask)
216 continue;
217
218 /* found the correct isr */
219
220 isr_data->isr = NULL;
221 isr_data->arg = NULL;
222 isr_data->mask = 0;
223
224 ret = 0;
225 break;
226 }
227
228 if (ret == 0)
229 _omap_dispc_set_irqs();
230
231 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
232
233 return ret;
234}
235EXPORT_SYMBOL(omap_dispc_unregister_isr);
236
237static void print_irq_status(u32 status)
238{
239 if ((status & dispc_compat.irq_error_mask) == 0)
240 return;
241
242#define PIS(x) (status & DISPC_IRQ_##x) ? (#x " ") : ""
243
244 pr_debug("DISPC IRQ: 0x%x: %s%s%s%s%s%s%s%s%s\n",
245 status,
246 PIS(OCP_ERR),
247 PIS(GFX_FIFO_UNDERFLOW),
248 PIS(VID1_FIFO_UNDERFLOW),
249 PIS(VID2_FIFO_UNDERFLOW),
250 dss_feat_get_num_ovls() > 3 ? PIS(VID3_FIFO_UNDERFLOW) : "",
251 PIS(SYNC_LOST),
252 PIS(SYNC_LOST_DIGIT),
253 dss_has_feature(FEAT_MGR_LCD2) ? PIS(SYNC_LOST2) : "",
254 dss_has_feature(FEAT_MGR_LCD3) ? PIS(SYNC_LOST3) : "");
255#undef PIS
256}
257
258/* Called from dss.c. Note that we don't touch clocks here,
259 * but we presume they are on because we got an IRQ. However,
260 * an irq handler may turn the clocks off, so we may not have
261 * clock later in the function. */
262static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
263{
264 int i;
265 u32 irqstatus, irqenable;
266 u32 handledirqs = 0;
267 u32 unhandled_errors;
268 struct omap_dispc_isr_data *isr_data;
269 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
270
271 spin_lock(&dispc_compat.irq_lock);
272
273 irqstatus = dispc_read_irqstatus();
274 irqenable = dispc_read_irqenable();
275
276 /* IRQ is not for us */
277 if (!(irqstatus & irqenable)) {
278 spin_unlock(&dispc_compat.irq_lock);
279 return IRQ_NONE;
280 }
281
282#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
283 spin_lock(&dispc_compat.irq_stats_lock);
284 dispc_compat.irq_stats.irq_count++;
285 dss_collect_irq_stats(irqstatus, dispc_compat.irq_stats.irqs);
286 spin_unlock(&dispc_compat.irq_stats_lock);
287#endif
288
289 print_irq_status(irqstatus);
290
291 /* Ack the interrupt. Do it here before clocks are possibly turned
292 * off */
293 dispc_clear_irqstatus(irqstatus);
294 /* flush posted write */
295 dispc_read_irqstatus();
296
297 /* make a copy and unlock, so that isrs can unregister
298 * themselves */
299 memcpy(registered_isr, dispc_compat.registered_isr,
300 sizeof(registered_isr));
301
302 spin_unlock(&dispc_compat.irq_lock);
303
304 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
305 isr_data = &registered_isr[i];
306
307 if (!isr_data->isr)
308 continue;
309
310 if (isr_data->mask & irqstatus) {
311 isr_data->isr(isr_data->arg, irqstatus);
312 handledirqs |= isr_data->mask;
313 }
314 }
315
316 spin_lock(&dispc_compat.irq_lock);
317
318 unhandled_errors = irqstatus & ~handledirqs & dispc_compat.irq_error_mask;
319
320 if (unhandled_errors) {
321 dispc_compat.error_irqs |= unhandled_errors;
322
323 dispc_compat.irq_error_mask &= ~unhandled_errors;
324 _omap_dispc_set_irqs();
325
326 schedule_work(&dispc_compat.error_work);
327 }
328
329 spin_unlock(&dispc_compat.irq_lock);
330
331 return IRQ_HANDLED;
332}
333
334static void dispc_error_worker(struct work_struct *work)
335{
336 int i;
337 u32 errors;
338 unsigned long flags;
339 static const unsigned fifo_underflow_bits[] = {
340 DISPC_IRQ_GFX_FIFO_UNDERFLOW,
341 DISPC_IRQ_VID1_FIFO_UNDERFLOW,
342 DISPC_IRQ_VID2_FIFO_UNDERFLOW,
343 DISPC_IRQ_VID3_FIFO_UNDERFLOW,
344 };
345
346 spin_lock_irqsave(&dispc_compat.irq_lock, flags);
347 errors = dispc_compat.error_irqs;
348 dispc_compat.error_irqs = 0;
349 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
350
351 dispc_runtime_get();
352
353 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
354 struct omap_overlay *ovl;
355 unsigned bit;
356
357 ovl = omap_dss_get_overlay(i);
358 bit = fifo_underflow_bits[i];
359
360 if (bit & errors) {
361 DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
362 ovl->name);
363 dispc_ovl_enable(ovl->id, false);
364 dispc_mgr_go(ovl->manager->id);
365 msleep(50);
366 }
367 }
368
369 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
370 struct omap_overlay_manager *mgr;
371 unsigned bit;
372
373 mgr = omap_dss_get_overlay_manager(i);
374 bit = dispc_mgr_get_sync_lost_irq(i);
375
376 if (bit & errors) {
377 int j;
378
379 DSSERR("SYNC_LOST on channel %s, restarting the output "
380 "with video overlays disabled\n",
381 mgr->name);
382
383 dss_mgr_disable(mgr);
384
385 for (j = 0; j < omap_dss_get_num_overlays(); ++j) {
386 struct omap_overlay *ovl;
387 ovl = omap_dss_get_overlay(j);
388
389 if (ovl->id != OMAP_DSS_GFX &&
390 ovl->manager == mgr)
391 ovl->disable(ovl);
392 }
393
394 dss_mgr_enable(mgr);
395 }
396 }
397
398 if (errors & DISPC_IRQ_OCP_ERR) {
399 DSSERR("OCP_ERR\n");
400 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
401 struct omap_overlay_manager *mgr;
402
403 mgr = omap_dss_get_overlay_manager(i);
404 dss_mgr_disable(mgr);
405 }
406 }
407
408 spin_lock_irqsave(&dispc_compat.irq_lock, flags);
409 dispc_compat.irq_error_mask |= errors;
410 _omap_dispc_set_irqs();
411 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
412
413 dispc_runtime_put();
414}
415
416int dss_dispc_initialize_irq(void)
417{
418 int r;
419
420#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
421 spin_lock_init(&dispc_compat.irq_stats_lock);
422 dispc_compat.irq_stats.last_reset = jiffies;
423 dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
424#endif
425
426 spin_lock_init(&dispc_compat.irq_lock);
427
428 memset(dispc_compat.registered_isr, 0,
429 sizeof(dispc_compat.registered_isr));
430
431 dispc_compat.irq_error_mask = DISPC_IRQ_MASK_ERROR;
432 if (dss_has_feature(FEAT_MGR_LCD2))
433 dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
434 if (dss_has_feature(FEAT_MGR_LCD3))
435 dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
436 if (dss_feat_get_num_ovls() > 3)
437 dispc_compat.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
438
439 /*
440 * there's SYNC_LOST_DIGIT waiting after enabling the DSS,
441 * so clear it
442 */
443 dispc_clear_irqstatus(dispc_read_irqstatus());
444
445 INIT_WORK(&dispc_compat.error_work, dispc_error_worker);
446
447 _omap_dispc_set_irqs();
448
449 r = dispc_request_irq(omap_dispc_irq_handler, &dispc_compat);
450 if (r) {
451 DSSERR("dispc_request_irq failed\n");
452 return r;
453 }
454
455 return 0;
456}
457
458void dss_dispc_uninitialize_irq(void)
459{
460 dispc_free_irq(&dispc_compat);
461}
462
463static void dispc_mgr_disable_isr(void *data, u32 mask)
464{
465 struct completion *compl = data;
466 complete(compl);
467}
468
469static void dispc_mgr_enable_lcd_out(enum omap_channel channel)
470{
471 dispc_mgr_enable(channel, true);
472}
473
474static void dispc_mgr_disable_lcd_out(enum omap_channel channel)
475{
476 DECLARE_COMPLETION_ONSTACK(framedone_compl);
477 int r;
478 u32 irq;
479
480 if (dispc_mgr_is_enabled(channel) == false)
481 return;
482
483 /*
484 * When we disable LCD output, we need to wait for FRAMEDONE to know
485 * that DISPC has finished with the LCD output.
486 */
487
488 irq = dispc_mgr_get_framedone_irq(channel);
489
490 r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
491 irq);
492 if (r)
493 DSSERR("failed to register FRAMEDONE isr\n");
494
495 dispc_mgr_enable(channel, false);
496
497 /* if we couldn't register for framedone, just sleep and exit */
498 if (r) {
499 msleep(100);
500 return;
501 }
502
503 if (!wait_for_completion_timeout(&framedone_compl,
504 msecs_to_jiffies(100)))
505 DSSERR("timeout waiting for FRAME DONE\n");
506
507 r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
508 irq);
509 if (r)
510 DSSERR("failed to unregister FRAMEDONE isr\n");
511}
512
513static void dispc_digit_out_enable_isr(void *data, u32 mask)
514{
515 struct completion *compl = data;
516
517 /* ignore any sync lost interrupts */
518 if (mask & (DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD))
519 complete(compl);
520}
521
522static void dispc_mgr_enable_digit_out(void)
523{
524 DECLARE_COMPLETION_ONSTACK(vsync_compl);
525 int r;
526 u32 irq_mask;
527
528 if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == true)
529 return;
530
531 /*
532 * Digit output produces some sync lost interrupts during the first
533 * frame when enabling. Those need to be ignored, so we register for the
534 * sync lost irq to prevent the error handler from triggering.
535 */
536
537 irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT) |
538 dispc_mgr_get_sync_lost_irq(OMAP_DSS_CHANNEL_DIGIT);
539
540 r = omap_dispc_register_isr(dispc_digit_out_enable_isr, &vsync_compl,
541 irq_mask);
542 if (r) {
543 DSSERR("failed to register %x isr\n", irq_mask);
544 return;
545 }
546
547 dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, true);
548
549 /* wait for the first evsync */
550 if (!wait_for_completion_timeout(&vsync_compl, msecs_to_jiffies(100)))
551 DSSERR("timeout waiting for digit out to start\n");
552
553 r = omap_dispc_unregister_isr(dispc_digit_out_enable_isr, &vsync_compl,
554 irq_mask);
555 if (r)
556 DSSERR("failed to unregister %x isr\n", irq_mask);
557}
558
559static void dispc_mgr_disable_digit_out(void)
560{
561 DECLARE_COMPLETION_ONSTACK(framedone_compl);
562 int r, i;
563 u32 irq_mask;
564 int num_irqs;
565
566 if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == false)
567 return;
568
569 /*
570 * When we disable the digit output, we need to wait for FRAMEDONE to
571 * know that DISPC has finished with the output.
572 */
573
574 irq_mask = dispc_mgr_get_framedone_irq(OMAP_DSS_CHANNEL_DIGIT);
575 num_irqs = 1;
576
577 if (!irq_mask) {
578 /*
579 * omap 2/3 don't have framedone irq for TV, so we need to use
580 * vsyncs for this.
581 */
582
583 irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT);
584 /*
585 * We need to wait for both even and odd vsyncs. Note that this
586 * is not totally reliable, as we could get a vsync interrupt
587 * before we disable the output, which leads to timeout in the
588 * wait_for_completion.
589 */
590 num_irqs = 2;
591 }
592
593 r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
594 irq_mask);
595 if (r)
596 DSSERR("failed to register %x isr\n", irq_mask);
597
598 dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, false);
599
600 /* if we couldn't register the irq, just sleep and exit */
601 if (r) {
602 msleep(100);
603 return;
604 }
605
606 for (i = 0; i < num_irqs; ++i) {
607 if (!wait_for_completion_timeout(&framedone_compl,
608 msecs_to_jiffies(100)))
609 DSSERR("timeout waiting for digit out to stop\n");
610 }
611
612 r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
613 irq_mask);
614 if (r)
615 DSSERR("failed to unregister %x isr\n", irq_mask);
616}
617
618void dispc_mgr_enable_sync(enum omap_channel channel)
619{
620 if (dss_mgr_is_lcd(channel))
621 dispc_mgr_enable_lcd_out(channel);
622 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
623 dispc_mgr_enable_digit_out();
624 else
625 WARN_ON(1);
626}
627
628void dispc_mgr_disable_sync(enum omap_channel channel)
629{
630 if (dss_mgr_is_lcd(channel))
631 dispc_mgr_disable_lcd_out(channel);
632 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
633 dispc_mgr_disable_digit_out();
634 else
635 WARN_ON(1);
636}
637
638int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
639 unsigned long timeout)
640{
641 void dispc_irq_wait_handler(void *data, u32 mask)
642 {
643 complete((struct completion *)data);
644 }
645
646 int r;
647 DECLARE_COMPLETION_ONSTACK(completion);
648
649 r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
650 irqmask);
651
652 if (r)
653 return r;
654
655 timeout = wait_for_completion_interruptible_timeout(&completion,
656 timeout);
657
658 omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
659
660 if (timeout == 0)
661 return -ETIMEDOUT;
662
663 if (timeout == -ERESTARTSYS)
664 return -ERESTARTSYS;
665
666 return 0;
667}
diff --git a/drivers/video/omap2/dss/dispc-compat.h b/drivers/video/omap2/dss/dispc-compat.h
new file mode 100644
index 000000000000..14a69b3d4fb0
--- /dev/null
+++ b/drivers/video/omap2/dss/dispc-compat.h
@@ -0,0 +1,30 @@
1/*
2 * Copyright (C) 2012 Texas Instruments
3 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef __OMAP2_DSS_DISPC_COMPAT_H
19#define __OMAP2_DSS_DISPC_COMPAT_H
20
21void dispc_mgr_enable_sync(enum omap_channel channel);
22void dispc_mgr_disable_sync(enum omap_channel channel);
23
24int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
25 unsigned long timeout);
26
27int dss_dispc_initialize_irq(void);
28void dss_dispc_uninitialize_irq(void);
29
30#endif
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index b43477a5fae8..05ff2b91d9e8 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -33,11 +33,9 @@
33#include <linux/delay.h> 33#include <linux/delay.h>
34#include <linux/workqueue.h> 34#include <linux/workqueue.h>
35#include <linux/hardirq.h> 35#include <linux/hardirq.h>
36#include <linux/interrupt.h>
37#include <linux/platform_device.h> 36#include <linux/platform_device.h>
38#include <linux/pm_runtime.h> 37#include <linux/pm_runtime.h>
39 38#include <linux/sizes.h>
40#include <plat/cpu.h>
41 39
42#include <video/omapdss.h> 40#include <video/omapdss.h>
43 41
@@ -48,21 +46,6 @@
48/* DISPC */ 46/* DISPC */
49#define DISPC_SZ_REGS SZ_4K 47#define DISPC_SZ_REGS SZ_4K
50 48
51#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
52 DISPC_IRQ_OCP_ERR | \
53 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
54 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
55 DISPC_IRQ_SYNC_LOST | \
56 DISPC_IRQ_SYNC_LOST_DIGIT)
57
58#define DISPC_MAX_NR_ISRS 8
59
60struct omap_dispc_isr_data {
61 omap_dispc_isr_t isr;
62 void *arg;
63 u32 mask;
64};
65
66enum omap_burst_size { 49enum omap_burst_size {
67 BURST_SIZE_X2 = 0, 50 BURST_SIZE_X2 = 0,
68 BURST_SIZE_X4 = 1, 51 BURST_SIZE_X4 = 1,
@@ -75,12 +58,6 @@ enum omap_burst_size {
75#define REG_FLD_MOD(idx, val, start, end) \ 58#define REG_FLD_MOD(idx, val, start, end) \
76 dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end)) 59 dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
77 60
78struct dispc_irq_stats {
79 unsigned long last_reset;
80 unsigned irq_count;
81 unsigned irqs[32];
82};
83
84struct dispc_features { 61struct dispc_features {
85 u8 sw_start; 62 u8 sw_start;
86 u8 fp_start; 63 u8 fp_start;
@@ -88,19 +65,26 @@ struct dispc_features {
88 u16 sw_max; 65 u16 sw_max;
89 u16 vp_max; 66 u16 vp_max;
90 u16 hp_max; 67 u16 hp_max;
91 int (*calc_scaling) (enum omap_plane plane, 68 u8 mgr_width_start;
69 u8 mgr_height_start;
70 u16 mgr_width_max;
71 u16 mgr_height_max;
72 int (*calc_scaling) (unsigned long pclk, unsigned long lclk,
92 const struct omap_video_timings *mgr_timings, 73 const struct omap_video_timings *mgr_timings,
93 u16 width, u16 height, u16 out_width, u16 out_height, 74 u16 width, u16 height, u16 out_width, u16 out_height,
94 enum omap_color_mode color_mode, bool *five_taps, 75 enum omap_color_mode color_mode, bool *five_taps,
95 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, 76 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
96 u16 pos_x, unsigned long *core_clk, bool mem_to_mem); 77 u16 pos_x, unsigned long *core_clk, bool mem_to_mem);
97 unsigned long (*calc_core_clk) (enum omap_plane plane, 78 unsigned long (*calc_core_clk) (unsigned long pclk,
98 u16 width, u16 height, u16 out_width, u16 out_height, 79 u16 width, u16 height, u16 out_width, u16 out_height,
99 bool mem_to_mem); 80 bool mem_to_mem);
100 u8 num_fifos; 81 u8 num_fifos;
101 82
102 /* swap GFX & WB fifos */ 83 /* swap GFX & WB fifos */
103 bool gfx_fifo_workaround:1; 84 bool gfx_fifo_workaround:1;
85
86 /* no DISPC_IRQ_FRAMEDONETV on this SoC */
87 bool no_framedone_tv:1;
104}; 88};
105 89
106#define DISPC_MAX_NR_FIFOS 5 90#define DISPC_MAX_NR_FIFOS 5
@@ -112,27 +96,15 @@ static struct {
112 int ctx_loss_cnt; 96 int ctx_loss_cnt;
113 97
114 int irq; 98 int irq;
115 struct clk *dss_clk;
116 99
117 u32 fifo_size[DISPC_MAX_NR_FIFOS]; 100 u32 fifo_size[DISPC_MAX_NR_FIFOS];
118 /* maps which plane is using a fifo. fifo-id -> plane-id */ 101 /* maps which plane is using a fifo. fifo-id -> plane-id */
119 int fifo_assignment[DISPC_MAX_NR_FIFOS]; 102 int fifo_assignment[DISPC_MAX_NR_FIFOS];
120 103
121 spinlock_t irq_lock;
122 u32 irq_error_mask;
123 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
124 u32 error_irqs;
125 struct work_struct error_work;
126
127 bool ctx_valid; 104 bool ctx_valid;
128 u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; 105 u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
129 106
130 const struct dispc_features *feat; 107 const struct dispc_features *feat;
131
132#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
133 spinlock_t irq_stats_lock;
134 struct dispc_irq_stats irq_stats;
135#endif
136} dispc; 108} dispc;
137 109
138enum omap_color_component { 110enum omap_color_component {
@@ -188,7 +160,7 @@ static const struct {
188 [OMAP_DSS_CHANNEL_DIGIT] = { 160 [OMAP_DSS_CHANNEL_DIGIT] = {
189 .name = "DIGIT", 161 .name = "DIGIT",
190 .vsync_irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN, 162 .vsync_irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN,
191 .framedone_irq = 0, 163 .framedone_irq = DISPC_IRQ_FRAMEDONETV,
192 .sync_lost_irq = DISPC_IRQ_SYNC_LOST_DIGIT, 164 .sync_lost_irq = DISPC_IRQ_SYNC_LOST_DIGIT,
193 .reg_desc = { 165 .reg_desc = {
194 [DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL, 1, 1 }, 166 [DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL, 1, 1 },
@@ -243,7 +215,6 @@ struct color_conv_coef {
243 int full_range; 215 int full_range;
244}; 216};
245 217
246static void _omap_dispc_set_irqs(void);
247static unsigned long dispc_plane_pclk_rate(enum omap_plane plane); 218static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
248static unsigned long dispc_plane_lclk_rate(enum omap_plane plane); 219static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
249 220
@@ -376,7 +347,7 @@ static void dispc_save_context(void)
376 if (dss_has_feature(FEAT_CORE_CLK_DIV)) 347 if (dss_has_feature(FEAT_CORE_CLK_DIV))
377 SR(DIVISOR); 348 SR(DIVISOR);
378 349
379 dispc.ctx_loss_cnt = dss_get_ctx_loss_count(&dispc.pdev->dev); 350 dispc.ctx_loss_cnt = dss_get_ctx_loss_count();
380 dispc.ctx_valid = true; 351 dispc.ctx_valid = true;
381 352
382 DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt); 353 DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
@@ -391,7 +362,7 @@ static void dispc_restore_context(void)
391 if (!dispc.ctx_valid) 362 if (!dispc.ctx_valid)
392 return; 363 return;
393 364
394 ctx = dss_get_ctx_loss_count(&dispc.pdev->dev); 365 ctx = dss_get_ctx_loss_count();
395 366
396 if (ctx >= 0 && ctx == dispc.ctx_loss_cnt) 367 if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
397 return; 368 return;
@@ -498,7 +469,7 @@ static void dispc_restore_context(void)
498 if (dss_has_feature(FEAT_MGR_LCD3)) 469 if (dss_has_feature(FEAT_MGR_LCD3))
499 RR(CONTROL3); 470 RR(CONTROL3);
500 /* clear spurious SYNC_LOST_DIGIT interrupts */ 471 /* clear spurious SYNC_LOST_DIGIT interrupts */
501 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); 472 dispc_clear_irqstatus(DISPC_IRQ_SYNC_LOST_DIGIT);
502 473
503 /* 474 /*
504 * enable last so IRQs won't trigger before 475 * enable last so IRQs won't trigger before
@@ -522,6 +493,7 @@ int dispc_runtime_get(void)
522 WARN_ON(r < 0); 493 WARN_ON(r < 0);
523 return r < 0 ? r : 0; 494 return r < 0 ? r : 0;
524} 495}
496EXPORT_SYMBOL(dispc_runtime_get);
525 497
526void dispc_runtime_put(void) 498void dispc_runtime_put(void)
527{ 499{
@@ -532,16 +504,28 @@ void dispc_runtime_put(void)
532 r = pm_runtime_put_sync(&dispc.pdev->dev); 504 r = pm_runtime_put_sync(&dispc.pdev->dev);
533 WARN_ON(r < 0 && r != -ENOSYS); 505 WARN_ON(r < 0 && r != -ENOSYS);
534} 506}
507EXPORT_SYMBOL(dispc_runtime_put);
535 508
536u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) 509u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
537{ 510{
538 return mgr_desc[channel].vsync_irq; 511 return mgr_desc[channel].vsync_irq;
539} 512}
513EXPORT_SYMBOL(dispc_mgr_get_vsync_irq);
540 514
541u32 dispc_mgr_get_framedone_irq(enum omap_channel channel) 515u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
542{ 516{
517 if (channel == OMAP_DSS_CHANNEL_DIGIT && dispc.feat->no_framedone_tv)
518 return 0;
519
543 return mgr_desc[channel].framedone_irq; 520 return mgr_desc[channel].framedone_irq;
544} 521}
522EXPORT_SYMBOL(dispc_mgr_get_framedone_irq);
523
524u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel)
525{
526 return mgr_desc[channel].sync_lost_irq;
527}
528EXPORT_SYMBOL(dispc_mgr_get_sync_lost_irq);
545 529
546u32 dispc_wb_get_framedone_irq(void) 530u32 dispc_wb_get_framedone_irq(void)
547{ 531{
@@ -552,28 +536,18 @@ bool dispc_mgr_go_busy(enum omap_channel channel)
552{ 536{
553 return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1; 537 return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
554} 538}
539EXPORT_SYMBOL(dispc_mgr_go_busy);
555 540
556void dispc_mgr_go(enum omap_channel channel) 541void dispc_mgr_go(enum omap_channel channel)
557{ 542{
558 bool enable_bit, go_bit; 543 WARN_ON(dispc_mgr_is_enabled(channel) == false);
559 544 WARN_ON(dispc_mgr_go_busy(channel));
560 /* if the channel is not enabled, we don't need GO */
561 enable_bit = mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE) == 1;
562
563 if (!enable_bit)
564 return;
565
566 go_bit = mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
567
568 if (go_bit) {
569 DSSERR("GO bit not down for channel %d\n", channel);
570 return;
571 }
572 545
573 DSSDBG("GO %s\n", mgr_desc[channel].name); 546 DSSDBG("GO %s\n", mgr_desc[channel].name);
574 547
575 mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1); 548 mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1);
576} 549}
550EXPORT_SYMBOL(dispc_mgr_go);
577 551
578bool dispc_wb_go_busy(void) 552bool dispc_wb_go_busy(void)
579{ 553{
@@ -977,6 +951,7 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
977 } 951 }
978 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); 952 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
979} 953}
954EXPORT_SYMBOL(dispc_ovl_set_channel_out);
980 955
981static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane) 956static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
982{ 957{
@@ -1042,7 +1017,7 @@ static void dispc_configure_burst_sizes(void)
1042 const int burst_size = BURST_SIZE_X8; 1017 const int burst_size = BURST_SIZE_X8;
1043 1018
1044 /* Configure burst size always to maximum size */ 1019 /* Configure burst size always to maximum size */
1045 for (i = 0; i < omap_dss_get_num_overlays(); ++i) 1020 for (i = 0; i < dss_feat_get_num_ovls(); ++i)
1046 dispc_ovl_set_burst_size(i, burst_size); 1021 dispc_ovl_set_burst_size(i, burst_size);
1047} 1022}
1048 1023
@@ -1076,7 +1051,7 @@ static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
1076} 1051}
1077 1052
1078static void dispc_mgr_set_cpr_coef(enum omap_channel channel, 1053static void dispc_mgr_set_cpr_coef(enum omap_channel channel,
1079 struct omap_dss_cpr_coefs *coefs) 1054 const struct omap_dss_cpr_coefs *coefs)
1080{ 1055{
1081 u32 coef_r, coef_g, coef_b; 1056 u32 coef_r, coef_g, coef_b;
1082 1057
@@ -1124,7 +1099,9 @@ static void dispc_mgr_set_size(enum omap_channel channel, u16 width,
1124{ 1099{
1125 u32 val; 1100 u32 val;
1126 1101
1127 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 1102 val = FLD_VAL(height - 1, dispc.feat->mgr_height_start, 16) |
1103 FLD_VAL(width - 1, dispc.feat->mgr_width_start, 0);
1104
1128 dispc_write_reg(DISPC_SIZE_MGR(channel), val); 1105 dispc_write_reg(DISPC_SIZE_MGR(channel), val);
1129} 1106}
1130 1107
@@ -1246,7 +1223,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
1246 1223
1247 if (use_fifomerge) { 1224 if (use_fifomerge) {
1248 total_fifo_size = 0; 1225 total_fifo_size = 0;
1249 for (i = 0; i < omap_dss_get_num_overlays(); ++i) 1226 for (i = 0; i < dss_feat_get_num_ovls(); ++i)
1250 total_fifo_size += dispc_ovl_get_fifo_size(i); 1227 total_fifo_size += dispc_ovl_get_fifo_size(i);
1251 } else { 1228 } else {
1252 total_fifo_size = ovl_fifo_size; 1229 total_fifo_size = ovl_fifo_size;
@@ -1991,16 +1968,14 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
1991 * This function is used to avoid synclosts in OMAP3, because of some 1968 * This function is used to avoid synclosts in OMAP3, because of some
1992 * undocumented horizontal position and timing related limitations. 1969 * undocumented horizontal position and timing related limitations.
1993 */ 1970 */
1994static int check_horiz_timing_omap3(enum omap_plane plane, 1971static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk,
1995 const struct omap_video_timings *t, u16 pos_x, 1972 const struct omap_video_timings *t, u16 pos_x,
1996 u16 width, u16 height, u16 out_width, u16 out_height) 1973 u16 width, u16 height, u16 out_width, u16 out_height)
1997{ 1974{
1998 int DS = DIV_ROUND_UP(height, out_height); 1975 const int ds = DIV_ROUND_UP(height, out_height);
1999 unsigned long nonactive; 1976 unsigned long nonactive;
2000 static const u8 limits[3] = { 8, 10, 20 }; 1977 static const u8 limits[3] = { 8, 10, 20 };
2001 u64 val, blank; 1978 u64 val, blank;
2002 unsigned long pclk = dispc_plane_pclk_rate(plane);
2003 unsigned long lclk = dispc_plane_lclk_rate(plane);
2004 int i; 1979 int i;
2005 1980
2006 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width; 1981 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
@@ -2022,8 +1997,8 @@ static int check_horiz_timing_omap3(enum omap_plane plane,
2022 */ 1997 */
2023 val = div_u64((u64)(nonactive - pos_x) * lclk, pclk); 1998 val = div_u64((u64)(nonactive - pos_x) * lclk, pclk);
2024 DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n", 1999 DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n",
2025 val, max(0, DS - 2) * width); 2000 val, max(0, ds - 2) * width);
2026 if (val < max(0, DS - 2) * width) 2001 if (val < max(0, ds - 2) * width)
2027 return -EINVAL; 2002 return -EINVAL;
2028 2003
2029 /* 2004 /*
@@ -2033,21 +2008,20 @@ static int check_horiz_timing_omap3(enum omap_plane plane,
2033 */ 2008 */
2034 val = div_u64((u64)nonactive * lclk, pclk); 2009 val = div_u64((u64)nonactive * lclk, pclk);
2035 DSSDBG("nonactive * pcd = %llu, max(0, DS - 1) * width = %d\n", 2010 DSSDBG("nonactive * pcd = %llu, max(0, DS - 1) * width = %d\n",
2036 val, max(0, DS - 1) * width); 2011 val, max(0, ds - 1) * width);
2037 if (val < max(0, DS - 1) * width) 2012 if (val < max(0, ds - 1) * width)
2038 return -EINVAL; 2013 return -EINVAL;
2039 2014
2040 return 0; 2015 return 0;
2041} 2016}
2042 2017
2043static unsigned long calc_core_clk_five_taps(enum omap_plane plane, 2018static unsigned long calc_core_clk_five_taps(unsigned long pclk,
2044 const struct omap_video_timings *mgr_timings, u16 width, 2019 const struct omap_video_timings *mgr_timings, u16 width,
2045 u16 height, u16 out_width, u16 out_height, 2020 u16 height, u16 out_width, u16 out_height,
2046 enum omap_color_mode color_mode) 2021 enum omap_color_mode color_mode)
2047{ 2022{
2048 u32 core_clk = 0; 2023 u32 core_clk = 0;
2049 u64 tmp; 2024 u64 tmp;
2050 unsigned long pclk = dispc_plane_pclk_rate(plane);
2051 2025
2052 if (height <= out_height && width <= out_width) 2026 if (height <= out_height && width <= out_width)
2053 return (unsigned long) pclk; 2027 return (unsigned long) pclk;
@@ -2081,22 +2055,19 @@ static unsigned long calc_core_clk_five_taps(enum omap_plane plane,
2081 return core_clk; 2055 return core_clk;
2082} 2056}
2083 2057
2084static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width, 2058static unsigned long calc_core_clk_24xx(unsigned long pclk, u16 width,
2085 u16 height, u16 out_width, u16 out_height, bool mem_to_mem) 2059 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
2086{ 2060{
2087 unsigned long pclk = dispc_plane_pclk_rate(plane);
2088
2089 if (height > out_height && width > out_width) 2061 if (height > out_height && width > out_width)
2090 return pclk * 4; 2062 return pclk * 4;
2091 else 2063 else
2092 return pclk * 2; 2064 return pclk * 2;
2093} 2065}
2094 2066
2095static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width, 2067static unsigned long calc_core_clk_34xx(unsigned long pclk, u16 width,
2096 u16 height, u16 out_width, u16 out_height, bool mem_to_mem) 2068 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
2097{ 2069{
2098 unsigned int hf, vf; 2070 unsigned int hf, vf;
2099 unsigned long pclk = dispc_plane_pclk_rate(plane);
2100 2071
2101 /* 2072 /*
2102 * FIXME how to determine the 'A' factor 2073 * FIXME how to determine the 'A' factor
@@ -2119,11 +2090,9 @@ static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width,
2119 return pclk * vf * hf; 2090 return pclk * vf * hf;
2120} 2091}
2121 2092
2122static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width, 2093static unsigned long calc_core_clk_44xx(unsigned long pclk, u16 width,
2123 u16 height, u16 out_width, u16 out_height, bool mem_to_mem) 2094 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
2124{ 2095{
2125 unsigned long pclk;
2126
2127 /* 2096 /*
2128 * If the overlay/writeback is in mem to mem mode, there are no 2097 * If the overlay/writeback is in mem to mem mode, there are no
2129 * downscaling limitations with respect to pixel clock, return 1 as 2098 * downscaling limitations with respect to pixel clock, return 1 as
@@ -2133,15 +2102,13 @@ static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width,
2133 if (mem_to_mem) 2102 if (mem_to_mem)
2134 return 1; 2103 return 1;
2135 2104
2136 pclk = dispc_plane_pclk_rate(plane);
2137
2138 if (width > out_width) 2105 if (width > out_width)
2139 return DIV_ROUND_UP(pclk, out_width) * width; 2106 return DIV_ROUND_UP(pclk, out_width) * width;
2140 else 2107 else
2141 return pclk; 2108 return pclk;
2142} 2109}
2143 2110
2144static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane, 2111static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk,
2145 const struct omap_video_timings *mgr_timings, 2112 const struct omap_video_timings *mgr_timings,
2146 u16 width, u16 height, u16 out_width, u16 out_height, 2113 u16 width, u16 height, u16 out_width, u16 out_height,
2147 enum omap_color_mode color_mode, bool *five_taps, 2114 enum omap_color_mode color_mode, bool *five_taps,
@@ -2159,7 +2126,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
2159 do { 2126 do {
2160 in_height = DIV_ROUND_UP(height, *decim_y); 2127 in_height = DIV_ROUND_UP(height, *decim_y);
2161 in_width = DIV_ROUND_UP(width, *decim_x); 2128 in_width = DIV_ROUND_UP(width, *decim_x);
2162 *core_clk = dispc.feat->calc_core_clk(plane, in_width, 2129 *core_clk = dispc.feat->calc_core_clk(pclk, in_width,
2163 in_height, out_width, out_height, mem_to_mem); 2130 in_height, out_width, out_height, mem_to_mem);
2164 error = (in_width > maxsinglelinewidth || !*core_clk || 2131 error = (in_width > maxsinglelinewidth || !*core_clk ||
2165 *core_clk > dispc_core_clk_rate()); 2132 *core_clk > dispc_core_clk_rate());
@@ -2182,7 +2149,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
2182 return 0; 2149 return 0;
2183} 2150}
2184 2151
2185static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane, 2152static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk,
2186 const struct omap_video_timings *mgr_timings, 2153 const struct omap_video_timings *mgr_timings,
2187 u16 width, u16 height, u16 out_width, u16 out_height, 2154 u16 width, u16 height, u16 out_width, u16 out_height,
2188 enum omap_color_mode color_mode, bool *five_taps, 2155 enum omap_color_mode color_mode, bool *five_taps,
@@ -2198,10 +2165,10 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
2198 do { 2165 do {
2199 in_height = DIV_ROUND_UP(height, *decim_y); 2166 in_height = DIV_ROUND_UP(height, *decim_y);
2200 in_width = DIV_ROUND_UP(width, *decim_x); 2167 in_width = DIV_ROUND_UP(width, *decim_x);
2201 *core_clk = calc_core_clk_five_taps(plane, mgr_timings, 2168 *core_clk = calc_core_clk_five_taps(pclk, mgr_timings,
2202 in_width, in_height, out_width, out_height, color_mode); 2169 in_width, in_height, out_width, out_height, color_mode);
2203 2170
2204 error = check_horiz_timing_omap3(plane, mgr_timings, 2171 error = check_horiz_timing_omap3(pclk, lclk, mgr_timings,
2205 pos_x, in_width, in_height, out_width, 2172 pos_x, in_width, in_height, out_width,
2206 out_height); 2173 out_height);
2207 2174
@@ -2210,7 +2177,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
2210 in_height < out_height * 2) 2177 in_height < out_height * 2)
2211 *five_taps = false; 2178 *five_taps = false;
2212 if (!*five_taps) 2179 if (!*five_taps)
2213 *core_clk = dispc.feat->calc_core_clk(plane, in_width, 2180 *core_clk = dispc.feat->calc_core_clk(pclk, in_width,
2214 in_height, out_width, out_height, 2181 in_height, out_width, out_height,
2215 mem_to_mem); 2182 mem_to_mem);
2216 2183
@@ -2229,8 +2196,8 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
2229 } 2196 }
2230 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); 2197 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2231 2198
2232 if (check_horiz_timing_omap3(plane, mgr_timings, pos_x, width, height, 2199 if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, width,
2233 out_width, out_height)){ 2200 height, out_width, out_height)){
2234 DSSERR("horizontal timing too tight\n"); 2201 DSSERR("horizontal timing too tight\n");
2235 return -EINVAL; 2202 return -EINVAL;
2236 } 2203 }
@@ -2248,7 +2215,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
2248 return 0; 2215 return 0;
2249} 2216}
2250 2217
2251static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane, 2218static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk,
2252 const struct omap_video_timings *mgr_timings, 2219 const struct omap_video_timings *mgr_timings,
2253 u16 width, u16 height, u16 out_width, u16 out_height, 2220 u16 width, u16 height, u16 out_width, u16 out_height,
2254 enum omap_color_mode color_mode, bool *five_taps, 2221 enum omap_color_mode color_mode, bool *five_taps,
@@ -2260,14 +2227,14 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
2260 u16 in_height = DIV_ROUND_UP(height, *decim_y); 2227 u16 in_height = DIV_ROUND_UP(height, *decim_y);
2261 const int maxsinglelinewidth = 2228 const int maxsinglelinewidth =
2262 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); 2229 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2263 unsigned long pclk = dispc_plane_pclk_rate(plane);
2264 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); 2230 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
2265 2231
2266 if (mem_to_mem) 2232 if (mem_to_mem) {
2267 in_width_max = DIV_ROUND_UP(out_width, maxdownscale); 2233 in_width_max = out_width * maxdownscale;
2268 else 2234 } else {
2269 in_width_max = dispc_core_clk_rate() / 2235 in_width_max = dispc_core_clk_rate() /
2270 DIV_ROUND_UP(pclk, out_width); 2236 DIV_ROUND_UP(pclk, out_width);
2237 }
2271 2238
2272 *decim_x = DIV_ROUND_UP(width, in_width_max); 2239 *decim_x = DIV_ROUND_UP(width, in_width_max);
2273 2240
@@ -2285,12 +2252,12 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
2285 return -EINVAL; 2252 return -EINVAL;
2286 } 2253 }
2287 2254
2288 *core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height, 2255 *core_clk = dispc.feat->calc_core_clk(pclk, in_width, in_height,
2289 out_width, out_height, mem_to_mem); 2256 out_width, out_height, mem_to_mem);
2290 return 0; 2257 return 0;
2291} 2258}
2292 2259
2293static int dispc_ovl_calc_scaling(enum omap_plane plane, 2260static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
2294 enum omap_overlay_caps caps, 2261 enum omap_overlay_caps caps,
2295 const struct omap_video_timings *mgr_timings, 2262 const struct omap_video_timings *mgr_timings,
2296 u16 width, u16 height, u16 out_width, u16 out_height, 2263 u16 width, u16 height, u16 out_width, u16 out_height,
@@ -2309,9 +2276,14 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
2309 if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0) 2276 if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
2310 return -EINVAL; 2277 return -EINVAL;
2311 2278
2312 *x_predecim = max_decim_limit; 2279 if (mem_to_mem) {
2313 *y_predecim = (rotation_type == OMAP_DSS_ROT_TILER && 2280 *x_predecim = *y_predecim = 1;
2314 dss_has_feature(FEAT_BURST_2D)) ? 2 : max_decim_limit; 2281 } else {
2282 *x_predecim = max_decim_limit;
2283 *y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
2284 dss_has_feature(FEAT_BURST_2D)) ?
2285 2 : max_decim_limit;
2286 }
2315 2287
2316 if (color_mode == OMAP_DSS_COLOR_CLUT1 || 2288 if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
2317 color_mode == OMAP_DSS_COLOR_CLUT2 || 2289 color_mode == OMAP_DSS_COLOR_CLUT2 ||
@@ -2332,7 +2304,7 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
2332 if (decim_y > *y_predecim || out_height > height * 8) 2304 if (decim_y > *y_predecim || out_height > height * 8)
2333 return -EINVAL; 2305 return -EINVAL;
2334 2306
2335 ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height, 2307 ret = dispc.feat->calc_scaling(pclk, lclk, mgr_timings, width, height,
2336 out_width, out_height, color_mode, five_taps, 2308 out_width, out_height, color_mode, five_taps,
2337 x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk, 2309 x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
2338 mem_to_mem); 2310 mem_to_mem);
@@ -2355,6 +2327,47 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
2355 return 0; 2327 return 0;
2356} 2328}
2357 2329
2330int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel,
2331 const struct omap_overlay_info *oi,
2332 const struct omap_video_timings *timings,
2333 int *x_predecim, int *y_predecim)
2334{
2335 enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
2336 bool five_taps = true;
2337 bool fieldmode = 0;
2338 u16 in_height = oi->height;
2339 u16 in_width = oi->width;
2340 bool ilace = timings->interlace;
2341 u16 out_width, out_height;
2342 int pos_x = oi->pos_x;
2343 unsigned long pclk = dispc_mgr_pclk_rate(channel);
2344 unsigned long lclk = dispc_mgr_lclk_rate(channel);
2345
2346 out_width = oi->out_width == 0 ? oi->width : oi->out_width;
2347 out_height = oi->out_height == 0 ? oi->height : oi->out_height;
2348
2349 if (ilace && oi->height == out_height)
2350 fieldmode = 1;
2351
2352 if (ilace) {
2353 if (fieldmode)
2354 in_height /= 2;
2355 out_height /= 2;
2356
2357 DSSDBG("adjusting for ilace: height %d, out_height %d\n",
2358 in_height, out_height);
2359 }
2360
2361 if (!dss_feat_color_mode_supported(plane, oi->color_mode))
2362 return -EINVAL;
2363
2364 return dispc_ovl_calc_scaling(pclk, lclk, caps, timings, in_width,
2365 in_height, out_width, out_height, oi->color_mode,
2366 &five_taps, x_predecim, y_predecim, pos_x,
2367 oi->rotation_type, false);
2368}
2369EXPORT_SYMBOL(dispc_ovl_check);
2370
2358static int dispc_ovl_setup_common(enum omap_plane plane, 2371static int dispc_ovl_setup_common(enum omap_plane plane,
2359 enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr, 2372 enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
2360 u16 screen_width, int pos_x, int pos_y, u16 width, u16 height, 2373 u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
@@ -2370,12 +2383,14 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
2370 unsigned offset0, offset1; 2383 unsigned offset0, offset1;
2371 s32 row_inc; 2384 s32 row_inc;
2372 s32 pix_inc; 2385 s32 pix_inc;
2373 u16 frame_height = height; 2386 u16 frame_width, frame_height;
2374 unsigned int field_offset = 0; 2387 unsigned int field_offset = 0;
2375 u16 in_height = height; 2388 u16 in_height = height;
2376 u16 in_width = width; 2389 u16 in_width = width;
2377 int x_predecim = 1, y_predecim = 1; 2390 int x_predecim = 1, y_predecim = 1;
2378 bool ilace = mgr_timings->interlace; 2391 bool ilace = mgr_timings->interlace;
2392 unsigned long pclk = dispc_plane_pclk_rate(plane);
2393 unsigned long lclk = dispc_plane_lclk_rate(plane);
2379 2394
2380 if (paddr == 0) 2395 if (paddr == 0)
2381 return -EINVAL; 2396 return -EINVAL;
@@ -2400,7 +2415,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
2400 if (!dss_feat_color_mode_supported(plane, color_mode)) 2415 if (!dss_feat_color_mode_supported(plane, color_mode))
2401 return -EINVAL; 2416 return -EINVAL;
2402 2417
2403 r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width, 2418 r = dispc_ovl_calc_scaling(pclk, lclk, caps, mgr_timings, in_width,
2404 in_height, out_width, out_height, color_mode, 2419 in_height, out_width, out_height, color_mode,
2405 &five_taps, &x_predecim, &y_predecim, pos_x, 2420 &five_taps, &x_predecim, &y_predecim, pos_x,
2406 rotation_type, mem_to_mem); 2421 rotation_type, mem_to_mem);
@@ -2438,20 +2453,28 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
2438 row_inc = 0; 2453 row_inc = 0;
2439 pix_inc = 0; 2454 pix_inc = 0;
2440 2455
2456 if (plane == OMAP_DSS_WB) {
2457 frame_width = out_width;
2458 frame_height = out_height;
2459 } else {
2460 frame_width = in_width;
2461 frame_height = height;
2462 }
2463
2441 if (rotation_type == OMAP_DSS_ROT_TILER) 2464 if (rotation_type == OMAP_DSS_ROT_TILER)
2442 calc_tiler_rotation_offset(screen_width, in_width, 2465 calc_tiler_rotation_offset(screen_width, frame_width,
2443 color_mode, fieldmode, field_offset, 2466 color_mode, fieldmode, field_offset,
2444 &offset0, &offset1, &row_inc, &pix_inc, 2467 &offset0, &offset1, &row_inc, &pix_inc,
2445 x_predecim, y_predecim); 2468 x_predecim, y_predecim);
2446 else if (rotation_type == OMAP_DSS_ROT_DMA) 2469 else if (rotation_type == OMAP_DSS_ROT_DMA)
2447 calc_dma_rotation_offset(rotation, mirror, 2470 calc_dma_rotation_offset(rotation, mirror, screen_width,
2448 screen_width, in_width, frame_height, 2471 frame_width, frame_height,
2449 color_mode, fieldmode, field_offset, 2472 color_mode, fieldmode, field_offset,
2450 &offset0, &offset1, &row_inc, &pix_inc, 2473 &offset0, &offset1, &row_inc, &pix_inc,
2451 x_predecim, y_predecim); 2474 x_predecim, y_predecim);
2452 else 2475 else
2453 calc_vrfb_rotation_offset(rotation, mirror, 2476 calc_vrfb_rotation_offset(rotation, mirror,
2454 screen_width, in_width, frame_height, 2477 screen_width, frame_width, frame_height,
2455 color_mode, fieldmode, field_offset, 2478 color_mode, fieldmode, field_offset,
2456 &offset0, &offset1, &row_inc, &pix_inc, 2479 &offset0, &offset1, &row_inc, &pix_inc,
2457 x_predecim, y_predecim); 2480 x_predecim, y_predecim);
@@ -2505,7 +2528,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
2505 bool mem_to_mem) 2528 bool mem_to_mem)
2506{ 2529{
2507 int r; 2530 int r;
2508 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 2531 enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
2509 enum omap_channel channel; 2532 enum omap_channel channel;
2510 2533
2511 channel = dispc_ovl_get_channel_out(plane); 2534 channel = dispc_ovl_get_channel_out(plane);
@@ -2516,7 +2539,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
2516 oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height, 2539 oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
2517 oi->color_mode, oi->rotation, oi->mirror, channel, replication); 2540 oi->color_mode, oi->rotation, oi->mirror, channel, replication);
2518 2541
2519 r = dispc_ovl_setup_common(plane, ovl->caps, oi->paddr, oi->p_uv_addr, 2542 r = dispc_ovl_setup_common(plane, caps, oi->paddr, oi->p_uv_addr,
2520 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height, 2543 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
2521 oi->out_width, oi->out_height, oi->color_mode, oi->rotation, 2544 oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
2522 oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha, 2545 oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
@@ -2524,6 +2547,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
2524 2547
2525 return r; 2548 return r;
2526} 2549}
2550EXPORT_SYMBOL(dispc_ovl_setup);
2527 2551
2528int dispc_wb_setup(const struct omap_dss_writeback_info *wi, 2552int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
2529 bool mem_to_mem, const struct omap_video_timings *mgr_timings) 2553 bool mem_to_mem, const struct omap_video_timings *mgr_timings)
@@ -2584,192 +2608,39 @@ int dispc_ovl_enable(enum omap_plane plane, bool enable)
2584 2608
2585 return 0; 2609 return 0;
2586} 2610}
2611EXPORT_SYMBOL(dispc_ovl_enable);
2587 2612
2588static void dispc_disable_isr(void *data, u32 mask) 2613bool dispc_ovl_enabled(enum omap_plane plane)
2589{ 2614{
2590 struct completion *compl = data; 2615 return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
2591 complete(compl);
2592} 2616}
2617EXPORT_SYMBOL(dispc_ovl_enabled);
2593 2618
2594static void _enable_lcd_out(enum omap_channel channel, bool enable) 2619void dispc_mgr_enable(enum omap_channel channel, bool enable)
2595{ 2620{
2596 mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable); 2621 mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable);
2597 /* flush posted write */ 2622 /* flush posted write */
2598 mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); 2623 mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
2599} 2624}
2600 2625EXPORT_SYMBOL(dispc_mgr_enable);
2601static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
2602{
2603 struct completion frame_done_completion;
2604 bool is_on;
2605 int r;
2606 u32 irq;
2607
2608 /* When we disable LCD output, we need to wait until frame is done.
2609 * Otherwise the DSS is still working, and turning off the clocks
2610 * prevents DSS from going to OFF mode */
2611 is_on = mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
2612
2613 irq = mgr_desc[channel].framedone_irq;
2614
2615 if (!enable && is_on) {
2616 init_completion(&frame_done_completion);
2617
2618 r = omap_dispc_register_isr(dispc_disable_isr,
2619 &frame_done_completion, irq);
2620
2621 if (r)
2622 DSSERR("failed to register FRAMEDONE isr\n");
2623 }
2624
2625 _enable_lcd_out(channel, enable);
2626
2627 if (!enable && is_on) {
2628 if (!wait_for_completion_timeout(&frame_done_completion,
2629 msecs_to_jiffies(100)))
2630 DSSERR("timeout waiting for FRAME DONE\n");
2631
2632 r = omap_dispc_unregister_isr(dispc_disable_isr,
2633 &frame_done_completion, irq);
2634
2635 if (r)
2636 DSSERR("failed to unregister FRAMEDONE isr\n");
2637 }
2638}
2639
2640static void _enable_digit_out(bool enable)
2641{
2642 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
2643 /* flush posted write */
2644 dispc_read_reg(DISPC_CONTROL);
2645}
2646
2647static void dispc_mgr_enable_digit_out(bool enable)
2648{
2649 struct completion frame_done_completion;
2650 enum dss_hdmi_venc_clk_source_select src;
2651 int r, i;
2652 u32 irq_mask;
2653 int num_irqs;
2654
2655 if (REG_GET(DISPC_CONTROL, 1, 1) == enable)
2656 return;
2657
2658 src = dss_get_hdmi_venc_clk_source();
2659
2660 if (enable) {
2661 unsigned long flags;
2662 /* When we enable digit output, we'll get an extra digit
2663 * sync lost interrupt, that we need to ignore */
2664 spin_lock_irqsave(&dispc.irq_lock, flags);
2665 dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
2666 _omap_dispc_set_irqs();
2667 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2668 }
2669
2670 /* When we disable digit output, we need to wait until fields are done.
2671 * Otherwise the DSS is still working, and turning off the clocks
2672 * prevents DSS from going to OFF mode. And when enabling, we need to
2673 * wait for the extra sync losts */
2674 init_completion(&frame_done_completion);
2675
2676 if (src == DSS_HDMI_M_PCLK && enable == false) {
2677 irq_mask = DISPC_IRQ_FRAMEDONETV;
2678 num_irqs = 1;
2679 } else {
2680 irq_mask = DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD;
2681 /* XXX I understand from TRM that we should only wait for the
2682 * current field to complete. But it seems we have to wait for
2683 * both fields */
2684 num_irqs = 2;
2685 }
2686
2687 r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
2688 irq_mask);
2689 if (r)
2690 DSSERR("failed to register %x isr\n", irq_mask);
2691
2692 _enable_digit_out(enable);
2693
2694 for (i = 0; i < num_irqs; ++i) {
2695 if (!wait_for_completion_timeout(&frame_done_completion,
2696 msecs_to_jiffies(100)))
2697 DSSERR("timeout waiting for digit out to %s\n",
2698 enable ? "start" : "stop");
2699 }
2700
2701 r = omap_dispc_unregister_isr(dispc_disable_isr, &frame_done_completion,
2702 irq_mask);
2703 if (r)
2704 DSSERR("failed to unregister %x isr\n", irq_mask);
2705
2706 if (enable) {
2707 unsigned long flags;
2708 spin_lock_irqsave(&dispc.irq_lock, flags);
2709 dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST_DIGIT;
2710 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
2711 _omap_dispc_set_irqs();
2712 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2713 }
2714}
2715 2626
2716bool dispc_mgr_is_enabled(enum omap_channel channel) 2627bool dispc_mgr_is_enabled(enum omap_channel channel)
2717{ 2628{
2718 return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); 2629 return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
2719} 2630}
2720 2631EXPORT_SYMBOL(dispc_mgr_is_enabled);
2721void dispc_mgr_enable(enum omap_channel channel, bool enable)
2722{
2723 if (dss_mgr_is_lcd(channel))
2724 dispc_mgr_enable_lcd_out(channel, enable);
2725 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
2726 dispc_mgr_enable_digit_out(enable);
2727 else
2728 BUG();
2729}
2730 2632
2731void dispc_wb_enable(bool enable) 2633void dispc_wb_enable(bool enable)
2732{ 2634{
2733 enum omap_plane plane = OMAP_DSS_WB; 2635 dispc_ovl_enable(OMAP_DSS_WB, enable);
2734 struct completion frame_done_completion;
2735 bool is_on;
2736 int r;
2737 u32 irq;
2738
2739 is_on = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
2740 irq = DISPC_IRQ_FRAMEDONEWB;
2741
2742 if (!enable && is_on) {
2743 init_completion(&frame_done_completion);
2744
2745 r = omap_dispc_register_isr(dispc_disable_isr,
2746 &frame_done_completion, irq);
2747 if (r)
2748 DSSERR("failed to register FRAMEDONEWB isr\n");
2749 }
2750
2751 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
2752
2753 if (!enable && is_on) {
2754 if (!wait_for_completion_timeout(&frame_done_completion,
2755 msecs_to_jiffies(100)))
2756 DSSERR("timeout waiting for FRAMEDONEWB\n");
2757
2758 r = omap_dispc_unregister_isr(dispc_disable_isr,
2759 &frame_done_completion, irq);
2760 if (r)
2761 DSSERR("failed to unregister FRAMEDONEWB isr\n");
2762 }
2763} 2636}
2764 2637
2765bool dispc_wb_is_enabled(void) 2638bool dispc_wb_is_enabled(void)
2766{ 2639{
2767 enum omap_plane plane = OMAP_DSS_WB; 2640 return dispc_ovl_enabled(OMAP_DSS_WB);
2768
2769 return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
2770} 2641}
2771 2642
2772void dispc_lcd_enable_signal_polarity(bool act_high) 2643static void dispc_lcd_enable_signal_polarity(bool act_high)
2773{ 2644{
2774 if (!dss_has_feature(FEAT_LCDENABLEPOL)) 2645 if (!dss_has_feature(FEAT_LCDENABLEPOL))
2775 return; 2646 return;
@@ -2793,13 +2664,13 @@ void dispc_pck_free_enable(bool enable)
2793 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); 2664 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
2794} 2665}
2795 2666
2796void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable) 2667static void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
2797{ 2668{
2798 mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable); 2669 mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable);
2799} 2670}
2800 2671
2801 2672
2802void dispc_mgr_set_lcd_type_tft(enum omap_channel channel) 2673static void dispc_mgr_set_lcd_type_tft(enum omap_channel channel)
2803{ 2674{
2804 mgr_fld_write(channel, DISPC_MGR_FLD_STNTFT, 1); 2675 mgr_fld_write(channel, DISPC_MGR_FLD_STNTFT, 1);
2805} 2676}
@@ -2842,7 +2713,7 @@ static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch,
2842} 2713}
2843 2714
2844void dispc_mgr_setup(enum omap_channel channel, 2715void dispc_mgr_setup(enum omap_channel channel,
2845 struct omap_overlay_manager_info *info) 2716 const struct omap_overlay_manager_info *info)
2846{ 2717{
2847 dispc_mgr_set_default_color(channel, info->default_color); 2718 dispc_mgr_set_default_color(channel, info->default_color);
2848 dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key); 2719 dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key);
@@ -2854,8 +2725,9 @@ void dispc_mgr_setup(enum omap_channel channel,
2854 dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs); 2725 dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs);
2855 } 2726 }
2856} 2727}
2728EXPORT_SYMBOL(dispc_mgr_setup);
2857 2729
2858void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines) 2730static void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
2859{ 2731{
2860 int code; 2732 int code;
2861 2733
@@ -2880,7 +2752,7 @@ void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
2880 mgr_fld_write(channel, DISPC_MGR_FLD_TFTDATALINES, code); 2752 mgr_fld_write(channel, DISPC_MGR_FLD_TFTDATALINES, code);
2881} 2753}
2882 2754
2883void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode) 2755static void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
2884{ 2756{
2885 u32 l; 2757 u32 l;
2886 int gpout0, gpout1; 2758 int gpout0, gpout1;
@@ -2909,15 +2781,33 @@ void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
2909 dispc_write_reg(DISPC_CONTROL, l); 2781 dispc_write_reg(DISPC_CONTROL, l);
2910} 2782}
2911 2783
2912void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable) 2784static void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
2913{ 2785{
2914 mgr_fld_write(channel, DISPC_MGR_FLD_STALLMODE, enable); 2786 mgr_fld_write(channel, DISPC_MGR_FLD_STALLMODE, enable);
2915} 2787}
2916 2788
2789void dispc_mgr_set_lcd_config(enum omap_channel channel,
2790 const struct dss_lcd_mgr_config *config)
2791{
2792 dispc_mgr_set_io_pad_mode(config->io_pad_mode);
2793
2794 dispc_mgr_enable_stallmode(channel, config->stallmode);
2795 dispc_mgr_enable_fifohandcheck(channel, config->fifohandcheck);
2796
2797 dispc_mgr_set_clock_div(channel, &config->clock_info);
2798
2799 dispc_mgr_set_tft_data_lines(channel, config->video_port_width);
2800
2801 dispc_lcd_enable_signal_polarity(config->lcden_sig_polarity);
2802
2803 dispc_mgr_set_lcd_type_tft(channel);
2804}
2805EXPORT_SYMBOL(dispc_mgr_set_lcd_config);
2806
2917static bool _dispc_mgr_size_ok(u16 width, u16 height) 2807static bool _dispc_mgr_size_ok(u16 width, u16 height)
2918{ 2808{
2919 return width <= dss_feat_get_param_max(FEAT_PARAM_MGR_WIDTH) && 2809 return width <= dispc.feat->mgr_width_max &&
2920 height <= dss_feat_get_param_max(FEAT_PARAM_MGR_HEIGHT); 2810 height <= dispc.feat->mgr_height_max;
2921} 2811}
2922 2812
2923static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, 2813static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
@@ -3012,7 +2902,7 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
3012 2902
3013/* change name to mode? */ 2903/* change name to mode? */
3014void dispc_mgr_set_timings(enum omap_channel channel, 2904void dispc_mgr_set_timings(enum omap_channel channel,
3015 struct omap_video_timings *timings) 2905 const struct omap_video_timings *timings)
3016{ 2906{
3017 unsigned xtot, ytot; 2907 unsigned xtot, ytot;
3018 unsigned long ht, vt; 2908 unsigned long ht, vt;
@@ -3051,6 +2941,7 @@ void dispc_mgr_set_timings(enum omap_channel channel,
3051 2941
3052 dispc_mgr_set_size(channel, t.x_res, t.y_res); 2942 dispc_mgr_set_size(channel, t.x_res, t.y_res);
3053} 2943}
2944EXPORT_SYMBOL(dispc_mgr_set_timings);
3054 2945
3055static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, 2946static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
3056 u16 pck_div) 2947 u16 pck_div)
@@ -3078,7 +2969,7 @@ unsigned long dispc_fclk_rate(void)
3078 2969
3079 switch (dss_get_dispc_clk_source()) { 2970 switch (dss_get_dispc_clk_source()) {
3080 case OMAP_DSS_CLK_SRC_FCK: 2971 case OMAP_DSS_CLK_SRC_FCK:
3081 r = clk_get_rate(dispc.dss_clk); 2972 r = dss_get_dispc_clk_rate();
3082 break; 2973 break;
3083 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: 2974 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
3084 dsidev = dsi_get_dsidev_from_id(0); 2975 dsidev = dsi_get_dsidev_from_id(0);
@@ -3103,28 +2994,32 @@ unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
3103 unsigned long r; 2994 unsigned long r;
3104 u32 l; 2995 u32 l;
3105 2996
3106 l = dispc_read_reg(DISPC_DIVISORo(channel)); 2997 if (dss_mgr_is_lcd(channel)) {
2998 l = dispc_read_reg(DISPC_DIVISORo(channel));
3107 2999
3108 lcd = FLD_GET(l, 23, 16); 3000 lcd = FLD_GET(l, 23, 16);
3109 3001
3110 switch (dss_get_lcd_clk_source(channel)) { 3002 switch (dss_get_lcd_clk_source(channel)) {
3111 case OMAP_DSS_CLK_SRC_FCK: 3003 case OMAP_DSS_CLK_SRC_FCK:
3112 r = clk_get_rate(dispc.dss_clk); 3004 r = dss_get_dispc_clk_rate();
3113 break; 3005 break;
3114 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: 3006 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
3115 dsidev = dsi_get_dsidev_from_id(0); 3007 dsidev = dsi_get_dsidev_from_id(0);
3116 r = dsi_get_pll_hsdiv_dispc_rate(dsidev); 3008 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
3117 break; 3009 break;
3118 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: 3010 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
3119 dsidev = dsi_get_dsidev_from_id(1); 3011 dsidev = dsi_get_dsidev_from_id(1);
3120 r = dsi_get_pll_hsdiv_dispc_rate(dsidev); 3012 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
3121 break; 3013 break;
3122 default: 3014 default:
3123 BUG(); 3015 BUG();
3124 return 0; 3016 return 0;
3125 } 3017 }
3126 3018
3127 return r / lcd; 3019 return r / lcd;
3020 } else {
3021 return dispc_fclk_rate();
3022 }
3128} 3023}
3129 3024
3130unsigned long dispc_mgr_pclk_rate(enum omap_channel channel) 3025unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
@@ -3174,21 +3069,28 @@ unsigned long dispc_core_clk_rate(void)
3174 3069
3175static unsigned long dispc_plane_pclk_rate(enum omap_plane plane) 3070static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
3176{ 3071{
3177 enum omap_channel channel = dispc_ovl_get_channel_out(plane); 3072 enum omap_channel channel;
3073
3074 if (plane == OMAP_DSS_WB)
3075 return 0;
3076
3077 channel = dispc_ovl_get_channel_out(plane);
3178 3078
3179 return dispc_mgr_pclk_rate(channel); 3079 return dispc_mgr_pclk_rate(channel);
3180} 3080}
3181 3081
3182static unsigned long dispc_plane_lclk_rate(enum omap_plane plane) 3082static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
3183{ 3083{
3184 enum omap_channel channel = dispc_ovl_get_channel_out(plane); 3084 enum omap_channel channel;
3185 3085
3186 if (dss_mgr_is_lcd(channel)) 3086 if (plane == OMAP_DSS_WB)
3187 return dispc_mgr_lclk_rate(channel); 3087 return 0;
3188 else 3088
3189 return dispc_fclk_rate(); 3089 channel = dispc_ovl_get_channel_out(plane);
3190 3090
3091 return dispc_mgr_lclk_rate(channel);
3191} 3092}
3093
3192static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel) 3094static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
3193{ 3095{
3194 int lcd, pcd; 3096 int lcd, pcd;
@@ -3246,64 +3148,6 @@ void dispc_dump_clocks(struct seq_file *s)
3246 dispc_runtime_put(); 3148 dispc_runtime_put();
3247} 3149}
3248 3150
3249#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3250void dispc_dump_irqs(struct seq_file *s)
3251{
3252 unsigned long flags;
3253 struct dispc_irq_stats stats;
3254
3255 spin_lock_irqsave(&dispc.irq_stats_lock, flags);
3256
3257 stats = dispc.irq_stats;
3258 memset(&dispc.irq_stats, 0, sizeof(dispc.irq_stats));
3259 dispc.irq_stats.last_reset = jiffies;
3260
3261 spin_unlock_irqrestore(&dispc.irq_stats_lock, flags);
3262
3263 seq_printf(s, "period %u ms\n",
3264 jiffies_to_msecs(jiffies - stats.last_reset));
3265
3266 seq_printf(s, "irqs %d\n", stats.irq_count);
3267#define PIS(x) \
3268 seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
3269
3270 PIS(FRAMEDONE);
3271 PIS(VSYNC);
3272 PIS(EVSYNC_EVEN);
3273 PIS(EVSYNC_ODD);
3274 PIS(ACBIAS_COUNT_STAT);
3275 PIS(PROG_LINE_NUM);
3276 PIS(GFX_FIFO_UNDERFLOW);
3277 PIS(GFX_END_WIN);
3278 PIS(PAL_GAMMA_MASK);
3279 PIS(OCP_ERR);
3280 PIS(VID1_FIFO_UNDERFLOW);
3281 PIS(VID1_END_WIN);
3282 PIS(VID2_FIFO_UNDERFLOW);
3283 PIS(VID2_END_WIN);
3284 if (dss_feat_get_num_ovls() > 3) {
3285 PIS(VID3_FIFO_UNDERFLOW);
3286 PIS(VID3_END_WIN);
3287 }
3288 PIS(SYNC_LOST);
3289 PIS(SYNC_LOST_DIGIT);
3290 PIS(WAKEUP);
3291 if (dss_has_feature(FEAT_MGR_LCD2)) {
3292 PIS(FRAMEDONE2);
3293 PIS(VSYNC2);
3294 PIS(ACBIAS_COUNT_STAT2);
3295 PIS(SYNC_LOST2);
3296 }
3297 if (dss_has_feature(FEAT_MGR_LCD3)) {
3298 PIS(FRAMEDONE3);
3299 PIS(VSYNC3);
3300 PIS(ACBIAS_COUNT_STAT3);
3301 PIS(SYNC_LOST3);
3302 }
3303#undef PIS
3304}
3305#endif
3306
3307static void dispc_dump_regs(struct seq_file *s) 3151static void dispc_dump_regs(struct seq_file *s)
3308{ 3152{
3309 int i, j; 3153 int i, j;
@@ -3353,7 +3197,7 @@ static void dispc_dump_regs(struct seq_file *s)
3353 3197
3354#define DISPC_REG(i, name) name(i) 3198#define DISPC_REG(i, name) name(i)
3355#define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \ 3199#define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \
3356 48 - strlen(#r) - strlen(p_names[i]), " ", \ 3200 (int)(48 - strlen(#r) - strlen(p_names[i])), " ", \
3357 dispc_read_reg(DISPC_REG(i, r))) 3201 dispc_read_reg(DISPC_REG(i, r)))
3358 3202
3359 p_names = mgr_names; 3203 p_names = mgr_names;
@@ -3430,7 +3274,7 @@ static void dispc_dump_regs(struct seq_file *s)
3430#define DISPC_REG(plane, name, i) name(plane, i) 3274#define DISPC_REG(plane, name, i) name(plane, i)
3431#define DUMPREG(plane, name, i) \ 3275#define DUMPREG(plane, name, i) \
3432 seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \ 3276 seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \
3433 46 - strlen(#name) - strlen(p_names[plane]), " ", \ 3277 (int)(46 - strlen(#name) - strlen(p_names[plane])), " ", \
3434 dispc_read_reg(DISPC_REG(plane, name, i))) 3278 dispc_read_reg(DISPC_REG(plane, name, i)))
3435 3279
3436 /* Video pipeline coefficient registers */ 3280 /* Video pipeline coefficient registers */
@@ -3533,7 +3377,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
3533} 3377}
3534 3378
3535void dispc_mgr_set_clock_div(enum omap_channel channel, 3379void dispc_mgr_set_clock_div(enum omap_channel channel,
3536 struct dispc_clock_info *cinfo) 3380 const struct dispc_clock_info *cinfo)
3537{ 3381{
3538 DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div); 3382 DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
3539 DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); 3383 DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
@@ -3557,403 +3401,34 @@ int dispc_mgr_get_clock_div(enum omap_channel channel,
3557 return 0; 3401 return 0;
3558} 3402}
3559 3403
3560/* dispc.irq_lock has to be locked by the caller */ 3404u32 dispc_read_irqstatus(void)
3561static void _omap_dispc_set_irqs(void)
3562{ 3405{
3563 u32 mask; 3406 return dispc_read_reg(DISPC_IRQSTATUS);
3564 u32 old_mask;
3565 int i;
3566 struct omap_dispc_isr_data *isr_data;
3567
3568 mask = dispc.irq_error_mask;
3569
3570 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3571 isr_data = &dispc.registered_isr[i];
3572
3573 if (isr_data->isr == NULL)
3574 continue;
3575
3576 mask |= isr_data->mask;
3577 }
3578
3579 old_mask = dispc_read_reg(DISPC_IRQENABLE);
3580 /* clear the irqstatus for newly enabled irqs */
3581 dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
3582
3583 dispc_write_reg(DISPC_IRQENABLE, mask);
3584}
3585
3586int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
3587{
3588 int i;
3589 int ret;
3590 unsigned long flags;
3591 struct omap_dispc_isr_data *isr_data;
3592
3593 if (isr == NULL)
3594 return -EINVAL;
3595
3596 spin_lock_irqsave(&dispc.irq_lock, flags);
3597
3598 /* check for duplicate entry */
3599 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3600 isr_data = &dispc.registered_isr[i];
3601 if (isr_data->isr == isr && isr_data->arg == arg &&
3602 isr_data->mask == mask) {
3603 ret = -EINVAL;
3604 goto err;
3605 }
3606 }
3607
3608 isr_data = NULL;
3609 ret = -EBUSY;
3610
3611 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3612 isr_data = &dispc.registered_isr[i];
3613
3614 if (isr_data->isr != NULL)
3615 continue;
3616
3617 isr_data->isr = isr;
3618 isr_data->arg = arg;
3619 isr_data->mask = mask;
3620 ret = 0;
3621
3622 break;
3623 }
3624
3625 if (ret)
3626 goto err;
3627
3628 _omap_dispc_set_irqs();
3629
3630 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3631
3632 return 0;
3633err:
3634 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3635
3636 return ret;
3637} 3407}
3638EXPORT_SYMBOL(omap_dispc_register_isr); 3408EXPORT_SYMBOL(dispc_read_irqstatus);
3639 3409
3640int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask) 3410void dispc_clear_irqstatus(u32 mask)
3641{ 3411{
3642 int i; 3412 dispc_write_reg(DISPC_IRQSTATUS, mask);
3643 unsigned long flags;
3644 int ret = -EINVAL;
3645 struct omap_dispc_isr_data *isr_data;
3646
3647 spin_lock_irqsave(&dispc.irq_lock, flags);
3648
3649 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3650 isr_data = &dispc.registered_isr[i];
3651 if (isr_data->isr != isr || isr_data->arg != arg ||
3652 isr_data->mask != mask)
3653 continue;
3654
3655 /* found the correct isr */
3656
3657 isr_data->isr = NULL;
3658 isr_data->arg = NULL;
3659 isr_data->mask = 0;
3660
3661 ret = 0;
3662 break;
3663 }
3664
3665 if (ret == 0)
3666 _omap_dispc_set_irqs();
3667
3668 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3669
3670 return ret;
3671} 3413}
3672EXPORT_SYMBOL(omap_dispc_unregister_isr); 3414EXPORT_SYMBOL(dispc_clear_irqstatus);
3673 3415
3674#ifdef DEBUG 3416u32 dispc_read_irqenable(void)
3675static void print_irq_status(u32 status)
3676{ 3417{
3677 if ((status & dispc.irq_error_mask) == 0) 3418 return dispc_read_reg(DISPC_IRQENABLE);
3678 return;
3679
3680 printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status);
3681
3682#define PIS(x) \
3683 if (status & DISPC_IRQ_##x) \
3684 printk(#x " ");
3685 PIS(GFX_FIFO_UNDERFLOW);
3686 PIS(OCP_ERR);
3687 PIS(VID1_FIFO_UNDERFLOW);
3688 PIS(VID2_FIFO_UNDERFLOW);
3689 if (dss_feat_get_num_ovls() > 3)
3690 PIS(VID3_FIFO_UNDERFLOW);
3691 PIS(SYNC_LOST);
3692 PIS(SYNC_LOST_DIGIT);
3693 if (dss_has_feature(FEAT_MGR_LCD2))
3694 PIS(SYNC_LOST2);
3695 if (dss_has_feature(FEAT_MGR_LCD3))
3696 PIS(SYNC_LOST3);
3697#undef PIS
3698
3699 printk("\n");
3700} 3419}
3701#endif 3420EXPORT_SYMBOL(dispc_read_irqenable);
3702 3421
3703/* Called from dss.c. Note that we don't touch clocks here, 3422void dispc_write_irqenable(u32 mask)
3704 * but we presume they are on because we got an IRQ. However,
3705 * an irq handler may turn the clocks off, so we may not have
3706 * clock later in the function. */
3707static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
3708{ 3423{
3709 int i; 3424 u32 old_mask = dispc_read_reg(DISPC_IRQENABLE);
3710 u32 irqstatus, irqenable;
3711 u32 handledirqs = 0;
3712 u32 unhandled_errors;
3713 struct omap_dispc_isr_data *isr_data;
3714 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
3715
3716 spin_lock(&dispc.irq_lock);
3717
3718 irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
3719 irqenable = dispc_read_reg(DISPC_IRQENABLE);
3720
3721 /* IRQ is not for us */
3722 if (!(irqstatus & irqenable)) {
3723 spin_unlock(&dispc.irq_lock);
3724 return IRQ_NONE;
3725 }
3726
3727#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3728 spin_lock(&dispc.irq_stats_lock);
3729 dispc.irq_stats.irq_count++;
3730 dss_collect_irq_stats(irqstatus, dispc.irq_stats.irqs);
3731 spin_unlock(&dispc.irq_stats_lock);
3732#endif
3733
3734#ifdef DEBUG
3735 if (dss_debug)
3736 print_irq_status(irqstatus);
3737#endif
3738 /* Ack the interrupt. Do it here before clocks are possibly turned
3739 * off */
3740 dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
3741 /* flush posted write */
3742 dispc_read_reg(DISPC_IRQSTATUS);
3743
3744 /* make a copy and unlock, so that isrs can unregister
3745 * themselves */
3746 memcpy(registered_isr, dispc.registered_isr,
3747 sizeof(registered_isr));
3748
3749 spin_unlock(&dispc.irq_lock);
3750
3751 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3752 isr_data = &registered_isr[i];
3753
3754 if (!isr_data->isr)
3755 continue;
3756
3757 if (isr_data->mask & irqstatus) {
3758 isr_data->isr(isr_data->arg, irqstatus);
3759 handledirqs |= isr_data->mask;
3760 }
3761 }
3762
3763 spin_lock(&dispc.irq_lock);
3764
3765 unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
3766
3767 if (unhandled_errors) {
3768 dispc.error_irqs |= unhandled_errors;
3769
3770 dispc.irq_error_mask &= ~unhandled_errors;
3771 _omap_dispc_set_irqs();
3772
3773 schedule_work(&dispc.error_work);
3774 }
3775
3776 spin_unlock(&dispc.irq_lock);
3777
3778 return IRQ_HANDLED;
3779}
3780
3781static void dispc_error_worker(struct work_struct *work)
3782{
3783 int i;
3784 u32 errors;
3785 unsigned long flags;
3786 static const unsigned fifo_underflow_bits[] = {
3787 DISPC_IRQ_GFX_FIFO_UNDERFLOW,
3788 DISPC_IRQ_VID1_FIFO_UNDERFLOW,
3789 DISPC_IRQ_VID2_FIFO_UNDERFLOW,
3790 DISPC_IRQ_VID3_FIFO_UNDERFLOW,
3791 };
3792
3793 spin_lock_irqsave(&dispc.irq_lock, flags);
3794 errors = dispc.error_irqs;
3795 dispc.error_irqs = 0;
3796 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3797
3798 dispc_runtime_get();
3799
3800 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3801 struct omap_overlay *ovl;
3802 unsigned bit;
3803
3804 ovl = omap_dss_get_overlay(i);
3805 bit = fifo_underflow_bits[i];
3806
3807 if (bit & errors) {
3808 DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
3809 ovl->name);
3810 dispc_ovl_enable(ovl->id, false);
3811 dispc_mgr_go(ovl->manager->id);
3812 msleep(50);
3813 }
3814 }
3815
3816 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3817 struct omap_overlay_manager *mgr;
3818 unsigned bit;
3819
3820 mgr = omap_dss_get_overlay_manager(i);
3821 bit = mgr_desc[i].sync_lost_irq;
3822
3823 if (bit & errors) {
3824 struct omap_dss_device *dssdev = mgr->get_device(mgr);
3825 bool enable;
3826
3827 DSSERR("SYNC_LOST on channel %s, restarting the output "
3828 "with video overlays disabled\n",
3829 mgr->name);
3830
3831 enable = dssdev->state == OMAP_DSS_DISPLAY_ACTIVE;
3832 dssdev->driver->disable(dssdev);
3833
3834 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3835 struct omap_overlay *ovl;
3836 ovl = omap_dss_get_overlay(i);
3837
3838 if (ovl->id != OMAP_DSS_GFX &&
3839 ovl->manager == mgr)
3840 dispc_ovl_enable(ovl->id, false);
3841 }
3842
3843 dispc_mgr_go(mgr->id);
3844 msleep(50);
3845
3846 if (enable)
3847 dssdev->driver->enable(dssdev);
3848 }
3849 }
3850
3851 if (errors & DISPC_IRQ_OCP_ERR) {
3852 DSSERR("OCP_ERR\n");
3853 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3854 struct omap_overlay_manager *mgr;
3855 struct omap_dss_device *dssdev;
3856 3425
3857 mgr = omap_dss_get_overlay_manager(i); 3426 /* clear the irqstatus for newly enabled irqs */
3858 dssdev = mgr->get_device(mgr); 3427 dispc_clear_irqstatus((mask ^ old_mask) & mask);
3859
3860 if (dssdev && dssdev->driver)
3861 dssdev->driver->disable(dssdev);
3862 }
3863 }
3864
3865 spin_lock_irqsave(&dispc.irq_lock, flags);
3866 dispc.irq_error_mask |= errors;
3867 _omap_dispc_set_irqs();
3868 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3869
3870 dispc_runtime_put();
3871}
3872
3873int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
3874{
3875 void dispc_irq_wait_handler(void *data, u32 mask)
3876 {
3877 complete((struct completion *)data);
3878 }
3879
3880 int r;
3881 DECLARE_COMPLETION_ONSTACK(completion);
3882
3883 r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
3884 irqmask);
3885
3886 if (r)
3887 return r;
3888
3889 timeout = wait_for_completion_timeout(&completion, timeout);
3890
3891 omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
3892
3893 if (timeout == 0)
3894 return -ETIMEDOUT;
3895
3896 if (timeout == -ERESTARTSYS)
3897 return -ERESTARTSYS;
3898
3899 return 0;
3900}
3901
3902int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
3903 unsigned long timeout)
3904{
3905 void dispc_irq_wait_handler(void *data, u32 mask)
3906 {
3907 complete((struct completion *)data);
3908 }
3909
3910 int r;
3911 DECLARE_COMPLETION_ONSTACK(completion);
3912
3913 r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
3914 irqmask);
3915
3916 if (r)
3917 return r;
3918
3919 timeout = wait_for_completion_interruptible_timeout(&completion,
3920 timeout);
3921
3922 omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
3923
3924 if (timeout == 0)
3925 return -ETIMEDOUT;
3926
3927 if (timeout == -ERESTARTSYS)
3928 return -ERESTARTSYS;
3929
3930 return 0;
3931}
3932
3933static void _omap_dispc_initialize_irq(void)
3934{
3935 unsigned long flags;
3936
3937 spin_lock_irqsave(&dispc.irq_lock, flags);
3938
3939 memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
3940
3941 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
3942 if (dss_has_feature(FEAT_MGR_LCD2))
3943 dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
3944 if (dss_has_feature(FEAT_MGR_LCD3))
3945 dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
3946 if (dss_feat_get_num_ovls() > 3)
3947 dispc.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
3948
3949 /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
3950 * so clear it */
3951 dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
3952
3953 _omap_dispc_set_irqs();
3954 3428
3955 spin_unlock_irqrestore(&dispc.irq_lock, flags); 3429 dispc_write_reg(DISPC_IRQENABLE, mask);
3956} 3430}
3431EXPORT_SYMBOL(dispc_write_irqenable);
3957 3432
3958void dispc_enable_sidle(void) 3433void dispc_enable_sidle(void)
3959{ 3434{
@@ -4000,9 +3475,14 @@ static const struct dispc_features omap24xx_dispc_feats __initconst = {
4000 .sw_max = 64, 3475 .sw_max = 64,
4001 .vp_max = 255, 3476 .vp_max = 255,
4002 .hp_max = 256, 3477 .hp_max = 256,
3478 .mgr_width_start = 10,
3479 .mgr_height_start = 26,
3480 .mgr_width_max = 2048,
3481 .mgr_height_max = 2048,
4003 .calc_scaling = dispc_ovl_calc_scaling_24xx, 3482 .calc_scaling = dispc_ovl_calc_scaling_24xx,
4004 .calc_core_clk = calc_core_clk_24xx, 3483 .calc_core_clk = calc_core_clk_24xx,
4005 .num_fifos = 3, 3484 .num_fifos = 3,
3485 .no_framedone_tv = true,
4006}; 3486};
4007 3487
4008static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = { 3488static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
@@ -4012,9 +3492,14 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
4012 .sw_max = 64, 3492 .sw_max = 64,
4013 .vp_max = 255, 3493 .vp_max = 255,
4014 .hp_max = 256, 3494 .hp_max = 256,
3495 .mgr_width_start = 10,
3496 .mgr_height_start = 26,
3497 .mgr_width_max = 2048,
3498 .mgr_height_max = 2048,
4015 .calc_scaling = dispc_ovl_calc_scaling_34xx, 3499 .calc_scaling = dispc_ovl_calc_scaling_34xx,
4016 .calc_core_clk = calc_core_clk_34xx, 3500 .calc_core_clk = calc_core_clk_34xx,
4017 .num_fifos = 3, 3501 .num_fifos = 3,
3502 .no_framedone_tv = true,
4018}; 3503};
4019 3504
4020static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = { 3505static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
@@ -4024,9 +3509,14 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
4024 .sw_max = 256, 3509 .sw_max = 256,
4025 .vp_max = 4095, 3510 .vp_max = 4095,
4026 .hp_max = 4096, 3511 .hp_max = 4096,
3512 .mgr_width_start = 10,
3513 .mgr_height_start = 26,
3514 .mgr_width_max = 2048,
3515 .mgr_height_max = 2048,
4027 .calc_scaling = dispc_ovl_calc_scaling_34xx, 3516 .calc_scaling = dispc_ovl_calc_scaling_34xx,
4028 .calc_core_clk = calc_core_clk_34xx, 3517 .calc_core_clk = calc_core_clk_34xx,
4029 .num_fifos = 3, 3518 .num_fifos = 3,
3519 .no_framedone_tv = true,
4030}; 3520};
4031 3521
4032static const struct dispc_features omap44xx_dispc_feats __initconst = { 3522static const struct dispc_features omap44xx_dispc_feats __initconst = {
@@ -4036,35 +3526,70 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = {
4036 .sw_max = 256, 3526 .sw_max = 256,
4037 .vp_max = 4095, 3527 .vp_max = 4095,
4038 .hp_max = 4096, 3528 .hp_max = 4096,
3529 .mgr_width_start = 10,
3530 .mgr_height_start = 26,
3531 .mgr_width_max = 2048,
3532 .mgr_height_max = 2048,
3533 .calc_scaling = dispc_ovl_calc_scaling_44xx,
3534 .calc_core_clk = calc_core_clk_44xx,
3535 .num_fifos = 5,
3536 .gfx_fifo_workaround = true,
3537};
3538
3539static const struct dispc_features omap54xx_dispc_feats __initconst = {
3540 .sw_start = 7,
3541 .fp_start = 19,
3542 .bp_start = 31,
3543 .sw_max = 256,
3544 .vp_max = 4095,
3545 .hp_max = 4096,
3546 .mgr_width_start = 11,
3547 .mgr_height_start = 27,
3548 .mgr_width_max = 4096,
3549 .mgr_height_max = 4096,
4039 .calc_scaling = dispc_ovl_calc_scaling_44xx, 3550 .calc_scaling = dispc_ovl_calc_scaling_44xx,
4040 .calc_core_clk = calc_core_clk_44xx, 3551 .calc_core_clk = calc_core_clk_44xx,
4041 .num_fifos = 5, 3552 .num_fifos = 5,
4042 .gfx_fifo_workaround = true, 3553 .gfx_fifo_workaround = true,
4043}; 3554};
4044 3555
4045static int __init dispc_init_features(struct device *dev) 3556static int __init dispc_init_features(struct platform_device *pdev)
4046{ 3557{
4047 const struct dispc_features *src; 3558 const struct dispc_features *src;
4048 struct dispc_features *dst; 3559 struct dispc_features *dst;
4049 3560
4050 dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL); 3561 dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
4051 if (!dst) { 3562 if (!dst) {
4052 dev_err(dev, "Failed to allocate DISPC Features\n"); 3563 dev_err(&pdev->dev, "Failed to allocate DISPC Features\n");
4053 return -ENOMEM; 3564 return -ENOMEM;
4054 } 3565 }
4055 3566
4056 if (cpu_is_omap24xx()) { 3567 switch (omapdss_get_version()) {
3568 case OMAPDSS_VER_OMAP24xx:
4057 src = &omap24xx_dispc_feats; 3569 src = &omap24xx_dispc_feats;
4058 } else if (cpu_is_omap34xx()) { 3570 break;
4059 if (omap_rev() < OMAP3430_REV_ES3_0) 3571
4060 src = &omap34xx_rev1_0_dispc_feats; 3572 case OMAPDSS_VER_OMAP34xx_ES1:
4061 else 3573 src = &omap34xx_rev1_0_dispc_feats;
4062 src = &omap34xx_rev3_0_dispc_feats; 3574 break;
4063 } else if (cpu_is_omap44xx()) { 3575
4064 src = &omap44xx_dispc_feats; 3576 case OMAPDSS_VER_OMAP34xx_ES3:
4065 } else if (soc_is_omap54xx()) { 3577 case OMAPDSS_VER_OMAP3630:
3578 case OMAPDSS_VER_AM35xx:
3579 src = &omap34xx_rev3_0_dispc_feats;
3580 break;
3581
3582 case OMAPDSS_VER_OMAP4430_ES1:
3583 case OMAPDSS_VER_OMAP4430_ES2:
3584 case OMAPDSS_VER_OMAP4:
4066 src = &omap44xx_dispc_feats; 3585 src = &omap44xx_dispc_feats;
4067 } else { 3586 break;
3587
3588 case OMAPDSS_VER_OMAP5:
3589 src = &omap54xx_dispc_feats;
3590 break;
3591
3592 default:
4068 return -ENODEV; 3593 return -ENODEV;
4069 } 3594 }
4070 3595
@@ -4074,29 +3599,32 @@ static int __init dispc_init_features(struct device *dev)
4074 return 0; 3599 return 0;
4075} 3600}
4076 3601
3602int dispc_request_irq(irq_handler_t handler, void *dev_id)
3603{
3604 return devm_request_irq(&dispc.pdev->dev, dispc.irq, handler,
3605 IRQF_SHARED, "OMAP DISPC", dev_id);
3606}
3607EXPORT_SYMBOL(dispc_request_irq);
3608
3609void dispc_free_irq(void *dev_id)
3610{
3611 devm_free_irq(&dispc.pdev->dev, dispc.irq, dev_id);
3612}
3613EXPORT_SYMBOL(dispc_free_irq);
3614
4077/* DISPC HW IP initialisation */ 3615/* DISPC HW IP initialisation */
4078static int __init omap_dispchw_probe(struct platform_device *pdev) 3616static int __init omap_dispchw_probe(struct platform_device *pdev)
4079{ 3617{
4080 u32 rev; 3618 u32 rev;
4081 int r = 0; 3619 int r = 0;
4082 struct resource *dispc_mem; 3620 struct resource *dispc_mem;
4083 struct clk *clk;
4084 3621
4085 dispc.pdev = pdev; 3622 dispc.pdev = pdev;
4086 3623
4087 r = dispc_init_features(&dispc.pdev->dev); 3624 r = dispc_init_features(dispc.pdev);
4088 if (r) 3625 if (r)
4089 return r; 3626 return r;
4090 3627
4091 spin_lock_init(&dispc.irq_lock);
4092
4093#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
4094 spin_lock_init(&dispc.irq_stats_lock);
4095 dispc.irq_stats.last_reset = jiffies;
4096#endif
4097
4098 INIT_WORK(&dispc.error_work, dispc_error_worker);
4099
4100 dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0); 3628 dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
4101 if (!dispc_mem) { 3629 if (!dispc_mem) {
4102 DSSERR("can't get IORESOURCE_MEM DISPC\n"); 3630 DSSERR("can't get IORESOURCE_MEM DISPC\n");
@@ -4116,22 +3644,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
4116 return -ENODEV; 3644 return -ENODEV;
4117 } 3645 }
4118 3646
4119 r = devm_request_irq(&pdev->dev, dispc.irq, omap_dispc_irq_handler,
4120 IRQF_SHARED, "OMAP DISPC", dispc.pdev);
4121 if (r < 0) {
4122 DSSERR("request_irq failed\n");
4123 return r;
4124 }
4125
4126 clk = clk_get(&pdev->dev, "fck");
4127 if (IS_ERR(clk)) {
4128 DSSERR("can't get fck\n");
4129 r = PTR_ERR(clk);
4130 return r;
4131 }
4132
4133 dispc.dss_clk = clk;
4134
4135 pm_runtime_enable(&pdev->dev); 3647 pm_runtime_enable(&pdev->dev);
4136 3648
4137 r = dispc_runtime_get(); 3649 r = dispc_runtime_get();
@@ -4140,8 +3652,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
4140 3652
4141 _omap_dispc_initial_config(); 3653 _omap_dispc_initial_config();
4142 3654
4143 _omap_dispc_initialize_irq();
4144
4145 rev = dispc_read_reg(DISPC_REVISION); 3655 rev = dispc_read_reg(DISPC_REVISION);
4146 dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n", 3656 dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
4147 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 3657 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
@@ -4150,14 +3660,10 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
4150 3660
4151 dss_debugfs_create_file("dispc", dispc_dump_regs); 3661 dss_debugfs_create_file("dispc", dispc_dump_regs);
4152 3662
4153#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
4154 dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
4155#endif
4156 return 0; 3663 return 0;
4157 3664
4158err_runtime_get: 3665err_runtime_get:
4159 pm_runtime_disable(&pdev->dev); 3666 pm_runtime_disable(&pdev->dev);
4160 clk_put(dispc.dss_clk);
4161 return r; 3667 return r;
4162} 3668}
4163 3669
@@ -4165,8 +3671,6 @@ static int __exit omap_dispchw_remove(struct platform_device *pdev)
4165{ 3671{
4166 pm_runtime_disable(&pdev->dev); 3672 pm_runtime_disable(&pdev->dev);
4167 3673
4168 clk_put(dispc.dss_clk);
4169
4170 return 0; 3674 return 0;
4171} 3675}
4172 3676
diff --git a/drivers/video/omap2/dss/display-sysfs.c b/drivers/video/omap2/dss/display-sysfs.c
new file mode 100644
index 000000000000..18211a9ab354
--- /dev/null
+++ b/drivers/video/omap2/dss/display-sysfs.c
@@ -0,0 +1,321 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * Some code and ideas taken from drivers/video/omap/ driver
6 * by Imre Deak.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#define DSS_SUBSYS_NAME "DISPLAY"
22
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/jiffies.h>
26#include <linux/platform_device.h>
27
28#include <video/omapdss.h>
29#include "dss.h"
30#include "dss_features.h"
31
32static ssize_t display_enabled_show(struct device *dev,
33 struct device_attribute *attr, char *buf)
34{
35 struct omap_dss_device *dssdev = to_dss_device(dev);
36 bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
37
38 return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
39}
40
41static ssize_t display_enabled_store(struct device *dev,
42 struct device_attribute *attr,
43 const char *buf, size_t size)
44{
45 struct omap_dss_device *dssdev = to_dss_device(dev);
46 int r;
47 bool enabled;
48
49 r = strtobool(buf, &enabled);
50 if (r)
51 return r;
52
53 if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
54 if (enabled) {
55 r = dssdev->driver->enable(dssdev);
56 if (r)
57 return r;
58 } else {
59 dssdev->driver->disable(dssdev);
60 }
61 }
62
63 return size;
64}
65
66static ssize_t display_tear_show(struct device *dev,
67 struct device_attribute *attr, char *buf)
68{
69 struct omap_dss_device *dssdev = to_dss_device(dev);
70 return snprintf(buf, PAGE_SIZE, "%d\n",
71 dssdev->driver->get_te ?
72 dssdev->driver->get_te(dssdev) : 0);
73}
74
75static ssize_t display_tear_store(struct device *dev,
76 struct device_attribute *attr, const char *buf, size_t size)
77{
78 struct omap_dss_device *dssdev = to_dss_device(dev);
79 int r;
80 bool te;
81
82 if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
83 return -ENOENT;
84
85 r = strtobool(buf, &te);
86 if (r)
87 return r;
88
89 r = dssdev->driver->enable_te(dssdev, te);
90 if (r)
91 return r;
92
93 return size;
94}
95
96static ssize_t display_timings_show(struct device *dev,
97 struct device_attribute *attr, char *buf)
98{
99 struct omap_dss_device *dssdev = to_dss_device(dev);
100 struct omap_video_timings t;
101
102 if (!dssdev->driver->get_timings)
103 return -ENOENT;
104
105 dssdev->driver->get_timings(dssdev, &t);
106
107 return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
108 t.pixel_clock,
109 t.x_res, t.hfp, t.hbp, t.hsw,
110 t.y_res, t.vfp, t.vbp, t.vsw);
111}
112
113static ssize_t display_timings_store(struct device *dev,
114 struct device_attribute *attr, const char *buf, size_t size)
115{
116 struct omap_dss_device *dssdev = to_dss_device(dev);
117 struct omap_video_timings t = dssdev->panel.timings;
118 int r, found;
119
120 if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
121 return -ENOENT;
122
123 found = 0;
124#ifdef CONFIG_OMAP2_DSS_VENC
125 if (strncmp("pal", buf, 3) == 0) {
126 t = omap_dss_pal_timings;
127 found = 1;
128 } else if (strncmp("ntsc", buf, 4) == 0) {
129 t = omap_dss_ntsc_timings;
130 found = 1;
131 }
132#endif
133 if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
134 &t.pixel_clock,
135 &t.x_res, &t.hfp, &t.hbp, &t.hsw,
136 &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
137 return -EINVAL;
138
139 r = dssdev->driver->check_timings(dssdev, &t);
140 if (r)
141 return r;
142
143 dssdev->driver->disable(dssdev);
144 dssdev->driver->set_timings(dssdev, &t);
145 r = dssdev->driver->enable(dssdev);
146 if (r)
147 return r;
148
149 return size;
150}
151
152static ssize_t display_rotate_show(struct device *dev,
153 struct device_attribute *attr, char *buf)
154{
155 struct omap_dss_device *dssdev = to_dss_device(dev);
156 int rotate;
157 if (!dssdev->driver->get_rotate)
158 return -ENOENT;
159 rotate = dssdev->driver->get_rotate(dssdev);
160 return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
161}
162
163static ssize_t display_rotate_store(struct device *dev,
164 struct device_attribute *attr, const char *buf, size_t size)
165{
166 struct omap_dss_device *dssdev = to_dss_device(dev);
167 int rot, r;
168
169 if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
170 return -ENOENT;
171
172 r = kstrtoint(buf, 0, &rot);
173 if (r)
174 return r;
175
176 r = dssdev->driver->set_rotate(dssdev, rot);
177 if (r)
178 return r;
179
180 return size;
181}
182
183static ssize_t display_mirror_show(struct device *dev,
184 struct device_attribute *attr, char *buf)
185{
186 struct omap_dss_device *dssdev = to_dss_device(dev);
187 int mirror;
188 if (!dssdev->driver->get_mirror)
189 return -ENOENT;
190 mirror = dssdev->driver->get_mirror(dssdev);
191 return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
192}
193
194static ssize_t display_mirror_store(struct device *dev,
195 struct device_attribute *attr, const char *buf, size_t size)
196{
197 struct omap_dss_device *dssdev = to_dss_device(dev);
198 int r;
199 bool mirror;
200
201 if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
202 return -ENOENT;
203
204 r = strtobool(buf, &mirror);
205 if (r)
206 return r;
207
208 r = dssdev->driver->set_mirror(dssdev, mirror);
209 if (r)
210 return r;
211
212 return size;
213}
214
215static ssize_t display_wss_show(struct device *dev,
216 struct device_attribute *attr, char *buf)
217{
218 struct omap_dss_device *dssdev = to_dss_device(dev);
219 unsigned int wss;
220
221 if (!dssdev->driver->get_wss)
222 return -ENOENT;
223
224 wss = dssdev->driver->get_wss(dssdev);
225
226 return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
227}
228
229static ssize_t display_wss_store(struct device *dev,
230 struct device_attribute *attr, const char *buf, size_t size)
231{
232 struct omap_dss_device *dssdev = to_dss_device(dev);
233 u32 wss;
234 int r;
235
236 if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
237 return -ENOENT;
238
239 r = kstrtou32(buf, 0, &wss);
240 if (r)
241 return r;
242
243 if (wss > 0xfffff)
244 return -EINVAL;
245
246 r = dssdev->driver->set_wss(dssdev, wss);
247 if (r)
248 return r;
249
250 return size;
251}
252
253static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
254 display_enabled_show, display_enabled_store);
255static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
256 display_tear_show, display_tear_store);
257static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
258 display_timings_show, display_timings_store);
259static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
260 display_rotate_show, display_rotate_store);
261static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
262 display_mirror_show, display_mirror_store);
263static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
264 display_wss_show, display_wss_store);
265
266static struct device_attribute *display_sysfs_attrs[] = {
267 &dev_attr_enabled,
268 &dev_attr_tear_elim,
269 &dev_attr_timings,
270 &dev_attr_rotate,
271 &dev_attr_mirror,
272 &dev_attr_wss,
273 NULL
274};
275
276int display_init_sysfs(struct platform_device *pdev,
277 struct omap_dss_device *dssdev)
278{
279 struct device_attribute *attr;
280 int i, r;
281
282 /* create device sysfs files */
283 i = 0;
284 while ((attr = display_sysfs_attrs[i++]) != NULL) {
285 r = device_create_file(&dssdev->dev, attr);
286 if (r) {
287 for (i = i - 2; i >= 0; i--) {
288 attr = display_sysfs_attrs[i];
289 device_remove_file(&dssdev->dev, attr);
290 }
291
292 DSSERR("failed to create sysfs file\n");
293 return r;
294 }
295 }
296
297 /* create display? sysfs links */
298 r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
299 dev_name(&dssdev->dev));
300 if (r) {
301 while ((attr = display_sysfs_attrs[i++]) != NULL)
302 device_remove_file(&dssdev->dev, attr);
303
304 DSSERR("failed to create sysfs display link\n");
305 return r;
306 }
307
308 return 0;
309}
310
311void display_uninit_sysfs(struct platform_device *pdev,
312 struct omap_dss_device *dssdev)
313{
314 struct device_attribute *attr;
315 int i = 0;
316
317 sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
318
319 while ((attr = display_sysfs_attrs[i++]) != NULL)
320 device_remove_file(&dssdev->dev, attr);
321}
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index ccf8550fafde..0aa8ad8f9667 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -31,250 +31,6 @@
31#include "dss.h" 31#include "dss.h"
32#include "dss_features.h" 32#include "dss_features.h"
33 33
34static ssize_t display_enabled_show(struct device *dev,
35 struct device_attribute *attr, char *buf)
36{
37 struct omap_dss_device *dssdev = to_dss_device(dev);
38 bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
39
40 return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
41}
42
43static ssize_t display_enabled_store(struct device *dev,
44 struct device_attribute *attr,
45 const char *buf, size_t size)
46{
47 struct omap_dss_device *dssdev = to_dss_device(dev);
48 int r;
49 bool enabled;
50
51 r = strtobool(buf, &enabled);
52 if (r)
53 return r;
54
55 if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
56 if (enabled) {
57 r = dssdev->driver->enable(dssdev);
58 if (r)
59 return r;
60 } else {
61 dssdev->driver->disable(dssdev);
62 }
63 }
64
65 return size;
66}
67
68static ssize_t display_tear_show(struct device *dev,
69 struct device_attribute *attr, char *buf)
70{
71 struct omap_dss_device *dssdev = to_dss_device(dev);
72 return snprintf(buf, PAGE_SIZE, "%d\n",
73 dssdev->driver->get_te ?
74 dssdev->driver->get_te(dssdev) : 0);
75}
76
77static ssize_t display_tear_store(struct device *dev,
78 struct device_attribute *attr, const char *buf, size_t size)
79{
80 struct omap_dss_device *dssdev = to_dss_device(dev);
81 int r;
82 bool te;
83
84 if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
85 return -ENOENT;
86
87 r = strtobool(buf, &te);
88 if (r)
89 return r;
90
91 r = dssdev->driver->enable_te(dssdev, te);
92 if (r)
93 return r;
94
95 return size;
96}
97
98static ssize_t display_timings_show(struct device *dev,
99 struct device_attribute *attr, char *buf)
100{
101 struct omap_dss_device *dssdev = to_dss_device(dev);
102 struct omap_video_timings t;
103
104 if (!dssdev->driver->get_timings)
105 return -ENOENT;
106
107 dssdev->driver->get_timings(dssdev, &t);
108
109 return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
110 t.pixel_clock,
111 t.x_res, t.hfp, t.hbp, t.hsw,
112 t.y_res, t.vfp, t.vbp, t.vsw);
113}
114
115static ssize_t display_timings_store(struct device *dev,
116 struct device_attribute *attr, const char *buf, size_t size)
117{
118 struct omap_dss_device *dssdev = to_dss_device(dev);
119 struct omap_video_timings t = dssdev->panel.timings;
120 int r, found;
121
122 if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
123 return -ENOENT;
124
125 found = 0;
126#ifdef CONFIG_OMAP2_DSS_VENC
127 if (strncmp("pal", buf, 3) == 0) {
128 t = omap_dss_pal_timings;
129 found = 1;
130 } else if (strncmp("ntsc", buf, 4) == 0) {
131 t = omap_dss_ntsc_timings;
132 found = 1;
133 }
134#endif
135 if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
136 &t.pixel_clock,
137 &t.x_res, &t.hfp, &t.hbp, &t.hsw,
138 &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
139 return -EINVAL;
140
141 r = dssdev->driver->check_timings(dssdev, &t);
142 if (r)
143 return r;
144
145 dssdev->driver->disable(dssdev);
146 dssdev->driver->set_timings(dssdev, &t);
147 r = dssdev->driver->enable(dssdev);
148 if (r)
149 return r;
150
151 return size;
152}
153
154static ssize_t display_rotate_show(struct device *dev,
155 struct device_attribute *attr, char *buf)
156{
157 struct omap_dss_device *dssdev = to_dss_device(dev);
158 int rotate;
159 if (!dssdev->driver->get_rotate)
160 return -ENOENT;
161 rotate = dssdev->driver->get_rotate(dssdev);
162 return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
163}
164
165static ssize_t display_rotate_store(struct device *dev,
166 struct device_attribute *attr, const char *buf, size_t size)
167{
168 struct omap_dss_device *dssdev = to_dss_device(dev);
169 int rot, r;
170
171 if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
172 return -ENOENT;
173
174 r = kstrtoint(buf, 0, &rot);
175 if (r)
176 return r;
177
178 r = dssdev->driver->set_rotate(dssdev, rot);
179 if (r)
180 return r;
181
182 return size;
183}
184
185static ssize_t display_mirror_show(struct device *dev,
186 struct device_attribute *attr, char *buf)
187{
188 struct omap_dss_device *dssdev = to_dss_device(dev);
189 int mirror;
190 if (!dssdev->driver->get_mirror)
191 return -ENOENT;
192 mirror = dssdev->driver->get_mirror(dssdev);
193 return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
194}
195
196static ssize_t display_mirror_store(struct device *dev,
197 struct device_attribute *attr, const char *buf, size_t size)
198{
199 struct omap_dss_device *dssdev = to_dss_device(dev);
200 int r;
201 bool mirror;
202
203 if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
204 return -ENOENT;
205
206 r = strtobool(buf, &mirror);
207 if (r)
208 return r;
209
210 r = dssdev->driver->set_mirror(dssdev, mirror);
211 if (r)
212 return r;
213
214 return size;
215}
216
217static ssize_t display_wss_show(struct device *dev,
218 struct device_attribute *attr, char *buf)
219{
220 struct omap_dss_device *dssdev = to_dss_device(dev);
221 unsigned int wss;
222
223 if (!dssdev->driver->get_wss)
224 return -ENOENT;
225
226 wss = dssdev->driver->get_wss(dssdev);
227
228 return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
229}
230
231static ssize_t display_wss_store(struct device *dev,
232 struct device_attribute *attr, const char *buf, size_t size)
233{
234 struct omap_dss_device *dssdev = to_dss_device(dev);
235 u32 wss;
236 int r;
237
238 if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
239 return -ENOENT;
240
241 r = kstrtou32(buf, 0, &wss);
242 if (r)
243 return r;
244
245 if (wss > 0xfffff)
246 return -EINVAL;
247
248 r = dssdev->driver->set_wss(dssdev, wss);
249 if (r)
250 return r;
251
252 return size;
253}
254
255static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
256 display_enabled_show, display_enabled_store);
257static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
258 display_tear_show, display_tear_store);
259static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
260 display_timings_show, display_timings_store);
261static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
262 display_rotate_show, display_rotate_store);
263static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
264 display_mirror_show, display_mirror_store);
265static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
266 display_wss_show, display_wss_store);
267
268static struct device_attribute *display_sysfs_attrs[] = {
269 &dev_attr_enabled,
270 &dev_attr_tear_elim,
271 &dev_attr_timings,
272 &dev_attr_rotate,
273 &dev_attr_mirror,
274 &dev_attr_wss,
275 NULL
276};
277
278void omapdss_default_get_resolution(struct omap_dss_device *dssdev, 34void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
279 u16 *xres, u16 *yres) 35 u16 *xres, u16 *yres)
280{ 36{
@@ -320,136 +76,8 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev,
320} 76}
321EXPORT_SYMBOL(omapdss_default_get_timings); 77EXPORT_SYMBOL(omapdss_default_get_timings);
322 78
323/*
324 * Connect dssdev to a manager if the manager is free or if force is specified.
325 * Connect all overlays to that manager if they are free or if force is
326 * specified.
327 */
328static int dss_init_connections(struct omap_dss_device *dssdev, bool force)
329{
330 struct omap_dss_output *out;
331 struct omap_overlay_manager *mgr;
332 int i, r;
333
334 out = omapdss_get_output_from_dssdev(dssdev);
335
336 WARN_ON(dssdev->output);
337 WARN_ON(out->device);
338
339 r = omapdss_output_set_device(out, dssdev);
340 if (r) {
341 DSSERR("failed to connect output to new device\n");
342 return r;
343 }
344
345 mgr = omap_dss_get_overlay_manager(dssdev->channel);
346
347 if (mgr->output && !force)
348 return 0;
349
350 if (mgr->output)
351 mgr->unset_output(mgr);
352
353 r = mgr->set_output(mgr, out);
354 if (r) {
355 DSSERR("failed to connect manager to output of new device\n");
356
357 /* remove the output-device connection we just made */
358 omapdss_output_unset_device(out);
359 return r;
360 }
361
362 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
363 struct omap_overlay *ovl = omap_dss_get_overlay(i);
364
365 if (!ovl->manager || force) {
366 if (ovl->manager)
367 ovl->unset_manager(ovl);
368
369 r = ovl->set_manager(ovl, mgr);
370 if (r) {
371 DSSERR("failed to set initial overlay\n");
372 return r;
373 }
374 }
375 }
376
377 return 0;
378}
379
380static void dss_uninit_connections(struct omap_dss_device *dssdev)
381{
382 if (dssdev->output) {
383 struct omap_overlay_manager *mgr = dssdev->output->manager;
384
385 if (mgr)
386 mgr->unset_output(mgr);
387
388 omapdss_output_unset_device(dssdev->output);
389 }
390}
391
392int dss_init_device(struct platform_device *pdev,
393 struct omap_dss_device *dssdev)
394{
395 struct device_attribute *attr;
396 int i, r;
397 const char *def_disp_name = dss_get_default_display_name();
398 bool force;
399
400 force = def_disp_name && strcmp(def_disp_name, dssdev->name) == 0;
401 dss_init_connections(dssdev, force);
402
403 /* create device sysfs files */
404 i = 0;
405 while ((attr = display_sysfs_attrs[i++]) != NULL) {
406 r = device_create_file(&dssdev->dev, attr);
407 if (r) {
408 for (i = i - 2; i >= 0; i--) {
409 attr = display_sysfs_attrs[i];
410 device_remove_file(&dssdev->dev, attr);
411 }
412
413 dss_uninit_connections(dssdev);
414
415 DSSERR("failed to create sysfs file\n");
416 return r;
417 }
418 }
419
420 /* create display? sysfs links */
421 r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
422 dev_name(&dssdev->dev));
423 if (r) {
424 while ((attr = display_sysfs_attrs[i++]) != NULL)
425 device_remove_file(&dssdev->dev, attr);
426
427 dss_uninit_connections(dssdev);
428
429 DSSERR("failed to create sysfs display link\n");
430 return r;
431 }
432
433 return 0;
434}
435
436void dss_uninit_device(struct platform_device *pdev,
437 struct omap_dss_device *dssdev)
438{
439 struct device_attribute *attr;
440 int i = 0;
441
442 sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
443
444 while ((attr = display_sysfs_attrs[i++]) != NULL)
445 device_remove_file(&dssdev->dev, attr);
446
447 dss_uninit_connections(dssdev);
448}
449
450static int dss_suspend_device(struct device *dev, void *data) 79static int dss_suspend_device(struct device *dev, void *data)
451{ 80{
452 int r;
453 struct omap_dss_device *dssdev = to_dss_device(dev); 81 struct omap_dss_device *dssdev = to_dss_device(dev);
454 82
455 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { 83 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
@@ -457,15 +85,7 @@ static int dss_suspend_device(struct device *dev, void *data)
457 return 0; 85 return 0;
458 } 86 }
459 87
460 if (!dssdev->driver->suspend) { 88 dssdev->driver->disable(dssdev);
461 DSSERR("display '%s' doesn't implement suspend\n",
462 dssdev->name);
463 return -ENOSYS;
464 }
465
466 r = dssdev->driver->suspend(dssdev);
467 if (r)
468 return r;
469 89
470 dssdev->activate_after_resume = true; 90 dssdev->activate_after_resume = true;
471 91
@@ -492,8 +112,8 @@ static int dss_resume_device(struct device *dev, void *data)
492 int r; 112 int r;
493 struct omap_dss_device *dssdev = to_dss_device(dev); 113 struct omap_dss_device *dssdev = to_dss_device(dev);
494 114
495 if (dssdev->activate_after_resume && dssdev->driver->resume) { 115 if (dssdev->activate_after_resume) {
496 r = dssdev->driver->resume(dssdev); 116 r = dssdev->driver->enable(dssdev);
497 if (r) 117 if (r)
498 return r; 118 return r;
499 } 119 }
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 56748cf8760e..4af136a04e53 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -49,34 +49,53 @@ static struct {
49 struct omap_dss_output output; 49 struct omap_dss_output output;
50} dpi; 50} dpi;
51 51
52static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk) 52static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
53{ 53{
54 int dsi_module; 54 /*
55 55 * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
56 dsi_module = clk == OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ? 0 : 1; 56 * would also be used for DISPC fclk. Meaning, when the DPI output is
57 * disabled, DISPC clock will be disabled, and TV out will stop.
58 */
59 switch (omapdss_get_version()) {
60 case OMAPDSS_VER_OMAP24xx:
61 case OMAPDSS_VER_OMAP34xx_ES1:
62 case OMAPDSS_VER_OMAP34xx_ES3:
63 case OMAPDSS_VER_OMAP3630:
64 case OMAPDSS_VER_AM35xx:
65 return NULL;
66 default:
67 break;
68 }
57 69
58 return dsi_get_dsidev_from_id(dsi_module); 70 switch (channel) {
71 case OMAP_DSS_CHANNEL_LCD:
72 return dsi_get_dsidev_from_id(0);
73 case OMAP_DSS_CHANNEL_LCD2:
74 return dsi_get_dsidev_from_id(1);
75 default:
76 return NULL;
77 }
59} 78}
60 79
61static bool dpi_use_dsi_pll(struct omap_dss_device *dssdev) 80static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
62{ 81{
63 if (dssdev->clocks.dispc.dispc_fclk_src == 82 switch (channel) {
64 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC || 83 case OMAP_DSS_CHANNEL_LCD:
65 dssdev->clocks.dispc.dispc_fclk_src == 84 return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC;
66 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC || 85 case OMAP_DSS_CHANNEL_LCD2:
67 dssdev->clocks.dispc.channel.lcd_clk_src == 86 return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
68 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC || 87 default:
69 dssdev->clocks.dispc.channel.lcd_clk_src == 88 /* this shouldn't happen */
70 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC) 89 WARN_ON(1);
71 return true; 90 return OMAP_DSS_CLK_SRC_FCK;
72 else 91 }
73 return false;
74} 92}
75 93
76static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, 94static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
77 unsigned long pck_req, unsigned long *fck, int *lck_div, 95 unsigned long pck_req, unsigned long *fck, int *lck_div,
78 int *pck_div) 96 int *pck_div)
79{ 97{
98 struct omap_overlay_manager *mgr = dssdev->output->manager;
80 struct dsi_clock_info dsi_cinfo; 99 struct dsi_clock_info dsi_cinfo;
81 struct dispc_clock_info dispc_cinfo; 100 struct dispc_clock_info dispc_cinfo;
82 int r; 101 int r;
@@ -90,7 +109,8 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
90 if (r) 109 if (r)
91 return r; 110 return r;
92 111
93 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); 112 dss_select_lcd_clk_source(mgr->id,
113 dpi_get_alt_clk_src(mgr->id));
94 114
95 dpi.mgr_config.clock_info = dispc_cinfo; 115 dpi.mgr_config.clock_info = dispc_cinfo;
96 116
@@ -135,7 +155,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
135 unsigned long pck; 155 unsigned long pck;
136 int r = 0; 156 int r = 0;
137 157
138 if (dpi_use_dsi_pll(dssdev)) 158 if (dpi.dsidev)
139 r = dpi_set_dsi_clk(dssdev, t->pixel_clock * 1000, &fck, 159 r = dpi_set_dsi_clk(dssdev, t->pixel_clock * 1000, &fck,
140 &lck_div, &pck_div); 160 &lck_div, &pck_div);
141 else 161 else
@@ -214,7 +234,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
214 if (r) 234 if (r)
215 goto err_src_sel; 235 goto err_src_sel;
216 236
217 if (dpi_use_dsi_pll(dssdev)) { 237 if (dpi.dsidev) {
218 r = dsi_runtime_get(dpi.dsidev); 238 r = dsi_runtime_get(dpi.dsidev);
219 if (r) 239 if (r)
220 goto err_get_dsi; 240 goto err_get_dsi;
@@ -242,10 +262,10 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
242 262
243err_mgr_enable: 263err_mgr_enable:
244err_set_mode: 264err_set_mode:
245 if (dpi_use_dsi_pll(dssdev)) 265 if (dpi.dsidev)
246 dsi_pll_uninit(dpi.dsidev, true); 266 dsi_pll_uninit(dpi.dsidev, true);
247err_dsi_pll_init: 267err_dsi_pll_init:
248 if (dpi_use_dsi_pll(dssdev)) 268 if (dpi.dsidev)
249 dsi_runtime_put(dpi.dsidev); 269 dsi_runtime_put(dpi.dsidev);
250err_get_dsi: 270err_get_dsi:
251err_src_sel: 271err_src_sel:
@@ -271,8 +291,8 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
271 291
272 dss_mgr_disable(mgr); 292 dss_mgr_disable(mgr);
273 293
274 if (dpi_use_dsi_pll(dssdev)) { 294 if (dpi.dsidev) {
275 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 295 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
276 dsi_pll_uninit(dpi.dsidev, true); 296 dsi_pll_uninit(dpi.dsidev, true);
277 dsi_runtime_put(dpi.dsidev); 297 dsi_runtime_put(dpi.dsidev);
278 } 298 }
@@ -311,13 +331,13 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
311 unsigned long pck; 331 unsigned long pck;
312 struct dispc_clock_info dispc_cinfo; 332 struct dispc_clock_info dispc_cinfo;
313 333
314 if (dss_mgr_check_timings(mgr, timings)) 334 if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
315 return -EINVAL; 335 return -EINVAL;
316 336
317 if (timings->pixel_clock == 0) 337 if (timings->pixel_clock == 0)
318 return -EINVAL; 338 return -EINVAL;
319 339
320 if (dpi_use_dsi_pll(dssdev)) { 340 if (dpi.dsidev) {
321 struct dsi_clock_info dsi_cinfo; 341 struct dsi_clock_info dsi_cinfo;
322 r = dsi_pll_calc_clock_div_pck(dpi.dsidev, 342 r = dsi_pll_calc_clock_div_pck(dpi.dsidev,
323 timings->pixel_clock * 1000, 343 timings->pixel_clock * 1000,
@@ -359,8 +379,32 @@ void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
359} 379}
360EXPORT_SYMBOL(omapdss_dpi_set_data_lines); 380EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
361 381
382static int __init dpi_verify_dsi_pll(struct platform_device *dsidev)
383{
384 int r;
385
386 /* do initial setup with the PLL to see if it is operational */
387
388 r = dsi_runtime_get(dsidev);
389 if (r)
390 return r;
391
392 r = dsi_pll_init(dsidev, 0, 1);
393 if (r) {
394 dsi_runtime_put(dsidev);
395 return r;
396 }
397
398 dsi_pll_uninit(dsidev, true);
399 dsi_runtime_put(dsidev);
400
401 return 0;
402}
403
362static int __init dpi_init_display(struct omap_dss_device *dssdev) 404static int __init dpi_init_display(struct omap_dss_device *dssdev)
363{ 405{
406 struct platform_device *dsidev;
407
364 DSSDBG("init_display\n"); 408 DSSDBG("init_display\n");
365 409
366 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && 410 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) &&
@@ -377,19 +421,30 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
377 dpi.vdds_dsi_reg = vdds_dsi; 421 dpi.vdds_dsi_reg = vdds_dsi;
378 } 422 }
379 423
380 if (dpi_use_dsi_pll(dssdev)) { 424 /*
381 enum omap_dss_clk_source dispc_fclk_src = 425 * XXX We shouldn't need dssdev->channel for this. The dsi pll clock
382 dssdev->clocks.dispc.dispc_fclk_src; 426 * source for DPI is SoC integration detail, not something that should
383 dpi.dsidev = dpi_get_dsidev(dispc_fclk_src); 427 * be configured in the dssdev
428 */
429 dsidev = dpi_get_dsidev(dssdev->channel);
430
431 if (dsidev && dpi_verify_dsi_pll(dsidev)) {
432 dsidev = NULL;
433 DSSWARN("DSI PLL not operational\n");
384 } 434 }
385 435
436 if (dsidev)
437 DSSDBG("using DSI PLL for DPI clock\n");
438
439 dpi.dsidev = dsidev;
440
386 return 0; 441 return 0;
387} 442}
388 443
389static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev) 444static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
390{ 445{
391 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 446 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
392 const char *def_disp_name = dss_get_default_display_name(); 447 const char *def_disp_name = omapdss_get_default_display_name();
393 struct omap_dss_device *def_dssdev; 448 struct omap_dss_device *def_dssdev;
394 int i; 449 int i;
395 450
@@ -438,9 +493,18 @@ static void __init dpi_probe_pdata(struct platform_device *dpidev)
438 return; 493 return;
439 } 494 }
440 495
496 r = omapdss_output_set_device(&dpi.output, dssdev);
497 if (r) {
498 DSSERR("failed to connect output to new device: %s\n",
499 dssdev->name);
500 dss_put_device(dssdev);
501 return;
502 }
503
441 r = dss_add_device(dssdev); 504 r = dss_add_device(dssdev);
442 if (r) { 505 if (r) {
443 DSSERR("device %s register failed: %d\n", dssdev->name, r); 506 DSSERR("device %s register failed: %d\n", dssdev->name, r);
507 omapdss_output_unset_device(&dpi.output);
444 dss_put_device(dssdev); 508 dss_put_device(dssdev);
445 return; 509 return;
446 } 510 }
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index bee92846cfab..28d41d16b7be 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -45,7 +45,6 @@
45#include "dss.h" 45#include "dss.h"
46#include "dss_features.h" 46#include "dss_features.h"
47 47
48/*#define VERBOSE_IRQ*/
49#define DSI_CATCH_MISSING_TE 48#define DSI_CATCH_MISSING_TE
50 49
51struct dsi_reg { u16 idx; }; 50struct dsi_reg { u16 idx; };
@@ -535,42 +534,38 @@ static inline void dsi_perf_show(struct platform_device *dsidev,
535} 534}
536#endif 535#endif
537 536
537static int verbose_irq;
538
538static void print_irq_status(u32 status) 539static void print_irq_status(u32 status)
539{ 540{
540 if (status == 0) 541 if (status == 0)
541 return; 542 return;
542 543
543#ifndef VERBOSE_IRQ 544 if (!verbose_irq && (status & ~DSI_IRQ_CHANNEL_MASK) == 0)
544 if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
545 return; 545 return;
546#endif
547 printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status);
548 546
549#define PIS(x) \ 547#define PIS(x) (status & DSI_IRQ_##x) ? (#x " ") : ""
550 if (status & DSI_IRQ_##x) \ 548
551 printk(#x " "); 549 pr_debug("DSI IRQ: 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
552#ifdef VERBOSE_IRQ 550 status,
553 PIS(VC0); 551 verbose_irq ? PIS(VC0) : "",
554 PIS(VC1); 552 verbose_irq ? PIS(VC1) : "",
555 PIS(VC2); 553 verbose_irq ? PIS(VC2) : "",
556 PIS(VC3); 554 verbose_irq ? PIS(VC3) : "",
557#endif 555 PIS(WAKEUP),
558 PIS(WAKEUP); 556 PIS(RESYNC),
559 PIS(RESYNC); 557 PIS(PLL_LOCK),
560 PIS(PLL_LOCK); 558 PIS(PLL_UNLOCK),
561 PIS(PLL_UNLOCK); 559 PIS(PLL_RECALL),
562 PIS(PLL_RECALL); 560 PIS(COMPLEXIO_ERR),
563 PIS(COMPLEXIO_ERR); 561 PIS(HS_TX_TIMEOUT),
564 PIS(HS_TX_TIMEOUT); 562 PIS(LP_RX_TIMEOUT),
565 PIS(LP_RX_TIMEOUT); 563 PIS(TE_TRIGGER),
566 PIS(TE_TRIGGER); 564 PIS(ACK_TRIGGER),
567 PIS(ACK_TRIGGER); 565 PIS(SYNC_LOST),
568 PIS(SYNC_LOST); 566 PIS(LDO_POWER_GOOD),
569 PIS(LDO_POWER_GOOD); 567 PIS(TA_TIMEOUT));
570 PIS(TA_TIMEOUT);
571#undef PIS 568#undef PIS
572
573 printk("\n");
574} 569}
575 570
576static void print_irq_status_vc(int channel, u32 status) 571static void print_irq_status_vc(int channel, u32 status)
@@ -578,28 +573,24 @@ static void print_irq_status_vc(int channel, u32 status)
578 if (status == 0) 573 if (status == 0)
579 return; 574 return;
580 575
581#ifndef VERBOSE_IRQ 576 if (!verbose_irq && (status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
582 if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
583 return; 577 return;
584#endif
585 printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status);
586 578
587#define PIS(x) \ 579#define PIS(x) (status & DSI_VC_IRQ_##x) ? (#x " ") : ""
588 if (status & DSI_VC_IRQ_##x) \ 580
589 printk(#x " "); 581 pr_debug("DSI VC(%d) IRQ 0x%x: %s%s%s%s%s%s%s%s%s\n",
590 PIS(CS); 582 channel,
591 PIS(ECC_CORR); 583 status,
592#ifdef VERBOSE_IRQ 584 PIS(CS),
593 PIS(PACKET_SENT); 585 PIS(ECC_CORR),
594#endif 586 PIS(ECC_NO_CORR),
595 PIS(FIFO_TX_OVF); 587 verbose_irq ? PIS(PACKET_SENT) : "",
596 PIS(FIFO_RX_OVF); 588 PIS(BTA),
597 PIS(BTA); 589 PIS(FIFO_TX_OVF),
598 PIS(ECC_NO_CORR); 590 PIS(FIFO_RX_OVF),
599 PIS(FIFO_TX_UDF); 591 PIS(FIFO_TX_UDF),
600 PIS(PP_BUSY_CHANGE); 592 PIS(PP_BUSY_CHANGE));
601#undef PIS 593#undef PIS
602 printk("\n");
603} 594}
604 595
605static void print_irq_status_cio(u32 status) 596static void print_irq_status_cio(u32 status)
@@ -607,34 +598,31 @@ static void print_irq_status_cio(u32 status)
607 if (status == 0) 598 if (status == 0)
608 return; 599 return;
609 600
610 printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status); 601#define PIS(x) (status & DSI_CIO_IRQ_##x) ? (#x " ") : ""
611 602
612#define PIS(x) \ 603 pr_debug("DSI CIO IRQ 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
613 if (status & DSI_CIO_IRQ_##x) \ 604 status,
614 printk(#x " "); 605 PIS(ERRSYNCESC1),
615 PIS(ERRSYNCESC1); 606 PIS(ERRSYNCESC2),
616 PIS(ERRSYNCESC2); 607 PIS(ERRSYNCESC3),
617 PIS(ERRSYNCESC3); 608 PIS(ERRESC1),
618 PIS(ERRESC1); 609 PIS(ERRESC2),
619 PIS(ERRESC2); 610 PIS(ERRESC3),
620 PIS(ERRESC3); 611 PIS(ERRCONTROL1),
621 PIS(ERRCONTROL1); 612 PIS(ERRCONTROL2),
622 PIS(ERRCONTROL2); 613 PIS(ERRCONTROL3),
623 PIS(ERRCONTROL3); 614 PIS(STATEULPS1),
624 PIS(STATEULPS1); 615 PIS(STATEULPS2),
625 PIS(STATEULPS2); 616 PIS(STATEULPS3),
626 PIS(STATEULPS3); 617 PIS(ERRCONTENTIONLP0_1),
627 PIS(ERRCONTENTIONLP0_1); 618 PIS(ERRCONTENTIONLP1_1),
628 PIS(ERRCONTENTIONLP1_1); 619 PIS(ERRCONTENTIONLP0_2),
629 PIS(ERRCONTENTIONLP0_2); 620 PIS(ERRCONTENTIONLP1_2),
630 PIS(ERRCONTENTIONLP1_2); 621 PIS(ERRCONTENTIONLP0_3),
631 PIS(ERRCONTENTIONLP0_3); 622 PIS(ERRCONTENTIONLP1_3),
632 PIS(ERRCONTENTIONLP1_3); 623 PIS(ULPSACTIVENOT_ALL0),
633 PIS(ULPSACTIVENOT_ALL0); 624 PIS(ULPSACTIVENOT_ALL1));
634 PIS(ULPSACTIVENOT_ALL1);
635#undef PIS 625#undef PIS
636
637 printk("\n");
638} 626}
639 627
640#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 628#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -1116,28 +1104,16 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
1116 } 1104 }
1117} 1105}
1118 1106
1119#ifdef DEBUG
1120static void _dsi_print_reset_status(struct platform_device *dsidev) 1107static void _dsi_print_reset_status(struct platform_device *dsidev)
1121{ 1108{
1122 u32 l; 1109 u32 l;
1123 int b0, b1, b2; 1110 int b0, b1, b2;
1124 1111
1125 if (!dss_debug)
1126 return;
1127
1128 /* A dummy read using the SCP interface to any DSIPHY register is 1112 /* A dummy read using the SCP interface to any DSIPHY register is
1129 * required after DSIPHY reset to complete the reset of the DSI complex 1113 * required after DSIPHY reset to complete the reset of the DSI complex
1130 * I/O. */ 1114 * I/O. */
1131 l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5); 1115 l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
1132 1116
1133 printk(KERN_DEBUG "DSI resets: ");
1134
1135 l = dsi_read_reg(dsidev, DSI_PLL_STATUS);
1136 printk("PLL (%d) ", FLD_GET(l, 0, 0));
1137
1138 l = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
1139 printk("CIO (%d) ", FLD_GET(l, 29, 29));
1140
1141 if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) { 1117 if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
1142 b0 = 28; 1118 b0 = 28;
1143 b1 = 27; 1119 b1 = 27;
@@ -1148,18 +1124,21 @@ static void _dsi_print_reset_status(struct platform_device *dsidev)
1148 b2 = 26; 1124 b2 = 26;
1149 } 1125 }
1150 1126
1151 l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5); 1127#define DSI_FLD_GET(fld, start, end)\
1152 printk("PHY (%x%x%x, %d, %d, %d)\n", 1128 FLD_GET(dsi_read_reg(dsidev, DSI_##fld), start, end)
1153 FLD_GET(l, b0, b0), 1129
1154 FLD_GET(l, b1, b1), 1130 pr_debug("DSI resets: PLL (%d) CIO (%d) PHY (%x%x%x, %d, %d, %d)\n",
1155 FLD_GET(l, b2, b2), 1131 DSI_FLD_GET(PLL_STATUS, 0, 0),
1156 FLD_GET(l, 29, 29), 1132 DSI_FLD_GET(COMPLEXIO_CFG1, 29, 29),
1157 FLD_GET(l, 30, 30), 1133 DSI_FLD_GET(DSIPHY_CFG5, b0, b0),
1158 FLD_GET(l, 31, 31)); 1134 DSI_FLD_GET(DSIPHY_CFG5, b1, b1),
1135 DSI_FLD_GET(DSIPHY_CFG5, b2, b2),
1136 DSI_FLD_GET(DSIPHY_CFG5, 29, 29),
1137 DSI_FLD_GET(DSIPHY_CFG5, 30, 30),
1138 DSI_FLD_GET(DSIPHY_CFG5, 31, 31));
1139
1140#undef DSI_FLD_GET
1159} 1141}
1160#else
1161#define _dsi_print_reset_status(x)
1162#endif
1163 1142
1164static inline int dsi_if_enable(struct platform_device *dsidev, bool enable) 1143static inline int dsi_if_enable(struct platform_device *dsidev, bool enable)
1165{ 1144{
@@ -1407,6 +1386,11 @@ retry:
1407 cur.dsi_pll_hsdiv_dispc_clk = 1386 cur.dsi_pll_hsdiv_dispc_clk =
1408 cur.clkin4ddr / cur.regm_dispc; 1387 cur.clkin4ddr / cur.regm_dispc;
1409 1388
1389 if (cur.regm_dispc > 1 &&
1390 cur.regm_dispc % 2 != 0 &&
1391 req_pck >= 1000000)
1392 continue;
1393
1410 /* this will narrow down the search a bit, 1394 /* this will narrow down the search a bit,
1411 * but still give pixclocks below what was 1395 * but still give pixclocks below what was
1412 * requested */ 1396 * requested */
@@ -1621,7 +1605,7 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
1621 u8 regn_start, regn_end, regm_start, regm_end; 1605 u8 regn_start, regn_end, regm_start, regm_end;
1622 u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end; 1606 u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
1623 1607
1624 DSSDBGF(); 1608 DSSDBG("DSI PLL clock config starts");
1625 1609
1626 dsi->current_cinfo.clkin = cinfo->clkin; 1610 dsi->current_cinfo.clkin = cinfo->clkin;
1627 dsi->current_cinfo.fint = cinfo->fint; 1611 dsi->current_cinfo.fint = cinfo->fint;
@@ -1757,11 +1741,21 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
1757 1741
1758 DSSDBG("PLL init\n"); 1742 DSSDBG("PLL init\n");
1759 1743
1744 /*
1745 * It seems that on many OMAPs we need to enable both to have a
1746 * functional HSDivider.
1747 */
1748 enable_hsclk = enable_hsdiv = true;
1749
1760 if (dsi->vdds_dsi_reg == NULL) { 1750 if (dsi->vdds_dsi_reg == NULL) {
1761 struct regulator *vdds_dsi; 1751 struct regulator *vdds_dsi;
1762 1752
1763 vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi"); 1753 vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
1764 1754
1755 /* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
1756 if (IS_ERR(vdds_dsi))
1757 vdds_dsi = regulator_get(&dsi->pdev->dev, "VCXIO");
1758
1765 if (IS_ERR(vdds_dsi)) { 1759 if (IS_ERR(vdds_dsi)) {
1766 DSSERR("can't get VDDS_DSI regulator\n"); 1760 DSSERR("can't get VDDS_DSI regulator\n");
1767 return PTR_ERR(vdds_dsi); 1761 return PTR_ERR(vdds_dsi);
@@ -2440,7 +2434,7 @@ static int dsi_cio_init(struct platform_device *dsidev)
2440 int r; 2434 int r;
2441 u32 l; 2435 u32 l;
2442 2436
2443 DSSDBGF(); 2437 DSSDBG("DSI CIO init starts");
2444 2438
2445 r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev)); 2439 r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
2446 if (r) 2440 if (r)
@@ -2791,7 +2785,7 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
2791{ 2785{
2792 u32 r; 2786 u32 r;
2793 2787
2794 DSSDBGF("%d", channel); 2788 DSSDBG("Initial config of virtual channel %d", channel);
2795 2789
2796 r = dsi_read_reg(dsidev, DSI_VC_CTRL(channel)); 2790 r = dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
2797 2791
@@ -2823,7 +2817,7 @@ static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
2823 if (dsi->vc[channel].source == source) 2817 if (dsi->vc[channel].source == source)
2824 return 0; 2818 return 0;
2825 2819
2826 DSSDBGF("%d", channel); 2820 DSSDBG("Source config of virtual channel %d", channel);
2827 2821
2828 dsi_sync_vc(dsidev, channel); 2822 dsi_sync_vc(dsidev, channel);
2829 2823
@@ -3581,7 +3575,7 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
3581 int r, i; 3575 int r, i;
3582 unsigned mask; 3576 unsigned mask;
3583 3577
3584 DSSDBGF(); 3578 DSSDBG("Entering ULPS");
3585 3579
3586 WARN_ON(!dsi_bus_is_locked(dsidev)); 3580 WARN_ON(!dsi_bus_is_locked(dsidev));
3587 3581
@@ -4285,7 +4279,7 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
4285 unsigned long pck; 4279 unsigned long pck;
4286 int r; 4280 int r;
4287 4281
4288 DSSDBGF("ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk); 4282 DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
4289 4283
4290 mutex_lock(&dsi->lock); 4284 mutex_lock(&dsi->lock);
4291 4285
@@ -4541,7 +4535,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
4541 dsi_handle_framedone(dsi->pdev, -ETIMEDOUT); 4535 dsi_handle_framedone(dsi->pdev, -ETIMEDOUT);
4542} 4536}
4543 4537
4544static void dsi_framedone_irq_callback(void *data, u32 mask) 4538static void dsi_framedone_irq_callback(void *data)
4545{ 4539{
4546 struct platform_device *dsidev = (struct platform_device *) data; 4540 struct platform_device *dsidev = (struct platform_device *) data;
4547 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4541 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -4615,7 +4609,6 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4615 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4609 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4616 struct omap_overlay_manager *mgr = dssdev->output->manager; 4610 struct omap_overlay_manager *mgr = dssdev->output->manager;
4617 int r; 4611 int r;
4618 u32 irq = 0;
4619 4612
4620 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) { 4613 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
4621 dsi->timings.hsw = 1; 4614 dsi->timings.hsw = 1;
@@ -4625,12 +4618,10 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4625 dsi->timings.vfp = 0; 4618 dsi->timings.vfp = 0;
4626 dsi->timings.vbp = 0; 4619 dsi->timings.vbp = 0;
4627 4620
4628 irq = dispc_mgr_get_framedone_irq(mgr->id); 4621 r = dss_mgr_register_framedone_handler(mgr,
4629 4622 dsi_framedone_irq_callback, dsidev);
4630 r = omap_dispc_register_isr(dsi_framedone_irq_callback,
4631 (void *) dsidev, irq);
4632 if (r) { 4623 if (r) {
4633 DSSERR("can't get FRAMEDONE irq\n"); 4624 DSSERR("can't register FRAMEDONE handler\n");
4634 goto err; 4625 goto err;
4635 } 4626 }
4636 4627
@@ -4668,8 +4659,8 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4668 return 0; 4659 return 0;
4669err1: 4660err1:
4670 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) 4661 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
4671 omap_dispc_unregister_isr(dsi_framedone_irq_callback, 4662 dss_mgr_unregister_framedone_handler(mgr,
4672 (void *) dsidev, irq); 4663 dsi_framedone_irq_callback, dsidev);
4673err: 4664err:
4674 return r; 4665 return r;
4675} 4666}
@@ -4680,14 +4671,9 @@ static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
4680 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4671 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4681 struct omap_overlay_manager *mgr = dssdev->output->manager; 4672 struct omap_overlay_manager *mgr = dssdev->output->manager;
4682 4673
4683 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) { 4674 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
4684 u32 irq; 4675 dss_mgr_unregister_framedone_handler(mgr,
4685 4676 dsi_framedone_irq_callback, dsidev);
4686 irq = dispc_mgr_get_framedone_irq(mgr->id);
4687
4688 omap_dispc_unregister_isr(dsi_framedone_irq_callback,
4689 (void *) dsidev, irq);
4690 }
4691} 4677}
4692 4678
4693static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) 4679static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
@@ -4730,7 +4716,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4730 if (r) 4716 if (r)
4731 goto err1; 4717 goto err1;
4732 4718
4733 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
4734 dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src); 4719 dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src);
4735 dss_select_lcd_clk_source(mgr->id, 4720 dss_select_lcd_clk_source(mgr->id,
4736 dssdev->clocks.dispc.channel.lcd_clk_src); 4721 dssdev->clocks.dispc.channel.lcd_clk_src);
@@ -4765,7 +4750,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4765err3: 4750err3:
4766 dsi_cio_uninit(dsidev); 4751 dsi_cio_uninit(dsidev);
4767err2: 4752err2:
4768 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
4769 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); 4753 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
4770 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); 4754 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
4771 4755
@@ -4792,7 +4776,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
4792 dsi_vc_enable(dsidev, 2, 0); 4776 dsi_vc_enable(dsidev, 2, 0);
4793 dsi_vc_enable(dsidev, 3, 0); 4777 dsi_vc_enable(dsidev, 3, 0);
4794 4778
4795 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
4796 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); 4779 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
4797 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); 4780 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
4798 dsi_cio_uninit(dsidev); 4781 dsi_cio_uninit(dsidev);
@@ -4981,6 +4964,10 @@ static int __init dsi_init_display(struct omap_dss_device *dssdev)
4981 4964
4982 vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi"); 4965 vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
4983 4966
4967 /* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
4968 if (IS_ERR(vdds_dsi))
4969 vdds_dsi = regulator_get(&dsi->pdev->dev, "VCXIO");
4970
4984 if (IS_ERR(vdds_dsi)) { 4971 if (IS_ERR(vdds_dsi)) {
4985 DSSERR("can't get VDDS_DSI regulator\n"); 4972 DSSERR("can't get VDDS_DSI regulator\n");
4986 return PTR_ERR(vdds_dsi); 4973 return PTR_ERR(vdds_dsi);
@@ -5121,7 +5108,7 @@ static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *p
5121{ 5108{
5122 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 5109 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
5123 struct dsi_data *dsi = dsi_get_dsidrv_data(pdev); 5110 struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
5124 const char *def_disp_name = dss_get_default_display_name(); 5111 const char *def_disp_name = omapdss_get_default_display_name();
5125 struct omap_dss_device *def_dssdev; 5112 struct omap_dss_device *def_dssdev;
5126 int i; 5113 int i;
5127 5114
@@ -5151,6 +5138,7 @@ static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *p
5151 5138
5152static void __init dsi_probe_pdata(struct platform_device *dsidev) 5139static void __init dsi_probe_pdata(struct platform_device *dsidev)
5153{ 5140{
5141 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5154 struct omap_dss_device *plat_dssdev; 5142 struct omap_dss_device *plat_dssdev;
5155 struct omap_dss_device *dssdev; 5143 struct omap_dss_device *dssdev;
5156 int r; 5144 int r;
@@ -5173,9 +5161,18 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)
5173 return; 5161 return;
5174 } 5162 }
5175 5163
5164 r = omapdss_output_set_device(&dsi->output, dssdev);
5165 if (r) {
5166 DSSERR("failed to connect output to new device: %s\n",
5167 dssdev->name);
5168 dss_put_device(dssdev);
5169 return;
5170 }
5171
5176 r = dss_add_device(dssdev); 5172 r = dss_add_device(dssdev);
5177 if (r) { 5173 if (r) {
5178 DSSERR("device %s register failed: %d\n", dssdev->name, r); 5174 DSSERR("device %s register failed: %d\n", dssdev->name, r);
5175 omapdss_output_unset_device(&dsi->output);
5179 dss_put_device(dssdev); 5176 dss_put_device(dssdev);
5180 return; 5177 return;
5181 } 5178 }
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 5f6eea801b06..054c2a22b3f1 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -32,11 +32,10 @@
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <linux/pm_runtime.h> 33#include <linux/pm_runtime.h>
34#include <linux/gfp.h> 34#include <linux/gfp.h>
35#include <linux/sizes.h>
35 36
36#include <video/omapdss.h> 37#include <video/omapdss.h>
37 38
38#include <plat/cpu.h>
39
40#include "dss.h" 39#include "dss.h"
41#include "dss_features.h" 40#include "dss_features.h"
42 41
@@ -78,6 +77,7 @@ static struct {
78 77
79 struct clk *dpll4_m4_ck; 78 struct clk *dpll4_m4_ck;
80 struct clk *dss_clk; 79 struct clk *dss_clk;
80 unsigned long dss_clk_rate;
81 81
82 unsigned long cache_req_pck; 82 unsigned long cache_req_pck;
83 unsigned long cache_prate; 83 unsigned long cache_prate;
@@ -98,6 +98,8 @@ static const char * const dss_generic_clk_source_names[] = {
98 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC", 98 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC",
99 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI", 99 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI",
100 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK", 100 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK",
101 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DSI_PLL2_HSDIV_DISPC",
102 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DSI_PLL2_HSDIV_DSI",
101}; 103};
102 104
103static inline void dss_write_reg(const struct dss_reg idx, u32 val) 105static inline void dss_write_reg(const struct dss_reg idx, u32 val)
@@ -153,6 +155,21 @@ static void dss_restore_context(void)
153#undef SR 155#undef SR
154#undef RR 156#undef RR
155 157
158int dss_get_ctx_loss_count(void)
159{
160 struct omap_dss_board_info *board_data = dss.pdev->dev.platform_data;
161 int cnt;
162
163 if (!board_data->get_context_loss_count)
164 return -ENOENT;
165
166 cnt = board_data->get_context_loss_count(&dss.pdev->dev);
167
168 WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
169
170 return cnt;
171}
172
156void dss_sdi_init(int datapairs) 173void dss_sdi_init(int datapairs)
157{ 174{
158 u32 l; 175 u32 l;
@@ -303,7 +320,7 @@ static void dss_dump_regs(struct seq_file *s)
303#undef DUMPREG 320#undef DUMPREG
304} 321}
305 322
306void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src) 323static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
307{ 324{
308 struct platform_device *dsidev; 325 struct platform_device *dsidev;
309 int b; 326 int b;
@@ -374,8 +391,10 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
374 struct platform_device *dsidev; 391 struct platform_device *dsidev;
375 int b, ix, pos; 392 int b, ix, pos;
376 393
377 if (!dss_has_feature(FEAT_LCD_CLK_SRC)) 394 if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
395 dss_select_dispc_clk_source(clk_src);
378 return; 396 return;
397 }
379 398
380 switch (clk_src) { 399 switch (clk_src) {
381 case OMAP_DSS_CLK_SRC_FCK: 400 case OMAP_DSS_CLK_SRC_FCK:
@@ -431,6 +450,29 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
431 } 450 }
432} 451}
433 452
453/* calculate clock rates using dividers in cinfo */
454int dss_calc_clock_rates(struct dss_clock_info *cinfo)
455{
456 if (dss.dpll4_m4_ck) {
457 unsigned long prate;
458
459 if (cinfo->fck_div > dss.feat->fck_div_max ||
460 cinfo->fck_div == 0)
461 return -EINVAL;
462
463 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
464
465 cinfo->fck = prate / cinfo->fck_div *
466 dss.feat->dss_fck_multiplier;
467 } else {
468 if (cinfo->fck_div != 0)
469 return -EINVAL;
470 cinfo->fck = clk_get_rate(dss.dss_clk);
471 }
472
473 return 0;
474}
475
434int dss_set_clock_div(struct dss_clock_info *cinfo) 476int dss_set_clock_div(struct dss_clock_info *cinfo)
435{ 477{
436 if (dss.dpll4_m4_ck) { 478 if (dss.dpll4_m4_ck) {
@@ -448,6 +490,10 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
448 return -EINVAL; 490 return -EINVAL;
449 } 491 }
450 492
493 dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
494
495 WARN_ONCE(dss.dss_clk_rate != cinfo->fck, "clk rate mismatch");
496
451 DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); 497 DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
452 498
453 return 0; 499 return 0;
@@ -461,6 +507,41 @@ unsigned long dss_get_dpll4_rate(void)
461 return 0; 507 return 0;
462} 508}
463 509
510unsigned long dss_get_dispc_clk_rate(void)
511{
512 return dss.dss_clk_rate;
513}
514
515static int dss_setup_default_clock(void)
516{
517 unsigned long max_dss_fck, prate;
518 unsigned fck_div;
519 struct dss_clock_info dss_cinfo = { 0 };
520 int r;
521
522 if (dss.dpll4_m4_ck == NULL)
523 return 0;
524
525 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
526
527 prate = dss_get_dpll4_rate();
528
529 fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
530 max_dss_fck);
531
532 dss_cinfo.fck_div = fck_div;
533
534 r = dss_calc_clock_rates(&dss_cinfo);
535 if (r)
536 return r;
537
538 r = dss_set_clock_div(&dss_cinfo);
539 if (r)
540 return r;
541
542 return 0;
543}
544
464int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo, 545int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
465 struct dispc_clock_info *dispc_cinfo) 546 struct dispc_clock_info *dispc_cinfo)
466{ 547{
@@ -750,7 +831,7 @@ static void dss_runtime_put(void)
750} 831}
751 832
752/* DEBUGFS */ 833/* DEBUGFS */
753#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) 834#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
754void dss_debug_dump_clocks(struct seq_file *s) 835void dss_debug_dump_clocks(struct seq_file *s)
755{ 836{
756 dss_dump_clocks(s); 837 dss_dump_clocks(s);
@@ -796,29 +877,45 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
796 .dpi_select_source = &dss_dpi_select_source_omap5, 877 .dpi_select_source = &dss_dpi_select_source_omap5,
797}; 878};
798 879
799static int __init dss_init_features(struct device *dev) 880static int __init dss_init_features(struct platform_device *pdev)
800{ 881{
801 const struct dss_features *src; 882 const struct dss_features *src;
802 struct dss_features *dst; 883 struct dss_features *dst;
803 884
804 dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL); 885 dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
805 if (!dst) { 886 if (!dst) {
806 dev_err(dev, "Failed to allocate local DSS Features\n"); 887 dev_err(&pdev->dev, "Failed to allocate local DSS Features\n");
807 return -ENOMEM; 888 return -ENOMEM;
808 } 889 }
809 890
810 if (cpu_is_omap24xx()) 891 switch (omapdss_get_version()) {
892 case OMAPDSS_VER_OMAP24xx:
811 src = &omap24xx_dss_feats; 893 src = &omap24xx_dss_feats;
812 else if (cpu_is_omap3630()) 894 break;
813 src = &omap3630_dss_feats; 895
814 else if (cpu_is_omap34xx()) 896 case OMAPDSS_VER_OMAP34xx_ES1:
897 case OMAPDSS_VER_OMAP34xx_ES3:
898 case OMAPDSS_VER_AM35xx:
815 src = &omap34xx_dss_feats; 899 src = &omap34xx_dss_feats;
816 else if (cpu_is_omap44xx()) 900 break;
901
902 case OMAPDSS_VER_OMAP3630:
903 src = &omap3630_dss_feats;
904 break;
905
906 case OMAPDSS_VER_OMAP4430_ES1:
907 case OMAPDSS_VER_OMAP4430_ES2:
908 case OMAPDSS_VER_OMAP4:
817 src = &omap44xx_dss_feats; 909 src = &omap44xx_dss_feats;
818 else if (soc_is_omap54xx()) 910 break;
911
912 case OMAPDSS_VER_OMAP5:
819 src = &omap54xx_dss_feats; 913 src = &omap54xx_dss_feats;
820 else 914 break;
915
916 default:
821 return -ENODEV; 917 return -ENODEV;
918 }
822 919
823 memcpy(dst, src, sizeof(*dst)); 920 memcpy(dst, src, sizeof(*dst));
824 dss.feat = dst; 921 dss.feat = dst;
@@ -835,7 +932,7 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
835 932
836 dss.pdev = pdev; 933 dss.pdev = pdev;
837 934
838 r = dss_init_features(&dss.pdev->dev); 935 r = dss_init_features(dss.pdev);
839 if (r) 936 if (r)
840 return r; 937 return r;
841 938
@@ -856,15 +953,23 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
856 if (r) 953 if (r)
857 return r; 954 return r;
858 955
956 r = dss_setup_default_clock();
957 if (r)
958 goto err_setup_clocks;
959
859 pm_runtime_enable(&pdev->dev); 960 pm_runtime_enable(&pdev->dev);
860 961
861 r = dss_runtime_get(); 962 r = dss_runtime_get();
862 if (r) 963 if (r)
863 goto err_runtime_get; 964 goto err_runtime_get;
864 965
966 dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
967
865 /* Select DPLL */ 968 /* Select DPLL */
866 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); 969 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
867 970
971 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
972
868#ifdef CONFIG_OMAP2_DSS_VENC 973#ifdef CONFIG_OMAP2_DSS_VENC
869 REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ 974 REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
870 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ 975 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
@@ -888,6 +993,7 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
888 993
889err_runtime_get: 994err_runtime_get:
890 pm_runtime_disable(&pdev->dev); 995 pm_runtime_disable(&pdev->dev);
996err_setup_clocks:
891 dss_put_clocks(); 997 dss_put_clocks();
892 return r; 998 return r;
893} 999}
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 6728892f9dad..610c8e563daa 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -23,44 +23,20 @@
23#ifndef __OMAP2_DSS_H 23#ifndef __OMAP2_DSS_H
24#define __OMAP2_DSS_H 24#define __OMAP2_DSS_H
25 25
26#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT 26#include <linux/interrupt.h>
27#define DEBUG
28#endif
29 27
30#ifdef DEBUG 28#ifdef pr_fmt
31extern bool dss_debug; 29#undef pr_fmt
32#ifdef DSS_SUBSYS_NAME
33#define DSSDBG(format, ...) \
34 if (dss_debug) \
35 printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \
36 ## __VA_ARGS__)
37#else
38#define DSSDBG(format, ...) \
39 if (dss_debug) \
40 printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__)
41#endif 30#endif
42 31
43#ifdef DSS_SUBSYS_NAME 32#ifdef DSS_SUBSYS_NAME
44#define DSSDBGF(format, ...) \ 33#define pr_fmt(fmt) DSS_SUBSYS_NAME ": " fmt
45 if (dss_debug) \
46 printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \
47 ": %s(" format ")\n", \
48 __func__, \
49 ## __VA_ARGS__)
50#else 34#else
51#define DSSDBGF(format, ...) \ 35#define pr_fmt(fmt) fmt
52 if (dss_debug) \
53 printk(KERN_DEBUG "omapdss: " \
54 ": %s(" format ")\n", \
55 __func__, \
56 ## __VA_ARGS__)
57#endif
58
59#else /* DEBUG */
60#define DSSDBG(format, ...)
61#define DSSDBGF(format, ...)
62#endif 36#endif
63 37
38#define DSSDBG(format, ...) \
39 pr_debug(format, ## __VA_ARGS__)
64 40
65#ifdef DSS_SUBSYS_NAME 41#ifdef DSS_SUBSYS_NAME
66#define DSSERR(format, ...) \ 42#define DSSERR(format, ...) \
@@ -186,11 +162,10 @@ struct seq_file;
186struct platform_device; 162struct platform_device;
187 163
188/* core */ 164/* core */
189const char *dss_get_default_display_name(void); 165struct platform_device *dss_get_core_pdev(void);
190struct bus_type *dss_get_bus(void); 166struct bus_type *dss_get_bus(void);
191struct regulator *dss_get_vdds_dsi(void); 167struct regulator *dss_get_vdds_dsi(void);
192struct regulator *dss_get_vdds_sdi(void); 168struct regulator *dss_get_vdds_sdi(void);
193int dss_get_ctx_loss_count(struct device *dev);
194int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask); 169int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask);
195void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask); 170void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
196int dss_set_min_bus_tput(struct device *dev, unsigned long tput); 171int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
@@ -204,55 +179,18 @@ void dss_put_device(struct omap_dss_device *dssdev);
204void dss_copy_device_pdata(struct omap_dss_device *dst, 179void dss_copy_device_pdata(struct omap_dss_device *dst,
205 const struct omap_dss_device *src); 180 const struct omap_dss_device *src);
206 181
207/* apply */
208void dss_apply_init(void);
209int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr);
210int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
211void dss_mgr_start_update(struct omap_overlay_manager *mgr);
212int omap_dss_mgr_apply(struct omap_overlay_manager *mgr);
213
214int dss_mgr_enable(struct omap_overlay_manager *mgr);
215void dss_mgr_disable(struct omap_overlay_manager *mgr);
216int dss_mgr_set_info(struct omap_overlay_manager *mgr,
217 struct omap_overlay_manager_info *info);
218void dss_mgr_get_info(struct omap_overlay_manager *mgr,
219 struct omap_overlay_manager_info *info);
220int dss_mgr_set_device(struct omap_overlay_manager *mgr,
221 struct omap_dss_device *dssdev);
222int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
223int dss_mgr_set_output(struct omap_overlay_manager *mgr,
224 struct omap_dss_output *output);
225int dss_mgr_unset_output(struct omap_overlay_manager *mgr);
226void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
227 const struct omap_video_timings *timings);
228void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
229 const struct dss_lcd_mgr_config *config);
230const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr);
231
232bool dss_ovl_is_enabled(struct omap_overlay *ovl);
233int dss_ovl_enable(struct omap_overlay *ovl);
234int dss_ovl_disable(struct omap_overlay *ovl);
235int dss_ovl_set_info(struct omap_overlay *ovl,
236 struct omap_overlay_info *info);
237void dss_ovl_get_info(struct omap_overlay *ovl,
238 struct omap_overlay_info *info);
239int dss_ovl_set_manager(struct omap_overlay *ovl,
240 struct omap_overlay_manager *mgr);
241int dss_ovl_unset_manager(struct omap_overlay *ovl);
242
243/* output */ 182/* output */
244void dss_register_output(struct omap_dss_output *out); 183void dss_register_output(struct omap_dss_output *out);
245void dss_unregister_output(struct omap_dss_output *out); 184void dss_unregister_output(struct omap_dss_output *out);
246struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev);
247 185
248/* display */ 186/* display */
249int dss_suspend_all_devices(void); 187int dss_suspend_all_devices(void);
250int dss_resume_all_devices(void); 188int dss_resume_all_devices(void);
251void dss_disable_all_devices(void); 189void dss_disable_all_devices(void);
252 190
253int dss_init_device(struct platform_device *pdev, 191int display_init_sysfs(struct platform_device *pdev,
254 struct omap_dss_device *dssdev); 192 struct omap_dss_device *dssdev);
255void dss_uninit_device(struct platform_device *pdev, 193void display_uninit_sysfs(struct platform_device *pdev,
256 struct omap_dss_device *dssdev); 194 struct omap_dss_device *dssdev);
257 195
258/* manager */ 196/* manager */
@@ -299,21 +237,23 @@ void dss_overlay_kobj_uninit(struct omap_overlay *ovl);
299int dss_init_platform_driver(void) __init; 237int dss_init_platform_driver(void) __init;
300void dss_uninit_platform_driver(void); 238void dss_uninit_platform_driver(void);
301 239
240unsigned long dss_get_dispc_clk_rate(void);
302int dss_dpi_select_source(enum omap_channel channel); 241int dss_dpi_select_source(enum omap_channel channel);
303void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); 242void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
304enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); 243enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
305const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); 244const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
306void dss_dump_clocks(struct seq_file *s); 245void dss_dump_clocks(struct seq_file *s);
307 246
308#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) 247#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
309void dss_debug_dump_clocks(struct seq_file *s); 248void dss_debug_dump_clocks(struct seq_file *s);
310#endif 249#endif
311 250
251int dss_get_ctx_loss_count(void);
252
312void dss_sdi_init(int datapairs); 253void dss_sdi_init(int datapairs);
313int dss_sdi_enable(void); 254int dss_sdi_enable(void);
314void dss_sdi_disable(void); 255void dss_sdi_disable(void);
315 256
316void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src);
317void dss_select_dsi_clk_source(int dsi_module, 257void dss_select_dsi_clk_source(int dsi_module,
318 enum omap_dss_clk_source clk_src); 258 enum omap_dss_clk_source clk_src);
319void dss_select_lcd_clk_source(enum omap_channel channel, 259void dss_select_lcd_clk_source(enum omap_channel channel,
@@ -326,6 +266,7 @@ void dss_set_venc_output(enum omap_dss_venc_type type);
326void dss_set_dac_pwrdn_bgz(bool enable); 266void dss_set_dac_pwrdn_bgz(bool enable);
327 267
328unsigned long dss_get_dpll4_rate(void); 268unsigned long dss_get_dpll4_rate(void);
269int dss_calc_clock_rates(struct dss_clock_info *cinfo);
329int dss_set_clock_div(struct dss_clock_info *cinfo); 270int dss_set_clock_div(struct dss_clock_info *cinfo);
330int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo, 271int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
331 struct dispc_clock_info *dispc_cinfo); 272 struct dispc_clock_info *dispc_cinfo);
@@ -413,8 +354,6 @@ static inline void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
413} 354}
414static inline struct platform_device *dsi_get_dsidev_from_id(int module) 355static inline struct platform_device *dsi_get_dsidev_from_id(int module)
415{ 356{
416 WARN("%s: DSI not compiled in, returning platform device as NULL\n",
417 __func__);
418 return NULL; 357 return NULL;
419} 358}
420#endif 359#endif
@@ -427,15 +366,10 @@ void dpi_uninit_platform_driver(void) __exit;
427int dispc_init_platform_driver(void) __init; 366int dispc_init_platform_driver(void) __init;
428void dispc_uninit_platform_driver(void) __exit; 367void dispc_uninit_platform_driver(void) __exit;
429void dispc_dump_clocks(struct seq_file *s); 368void dispc_dump_clocks(struct seq_file *s);
430void dispc_irq_handler(void);
431
432int dispc_runtime_get(void);
433void dispc_runtime_put(void);
434 369
435void dispc_enable_sidle(void); 370void dispc_enable_sidle(void);
436void dispc_disable_sidle(void); 371void dispc_disable_sidle(void);
437 372
438void dispc_lcd_enable_signal_polarity(bool act_high);
439void dispc_lcd_enable_signal(bool enable); 373void dispc_lcd_enable_signal(bool enable);
440void dispc_pck_free_enable(bool enable); 374void dispc_pck_free_enable(bool enable);
441void dispc_enable_fifomerge(bool enable); 375void dispc_enable_fifomerge(bool enable);
@@ -455,36 +389,14 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
455void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, 389void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
456 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, 390 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
457 bool manual_update); 391 bool manual_update);
458int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, 392
459 bool replication, const struct omap_video_timings *mgr_timings,
460 bool mem_to_mem);
461int dispc_ovl_enable(enum omap_plane plane, bool enable);
462void dispc_ovl_set_channel_out(enum omap_plane plane,
463 enum omap_channel channel);
464
465void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable);
466u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
467u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
468bool dispc_mgr_go_busy(enum omap_channel channel);
469void dispc_mgr_go(enum omap_channel channel);
470bool dispc_mgr_is_enabled(enum omap_channel channel);
471void dispc_mgr_enable(enum omap_channel channel, bool enable);
472bool dispc_mgr_is_channel_enabled(enum omap_channel channel);
473void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode);
474void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable);
475void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
476void dispc_mgr_set_lcd_type_tft(enum omap_channel channel);
477void dispc_mgr_set_timings(enum omap_channel channel,
478 struct omap_video_timings *timings);
479unsigned long dispc_mgr_lclk_rate(enum omap_channel channel); 393unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
480unsigned long dispc_mgr_pclk_rate(enum omap_channel channel); 394unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
481unsigned long dispc_core_clk_rate(void); 395unsigned long dispc_core_clk_rate(void);
482void dispc_mgr_set_clock_div(enum omap_channel channel, 396void dispc_mgr_set_clock_div(enum omap_channel channel,
483 struct dispc_clock_info *cinfo); 397 const struct dispc_clock_info *cinfo);
484int dispc_mgr_get_clock_div(enum omap_channel channel, 398int dispc_mgr_get_clock_div(enum omap_channel channel,
485 struct dispc_clock_info *cinfo); 399 struct dispc_clock_info *cinfo);
486void dispc_mgr_setup(enum omap_channel channel,
487 struct omap_overlay_manager_info *info);
488 400
489u32 dispc_wb_get_framedone_irq(void); 401u32 dispc_wb_get_framedone_irq(void);
490bool dispc_wb_go_busy(void); 402bool dispc_wb_go_busy(void);
@@ -536,6 +448,8 @@ static inline unsigned long hdmi_get_pixel_clock(void)
536#endif 448#endif
537int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); 449int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
538void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); 450void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
451int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev);
452void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev);
539void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev, 453void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
540 struct omap_video_timings *timings); 454 struct omap_video_timings *timings);
541int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, 455int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index acbc1e1efba3..18688c12e30d 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -18,12 +18,12 @@
18 */ 18 */
19 19
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <linux/module.h>
21#include <linux/types.h> 22#include <linux/types.h>
22#include <linux/err.h> 23#include <linux/err.h>
23#include <linux/slab.h> 24#include <linux/slab.h>
24 25
25#include <video/omapdss.h> 26#include <video/omapdss.h>
26#include <plat/cpu.h>
27 27
28#include "dss.h" 28#include "dss.h"
29#include "dss_features.h" 29#include "dss_features.h"
@@ -430,8 +430,6 @@ static const struct dss_param_range omap2_dss_param_range[] = {
430 * scaler cannot scale a image with width more than 768. 430 * scaler cannot scale a image with width more than 768.
431 */ 431 */
432 [FEAT_PARAM_LINEWIDTH] = { 1, 768 }, 432 [FEAT_PARAM_LINEWIDTH] = { 1, 768 },
433 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
434 [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
435}; 433};
436 434
437static const struct dss_param_range omap3_dss_param_range[] = { 435static const struct dss_param_range omap3_dss_param_range[] = {
@@ -446,8 +444,6 @@ static const struct dss_param_range omap3_dss_param_range[] = {
446 [FEAT_PARAM_DSI_FCK] = { 0, 173000000 }, 444 [FEAT_PARAM_DSI_FCK] = { 0, 173000000 },
447 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 445 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
448 [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, 446 [FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
449 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
450 [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
451}; 447};
452 448
453static const struct dss_param_range omap4_dss_param_range[] = { 449static const struct dss_param_range omap4_dss_param_range[] = {
@@ -462,8 +458,6 @@ static const struct dss_param_range omap4_dss_param_range[] = {
462 [FEAT_PARAM_DSI_FCK] = { 0, 170000000 }, 458 [FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
463 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 459 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
464 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, 460 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
465 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
466 [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
467}; 461};
468 462
469static const struct dss_param_range omap5_dss_param_range[] = { 463static const struct dss_param_range omap5_dss_param_range[] = {
@@ -478,8 +472,6 @@ static const struct dss_param_range omap5_dss_param_range[] = {
478 [FEAT_PARAM_DSI_FCK] = { 0, 170000000 }, 472 [FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
479 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 473 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
480 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, 474 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
481 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
482 [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
483}; 475};
484 476
485static const enum dss_feat_id omap2_dss_feat_list[] = { 477static const enum dss_feat_id omap2_dss_feat_list[] = {
@@ -821,14 +813,25 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
821 .audio_start = ti_hdmi_4xxx_audio_start, 813 .audio_start = ti_hdmi_4xxx_audio_start,
822 .audio_stop = ti_hdmi_4xxx_audio_stop, 814 .audio_stop = ti_hdmi_4xxx_audio_stop,
823 .audio_config = ti_hdmi_4xxx_audio_config, 815 .audio_config = ti_hdmi_4xxx_audio_config,
816 .audio_get_dma_port = ti_hdmi_4xxx_audio_get_dma_port,
824#endif 817#endif
825 818
826}; 819};
827 820
828void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data) 821void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data,
822 enum omapdss_version version)
829{ 823{
830 if (cpu_is_omap44xx()) 824 switch (version) {
825 case OMAPDSS_VER_OMAP4430_ES1:
826 case OMAPDSS_VER_OMAP4430_ES2:
827 case OMAPDSS_VER_OMAP4:
831 ip_data->ops = &omap4_hdmi_functions; 828 ip_data->ops = &omap4_hdmi_functions;
829 break;
830 default:
831 ip_data->ops = NULL;
832 }
833
834 WARN_ON(ip_data->ops == NULL);
832} 835}
833#endif 836#endif
834 837
@@ -837,11 +840,13 @@ int dss_feat_get_num_mgrs(void)
837{ 840{
838 return omap_current_dss_features->num_mgrs; 841 return omap_current_dss_features->num_mgrs;
839} 842}
843EXPORT_SYMBOL(dss_feat_get_num_mgrs);
840 844
841int dss_feat_get_num_ovls(void) 845int dss_feat_get_num_ovls(void)
842{ 846{
843 return omap_current_dss_features->num_ovls; 847 return omap_current_dss_features->num_ovls;
844} 848}
849EXPORT_SYMBOL(dss_feat_get_num_ovls);
845 850
846int dss_feat_get_num_wbs(void) 851int dss_feat_get_num_wbs(void)
847{ 852{
@@ -862,16 +867,19 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel
862{ 867{
863 return omap_current_dss_features->supported_displays[channel]; 868 return omap_current_dss_features->supported_displays[channel];
864} 869}
870EXPORT_SYMBOL(dss_feat_get_supported_displays);
865 871
866enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel) 872enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
867{ 873{
868 return omap_current_dss_features->supported_outputs[channel]; 874 return omap_current_dss_features->supported_outputs[channel];
869} 875}
876EXPORT_SYMBOL(dss_feat_get_supported_outputs);
870 877
871enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane) 878enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
872{ 879{
873 return omap_current_dss_features->supported_color_modes[plane]; 880 return omap_current_dss_features->supported_color_modes[plane];
874} 881}
882EXPORT_SYMBOL(dss_feat_get_supported_color_modes);
875 883
876enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane) 884enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane)
877{ 885{
@@ -929,29 +937,44 @@ bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type)
929 return omap_current_dss_features->supported_rotation_types & rot_type; 937 return omap_current_dss_features->supported_rotation_types & rot_type;
930} 938}
931 939
932void dss_features_init(void) 940void dss_features_init(enum omapdss_version version)
933{ 941{
934 if (cpu_is_omap24xx()) 942 switch (version) {
943 case OMAPDSS_VER_OMAP24xx:
935 omap_current_dss_features = &omap2_dss_features; 944 omap_current_dss_features = &omap2_dss_features;
936 else if (cpu_is_omap3630()) 945 break;
946
947 case OMAPDSS_VER_OMAP34xx_ES1:
948 case OMAPDSS_VER_OMAP34xx_ES3:
949 omap_current_dss_features = &omap3430_dss_features;
950 break;
951
952 case OMAPDSS_VER_OMAP3630:
937 omap_current_dss_features = &omap3630_dss_features; 953 omap_current_dss_features = &omap3630_dss_features;
938 else if (cpu_is_omap34xx()) { 954 break;
939 if (soc_is_am35xx()) { 955
940 omap_current_dss_features = &am35xx_dss_features; 956 case OMAPDSS_VER_OMAP4430_ES1:
941 } else {
942 omap_current_dss_features = &omap3430_dss_features;
943 }
944 }
945 else if (omap_rev() == OMAP4430_REV_ES1_0)
946 omap_current_dss_features = &omap4430_es1_0_dss_features; 957 omap_current_dss_features = &omap4430_es1_0_dss_features;
947 else if (omap_rev() == OMAP4430_REV_ES2_0 || 958 break;
948 omap_rev() == OMAP4430_REV_ES2_1 || 959
949 omap_rev() == OMAP4430_REV_ES2_2) 960 case OMAPDSS_VER_OMAP4430_ES2:
950 omap_current_dss_features = &omap4430_es2_0_1_2_dss_features; 961 omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
951 else if (cpu_is_omap44xx()) 962 break;
963
964 case OMAPDSS_VER_OMAP4:
952 omap_current_dss_features = &omap4_dss_features; 965 omap_current_dss_features = &omap4_dss_features;
953 else if (soc_is_omap54xx()) 966 break;
967
968 case OMAPDSS_VER_OMAP5:
954 omap_current_dss_features = &omap5_dss_features; 969 omap_current_dss_features = &omap5_dss_features;
955 else 970 break;
971
972 case OMAPDSS_VER_AM35xx:
973 omap_current_dss_features = &am35xx_dss_features;
974 break;
975
976 default:
956 DSSWARN("Unsupported OMAP version"); 977 DSSWARN("Unsupported OMAP version");
978 break;
979 }
957} 980}
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 9218113b5e88..489b9bec4a6d 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -98,19 +98,12 @@ enum dss_range_param {
98 FEAT_PARAM_DSI_FCK, 98 FEAT_PARAM_DSI_FCK,
99 FEAT_PARAM_DOWNSCALE, 99 FEAT_PARAM_DOWNSCALE,
100 FEAT_PARAM_LINEWIDTH, 100 FEAT_PARAM_LINEWIDTH,
101 FEAT_PARAM_MGR_WIDTH,
102 FEAT_PARAM_MGR_HEIGHT,
103}; 101};
104 102
105/* DSS Feature Functions */ 103/* DSS Feature Functions */
106int dss_feat_get_num_mgrs(void);
107int dss_feat_get_num_ovls(void);
108int dss_feat_get_num_wbs(void); 104int dss_feat_get_num_wbs(void);
109unsigned long dss_feat_get_param_min(enum dss_range_param param); 105unsigned long dss_feat_get_param_min(enum dss_range_param param);
110unsigned long dss_feat_get_param_max(enum dss_range_param param); 106unsigned long dss_feat_get_param_max(enum dss_range_param param);
111enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
112enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel);
113enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
114enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane); 107enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
115bool dss_feat_color_mode_supported(enum omap_plane plane, 108bool dss_feat_color_mode_supported(enum omap_plane plane,
116 enum omap_color_mode color_mode); 109 enum omap_color_mode color_mode);
@@ -123,8 +116,9 @@ bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type);
123 116
124bool dss_has_feature(enum dss_feat_id id); 117bool dss_has_feature(enum dss_feat_id id);
125void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); 118void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
126void dss_features_init(void); 119void dss_features_init(enum omapdss_version version);
127#if defined(CONFIG_OMAP4_DSS_HDMI) 120#if defined(CONFIG_OMAP4_DSS_HDMI)
128void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data); 121void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data,
122 enum omapdss_version version);
129#endif 123#endif
130#endif 124#endif
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 8c9b8b3b7f77..769d0828581c 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -60,6 +60,7 @@
60static struct { 60static struct {
61 struct mutex lock; 61 struct mutex lock;
62 struct platform_device *pdev; 62 struct platform_device *pdev;
63
63 struct hdmi_ip_data ip_data; 64 struct hdmi_ip_data ip_data;
64 65
65 struct clk *sys_clk; 66 struct clk *sys_clk;
@@ -295,6 +296,12 @@ static const struct hdmi_config vesa_timings[] = {
295 false, }, 296 false, },
296 { 0x55, HDMI_DVI }, 297 { 0x55, HDMI_DVI },
297 }, 298 },
299 {
300 { 1920, 1200, 154000, 32, 48, 80, 6, 3, 26,
301 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
302 false, },
303 { 0x44, HDMI_DVI },
304 },
298}; 305};
299 306
300static int hdmi_runtime_get(void) 307static int hdmi_runtime_get(void)
@@ -333,13 +340,17 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev)
333 340
334 DSSDBG("init_display\n"); 341 DSSDBG("init_display\n");
335 342
336 dss_init_hdmi_ip_ops(&hdmi.ip_data); 343 dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version());
337 344
338 if (hdmi.vdda_hdmi_dac_reg == NULL) { 345 if (hdmi.vdda_hdmi_dac_reg == NULL) {
339 struct regulator *reg; 346 struct regulator *reg;
340 347
341 reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac"); 348 reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
342 349
350 /* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */
351 if (IS_ERR(reg))
352 reg = devm_regulator_get(&hdmi.pdev->dev, "VDAC");
353
343 if (IS_ERR(reg)) { 354 if (IS_ERR(reg)) {
344 DSSERR("can't get VDDA_HDMI_DAC regulator\n"); 355 DSSERR("can't get VDDA_HDMI_DAC regulator\n");
345 return PTR_ERR(reg); 356 return PTR_ERR(reg);
@@ -355,7 +366,7 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev)
355 return 0; 366 return 0;
356} 367}
357 368
358static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev) 369static void hdmi_uninit_display(struct omap_dss_device *dssdev)
359{ 370{
360 DSSDBG("uninit_display\n"); 371 DSSDBG("uninit_display\n");
361 372
@@ -398,7 +409,8 @@ static bool hdmi_timings_compare(struct omap_video_timings *timing1,
398{ 409{
399 int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync; 410 int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
400 411
401 if ((timing2->pixel_clock == timing1->pixel_clock) && 412 if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) ==
413 DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) &&
402 (timing2->x_res == timing1->x_res) && 414 (timing2->x_res == timing1->x_res) &&
403 (timing2->y_res == timing1->y_res)) { 415 (timing2->y_res == timing1->y_res)) {
404 416
@@ -500,12 +512,9 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
500 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); 512 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
501} 513}
502 514
503static int hdmi_power_on(struct omap_dss_device *dssdev) 515static int hdmi_power_on_core(struct omap_dss_device *dssdev)
504{ 516{
505 int r; 517 int r;
506 struct omap_video_timings *p;
507 struct omap_overlay_manager *mgr = dssdev->output->manager;
508 unsigned long phy;
509 518
510 gpio_set_value(hdmi.ct_cp_hpd_gpio, 1); 519 gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
511 gpio_set_value(hdmi.ls_oe_gpio, 1); 520 gpio_set_value(hdmi.ls_oe_gpio, 1);
@@ -521,6 +530,38 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
521 if (r) 530 if (r)
522 goto err_runtime_get; 531 goto err_runtime_get;
523 532
533 /* Make selection of HDMI in DSS */
534 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
535
536 return 0;
537
538err_runtime_get:
539 regulator_disable(hdmi.vdda_hdmi_dac_reg);
540err_vdac_enable:
541 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
542 gpio_set_value(hdmi.ls_oe_gpio, 0);
543 return r;
544}
545
546static void hdmi_power_off_core(struct omap_dss_device *dssdev)
547{
548 hdmi_runtime_put();
549 regulator_disable(hdmi.vdda_hdmi_dac_reg);
550 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
551 gpio_set_value(hdmi.ls_oe_gpio, 0);
552}
553
554static int hdmi_power_on_full(struct omap_dss_device *dssdev)
555{
556 int r;
557 struct omap_video_timings *p;
558 struct omap_overlay_manager *mgr = dssdev->output->manager;
559 unsigned long phy;
560
561 r = hdmi_power_on_core(dssdev);
562 if (r)
563 return r;
564
524 dss_mgr_disable(mgr); 565 dss_mgr_disable(mgr);
525 566
526 p = &hdmi.ip_data.cfg.timings; 567 p = &hdmi.ip_data.cfg.timings;
@@ -548,17 +589,6 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
548 589
549 hdmi.ip_data.ops->video_configure(&hdmi.ip_data); 590 hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
550 591
551 /* Make selection of HDMI in DSS */
552 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
553
554 /* Select the dispc clock source as PRCM clock, to ensure that it is not
555 * DSI PLL source as the clock selected by DSI PLL might not be
556 * sufficient for the resolution selected / that can be changed
557 * dynamically by user. This can be moved to single location , say
558 * Boardfile.
559 */
560 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
561
562 /* bypass TV gamma table */ 592 /* bypass TV gamma table */
563 dispc_enable_gamma_table(0); 593 dispc_enable_gamma_table(0);
564 594
@@ -582,16 +612,11 @@ err_vid_enable:
582err_phy_enable: 612err_phy_enable:
583 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 613 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
584err_pll_enable: 614err_pll_enable:
585 hdmi_runtime_put(); 615 hdmi_power_off_core(dssdev);
586err_runtime_get:
587 regulator_disable(hdmi.vdda_hdmi_dac_reg);
588err_vdac_enable:
589 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
590 gpio_set_value(hdmi.ls_oe_gpio, 0);
591 return -EIO; 616 return -EIO;
592} 617}
593 618
594static void hdmi_power_off(struct omap_dss_device *dssdev) 619static void hdmi_power_off_full(struct omap_dss_device *dssdev)
595{ 620{
596 struct omap_overlay_manager *mgr = dssdev->output->manager; 621 struct omap_overlay_manager *mgr = dssdev->output->manager;
597 622
@@ -600,12 +625,8 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
600 hdmi.ip_data.ops->video_disable(&hdmi.ip_data); 625 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
601 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); 626 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
602 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 627 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
603 hdmi_runtime_put();
604
605 regulator_disable(hdmi.vdda_hdmi_dac_reg);
606 628
607 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0); 629 hdmi_power_off_core(dssdev);
608 gpio_set_value(hdmi.ls_oe_gpio, 0);
609} 630}
610 631
611int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, 632int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -715,7 +736,7 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
715 goto err0; 736 goto err0;
716 } 737 }
717 738
718 r = hdmi_power_on(dssdev); 739 r = hdmi_power_on_full(dssdev);
719 if (r) { 740 if (r) {
720 DSSERR("failed to power on device\n"); 741 DSSERR("failed to power on device\n");
721 goto err1; 742 goto err1;
@@ -737,13 +758,48 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
737 758
738 mutex_lock(&hdmi.lock); 759 mutex_lock(&hdmi.lock);
739 760
740 hdmi_power_off(dssdev); 761 hdmi_power_off_full(dssdev);
741 762
742 omap_dss_stop_device(dssdev); 763 omap_dss_stop_device(dssdev);
743 764
744 mutex_unlock(&hdmi.lock); 765 mutex_unlock(&hdmi.lock);
745} 766}
746 767
768int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev)
769{
770 int r = 0;
771
772 DSSDBG("ENTER omapdss_hdmi_core_enable\n");
773
774 mutex_lock(&hdmi.lock);
775
776 hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
777
778 r = hdmi_power_on_core(dssdev);
779 if (r) {
780 DSSERR("failed to power on device\n");
781 goto err0;
782 }
783
784 mutex_unlock(&hdmi.lock);
785 return 0;
786
787err0:
788 mutex_unlock(&hdmi.lock);
789 return r;
790}
791
792void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev)
793{
794 DSSDBG("Enter omapdss_hdmi_core_disable\n");
795
796 mutex_lock(&hdmi.lock);
797
798 hdmi_power_off_core(dssdev);
799
800 mutex_unlock(&hdmi.lock);
801}
802
747static int hdmi_get_clocks(struct platform_device *pdev) 803static int hdmi_get_clocks(struct platform_device *pdev)
748{ 804{
749 struct clk *clk; 805 struct clk *clk;
@@ -912,7 +968,7 @@ int hdmi_audio_config(struct omap_dss_audio *audio)
912static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev) 968static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
913{ 969{
914 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 970 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
915 const char *def_disp_name = dss_get_default_display_name(); 971 const char *def_disp_name = omapdss_get_default_display_name();
916 struct omap_dss_device *def_dssdev; 972 struct omap_dss_device *def_dssdev;
917 int i; 973 int i;
918 974
@@ -970,9 +1026,19 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
970 return; 1026 return;
971 } 1027 }
972 1028
1029 r = omapdss_output_set_device(&hdmi.output, dssdev);
1030 if (r) {
1031 DSSERR("failed to connect output to new device: %s\n",
1032 dssdev->name);
1033 dss_put_device(dssdev);
1034 return;
1035 }
1036
973 r = dss_add_device(dssdev); 1037 r = dss_add_device(dssdev);
974 if (r) { 1038 if (r) {
975 DSSERR("device %s register failed: %d\n", dssdev->name, r); 1039 DSSERR("device %s register failed: %d\n", dssdev->name, r);
1040 omapdss_output_unset_device(&hdmi.output);
1041 hdmi_uninit_display(dssdev);
976 dss_put_device(dssdev); 1042 dss_put_device(dssdev);
977 return; 1043 return;
978 } 1044 }
@@ -999,22 +1065,22 @@ static void __exit hdmi_uninit_output(struct platform_device *pdev)
999/* HDMI HW IP initialisation */ 1065/* HDMI HW IP initialisation */
1000static int __init omapdss_hdmihw_probe(struct platform_device *pdev) 1066static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
1001{ 1067{
1002 struct resource *hdmi_mem; 1068 struct resource *res;
1003 int r; 1069 int r;
1004 1070
1005 hdmi.pdev = pdev; 1071 hdmi.pdev = pdev;
1006 1072
1007 mutex_init(&hdmi.lock); 1073 mutex_init(&hdmi.lock);
1074 mutex_init(&hdmi.ip_data.lock);
1008 1075
1009 hdmi_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0); 1076 res = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
1010 if (!hdmi_mem) { 1077 if (!res) {
1011 DSSERR("can't get IORESOURCE_MEM HDMI\n"); 1078 DSSERR("can't get IORESOURCE_MEM HDMI\n");
1012 return -EINVAL; 1079 return -EINVAL;
1013 } 1080 }
1014 1081
1015 /* Base address taken from platform */ 1082 /* Base address taken from platform */
1016 hdmi.ip_data.base_wp = ioremap(hdmi_mem->start, 1083 hdmi.ip_data.base_wp = devm_request_and_ioremap(&pdev->dev, res);
1017 resource_size(hdmi_mem));
1018 if (!hdmi.ip_data.base_wp) { 1084 if (!hdmi.ip_data.base_wp) {
1019 DSSERR("can't ioremap WP\n"); 1085 DSSERR("can't ioremap WP\n");
1020 return -ENOMEM; 1086 return -ENOMEM;
@@ -1022,7 +1088,7 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
1022 1088
1023 r = hdmi_get_clocks(pdev); 1089 r = hdmi_get_clocks(pdev);
1024 if (r) { 1090 if (r) {
1025 iounmap(hdmi.ip_data.base_wp); 1091 DSSERR("can't get clocks\n");
1026 return r; 1092 return r;
1027 } 1093 }
1028 1094
@@ -1033,9 +1099,11 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
1033 hdmi.ip_data.pll_offset = HDMI_PLLCTRL; 1099 hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
1034 hdmi.ip_data.phy_offset = HDMI_PHY; 1100 hdmi.ip_data.phy_offset = HDMI_PHY;
1035 1101
1036 mutex_init(&hdmi.ip_data.lock); 1102 r = hdmi_panel_init();
1037 1103 if (r) {
1038 hdmi_panel_init(); 1104 DSSERR("can't init panel\n");
1105 goto err_panel_init;
1106 }
1039 1107
1040 dss_debugfs_create_file("hdmi", hdmi_dump_regs); 1108 dss_debugfs_create_file("hdmi", hdmi_dump_regs);
1041 1109
@@ -1044,6 +1112,10 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
1044 hdmi_probe_pdata(pdev); 1112 hdmi_probe_pdata(pdev);
1045 1113
1046 return 0; 1114 return 0;
1115
1116err_panel_init:
1117 hdmi_put_clocks();
1118 return r;
1047} 1119}
1048 1120
1049static int __exit hdmi_remove_child(struct device *dev, void *data) 1121static int __exit hdmi_remove_child(struct device *dev, void *data)
@@ -1067,8 +1139,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
1067 1139
1068 hdmi_put_clocks(); 1140 hdmi_put_clocks();
1069 1141
1070 iounmap(hdmi.ip_data.base_wp);
1071
1072 return 0; 1142 return 0;
1073} 1143}
1074 1144
diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
index 69fb115bab32..dfb8eda81b61 100644
--- a/drivers/video/omap2/dss/hdmi_panel.c
+++ b/drivers/video/omap2/dss/hdmi_panel.c
@@ -280,58 +280,6 @@ static void hdmi_panel_disable(struct omap_dss_device *dssdev)
280 mutex_unlock(&hdmi.lock); 280 mutex_unlock(&hdmi.lock);
281} 281}
282 282
283static int hdmi_panel_suspend(struct omap_dss_device *dssdev)
284{
285 int r = 0;
286
287 mutex_lock(&hdmi.lock);
288
289 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
290 r = -EINVAL;
291 goto err;
292 }
293
294 /*
295 * TODO: notify audio users that the display was suspended. For now,
296 * disable audio locally to not break our audio state machine.
297 */
298 hdmi_panel_audio_disable(dssdev);
299
300 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
301 omapdss_hdmi_display_disable(dssdev);
302
303err:
304 mutex_unlock(&hdmi.lock);
305
306 return r;
307}
308
309static int hdmi_panel_resume(struct omap_dss_device *dssdev)
310{
311 int r = 0;
312
313 mutex_lock(&hdmi.lock);
314
315 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
316 r = -EINVAL;
317 goto err;
318 }
319
320 r = omapdss_hdmi_display_enable(dssdev);
321 if (r) {
322 DSSERR("failed to power on\n");
323 goto err;
324 }
325 /* TODO: notify audio users that the panel resumed. */
326
327 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
328
329err:
330 mutex_unlock(&hdmi.lock);
331
332 return r;
333}
334
335static void hdmi_get_timings(struct omap_dss_device *dssdev, 283static void hdmi_get_timings(struct omap_dss_device *dssdev,
336 struct omap_video_timings *timings) 284 struct omap_video_timings *timings)
337{ 285{
@@ -379,20 +327,22 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,
379static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len) 327static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
380{ 328{
381 int r; 329 int r;
330 bool need_enable;
382 331
383 mutex_lock(&hdmi.lock); 332 mutex_lock(&hdmi.lock);
384 333
385 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { 334 need_enable = dssdev->state == OMAP_DSS_DISPLAY_DISABLED;
386 r = omapdss_hdmi_display_enable(dssdev); 335
336 if (need_enable) {
337 r = omapdss_hdmi_core_enable(dssdev);
387 if (r) 338 if (r)
388 goto err; 339 goto err;
389 } 340 }
390 341
391 r = omapdss_hdmi_read_edid(buf, len); 342 r = omapdss_hdmi_read_edid(buf, len);
392 343
393 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED || 344 if (need_enable)
394 dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) 345 omapdss_hdmi_core_disable(dssdev);
395 omapdss_hdmi_display_disable(dssdev);
396err: 346err:
397 mutex_unlock(&hdmi.lock); 347 mutex_unlock(&hdmi.lock);
398 348
@@ -402,20 +352,22 @@ err:
402static bool hdmi_detect(struct omap_dss_device *dssdev) 352static bool hdmi_detect(struct omap_dss_device *dssdev)
403{ 353{
404 int r; 354 int r;
355 bool need_enable;
405 356
406 mutex_lock(&hdmi.lock); 357 mutex_lock(&hdmi.lock);
407 358
408 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { 359 need_enable = dssdev->state == OMAP_DSS_DISPLAY_DISABLED;
409 r = omapdss_hdmi_display_enable(dssdev); 360
361 if (need_enable) {
362 r = omapdss_hdmi_core_enable(dssdev);
410 if (r) 363 if (r)
411 goto err; 364 goto err;
412 } 365 }
413 366
414 r = omapdss_hdmi_detect(); 367 r = omapdss_hdmi_detect();
415 368
416 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED || 369 if (need_enable)
417 dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) 370 omapdss_hdmi_core_disable(dssdev);
418 omapdss_hdmi_display_disable(dssdev);
419err: 371err:
420 mutex_unlock(&hdmi.lock); 372 mutex_unlock(&hdmi.lock);
421 373
@@ -427,8 +379,6 @@ static struct omap_dss_driver hdmi_driver = {
427 .remove = hdmi_panel_remove, 379 .remove = hdmi_panel_remove,
428 .enable = hdmi_panel_enable, 380 .enable = hdmi_panel_enable,
429 .disable = hdmi_panel_disable, 381 .disable = hdmi_panel_disable,
430 .suspend = hdmi_panel_suspend,
431 .resume = hdmi_panel_resume,
432 .get_timings = hdmi_get_timings, 382 .get_timings = hdmi_get_timings,
433 .set_timings = hdmi_set_timings, 383 .set_timings = hdmi_set_timings,
434 .check_timings = hdmi_check_timings, 384 .check_timings = hdmi_check_timings,
@@ -454,9 +404,7 @@ int hdmi_panel_init(void)
454 spin_lock_init(&hdmi.audio_lock); 404 spin_lock_init(&hdmi.audio_lock);
455#endif 405#endif
456 406
457 omap_dss_register_driver(&hdmi_driver); 407 return omap_dss_register_driver(&hdmi_driver);
458
459 return 0;
460} 408}
461 409
462void hdmi_panel_exit(void) 410void hdmi_panel_exit(void)
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index c54d2f620ce3..2551eaa14c42 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -36,36 +36,6 @@
36static int num_managers; 36static int num_managers;
37static struct omap_overlay_manager *managers; 37static struct omap_overlay_manager *managers;
38 38
39static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
40{
41 return mgr->output ? mgr->output->device : NULL;
42}
43
44static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
45{
46 unsigned long timeout = msecs_to_jiffies(500);
47 struct omap_dss_device *dssdev = mgr->get_device(mgr);
48 u32 irq;
49 int r;
50
51 r = dispc_runtime_get();
52 if (r)
53 return r;
54
55 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
56 irq = DISPC_IRQ_EVSYNC_ODD;
57 else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
58 irq = DISPC_IRQ_EVSYNC_EVEN;
59 else
60 irq = dispc_mgr_get_vsync_irq(mgr->id);
61
62 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
63
64 dispc_runtime_put();
65
66 return r;
67}
68
69int dss_init_overlay_managers(struct platform_device *pdev) 39int dss_init_overlay_managers(struct platform_device *pdev)
70{ 40{
71 int i, r; 41 int i, r;
@@ -99,15 +69,6 @@ int dss_init_overlay_managers(struct platform_device *pdev)
99 break; 69 break;
100 } 70 }
101 71
102 mgr->set_output = &dss_mgr_set_output;
103 mgr->unset_output = &dss_mgr_unset_output;
104 mgr->apply = &omap_dss_mgr_apply;
105 mgr->set_manager_info = &dss_mgr_set_info;
106 mgr->get_manager_info = &dss_mgr_get_info;
107 mgr->wait_for_go = &dss_mgr_wait_for_go;
108 mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
109 mgr->get_device = &dss_mgr_get_device;
110
111 mgr->caps = 0; 72 mgr->caps = 0;
112 mgr->supported_displays = 73 mgr->supported_displays =
113 dss_feat_get_supported_displays(mgr->id); 74 dss_feat_get_supported_displays(mgr->id);
diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c
index 813f26682b7a..79dea1a1a732 100644
--- a/drivers/video/omap2/dss/output.c
+++ b/drivers/video/omap2/dss/output.c
@@ -114,35 +114,67 @@ struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id)
114 return NULL; 114 return NULL;
115} 115}
116 116
117struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev) 117static const struct dss_mgr_ops *dss_mgr_ops;
118
119int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops)
118{ 120{
119 struct omap_dss_output *out = NULL; 121 if (dss_mgr_ops)
120 enum omap_dss_output_id id; 122 return -EBUSY;
121 123
122 switch (dssdev->type) { 124 dss_mgr_ops = mgr_ops;
123 case OMAP_DISPLAY_TYPE_DPI: 125
124 out = omap_dss_get_output(OMAP_DSS_OUTPUT_DPI); 126 return 0;
125 break; 127}
126 case OMAP_DISPLAY_TYPE_DBI: 128EXPORT_SYMBOL(dss_install_mgr_ops);
127 out = omap_dss_get_output(OMAP_DSS_OUTPUT_DBI); 129
128 break; 130void dss_uninstall_mgr_ops(void)
129 case OMAP_DISPLAY_TYPE_SDI: 131{
130 out = omap_dss_get_output(OMAP_DSS_OUTPUT_SDI); 132 dss_mgr_ops = NULL;
131 break; 133}
132 case OMAP_DISPLAY_TYPE_VENC: 134EXPORT_SYMBOL(dss_uninstall_mgr_ops);
133 out = omap_dss_get_output(OMAP_DSS_OUTPUT_VENC); 135
134 break; 136void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
135 case OMAP_DISPLAY_TYPE_HDMI: 137 const struct omap_video_timings *timings)
136 out = omap_dss_get_output(OMAP_DSS_OUTPUT_HDMI); 138{
137 break; 139 dss_mgr_ops->set_timings(mgr, timings);
138 case OMAP_DISPLAY_TYPE_DSI: 140}
139 id = dssdev->phy.dsi.module == 0 ? OMAP_DSS_OUTPUT_DSI1 : 141EXPORT_SYMBOL(dss_mgr_set_timings);
140 OMAP_DSS_OUTPUT_DSI2; 142
141 out = omap_dss_get_output(id); 143void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
142 break; 144 const struct dss_lcd_mgr_config *config)
143 default: 145{
144 break; 146 dss_mgr_ops->set_lcd_config(mgr, config);
145 } 147}
148EXPORT_SYMBOL(dss_mgr_set_lcd_config);
149
150int dss_mgr_enable(struct omap_overlay_manager *mgr)
151{
152 return dss_mgr_ops->enable(mgr);
153}
154EXPORT_SYMBOL(dss_mgr_enable);
155
156void dss_mgr_disable(struct omap_overlay_manager *mgr)
157{
158 dss_mgr_ops->disable(mgr);
159}
160EXPORT_SYMBOL(dss_mgr_disable);
146 161
147 return out; 162void dss_mgr_start_update(struct omap_overlay_manager *mgr)
163{
164 dss_mgr_ops->start_update(mgr);
165}
166EXPORT_SYMBOL(dss_mgr_start_update);
167
168int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr,
169 void (*handler)(void *), void *data)
170{
171 return dss_mgr_ops->register_framedone_handler(mgr, handler, data);
172}
173EXPORT_SYMBOL(dss_mgr_register_framedone_handler);
174
175void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
176 void (*handler)(void *), void *data)
177{
178 dss_mgr_ops->unregister_framedone_handler(mgr, handler, data);
148} 179}
180EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler);
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 45f4994bc6b0..eccde322c28a 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -38,13 +38,6 @@
38static int num_overlays; 38static int num_overlays;
39static struct omap_overlay *overlays; 39static struct omap_overlay *overlays;
40 40
41static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
42{
43 return ovl->manager ?
44 (ovl->manager->output ? ovl->manager->output->device : NULL) :
45 NULL;
46}
47
48int omap_dss_get_num_overlays(void) 41int omap_dss_get_num_overlays(void)
49{ 42{
50 return num_overlays; 43 return num_overlays;
@@ -93,16 +86,6 @@ void dss_init_overlays(struct platform_device *pdev)
93 break; 86 break;
94 } 87 }
95 88
96 ovl->is_enabled = &dss_ovl_is_enabled;
97 ovl->enable = &dss_ovl_enable;
98 ovl->disable = &dss_ovl_disable;
99 ovl->set_manager = &dss_ovl_set_manager;
100 ovl->unset_manager = &dss_ovl_unset_manager;
101 ovl->set_overlay_info = &dss_ovl_set_info;
102 ovl->get_overlay_info = &dss_ovl_get_info;
103 ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
104 ovl->get_device = &dss_ovl_get_device;
105
106 ovl->caps = dss_feat_get_overlay_caps(ovl->id); 89 ovl->caps = dss_feat_get_overlay_caps(ovl->id);
107 ovl->supported_modes = 90 ovl->supported_modes =
108 dss_feat_get_supported_color_modes(ovl->id); 91 dss_feat_get_supported_color_modes(ovl->id);
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 7282e5af3e1a..e903dd3f54d9 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -342,7 +342,7 @@ static int rfbi_transfer_area(struct omap_dss_device *dssdev,
342 return 0; 342 return 0;
343} 343}
344 344
345static void framedone_callback(void *data, u32 mask) 345static void framedone_callback(void *data)
346{ 346{
347 void (*callback)(void *data); 347 void (*callback)(void *data);
348 348
@@ -908,8 +908,8 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
908 goto err0; 908 goto err0;
909 } 909 }
910 910
911 r = omap_dispc_register_isr(framedone_callback, NULL, 911 r = dss_mgr_register_framedone_handler(out->manager,
912 DISPC_IRQ_FRAMEDONE); 912 framedone_callback, NULL);
913 if (r) { 913 if (r) {
914 DSSERR("can't get FRAMEDONE irq\n"); 914 DSSERR("can't get FRAMEDONE irq\n");
915 goto err1; 915 goto err1;
@@ -933,8 +933,10 @@ EXPORT_SYMBOL(omapdss_rfbi_display_enable);
933 933
934void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev) 934void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
935{ 935{
936 omap_dispc_unregister_isr(framedone_callback, NULL, 936 struct omap_dss_output *out = dssdev->output;
937 DISPC_IRQ_FRAMEDONE); 937
938 dss_mgr_unregister_framedone_handler(out->manager,
939 framedone_callback, NULL);
938 omap_dss_stop_device(dssdev); 940 omap_dss_stop_device(dssdev);
939 941
940 rfbi_runtime_put(); 942 rfbi_runtime_put();
@@ -950,7 +952,7 @@ static int __init rfbi_init_display(struct omap_dss_device *dssdev)
950static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev) 952static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
951{ 953{
952 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 954 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
953 const char *def_disp_name = dss_get_default_display_name(); 955 const char *def_disp_name = omapdss_get_default_display_name();
954 struct omap_dss_device *def_dssdev; 956 struct omap_dss_device *def_dssdev;
955 int i; 957 int i;
956 958
@@ -999,9 +1001,18 @@ static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
999 return; 1001 return;
1000 } 1002 }
1001 1003
1004 r = omapdss_output_set_device(&rfbi.output, dssdev);
1005 if (r) {
1006 DSSERR("failed to connect output to new device: %s\n",
1007 dssdev->name);
1008 dss_put_device(dssdev);
1009 return;
1010 }
1011
1002 r = dss_add_device(dssdev); 1012 r = dss_add_device(dssdev);
1003 if (r) { 1013 if (r) {
1004 DSSERR("device %s register failed: %d\n", dssdev->name, r); 1014 DSSERR("device %s register failed: %d\n", dssdev->name, r);
1015 omapdss_output_unset_device(&rfbi.output);
1005 dss_put_device(dssdev); 1016 dss_put_device(dssdev);
1006 return; 1017 return;
1007 } 1018 }
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 7760851f6e5d..62b5374ce438 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -205,7 +205,7 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev)
205static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev) 205static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev)
206{ 206{
207 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 207 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
208 const char *def_disp_name = dss_get_default_display_name(); 208 const char *def_disp_name = omapdss_get_default_display_name();
209 struct omap_dss_device *def_dssdev; 209 struct omap_dss_device *def_dssdev;
210 int i; 210 int i;
211 211
@@ -254,9 +254,18 @@ static void __init sdi_probe_pdata(struct platform_device *sdidev)
254 return; 254 return;
255 } 255 }
256 256
257 r = omapdss_output_set_device(&sdi.output, dssdev);
258 if (r) {
259 DSSERR("failed to connect output to new device: %s\n",
260 dssdev->name);
261 dss_put_device(dssdev);
262 return;
263 }
264
257 r = dss_add_device(dssdev); 265 r = dss_add_device(dssdev);
258 if (r) { 266 if (r) {
259 DSSERR("device %s register failed: %d\n", dssdev->name, r); 267 DSSERR("device %s register failed: %d\n", dssdev->name, r);
268 omapdss_output_unset_device(&sdi.output);
260 dss_put_device(dssdev); 269 dss_put_device(dssdev);
261 return; 270 return;
262 } 271 }
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h
index b046c208cb97..216aa704f9d7 100644
--- a/drivers/video/omap2/dss/ti_hdmi.h
+++ b/drivers/video/omap2/dss/ti_hdmi.h
@@ -102,6 +102,8 @@ struct ti_hdmi_ip_ops {
102 102
103 int (*audio_config)(struct hdmi_ip_data *ip_data, 103 int (*audio_config)(struct hdmi_ip_data *ip_data,
104 struct omap_dss_audio *audio); 104 struct omap_dss_audio *audio);
105
106 int (*audio_get_dma_port)(u32 *offset, u32 *size);
105#endif 107#endif
106 108
107}; 109};
@@ -183,5 +185,6 @@ int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data);
183void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data); 185void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data);
184int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data, 186int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
185 struct omap_dss_audio *audio); 187 struct omap_dss_audio *audio);
188int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size);
186#endif 189#endif
187#endif 190#endif
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
index c23b85a20cdc..e18b222ed739 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
@@ -899,7 +899,7 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
899#define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\ 899#define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\
900 hdmi_read_reg(hdmi_av_base(ip_data), r)) 900 hdmi_read_reg(hdmi_av_base(ip_data), r))
901#define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \ 901#define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
902 (i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \ 902 (i < 10) ? 32 - (int)strlen(#r) : 31 - (int)strlen(#r), " ", \
903 hdmi_read_reg(hdmi_av_base(ip_data), CORE_REG(i, r))) 903 hdmi_read_reg(hdmi_av_base(ip_data), CORE_REG(i, r)))
904 904
905 DUMPCORE(HDMI_CORE_SYS_VND_IDL); 905 DUMPCORE(HDMI_CORE_SYS_VND_IDL);
@@ -1418,4 +1418,13 @@ void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data)
1418 REG_FLD_MOD(hdmi_wp_base(ip_data), 1418 REG_FLD_MOD(hdmi_wp_base(ip_data),
1419 HDMI_WP_AUDIO_CTRL, false, 30, 30); 1419 HDMI_WP_AUDIO_CTRL, false, 30, 30);
1420} 1420}
1421
1422int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size)
1423{
1424 if (!offset || !size)
1425 return -EINVAL;
1426 *offset = HDMI_WP_AUDIO_DATA;
1427 *size = 4;
1428 return 0;
1429}
1421#endif 1430#endif
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 56efa3bb465d..006caf3cb509 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -744,7 +744,7 @@ static void venc_put_clocks(void)
744static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev) 744static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
745{ 745{
746 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 746 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
747 const char *def_disp_name = dss_get_default_display_name(); 747 const char *def_disp_name = omapdss_get_default_display_name();
748 struct omap_dss_device *def_dssdev; 748 struct omap_dss_device *def_dssdev;
749 int i; 749 int i;
750 750
@@ -795,9 +795,18 @@ static void __init venc_probe_pdata(struct platform_device *vencdev)
795 return; 795 return;
796 } 796 }
797 797
798 r = omapdss_output_set_device(&venc.output, dssdev);
799 if (r) {
800 DSSERR("failed to connect output to new device: %s\n",
801 dssdev->name);
802 dss_put_device(dssdev);
803 return;
804 }
805
798 r = dss_add_device(dssdev); 806 r = dss_add_device(dssdev);
799 if (r) { 807 if (r) {
800 DSSERR("device %s register failed: %d\n", dssdev->name, r); 808 DSSERR("device %s register failed: %d\n", dssdev->name, r);
809 omapdss_output_unset_device(&venc.output);
801 dss_put_device(dssdev); 810 dss_put_device(dssdev);
802 return; 811 return;
803 } 812 }
diff --git a/drivers/video/omap2/dss/venc_panel.c b/drivers/video/omap2/dss/venc_panel.c
index d55b8784ecfd..0d2b1a0834a0 100644
--- a/drivers/video/omap2/dss/venc_panel.c
+++ b/drivers/video/omap2/dss/venc_panel.c
@@ -157,12 +157,6 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
157 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED) 157 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
158 goto end; 158 goto end;
159 159
160 if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
161 /* suspended is the same as disabled with venc */
162 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
163 goto end;
164 }
165
166 omapdss_venc_display_disable(dssdev); 160 omapdss_venc_display_disable(dssdev);
167 161
168 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 162 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
@@ -170,17 +164,6 @@ end:
170 mutex_unlock(&venc_panel.lock); 164 mutex_unlock(&venc_panel.lock);
171} 165}
172 166
173static int venc_panel_suspend(struct omap_dss_device *dssdev)
174{
175 venc_panel_disable(dssdev);
176 return 0;
177}
178
179static int venc_panel_resume(struct omap_dss_device *dssdev)
180{
181 return venc_panel_enable(dssdev);
182}
183
184static void venc_panel_set_timings(struct omap_dss_device *dssdev, 167static void venc_panel_set_timings(struct omap_dss_device *dssdev,
185 struct omap_video_timings *timings) 168 struct omap_video_timings *timings)
186{ 169{
@@ -222,8 +205,6 @@ static struct omap_dss_driver venc_driver = {
222 205
223 .enable = venc_panel_enable, 206 .enable = venc_panel_enable,
224 .disable = venc_panel_disable, 207 .disable = venc_panel_disable,
225 .suspend = venc_panel_suspend,
226 .resume = venc_panel_resume,
227 208
228 .get_resolution = omapdss_default_get_resolution, 209 .get_resolution = omapdss_default_get_resolution,
229 .get_recommended_bpp = omapdss_default_get_recommended_bpp, 210 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
index 4ea17dc3258c..4cb12ce68855 100644
--- a/drivers/video/omap2/omapfb/Kconfig
+++ b/drivers/video/omap2/omapfb/Kconfig
@@ -2,7 +2,6 @@ menuconfig FB_OMAP2
2 tristate "OMAP2+ frame buffer support" 2 tristate "OMAP2+ frame buffer support"
3 depends on FB && OMAP2_DSS && !DRM_OMAP 3 depends on FB && OMAP2_DSS && !DRM_OMAP
4 4
5 select OMAP2_VRAM
6 select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3 5 select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
7 select FB_CFB_FILLRECT 6 select FB_CFB_FILLRECT
8 select FB_CFB_COPYAREA 7 select FB_CFB_COPYAREA
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index d630b26a005c..d30b45d72649 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -28,10 +28,10 @@
28#include <linux/omapfb.h> 28#include <linux/omapfb.h>
29#include <linux/vmalloc.h> 29#include <linux/vmalloc.h>
30#include <linux/export.h> 30#include <linux/export.h>
31#include <linux/sizes.h>
31 32
32#include <video/omapdss.h> 33#include <video/omapdss.h>
33#include <plat/vrfb.h> 34#include <video/omapvrfb.h>
34#include <plat/vram.h>
35 35
36#include "omapfb.h" 36#include "omapfb.h"
37 37
@@ -211,6 +211,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
211{ 211{
212 struct omapfb_info *ofbi = FB2OFB(fbi); 212 struct omapfb_info *ofbi = FB2OFB(fbi);
213 struct omapfb2_device *fbdev = ofbi->fbdev; 213 struct omapfb2_device *fbdev = ofbi->fbdev;
214 struct omap_dss_device *display = fb2display(fbi);
214 struct omapfb2_mem_region *rg; 215 struct omapfb2_mem_region *rg;
215 int r = 0, i; 216 int r = 0, i;
216 size_t size; 217 size_t size;
@@ -220,6 +221,9 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
220 221
221 size = PAGE_ALIGN(mi->size); 222 size = PAGE_ALIGN(mi->size);
222 223
224 if (display && display->driver->sync)
225 display->driver->sync(display);
226
223 rg = ofbi->region; 227 rg = ofbi->region;
224 228
225 down_write_nested(&rg->lock, rg->id); 229 down_write_nested(&rg->lock, rg->id);
@@ -279,7 +283,7 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
279 return 0; 283 return 0;
280} 284}
281 285
282static int omapfb_update_window_nolock(struct fb_info *fbi, 286static int omapfb_update_window(struct fb_info *fbi,
283 u32 x, u32 y, u32 w, u32 h) 287 u32 x, u32 y, u32 w, u32 h)
284{ 288{
285 struct omap_dss_device *display = fb2display(fbi); 289 struct omap_dss_device *display = fb2display(fbi);
@@ -299,27 +303,6 @@ static int omapfb_update_window_nolock(struct fb_info *fbi,
299 return display->driver->update(display, x, y, w, h); 303 return display->driver->update(display, x, y, w, h);
300} 304}
301 305
302/* This function is exported for SGX driver use */
303int omapfb_update_window(struct fb_info *fbi,
304 u32 x, u32 y, u32 w, u32 h)
305{
306 struct omapfb_info *ofbi = FB2OFB(fbi);
307 struct omapfb2_device *fbdev = ofbi->fbdev;
308 int r;
309
310 if (!lock_fb_info(fbi))
311 return -ENODEV;
312 omapfb_lock(fbdev);
313
314 r = omapfb_update_window_nolock(fbi, x, y, w, h);
315
316 omapfb_unlock(fbdev);
317 unlock_fb_info(fbi);
318
319 return r;
320}
321EXPORT_SYMBOL(omapfb_update_window);
322
323int omapfb_set_update_mode(struct fb_info *fbi, 306int omapfb_set_update_mode(struct fb_info *fbi,
324 enum omapfb_update_mode mode) 307 enum omapfb_update_mode mode)
325{ 308{
@@ -646,7 +629,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
646 break; 629 break;
647 } 630 }
648 631
649 r = omapfb_update_window_nolock(fbi, p.uwnd_o.x, p.uwnd_o.y, 632 r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y,
650 p.uwnd_o.width, p.uwnd_o.height); 633 p.uwnd_o.width, p.uwnd_o.height);
651 break; 634 break;
652 635
@@ -663,7 +646,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
663 break; 646 break;
664 } 647 }
665 648
666 r = omapfb_update_window_nolock(fbi, p.uwnd.x, p.uwnd.y, 649 r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y,
667 p.uwnd.width, p.uwnd.height); 650 p.uwnd.width, p.uwnd.height);
668 break; 651 break;
669 652
@@ -853,14 +836,15 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
853 break; 836 break;
854 837
855 case OMAPFB_GET_VRAM_INFO: { 838 case OMAPFB_GET_VRAM_INFO: {
856 unsigned long vram, free, largest;
857
858 DBG("ioctl GET_VRAM_INFO\n"); 839 DBG("ioctl GET_VRAM_INFO\n");
859 840
860 omap_vram_get_info(&vram, &free, &largest); 841 /*
861 p.vram_info.total = vram; 842 * We don't have the ability to get this vram info anymore.
862 p.vram_info.free = free; 843 * Fill in something that should keep the applications working.
863 p.vram_info.largest_free_block = largest; 844 */
845 p.vram_info.total = SZ_1M * 64;
846 p.vram_info.free = SZ_1M * 64;
847 p.vram_info.largest_free_block = SZ_1M * 64;
864 848
865 if (copy_to_user((void __user *)arg, &p.vram_info, 849 if (copy_to_user((void __user *)arg, &p.vram_info,
866 sizeof(p.vram_info))) 850 sizeof(p.vram_info)))
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 16db1589bd91..ca585ef37f25 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -31,9 +31,7 @@
31#include <linux/omapfb.h> 31#include <linux/omapfb.h>
32 32
33#include <video/omapdss.h> 33#include <video/omapdss.h>
34#include <plat/cpu.h> 34#include <video/omapvrfb.h>
35#include <plat/vram.h>
36#include <plat/vrfb.h>
37 35
38#include "omapfb.h" 36#include "omapfb.h"
39 37
@@ -1259,11 +1257,10 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
1259 1257
1260 switch (blank) { 1258 switch (blank) {
1261 case FB_BLANK_UNBLANK: 1259 case FB_BLANK_UNBLANK:
1262 if (display->state != OMAP_DSS_DISPLAY_SUSPENDED) 1260 if (display->state == OMAP_DSS_DISPLAY_ACTIVE)
1263 goto exit; 1261 goto exit;
1264 1262
1265 if (display->driver->resume) 1263 r = display->driver->enable(display);
1266 r = display->driver->resume(display);
1267 1264
1268 if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) && 1265 if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
1269 d->update_mode == OMAPFB_AUTO_UPDATE && 1266 d->update_mode == OMAPFB_AUTO_UPDATE &&
@@ -1284,8 +1281,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
1284 if (d->auto_update_work_enabled) 1281 if (d->auto_update_work_enabled)
1285 omapfb_stop_auto_update(fbdev, display); 1282 omapfb_stop_auto_update(fbdev, display);
1286 1283
1287 if (display->driver->suspend) 1284 display->driver->disable(display);
1288 r = display->driver->suspend(display);
1289 1285
1290 break; 1286 break;
1291 1287
@@ -1336,24 +1332,25 @@ static void omapfb_free_fbmem(struct fb_info *fbi)
1336 1332
1337 rg = ofbi->region; 1333 rg = ofbi->region;
1338 1334
1339 WARN_ON(atomic_read(&rg->map_count)); 1335 if (rg->token == NULL)
1340 1336 return;
1341 if (rg->paddr)
1342 if (omap_vram_free(rg->paddr, rg->size))
1343 dev_err(fbdev->dev, "VRAM FREE failed\n");
1344 1337
1345 if (rg->vaddr) 1338 WARN_ON(atomic_read(&rg->map_count));
1346 iounmap(rg->vaddr);
1347 1339
1348 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { 1340 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1349 /* unmap the 0 angle rotation */ 1341 /* unmap the 0 angle rotation */
1350 if (rg->vrfb.vaddr[0]) { 1342 if (rg->vrfb.vaddr[0]) {
1351 iounmap(rg->vrfb.vaddr[0]); 1343 iounmap(rg->vrfb.vaddr[0]);
1352 omap_vrfb_release_ctx(&rg->vrfb);
1353 rg->vrfb.vaddr[0] = NULL; 1344 rg->vrfb.vaddr[0] = NULL;
1354 } 1345 }
1346
1347 omap_vrfb_release_ctx(&rg->vrfb);
1355 } 1348 }
1356 1349
1350 dma_free_attrs(fbdev->dev, rg->size, rg->token, rg->dma_handle,
1351 &rg->attrs);
1352
1353 rg->token = NULL;
1357 rg->vaddr = NULL; 1354 rg->vaddr = NULL;
1358 rg->paddr = 0; 1355 rg->paddr = 0;
1359 rg->alloc = 0; 1356 rg->alloc = 0;
@@ -1388,7 +1385,9 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
1388 struct omapfb_info *ofbi = FB2OFB(fbi); 1385 struct omapfb_info *ofbi = FB2OFB(fbi);
1389 struct omapfb2_device *fbdev = ofbi->fbdev; 1386 struct omapfb2_device *fbdev = ofbi->fbdev;
1390 struct omapfb2_mem_region *rg; 1387 struct omapfb2_mem_region *rg;
1391 void __iomem *vaddr; 1388 void *token;
1389 DEFINE_DMA_ATTRS(attrs);
1390 dma_addr_t dma_handle;
1392 int r; 1391 int r;
1393 1392
1394 rg = ofbi->region; 1393 rg = ofbi->region;
@@ -1403,42 +1402,40 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
1403 1402
1404 size = PAGE_ALIGN(size); 1403 size = PAGE_ALIGN(size);
1405 1404
1406 if (!paddr) { 1405 dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
1407 DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
1408 r = omap_vram_alloc(size, &paddr);
1409 } else {
1410 DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
1411 ofbi->id);
1412 r = omap_vram_reserve(paddr, size);
1413 }
1414 1406
1415 if (r) { 1407 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
1408 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
1409
1410 DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
1411
1412 token = dma_alloc_attrs(fbdev->dev, size, &dma_handle,
1413 GFP_KERNEL, &attrs);
1414
1415 if (token == NULL) {
1416 dev_err(fbdev->dev, "failed to allocate framebuffer\n"); 1416 dev_err(fbdev->dev, "failed to allocate framebuffer\n");
1417 return -ENOMEM; 1417 return -ENOMEM;
1418 } 1418 }
1419 1419
1420 if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) { 1420 DBG("allocated VRAM paddr %lx, vaddr %p\n",
1421 vaddr = ioremap_wc(paddr, size); 1421 (unsigned long)dma_handle, token);
1422
1423 if (!vaddr) {
1424 dev_err(fbdev->dev, "failed to ioremap framebuffer\n");
1425 omap_vram_free(paddr, size);
1426 return -ENOMEM;
1427 }
1428 1422
1429 DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr); 1423 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1430 } else {
1431 r = omap_vrfb_request_ctx(&rg->vrfb); 1424 r = omap_vrfb_request_ctx(&rg->vrfb);
1432 if (r) { 1425 if (r) {
1426 dma_free_attrs(fbdev->dev, size, token, dma_handle,
1427 &attrs);
1433 dev_err(fbdev->dev, "vrfb create ctx failed\n"); 1428 dev_err(fbdev->dev, "vrfb create ctx failed\n");
1434 return r; 1429 return r;
1435 } 1430 }
1436
1437 vaddr = NULL;
1438 } 1431 }
1439 1432
1440 rg->paddr = paddr; 1433 rg->attrs = attrs;
1441 rg->vaddr = vaddr; 1434 rg->token = token;
1435 rg->dma_handle = dma_handle;
1436
1437 rg->paddr = (unsigned long)dma_handle;
1438 rg->vaddr = (void __iomem *)token;
1442 rg->size = size; 1439 rg->size = size;
1443 rg->alloc = 1; 1440 rg->alloc = 1;
1444 1441
@@ -1532,6 +1529,9 @@ static int omapfb_parse_vram_param(const char *param, int max_entries,
1532 1529
1533 } 1530 }
1534 1531
1532 WARN_ONCE(paddr,
1533 "reserving memory at predefined address not supported\n");
1534
1535 paddrs[fbnum] = paddr; 1535 paddrs[fbnum] = paddr;
1536 sizes[fbnum] = size; 1536 sizes[fbnum] = size;
1537 1537
@@ -1611,7 +1611,6 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1611{ 1611{
1612 struct omapfb_info *ofbi = FB2OFB(fbi); 1612 struct omapfb_info *ofbi = FB2OFB(fbi);
1613 struct omapfb2_device *fbdev = ofbi->fbdev; 1613 struct omapfb2_device *fbdev = ofbi->fbdev;
1614 struct omap_dss_device *display = fb2display(fbi);
1615 struct omapfb2_mem_region *rg = ofbi->region; 1614 struct omapfb2_mem_region *rg = ofbi->region;
1616 unsigned long old_size = rg->size; 1615 unsigned long old_size = rg->size;
1617 unsigned long old_paddr = rg->paddr; 1616 unsigned long old_paddr = rg->paddr;
@@ -1626,9 +1625,6 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1626 if (old_size == size && old_type == type) 1625 if (old_size == size && old_type == type)
1627 return 0; 1626 return 0;
1628 1627
1629 if (display && display->driver->sync)
1630 display->driver->sync(display);
1631
1632 omapfb_free_fbmem(fbi); 1628 omapfb_free_fbmem(fbi);
1633 1629
1634 if (size == 0) { 1630 if (size == 0) {
@@ -1883,7 +1879,6 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev)
1883 } 1879 }
1884 1880
1885 dev_set_drvdata(fbdev->dev, NULL); 1881 dev_set_drvdata(fbdev->dev, NULL);
1886 kfree(fbdev);
1887} 1882}
1888 1883
1889static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) 1884static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
@@ -2259,26 +2254,28 @@ static int omapfb_find_best_mode(struct omap_dss_device *display,
2259{ 2254{
2260 struct fb_monspecs *specs; 2255 struct fb_monspecs *specs;
2261 u8 *edid; 2256 u8 *edid;
2262 int r, i, best_xres, best_idx, len; 2257 int r, i, best_idx, len;
2263 2258
2264 if (!display->driver->read_edid) 2259 if (!display->driver->read_edid)
2265 return -ENODEV; 2260 return -ENODEV;
2266 2261
2267 len = 0x80 * 2; 2262 len = 0x80 * 2;
2268 edid = kmalloc(len, GFP_KERNEL); 2263 edid = kmalloc(len, GFP_KERNEL);
2264 if (edid == NULL)
2265 return -ENOMEM;
2269 2266
2270 r = display->driver->read_edid(display, edid, len); 2267 r = display->driver->read_edid(display, edid, len);
2271 if (r < 0) 2268 if (r < 0)
2272 goto err1; 2269 goto err1;
2273 2270
2274 specs = kzalloc(sizeof(*specs), GFP_KERNEL); 2271 specs = kzalloc(sizeof(*specs), GFP_KERNEL);
2272 if (specs == NULL) {
2273 r = -ENOMEM;
2274 goto err1;
2275 }
2275 2276
2276 fb_edid_to_monspecs(edid, specs); 2277 fb_edid_to_monspecs(edid, specs);
2277 2278
2278 if (edid[126] > 0)
2279 fb_edid_add_monspecs(edid + 0x80, specs);
2280
2281 best_xres = 0;
2282 best_idx = -1; 2279 best_idx = -1;
2283 2280
2284 for (i = 0; i < specs->modedb_len; ++i) { 2281 for (i = 0; i < specs->modedb_len; ++i) {
@@ -2294,16 +2291,20 @@ static int omapfb_find_best_mode(struct omap_dss_device *display,
2294 if (m->xres == 2880 || m->xres == 1440) 2291 if (m->xres == 2880 || m->xres == 1440)
2295 continue; 2292 continue;
2296 2293
2294 if (m->vmode & FB_VMODE_INTERLACED ||
2295 m->vmode & FB_VMODE_DOUBLE)
2296 continue;
2297
2297 fb_videomode_to_omap_timings(m, display, &t); 2298 fb_videomode_to_omap_timings(m, display, &t);
2298 2299
2299 r = display->driver->check_timings(display, &t); 2300 r = display->driver->check_timings(display, &t);
2300 if (r == 0 && best_xres < m->xres) { 2301 if (r == 0) {
2301 best_xres = m->xres;
2302 best_idx = i; 2302 best_idx = i;
2303 break;
2303 } 2304 }
2304 } 2305 }
2305 2306
2306 if (best_xres == 0) { 2307 if (best_idx == -1) {
2307 r = -ENOENT; 2308 r = -ENOENT;
2308 goto err2; 2309 goto err2;
2309 } 2310 }
@@ -2372,15 +2373,62 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
2372 return 0; 2373 return 0;
2373} 2374}
2374 2375
2376static int omapfb_init_connections(struct omapfb2_device *fbdev,
2377 struct omap_dss_device *def_dssdev)
2378{
2379 int i, r;
2380 struct omap_overlay_manager *mgr;
2381
2382 if (!def_dssdev->output) {
2383 dev_err(fbdev->dev, "no output for the default display\n");
2384 return -EINVAL;
2385 }
2386
2387 for (i = 0; i < fbdev->num_displays; ++i) {
2388 struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
2389 struct omap_dss_output *out = dssdev->output;
2390
2391 mgr = omap_dss_get_overlay_manager(dssdev->channel);
2392
2393 if (!mgr || !out)
2394 continue;
2395
2396 if (mgr->output)
2397 mgr->unset_output(mgr);
2398
2399 mgr->set_output(mgr, out);
2400 }
2401
2402 mgr = def_dssdev->output->manager;
2403
2404 if (!mgr) {
2405 dev_err(fbdev->dev, "no ovl manager for the default display\n");
2406 return -EINVAL;
2407 }
2408
2409 for (i = 0; i < fbdev->num_overlays; i++) {
2410 struct omap_overlay *ovl = fbdev->overlays[i];
2411
2412 if (ovl->manager)
2413 ovl->unset_manager(ovl);
2414
2415 r = ovl->set_manager(ovl, mgr);
2416 if (r)
2417 dev_warn(fbdev->dev,
2418 "failed to connect overlay %s to manager %s\n",
2419 ovl->name, mgr->name);
2420 }
2421
2422 return 0;
2423}
2424
2375static int __init omapfb_probe(struct platform_device *pdev) 2425static int __init omapfb_probe(struct platform_device *pdev)
2376{ 2426{
2377 struct omapfb2_device *fbdev = NULL; 2427 struct omapfb2_device *fbdev = NULL;
2378 int r = 0; 2428 int r = 0;
2379 int i; 2429 int i;
2380 struct omap_overlay *ovl;
2381 struct omap_dss_device *def_display; 2430 struct omap_dss_device *def_display;
2382 struct omap_dss_device *dssdev; 2431 struct omap_dss_device *dssdev;
2383 struct omap_dss_device *ovl_device;
2384 2432
2385 DBG("omapfb_probe\n"); 2433 DBG("omapfb_probe\n");
2386 2434
@@ -2390,28 +2438,28 @@ static int __init omapfb_probe(struct platform_device *pdev)
2390 goto err0; 2438 goto err0;
2391 } 2439 }
2392 2440
2393 fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL); 2441 fbdev = devm_kzalloc(&pdev->dev, sizeof(struct omapfb2_device),
2442 GFP_KERNEL);
2394 if (fbdev == NULL) { 2443 if (fbdev == NULL) {
2395 r = -ENOMEM; 2444 r = -ENOMEM;
2396 goto err0; 2445 goto err0;
2397 } 2446 }
2398 2447
2399 /* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE 2448 if (def_vrfb && !omap_vrfb_supported()) {
2400 * available for OMAP2 and OMAP3
2401 */
2402 if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) {
2403 def_vrfb = 0; 2449 def_vrfb = 0;
2404 dev_warn(&pdev->dev, "VRFB is not supported on this hardware, " 2450 dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
2405 "ignoring the module parameter vrfb=y\n"); 2451 "ignoring the module parameter vrfb=y\n");
2406 } 2452 }
2407 2453
2454 r = omapdss_compat_init();
2455 if (r)
2456 goto err0;
2408 2457
2409 mutex_init(&fbdev->mtx); 2458 mutex_init(&fbdev->mtx);
2410 2459
2411 fbdev->dev = &pdev->dev; 2460 fbdev->dev = &pdev->dev;
2412 platform_set_drvdata(pdev, fbdev); 2461 platform_set_drvdata(pdev, fbdev);
2413 2462
2414 r = 0;
2415 fbdev->num_displays = 0; 2463 fbdev->num_displays = 0;
2416 dssdev = NULL; 2464 dssdev = NULL;
2417 for_each_dss_dev(dssdev) { 2465 for_each_dss_dev(dssdev) {
@@ -2434,9 +2482,6 @@ static int __init omapfb_probe(struct platform_device *pdev)
2434 d->update_mode = OMAPFB_AUTO_UPDATE; 2482 d->update_mode = OMAPFB_AUTO_UPDATE;
2435 } 2483 }
2436 2484
2437 if (r)
2438 goto cleanup;
2439
2440 if (fbdev->num_displays == 0) { 2485 if (fbdev->num_displays == 0) {
2441 dev_err(&pdev->dev, "no displays\n"); 2486 dev_err(&pdev->dev, "no displays\n");
2442 r = -EINVAL; 2487 r = -EINVAL;
@@ -2451,15 +2496,33 @@ static int __init omapfb_probe(struct platform_device *pdev)
2451 for (i = 0; i < fbdev->num_managers; i++) 2496 for (i = 0; i < fbdev->num_managers; i++)
2452 fbdev->managers[i] = omap_dss_get_overlay_manager(i); 2497 fbdev->managers[i] = omap_dss_get_overlay_manager(i);
2453 2498
2454 /* gfx overlay should be the default one. find a display 2499 def_display = NULL;
2455 * connected to that, and use it as default display */ 2500
2456 ovl = omap_dss_get_overlay(0); 2501 for (i = 0; i < fbdev->num_displays; ++i) {
2457 ovl_device = ovl->get_device(ovl); 2502 struct omap_dss_device *dssdev;
2458 if (ovl_device) { 2503 const char *def_name;
2459 def_display = ovl_device; 2504
2460 } else { 2505 def_name = omapdss_get_default_display_name();
2461 dev_warn(&pdev->dev, "cannot find default display\n"); 2506
2462 def_display = NULL; 2507 dssdev = fbdev->displays[i].dssdev;
2508
2509 if (def_name == NULL ||
2510 (dssdev->name && strcmp(def_name, dssdev->name) == 0)) {
2511 def_display = dssdev;
2512 break;
2513 }
2514 }
2515
2516 if (def_display == NULL) {
2517 dev_err(fbdev->dev, "failed to find default display\n");
2518 r = -EINVAL;
2519 goto cleanup;
2520 }
2521
2522 r = omapfb_init_connections(fbdev, def_display);
2523 if (r) {
2524 dev_err(fbdev->dev, "failed to init overlay connections\n");
2525 goto cleanup;
2463 } 2526 }
2464 2527
2465 if (def_mode && strlen(def_mode) > 0) { 2528 if (def_mode && strlen(def_mode) > 0) {
@@ -2510,6 +2573,7 @@ static int __init omapfb_probe(struct platform_device *pdev)
2510 2573
2511cleanup: 2574cleanup:
2512 omapfb_free_resources(fbdev); 2575 omapfb_free_resources(fbdev);
2576 omapdss_compat_uninit();
2513err0: 2577err0:
2514 dev_err(&pdev->dev, "failed to setup omapfb\n"); 2578 dev_err(&pdev->dev, "failed to setup omapfb\n");
2515 return r; 2579 return r;
@@ -2525,6 +2589,8 @@ static int __exit omapfb_remove(struct platform_device *pdev)
2525 2589
2526 omapfb_free_resources(fbdev); 2590 omapfb_free_resources(fbdev);
2527 2591
2592 omapdss_compat_uninit();
2593
2528 return 0; 2594 return 0;
2529} 2595}
2530 2596
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index e8d8cc76a435..18fa9e1d0033 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -30,7 +30,7 @@
30#include <linux/omapfb.h> 30#include <linux/omapfb.h>
31 31
32#include <video/omapdss.h> 32#include <video/omapdss.h>
33#include <plat/vrfb.h> 33#include <video/omapvrfb.h>
34 34
35#include "omapfb.h" 35#include "omapfb.h"
36 36
@@ -441,6 +441,7 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
441 struct fb_info *fbi = dev_get_drvdata(dev); 441 struct fb_info *fbi = dev_get_drvdata(dev);
442 struct omapfb_info *ofbi = FB2OFB(fbi); 442 struct omapfb_info *ofbi = FB2OFB(fbi);
443 struct omapfb2_device *fbdev = ofbi->fbdev; 443 struct omapfb2_device *fbdev = ofbi->fbdev;
444 struct omap_dss_device *display = fb2display(fbi);
444 struct omapfb2_mem_region *rg; 445 struct omapfb2_mem_region *rg;
445 unsigned long size; 446 unsigned long size;
446 int r; 447 int r;
@@ -455,6 +456,9 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
455 if (!lock_fb_info(fbi)) 456 if (!lock_fb_info(fbi))
456 return -ENODEV; 457 return -ENODEV;
457 458
459 if (display && display->driver->sync)
460 display->driver->sync(display);
461
458 rg = ofbi->region; 462 rg = ofbi->region;
459 463
460 down_write_nested(&rg->lock, rg->id); 464 down_write_nested(&rg->lock, rg->id);
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index 5ced9b334d35..623cd872a367 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -28,6 +28,8 @@
28#endif 28#endif
29 29
30#include <linux/rwsem.h> 30#include <linux/rwsem.h>
31#include <linux/dma-attrs.h>
32#include <linux/dma-mapping.h>
31 33
32#include <video/omapdss.h> 34#include <video/omapdss.h>
33 35
@@ -49,6 +51,9 @@ extern bool omapfb_debug;
49 51
50struct omapfb2_mem_region { 52struct omapfb2_mem_region {
51 int id; 53 int id;
54 struct dma_attrs attrs;
55 void *token;
56 dma_addr_t dma_handle;
52 u32 paddr; 57 u32 paddr;
53 void __iomem *vaddr; 58 void __iomem *vaddr;
54 struct vrfb vrfb; 59 struct vrfb vrfb;
@@ -124,9 +129,6 @@ void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
124 129
125int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg); 130int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
126 131
127int omapfb_update_window(struct fb_info *fbi,
128 u32 x, u32 y, u32 w, u32 h);
129
130int dss_mode_to_fb_mode(enum omap_color_mode dssmode, 132int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
131 struct fb_var_screeninfo *var); 133 struct fb_var_screeninfo *var);
132 134
@@ -144,16 +146,16 @@ int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode);
144static inline struct omap_dss_device *fb2display(struct fb_info *fbi) 146static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
145{ 147{
146 struct omapfb_info *ofbi = FB2OFB(fbi); 148 struct omapfb_info *ofbi = FB2OFB(fbi);
147 int i; 149 struct omap_overlay *ovl;
148 150
149 /* XXX: returns the display connected to first attached overlay */ 151 /* XXX: returns the display connected to first attached overlay */
150 for (i = 0; i < ofbi->num_overlays; i++) {
151 struct omap_overlay *ovl = ofbi->overlays[i];
152 152
153 return ovl->get_device(ovl); 153 if (ofbi->num_overlays == 0)
154 } 154 return NULL;
155 155
156 return NULL; 156 ovl = ofbi->overlays[0];
157
158 return ovl->get_device(ovl);
157} 159}
158 160
159static inline struct omapfb_display_data *get_display_data( 161static inline struct omapfb_display_data *get_display_data(
diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c
deleted file mode 100644
index f2b15c4a75bc..000000000000
--- a/drivers/video/omap2/vram.c
+++ /dev/null
@@ -1,514 +0,0 @@
1/*
2 * VRAM manager for OMAP
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21/*#define DEBUG*/
22
23#include <linux/kernel.h>
24#include <linux/mm.h>
25#include <linux/list.h>
26#include <linux/slab.h>
27#include <linux/seq_file.h>
28#include <linux/memblock.h>
29#include <linux/completion.h>
30#include <linux/debugfs.h>
31#include <linux/jiffies.h>
32#include <linux/module.h>
33
34#include <asm/setup.h>
35
36#include <plat/vram.h>
37
38#ifdef DEBUG
39#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__)
40#else
41#define DBG(format, ...)
42#endif
43
44/* postponed regions are used to temporarily store region information at boot
45 * time when we cannot yet allocate the region list */
46#define MAX_POSTPONED_REGIONS 10
47
48static bool vram_initialized;
49static int postponed_cnt;
50static struct {
51 unsigned long paddr;
52 size_t size;
53} postponed_regions[MAX_POSTPONED_REGIONS];
54
55struct vram_alloc {
56 struct list_head list;
57 unsigned long paddr;
58 unsigned pages;
59};
60
61struct vram_region {
62 struct list_head list;
63 struct list_head alloc_list;
64 unsigned long paddr;
65 unsigned pages;
66};
67
68static DEFINE_MUTEX(region_mutex);
69static LIST_HEAD(region_list);
70
71static struct vram_region *omap_vram_create_region(unsigned long paddr,
72 unsigned pages)
73{
74 struct vram_region *rm;
75
76 rm = kzalloc(sizeof(*rm), GFP_KERNEL);
77
78 if (rm) {
79 INIT_LIST_HEAD(&rm->alloc_list);
80 rm->paddr = paddr;
81 rm->pages = pages;
82 }
83
84 return rm;
85}
86
87#if 0
88static void omap_vram_free_region(struct vram_region *vr)
89{
90 list_del(&vr->list);
91 kfree(vr);
92}
93#endif
94
95static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr,
96 unsigned long paddr, unsigned pages)
97{
98 struct vram_alloc *va;
99 struct vram_alloc *new;
100
101 new = kzalloc(sizeof(*va), GFP_KERNEL);
102
103 if (!new)
104 return NULL;
105
106 new->paddr = paddr;
107 new->pages = pages;
108
109 list_for_each_entry(va, &vr->alloc_list, list) {
110 if (va->paddr > new->paddr)
111 break;
112 }
113
114 list_add_tail(&new->list, &va->list);
115
116 return new;
117}
118
119static void omap_vram_free_allocation(struct vram_alloc *va)
120{
121 list_del(&va->list);
122 kfree(va);
123}
124
125int omap_vram_add_region(unsigned long paddr, size_t size)
126{
127 struct vram_region *rm;
128 unsigned pages;
129
130 if (vram_initialized) {
131 DBG("adding region paddr %08lx size %d\n",
132 paddr, size);
133
134 size &= PAGE_MASK;
135 pages = size >> PAGE_SHIFT;
136
137 rm = omap_vram_create_region(paddr, pages);
138 if (rm == NULL)
139 return -ENOMEM;
140
141 list_add(&rm->list, &region_list);
142 } else {
143 if (postponed_cnt == MAX_POSTPONED_REGIONS)
144 return -ENOMEM;
145
146 postponed_regions[postponed_cnt].paddr = paddr;
147 postponed_regions[postponed_cnt].size = size;
148
149 ++postponed_cnt;
150 }
151 return 0;
152}
153
154int omap_vram_free(unsigned long paddr, size_t size)
155{
156 struct vram_region *rm;
157 struct vram_alloc *alloc;
158 unsigned start, end;
159
160 DBG("free mem paddr %08lx size %d\n", paddr, size);
161
162 size = PAGE_ALIGN(size);
163
164 mutex_lock(&region_mutex);
165
166 list_for_each_entry(rm, &region_list, list) {
167 list_for_each_entry(alloc, &rm->alloc_list, list) {
168 start = alloc->paddr;
169 end = alloc->paddr + (alloc->pages >> PAGE_SHIFT);
170
171 if (start >= paddr && end < paddr + size)
172 goto found;
173 }
174 }
175
176 mutex_unlock(&region_mutex);
177 return -EINVAL;
178
179found:
180 omap_vram_free_allocation(alloc);
181
182 mutex_unlock(&region_mutex);
183 return 0;
184}
185EXPORT_SYMBOL(omap_vram_free);
186
187static int _omap_vram_reserve(unsigned long paddr, unsigned pages)
188{
189 struct vram_region *rm;
190 struct vram_alloc *alloc;
191 size_t size;
192
193 size = pages << PAGE_SHIFT;
194
195 list_for_each_entry(rm, &region_list, list) {
196 unsigned long start, end;
197
198 DBG("checking region %lx %d\n", rm->paddr, rm->pages);
199
200 start = rm->paddr;
201 end = start + (rm->pages << PAGE_SHIFT) - 1;
202 if (start > paddr || end < paddr + size - 1)
203 continue;
204
205 DBG("block ok, checking allocs\n");
206
207 list_for_each_entry(alloc, &rm->alloc_list, list) {
208 end = alloc->paddr - 1;
209
210 if (start <= paddr && end >= paddr + size - 1)
211 goto found;
212
213 start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
214 }
215
216 end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1;
217
218 if (!(start <= paddr && end >= paddr + size - 1))
219 continue;
220found:
221 DBG("found area start %lx, end %lx\n", start, end);
222
223 if (omap_vram_create_allocation(rm, paddr, pages) == NULL)
224 return -ENOMEM;
225
226 return 0;
227 }
228
229 return -ENOMEM;
230}
231
232int omap_vram_reserve(unsigned long paddr, size_t size)
233{
234 unsigned pages;
235 int r;
236
237 DBG("reserve mem paddr %08lx size %d\n", paddr, size);
238
239 size = PAGE_ALIGN(size);
240 pages = size >> PAGE_SHIFT;
241
242 mutex_lock(&region_mutex);
243
244 r = _omap_vram_reserve(paddr, pages);
245
246 mutex_unlock(&region_mutex);
247
248 return r;
249}
250EXPORT_SYMBOL(omap_vram_reserve);
251
252static int _omap_vram_alloc(unsigned pages, unsigned long *paddr)
253{
254 struct vram_region *rm;
255 struct vram_alloc *alloc;
256
257 list_for_each_entry(rm, &region_list, list) {
258 unsigned long start, end;
259
260 DBG("checking region %lx %d\n", rm->paddr, rm->pages);
261
262 start = rm->paddr;
263
264 list_for_each_entry(alloc, &rm->alloc_list, list) {
265 end = alloc->paddr;
266
267 if (end - start >= pages << PAGE_SHIFT)
268 goto found;
269
270 start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
271 }
272
273 end = rm->paddr + (rm->pages << PAGE_SHIFT);
274found:
275 if (end - start < pages << PAGE_SHIFT)
276 continue;
277
278 DBG("found %lx, end %lx\n", start, end);
279
280 alloc = omap_vram_create_allocation(rm, start, pages);
281 if (alloc == NULL)
282 return -ENOMEM;
283
284 *paddr = start;
285
286 return 0;
287 }
288
289 return -ENOMEM;
290}
291
292int omap_vram_alloc(size_t size, unsigned long *paddr)
293{
294 unsigned pages;
295 int r;
296
297 BUG_ON(!size);
298
299 DBG("alloc mem size %d\n", size);
300
301 size = PAGE_ALIGN(size);
302 pages = size >> PAGE_SHIFT;
303
304 mutex_lock(&region_mutex);
305
306 r = _omap_vram_alloc(pages, paddr);
307
308 mutex_unlock(&region_mutex);
309
310 return r;
311}
312EXPORT_SYMBOL(omap_vram_alloc);
313
314void omap_vram_get_info(unsigned long *vram,
315 unsigned long *free_vram,
316 unsigned long *largest_free_block)
317{
318 struct vram_region *vr;
319 struct vram_alloc *va;
320
321 *vram = 0;
322 *free_vram = 0;
323 *largest_free_block = 0;
324
325 mutex_lock(&region_mutex);
326
327 list_for_each_entry(vr, &region_list, list) {
328 unsigned free;
329 unsigned long pa;
330
331 pa = vr->paddr;
332 *vram += vr->pages << PAGE_SHIFT;
333
334 list_for_each_entry(va, &vr->alloc_list, list) {
335 free = va->paddr - pa;
336 *free_vram += free;
337 if (free > *largest_free_block)
338 *largest_free_block = free;
339 pa = va->paddr + (va->pages << PAGE_SHIFT);
340 }
341
342 free = vr->paddr + (vr->pages << PAGE_SHIFT) - pa;
343 *free_vram += free;
344 if (free > *largest_free_block)
345 *largest_free_block = free;
346 }
347
348 mutex_unlock(&region_mutex);
349}
350EXPORT_SYMBOL(omap_vram_get_info);
351
352#if defined(CONFIG_DEBUG_FS)
353static int vram_debug_show(struct seq_file *s, void *unused)
354{
355 struct vram_region *vr;
356 struct vram_alloc *va;
357 unsigned size;
358
359 mutex_lock(&region_mutex);
360
361 list_for_each_entry(vr, &region_list, list) {
362 size = vr->pages << PAGE_SHIFT;
363 seq_printf(s, "%08lx-%08lx (%d bytes)\n",
364 vr->paddr, vr->paddr + size - 1,
365 size);
366
367 list_for_each_entry(va, &vr->alloc_list, list) {
368 size = va->pages << PAGE_SHIFT;
369 seq_printf(s, " %08lx-%08lx (%d bytes)\n",
370 va->paddr, va->paddr + size - 1,
371 size);
372 }
373 }
374
375 mutex_unlock(&region_mutex);
376
377 return 0;
378}
379
380static int vram_debug_open(struct inode *inode, struct file *file)
381{
382 return single_open(file, vram_debug_show, inode->i_private);
383}
384
385static const struct file_operations vram_debug_fops = {
386 .open = vram_debug_open,
387 .read = seq_read,
388 .llseek = seq_lseek,
389 .release = single_release,
390};
391
392static int __init omap_vram_create_debugfs(void)
393{
394 struct dentry *d;
395
396 d = debugfs_create_file("vram", S_IRUGO, NULL,
397 NULL, &vram_debug_fops);
398 if (IS_ERR(d))
399 return PTR_ERR(d);
400
401 return 0;
402}
403#endif
404
405static __init int omap_vram_init(void)
406{
407 int i;
408
409 vram_initialized = 1;
410
411 for (i = 0; i < postponed_cnt; i++)
412 omap_vram_add_region(postponed_regions[i].paddr,
413 postponed_regions[i].size);
414
415#ifdef CONFIG_DEBUG_FS
416 if (omap_vram_create_debugfs())
417 pr_err("VRAM: Failed to create debugfs file\n");
418#endif
419
420 return 0;
421}
422
423arch_initcall(omap_vram_init);
424
425/* boottime vram alloc stuff */
426
427/* set from board file */
428static u32 omap_vram_sdram_start __initdata;
429static u32 omap_vram_sdram_size __initdata;
430
431/* set from kernel cmdline */
432static u32 omap_vram_def_sdram_size __initdata;
433static u32 omap_vram_def_sdram_start __initdata;
434
435static int __init omap_vram_early_vram(char *p)
436{
437 omap_vram_def_sdram_size = memparse(p, &p);
438 if (*p == ',')
439 omap_vram_def_sdram_start = simple_strtoul(p + 1, &p, 16);
440 return 0;
441}
442early_param("vram", omap_vram_early_vram);
443
444/*
445 * Called from map_io. We need to call to this early enough so that we
446 * can reserve the fixed SDRAM regions before VM could get hold of them.
447 */
448void __init omap_vram_reserve_sdram_memblock(void)
449{
450 u32 paddr;
451 u32 size = 0;
452
453 /* cmdline arg overrides the board file definition */
454 if (omap_vram_def_sdram_size) {
455 size = omap_vram_def_sdram_size;
456 paddr = omap_vram_def_sdram_start;
457 }
458
459 if (!size) {
460 size = omap_vram_sdram_size;
461 paddr = omap_vram_sdram_start;
462 }
463
464#ifdef CONFIG_OMAP2_VRAM_SIZE
465 if (!size) {
466 size = CONFIG_OMAP2_VRAM_SIZE * 1024 * 1024;
467 paddr = 0;
468 }
469#endif
470
471 if (!size)
472 return;
473
474 size = ALIGN(size, SZ_2M);
475
476 if (paddr) {
477 if (paddr & ~PAGE_MASK) {
478 pr_err("VRAM start address 0x%08x not page aligned\n",
479 paddr);
480 return;
481 }
482
483 if (!memblock_is_region_memory(paddr, size)) {
484 pr_err("Illegal SDRAM region 0x%08x..0x%08x for VRAM\n",
485 paddr, paddr + size - 1);
486 return;
487 }
488
489 if (memblock_is_region_reserved(paddr, size)) {
490 pr_err("FB: failed to reserve VRAM - busy\n");
491 return;
492 }
493
494 if (memblock_reserve(paddr, size) < 0) {
495 pr_err("FB: failed to reserve VRAM - no memory\n");
496 return;
497 }
498 } else {
499 paddr = memblock_alloc(size, SZ_2M);
500 }
501
502 memblock_free(paddr, size);
503 memblock_remove(paddr, size);
504
505 omap_vram_add_region(paddr, size);
506
507 pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
508}
509
510void __init omap_vram_set_sdram_vram(u32 size, u32 start)
511{
512 omap_vram_sdram_start = start;
513 omap_vram_sdram_size = size;
514}
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c
index 7e990220ad2a..5d8fdac3b800 100644
--- a/drivers/video/omap2/vrfb.c
+++ b/drivers/video/omap2/vrfb.c
@@ -26,9 +26,9 @@
26#include <linux/io.h> 26#include <linux/io.h>
27#include <linux/bitops.h> 27#include <linux/bitops.h>
28#include <linux/mutex.h> 28#include <linux/mutex.h>
29#include <linux/platform_device.h>
29 30
30#include <plat/vrfb.h> 31#include <video/omapvrfb.h>
31#include <plat/sdrc.h>
32 32
33#ifdef DEBUG 33#ifdef DEBUG
34#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__) 34#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
@@ -36,10 +36,10 @@
36#define DBG(format, ...) 36#define DBG(format, ...)
37#endif 37#endif
38 38
39#define SMS_ROT_VIRT_BASE(context, rot) \ 39#define SMS_ROT_CONTROL(context) (0x0 + 0x10 * context)
40 (((context >= 4) ? 0xD0000000 : 0x70000000) \ 40#define SMS_ROT_SIZE(context) (0x4 + 0x10 * context)
41 + (0x4000000 * (context)) \ 41#define SMS_ROT_PHYSICAL_BA(context) (0x8 + 0x10 * context)
42 + (0x1000000 * (rot))) 42#define SMS_ROT_VIRT_BASE(rot) (0x1000000 * (rot))
43 43
44#define OMAP_VRFB_SIZE (2048 * 2048 * 4) 44#define OMAP_VRFB_SIZE (2048 * 2048 * 4)
45 45
@@ -53,10 +53,16 @@
53#define SMS_PW_OFFSET 4 53#define SMS_PW_OFFSET 4
54#define SMS_PS_OFFSET 0 54#define SMS_PS_OFFSET 0
55 55
56#define VRFB_NUM_CTXS 12
57/* bitmap of reserved contexts */ 56/* bitmap of reserved contexts */
58static unsigned long ctx_map; 57static unsigned long ctx_map;
59 58
59struct vrfb_ctx {
60 u32 base;
61 u32 physical_ba;
62 u32 control;
63 u32 size;
64};
65
60static DEFINE_MUTEX(ctx_lock); 66static DEFINE_MUTEX(ctx_lock);
61 67
62/* 68/*
@@ -65,17 +71,34 @@ static DEFINE_MUTEX(ctx_lock);
65 * we don't need locking, since no drivers will run until after the wake-up 71 * we don't need locking, since no drivers will run until after the wake-up
66 * has finished. 72 * has finished.
67 */ 73 */
68static struct { 74
69 u32 physical_ba; 75static void __iomem *vrfb_base;
70 u32 control; 76
71 u32 size; 77static int num_ctxs;
72} vrfb_hw_context[VRFB_NUM_CTXS]; 78static struct vrfb_ctx *ctxs;
79
80static bool vrfb_loaded;
81
82static void omap2_sms_write_rot_control(u32 val, unsigned ctx)
83{
84 __raw_writel(val, vrfb_base + SMS_ROT_CONTROL(ctx));
85}
86
87static void omap2_sms_write_rot_size(u32 val, unsigned ctx)
88{
89 __raw_writel(val, vrfb_base + SMS_ROT_SIZE(ctx));
90}
91
92static void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
93{
94 __raw_writel(val, vrfb_base + SMS_ROT_PHYSICAL_BA(ctx));
95}
73 96
74static inline void restore_hw_context(int ctx) 97static inline void restore_hw_context(int ctx)
75{ 98{
76 omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx); 99 omap2_sms_write_rot_control(ctxs[ctx].control, ctx);
77 omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx); 100 omap2_sms_write_rot_size(ctxs[ctx].size, ctx);
78 omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx); 101 omap2_sms_write_rot_physical_ba(ctxs[ctx].physical_ba, ctx);
79} 102}
80 103
81static u32 get_image_width_roundup(u16 width, u8 bytespp) 104static u32 get_image_width_roundup(u16 width, u8 bytespp)
@@ -196,9 +219,9 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
196 control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET; 219 control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET;
197 control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET; 220 control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
198 221
199 vrfb_hw_context[ctx].physical_ba = paddr; 222 ctxs[ctx].physical_ba = paddr;
200 vrfb_hw_context[ctx].size = size; 223 ctxs[ctx].size = size;
201 vrfb_hw_context[ctx].control = control; 224 ctxs[ctx].control = control;
202 225
203 omap2_sms_write_rot_physical_ba(paddr, ctx); 226 omap2_sms_write_rot_physical_ba(paddr, ctx);
204 omap2_sms_write_rot_size(size, ctx); 227 omap2_sms_write_rot_size(size, ctx);
@@ -274,11 +297,11 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
274 297
275 mutex_lock(&ctx_lock); 298 mutex_lock(&ctx_lock);
276 299
277 for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx) 300 for (ctx = 0; ctx < num_ctxs; ++ctx)
278 if ((ctx_map & (1 << ctx)) == 0) 301 if ((ctx_map & (1 << ctx)) == 0)
279 break; 302 break;
280 303
281 if (ctx == VRFB_NUM_CTXS) { 304 if (ctx == num_ctxs) {
282 pr_err("vrfb: no free contexts\n"); 305 pr_err("vrfb: no free contexts\n");
283 r = -EBUSY; 306 r = -EBUSY;
284 goto out; 307 goto out;
@@ -293,7 +316,7 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
293 vrfb->context = ctx; 316 vrfb->context = ctx;
294 317
295 for (rot = 0; rot < 4; ++rot) { 318 for (rot = 0; rot < 4; ++rot) {
296 paddr = SMS_ROT_VIRT_BASE(ctx, rot); 319 paddr = ctxs[ctx].base + SMS_ROT_VIRT_BASE(rot);
297 if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) { 320 if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
298 pr_err("vrfb: failed to reserve VRFB " 321 pr_err("vrfb: failed to reserve VRFB "
299 "area for ctx %d, rotation %d\n", 322 "area for ctx %d, rotation %d\n",
@@ -314,3 +337,80 @@ out:
314 return r; 337 return r;
315} 338}
316EXPORT_SYMBOL(omap_vrfb_request_ctx); 339EXPORT_SYMBOL(omap_vrfb_request_ctx);
340
341bool omap_vrfb_supported(void)
342{
343 return vrfb_loaded;
344}
345EXPORT_SYMBOL(omap_vrfb_supported);
346
347static int __init vrfb_probe(struct platform_device *pdev)
348{
349 struct resource *mem;
350 int i;
351
352 /* first resource is the register res, the rest are vrfb contexts */
353
354 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
355 if (!mem) {
356 dev_err(&pdev->dev, "can't get vrfb base address\n");
357 return -EINVAL;
358 }
359
360 vrfb_base = devm_request_and_ioremap(&pdev->dev, mem);
361 if (!vrfb_base) {
362 dev_err(&pdev->dev, "can't ioremap vrfb memory\n");
363 return -ENOMEM;
364 }
365
366 num_ctxs = pdev->num_resources - 1;
367
368 ctxs = devm_kzalloc(&pdev->dev,
369 sizeof(struct vrfb_ctx) * num_ctxs,
370 GFP_KERNEL);
371
372 if (!ctxs)
373 return -ENOMEM;
374
375 for (i = 0; i < num_ctxs; ++i) {
376 mem = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
377 if (!mem) {
378 dev_err(&pdev->dev, "can't get vrfb ctx %d address\n",
379 i);
380 return -EINVAL;
381 }
382
383 ctxs[i].base = mem->start;
384 }
385
386 vrfb_loaded = true;
387
388 return 0;
389}
390
391static void __exit vrfb_remove(struct platform_device *pdev)
392{
393 vrfb_loaded = false;
394}
395
396static struct platform_driver vrfb_driver = {
397 .driver.name = "omapvrfb",
398 .remove = __exit_p(vrfb_remove),
399};
400
401static int __init vrfb_init(void)
402{
403 return platform_driver_probe(&vrfb_driver, &vrfb_probe);
404}
405
406static void __exit vrfb_exit(void)
407{
408 platform_driver_unregister(&vrfb_driver);
409}
410
411module_init(vrfb_init);
412module_exit(vrfb_exit);
413
414MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
415MODULE_DESCRIPTION("OMAP VRFB");
416MODULE_LICENSE("GPL v2");
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 3729173b7fbc..caefa093337d 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -21,6 +21,7 @@
21#include <linux/list.h> 21#include <linux/list.h>
22#include <linux/kobject.h> 22#include <linux/kobject.h>
23#include <linux/device.h> 23#include <linux/device.h>
24#include <linux/interrupt.h>
24 25
25#define DISPC_IRQ_FRAMEDONE (1 << 0) 26#define DISPC_IRQ_FRAMEDONE (1 << 0)
26#define DISPC_IRQ_VSYNC (1 << 1) 27#define DISPC_IRQ_VSYNC (1 << 1)
@@ -55,6 +56,7 @@
55 56
56struct omap_dss_device; 57struct omap_dss_device;
57struct omap_overlay_manager; 58struct omap_overlay_manager;
59struct dss_lcd_mgr_config;
58struct snd_aes_iec958; 60struct snd_aes_iec958;
59struct snd_cea_861_aud_if; 61struct snd_cea_861_aud_if;
60 62
@@ -158,7 +160,6 @@ enum omap_display_caps {
158enum omap_dss_display_state { 160enum omap_dss_display_state {
159 OMAP_DSS_DISPLAY_DISABLED = 0, 161 OMAP_DSS_DISPLAY_DISABLED = 0,
160 OMAP_DSS_DISPLAY_ACTIVE, 162 OMAP_DSS_DISPLAY_ACTIVE,
161 OMAP_DSS_DISPLAY_SUSPENDED,
162}; 163};
163 164
164enum omap_dss_audio_state { 165enum omap_dss_audio_state {
@@ -314,6 +315,19 @@ int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel);
314int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel); 315int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel);
315void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel); 316void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel);
316 317
318enum omapdss_version {
319 OMAPDSS_VER_UNKNOWN = 0,
320 OMAPDSS_VER_OMAP24xx,
321 OMAPDSS_VER_OMAP34xx_ES1, /* OMAP3430 ES1.0, 2.0 */
322 OMAPDSS_VER_OMAP34xx_ES3, /* OMAP3430 ES3.0+ */
323 OMAPDSS_VER_OMAP3630,
324 OMAPDSS_VER_AM35xx,
325 OMAPDSS_VER_OMAP4430_ES1, /* OMAP4430 ES1.0 */
326 OMAPDSS_VER_OMAP4430_ES2, /* OMAP4430 ES2.0, 2.1, 2.2 */
327 OMAPDSS_VER_OMAP4, /* All other OMAP4s */
328 OMAPDSS_VER_OMAP5,
329};
330
317/* Board specific data */ 331/* Board specific data */
318struct omap_dss_board_info { 332struct omap_dss_board_info {
319 int (*get_context_loss_count)(struct device *dev); 333 int (*get_context_loss_count)(struct device *dev);
@@ -323,6 +337,7 @@ struct omap_dss_board_info {
323 int (*dsi_enable_pads)(int dsi_id, unsigned lane_mask); 337 int (*dsi_enable_pads)(int dsi_id, unsigned lane_mask);
324 void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask); 338 void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask);
325 int (*set_min_bus_tput)(struct device *dev, unsigned long r); 339 int (*set_min_bus_tput)(struct device *dev, unsigned long r);
340 enum omapdss_version version;
326}; 341};
327 342
328/* Init with the board info */ 343/* Init with the board info */
@@ -607,10 +622,6 @@ struct omap_dss_device {
607 struct { 622 struct {
608 struct omap_video_timings timings; 623 struct omap_video_timings timings;
609 624
610 int acbi; /* ac-bias pin transitions per interrupt */
611 /* Unit: line clocks */
612 int acb; /* ac-bias pin frequency */
613
614 enum omap_dss_dsi_pixel_format dsi_pix_fmt; 625 enum omap_dss_dsi_pixel_format dsi_pix_fmt;
615 enum omap_dss_dsi_mode dsi_mode; 626 enum omap_dss_dsi_mode dsi_mode;
616 struct omap_dss_dsi_videomode_timings dsi_vm_timings; 627 struct omap_dss_dsi_videomode_timings dsi_vm_timings;
@@ -672,8 +683,6 @@ struct omap_dss_driver {
672 683
673 int (*enable)(struct omap_dss_device *display); 684 int (*enable)(struct omap_dss_device *display);
674 void (*disable)(struct omap_dss_device *display); 685 void (*disable)(struct omap_dss_device *display);
675 int (*suspend)(struct omap_dss_device *display);
676 int (*resume)(struct omap_dss_device *display);
677 int (*run_test)(struct omap_dss_device *display, int test); 686 int (*run_test)(struct omap_dss_device *display, int test);
678 687
679 int (*update)(struct omap_dss_device *dssdev, 688 int (*update)(struct omap_dss_device *dssdev,
@@ -731,6 +740,8 @@ struct omap_dss_driver {
731 740
732}; 741};
733 742
743enum omapdss_version omapdss_get_version(void);
744
734int omap_dss_register_driver(struct omap_dss_driver *); 745int omap_dss_register_driver(struct omap_dss_driver *);
735void omap_dss_unregister_driver(struct omap_dss_driver *); 746void omap_dss_unregister_driver(struct omap_dss_driver *);
736 747
@@ -740,10 +751,19 @@ void omap_dss_put_device(struct omap_dss_device *dssdev);
740struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from); 751struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from);
741struct omap_dss_device *omap_dss_find_device(void *data, 752struct omap_dss_device *omap_dss_find_device(void *data,
742 int (*match)(struct omap_dss_device *dssdev, void *data)); 753 int (*match)(struct omap_dss_device *dssdev, void *data));
754const char *omapdss_get_default_display_name(void);
743 755
744int omap_dss_start_device(struct omap_dss_device *dssdev); 756int omap_dss_start_device(struct omap_dss_device *dssdev);
745void omap_dss_stop_device(struct omap_dss_device *dssdev); 757void omap_dss_stop_device(struct omap_dss_device *dssdev);
746 758
759int dss_feat_get_num_mgrs(void);
760int dss_feat_get_num_ovls(void);
761enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
762enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel);
763enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
764
765
766
747int omap_dss_get_num_overlay_managers(void); 767int omap_dss_get_num_overlay_managers(void);
748struct omap_overlay_manager *omap_dss_get_overlay_manager(int num); 768struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
749 769
@@ -765,9 +785,43 @@ typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
765int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask); 785int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
766int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask); 786int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
767 787
768int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout); 788u32 dispc_read_irqstatus(void);
769int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, 789void dispc_clear_irqstatus(u32 mask);
770 unsigned long timeout); 790u32 dispc_read_irqenable(void);
791void dispc_write_irqenable(u32 mask);
792
793int dispc_request_irq(irq_handler_t handler, void *dev_id);
794void dispc_free_irq(void *dev_id);
795
796int dispc_runtime_get(void);
797void dispc_runtime_put(void);
798
799void dispc_mgr_enable(enum omap_channel channel, bool enable);
800bool dispc_mgr_is_enabled(enum omap_channel channel);
801u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
802u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
803u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel);
804bool dispc_mgr_go_busy(enum omap_channel channel);
805void dispc_mgr_go(enum omap_channel channel);
806void dispc_mgr_set_lcd_config(enum omap_channel channel,
807 const struct dss_lcd_mgr_config *config);
808void dispc_mgr_set_timings(enum omap_channel channel,
809 const struct omap_video_timings *timings);
810void dispc_mgr_setup(enum omap_channel channel,
811 const struct omap_overlay_manager_info *info);
812
813int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel,
814 const struct omap_overlay_info *oi,
815 const struct omap_video_timings *timings,
816 int *x_predecim, int *y_predecim);
817
818int dispc_ovl_enable(enum omap_plane plane, bool enable);
819bool dispc_ovl_enabled(enum omap_plane plane);
820void dispc_ovl_set_channel_out(enum omap_plane plane,
821 enum omap_channel channel);
822int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
823 bool replication, const struct omap_video_timings *mgr_timings,
824 bool mem_to_mem);
771 825
772#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver) 826#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
773#define to_dss_device(x) container_of((x), struct omap_dss_device, dev) 827#define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
@@ -826,4 +880,35 @@ void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev,
826void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev, 880void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
827 struct rfbi_timings *timings); 881 struct rfbi_timings *timings);
828 882
883int omapdss_compat_init(void);
884void omapdss_compat_uninit(void);
885
886struct dss_mgr_ops {
887 void (*start_update)(struct omap_overlay_manager *mgr);
888 int (*enable)(struct omap_overlay_manager *mgr);
889 void (*disable)(struct omap_overlay_manager *mgr);
890 void (*set_timings)(struct omap_overlay_manager *mgr,
891 const struct omap_video_timings *timings);
892 void (*set_lcd_config)(struct omap_overlay_manager *mgr,
893 const struct dss_lcd_mgr_config *config);
894 int (*register_framedone_handler)(struct omap_overlay_manager *mgr,
895 void (*handler)(void *), void *data);
896 void (*unregister_framedone_handler)(struct omap_overlay_manager *mgr,
897 void (*handler)(void *), void *data);
898};
899
900int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops);
901void dss_uninstall_mgr_ops(void);
902
903void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
904 const struct omap_video_timings *timings);
905void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
906 const struct dss_lcd_mgr_config *config);
907int dss_mgr_enable(struct omap_overlay_manager *mgr);
908void dss_mgr_disable(struct omap_overlay_manager *mgr);
909void dss_mgr_start_update(struct omap_overlay_manager *mgr);
910int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr,
911 void (*handler)(void *), void *data);
912void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
913 void (*handler)(void *), void *data);
829#endif 914#endif
diff --git a/arch/arm/plat-omap/include/plat/vrfb.h b/include/video/omapvrfb.h
index 3792bdea2f6d..bb0bd89f8bc6 100644
--- a/arch/arm/plat-omap/include/plat/vrfb.h
+++ b/include/video/omapvrfb.h
@@ -36,6 +36,7 @@ struct vrfb {
36}; 36};
37 37
38#ifdef CONFIG_OMAP2_VRFB 38#ifdef CONFIG_OMAP2_VRFB
39extern bool omap_vrfb_supported(void);
39extern int omap_vrfb_request_ctx(struct vrfb *vrfb); 40extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
40extern void omap_vrfb_release_ctx(struct vrfb *vrfb); 41extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
41extern void omap_vrfb_adjust_size(u16 *width, u16 *height, 42extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
@@ -49,6 +50,7 @@ extern int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot);
49extern void omap_vrfb_restore_context(void); 50extern void omap_vrfb_restore_context(void);
50 51
51#else 52#else
53static inline bool omap_vrfb_supported(void) { return false; }
52static inline int omap_vrfb_request_ctx(struct vrfb *vrfb) { return 0; } 54static inline int omap_vrfb_request_ctx(struct vrfb *vrfb) { return 0; }
53static inline void omap_vrfb_release_ctx(struct vrfb *vrfb) {} 55static inline void omap_vrfb_release_ctx(struct vrfb *vrfb) {}
54static inline void omap_vrfb_adjust_size(u16 *width, u16 *height, 56static inline void omap_vrfb_adjust_size(u16 *width, u16 *height,