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, |
