diff options
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 | |||
285 | Misc notes | 285 | Misc notes |
286 | ---------- | 286 | ---------- |
287 | 287 | ||
288 | OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator. | 288 | OMAP FB allocates the framebuffer memory using the standard dma allocator. You |
289 | can enable Contiguous Memory Allocator (CONFIG_CMA) to improve the dma | ||
290 | allocator, and if CMA is enabled, you use "cma=" kernel parameter to increase | ||
291 | the global memory area for CMA. | ||
289 | 292 | ||
290 | Using DSI DPLL to generate pixel clock it is possible produce the pixel clock | 293 | Using DSI DPLL to generate pixel clock it is possible produce the pixel clock |
291 | of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI. | 294 | of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI. |
@@ -301,11 +304,6 @@ framebuffer parameters. | |||
301 | Kernel boot arguments | 304 | Kernel boot arguments |
302 | --------------------- | 305 | --------------------- |
303 | 306 | ||
304 | vram=<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 | |||
309 | omapfb.mode=<display>:<mode>[,...] | 307 | omapfb.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 | ||
89 | subsys_initcall(rx51_video_init); | 88 | subsys_initcall(rx51_video_init); |
90 | |||
91 | void __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 | ||
102 | void __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 | ||
37 | extern void rx51_video_mem_init(void); | ||
38 | |||
39 | static struct gpio_led gpio_leds[] = { | 37 | static 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 | ||
113 | static void __init rx51_reserve(void) | 111 | static 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 | ||
103 | static void __init omap4_hdmi_mux_pads(enum omap_hdmi_flags flags) | 103 | static 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 | |||
113 | static 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 | ||
162 | int __init omap_hdmi_init(enum omap_hdmi_flags flags) | 165 | int __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 | ||
292 | static 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 | |||
287 | int __init omap_display_init(struct omap_dss_board_info *board_data) | 321 | int __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 | |||
164 | void omap2_sms_write_rot_control(u32 val, unsigned ctx) | ||
165 | { | ||
166 | sms_write_reg(val, SMS_ROT_CONTROL(ctx)); | ||
167 | } | ||
168 | |||
169 | void omap2_sms_write_rot_size(u32 val, unsigned ctx) | ||
170 | { | ||
171 | sms_write_reg(val, SMS_ROT_SIZE(ctx)); | ||
172 | } | ||
173 | |||
174 | void 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 | ||
26 | void __init omap_reserve(void) | 25 | void __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 | |||
46 | static 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 | |||
54 | static 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 | |||
70 | static 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 | |||
95 | arch_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 | ||
38 | static bool omapfb_lcd_configured; | 100 | static 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, | |||
137 | void omap2_sms_save_context(void); | 134 | void omap2_sms_save_context(void); |
138 | void omap2_sms_restore_context(void); | 135 | void omap2_sms_restore_context(void); |
139 | 136 | ||
140 | void omap2_sms_write_rot_control(u32 val, unsigned ctx); | ||
141 | void omap2_sms_write_rot_size(u32 val, unsigned ctx); | ||
142 | void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx); | ||
143 | |||
144 | #ifdef CONFIG_ARCH_OMAP2 | 137 | #ifdef CONFIG_ARCH_OMAP2 |
145 | 138 | ||
146 | struct memory_timings { | 139 | struct 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 | |||
26 | extern int omap_vram_add_region(unsigned long paddr, size_t size); | ||
27 | extern int omap_vram_free(unsigned long paddr, size_t size); | ||
28 | extern int omap_vram_alloc(size_t size, unsigned long *paddr); | ||
29 | extern int omap_vram_reserve(unsigned long paddr, size_t size); | ||
30 | extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram, | ||
31 | unsigned long *largest_free_block); | ||
32 | |||
33 | #ifdef CONFIG_OMAP2_VRAM | ||
34 | extern void omap_vram_set_sdram_vram(u32 size, u32 start); | ||
35 | |||
36 | extern void omap_vram_reserve_sdram_memblock(void); | ||
37 | #else | ||
38 | static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { } | ||
39 | |||
40 | static 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 | } |
2289 | probe_err0: | 2296 | probe_err0: |
2290 | kfree(vid_dev); | 2297 | kfree(vid_dev); |
2298 | err_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 | |||
341 | bool omap_vout_dss_omap24xx(void) | ||
342 | { | ||
343 | return omapdss_get_version() == OMAPDSS_VER_OMAP24xx; | ||
344 | } | ||
345 | |||
346 | bool 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); |
33 | unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr); | 33 | unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr); |
34 | void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size); | 34 | void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size); |
35 | |||
36 | bool omap_vout_dss_omap24xx(void); | ||
37 | bool 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 @@ | |||
1 | config OMAP2_VRAM | ||
2 | bool | ||
3 | |||
4 | config OMAP2_VRFB | 1 | config 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 @@ | |||
1 | obj-$(CONFIG_OMAP2_VRAM) += vram.o | ||
2 | obj-$(CONFIG_OMAP2_VRFB) += vrfb.o | 1 | obj-$(CONFIG_OMAP2_VRFB) += vrfb.o |
3 | 2 | ||
4 | obj-$(CONFIG_OMAP2_DSS) += dss/ | 3 | obj-$(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 | ||
713 | static 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 | |||
721 | static 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 | |||
734 | static void acx_panel_set_timings(struct omap_dss_device *dssdev, | 713 | static 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 | ||
691 | static 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 | |||
706 | static 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 | |||
719 | err: | ||
720 | mutex_unlock(&drv_data->lock); | ||
721 | |||
722 | return r; | ||
723 | } | ||
724 | |||
725 | static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev, | 691 | static 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 | ||
146 | static 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 | |||
159 | static 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; | ||
173 | err: | ||
174 | mutex_unlock(&ld->lock); | ||
175 | return r; | ||
176 | } | ||
177 | |||
178 | static struct omap_dss_driver lb035q02_driver = { | 146 | static 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 | ||
577 | static 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 | |||
598 | static 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 | |||
625 | static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev, | 577 | static 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 | ||
703 | static int mipid_spi_probe(struct spi_device *spi) | 653 | static 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 | ||
714 | static int mipid_spi_remove(struct spi_device *spi) | 670 | static 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 | }; |
685 | module_spi_driver(mipid_spi_driver); | ||
728 | 686 | ||
729 | static 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 | |||
749 | static 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 | |||
756 | module_init(n8x0_panel_drv_init); | ||
757 | module_exit(n8x0_panel_drv_exit); | ||
758 | MODULE_LICENSE("GPL"); | 687 | MODULE_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 | ||
239 | static 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 | |||
248 | static 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 | |||
261 | static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev) | 239 | static 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 | ||
51 | static struct i2c_device_id picodlp_i2c_id[] = { | 51 | static struct i2c_device_id picodlp_i2c_id[] = { |
52 | { "picodlp_i2c_driver", 0 }, | 52 | { "picodlp_i2c_driver", 0 }, |
53 | { } | ||
53 | }; | 54 | }; |
54 | 55 | ||
55 | struct picodlp_i2c_command { | 56 | struct 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 | ||
506 | static 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 | |||
528 | static 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 | |||
547 | static void picodlp_get_resolution(struct omap_dss_device *dssdev, | 507 | static 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 | ||
197 | static 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 | |||
204 | static 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 | |||
212 | static struct omap_dss_driver sharp_ls_driver = { | 197 | static 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 | ||
1248 | static 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; | ||
1278 | err: | ||
1279 | mutex_unlock(&td->lock); | ||
1280 | return r; | ||
1281 | } | ||
1282 | |||
1283 | static 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; | ||
1313 | err: | ||
1314 | mutex_unlock(&td->lock); | ||
1315 | return r; | ||
1316 | } | ||
1317 | |||
1318 | static void taal_framedone_cb(int err, void *data) | 1248 | static 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 | ||
192 | static 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 | |||
207 | static 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 | |||
223 | static void tfp410_set_timings(struct omap_dss_device *dssdev, | 192 | static 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 | ||
404 | static 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 | |||
415 | static 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 | |||
422 | static int tpo_td043_probe(struct omap_dss_device *dssdev) | 404 | static 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 @@ | |||
1 | menuconfig OMAP2_DSS | 1 | menuconfig 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 | ||
7 | if OMAP2_DSS | 6 | if OMAP2_DSS |
8 | 7 | ||
9 | config OMAP2_VRAM_SIZE | 8 | config 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 | 16 | config OMAP2_DSS_DEBUGFS |
19 | in the board file. | 17 | bool "Debugfs filesystem support" |
20 | 18 | depends on DEBUG_FS | |
21 | config 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 | ||
28 | config OMAP2_DSS_COLLECT_IRQ_STATS | 25 | config 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 | ||
63 | config OMAP4_DSS_HDMI | 60 | config 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 | ||
71 | config OMAP4_DSS_HDMI_AUDIO | 67 | config OMAP4_DSS_HDMI_AUDIO |
72 | bool | 68 | bool |
73 | depends on OMAP4_DSS_HDMI | ||
74 | 69 | ||
75 | config OMAP2_DSS_SDI | 70 | config 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 | ||
85 | config OMAP2_DSS_DSI | 79 | config 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 @@ | |||
1 | obj-$(CONFIG_OMAP2_DSS) += omapdss.o | 1 | obj-$(CONFIG_OMAP2_DSS) += omapdss.o |
2 | # Core DSS files | ||
2 | omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ | 3 | omapdss-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 | ||
6 | omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \ | ||
7 | dispc-compat.o display-sysfs.o | ||
4 | omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o | 8 | omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o |
5 | omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o | 9 | omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o |
6 | omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o | 10 | omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o |
@@ -8,3 +12,4 @@ omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o | |||
8 | omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o | 12 | omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o |
9 | omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ | 13 | omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ |
10 | hdmi_panel.o ti_hdmi_4xxx_ip.o | 14 | hdmi_panel.o ti_hdmi_4xxx_ip.o |
15 | ccflags-$(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 | ||
110 | static struct { | 114 | static 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 | ||
135 | void dss_apply_init(void) | 139 | static 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 | ||
421 | int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) | 423 | static 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 | |||
430 | static 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 | |||
435 | static 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 | |||
460 | static 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 | ||
491 | int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) | 530 | static 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 | ||
764 | void dss_mgr_start_update(struct omap_overlay_manager *mgr) | 788 | static 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 | ||
909 | int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | 944 | static 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 | ||
1008 | int dss_mgr_enable(struct omap_overlay_manager *mgr) | 1043 | static 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 | ||
1043 | out: | 1081 | out: |
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 | ||
1055 | void dss_mgr_disable(struct omap_overlay_manager *mgr) | 1093 | static 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 | ||
1079 | int dss_mgr_set_info(struct omap_overlay_manager *mgr, | 1117 | static 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 | ||
1100 | void dss_mgr_get_info(struct omap_overlay_manager *mgr, | 1138 | static 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 | ||
1113 | int dss_mgr_set_output(struct omap_overlay_manager *mgr, | 1151 | static 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 | ||
1145 | int dss_mgr_unset_output(struct omap_overlay_manager *mgr) | 1183 | static 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 | ||
1192 | void dss_mgr_set_timings(struct omap_overlay_manager *mgr, | 1230 | static 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 | ||
1220 | void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr, | 1258 | static 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 | ||
1239 | int dss_ovl_set_info(struct omap_overlay *ovl, | 1277 | static 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 | ||
1260 | void dss_ovl_get_info(struct omap_overlay *ovl, | 1298 | static 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 | ||
1273 | int dss_ovl_set_manager(struct omap_overlay *ovl, | 1311 | static 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 | |||
1356 | err1: | ||
1357 | dispc_runtime_put(); | ||
1325 | err: | 1358 | err: |
1326 | mutex_unlock(&apply_lock); | 1359 | mutex_unlock(&apply_lock); |
1327 | return r; | 1360 | return r; |
1328 | } | 1361 | } |
1329 | 1362 | ||
1330 | int dss_ovl_unset_manager(struct omap_overlay *ovl) | 1363 | static 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 | ||
1375 | bool dss_ovl_is_enabled(struct omap_overlay *ovl) | 1423 | static 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 | ||
1390 | int dss_ovl_enable(struct omap_overlay *ovl) | 1438 | static 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 | ||
1440 | int dss_ovl_disable(struct omap_overlay *ovl) | 1488 | static 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 | ||
1523 | static 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 | |||
1537 | static 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 | |||
1549 | static 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 | |||
1559 | static int compat_refcnt; | ||
1560 | static DEFINE_MUTEX(compat_init_lock); | ||
1561 | |||
1562 | int 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 | |||
1626 | out: | ||
1627 | mutex_unlock(&compat_init_lock); | ||
1628 | |||
1629 | return 0; | ||
1630 | |||
1631 | err_init_irq: | ||
1632 | dispc_runtime_put(); | ||
1633 | |||
1634 | err_disp_sysfs: | ||
1635 | dss_uninstall_mgr_ops(); | ||
1636 | |||
1637 | err_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 | } | ||
1647 | EXPORT_SYMBOL(omapdss_compat_init); | ||
1648 | |||
1649 | void 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); | ||
1668 | out: | ||
1669 | mutex_unlock(&compat_init_lock); | ||
1670 | } | ||
1671 | EXPORT_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; | |||
53 | module_param_named(def_disp, def_disp_name, charp, 0); | 53 | module_param_named(def_disp, def_disp_name, charp, 0); |
54 | MODULE_PARM_DESC(def_disp, "default display name"); | 54 | MODULE_PARM_DESC(def_disp, "default display name"); |
55 | 55 | ||
56 | #ifdef DEBUG | 56 | const char *omapdss_get_default_display_name(void) |
57 | bool dss_debug; | ||
58 | module_param_named(debug, dss_debug, bool, 0644); | ||
59 | #endif | ||
60 | |||
61 | const char *dss_get_default_display_name(void) | ||
62 | { | 57 | { |
63 | return core.default_display_name; | 58 | return core.default_display_name; |
64 | } | 59 | } |
60 | EXPORT_SYMBOL(omapdss_get_default_display_name); | ||
61 | |||
62 | enum omapdss_version omapdss_get_version(void) | ||
63 | { | ||
64 | struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; | ||
65 | return pdata->version; | ||
66 | } | ||
67 | EXPORT_SYMBOL(omapdss_get_version); | ||
68 | |||
69 | struct 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 | ||
96 | int 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 | |||
111 | int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask) | 104 | int 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) |
142 | static int dss_debug_show(struct seq_file *s, void *unused) | 135 | static 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 */ |
197 | static inline int dss_initialize_debugfs(void) | 190 | static 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 */ |
211 | static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d) | 204 | static 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 */ |
509 | static int (*dss_output_drv_reg_funcs[])(void) __initdata = { | 487 | static 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 | ||
530 | static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = { | 508 | static 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 | |||
44 | struct omap_dispc_isr_data { | ||
45 | omap_dispc_isr_t isr; | ||
46 | void *arg; | ||
47 | u32 mask; | ||
48 | }; | ||
49 | |||
50 | struct dispc_irq_stats { | ||
51 | unsigned long last_reset; | ||
52 | unsigned irq_count; | ||
53 | unsigned irqs[32]; | ||
54 | }; | ||
55 | |||
56 | static 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 | ||
71 | static 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 */ | ||
129 | static 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 | |||
149 | int 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; | ||
196 | err: | ||
197 | spin_unlock_irqrestore(&dispc_compat.irq_lock, flags); | ||
198 | |||
199 | return ret; | ||
200 | } | ||
201 | EXPORT_SYMBOL(omap_dispc_register_isr); | ||
202 | |||
203 | int 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 | } | ||
235 | EXPORT_SYMBOL(omap_dispc_unregister_isr); | ||
236 | |||
237 | static 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. */ | ||
262 | static 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 = ®istered_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 | |||
334 | static 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 | |||
416 | int 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 | |||
458 | void dss_dispc_uninitialize_irq(void) | ||
459 | { | ||
460 | dispc_free_irq(&dispc_compat); | ||
461 | } | ||
462 | |||
463 | static void dispc_mgr_disable_isr(void *data, u32 mask) | ||
464 | { | ||
465 | struct completion *compl = data; | ||
466 | complete(compl); | ||
467 | } | ||
468 | |||
469 | static void dispc_mgr_enable_lcd_out(enum omap_channel channel) | ||
470 | { | ||
471 | dispc_mgr_enable(channel, true); | ||
472 | } | ||
473 | |||
474 | static 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 | |||
513 | static 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 | |||
522 | static 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 | |||
559 | static 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 | |||
618 | void 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 | |||
628 | void 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 | |||
638 | int 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 | |||
21 | void dispc_mgr_enable_sync(enum omap_channel channel); | ||
22 | void dispc_mgr_disable_sync(enum omap_channel channel); | ||
23 | |||
24 | int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, | ||
25 | unsigned long timeout); | ||
26 | |||
27 | int dss_dispc_initialize_irq(void); | ||
28 | void 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 | |||
60 | struct omap_dispc_isr_data { | ||
61 | omap_dispc_isr_t isr; | ||
62 | void *arg; | ||
63 | u32 mask; | ||
64 | }; | ||
65 | |||
66 | enum omap_burst_size { | 49 | enum 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 | ||
78 | struct dispc_irq_stats { | ||
79 | unsigned long last_reset; | ||
80 | unsigned irq_count; | ||
81 | unsigned irqs[32]; | ||
82 | }; | ||
83 | |||
84 | struct dispc_features { | 61 | struct 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 | ||
138 | enum omap_color_component { | 110 | enum 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 | ||
246 | static void _omap_dispc_set_irqs(void); | ||
247 | static unsigned long dispc_plane_pclk_rate(enum omap_plane plane); | 218 | static unsigned long dispc_plane_pclk_rate(enum omap_plane plane); |
248 | static unsigned long dispc_plane_lclk_rate(enum omap_plane plane); | 219 | static 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 | } |
496 | EXPORT_SYMBOL(dispc_runtime_get); | ||
525 | 497 | ||
526 | void dispc_runtime_put(void) | 498 | void 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 | } |
507 | EXPORT_SYMBOL(dispc_runtime_put); | ||
535 | 508 | ||
536 | u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) | 509 | u32 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 | } |
513 | EXPORT_SYMBOL(dispc_mgr_get_vsync_irq); | ||
540 | 514 | ||
541 | u32 dispc_mgr_get_framedone_irq(enum omap_channel channel) | 515 | u32 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 | } |
522 | EXPORT_SYMBOL(dispc_mgr_get_framedone_irq); | ||
523 | |||
524 | u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel) | ||
525 | { | ||
526 | return mgr_desc[channel].sync_lost_irq; | ||
527 | } | ||
528 | EXPORT_SYMBOL(dispc_mgr_get_sync_lost_irq); | ||
545 | 529 | ||
546 | u32 dispc_wb_get_framedone_irq(void) | 530 | u32 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 | } |
539 | EXPORT_SYMBOL(dispc_mgr_go_busy); | ||
555 | 540 | ||
556 | void dispc_mgr_go(enum omap_channel channel) | 541 | void 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 | } |
550 | EXPORT_SYMBOL(dispc_mgr_go); | ||
577 | 551 | ||
578 | bool dispc_wb_go_busy(void) | 552 | bool 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 | } |
954 | EXPORT_SYMBOL(dispc_ovl_set_channel_out); | ||
980 | 955 | ||
981 | static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane) | 956 | static 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 | ||
1078 | static void dispc_mgr_set_cpr_coef(enum omap_channel channel, | 1053 | static 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 | */ |
1994 | static int check_horiz_timing_omap3(enum omap_plane plane, | 1971 | static 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 | ||
2043 | static unsigned long calc_core_clk_five_taps(enum omap_plane plane, | 2018 | static 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 | ||
2084 | static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width, | 2058 | static 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 | ||
2095 | static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width, | 2067 | static 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 | ||
2122 | static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width, | 2093 | static 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 | ||
2144 | static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane, | 2111 | static 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 | ||
2185 | static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane, | 2152 | static 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 | ||
2251 | static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane, | 2218 | static 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 | ||
2293 | static int dispc_ovl_calc_scaling(enum omap_plane plane, | 2260 | static 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 | ||
2330 | int 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 | } | ||
2369 | EXPORT_SYMBOL(dispc_ovl_check); | ||
2370 | |||
2358 | static int dispc_ovl_setup_common(enum omap_plane plane, | 2371 | static 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 | } |
2550 | EXPORT_SYMBOL(dispc_ovl_setup); | ||
2527 | 2551 | ||
2528 | int dispc_wb_setup(const struct omap_dss_writeback_info *wi, | 2552 | int 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 | } |
2611 | EXPORT_SYMBOL(dispc_ovl_enable); | ||
2587 | 2612 | ||
2588 | static void dispc_disable_isr(void *data, u32 mask) | 2613 | bool 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 | } |
2617 | EXPORT_SYMBOL(dispc_ovl_enabled); | ||
2593 | 2618 | ||
2594 | static void _enable_lcd_out(enum omap_channel channel, bool enable) | 2619 | void 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 | 2625 | EXPORT_SYMBOL(dispc_mgr_enable); | |
2601 | static 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 | |||
2640 | static 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 | |||
2647 | static 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 | ||
2716 | bool dispc_mgr_is_enabled(enum omap_channel channel) | 2627 | bool 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 | 2631 | EXPORT_SYMBOL(dispc_mgr_is_enabled); | |
2721 | void 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 | ||
2731 | void dispc_wb_enable(bool enable) | 2633 | void 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 | ||
2765 | bool dispc_wb_is_enabled(void) | 2638 | bool 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 | ||
2772 | void dispc_lcd_enable_signal_polarity(bool act_high) | 2643 | static 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 | ||
2796 | void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable) | 2667 | static 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 | ||
2802 | void dispc_mgr_set_lcd_type_tft(enum omap_channel channel) | 2673 | static 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 | ||
2844 | void dispc_mgr_setup(enum omap_channel channel, | 2715 | void 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 | } |
2728 | EXPORT_SYMBOL(dispc_mgr_setup); | ||
2857 | 2729 | ||
2858 | void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines) | 2730 | static 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 | ||
2883 | void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode) | 2755 | static 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 | ||
2912 | void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable) | 2784 | static 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 | ||
2789 | void 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 | } | ||
2805 | EXPORT_SYMBOL(dispc_mgr_set_lcd_config); | ||
2806 | |||
2917 | static bool _dispc_mgr_size_ok(u16 width, u16 height) | 2807 | static 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 | ||
2923 | static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, | 2813 | static 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? */ |
3014 | void dispc_mgr_set_timings(enum omap_channel channel, | 2904 | void 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 | } |
2944 | EXPORT_SYMBOL(dispc_mgr_set_timings); | ||
3054 | 2945 | ||
3055 | static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, | 2946 | static 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 | ||
3130 | unsigned long dispc_mgr_pclk_rate(enum omap_channel channel) | 3025 | unsigned long dispc_mgr_pclk_rate(enum omap_channel channel) |
@@ -3174,21 +3069,28 @@ unsigned long dispc_core_clk_rate(void) | |||
3174 | 3069 | ||
3175 | static unsigned long dispc_plane_pclk_rate(enum omap_plane plane) | 3070 | static 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 | ||
3182 | static unsigned long dispc_plane_lclk_rate(enum omap_plane plane) | 3082 | static 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 | |||
3192 | static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel) | 3094 | static 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 | ||
3250 | void 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 | |||
3307 | static void dispc_dump_regs(struct seq_file *s) | 3151 | static 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 | ||
3535 | void dispc_mgr_set_clock_div(enum omap_channel channel, | 3379 | void 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 */ | 3404 | u32 dispc_read_irqstatus(void) |
3561 | static 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 | |||
3586 | int 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; | ||
3633 | err: | ||
3634 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | ||
3635 | |||
3636 | return ret; | ||
3637 | } | 3407 | } |
3638 | EXPORT_SYMBOL(omap_dispc_register_isr); | 3408 | EXPORT_SYMBOL(dispc_read_irqstatus); |
3639 | 3409 | ||
3640 | int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask) | 3410 | void 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 | } |
3672 | EXPORT_SYMBOL(omap_dispc_unregister_isr); | 3414 | EXPORT_SYMBOL(dispc_clear_irqstatus); |
3673 | 3415 | ||
3674 | #ifdef DEBUG | 3416 | u32 dispc_read_irqenable(void) |
3675 | static 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 | 3420 | EXPORT_SYMBOL(dispc_read_irqenable); |
3702 | 3421 | ||
3703 | /* Called from dss.c. Note that we don't touch clocks here, | 3422 | void 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. */ | ||
3707 | static 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 = ®istered_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 | |||
3781 | static 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 | |||
3873 | int 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 | |||
3902 | int 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 | |||
3933 | static 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 | } |
3431 | EXPORT_SYMBOL(dispc_write_irqenable); | ||
3957 | 3432 | ||
3958 | void dispc_enable_sidle(void) | 3433 | void 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 | ||
4008 | static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = { | 3488 | static 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 | ||
4020 | static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = { | 3505 | static 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 | ||
4032 | static const struct dispc_features omap44xx_dispc_feats __initconst = { | 3522 | static 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 | |||
3539 | static 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 | ||
4045 | static int __init dispc_init_features(struct device *dev) | 3556 | static 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 | ||
3602 | int 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 | } | ||
3607 | EXPORT_SYMBOL(dispc_request_irq); | ||
3608 | |||
3609 | void dispc_free_irq(void *dev_id) | ||
3610 | { | ||
3611 | devm_free_irq(&dispc.pdev->dev, dispc.irq, dev_id); | ||
3612 | } | ||
3613 | EXPORT_SYMBOL(dispc_free_irq); | ||
3614 | |||
4077 | /* DISPC HW IP initialisation */ | 3615 | /* DISPC HW IP initialisation */ |
4078 | static int __init omap_dispchw_probe(struct platform_device *pdev) | 3616 | static 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 | ||
4158 | err_runtime_get: | 3665 | err_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 | |||
32 | static 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 | |||
41 | static 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 | |||
66 | static 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 | |||
75 | static 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 | |||
96 | static 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 | |||
113 | static 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 | |||
152 | static 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 | |||
163 | static 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 | |||
183 | static 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 | |||
194 | static 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 | |||
215 | static 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 | |||
229 | static 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 | |||
253 | static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR, | ||
254 | display_enabled_show, display_enabled_store); | ||
255 | static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR, | ||
256 | display_tear_show, display_tear_store); | ||
257 | static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR, | ||
258 | display_timings_show, display_timings_store); | ||
259 | static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR, | ||
260 | display_rotate_show, display_rotate_store); | ||
261 | static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR, | ||
262 | display_mirror_show, display_mirror_store); | ||
263 | static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR, | ||
264 | display_wss_show, display_wss_store); | ||
265 | |||
266 | static 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 | |||
276 | int 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 | |||
311 | void 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 | ||
34 | static 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 | |||
43 | static 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 | |||
68 | static 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 | |||
77 | static 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 | |||
98 | static 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 | |||
115 | static 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 | |||
154 | static 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 | |||
165 | static 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 | |||
185 | static 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 | |||
196 | static 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 | |||
217 | static 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 | |||
231 | static 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 | |||
255 | static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR, | ||
256 | display_enabled_show, display_enabled_store); | ||
257 | static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR, | ||
258 | display_tear_show, display_tear_store); | ||
259 | static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR, | ||
260 | display_timings_show, display_timings_store); | ||
261 | static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR, | ||
262 | display_rotate_show, display_rotate_store); | ||
263 | static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR, | ||
264 | display_mirror_show, display_mirror_store); | ||
265 | static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR, | ||
266 | display_wss_show, display_wss_store); | ||
267 | |||
268 | static 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 | |||
278 | void omapdss_default_get_resolution(struct omap_dss_device *dssdev, | 34 | void 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 | } |
321 | EXPORT_SYMBOL(omapdss_default_get_timings); | 77 | EXPORT_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 | */ | ||
328 | static 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 | |||
380 | static 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 | |||
392 | int 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 | |||
436 | void 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 | |||
450 | static int dss_suspend_device(struct device *dev, void *data) | 79 | static 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 | ||
52 | static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk) | 52 | static 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 | ||
61 | static bool dpi_use_dsi_pll(struct omap_dss_device *dssdev) | 80 | static 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 | ||
76 | static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, | 94 | static 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 | ||
243 | err_mgr_enable: | 263 | err_mgr_enable: |
244 | err_set_mode: | 264 | err_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); |
247 | err_dsi_pll_init: | 267 | err_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); |
250 | err_get_dsi: | 270 | err_get_dsi: |
251 | err_src_sel: | 271 | err_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 | } |
360 | EXPORT_SYMBOL(omapdss_dpi_set_data_lines); | 380 | EXPORT_SYMBOL(omapdss_dpi_set_data_lines); |
361 | 381 | ||
382 | static 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 | |||
362 | static int __init dpi_init_display(struct omap_dss_device *dssdev) | 404 | static 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 | ||
389 | static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev) | 444 | static 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 | ||
51 | struct dsi_reg { u16 idx; }; | 50 | struct 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 | ||
537 | static int verbose_irq; | ||
538 | |||
538 | static void print_irq_status(u32 status) | 539 | static 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 | ||
576 | static void print_irq_status_vc(int channel, u32 status) | 571 | static 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 | ||
605 | static void print_irq_status_cio(u32 status) | 596 | static 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 | ||
1120 | static void _dsi_print_reset_status(struct platform_device *dsidev) | 1107 | static 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 | ||
1164 | static inline int dsi_if_enable(struct platform_device *dsidev, bool enable) | 1143 | static 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 | ||
4544 | static void dsi_framedone_irq_callback(void *data, u32 mask) | 4538 | static 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; |
4669 | err1: | 4660 | err1: |
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); |
4673 | err: | 4664 | err: |
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 | ||
4693 | static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) | 4679 | static 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) | |||
4765 | err3: | 4750 | err3: |
4766 | dsi_cio_uninit(dsidev); | 4751 | dsi_cio_uninit(dsidev); |
4767 | err2: | 4752 | err2: |
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 | ||
5152 | static void __init dsi_probe_pdata(struct platform_device *dsidev) | 5139 | static 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 | ||
103 | static inline void dss_write_reg(const struct dss_reg idx, u32 val) | 105 | static 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 | ||
158 | int 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 | |||
156 | void dss_sdi_init(int datapairs) | 173 | void 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 | ||
306 | void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src) | 323 | static 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 */ | ||
454 | int 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 | |||
434 | int dss_set_clock_div(struct dss_clock_info *cinfo) | 476 | int 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 | ||
510 | unsigned long dss_get_dispc_clk_rate(void) | ||
511 | { | ||
512 | return dss.dss_clk_rate; | ||
513 | } | ||
514 | |||
515 | static 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 | |||
464 | int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo, | 545 | int 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) |
754 | void dss_debug_dump_clocks(struct seq_file *s) | 835 | void 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 | ||
799 | static int __init dss_init_features(struct device *dev) | 880 | static 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 | ||
889 | err_runtime_get: | 994 | err_runtime_get: |
890 | pm_runtime_disable(&pdev->dev); | 995 | pm_runtime_disable(&pdev->dev); |
996 | err_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 |
31 | extern 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; | |||
186 | struct platform_device; | 162 | struct platform_device; |
187 | 163 | ||
188 | /* core */ | 164 | /* core */ |
189 | const char *dss_get_default_display_name(void); | 165 | struct platform_device *dss_get_core_pdev(void); |
190 | struct bus_type *dss_get_bus(void); | 166 | struct bus_type *dss_get_bus(void); |
191 | struct regulator *dss_get_vdds_dsi(void); | 167 | struct regulator *dss_get_vdds_dsi(void); |
192 | struct regulator *dss_get_vdds_sdi(void); | 168 | struct regulator *dss_get_vdds_sdi(void); |
193 | int dss_get_ctx_loss_count(struct device *dev); | ||
194 | int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask); | 169 | int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask); |
195 | void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask); | 170 | void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask); |
196 | int dss_set_min_bus_tput(struct device *dev, unsigned long tput); | 171 | int dss_set_min_bus_tput(struct device *dev, unsigned long tput); |
@@ -204,55 +179,18 @@ void dss_put_device(struct omap_dss_device *dssdev); | |||
204 | void dss_copy_device_pdata(struct omap_dss_device *dst, | 179 | void 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 */ | ||
208 | void dss_apply_init(void); | ||
209 | int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr); | ||
210 | int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl); | ||
211 | void dss_mgr_start_update(struct omap_overlay_manager *mgr); | ||
212 | int omap_dss_mgr_apply(struct omap_overlay_manager *mgr); | ||
213 | |||
214 | int dss_mgr_enable(struct omap_overlay_manager *mgr); | ||
215 | void dss_mgr_disable(struct omap_overlay_manager *mgr); | ||
216 | int dss_mgr_set_info(struct omap_overlay_manager *mgr, | ||
217 | struct omap_overlay_manager_info *info); | ||
218 | void dss_mgr_get_info(struct omap_overlay_manager *mgr, | ||
219 | struct omap_overlay_manager_info *info); | ||
220 | int dss_mgr_set_device(struct omap_overlay_manager *mgr, | ||
221 | struct omap_dss_device *dssdev); | ||
222 | int dss_mgr_unset_device(struct omap_overlay_manager *mgr); | ||
223 | int dss_mgr_set_output(struct omap_overlay_manager *mgr, | ||
224 | struct omap_dss_output *output); | ||
225 | int dss_mgr_unset_output(struct omap_overlay_manager *mgr); | ||
226 | void dss_mgr_set_timings(struct omap_overlay_manager *mgr, | ||
227 | const struct omap_video_timings *timings); | ||
228 | void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr, | ||
229 | const struct dss_lcd_mgr_config *config); | ||
230 | const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr); | ||
231 | |||
232 | bool dss_ovl_is_enabled(struct omap_overlay *ovl); | ||
233 | int dss_ovl_enable(struct omap_overlay *ovl); | ||
234 | int dss_ovl_disable(struct omap_overlay *ovl); | ||
235 | int dss_ovl_set_info(struct omap_overlay *ovl, | ||
236 | struct omap_overlay_info *info); | ||
237 | void dss_ovl_get_info(struct omap_overlay *ovl, | ||
238 | struct omap_overlay_info *info); | ||
239 | int dss_ovl_set_manager(struct omap_overlay *ovl, | ||
240 | struct omap_overlay_manager *mgr); | ||
241 | int dss_ovl_unset_manager(struct omap_overlay *ovl); | ||
242 | |||
243 | /* output */ | 182 | /* output */ |
244 | void dss_register_output(struct omap_dss_output *out); | 183 | void dss_register_output(struct omap_dss_output *out); |
245 | void dss_unregister_output(struct omap_dss_output *out); | 184 | void dss_unregister_output(struct omap_dss_output *out); |
246 | struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev); | ||
247 | 185 | ||
248 | /* display */ | 186 | /* display */ |
249 | int dss_suspend_all_devices(void); | 187 | int dss_suspend_all_devices(void); |
250 | int dss_resume_all_devices(void); | 188 | int dss_resume_all_devices(void); |
251 | void dss_disable_all_devices(void); | 189 | void dss_disable_all_devices(void); |
252 | 190 | ||
253 | int dss_init_device(struct platform_device *pdev, | 191 | int display_init_sysfs(struct platform_device *pdev, |
254 | struct omap_dss_device *dssdev); | 192 | struct omap_dss_device *dssdev); |
255 | void dss_uninit_device(struct platform_device *pdev, | 193 | void 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); | |||
299 | int dss_init_platform_driver(void) __init; | 237 | int dss_init_platform_driver(void) __init; |
300 | void dss_uninit_platform_driver(void); | 238 | void dss_uninit_platform_driver(void); |
301 | 239 | ||
240 | unsigned long dss_get_dispc_clk_rate(void); | ||
302 | int dss_dpi_select_source(enum omap_channel channel); | 241 | int dss_dpi_select_source(enum omap_channel channel); |
303 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); | 242 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); |
304 | enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); | 243 | enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); |
305 | const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); | 244 | const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); |
306 | void dss_dump_clocks(struct seq_file *s); | 245 | void 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) |
309 | void dss_debug_dump_clocks(struct seq_file *s); | 248 | void dss_debug_dump_clocks(struct seq_file *s); |
310 | #endif | 249 | #endif |
311 | 250 | ||
251 | int dss_get_ctx_loss_count(void); | ||
252 | |||
312 | void dss_sdi_init(int datapairs); | 253 | void dss_sdi_init(int datapairs); |
313 | int dss_sdi_enable(void); | 254 | int dss_sdi_enable(void); |
314 | void dss_sdi_disable(void); | 255 | void dss_sdi_disable(void); |
315 | 256 | ||
316 | void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src); | ||
317 | void dss_select_dsi_clk_source(int dsi_module, | 257 | void dss_select_dsi_clk_source(int dsi_module, |
318 | enum omap_dss_clk_source clk_src); | 258 | enum omap_dss_clk_source clk_src); |
319 | void dss_select_lcd_clk_source(enum omap_channel channel, | 259 | void dss_select_lcd_clk_source(enum omap_channel channel, |
@@ -326,6 +266,7 @@ void dss_set_venc_output(enum omap_dss_venc_type type); | |||
326 | void dss_set_dac_pwrdn_bgz(bool enable); | 266 | void dss_set_dac_pwrdn_bgz(bool enable); |
327 | 267 | ||
328 | unsigned long dss_get_dpll4_rate(void); | 268 | unsigned long dss_get_dpll4_rate(void); |
269 | int dss_calc_clock_rates(struct dss_clock_info *cinfo); | ||
329 | int dss_set_clock_div(struct dss_clock_info *cinfo); | 270 | int dss_set_clock_div(struct dss_clock_info *cinfo); |
330 | int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo, | 271 | int 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 | } |
414 | static inline struct platform_device *dsi_get_dsidev_from_id(int module) | 355 | static 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; | |||
427 | int dispc_init_platform_driver(void) __init; | 366 | int dispc_init_platform_driver(void) __init; |
428 | void dispc_uninit_platform_driver(void) __exit; | 367 | void dispc_uninit_platform_driver(void) __exit; |
429 | void dispc_dump_clocks(struct seq_file *s); | 368 | void dispc_dump_clocks(struct seq_file *s); |
430 | void dispc_irq_handler(void); | ||
431 | |||
432 | int dispc_runtime_get(void); | ||
433 | void dispc_runtime_put(void); | ||
434 | 369 | ||
435 | void dispc_enable_sidle(void); | 370 | void dispc_enable_sidle(void); |
436 | void dispc_disable_sidle(void); | 371 | void dispc_disable_sidle(void); |
437 | 372 | ||
438 | void dispc_lcd_enable_signal_polarity(bool act_high); | ||
439 | void dispc_lcd_enable_signal(bool enable); | 373 | void dispc_lcd_enable_signal(bool enable); |
440 | void dispc_pck_free_enable(bool enable); | 374 | void dispc_pck_free_enable(bool enable); |
441 | void dispc_enable_fifomerge(bool enable); | 375 | void dispc_enable_fifomerge(bool enable); |
@@ -455,36 +389,14 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); | |||
455 | void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, | 389 | void 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); |
458 | int 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); | ||
461 | int dispc_ovl_enable(enum omap_plane plane, bool enable); | ||
462 | void dispc_ovl_set_channel_out(enum omap_plane plane, | ||
463 | enum omap_channel channel); | ||
464 | |||
465 | void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable); | ||
466 | u32 dispc_mgr_get_vsync_irq(enum omap_channel channel); | ||
467 | u32 dispc_mgr_get_framedone_irq(enum omap_channel channel); | ||
468 | bool dispc_mgr_go_busy(enum omap_channel channel); | ||
469 | void dispc_mgr_go(enum omap_channel channel); | ||
470 | bool dispc_mgr_is_enabled(enum omap_channel channel); | ||
471 | void dispc_mgr_enable(enum omap_channel channel, bool enable); | ||
472 | bool dispc_mgr_is_channel_enabled(enum omap_channel channel); | ||
473 | void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode); | ||
474 | void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable); | ||
475 | void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines); | ||
476 | void dispc_mgr_set_lcd_type_tft(enum omap_channel channel); | ||
477 | void dispc_mgr_set_timings(enum omap_channel channel, | ||
478 | struct omap_video_timings *timings); | ||
479 | unsigned long dispc_mgr_lclk_rate(enum omap_channel channel); | 393 | unsigned long dispc_mgr_lclk_rate(enum omap_channel channel); |
480 | unsigned long dispc_mgr_pclk_rate(enum omap_channel channel); | 394 | unsigned long dispc_mgr_pclk_rate(enum omap_channel channel); |
481 | unsigned long dispc_core_clk_rate(void); | 395 | unsigned long dispc_core_clk_rate(void); |
482 | void dispc_mgr_set_clock_div(enum omap_channel channel, | 396 | void dispc_mgr_set_clock_div(enum omap_channel channel, |
483 | struct dispc_clock_info *cinfo); | 397 | const struct dispc_clock_info *cinfo); |
484 | int dispc_mgr_get_clock_div(enum omap_channel channel, | 398 | int dispc_mgr_get_clock_div(enum omap_channel channel, |
485 | struct dispc_clock_info *cinfo); | 399 | struct dispc_clock_info *cinfo); |
486 | void dispc_mgr_setup(enum omap_channel channel, | ||
487 | struct omap_overlay_manager_info *info); | ||
488 | 400 | ||
489 | u32 dispc_wb_get_framedone_irq(void); | 401 | u32 dispc_wb_get_framedone_irq(void); |
490 | bool dispc_wb_go_busy(void); | 402 | bool dispc_wb_go_busy(void); |
@@ -536,6 +448,8 @@ static inline unsigned long hdmi_get_pixel_clock(void) | |||
536 | #endif | 448 | #endif |
537 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); | 449 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); |
538 | void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); | 450 | void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); |
451 | int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev); | ||
452 | void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev); | ||
539 | void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev, | 453 | void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev, |
540 | struct omap_video_timings *timings); | 454 | struct omap_video_timings *timings); |
541 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | 455 | int 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 | ||
437 | static const struct dss_param_range omap3_dss_param_range[] = { | 435 | static 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 | ||
453 | static const struct dss_param_range omap4_dss_param_range[] = { | 449 | static 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 | ||
469 | static const struct dss_param_range omap5_dss_param_range[] = { | 463 | static 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 | ||
485 | static const enum dss_feat_id omap2_dss_feat_list[] = { | 477 | static 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 | ||
828 | void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data) | 821 | void 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 | } |
843 | EXPORT_SYMBOL(dss_feat_get_num_mgrs); | ||
840 | 844 | ||
841 | int dss_feat_get_num_ovls(void) | 845 | int 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 | } |
849 | EXPORT_SYMBOL(dss_feat_get_num_ovls); | ||
845 | 850 | ||
846 | int dss_feat_get_num_wbs(void) | 851 | int 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 | } |
870 | EXPORT_SYMBOL(dss_feat_get_supported_displays); | ||
865 | 871 | ||
866 | enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel) | 872 | enum 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 | } |
876 | EXPORT_SYMBOL(dss_feat_get_supported_outputs); | ||
870 | 877 | ||
871 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane) | 878 | enum 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 | } |
882 | EXPORT_SYMBOL(dss_feat_get_supported_color_modes); | ||
875 | 883 | ||
876 | enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane) | 884 | enum 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 | ||
932 | void dss_features_init(void) | 940 | void 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 */ |
106 | int dss_feat_get_num_mgrs(void); | ||
107 | int dss_feat_get_num_ovls(void); | ||
108 | int dss_feat_get_num_wbs(void); | 104 | int dss_feat_get_num_wbs(void); |
109 | unsigned long dss_feat_get_param_min(enum dss_range_param param); | 105 | unsigned long dss_feat_get_param_min(enum dss_range_param param); |
110 | unsigned long dss_feat_get_param_max(enum dss_range_param param); | 106 | unsigned long dss_feat_get_param_max(enum dss_range_param param); |
111 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); | ||
112 | enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel); | ||
113 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); | ||
114 | enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane); | 107 | enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane); |
115 | bool dss_feat_color_mode_supported(enum omap_plane plane, | 108 | bool 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 | ||
124 | bool dss_has_feature(enum dss_feat_id id); | 117 | bool dss_has_feature(enum dss_feat_id id); |
125 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); | 118 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); |
126 | void dss_features_init(void); | 119 | void dss_features_init(enum omapdss_version version); |
127 | #if defined(CONFIG_OMAP4_DSS_HDMI) | 120 | #if defined(CONFIG_OMAP4_DSS_HDMI) |
128 | void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data); | 121 | void 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 @@ | |||
60 | static struct { | 60 | static 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 | ||
300 | static int hdmi_runtime_get(void) | 307 | static 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 | ||
358 | static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev) | 369 | static 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 | ||
503 | static int hdmi_power_on(struct omap_dss_device *dssdev) | 515 | static 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 | |||
538 | err_runtime_get: | ||
539 | regulator_disable(hdmi.vdda_hdmi_dac_reg); | ||
540 | err_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 | |||
546 | static 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 | |||
554 | static 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: | |||
582 | err_phy_enable: | 612 | err_phy_enable: |
583 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); | 613 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); |
584 | err_pll_enable: | 614 | err_pll_enable: |
585 | hdmi_runtime_put(); | 615 | hdmi_power_off_core(dssdev); |
586 | err_runtime_get: | ||
587 | regulator_disable(hdmi.vdda_hdmi_dac_reg); | ||
588 | err_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 | ||
594 | static void hdmi_power_off(struct omap_dss_device *dssdev) | 619 | static 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 | ||
611 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | 632 | int 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 | ||
768 | int 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 | |||
787 | err0: | ||
788 | mutex_unlock(&hdmi.lock); | ||
789 | return r; | ||
790 | } | ||
791 | |||
792 | void 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 | |||
747 | static int hdmi_get_clocks(struct platform_device *pdev) | 803 | static 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) | |||
912 | static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev) | 968 | static 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 */ |
1000 | static int __init omapdss_hdmihw_probe(struct platform_device *pdev) | 1066 | static 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 | |||
1116 | err_panel_init: | ||
1117 | hdmi_put_clocks(); | ||
1118 | return r; | ||
1047 | } | 1119 | } |
1048 | 1120 | ||
1049 | static int __exit hdmi_remove_child(struct device *dev, void *data) | 1121 | static 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 | ||
283 | static 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 | |||
303 | err: | ||
304 | mutex_unlock(&hdmi.lock); | ||
305 | |||
306 | return r; | ||
307 | } | ||
308 | |||
309 | static 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 | |||
329 | err: | ||
330 | mutex_unlock(&hdmi.lock); | ||
331 | |||
332 | return r; | ||
333 | } | ||
334 | |||
335 | static void hdmi_get_timings(struct omap_dss_device *dssdev, | 283 | static 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, | |||
379 | static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len) | 327 | static 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); | ||
396 | err: | 346 | err: |
397 | mutex_unlock(&hdmi.lock); | 347 | mutex_unlock(&hdmi.lock); |
398 | 348 | ||
@@ -402,20 +352,22 @@ err: | |||
402 | static bool hdmi_detect(struct omap_dss_device *dssdev) | 352 | static 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); | ||
419 | err: | 371 | err: |
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 | ||
462 | void hdmi_panel_exit(void) | 410 | void 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 @@ | |||
36 | static int num_managers; | 36 | static int num_managers; |
37 | static struct omap_overlay_manager *managers; | 37 | static struct omap_overlay_manager *managers; |
38 | 38 | ||
39 | static 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 | |||
44 | static 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 | |||
69 | int dss_init_overlay_managers(struct platform_device *pdev) | 39 | int 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 | ||
117 | struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev) | 117 | static const struct dss_mgr_ops *dss_mgr_ops; |
118 | |||
119 | int 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: | 128 | EXPORT_SYMBOL(dss_install_mgr_ops); |
127 | out = omap_dss_get_output(OMAP_DSS_OUTPUT_DBI); | 129 | |
128 | break; | 130 | void 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: | 134 | EXPORT_SYMBOL(dss_uninstall_mgr_ops); |
133 | out = omap_dss_get_output(OMAP_DSS_OUTPUT_VENC); | 135 | |
134 | break; | 136 | void 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 : | 141 | EXPORT_SYMBOL(dss_mgr_set_timings); |
140 | OMAP_DSS_OUTPUT_DSI2; | 142 | |
141 | out = omap_dss_get_output(id); | 143 | void 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 | } |
148 | EXPORT_SYMBOL(dss_mgr_set_lcd_config); | ||
149 | |||
150 | int dss_mgr_enable(struct omap_overlay_manager *mgr) | ||
151 | { | ||
152 | return dss_mgr_ops->enable(mgr); | ||
153 | } | ||
154 | EXPORT_SYMBOL(dss_mgr_enable); | ||
155 | |||
156 | void dss_mgr_disable(struct omap_overlay_manager *mgr) | ||
157 | { | ||
158 | dss_mgr_ops->disable(mgr); | ||
159 | } | ||
160 | EXPORT_SYMBOL(dss_mgr_disable); | ||
146 | 161 | ||
147 | return out; | 162 | void dss_mgr_start_update(struct omap_overlay_manager *mgr) |
163 | { | ||
164 | dss_mgr_ops->start_update(mgr); | ||
165 | } | ||
166 | EXPORT_SYMBOL(dss_mgr_start_update); | ||
167 | |||
168 | int 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 | } | ||
173 | EXPORT_SYMBOL(dss_mgr_register_framedone_handler); | ||
174 | |||
175 | void 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 | } |
180 | EXPORT_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 @@ | |||
38 | static int num_overlays; | 38 | static int num_overlays; |
39 | static struct omap_overlay *overlays; | 39 | static struct omap_overlay *overlays; |
40 | 40 | ||
41 | static 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 | |||
48 | int omap_dss_get_num_overlays(void) | 41 | int 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 | ||
345 | static void framedone_callback(void *data, u32 mask) | 345 | static 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 | ||
934 | void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev) | 934 | void 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) | |||
950 | static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev) | 952 | static 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) | |||
205 | static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev) | 205 | static 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); | |||
183 | void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data); | 185 | void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data); |
184 | int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data, | 186 | int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data, |
185 | struct omap_dss_audio *audio); | 187 | struct omap_dss_audio *audio); |
188 | int 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 | |||
1422 | int 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) | |||
744 | static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev) | 744 | static 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 | ||
173 | static int venc_panel_suspend(struct omap_dss_device *dssdev) | ||
174 | { | ||
175 | venc_panel_disable(dssdev); | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static int venc_panel_resume(struct omap_dss_device *dssdev) | ||
180 | { | ||
181 | return venc_panel_enable(dssdev); | ||
182 | } | ||
183 | |||
184 | static void venc_panel_set_timings(struct omap_dss_device *dssdev, | 167 | static 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 | ||
282 | static int omapfb_update_window_nolock(struct fb_info *fbi, | 286 | static 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 */ | ||
303 | int 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 | } | ||
321 | EXPORT_SYMBOL(omapfb_update_window); | ||
322 | |||
323 | int omapfb_set_update_mode(struct fb_info *fbi, | 306 | int 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 | ||
1889 | static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) | 1884 | static 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 | ||
2376 | static 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 | |||
2375 | static int __init omapfb_probe(struct platform_device *pdev) | 2425 | static 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 | ||
2511 | cleanup: | 2574 | cleanup: |
2512 | omapfb_free_resources(fbdev); | 2575 | omapfb_free_resources(fbdev); |
2576 | omapdss_compat_uninit(); | ||
2513 | err0: | 2577 | err0: |
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 | ||
50 | struct omapfb2_mem_region { | 52 | struct 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 | ||
125 | int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg); | 130 | int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg); |
126 | 131 | ||
127 | int omapfb_update_window(struct fb_info *fbi, | ||
128 | u32 x, u32 y, u32 w, u32 h); | ||
129 | |||
130 | int dss_mode_to_fb_mode(enum omap_color_mode dssmode, | 132 | int 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); | |||
144 | static inline struct omap_dss_device *fb2display(struct fb_info *fbi) | 146 | static 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 | ||
159 | static inline struct omapfb_display_data *get_display_data( | 161 | static 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 | |||
48 | static bool vram_initialized; | ||
49 | static int postponed_cnt; | ||
50 | static struct { | ||
51 | unsigned long paddr; | ||
52 | size_t size; | ||
53 | } postponed_regions[MAX_POSTPONED_REGIONS]; | ||
54 | |||
55 | struct vram_alloc { | ||
56 | struct list_head list; | ||
57 | unsigned long paddr; | ||
58 | unsigned pages; | ||
59 | }; | ||
60 | |||
61 | struct vram_region { | ||
62 | struct list_head list; | ||
63 | struct list_head alloc_list; | ||
64 | unsigned long paddr; | ||
65 | unsigned pages; | ||
66 | }; | ||
67 | |||
68 | static DEFINE_MUTEX(region_mutex); | ||
69 | static LIST_HEAD(region_list); | ||
70 | |||
71 | static 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 | ||
88 | static void omap_vram_free_region(struct vram_region *vr) | ||
89 | { | ||
90 | list_del(&vr->list); | ||
91 | kfree(vr); | ||
92 | } | ||
93 | #endif | ||
94 | |||
95 | static 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 | |||
119 | static void omap_vram_free_allocation(struct vram_alloc *va) | ||
120 | { | ||
121 | list_del(&va->list); | ||
122 | kfree(va); | ||
123 | } | ||
124 | |||
125 | int 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, ®ion_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 | |||
154 | int 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(®ion_mutex); | ||
165 | |||
166 | list_for_each_entry(rm, ®ion_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(®ion_mutex); | ||
177 | return -EINVAL; | ||
178 | |||
179 | found: | ||
180 | omap_vram_free_allocation(alloc); | ||
181 | |||
182 | mutex_unlock(®ion_mutex); | ||
183 | return 0; | ||
184 | } | ||
185 | EXPORT_SYMBOL(omap_vram_free); | ||
186 | |||
187 | static 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, ®ion_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; | ||
220 | found: | ||
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 | |||
232 | int 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(®ion_mutex); | ||
243 | |||
244 | r = _omap_vram_reserve(paddr, pages); | ||
245 | |||
246 | mutex_unlock(®ion_mutex); | ||
247 | |||
248 | return r; | ||
249 | } | ||
250 | EXPORT_SYMBOL(omap_vram_reserve); | ||
251 | |||
252 | static 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, ®ion_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); | ||
274 | found: | ||
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 | |||
292 | int 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(®ion_mutex); | ||
305 | |||
306 | r = _omap_vram_alloc(pages, paddr); | ||
307 | |||
308 | mutex_unlock(®ion_mutex); | ||
309 | |||
310 | return r; | ||
311 | } | ||
312 | EXPORT_SYMBOL(omap_vram_alloc); | ||
313 | |||
314 | void 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(®ion_mutex); | ||
326 | |||
327 | list_for_each_entry(vr, ®ion_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(®ion_mutex); | ||
349 | } | ||
350 | EXPORT_SYMBOL(omap_vram_get_info); | ||
351 | |||
352 | #if defined(CONFIG_DEBUG_FS) | ||
353 | static 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(®ion_mutex); | ||
360 | |||
361 | list_for_each_entry(vr, ®ion_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(®ion_mutex); | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static int vram_debug_open(struct inode *inode, struct file *file) | ||
381 | { | ||
382 | return single_open(file, vram_debug_show, inode->i_private); | ||
383 | } | ||
384 | |||
385 | static 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 | |||
392 | static 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 | |||
405 | static __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 | |||
423 | arch_initcall(omap_vram_init); | ||
424 | |||
425 | /* boottime vram alloc stuff */ | ||
426 | |||
427 | /* set from board file */ | ||
428 | static u32 omap_vram_sdram_start __initdata; | ||
429 | static u32 omap_vram_sdram_size __initdata; | ||
430 | |||
431 | /* set from kernel cmdline */ | ||
432 | static u32 omap_vram_def_sdram_size __initdata; | ||
433 | static u32 omap_vram_def_sdram_start __initdata; | ||
434 | |||
435 | static 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 | } | ||
442 | early_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 | */ | ||
448 | void __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 | |||
510 | void __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 */ |
58 | static unsigned long ctx_map; | 57 | static unsigned long ctx_map; |
59 | 58 | ||
59 | struct vrfb_ctx { | ||
60 | u32 base; | ||
61 | u32 physical_ba; | ||
62 | u32 control; | ||
63 | u32 size; | ||
64 | }; | ||
65 | |||
60 | static DEFINE_MUTEX(ctx_lock); | 66 | static 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 | */ |
68 | static struct { | 74 | |
69 | u32 physical_ba; | 75 | static void __iomem *vrfb_base; |
70 | u32 control; | 76 | |
71 | u32 size; | 77 | static int num_ctxs; |
72 | } vrfb_hw_context[VRFB_NUM_CTXS]; | 78 | static struct vrfb_ctx *ctxs; |
79 | |||
80 | static bool vrfb_loaded; | ||
81 | |||
82 | static void omap2_sms_write_rot_control(u32 val, unsigned ctx) | ||
83 | { | ||
84 | __raw_writel(val, vrfb_base + SMS_ROT_CONTROL(ctx)); | ||
85 | } | ||
86 | |||
87 | static void omap2_sms_write_rot_size(u32 val, unsigned ctx) | ||
88 | { | ||
89 | __raw_writel(val, vrfb_base + SMS_ROT_SIZE(ctx)); | ||
90 | } | ||
91 | |||
92 | static 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 | ||
74 | static inline void restore_hw_context(int ctx) | 97 | static 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 | ||
81 | static u32 get_image_width_roundup(u16 width, u8 bytespp) | 104 | static 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 | } |
316 | EXPORT_SYMBOL(omap_vrfb_request_ctx); | 339 | EXPORT_SYMBOL(omap_vrfb_request_ctx); |
340 | |||
341 | bool omap_vrfb_supported(void) | ||
342 | { | ||
343 | return vrfb_loaded; | ||
344 | } | ||
345 | EXPORT_SYMBOL(omap_vrfb_supported); | ||
346 | |||
347 | static 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 | |||
391 | static void __exit vrfb_remove(struct platform_device *pdev) | ||
392 | { | ||
393 | vrfb_loaded = false; | ||
394 | } | ||
395 | |||
396 | static struct platform_driver vrfb_driver = { | ||
397 | .driver.name = "omapvrfb", | ||
398 | .remove = __exit_p(vrfb_remove), | ||
399 | }; | ||
400 | |||
401 | static int __init vrfb_init(void) | ||
402 | { | ||
403 | return platform_driver_probe(&vrfb_driver, &vrfb_probe); | ||
404 | } | ||
405 | |||
406 | static void __exit vrfb_exit(void) | ||
407 | { | ||
408 | platform_driver_unregister(&vrfb_driver); | ||
409 | } | ||
410 | |||
411 | module_init(vrfb_init); | ||
412 | module_exit(vrfb_exit); | ||
413 | |||
414 | MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); | ||
415 | MODULE_DESCRIPTION("OMAP VRFB"); | ||
416 | MODULE_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 | ||
56 | struct omap_dss_device; | 57 | struct omap_dss_device; |
57 | struct omap_overlay_manager; | 58 | struct omap_overlay_manager; |
59 | struct dss_lcd_mgr_config; | ||
58 | struct snd_aes_iec958; | 60 | struct snd_aes_iec958; |
59 | struct snd_cea_861_aud_if; | 61 | struct snd_cea_861_aud_if; |
60 | 62 | ||
@@ -158,7 +160,6 @@ enum omap_display_caps { | |||
158 | enum omap_dss_display_state { | 160 | enum 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 | ||
164 | enum omap_dss_audio_state { | 165 | enum omap_dss_audio_state { |
@@ -314,6 +315,19 @@ int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel); | |||
314 | int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel); | 315 | int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel); |
315 | void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel); | 316 | void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel); |
316 | 317 | ||
318 | enum 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 */ |
318 | struct omap_dss_board_info { | 332 | struct 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 | ||
743 | enum omapdss_version omapdss_get_version(void); | ||
744 | |||
734 | int omap_dss_register_driver(struct omap_dss_driver *); | 745 | int omap_dss_register_driver(struct omap_dss_driver *); |
735 | void omap_dss_unregister_driver(struct omap_dss_driver *); | 746 | void omap_dss_unregister_driver(struct omap_dss_driver *); |
736 | 747 | ||
@@ -740,10 +751,19 @@ void omap_dss_put_device(struct omap_dss_device *dssdev); | |||
740 | struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from); | 751 | struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from); |
741 | struct omap_dss_device *omap_dss_find_device(void *data, | 752 | struct 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)); |
754 | const char *omapdss_get_default_display_name(void); | ||
743 | 755 | ||
744 | int omap_dss_start_device(struct omap_dss_device *dssdev); | 756 | int omap_dss_start_device(struct omap_dss_device *dssdev); |
745 | void omap_dss_stop_device(struct omap_dss_device *dssdev); | 757 | void omap_dss_stop_device(struct omap_dss_device *dssdev); |
746 | 758 | ||
759 | int dss_feat_get_num_mgrs(void); | ||
760 | int dss_feat_get_num_ovls(void); | ||
761 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); | ||
762 | enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel); | ||
763 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); | ||
764 | |||
765 | |||
766 | |||
747 | int omap_dss_get_num_overlay_managers(void); | 767 | int omap_dss_get_num_overlay_managers(void); |
748 | struct omap_overlay_manager *omap_dss_get_overlay_manager(int num); | 768 | struct 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); | |||
765 | int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask); | 785 | int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask); |
766 | int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask); | 786 | int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask); |
767 | 787 | ||
768 | int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout); | 788 | u32 dispc_read_irqstatus(void); |
769 | int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, | 789 | void dispc_clear_irqstatus(u32 mask); |
770 | unsigned long timeout); | 790 | u32 dispc_read_irqenable(void); |
791 | void dispc_write_irqenable(u32 mask); | ||
792 | |||
793 | int dispc_request_irq(irq_handler_t handler, void *dev_id); | ||
794 | void dispc_free_irq(void *dev_id); | ||
795 | |||
796 | int dispc_runtime_get(void); | ||
797 | void dispc_runtime_put(void); | ||
798 | |||
799 | void dispc_mgr_enable(enum omap_channel channel, bool enable); | ||
800 | bool dispc_mgr_is_enabled(enum omap_channel channel); | ||
801 | u32 dispc_mgr_get_vsync_irq(enum omap_channel channel); | ||
802 | u32 dispc_mgr_get_framedone_irq(enum omap_channel channel); | ||
803 | u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel); | ||
804 | bool dispc_mgr_go_busy(enum omap_channel channel); | ||
805 | void dispc_mgr_go(enum omap_channel channel); | ||
806 | void dispc_mgr_set_lcd_config(enum omap_channel channel, | ||
807 | const struct dss_lcd_mgr_config *config); | ||
808 | void dispc_mgr_set_timings(enum omap_channel channel, | ||
809 | const struct omap_video_timings *timings); | ||
810 | void dispc_mgr_setup(enum omap_channel channel, | ||
811 | const struct omap_overlay_manager_info *info); | ||
812 | |||
813 | int 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 | |||
818 | int dispc_ovl_enable(enum omap_plane plane, bool enable); | ||
819 | bool dispc_ovl_enabled(enum omap_plane plane); | ||
820 | void dispc_ovl_set_channel_out(enum omap_plane plane, | ||
821 | enum omap_channel channel); | ||
822 | int 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, | |||
826 | void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev, | 880 | void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev, |
827 | struct rfbi_timings *timings); | 881 | struct rfbi_timings *timings); |
828 | 882 | ||
883 | int omapdss_compat_init(void); | ||
884 | void omapdss_compat_uninit(void); | ||
885 | |||
886 | struct 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 | |||
900 | int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops); | ||
901 | void dss_uninstall_mgr_ops(void); | ||
902 | |||
903 | void dss_mgr_set_timings(struct omap_overlay_manager *mgr, | ||
904 | const struct omap_video_timings *timings); | ||
905 | void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr, | ||
906 | const struct dss_lcd_mgr_config *config); | ||
907 | int dss_mgr_enable(struct omap_overlay_manager *mgr); | ||
908 | void dss_mgr_disable(struct omap_overlay_manager *mgr); | ||
909 | void dss_mgr_start_update(struct omap_overlay_manager *mgr); | ||
910 | int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr, | ||
911 | void (*handler)(void *), void *data); | ||
912 | void 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 |
39 | extern bool omap_vrfb_supported(void); | ||
39 | extern int omap_vrfb_request_ctx(struct vrfb *vrfb); | 40 | extern int omap_vrfb_request_ctx(struct vrfb *vrfb); |
40 | extern void omap_vrfb_release_ctx(struct vrfb *vrfb); | 41 | extern void omap_vrfb_release_ctx(struct vrfb *vrfb); |
41 | extern void omap_vrfb_adjust_size(u16 *width, u16 *height, | 42 | extern 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); | |||
49 | extern void omap_vrfb_restore_context(void); | 50 | extern void omap_vrfb_restore_context(void); |
50 | 51 | ||
51 | #else | 52 | #else |
53 | static inline bool omap_vrfb_supported(void) { return false; } | ||
52 | static inline int omap_vrfb_request_ctx(struct vrfb *vrfb) { return 0; } | 54 | static inline int omap_vrfb_request_ctx(struct vrfb *vrfb) { return 0; } |
53 | static inline void omap_vrfb_release_ctx(struct vrfb *vrfb) {} | 55 | static inline void omap_vrfb_release_ctx(struct vrfb *vrfb) {} |
54 | static inline void omap_vrfb_adjust_size(u16 *width, u16 *height, | 56 | static inline void omap_vrfb_adjust_size(u16 *width, u16 *height, |