diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-15 16:03:48 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-15 16:03:48 -0500 |
commit | 2b8318881ddbcb67c5e8d2178b42284749442222 (patch) | |
tree | b43ded0118bb7a6d9f89f6875c18d7ef447ba3be | |
parent | e81d372ff9f694e13fa46e8b5aaed505c7fd2a1f (diff) | |
parent | e7f5c9a16ea2648a3e85af8e34191026bf3dcb62 (diff) |
Merge tag 'fbdev-for-3.8' of git://gitorious.org/linux-omap-dss2/linux
Pull fbdev changes from Tomi Valkeinen:
"OMAPDSS changes, including:
- use dynanic debug prints
- OMAP platform dependency removals
- Creation of compat-layer, helping us to improve omapdrm
- Misc cleanups, aiming to make omadss more in line with the upcoming
common display framework
Exynos DP changes for the 3.8 merge window:
- Device Tree support for Samsung Exynos DP
- SW Link training is cleaned up.
- HPD interrupt is supported.
Samsung Framebuffer changes for the 3.8 merge window:
- The bit definitions of header file are updated.
- Some minor typos are fixed.
- Some minor bugs of s3c_fb_check_var() are fixed.
FB related changes for SH Mobile, Freescale DIU
Add support for the Solomon SSD1307 OLED Controller"
* tag 'fbdev-for-3.8' of git://gitorious.org/linux-omap-dss2/linux: (191 commits)
OMAPDSS: fix TV-out issue with DSI PLL
Revert "OMAPFB: simplify locking"
OMAPFB: remove silly loop in fb2display()
OMAPFB: fix error handling in omapfb_find_best_mode()
OMAPFB: use devm_kzalloc to allocate omapfb2_device
OMAPDSS: DISPC: remove dispc fck uses
OMAPDSS: DISPC: get dss clock rate from dss driver
drivers/video/console/softcursor.c: remove redundant NULL check before kfree()
drivers/video: add support for the Solomon SSD1307 OLED Controller
OMAPDSS: use omapdss_compat_init() in other drivers
OMAPDSS: export dispc functions
OMAPDSS: export dss_feat functions
OMAPDSS: export dss_mgr_ops functions
OMAPDSS: separate compat files in the Makefile
OMAPDSS: move display sysfs init to compat layer
OMAPDSS: DPI: use dispc's check_timings
OMAPDSS: DISPC: add dispc_ovl_check()
OMAPDSS: move irq handling to dispc-compat
OMAPDSS: move omap_dispc_wait_for_irq_interruptible_timeout to dispc-compat.c
OMAPDSS: move blocking mgr enable/disable to compat layer
...
Conflicts:
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/plat-omap/common.c
drivers/media/platform/omap/omap_vout.c
89 files changed, 4013 insertions, 3771 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/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt new file mode 100644 index 000000000000..c60da67a5d76 --- /dev/null +++ b/Documentation/devicetree/bindings/video/exynos_dp.txt | |||
@@ -0,0 +1,80 @@ | |||
1 | The Exynos display port interface should be configured based on | ||
2 | the type of panel connected to it. | ||
3 | |||
4 | We use two nodes: | ||
5 | -dp-controller node | ||
6 | -dptx-phy node(defined inside dp-controller node) | ||
7 | |||
8 | For the DP-PHY initialization, we use the dptx-phy node. | ||
9 | Required properties for dptx-phy: | ||
10 | -reg: | ||
11 | Base address of DP PHY register. | ||
12 | -samsung,enable-mask: | ||
13 | The bit-mask used to enable/disable DP PHY. | ||
14 | |||
15 | For the Panel initialization, we read data from dp-controller node. | ||
16 | Required properties for dp-controller: | ||
17 | -compatible: | ||
18 | should be "samsung,exynos5-dp". | ||
19 | -reg: | ||
20 | physical base address of the controller and length | ||
21 | of memory mapped region. | ||
22 | -interrupts: | ||
23 | interrupt combiner values. | ||
24 | -interrupt-parent: | ||
25 | phandle to Interrupt combiner node. | ||
26 | -samsung,color-space: | ||
27 | input video data format. | ||
28 | COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2 | ||
29 | -samsung,dynamic-range: | ||
30 | dynamic range for input video data. | ||
31 | VESA = 0, CEA = 1 | ||
32 | -samsung,ycbcr-coeff: | ||
33 | YCbCr co-efficients for input video. | ||
34 | COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1 | ||
35 | -samsung,color-depth: | ||
36 | number of bits per colour component. | ||
37 | COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3 | ||
38 | -samsung,link-rate: | ||
39 | link rate supported by the panel. | ||
40 | LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A | ||
41 | -samsung,lane-count: | ||
42 | number of lanes supported by the panel. | ||
43 | LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4 | ||
44 | |||
45 | Optional properties for dp-controller: | ||
46 | -interlaced: | ||
47 | interlace scan mode. | ||
48 | Progressive if defined, Interlaced if not defined | ||
49 | -vsync-active-high: | ||
50 | VSYNC polarity configuration. | ||
51 | High if defined, Low if not defined | ||
52 | -hsync-active-high: | ||
53 | HSYNC polarity configuration. | ||
54 | High if defined, Low if not defined | ||
55 | |||
56 | Example: | ||
57 | |||
58 | SOC specific portion: | ||
59 | dp-controller { | ||
60 | compatible = "samsung,exynos5-dp"; | ||
61 | reg = <0x145b0000 0x10000>; | ||
62 | interrupts = <10 3>; | ||
63 | interrupt-parent = <&combiner>; | ||
64 | |||
65 | dptx-phy { | ||
66 | reg = <0x10040720>; | ||
67 | samsung,enable-mask = <1>; | ||
68 | }; | ||
69 | |||
70 | }; | ||
71 | |||
72 | Board Specific portion: | ||
73 | dp-controller { | ||
74 | samsung,color-space = <0>; | ||
75 | samsung,dynamic-range = <0>; | ||
76 | samsung,ycbcr-coeff = <0>; | ||
77 | samsung,color-depth = <1>; | ||
78 | samsung,link-rate = <0x0a>; | ||
79 | samsung,lane-count = <4>; | ||
80 | }; | ||
diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt new file mode 100644 index 000000000000..3d0060cff062 --- /dev/null +++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt | |||
@@ -0,0 +1,24 @@ | |||
1 | * Solomon SSD1307 Framebuffer Driver | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: Should be "solomon,ssd1307fb-<bus>". The only supported bus for | ||
5 | now is i2c. | ||
6 | - reg: Should contain address of the controller on the I2C bus. Most likely | ||
7 | 0x3c or 0x3d | ||
8 | - pwm: Should contain the pwm to use according to the OF device tree PWM | ||
9 | specification [0] | ||
10 | - reset-gpios: Should contain the GPIO used to reset the OLED display | ||
11 | |||
12 | Optional properties: | ||
13 | - reset-active-low: Is the reset gpio is active on physical low? | ||
14 | |||
15 | [0]: Documentation/devicetree/bindings/pwm/pwm.txt | ||
16 | |||
17 | Examples: | ||
18 | ssd1307: oled@3c { | ||
19 | compatible = "solomon,ssd1307fb-i2c"; | ||
20 | reg = <0x3c>; | ||
21 | pwms = <&pwm 4 3000>; | ||
22 | reset-gpios = <&gpio2 7>; | ||
23 | reset-active-low; | ||
24 | }; | ||
diff --git a/MAINTAINERS b/MAINTAINERS index b95ae9b07121..f71d2f901a69 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3162,6 +3162,12 @@ F: drivers/video/ | |||
3162 | F: include/video/ | 3162 | F: include/video/ |
3163 | F: include/linux/fb.h | 3163 | F: include/linux/fb.h |
3164 | 3164 | ||
3165 | FREESCALE DIU FRAMEBUFFER DRIVER | ||
3166 | M: Timur Tabi <timur@freescale.com> | ||
3167 | L: linux-fbdev@vger.kernel.org | ||
3168 | S: Supported | ||
3169 | F: drivers/video/fsl-diu-fb.* | ||
3170 | |||
3165 | FREESCALE DMA DRIVER | 3171 | FREESCALE DMA DRIVER |
3166 | M: Li Yang <leoli@freescale.com> | 3172 | M: Li Yang <leoli@freescale.com> |
3167 | M: Zhang Wei <zw@zh-kernel.org> | 3173 | M: Zhang Wei <zw@zh-kernel.org> |
diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index 510648e0394b..678a54a64dae 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c | |||
@@ -408,7 +408,7 @@ static struct clk_lookup da830_clks[] = { | |||
408 | CLK(NULL, "pwm2", &pwm2_clk), | 408 | CLK(NULL, "pwm2", &pwm2_clk), |
409 | CLK("eqep.0", NULL, &eqep0_clk), | 409 | CLK("eqep.0", NULL, &eqep0_clk), |
410 | CLK("eqep.1", NULL, &eqep1_clk), | 410 | CLK("eqep.1", NULL, &eqep1_clk), |
411 | CLK("da8xx_lcdc.0", NULL, &lcdc_clk), | 411 | CLK("da8xx_lcdc.0", "fck", &lcdc_clk), |
412 | CLK("davinci-mcasp.0", NULL, &mcasp0_clk), | 412 | CLK("davinci-mcasp.0", NULL, &mcasp0_clk), |
413 | CLK("davinci-mcasp.1", NULL, &mcasp1_clk), | 413 | CLK("davinci-mcasp.1", NULL, &mcasp1_clk), |
414 | CLK("davinci-mcasp.2", NULL, &mcasp2_clk), | 414 | CLK("davinci-mcasp.2", NULL, &mcasp2_clk), |
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 68c5fe01857c..6b9154e9f908 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c | |||
@@ -403,7 +403,7 @@ static struct clk_lookup da850_clks[] = { | |||
403 | CLK(NULL, "rmii", &rmii_clk), | 403 | CLK(NULL, "rmii", &rmii_clk), |
404 | CLK("davinci_emac.1", NULL, &emac_clk), | 404 | CLK("davinci_emac.1", NULL, &emac_clk), |
405 | CLK("davinci-mcasp.0", NULL, &mcasp_clk), | 405 | CLK("davinci-mcasp.0", NULL, &mcasp_clk), |
406 | CLK("da8xx_lcdc.0", NULL, &lcdc_clk), | 406 | CLK("da8xx_lcdc.0", "fck", &lcdc_clk), |
407 | CLK("davinci_mmc.0", NULL, &mmcsd0_clk), | 407 | CLK("davinci_mmc.0", NULL, &mmcsd0_clk), |
408 | CLK("davinci_mmc.1", NULL, &mmcsd1_clk), | 408 | CLK("davinci_mmc.1", NULL, &mmcsd1_clk), |
409 | CLK(NULL, "aemif", &aemif_clk), | 409 | CLK(NULL, "aemif", &aemif_clk), |
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 46c9a0c09ae5..fcdbe437409e 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c | |||
@@ -589,29 +589,9 @@ int __init da8xx_register_uio_pruss(void) | |||
589 | return platform_device_register(&da8xx_uio_pruss_dev); | 589 | return platform_device_register(&da8xx_uio_pruss_dev); |
590 | } | 590 | } |
591 | 591 | ||
592 | static const struct display_panel disp_panel = { | ||
593 | QVGA, | ||
594 | 16, | ||
595 | 16, | ||
596 | COLOR_ACTIVE, | ||
597 | }; | ||
598 | |||
599 | static struct lcd_ctrl_config lcd_cfg = { | 592 | static struct lcd_ctrl_config lcd_cfg = { |
600 | &disp_panel, | 593 | .panel_shade = COLOR_ACTIVE, |
601 | .ac_bias = 255, | ||
602 | .ac_bias_intrpt = 0, | ||
603 | .dma_burst_sz = 16, | ||
604 | .bpp = 16, | 594 | .bpp = 16, |
605 | .fdd = 255, | ||
606 | .tft_alt_mode = 0, | ||
607 | .stn_565_mode = 0, | ||
608 | .mono_8bit_mode = 0, | ||
609 | .invert_line_clock = 1, | ||
610 | .invert_frm_clock = 1, | ||
611 | .sync_edge = 0, | ||
612 | .sync_ctrl = 1, | ||
613 | .raster_order = 0, | ||
614 | .fifo_th = 6, | ||
615 | }; | 595 | }; |
616 | 596 | ||
617 | struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata = { | 597 | struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata = { |
diff --git a/arch/arm/mach-davinci/pm_domain.c b/arch/arm/mach-davinci/pm_domain.c index 00946e23c1ee..c90250e3bef8 100644 --- a/arch/arm/mach-davinci/pm_domain.c +++ b/arch/arm/mach-davinci/pm_domain.c | |||
@@ -53,6 +53,7 @@ static struct dev_pm_domain davinci_pm_domain = { | |||
53 | 53 | ||
54 | static struct pm_clk_notifier_block platform_bus_notifier = { | 54 | static struct pm_clk_notifier_block platform_bus_notifier = { |
55 | .pm_domain = &davinci_pm_domain, | 55 | .pm_domain = &davinci_pm_domain, |
56 | .con_ids = { "fck", NULL, }, | ||
56 | }; | 57 | }; |
57 | 58 | ||
58 | static int __init davinci_pm_runtime_init(void) | 59 | static int __init davinci_pm_runtime_init(void) |
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 f1d6efe079ca..d0374ea2dfb0 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 38ba58c97628..cc75aaf6e764 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c | |||
@@ -102,17 +102,20 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initconst = { | |||
102 | { "dss_hdmi", "omapdss_hdmi", -1 }, | 102 | { "dss_hdmi", "omapdss_hdmi", -1 }, |
103 | }; | 103 | }; |
104 | 104 | ||
105 | static void __init omap4_hdmi_mux_pads(enum omap_hdmi_flags flags) | 105 | static void __init omap4_tpd12s015_mux_pads(void) |
106 | { | 106 | { |
107 | u32 reg; | ||
108 | u16 control_i2c_1; | ||
109 | |||
110 | omap_mux_init_signal("hdmi_cec", | 107 | omap_mux_init_signal("hdmi_cec", |
111 | OMAP_PIN_INPUT_PULLUP); | 108 | OMAP_PIN_INPUT_PULLUP); |
112 | omap_mux_init_signal("hdmi_ddc_scl", | 109 | omap_mux_init_signal("hdmi_ddc_scl", |
113 | OMAP_PIN_INPUT_PULLUP); | 110 | OMAP_PIN_INPUT_PULLUP); |
114 | omap_mux_init_signal("hdmi_ddc_sda", | 111 | omap_mux_init_signal("hdmi_ddc_sda", |
115 | OMAP_PIN_INPUT_PULLUP); | 112 | OMAP_PIN_INPUT_PULLUP); |
113 | } | ||
114 | |||
115 | static void __init omap4_hdmi_mux_pads(enum omap_hdmi_flags flags) | ||
116 | { | ||
117 | u32 reg; | ||
118 | u16 control_i2c_1; | ||
116 | 119 | ||
117 | /* | 120 | /* |
118 | * CONTROL_I2C_1: HDMI_DDC_SDA_PULLUPRESX (bit 28) and | 121 | * CONTROL_I2C_1: HDMI_DDC_SDA_PULLUPRESX (bit 28) and |
@@ -163,8 +166,10 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes) | |||
163 | 166 | ||
164 | int __init omap_hdmi_init(enum omap_hdmi_flags flags) | 167 | int __init omap_hdmi_init(enum omap_hdmi_flags flags) |
165 | { | 168 | { |
166 | if (cpu_is_omap44xx()) | 169 | if (cpu_is_omap44xx()) { |
167 | omap4_hdmi_mux_pads(flags); | 170 | omap4_hdmi_mux_pads(flags); |
171 | omap4_tpd12s015_mux_pads(); | ||
172 | } | ||
168 | 173 | ||
169 | return 0; | 174 | return 0; |
170 | } | 175 | } |
diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index 25eb88a923e6..032d10817e79 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c | |||
@@ -213,95 +213,6 @@ static struct platform_device irda_device = { | |||
213 | .num_resources = ARRAY_SIZE(irda_resources), | 213 | .num_resources = ARRAY_SIZE(irda_resources), |
214 | }; | 214 | }; |
215 | 215 | ||
216 | static unsigned char lcd_backlight_seq[3][2] = { | ||
217 | { 0x04, 0x07 }, | ||
218 | { 0x23, 0x80 }, | ||
219 | { 0x03, 0x01 }, | ||
220 | }; | ||
221 | |||
222 | static void lcd_backlight_on(void) | ||
223 | { | ||
224 | struct i2c_adapter *a; | ||
225 | struct i2c_msg msg; | ||
226 | int k; | ||
227 | |||
228 | a = i2c_get_adapter(1); | ||
229 | for (k = 0; a && k < 3; k++) { | ||
230 | msg.addr = 0x6d; | ||
231 | msg.buf = &lcd_backlight_seq[k][0]; | ||
232 | msg.len = 2; | ||
233 | msg.flags = 0; | ||
234 | if (i2c_transfer(a, &msg, 1) != 1) | ||
235 | break; | ||
236 | } | ||
237 | } | ||
238 | |||
239 | static void lcd_backlight_reset(void) | ||
240 | { | ||
241 | gpio_set_value(GPIO_PORT235, 0); | ||
242 | mdelay(24); | ||
243 | gpio_set_value(GPIO_PORT235, 1); | ||
244 | } | ||
245 | |||
246 | /* LCDC0 */ | ||
247 | static const struct fb_videomode lcdc0_modes[] = { | ||
248 | { | ||
249 | .name = "R63302(QHD)", | ||
250 | .xres = 544, | ||
251 | .yres = 961, | ||
252 | .left_margin = 72, | ||
253 | .right_margin = 600, | ||
254 | .hsync_len = 16, | ||
255 | .upper_margin = 8, | ||
256 | .lower_margin = 8, | ||
257 | .vsync_len = 2, | ||
258 | .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, | ||
259 | }, | ||
260 | }; | ||
261 | |||
262 | static struct sh_mobile_lcdc_info lcdc0_info = { | ||
263 | .clock_source = LCDC_CLK_PERIPHERAL, | ||
264 | .ch[0] = { | ||
265 | .chan = LCDC_CHAN_MAINLCD, | ||
266 | .interface_type = RGB24, | ||
267 | .clock_divider = 1, | ||
268 | .flags = LCDC_FLAGS_DWPOL, | ||
269 | .fourcc = V4L2_PIX_FMT_RGB565, | ||
270 | .lcd_modes = lcdc0_modes, | ||
271 | .num_modes = ARRAY_SIZE(lcdc0_modes), | ||
272 | .panel_cfg = { | ||
273 | .width = 44, | ||
274 | .height = 79, | ||
275 | .display_on = lcd_backlight_on, | ||
276 | .display_off = lcd_backlight_reset, | ||
277 | }, | ||
278 | } | ||
279 | }; | ||
280 | |||
281 | static struct resource lcdc0_resources[] = { | ||
282 | [0] = { | ||
283 | .name = "LCDC0", | ||
284 | .start = 0xfe940000, /* P4-only space */ | ||
285 | .end = 0xfe943fff, | ||
286 | .flags = IORESOURCE_MEM, | ||
287 | }, | ||
288 | [1] = { | ||
289 | .start = intcs_evt2irq(0x580), | ||
290 | .flags = IORESOURCE_IRQ, | ||
291 | }, | ||
292 | }; | ||
293 | |||
294 | static struct platform_device lcdc0_device = { | ||
295 | .name = "sh_mobile_lcdc_fb", | ||
296 | .num_resources = ARRAY_SIZE(lcdc0_resources), | ||
297 | .resource = lcdc0_resources, | ||
298 | .id = 0, | ||
299 | .dev = { | ||
300 | .platform_data = &lcdc0_info, | ||
301 | .coherent_dma_mask = ~0, | ||
302 | }, | ||
303 | }; | ||
304 | |||
305 | /* MIPI-DSI */ | 216 | /* MIPI-DSI */ |
306 | static struct resource mipidsi0_resources[] = { | 217 | static struct resource mipidsi0_resources[] = { |
307 | [0] = { | 218 | [0] = { |
@@ -358,7 +269,7 @@ sh_mipi_set_dot_clock_pck_err: | |||
358 | 269 | ||
359 | static struct sh_mipi_dsi_info mipidsi0_info = { | 270 | static struct sh_mipi_dsi_info mipidsi0_info = { |
360 | .data_format = MIPI_RGB888, | 271 | .data_format = MIPI_RGB888, |
361 | .lcd_chan = &lcdc0_info.ch[0], | 272 | .channel = LCDC_CHAN_MAINLCD, |
362 | .lane = 2, | 273 | .lane = 2, |
363 | .vsynw_offset = 20, | 274 | .vsynw_offset = 20, |
364 | .clksrc = 1, | 275 | .clksrc = 1, |
@@ -378,6 +289,109 @@ static struct platform_device mipidsi0_device = { | |||
378 | }, | 289 | }, |
379 | }; | 290 | }; |
380 | 291 | ||
292 | static unsigned char lcd_backlight_seq[3][2] = { | ||
293 | { 0x04, 0x07 }, | ||
294 | { 0x23, 0x80 }, | ||
295 | { 0x03, 0x01 }, | ||
296 | }; | ||
297 | |||
298 | static int lcd_backlight_set_brightness(int brightness) | ||
299 | { | ||
300 | struct i2c_adapter *adap; | ||
301 | struct i2c_msg msg; | ||
302 | unsigned int i; | ||
303 | int ret; | ||
304 | |||
305 | if (brightness == 0) { | ||
306 | /* Reset the chip */ | ||
307 | gpio_set_value(GPIO_PORT235, 0); | ||
308 | mdelay(24); | ||
309 | gpio_set_value(GPIO_PORT235, 1); | ||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | adap = i2c_get_adapter(1); | ||
314 | if (adap == NULL) | ||
315 | return -ENODEV; | ||
316 | |||
317 | for (i = 0; i < ARRAY_SIZE(lcd_backlight_seq); i++) { | ||
318 | msg.addr = 0x6d; | ||
319 | msg.buf = &lcd_backlight_seq[i][0]; | ||
320 | msg.len = 2; | ||
321 | msg.flags = 0; | ||
322 | |||
323 | ret = i2c_transfer(adap, &msg, 1); | ||
324 | if (ret < 0) | ||
325 | break; | ||
326 | } | ||
327 | |||
328 | i2c_put_adapter(adap); | ||
329 | return ret < 0 ? ret : 0; | ||
330 | } | ||
331 | |||
332 | /* LCDC0 */ | ||
333 | static const struct fb_videomode lcdc0_modes[] = { | ||
334 | { | ||
335 | .name = "R63302(QHD)", | ||
336 | .xres = 544, | ||
337 | .yres = 961, | ||
338 | .left_margin = 72, | ||
339 | .right_margin = 600, | ||
340 | .hsync_len = 16, | ||
341 | .upper_margin = 8, | ||
342 | .lower_margin = 8, | ||
343 | .vsync_len = 2, | ||
344 | .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, | ||
345 | }, | ||
346 | }; | ||
347 | |||
348 | static struct sh_mobile_lcdc_info lcdc0_info = { | ||
349 | .clock_source = LCDC_CLK_PERIPHERAL, | ||
350 | .ch[0] = { | ||
351 | .chan = LCDC_CHAN_MAINLCD, | ||
352 | .interface_type = RGB24, | ||
353 | .clock_divider = 1, | ||
354 | .flags = LCDC_FLAGS_DWPOL, | ||
355 | .fourcc = V4L2_PIX_FMT_RGB565, | ||
356 | .lcd_modes = lcdc0_modes, | ||
357 | .num_modes = ARRAY_SIZE(lcdc0_modes), | ||
358 | .panel_cfg = { | ||
359 | .width = 44, | ||
360 | .height = 79, | ||
361 | }, | ||
362 | .bl_info = { | ||
363 | .name = "sh_mobile_lcdc_bl", | ||
364 | .max_brightness = 1, | ||
365 | .set_brightness = lcd_backlight_set_brightness, | ||
366 | }, | ||
367 | .tx_dev = &mipidsi0_device, | ||
368 | } | ||
369 | }; | ||
370 | |||
371 | static struct resource lcdc0_resources[] = { | ||
372 | [0] = { | ||
373 | .name = "LCDC0", | ||
374 | .start = 0xfe940000, /* P4-only space */ | ||
375 | .end = 0xfe943fff, | ||
376 | .flags = IORESOURCE_MEM, | ||
377 | }, | ||
378 | [1] = { | ||
379 | .start = intcs_evt2irq(0x580), | ||
380 | .flags = IORESOURCE_IRQ, | ||
381 | }, | ||
382 | }; | ||
383 | |||
384 | static struct platform_device lcdc0_device = { | ||
385 | .name = "sh_mobile_lcdc_fb", | ||
386 | .num_resources = ARRAY_SIZE(lcdc0_resources), | ||
387 | .resource = lcdc0_resources, | ||
388 | .id = 0, | ||
389 | .dev = { | ||
390 | .platform_data = &lcdc0_info, | ||
391 | .coherent_dma_mask = ~0, | ||
392 | }, | ||
393 | }; | ||
394 | |||
381 | /* Fixed 2.8V regulators to be used by SDHI0 */ | 395 | /* Fixed 2.8V regulators to be used by SDHI0 */ |
382 | static struct regulator_consumer_supply fixed2v8_power_consumers[] = | 396 | static struct regulator_consumer_supply fixed2v8_power_consumers[] = |
383 | { | 397 | { |
@@ -531,8 +545,8 @@ static struct platform_device *ag5evm_devices[] __initdata = { | |||
531 | &fsi_device, | 545 | &fsi_device, |
532 | &mmc_device, | 546 | &mmc_device, |
533 | &irda_device, | 547 | &irda_device, |
534 | &lcdc0_device, | ||
535 | &mipidsi0_device, | 548 | &mipidsi0_device, |
549 | &lcdc0_device, | ||
536 | &sdhi0_device, | 550 | &sdhi0_device, |
537 | &sdhi1_device, | 551 | &sdhi1_device, |
538 | }; | 552 | }; |
@@ -621,7 +635,7 @@ static void __init ag5evm_init(void) | |||
621 | /* LCD backlight controller */ | 635 | /* LCD backlight controller */ |
622 | gpio_request(GPIO_PORT235, NULL); /* RESET */ | 636 | gpio_request(GPIO_PORT235, NULL); /* RESET */ |
623 | gpio_direction_output(GPIO_PORT235, 0); | 637 | gpio_direction_output(GPIO_PORT235, 0); |
624 | lcd_backlight_reset(); | 638 | lcd_backlight_set_brightness(0); |
625 | 639 | ||
626 | /* enable SDHI0 on CN15 [SD I/F] */ | 640 | /* enable SDHI0 on CN15 [SD I/F] */ |
627 | gpio_request(GPIO_FN_SDHIWP0, NULL); | 641 | gpio_request(GPIO_FN_SDHIWP0, NULL); |
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 40657854e3ad..99ef190d0909 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c | |||
@@ -552,11 +552,9 @@ static struct resource mipidsi0_resources[] = { | |||
552 | }, | 552 | }, |
553 | }; | 553 | }; |
554 | 554 | ||
555 | static struct sh_mobile_lcdc_info lcdc_info; | ||
556 | |||
557 | static struct sh_mipi_dsi_info mipidsi0_info = { | 555 | static struct sh_mipi_dsi_info mipidsi0_info = { |
558 | .data_format = MIPI_RGB888, | 556 | .data_format = MIPI_RGB888, |
559 | .lcd_chan = &lcdc_info.ch[0], | 557 | .channel = LCDC_CHAN_MAINLCD, |
560 | .lane = 2, | 558 | .lane = 2, |
561 | .vsynw_offset = 17, | 559 | .vsynw_offset = 17, |
562 | .phyctrl = 0x6 << 8, | 560 | .phyctrl = 0x6 << 8, |
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 3f56e70795b7..2fed62f66045 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c | |||
@@ -370,11 +370,6 @@ static int mackerel_set_brightness(int brightness) | |||
370 | return 0; | 370 | return 0; |
371 | } | 371 | } |
372 | 372 | ||
373 | static int mackerel_get_brightness(void) | ||
374 | { | ||
375 | return gpio_get_value(GPIO_PORT31); | ||
376 | } | ||
377 | |||
378 | static const struct sh_mobile_meram_cfg lcd_meram_cfg = { | 373 | static const struct sh_mobile_meram_cfg lcd_meram_cfg = { |
379 | .icb[0] = { | 374 | .icb[0] = { |
380 | .meram_size = 0x40, | 375 | .meram_size = 0x40, |
@@ -403,7 +398,6 @@ static struct sh_mobile_lcdc_info lcdc_info = { | |||
403 | .name = "sh_mobile_lcdc_bl", | 398 | .name = "sh_mobile_lcdc_bl", |
404 | .max_brightness = 1, | 399 | .max_brightness = 1, |
405 | .set_brightness = mackerel_set_brightness, | 400 | .set_brightness = mackerel_set_brightness, |
406 | .get_brightness = mackerel_get_brightness, | ||
407 | }, | 401 | }, |
408 | .meram_cfg = &lcd_meram_cfg, | 402 | .meram_cfg = &lcd_meram_cfg, |
409 | } | 403 | } |
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c index 3a77b30f53d4..a3367b783fc7 100644 --- a/arch/arm/plat-omap/fb.c +++ b/arch/arm/plat-omap/fb.c | |||
@@ -29,6 +29,7 @@ | |||
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 <asm/mach/map.h> | 34 | #include <asm/mach/map.h> |
34 | 35 | ||
@@ -105,7 +106,7 @@ static struct platform_device omap_fb_device = { | |||
105 | .id = -1, | 106 | .id = -1, |
106 | .dev = { | 107 | .dev = { |
107 | .dma_mask = &omap_fb_dma_mask, | 108 | .dma_mask = &omap_fb_dma_mask, |
108 | .coherent_dma_mask = ~(u32)0, | 109 | .coherent_dma_mask = DMA_BIT_MASK(32), |
109 | .platform_data = &omapfb_config, | 110 | .platform_data = &omapfb_config, |
110 | }, | 111 | }, |
111 | .num_resources = 0, | 112 | .num_resources = 0, |
@@ -141,7 +142,7 @@ static struct platform_device omap_fb_device = { | |||
141 | .id = -1, | 142 | .id = -1, |
142 | .dev = { | 143 | .dev = { |
143 | .dma_mask = &omap_fb_dma_mask, | 144 | .dma_mask = &omap_fb_dma_mask, |
144 | .coherent_dma_mask = ~(u32)0, | 145 | .coherent_dma_mask = DMA_BIT_MASK(32), |
145 | .platform_data = &omapfb_config, | 146 | .platform_data = &omapfb_config, |
146 | }, | 147 | }, |
147 | .num_resources = 0, | 148 | .num_resources = 0, |
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/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c index 9e963c1d1447..5620e33c18a0 100644 --- a/arch/sh/boards/mach-ap325rxa/setup.c +++ b/arch/sh/boards/mach-ap325rxa/setup.c | |||
@@ -179,11 +179,6 @@ static int ap320_wvga_set_brightness(int brightness) | |||
179 | return 0; | 179 | return 0; |
180 | } | 180 | } |
181 | 181 | ||
182 | static int ap320_wvga_get_brightness(void) | ||
183 | { | ||
184 | return gpio_get_value(GPIO_PTS3); | ||
185 | } | ||
186 | |||
187 | static void ap320_wvga_power_on(void) | 182 | static void ap320_wvga_power_on(void) |
188 | { | 183 | { |
189 | msleep(100); | 184 | msleep(100); |
@@ -232,7 +227,6 @@ static struct sh_mobile_lcdc_info lcdc_info = { | |||
232 | .name = "sh_mobile_lcdc_bl", | 227 | .name = "sh_mobile_lcdc_bl", |
233 | .max_brightness = 1, | 228 | .max_brightness = 1, |
234 | .set_brightness = ap320_wvga_set_brightness, | 229 | .set_brightness = ap320_wvga_set_brightness, |
235 | .get_brightness = ap320_wvga_get_brightness, | ||
236 | }, | 230 | }, |
237 | } | 231 | } |
238 | }; | 232 | }; |
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 64559e8af14b..3fede4556c91 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c | |||
@@ -329,11 +329,6 @@ static int ecovec24_set_brightness(int brightness) | |||
329 | return 0; | 329 | return 0; |
330 | } | 330 | } |
331 | 331 | ||
332 | static int ecovec24_get_brightness(void) | ||
333 | { | ||
334 | return gpio_get_value(GPIO_PTR1); | ||
335 | } | ||
336 | |||
337 | static struct sh_mobile_lcdc_info lcdc_info = { | 332 | static struct sh_mobile_lcdc_info lcdc_info = { |
338 | .ch[0] = { | 333 | .ch[0] = { |
339 | .interface_type = RGB18, | 334 | .interface_type = RGB18, |
@@ -347,7 +342,6 @@ static struct sh_mobile_lcdc_info lcdc_info = { | |||
347 | .name = "sh_mobile_lcdc_bl", | 342 | .name = "sh_mobile_lcdc_bl", |
348 | .max_brightness = 1, | 343 | .max_brightness = 1, |
349 | .set_brightness = ecovec24_set_brightness, | 344 | .set_brightness = ecovec24_set_brightness, |
350 | .get_brightness = ecovec24_get_brightness, | ||
351 | }, | 345 | }, |
352 | } | 346 | } |
353 | }; | 347 | }; |
diff --git a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c index c148b36ecb65..c62050332629 100644 --- a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c +++ b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c | |||
@@ -283,7 +283,7 @@ void kfr2r09_lcd_start(void *sohandle, struct sh_mobile_lcdc_sys_bus_ops *so) | |||
283 | #define MAIN_MLED4 0x40 | 283 | #define MAIN_MLED4 0x40 |
284 | #define MAIN_MSW 0x80 | 284 | #define MAIN_MSW 0x80 |
285 | 285 | ||
286 | static int kfr2r09_lcd_backlight(int on) | 286 | int kfr2r09_lcd_set_brightness(int brightness) |
287 | { | 287 | { |
288 | struct i2c_adapter *a; | 288 | struct i2c_adapter *a; |
289 | struct i2c_msg msg; | 289 | struct i2c_msg msg; |
@@ -295,7 +295,7 @@ static int kfr2r09_lcd_backlight(int on) | |||
295 | return -ENODEV; | 295 | return -ENODEV; |
296 | 296 | ||
297 | buf[0] = 0x00; | 297 | buf[0] = 0x00; |
298 | if (on) | 298 | if (brightness) |
299 | buf[1] = CTRL_CPSW | CTRL_C10 | CTRL_CKSW; | 299 | buf[1] = CTRL_CPSW | CTRL_C10 | CTRL_CKSW; |
300 | else | 300 | else |
301 | buf[1] = 0; | 301 | buf[1] = 0; |
@@ -309,7 +309,7 @@ static int kfr2r09_lcd_backlight(int on) | |||
309 | return -ENODEV; | 309 | return -ENODEV; |
310 | 310 | ||
311 | buf[0] = 0x01; | 311 | buf[0] = 0x01; |
312 | if (on) | 312 | if (brightness) |
313 | buf[1] = MAIN_MSW | MAIN_MLED4 | 0x0c; | 313 | buf[1] = MAIN_MSW | MAIN_MLED4 | 0x0c; |
314 | else | 314 | else |
315 | buf[1] = 0; | 315 | buf[1] = 0; |
@@ -324,13 +324,3 @@ static int kfr2r09_lcd_backlight(int on) | |||
324 | 324 | ||
325 | return 0; | 325 | return 0; |
326 | } | 326 | } |
327 | |||
328 | void kfr2r09_lcd_on(void) | ||
329 | { | ||
330 | kfr2r09_lcd_backlight(1); | ||
331 | } | ||
332 | |||
333 | void kfr2r09_lcd_off(void) | ||
334 | { | ||
335 | kfr2r09_lcd_backlight(0); | ||
336 | } | ||
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c index f2a4304fbe23..ab502f12ef57 100644 --- a/arch/sh/boards/mach-kfr2r09/setup.c +++ b/arch/sh/boards/mach-kfr2r09/setup.c | |||
@@ -158,8 +158,11 @@ static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = { | |||
158 | .height = 58, | 158 | .height = 58, |
159 | .setup_sys = kfr2r09_lcd_setup, | 159 | .setup_sys = kfr2r09_lcd_setup, |
160 | .start_transfer = kfr2r09_lcd_start, | 160 | .start_transfer = kfr2r09_lcd_start, |
161 | .display_on = kfr2r09_lcd_on, | 161 | }, |
162 | .display_off = kfr2r09_lcd_off, | 162 | .bl_info = { |
163 | .name = "sh_mobile_lcdc_bl", | ||
164 | .max_brightness = 1, | ||
165 | .set_brightness = kfr2r09_lcd_set_brightness, | ||
163 | }, | 166 | }, |
164 | .sys_bus_cfg = { | 167 | .sys_bus_cfg = { |
165 | .ldmt2r = 0x07010904, | 168 | .ldmt2r = 0x07010904, |
diff --git a/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h index ba3d93d333f8..c20c9e5f5eab 100644 --- a/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h +++ b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h | |||
@@ -4,15 +4,13 @@ | |||
4 | #include <video/sh_mobile_lcdc.h> | 4 | #include <video/sh_mobile_lcdc.h> |
5 | 5 | ||
6 | #if defined(CONFIG_FB_SH_MOBILE_LCDC) || defined(CONFIG_FB_SH_MOBILE_LCDC_MODULE) | 6 | #if defined(CONFIG_FB_SH_MOBILE_LCDC) || defined(CONFIG_FB_SH_MOBILE_LCDC_MODULE) |
7 | void kfr2r09_lcd_on(void); | 7 | int kfr2r09_lcd_set_brightness(int brightness); |
8 | void kfr2r09_lcd_off(void); | ||
9 | int kfr2r09_lcd_setup(void *sys_ops_handle, | 8 | int kfr2r09_lcd_setup(void *sys_ops_handle, |
10 | struct sh_mobile_lcdc_sys_bus_ops *sys_ops); | 9 | struct sh_mobile_lcdc_sys_bus_ops *sys_ops); |
11 | void kfr2r09_lcd_start(void *sys_ops_handle, | 10 | void kfr2r09_lcd_start(void *sys_ops_handle, |
12 | struct sh_mobile_lcdc_sys_bus_ops *sys_ops); | 11 | struct sh_mobile_lcdc_sys_bus_ops *sys_ops); |
13 | #else | 12 | #else |
14 | static void kfr2r09_lcd_on(void) {} | 13 | static int kfr2r09_lcd_set_brightness(int brightness) {} |
15 | static void kfr2r09_lcd_off(void) {} | ||
16 | static int kfr2r09_lcd_setup(void *sys_ops_handle, | 14 | static int kfr2r09_lcd_setup(void *sys_ops_handle, |
17 | struct sh_mobile_lcdc_sys_bus_ops *sys_ops) | 15 | struct sh_mobile_lcdc_sys_bus_ops *sys_ops) |
18 | { | 16 | { |
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index 202d1b4b9bee..35cc526e6c93 100644 --- a/drivers/media/platform/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c | |||
@@ -44,8 +44,6 @@ | |||
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> | ||
48 | #include <linux/omap-dma.h> | ||
49 | #include <video/omapvrfb.h> | 47 | #include <video/omapvrfb.h> |
50 | #include <video/omapdss.h> | 48 | #include <video/omapdss.h> |
51 | 49 | ||
@@ -2043,7 +2041,7 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev) | |||
2043 | vout->vid_info.id = k + 1; | 2041 | vout->vid_info.id = k + 1; |
2044 | 2042 | ||
2045 | /* Set VRFB as rotation_type for omap2 and omap3 */ | 2043 | /* Set VRFB as rotation_type for omap2 and omap3 */ |
2046 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) | 2044 | if (omap_vout_dss_omap24xx() || omap_vout_dss_omap34xx()) |
2047 | vout->vid_info.rotation_type = VOUT_ROT_VRFB; | 2045 | vout->vid_info.rotation_type = VOUT_ROT_VRFB; |
2048 | 2046 | ||
2049 | /* Setup the default configuration for the video devices | 2047 | /* Setup the default configuration for the video devices |
@@ -2160,14 +2158,23 @@ static int __init omap_vout_probe(struct platform_device *pdev) | |||
2160 | struct omap_dss_device *def_display; | 2158 | struct omap_dss_device *def_display; |
2161 | struct omap2video_device *vid_dev = NULL; | 2159 | struct omap2video_device *vid_dev = NULL; |
2162 | 2160 | ||
2161 | ret = omapdss_compat_init(); | ||
2162 | if (ret) { | ||
2163 | dev_err(&pdev->dev, "failed to init dss\n"); | ||
2164 | return ret; | ||
2165 | } | ||
2166 | |||
2163 | if (pdev->num_resources == 0) { | 2167 | if (pdev->num_resources == 0) { |
2164 | dev_err(&pdev->dev, "probed for an unknown device\n"); | 2168 | dev_err(&pdev->dev, "probed for an unknown device\n"); |
2165 | return -ENODEV; | 2169 | ret = -ENODEV; |
2170 | goto err_dss_init; | ||
2166 | } | 2171 | } |
2167 | 2172 | ||
2168 | vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL); | 2173 | vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL); |
2169 | if (vid_dev == NULL) | 2174 | if (vid_dev == NULL) { |
2170 | return -ENOMEM; | 2175 | ret = -ENOMEM; |
2176 | goto err_dss_init; | ||
2177 | } | ||
2171 | 2178 | ||
2172 | vid_dev->num_displays = 0; | 2179 | vid_dev->num_displays = 0; |
2173 | for_each_dss_dev(dssdev) { | 2180 | for_each_dss_dev(dssdev) { |
@@ -2262,6 +2269,8 @@ probe_err1: | |||
2262 | } | 2269 | } |
2263 | probe_err0: | 2270 | probe_err0: |
2264 | kfree(vid_dev); | 2271 | kfree(vid_dev); |
2272 | err_dss_init: | ||
2273 | omapdss_compat_uninit(); | ||
2265 | return ret; | 2274 | return ret; |
2266 | } | 2275 | } |
2267 | 2276 | ||
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 d4823fd67768..84943e5ba1d6 100644 --- a/drivers/staging/omapdrm/omap_drv.c +++ b/drivers/staging/omapdrm/omap_drv.c | |||
@@ -565,6 +565,14 @@ static int dev_load(struct drm_device *dev, unsigned long flags) | |||
565 | 565 | ||
566 | dev->dev_private = priv; | 566 | dev->dev_private = priv; |
567 | 567 | ||
568 | ret = omapdss_compat_init(); | ||
569 | if (ret) { | ||
570 | dev_err(dev->dev, "coult not init omapdss\n"); | ||
571 | dev->dev_private = NULL; | ||
572 | kfree(priv); | ||
573 | return ret; | ||
574 | } | ||
575 | |||
568 | priv->wq = alloc_ordered_workqueue("omapdrm", 0); | 576 | priv->wq = alloc_ordered_workqueue("omapdrm", 0); |
569 | 577 | ||
570 | INIT_LIST_HEAD(&priv->obj_list); | 578 | INIT_LIST_HEAD(&priv->obj_list); |
@@ -576,6 +584,7 @@ static int dev_load(struct drm_device *dev, unsigned long flags) | |||
576 | dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret); | 584 | dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret); |
577 | dev->dev_private = NULL; | 585 | dev->dev_private = NULL; |
578 | kfree(priv); | 586 | kfree(priv); |
587 | omapdss_compat_uninit(); | ||
579 | return ret; | 588 | return ret; |
580 | } | 589 | } |
581 | 590 | ||
@@ -610,6 +619,8 @@ static int dev_unload(struct drm_device *dev) | |||
610 | flush_workqueue(priv->wq); | 619 | flush_workqueue(priv->wq); |
611 | destroy_workqueue(priv->wq); | 620 | destroy_workqueue(priv->wq); |
612 | 621 | ||
622 | omapdss_compat_uninit(); | ||
623 | |||
613 | kfree(dev->dev_private); | 624 | kfree(dev->dev_private); |
614 | dev->dev_private = NULL; | 625 | dev->dev_private = NULL; |
615 | 626 | ||
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index d08d7998a4aa..9c31277b3a81 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -2045,7 +2045,7 @@ config FB_S3C_DEBUG_REGWRITE | |||
2045 | bool "Debug register writes" | 2045 | bool "Debug register writes" |
2046 | depends on FB_S3C | 2046 | depends on FB_S3C |
2047 | ---help--- | 2047 | ---help--- |
2048 | Show all register writes via printk(KERN_DEBUG) | 2048 | Show all register writes via pr_debug() |
2049 | 2049 | ||
2050 | config FB_S3C2410 | 2050 | config FB_S3C2410 |
2051 | tristate "S3C2410 LCD framebuffer support" | 2051 | tristate "S3C2410 LCD framebuffer support" |
@@ -2442,4 +2442,19 @@ config FB_SH_MOBILE_MERAM | |||
2442 | Up to 4 memory channels can be configured, allowing 4 RGB or | 2442 | Up to 4 memory channels can be configured, allowing 4 RGB or |
2443 | 2 YCbCr framebuffers to be configured. | 2443 | 2 YCbCr framebuffers to be configured. |
2444 | 2444 | ||
2445 | config FB_SSD1307 | ||
2446 | tristate "Solomon SSD1307 framebuffer support" | ||
2447 | depends on FB && I2C | ||
2448 | depends on OF | ||
2449 | depends on GENERIC_GPIO | ||
2450 | select FB_SYS_FOPS | ||
2451 | select FB_SYS_FILLRECT | ||
2452 | select FB_SYS_COPYAREA | ||
2453 | select FB_SYS_IMAGEBLIT | ||
2454 | select FB_DEFERRED_IO | ||
2455 | select PWM | ||
2456 | help | ||
2457 | This driver implements support for the Solomon SSD1307 | ||
2458 | OLED controller over I2C. | ||
2459 | |||
2445 | endmenu | 2460 | endmenu |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 23e948ebfab8..768a137a1bac 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -161,6 +161,7 @@ obj-$(CONFIG_FB_BFIN_7393) += bfin_adv7393fb.o | |||
161 | obj-$(CONFIG_FB_MX3) += mx3fb.o | 161 | obj-$(CONFIG_FB_MX3) += mx3fb.o |
162 | obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o | 162 | obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o |
163 | obj-$(CONFIG_FB_MXS) += mxsfb.o | 163 | obj-$(CONFIG_FB_MXS) += mxsfb.o |
164 | obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o | ||
164 | 165 | ||
165 | # the test framebuffer is last | 166 | # the test framebuffer is last |
166 | obj-$(CONFIG_FB_VIRTUAL) += vfb.o | 167 | obj-$(CONFIG_FB_VIRTUAL) += vfb.o |
diff --git a/drivers/video/console/softcursor.c b/drivers/video/console/softcursor.c index 25f835bf3d72..46dd8f5d2e9e 100644 --- a/drivers/video/console/softcursor.c +++ b/drivers/video/console/softcursor.c | |||
@@ -35,8 +35,7 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
35 | dsize = s_pitch * cursor->image.height; | 35 | dsize = s_pitch * cursor->image.height; |
36 | 36 | ||
37 | if (dsize + sizeof(struct fb_image) != ops->cursor_size) { | 37 | if (dsize + sizeof(struct fb_image) != ops->cursor_size) { |
38 | if (ops->cursor_src != NULL) | 38 | kfree(ops->cursor_src); |
39 | kfree(ops->cursor_src); | ||
40 | ops->cursor_size = dsize + sizeof(struct fb_image); | 39 | ops->cursor_size = dsize + sizeof(struct fb_image); |
41 | 40 | ||
42 | ops->cursor_src = kmalloc(ops->cursor_size, GFP_ATOMIC); | 41 | ops->cursor_src = kmalloc(ops->cursor_size, GFP_ATOMIC); |
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 80665f66ac1a..46534e00fe01 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c | |||
@@ -213,62 +213,51 @@ static struct fb_fix_screeninfo da8xx_fb_fix __devinitdata = { | |||
213 | .accel = FB_ACCEL_NONE | 213 | .accel = FB_ACCEL_NONE |
214 | }; | 214 | }; |
215 | 215 | ||
216 | struct da8xx_panel { | 216 | static struct fb_videomode known_lcd_panels[] = { |
217 | const char name[25]; /* Full name <vendor>_<model> */ | ||
218 | unsigned short width; | ||
219 | unsigned short height; | ||
220 | int hfp; /* Horizontal front porch */ | ||
221 | int hbp; /* Horizontal back porch */ | ||
222 | int hsw; /* Horizontal Sync Pulse Width */ | ||
223 | int vfp; /* Vertical front porch */ | ||
224 | int vbp; /* Vertical back porch */ | ||
225 | int vsw; /* Vertical Sync Pulse Width */ | ||
226 | unsigned int pxl_clk; /* Pixel clock */ | ||
227 | unsigned char invert_pxl_clk; /* Invert Pixel clock */ | ||
228 | }; | ||
229 | |||
230 | static struct da8xx_panel known_lcd_panels[] = { | ||
231 | /* Sharp LCD035Q3DG01 */ | 217 | /* Sharp LCD035Q3DG01 */ |
232 | [0] = { | 218 | [0] = { |
233 | .name = "Sharp_LCD035Q3DG01", | 219 | .name = "Sharp_LCD035Q3DG01", |
234 | .width = 320, | 220 | .xres = 320, |
235 | .height = 240, | 221 | .yres = 240, |
236 | .hfp = 8, | 222 | .pixclock = 4608000, |
237 | .hbp = 6, | 223 | .left_margin = 6, |
238 | .hsw = 0, | 224 | .right_margin = 8, |
239 | .vfp = 2, | 225 | .upper_margin = 2, |
240 | .vbp = 2, | 226 | .lower_margin = 2, |
241 | .vsw = 0, | 227 | .hsync_len = 0, |
242 | .pxl_clk = 4608000, | 228 | .vsync_len = 0, |
243 | .invert_pxl_clk = 1, | 229 | .sync = FB_SYNC_CLK_INVERT | |
230 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
244 | }, | 231 | }, |
245 | /* Sharp LK043T1DG01 */ | 232 | /* Sharp LK043T1DG01 */ |
246 | [1] = { | 233 | [1] = { |
247 | .name = "Sharp_LK043T1DG01", | 234 | .name = "Sharp_LK043T1DG01", |
248 | .width = 480, | 235 | .xres = 480, |
249 | .height = 272, | 236 | .yres = 272, |
250 | .hfp = 2, | 237 | .pixclock = 7833600, |
251 | .hbp = 2, | 238 | .left_margin = 2, |
252 | .hsw = 41, | 239 | .right_margin = 2, |
253 | .vfp = 2, | 240 | .upper_margin = 2, |
254 | .vbp = 2, | 241 | .lower_margin = 2, |
255 | .vsw = 10, | 242 | .hsync_len = 41, |
256 | .pxl_clk = 7833600, | 243 | .vsync_len = 10, |
257 | .invert_pxl_clk = 0, | 244 | .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
245 | .flag = 0, | ||
258 | }, | 246 | }, |
259 | [2] = { | 247 | [2] = { |
260 | /* Hitachi SP10Q010 */ | 248 | /* Hitachi SP10Q010 */ |
261 | .name = "SP10Q010", | 249 | .name = "SP10Q010", |
262 | .width = 320, | 250 | .xres = 320, |
263 | .height = 240, | 251 | .yres = 240, |
264 | .hfp = 10, | 252 | .pixclock = 7833600, |
265 | .hbp = 10, | 253 | .left_margin = 10, |
266 | .hsw = 10, | 254 | .right_margin = 10, |
267 | .vfp = 10, | 255 | .upper_margin = 10, |
268 | .vbp = 10, | 256 | .lower_margin = 10, |
269 | .vsw = 10, | 257 | .hsync_len = 10, |
270 | .pxl_clk = 7833600, | 258 | .vsync_len = 10, |
271 | .invert_pxl_clk = 0, | 259 | .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
260 | .flag = 0, | ||
272 | }, | 261 | }, |
273 | }; | 262 | }; |
274 | 263 | ||
@@ -399,10 +388,9 @@ static int lcd_cfg_dma(int burst_size, int fifo_th) | |||
399 | reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8); | 388 | reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8); |
400 | break; | 389 | break; |
401 | case 16: | 390 | case 16: |
391 | default: | ||
402 | reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16); | 392 | reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16); |
403 | break; | 393 | break; |
404 | default: | ||
405 | return -EINVAL; | ||
406 | } | 394 | } |
407 | 395 | ||
408 | reg |= (fifo_th << 8); | 396 | reg |= (fifo_th << 8); |
@@ -447,7 +435,8 @@ static void lcd_cfg_vertical_sync(int back_porch, int pulse_width, | |||
447 | lcdc_write(reg, LCD_RASTER_TIMING_1_REG); | 435 | lcdc_write(reg, LCD_RASTER_TIMING_1_REG); |
448 | } | 436 | } |
449 | 437 | ||
450 | static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) | 438 | static int lcd_cfg_display(const struct lcd_ctrl_config *cfg, |
439 | struct fb_videomode *panel) | ||
451 | { | 440 | { |
452 | u32 reg; | 441 | u32 reg; |
453 | u32 reg_int; | 442 | u32 reg_int; |
@@ -456,7 +445,7 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) | |||
456 | LCD_MONO_8BIT_MODE | | 445 | LCD_MONO_8BIT_MODE | |
457 | LCD_MONOCHROME_MODE); | 446 | LCD_MONOCHROME_MODE); |
458 | 447 | ||
459 | switch (cfg->p_disp_panel->panel_shade) { | 448 | switch (cfg->panel_shade) { |
460 | case MONOCHROME: | 449 | case MONOCHROME: |
461 | reg |= LCD_MONOCHROME_MODE; | 450 | reg |= LCD_MONOCHROME_MODE; |
462 | if (cfg->mono_8bit_mode) | 451 | if (cfg->mono_8bit_mode) |
@@ -469,7 +458,9 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) | |||
469 | break; | 458 | break; |
470 | 459 | ||
471 | case COLOR_PASSIVE: | 460 | case COLOR_PASSIVE: |
472 | if (cfg->stn_565_mode) | 461 | /* AC bias applicable only for Pasive panels */ |
462 | lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt); | ||
463 | if (cfg->bpp == 12 && cfg->stn_565_mode) | ||
473 | reg |= LCD_STN_565_ENABLE; | 464 | reg |= LCD_STN_565_ENABLE; |
474 | break; | 465 | break; |
475 | 466 | ||
@@ -490,22 +481,19 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) | |||
490 | 481 | ||
491 | reg = lcdc_read(LCD_RASTER_TIMING_2_REG); | 482 | reg = lcdc_read(LCD_RASTER_TIMING_2_REG); |
492 | 483 | ||
493 | if (cfg->sync_ctrl) | 484 | reg |= LCD_SYNC_CTRL; |
494 | reg |= LCD_SYNC_CTRL; | ||
495 | else | ||
496 | reg &= ~LCD_SYNC_CTRL; | ||
497 | 485 | ||
498 | if (cfg->sync_edge) | 486 | if (cfg->sync_edge) |
499 | reg |= LCD_SYNC_EDGE; | 487 | reg |= LCD_SYNC_EDGE; |
500 | else | 488 | else |
501 | reg &= ~LCD_SYNC_EDGE; | 489 | reg &= ~LCD_SYNC_EDGE; |
502 | 490 | ||
503 | if (cfg->invert_line_clock) | 491 | if (panel->sync & FB_SYNC_HOR_HIGH_ACT) |
504 | reg |= LCD_INVERT_LINE_CLOCK; | 492 | reg |= LCD_INVERT_LINE_CLOCK; |
505 | else | 493 | else |
506 | reg &= ~LCD_INVERT_LINE_CLOCK; | 494 | reg &= ~LCD_INVERT_LINE_CLOCK; |
507 | 495 | ||
508 | if (cfg->invert_frm_clock) | 496 | if (panel->sync & FB_SYNC_VERT_HIGH_ACT) |
509 | reg |= LCD_INVERT_FRAME_CLOCK; | 497 | reg |= LCD_INVERT_FRAME_CLOCK; |
510 | else | 498 | else |
511 | reg &= ~LCD_INVERT_FRAME_CLOCK; | 499 | reg &= ~LCD_INVERT_FRAME_CLOCK; |
@@ -728,7 +716,7 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par) | |||
728 | } | 716 | } |
729 | 717 | ||
730 | static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, | 718 | static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, |
731 | struct da8xx_panel *panel) | 719 | struct fb_videomode *panel) |
732 | { | 720 | { |
733 | u32 bpp; | 721 | u32 bpp; |
734 | int ret = 0; | 722 | int ret = 0; |
@@ -738,7 +726,7 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, | |||
738 | /* Calculate the divider */ | 726 | /* Calculate the divider */ |
739 | lcd_calc_clk_divider(par); | 727 | lcd_calc_clk_divider(par); |
740 | 728 | ||
741 | if (panel->invert_pxl_clk) | 729 | if (panel->sync & FB_SYNC_CLK_INVERT) |
742 | lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) | | 730 | lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) | |
743 | LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG); | 731 | LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG); |
744 | else | 732 | else |
@@ -750,30 +738,23 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, | |||
750 | if (ret < 0) | 738 | if (ret < 0) |
751 | return ret; | 739 | return ret; |
752 | 740 | ||
753 | /* Configure the AC bias properties. */ | ||
754 | lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt); | ||
755 | |||
756 | /* Configure the vertical and horizontal sync properties. */ | 741 | /* Configure the vertical and horizontal sync properties. */ |
757 | lcd_cfg_vertical_sync(panel->vbp, panel->vsw, panel->vfp); | 742 | lcd_cfg_vertical_sync(panel->lower_margin, panel->vsync_len, |
758 | lcd_cfg_horizontal_sync(panel->hbp, panel->hsw, panel->hfp); | 743 | panel->upper_margin); |
744 | lcd_cfg_horizontal_sync(panel->right_margin, panel->hsync_len, | ||
745 | panel->left_margin); | ||
759 | 746 | ||
760 | /* Configure for disply */ | 747 | /* Configure for disply */ |
761 | ret = lcd_cfg_display(cfg); | 748 | ret = lcd_cfg_display(cfg, panel); |
762 | if (ret < 0) | 749 | if (ret < 0) |
763 | return ret; | 750 | return ret; |
764 | 751 | ||
765 | if (QVGA != cfg->p_disp_panel->panel_type) | 752 | bpp = cfg->bpp; |
766 | return -EINVAL; | ||
767 | 753 | ||
768 | if (cfg->bpp <= cfg->p_disp_panel->max_bpp && | ||
769 | cfg->bpp >= cfg->p_disp_panel->min_bpp) | ||
770 | bpp = cfg->bpp; | ||
771 | else | ||
772 | bpp = cfg->p_disp_panel->max_bpp; | ||
773 | if (bpp == 12) | 754 | if (bpp == 12) |
774 | bpp = 16; | 755 | bpp = 16; |
775 | ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->width, | 756 | ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->xres, |
776 | (unsigned int)panel->height, bpp, | 757 | (unsigned int)panel->yres, bpp, |
777 | cfg->raster_order); | 758 | cfg->raster_order); |
778 | if (ret < 0) | 759 | if (ret < 0) |
779 | return ret; | 760 | return ret; |
@@ -1235,7 +1216,7 @@ static int __devinit fb_probe(struct platform_device *device) | |||
1235 | struct da8xx_lcdc_platform_data *fb_pdata = | 1216 | struct da8xx_lcdc_platform_data *fb_pdata = |
1236 | device->dev.platform_data; | 1217 | device->dev.platform_data; |
1237 | struct lcd_ctrl_config *lcd_cfg; | 1218 | struct lcd_ctrl_config *lcd_cfg; |
1238 | struct da8xx_panel *lcdc_info; | 1219 | struct fb_videomode *lcdc_info; |
1239 | struct fb_info *da8xx_fb_info; | 1220 | struct fb_info *da8xx_fb_info; |
1240 | struct clk *fb_clk = NULL; | 1221 | struct clk *fb_clk = NULL; |
1241 | struct da8xx_fb_par *par; | 1222 | struct da8xx_fb_par *par; |
@@ -1267,7 +1248,7 @@ static int __devinit fb_probe(struct platform_device *device) | |||
1267 | goto err_request_mem; | 1248 | goto err_request_mem; |
1268 | } | 1249 | } |
1269 | 1250 | ||
1270 | fb_clk = clk_get(&device->dev, NULL); | 1251 | fb_clk = clk_get(&device->dev, "fck"); |
1271 | if (IS_ERR(fb_clk)) { | 1252 | if (IS_ERR(fb_clk)) { |
1272 | dev_err(&device->dev, "Can not get device clock\n"); | 1253 | dev_err(&device->dev, "Can not get device clock\n"); |
1273 | ret = -ENODEV; | 1254 | ret = -ENODEV; |
@@ -1283,6 +1264,7 @@ static int __devinit fb_probe(struct platform_device *device) | |||
1283 | lcd_revision = LCD_VERSION_1; | 1264 | lcd_revision = LCD_VERSION_1; |
1284 | break; | 1265 | break; |
1285 | case 0x4F200800: | 1266 | case 0x4F200800: |
1267 | case 0x4F201000: | ||
1286 | lcd_revision = LCD_VERSION_2; | 1268 | lcd_revision = LCD_VERSION_2; |
1287 | break; | 1269 | break; |
1288 | default: | 1270 | default: |
@@ -1323,7 +1305,7 @@ static int __devinit fb_probe(struct platform_device *device) | |||
1323 | #ifdef CONFIG_CPU_FREQ | 1305 | #ifdef CONFIG_CPU_FREQ |
1324 | par->lcd_fck_rate = clk_get_rate(fb_clk); | 1306 | par->lcd_fck_rate = clk_get_rate(fb_clk); |
1325 | #endif | 1307 | #endif |
1326 | par->pxl_clk = lcdc_info->pxl_clk; | 1308 | par->pxl_clk = lcdc_info->pixclock; |
1327 | if (fb_pdata->panel_power_ctrl) { | 1309 | if (fb_pdata->panel_power_ctrl) { |
1328 | par->panel_power_ctrl = fb_pdata->panel_power_ctrl; | 1310 | par->panel_power_ctrl = fb_pdata->panel_power_ctrl; |
1329 | par->panel_power_ctrl(1); | 1311 | par->panel_power_ctrl(1); |
@@ -1336,8 +1318,8 @@ static int __devinit fb_probe(struct platform_device *device) | |||
1336 | } | 1318 | } |
1337 | 1319 | ||
1338 | /* allocate frame buffer */ | 1320 | /* allocate frame buffer */ |
1339 | par->vram_size = lcdc_info->width * lcdc_info->height * lcd_cfg->bpp; | 1321 | par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp; |
1340 | ulcm = lcm((lcdc_info->width * lcd_cfg->bpp)/8, PAGE_SIZE); | 1322 | ulcm = lcm((lcdc_info->xres * lcd_cfg->bpp)/8, PAGE_SIZE); |
1341 | par->vram_size = roundup(par->vram_size/8, ulcm); | 1323 | par->vram_size = roundup(par->vram_size/8, ulcm); |
1342 | par->vram_size = par->vram_size * LCD_NUM_BUFFERS; | 1324 | par->vram_size = par->vram_size * LCD_NUM_BUFFERS; |
1343 | 1325 | ||
@@ -1355,10 +1337,10 @@ static int __devinit fb_probe(struct platform_device *device) | |||
1355 | da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt; | 1337 | da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt; |
1356 | da8xx_fb_fix.smem_start = par->vram_phys; | 1338 | da8xx_fb_fix.smem_start = par->vram_phys; |
1357 | da8xx_fb_fix.smem_len = par->vram_size; | 1339 | da8xx_fb_fix.smem_len = par->vram_size; |
1358 | da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8; | 1340 | da8xx_fb_fix.line_length = (lcdc_info->xres * lcd_cfg->bpp) / 8; |
1359 | 1341 | ||
1360 | par->dma_start = par->vram_phys; | 1342 | par->dma_start = par->vram_phys; |
1361 | par->dma_end = par->dma_start + lcdc_info->height * | 1343 | par->dma_end = par->dma_start + lcdc_info->yres * |
1362 | da8xx_fb_fix.line_length - 1; | 1344 | da8xx_fb_fix.line_length - 1; |
1363 | 1345 | ||
1364 | /* allocate palette buffer */ | 1346 | /* allocate palette buffer */ |
@@ -1384,22 +1366,22 @@ static int __devinit fb_probe(struct platform_device *device) | |||
1384 | /* Initialize par */ | 1366 | /* Initialize par */ |
1385 | da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp; | 1367 | da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp; |
1386 | 1368 | ||
1387 | da8xx_fb_var.xres = lcdc_info->width; | 1369 | da8xx_fb_var.xres = lcdc_info->xres; |
1388 | da8xx_fb_var.xres_virtual = lcdc_info->width; | 1370 | da8xx_fb_var.xres_virtual = lcdc_info->xres; |
1389 | 1371 | ||
1390 | da8xx_fb_var.yres = lcdc_info->height; | 1372 | da8xx_fb_var.yres = lcdc_info->yres; |
1391 | da8xx_fb_var.yres_virtual = lcdc_info->height * LCD_NUM_BUFFERS; | 1373 | da8xx_fb_var.yres_virtual = lcdc_info->yres * LCD_NUM_BUFFERS; |
1392 | 1374 | ||
1393 | da8xx_fb_var.grayscale = | 1375 | da8xx_fb_var.grayscale = |
1394 | lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0; | 1376 | lcd_cfg->panel_shade == MONOCHROME ? 1 : 0; |
1395 | da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp; | 1377 | da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp; |
1396 | 1378 | ||
1397 | da8xx_fb_var.hsync_len = lcdc_info->hsw; | 1379 | da8xx_fb_var.hsync_len = lcdc_info->hsync_len; |
1398 | da8xx_fb_var.vsync_len = lcdc_info->vsw; | 1380 | da8xx_fb_var.vsync_len = lcdc_info->vsync_len; |
1399 | da8xx_fb_var.right_margin = lcdc_info->hfp; | 1381 | da8xx_fb_var.right_margin = lcdc_info->right_margin; |
1400 | da8xx_fb_var.left_margin = lcdc_info->hbp; | 1382 | da8xx_fb_var.left_margin = lcdc_info->left_margin; |
1401 | da8xx_fb_var.lower_margin = lcdc_info->vfp; | 1383 | da8xx_fb_var.lower_margin = lcdc_info->lower_margin; |
1402 | da8xx_fb_var.upper_margin = lcdc_info->vbp; | 1384 | da8xx_fb_var.upper_margin = lcdc_info->upper_margin; |
1403 | da8xx_fb_var.pixclock = da8xxfb_pixel_clk_period(par); | 1385 | da8xx_fb_var.pixclock = da8xxfb_pixel_clk_period(par); |
1404 | 1386 | ||
1405 | /* Initialize fbinfo */ | 1387 | /* Initialize fbinfo */ |
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c index d55470e75412..28fd686c6b81 100644 --- a/drivers/video/exynos/exynos_dp_core.c +++ b/drivers/video/exynos/exynos_dp_core.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/of.h> | ||
21 | 22 | ||
22 | #include <video/exynos_dp.h> | 23 | #include <video/exynos_dp.h> |
23 | 24 | ||
@@ -48,10 +49,6 @@ static int exynos_dp_detect_hpd(struct exynos_dp_device *dp) | |||
48 | { | 49 | { |
49 | int timeout_loop = 0; | 50 | int timeout_loop = 0; |
50 | 51 | ||
51 | exynos_dp_init_hpd(dp); | ||
52 | |||
53 | usleep_range(200, 210); | ||
54 | |||
55 | while (exynos_dp_get_plug_in_status(dp) != 0) { | 52 | while (exynos_dp_get_plug_in_status(dp) != 0) { |
56 | timeout_loop++; | 53 | timeout_loop++; |
57 | if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { | 54 | if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { |
@@ -90,9 +87,11 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) | |||
90 | */ | 87 | */ |
91 | 88 | ||
92 | /* Read Extension Flag, Number of 128-byte EDID extension blocks */ | 89 | /* Read Extension Flag, Number of 128-byte EDID extension blocks */ |
93 | exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR, | 90 | retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR, |
94 | EDID_EXTENSION_FLAG, | 91 | EDID_EXTENSION_FLAG, |
95 | &extend_block); | 92 | &extend_block); |
93 | if (retval) | ||
94 | return retval; | ||
96 | 95 | ||
97 | if (extend_block > 0) { | 96 | if (extend_block > 0) { |
98 | dev_dbg(dp->dev, "EDID data includes a single extension!\n"); | 97 | dev_dbg(dp->dev, "EDID data includes a single extension!\n"); |
@@ -181,14 +180,15 @@ static int exynos_dp_handle_edid(struct exynos_dp_device *dp) | |||
181 | int retval; | 180 | int retval; |
182 | 181 | ||
183 | /* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */ | 182 | /* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */ |
184 | exynos_dp_read_bytes_from_dpcd(dp, | 183 | retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_DPCD_REV, |
185 | DPCD_ADDR_DPCD_REV, | 184 | 12, buf); |
186 | 12, buf); | 185 | if (retval) |
186 | return retval; | ||
187 | 187 | ||
188 | /* Read EDID */ | 188 | /* Read EDID */ |
189 | for (i = 0; i < 3; i++) { | 189 | for (i = 0; i < 3; i++) { |
190 | retval = exynos_dp_read_edid(dp); | 190 | retval = exynos_dp_read_edid(dp); |
191 | if (retval == 0) | 191 | if (!retval) |
192 | break; | 192 | break; |
193 | } | 193 | } |
194 | 194 | ||
@@ -261,11 +261,10 @@ static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp, | |||
261 | } | 261 | } |
262 | } | 262 | } |
263 | 263 | ||
264 | static void exynos_dp_link_start(struct exynos_dp_device *dp) | 264 | static int exynos_dp_link_start(struct exynos_dp_device *dp) |
265 | { | 265 | { |
266 | u8 buf[4]; | 266 | u8 buf[4]; |
267 | int lane; | 267 | int lane, lane_count, pll_tries, retval; |
268 | int lane_count; | ||
269 | 268 | ||
270 | lane_count = dp->link_train.lane_count; | 269 | lane_count = dp->link_train.lane_count; |
271 | 270 | ||
@@ -275,10 +274,6 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp) | |||
275 | for (lane = 0; lane < lane_count; lane++) | 274 | for (lane = 0; lane < lane_count; lane++) |
276 | dp->link_train.cr_loop[lane] = 0; | 275 | dp->link_train.cr_loop[lane] = 0; |
277 | 276 | ||
278 | /* Set sink to D0 (Sink Not Ready) mode. */ | ||
279 | exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE, | ||
280 | DPCD_SET_POWER_STATE_D0); | ||
281 | |||
282 | /* Set link rate and count as you want to establish*/ | 277 | /* Set link rate and count as you want to establish*/ |
283 | exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate); | 278 | exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate); |
284 | exynos_dp_set_lane_count(dp, dp->link_train.lane_count); | 279 | exynos_dp_set_lane_count(dp, dp->link_train.lane_count); |
@@ -286,29 +281,46 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp) | |||
286 | /* Setup RX configuration */ | 281 | /* Setup RX configuration */ |
287 | buf[0] = dp->link_train.link_rate; | 282 | buf[0] = dp->link_train.link_rate; |
288 | buf[1] = dp->link_train.lane_count; | 283 | buf[1] = dp->link_train.lane_count; |
289 | exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET, | 284 | retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET, |
290 | 2, buf); | 285 | 2, buf); |
286 | if (retval) | ||
287 | return retval; | ||
291 | 288 | ||
292 | /* Set TX pre-emphasis to minimum */ | 289 | /* Set TX pre-emphasis to minimum */ |
293 | for (lane = 0; lane < lane_count; lane++) | 290 | for (lane = 0; lane < lane_count; lane++) |
294 | exynos_dp_set_lane_lane_pre_emphasis(dp, | 291 | exynos_dp_set_lane_lane_pre_emphasis(dp, |
295 | PRE_EMPHASIS_LEVEL_0, lane); | 292 | PRE_EMPHASIS_LEVEL_0, lane); |
296 | 293 | ||
294 | /* Wait for PLL lock */ | ||
295 | pll_tries = 0; | ||
296 | while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { | ||
297 | if (pll_tries == DP_TIMEOUT_LOOP_COUNT) { | ||
298 | dev_err(dp->dev, "Wait for PLL lock timed out\n"); | ||
299 | return -ETIMEDOUT; | ||
300 | } | ||
301 | |||
302 | pll_tries++; | ||
303 | usleep_range(90, 120); | ||
304 | } | ||
305 | |||
297 | /* Set training pattern 1 */ | 306 | /* Set training pattern 1 */ |
298 | exynos_dp_set_training_pattern(dp, TRAINING_PTN1); | 307 | exynos_dp_set_training_pattern(dp, TRAINING_PTN1); |
299 | 308 | ||
300 | /* Set RX training pattern */ | 309 | /* Set RX training pattern */ |
301 | exynos_dp_write_byte_to_dpcd(dp, | 310 | retval = exynos_dp_write_byte_to_dpcd(dp, |
302 | DPCD_ADDR_TRAINING_PATTERN_SET, | 311 | DPCD_ADDR_TRAINING_PATTERN_SET, |
303 | DPCD_SCRAMBLING_DISABLED | | 312 | DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1); |
304 | DPCD_TRAINING_PATTERN_1); | 313 | if (retval) |
314 | return retval; | ||
305 | 315 | ||
306 | for (lane = 0; lane < lane_count; lane++) | 316 | for (lane = 0; lane < lane_count; lane++) |
307 | buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 | | 317 | buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 | |
308 | DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0; | 318 | DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0; |
309 | exynos_dp_write_bytes_to_dpcd(dp, | 319 | |
310 | DPCD_ADDR_TRAINING_LANE0_SET, | 320 | retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET, |
311 | lane_count, buf); | 321 | lane_count, buf); |
322 | |||
323 | return retval; | ||
312 | } | 324 | } |
313 | 325 | ||
314 | static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane) | 326 | static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane) |
@@ -332,18 +344,17 @@ static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count) | |||
332 | return 0; | 344 | return 0; |
333 | } | 345 | } |
334 | 346 | ||
335 | static int exynos_dp_channel_eq_ok(u8 link_align[3], int lane_count) | 347 | static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align, |
348 | int lane_count) | ||
336 | { | 349 | { |
337 | int lane; | 350 | int lane; |
338 | u8 lane_align; | ||
339 | u8 lane_status; | 351 | u8 lane_status; |
340 | 352 | ||
341 | lane_align = link_align[2]; | 353 | if ((link_align & DPCD_INTERLANE_ALIGN_DONE) == 0) |
342 | if ((lane_align & DPCD_INTERLANE_ALIGN_DONE) == 0) | ||
343 | return -EINVAL; | 354 | return -EINVAL; |
344 | 355 | ||
345 | for (lane = 0; lane < lane_count; lane++) { | 356 | for (lane = 0; lane < lane_count; lane++) { |
346 | lane_status = exynos_dp_get_lane_status(link_align, lane); | 357 | lane_status = exynos_dp_get_lane_status(link_status, lane); |
347 | lane_status &= DPCD_CHANNEL_EQ_BITS; | 358 | lane_status &= DPCD_CHANNEL_EQ_BITS; |
348 | if (lane_status != DPCD_CHANNEL_EQ_BITS) | 359 | if (lane_status != DPCD_CHANNEL_EQ_BITS) |
349 | return -EINVAL; | 360 | return -EINVAL; |
@@ -427,60 +438,60 @@ static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp) | |||
427 | dp->link_train.lt_state = FAILED; | 438 | dp->link_train.lt_state = FAILED; |
428 | } | 439 | } |
429 | 440 | ||
430 | static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) | 441 | static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp, |
442 | u8 adjust_request[2]) | ||
431 | { | 443 | { |
432 | u8 link_status[2]; | 444 | int lane, lane_count; |
433 | int lane; | 445 | u8 voltage_swing, pre_emphasis, training_lane; |
434 | int lane_count; | ||
435 | 446 | ||
436 | u8 adjust_request[2]; | 447 | lane_count = dp->link_train.lane_count; |
437 | u8 voltage_swing; | 448 | for (lane = 0; lane < lane_count; lane++) { |
438 | u8 pre_emphasis; | 449 | voltage_swing = exynos_dp_get_adjust_request_voltage( |
439 | u8 training_lane; | 450 | adjust_request, lane); |
451 | pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( | ||
452 | adjust_request, lane); | ||
453 | training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | | ||
454 | DPCD_PRE_EMPHASIS_SET(pre_emphasis); | ||
455 | |||
456 | if (voltage_swing == VOLTAGE_LEVEL_3) | ||
457 | training_lane |= DPCD_MAX_SWING_REACHED; | ||
458 | if (pre_emphasis == PRE_EMPHASIS_LEVEL_3) | ||
459 | training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED; | ||
460 | |||
461 | dp->link_train.training_lane[lane] = training_lane; | ||
462 | } | ||
463 | } | ||
464 | |||
465 | static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) | ||
466 | { | ||
467 | int lane, lane_count, retval; | ||
468 | u8 voltage_swing, pre_emphasis, training_lane; | ||
469 | u8 link_status[2], adjust_request[2]; | ||
440 | 470 | ||
441 | usleep_range(100, 101); | 471 | usleep_range(100, 101); |
442 | 472 | ||
443 | lane_count = dp->link_train.lane_count; | 473 | lane_count = dp->link_train.lane_count; |
444 | 474 | ||
445 | exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS, | 475 | retval = exynos_dp_read_bytes_from_dpcd(dp, |
446 | 2, link_status); | 476 | DPCD_ADDR_LANE0_1_STATUS, 2, link_status); |
477 | if (retval) | ||
478 | return retval; | ||
479 | |||
480 | retval = exynos_dp_read_bytes_from_dpcd(dp, | ||
481 | DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request); | ||
482 | if (retval) | ||
483 | return retval; | ||
447 | 484 | ||
448 | if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) { | 485 | if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) { |
449 | /* set training pattern 2 for EQ */ | 486 | /* set training pattern 2 for EQ */ |
450 | exynos_dp_set_training_pattern(dp, TRAINING_PTN2); | 487 | exynos_dp_set_training_pattern(dp, TRAINING_PTN2); |
451 | 488 | ||
452 | for (lane = 0; lane < lane_count; lane++) { | 489 | retval = exynos_dp_write_byte_to_dpcd(dp, |
453 | exynos_dp_read_bytes_from_dpcd(dp, | 490 | DPCD_ADDR_TRAINING_PATTERN_SET, |
454 | DPCD_ADDR_ADJUST_REQUEST_LANE0_1, | 491 | DPCD_SCRAMBLING_DISABLED | |
455 | 2, adjust_request); | 492 | DPCD_TRAINING_PATTERN_2); |
456 | voltage_swing = exynos_dp_get_adjust_request_voltage( | 493 | if (retval) |
457 | adjust_request, lane); | 494 | return retval; |
458 | pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( | ||
459 | adjust_request, lane); | ||
460 | training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | | ||
461 | DPCD_PRE_EMPHASIS_SET(pre_emphasis); | ||
462 | |||
463 | if (voltage_swing == VOLTAGE_LEVEL_3) | ||
464 | training_lane |= DPCD_MAX_SWING_REACHED; | ||
465 | if (pre_emphasis == PRE_EMPHASIS_LEVEL_3) | ||
466 | training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED; | ||
467 | |||
468 | dp->link_train.training_lane[lane] = training_lane; | ||
469 | |||
470 | exynos_dp_set_lane_link_training(dp, | ||
471 | dp->link_train.training_lane[lane], | ||
472 | lane); | ||
473 | } | ||
474 | |||
475 | exynos_dp_write_byte_to_dpcd(dp, | ||
476 | DPCD_ADDR_TRAINING_PATTERN_SET, | ||
477 | DPCD_SCRAMBLING_DISABLED | | ||
478 | DPCD_TRAINING_PATTERN_2); | ||
479 | |||
480 | exynos_dp_write_bytes_to_dpcd(dp, | ||
481 | DPCD_ADDR_TRAINING_LANE0_SET, | ||
482 | lane_count, | ||
483 | dp->link_train.training_lane); | ||
484 | 495 | ||
485 | dev_info(dp->dev, "Link Training Clock Recovery success\n"); | 496 | dev_info(dp->dev, "Link Training Clock Recovery success\n"); |
486 | dp->link_train.lt_state = EQUALIZER_TRAINING; | 497 | dp->link_train.lt_state = EQUALIZER_TRAINING; |
@@ -488,152 +499,116 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) | |||
488 | for (lane = 0; lane < lane_count; lane++) { | 499 | for (lane = 0; lane < lane_count; lane++) { |
489 | training_lane = exynos_dp_get_lane_link_training( | 500 | training_lane = exynos_dp_get_lane_link_training( |
490 | dp, lane); | 501 | dp, lane); |
491 | exynos_dp_read_bytes_from_dpcd(dp, | ||
492 | DPCD_ADDR_ADJUST_REQUEST_LANE0_1, | ||
493 | 2, adjust_request); | ||
494 | voltage_swing = exynos_dp_get_adjust_request_voltage( | 502 | voltage_swing = exynos_dp_get_adjust_request_voltage( |
495 | adjust_request, lane); | 503 | adjust_request, lane); |
496 | pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( | 504 | pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( |
497 | adjust_request, lane); | 505 | adjust_request, lane); |
498 | 506 | ||
499 | if (voltage_swing == VOLTAGE_LEVEL_3 || | 507 | if (DPCD_VOLTAGE_SWING_GET(training_lane) == |
500 | pre_emphasis == PRE_EMPHASIS_LEVEL_3) { | 508 | voltage_swing && |
501 | dev_err(dp->dev, "voltage or pre emphasis reached max level\n"); | 509 | DPCD_PRE_EMPHASIS_GET(training_lane) == |
502 | goto reduce_link_rate; | 510 | pre_emphasis) |
503 | } | ||
504 | |||
505 | if ((DPCD_VOLTAGE_SWING_GET(training_lane) == | ||
506 | voltage_swing) && | ||
507 | (DPCD_PRE_EMPHASIS_GET(training_lane) == | ||
508 | pre_emphasis)) { | ||
509 | dp->link_train.cr_loop[lane]++; | 511 | dp->link_train.cr_loop[lane]++; |
510 | if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP) { | ||
511 | dev_err(dp->dev, "CR Max loop\n"); | ||
512 | goto reduce_link_rate; | ||
513 | } | ||
514 | } | ||
515 | |||
516 | training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | | ||
517 | DPCD_PRE_EMPHASIS_SET(pre_emphasis); | ||
518 | 512 | ||
519 | if (voltage_swing == VOLTAGE_LEVEL_3) | 513 | if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP || |
520 | training_lane |= DPCD_MAX_SWING_REACHED; | 514 | voltage_swing == VOLTAGE_LEVEL_3 || |
521 | if (pre_emphasis == PRE_EMPHASIS_LEVEL_3) | 515 | pre_emphasis == PRE_EMPHASIS_LEVEL_3) { |
522 | training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED; | 516 | dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n", |
517 | dp->link_train.cr_loop[lane], | ||
518 | voltage_swing, pre_emphasis); | ||
519 | exynos_dp_reduce_link_rate(dp); | ||
520 | return -EIO; | ||
521 | } | ||
522 | } | ||
523 | } | ||
523 | 524 | ||
524 | dp->link_train.training_lane[lane] = training_lane; | 525 | exynos_dp_get_adjust_training_lane(dp, adjust_request); |
525 | 526 | ||
526 | exynos_dp_set_lane_link_training(dp, | 527 | for (lane = 0; lane < lane_count; lane++) |
527 | dp->link_train.training_lane[lane], lane); | 528 | exynos_dp_set_lane_link_training(dp, |
528 | } | 529 | dp->link_train.training_lane[lane], lane); |
529 | 530 | ||
530 | exynos_dp_write_bytes_to_dpcd(dp, | 531 | retval = exynos_dp_write_bytes_to_dpcd(dp, |
531 | DPCD_ADDR_TRAINING_LANE0_SET, | 532 | DPCD_ADDR_TRAINING_LANE0_SET, lane_count, |
532 | lane_count, | ||
533 | dp->link_train.training_lane); | 533 | dp->link_train.training_lane); |
534 | } | 534 | if (retval) |
535 | 535 | return retval; | |
536 | return 0; | ||
537 | 536 | ||
538 | reduce_link_rate: | 537 | return retval; |
539 | exynos_dp_reduce_link_rate(dp); | ||
540 | return -EIO; | ||
541 | } | 538 | } |
542 | 539 | ||
543 | static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) | 540 | static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) |
544 | { | 541 | { |
545 | u8 link_status[2]; | 542 | int lane, lane_count, retval; |
546 | u8 link_align[3]; | ||
547 | int lane; | ||
548 | int lane_count; | ||
549 | u32 reg; | 543 | u32 reg; |
550 | 544 | u8 link_align, link_status[2], adjust_request[2]; | |
551 | u8 adjust_request[2]; | ||
552 | u8 voltage_swing; | ||
553 | u8 pre_emphasis; | ||
554 | u8 training_lane; | ||
555 | 545 | ||
556 | usleep_range(400, 401); | 546 | usleep_range(400, 401); |
557 | 547 | ||
558 | lane_count = dp->link_train.lane_count; | 548 | lane_count = dp->link_train.lane_count; |
559 | 549 | ||
560 | exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS, | 550 | retval = exynos_dp_read_bytes_from_dpcd(dp, |
561 | 2, link_status); | 551 | DPCD_ADDR_LANE0_1_STATUS, 2, link_status); |
552 | if (retval) | ||
553 | return retval; | ||
562 | 554 | ||
563 | if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) { | 555 | if (exynos_dp_clock_recovery_ok(link_status, lane_count)) { |
564 | link_align[0] = link_status[0]; | 556 | exynos_dp_reduce_link_rate(dp); |
565 | link_align[1] = link_status[1]; | 557 | return -EIO; |
558 | } | ||
566 | 559 | ||
567 | exynos_dp_read_byte_from_dpcd(dp, | 560 | retval = exynos_dp_read_bytes_from_dpcd(dp, |
568 | DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, | 561 | DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request); |
569 | &link_align[2]); | 562 | if (retval) |
563 | return retval; | ||
570 | 564 | ||
571 | for (lane = 0; lane < lane_count; lane++) { | 565 | retval = exynos_dp_read_byte_from_dpcd(dp, |
572 | exynos_dp_read_bytes_from_dpcd(dp, | 566 | DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, &link_align); |
573 | DPCD_ADDR_ADJUST_REQUEST_LANE0_1, | 567 | if (retval) |
574 | 2, adjust_request); | 568 | return retval; |
575 | voltage_swing = exynos_dp_get_adjust_request_voltage( | ||
576 | adjust_request, lane); | ||
577 | pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( | ||
578 | adjust_request, lane); | ||
579 | training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | | ||
580 | DPCD_PRE_EMPHASIS_SET(pre_emphasis); | ||
581 | 569 | ||
582 | if (voltage_swing == VOLTAGE_LEVEL_3) | 570 | exynos_dp_get_adjust_training_lane(dp, adjust_request); |
583 | training_lane |= DPCD_MAX_SWING_REACHED; | ||
584 | if (pre_emphasis == PRE_EMPHASIS_LEVEL_3) | ||
585 | training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED; | ||
586 | 571 | ||
587 | dp->link_train.training_lane[lane] = training_lane; | 572 | if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count)) { |
588 | } | 573 | /* traing pattern Set to Normal */ |
574 | exynos_dp_training_pattern_dis(dp); | ||
589 | 575 | ||
590 | if (exynos_dp_channel_eq_ok(link_align, lane_count) == 0) { | 576 | dev_info(dp->dev, "Link Training success!\n"); |
591 | /* traing pattern Set to Normal */ | ||
592 | exynos_dp_training_pattern_dis(dp); | ||
593 | 577 | ||
594 | dev_info(dp->dev, "Link Training success!\n"); | 578 | exynos_dp_get_link_bandwidth(dp, ®); |
595 | 579 | dp->link_train.link_rate = reg; | |
596 | exynos_dp_get_link_bandwidth(dp, ®); | 580 | dev_dbg(dp->dev, "final bandwidth = %.2x\n", |
597 | dp->link_train.link_rate = reg; | 581 | dp->link_train.link_rate); |
598 | dev_dbg(dp->dev, "final bandwidth = %.2x\n", | ||
599 | dp->link_train.link_rate); | ||
600 | 582 | ||
601 | exynos_dp_get_lane_count(dp, ®); | 583 | exynos_dp_get_lane_count(dp, ®); |
602 | dp->link_train.lane_count = reg; | 584 | dp->link_train.lane_count = reg; |
603 | dev_dbg(dp->dev, "final lane count = %.2x\n", | 585 | dev_dbg(dp->dev, "final lane count = %.2x\n", |
604 | dp->link_train.lane_count); | 586 | dp->link_train.lane_count); |
605 | 587 | ||
606 | /* set enhanced mode if available */ | 588 | /* set enhanced mode if available */ |
607 | exynos_dp_set_enhanced_mode(dp); | 589 | exynos_dp_set_enhanced_mode(dp); |
608 | dp->link_train.lt_state = FINISHED; | 590 | dp->link_train.lt_state = FINISHED; |
609 | } else { | ||
610 | /* not all locked */ | ||
611 | dp->link_train.eq_loop++; | ||
612 | 591 | ||
613 | if (dp->link_train.eq_loop > MAX_EQ_LOOP) { | 592 | return 0; |
614 | dev_err(dp->dev, "EQ Max loop\n"); | 593 | } |
615 | goto reduce_link_rate; | ||
616 | } | ||
617 | 594 | ||
618 | for (lane = 0; lane < lane_count; lane++) | 595 | /* not all locked */ |
619 | exynos_dp_set_lane_link_training(dp, | 596 | dp->link_train.eq_loop++; |
620 | dp->link_train.training_lane[lane], | ||
621 | lane); | ||
622 | 597 | ||
623 | exynos_dp_write_bytes_to_dpcd(dp, | 598 | if (dp->link_train.eq_loop > MAX_EQ_LOOP) { |
624 | DPCD_ADDR_TRAINING_LANE0_SET, | 599 | dev_err(dp->dev, "EQ Max loop\n"); |
625 | lane_count, | 600 | exynos_dp_reduce_link_rate(dp); |
626 | dp->link_train.training_lane); | 601 | return -EIO; |
627 | } | ||
628 | } else { | ||
629 | goto reduce_link_rate; | ||
630 | } | 602 | } |
631 | 603 | ||
632 | return 0; | 604 | for (lane = 0; lane < lane_count; lane++) |
605 | exynos_dp_set_lane_link_training(dp, | ||
606 | dp->link_train.training_lane[lane], lane); | ||
607 | |||
608 | retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET, | ||
609 | lane_count, dp->link_train.training_lane); | ||
633 | 610 | ||
634 | reduce_link_rate: | 611 | return retval; |
635 | exynos_dp_reduce_link_rate(dp); | ||
636 | return -EIO; | ||
637 | } | 612 | } |
638 | 613 | ||
639 | static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp, | 614 | static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp, |
@@ -701,16 +676,17 @@ static void exynos_dp_init_training(struct exynos_dp_device *dp, | |||
701 | 676 | ||
702 | static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) | 677 | static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) |
703 | { | 678 | { |
704 | int retval = 0; | 679 | int retval = 0, training_finished = 0; |
705 | int training_finished = 0; | ||
706 | 680 | ||
707 | dp->link_train.lt_state = START; | 681 | dp->link_train.lt_state = START; |
708 | 682 | ||
709 | /* Process here */ | 683 | /* Process here */ |
710 | while (!training_finished) { | 684 | while (!retval && !training_finished) { |
711 | switch (dp->link_train.lt_state) { | 685 | switch (dp->link_train.lt_state) { |
712 | case START: | 686 | case START: |
713 | exynos_dp_link_start(dp); | 687 | retval = exynos_dp_link_start(dp); |
688 | if (retval) | ||
689 | dev_err(dp->dev, "LT link start failed!\n"); | ||
714 | break; | 690 | break; |
715 | case CLOCK_RECOVERY: | 691 | case CLOCK_RECOVERY: |
716 | retval = exynos_dp_process_clock_recovery(dp); | 692 | retval = exynos_dp_process_clock_recovery(dp); |
@@ -729,6 +705,8 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) | |||
729 | return -EREMOTEIO; | 705 | return -EREMOTEIO; |
730 | } | 706 | } |
731 | } | 707 | } |
708 | if (retval) | ||
709 | dev_err(dp->dev, "eDP link training failed (%d)\n", retval); | ||
732 | 710 | ||
733 | return retval; | 711 | return retval; |
734 | } | 712 | } |
@@ -752,19 +730,15 @@ static int exynos_dp_set_link_train(struct exynos_dp_device *dp, | |||
752 | return retval; | 730 | return retval; |
753 | } | 731 | } |
754 | 732 | ||
755 | static int exynos_dp_config_video(struct exynos_dp_device *dp, | 733 | static int exynos_dp_config_video(struct exynos_dp_device *dp) |
756 | struct video_info *video_info) | ||
757 | { | 734 | { |
758 | int retval = 0; | 735 | int retval = 0; |
759 | int timeout_loop = 0; | 736 | int timeout_loop = 0; |
760 | int done_count = 0; | 737 | int done_count = 0; |
761 | 738 | ||
762 | exynos_dp_config_video_slave_mode(dp, video_info); | 739 | exynos_dp_config_video_slave_mode(dp); |
763 | 740 | ||
764 | exynos_dp_set_video_color_format(dp, video_info->color_depth, | 741 | exynos_dp_set_video_color_format(dp); |
765 | video_info->color_space, | ||
766 | video_info->dynamic_range, | ||
767 | video_info->ycbcr_coeff); | ||
768 | 742 | ||
769 | if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { | 743 | if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { |
770 | dev_err(dp->dev, "PLL is not locked yet.\n"); | 744 | dev_err(dp->dev, "PLL is not locked yet.\n"); |
@@ -852,10 +826,213 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg) | |||
852 | { | 826 | { |
853 | struct exynos_dp_device *dp = arg; | 827 | struct exynos_dp_device *dp = arg; |
854 | 828 | ||
855 | dev_err(dp->dev, "exynos_dp_irq_handler\n"); | 829 | enum dp_irq_type irq_type; |
830 | |||
831 | irq_type = exynos_dp_get_irq_type(dp); | ||
832 | switch (irq_type) { | ||
833 | case DP_IRQ_TYPE_HP_CABLE_IN: | ||
834 | dev_dbg(dp->dev, "Received irq - cable in\n"); | ||
835 | schedule_work(&dp->hotplug_work); | ||
836 | exynos_dp_clear_hotplug_interrupts(dp); | ||
837 | break; | ||
838 | case DP_IRQ_TYPE_HP_CABLE_OUT: | ||
839 | dev_dbg(dp->dev, "Received irq - cable out\n"); | ||
840 | exynos_dp_clear_hotplug_interrupts(dp); | ||
841 | break; | ||
842 | case DP_IRQ_TYPE_HP_CHANGE: | ||
843 | /* | ||
844 | * We get these change notifications once in a while, but there | ||
845 | * is nothing we can do with them. Just ignore it for now and | ||
846 | * only handle cable changes. | ||
847 | */ | ||
848 | dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n"); | ||
849 | exynos_dp_clear_hotplug_interrupts(dp); | ||
850 | break; | ||
851 | default: | ||
852 | dev_err(dp->dev, "Received irq - unknown type!\n"); | ||
853 | break; | ||
854 | } | ||
856 | return IRQ_HANDLED; | 855 | return IRQ_HANDLED; |
857 | } | 856 | } |
858 | 857 | ||
858 | static void exynos_dp_hotplug(struct work_struct *work) | ||
859 | { | ||
860 | struct exynos_dp_device *dp; | ||
861 | int ret; | ||
862 | |||
863 | dp = container_of(work, struct exynos_dp_device, hotplug_work); | ||
864 | |||
865 | ret = exynos_dp_detect_hpd(dp); | ||
866 | if (ret) { | ||
867 | /* Cable has been disconnected, we're done */ | ||
868 | return; | ||
869 | } | ||
870 | |||
871 | ret = exynos_dp_handle_edid(dp); | ||
872 | if (ret) { | ||
873 | dev_err(dp->dev, "unable to handle edid\n"); | ||
874 | return; | ||
875 | } | ||
876 | |||
877 | ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count, | ||
878 | dp->video_info->link_rate); | ||
879 | if (ret) { | ||
880 | dev_err(dp->dev, "unable to do link train\n"); | ||
881 | return; | ||
882 | } | ||
883 | |||
884 | exynos_dp_enable_scramble(dp, 1); | ||
885 | exynos_dp_enable_rx_to_enhanced_mode(dp, 1); | ||
886 | exynos_dp_enable_enhanced_mode(dp, 1); | ||
887 | |||
888 | exynos_dp_set_lane_count(dp, dp->video_info->lane_count); | ||
889 | exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate); | ||
890 | |||
891 | exynos_dp_init_video(dp); | ||
892 | ret = exynos_dp_config_video(dp); | ||
893 | if (ret) | ||
894 | dev_err(dp->dev, "unable to config video\n"); | ||
895 | } | ||
896 | |||
897 | #ifdef CONFIG_OF | ||
898 | static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev) | ||
899 | { | ||
900 | struct device_node *dp_node = dev->of_node; | ||
901 | struct exynos_dp_platdata *pd; | ||
902 | struct video_info *dp_video_config; | ||
903 | |||
904 | pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); | ||
905 | if (!pd) { | ||
906 | dev_err(dev, "memory allocation for pdata failed\n"); | ||
907 | return ERR_PTR(-ENOMEM); | ||
908 | } | ||
909 | dp_video_config = devm_kzalloc(dev, | ||
910 | sizeof(*dp_video_config), GFP_KERNEL); | ||
911 | |||
912 | if (!dp_video_config) { | ||
913 | dev_err(dev, "memory allocation for video config failed\n"); | ||
914 | return ERR_PTR(-ENOMEM); | ||
915 | } | ||
916 | pd->video_info = dp_video_config; | ||
917 | |||
918 | dp_video_config->h_sync_polarity = | ||
919 | of_property_read_bool(dp_node, "hsync-active-high"); | ||
920 | |||
921 | dp_video_config->v_sync_polarity = | ||
922 | of_property_read_bool(dp_node, "vsync-active-high"); | ||
923 | |||
924 | dp_video_config->interlaced = | ||
925 | of_property_read_bool(dp_node, "interlaced"); | ||
926 | |||
927 | if (of_property_read_u32(dp_node, "samsung,color-space", | ||
928 | &dp_video_config->color_space)) { | ||
929 | dev_err(dev, "failed to get color-space\n"); | ||
930 | return ERR_PTR(-EINVAL); | ||
931 | } | ||
932 | |||
933 | if (of_property_read_u32(dp_node, "samsung,dynamic-range", | ||
934 | &dp_video_config->dynamic_range)) { | ||
935 | dev_err(dev, "failed to get dynamic-range\n"); | ||
936 | return ERR_PTR(-EINVAL); | ||
937 | } | ||
938 | |||
939 | if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff", | ||
940 | &dp_video_config->ycbcr_coeff)) { | ||
941 | dev_err(dev, "failed to get ycbcr-coeff\n"); | ||
942 | return ERR_PTR(-EINVAL); | ||
943 | } | ||
944 | |||
945 | if (of_property_read_u32(dp_node, "samsung,color-depth", | ||
946 | &dp_video_config->color_depth)) { | ||
947 | dev_err(dev, "failed to get color-depth\n"); | ||
948 | return ERR_PTR(-EINVAL); | ||
949 | } | ||
950 | |||
951 | if (of_property_read_u32(dp_node, "samsung,link-rate", | ||
952 | &dp_video_config->link_rate)) { | ||
953 | dev_err(dev, "failed to get link-rate\n"); | ||
954 | return ERR_PTR(-EINVAL); | ||
955 | } | ||
956 | |||
957 | if (of_property_read_u32(dp_node, "samsung,lane-count", | ||
958 | &dp_video_config->lane_count)) { | ||
959 | dev_err(dev, "failed to get lane-count\n"); | ||
960 | return ERR_PTR(-EINVAL); | ||
961 | } | ||
962 | |||
963 | return pd; | ||
964 | } | ||
965 | |||
966 | static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp) | ||
967 | { | ||
968 | struct device_node *dp_phy_node; | ||
969 | u32 phy_base; | ||
970 | |||
971 | dp_phy_node = of_find_node_by_name(dp->dev->of_node, "dptx-phy"); | ||
972 | if (!dp_phy_node) { | ||
973 | dev_err(dp->dev, "could not find dptx-phy node\n"); | ||
974 | return -ENODEV; | ||
975 | } | ||
976 | |||
977 | if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) { | ||
978 | dev_err(dp->dev, "faild to get reg for dptx-phy\n"); | ||
979 | return -EINVAL; | ||
980 | } | ||
981 | |||
982 | if (of_property_read_u32(dp_phy_node, "samsung,enable-mask", | ||
983 | &dp->enable_mask)) { | ||
984 | dev_err(dp->dev, "faild to get enable-mask for dptx-phy\n"); | ||
985 | return -EINVAL; | ||
986 | } | ||
987 | |||
988 | dp->phy_addr = ioremap(phy_base, SZ_4); | ||
989 | if (!dp->phy_addr) { | ||
990 | dev_err(dp->dev, "failed to ioremap dp-phy\n"); | ||
991 | return -ENOMEM; | ||
992 | } | ||
993 | |||
994 | return 0; | ||
995 | } | ||
996 | |||
997 | static void exynos_dp_phy_init(struct exynos_dp_device *dp) | ||
998 | { | ||
999 | u32 reg; | ||
1000 | |||
1001 | reg = __raw_readl(dp->phy_addr); | ||
1002 | reg |= dp->enable_mask; | ||
1003 | __raw_writel(reg, dp->phy_addr); | ||
1004 | } | ||
1005 | |||
1006 | static void exynos_dp_phy_exit(struct exynos_dp_device *dp) | ||
1007 | { | ||
1008 | u32 reg; | ||
1009 | |||
1010 | reg = __raw_readl(dp->phy_addr); | ||
1011 | reg &= ~(dp->enable_mask); | ||
1012 | __raw_writel(reg, dp->phy_addr); | ||
1013 | } | ||
1014 | #else | ||
1015 | static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev) | ||
1016 | { | ||
1017 | return NULL; | ||
1018 | } | ||
1019 | |||
1020 | static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp) | ||
1021 | { | ||
1022 | return -EINVAL; | ||
1023 | } | ||
1024 | |||
1025 | static void exynos_dp_phy_init(struct exynos_dp_device *dp) | ||
1026 | { | ||
1027 | return; | ||
1028 | } | ||
1029 | |||
1030 | static void exynos_dp_phy_exit(struct exynos_dp_device *dp) | ||
1031 | { | ||
1032 | return; | ||
1033 | } | ||
1034 | #endif /* CONFIG_OF */ | ||
1035 | |||
859 | static int __devinit exynos_dp_probe(struct platform_device *pdev) | 1036 | static int __devinit exynos_dp_probe(struct platform_device *pdev) |
860 | { | 1037 | { |
861 | struct resource *res; | 1038 | struct resource *res; |
@@ -864,12 +1041,6 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev) | |||
864 | 1041 | ||
865 | int ret = 0; | 1042 | int ret = 0; |
866 | 1043 | ||
867 | pdata = pdev->dev.platform_data; | ||
868 | if (!pdata) { | ||
869 | dev_err(&pdev->dev, "no platform data\n"); | ||
870 | return -EINVAL; | ||
871 | } | ||
872 | |||
873 | dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), | 1044 | dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), |
874 | GFP_KERNEL); | 1045 | GFP_KERNEL); |
875 | if (!dp) { | 1046 | if (!dp) { |
@@ -879,6 +1050,22 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev) | |||
879 | 1050 | ||
880 | dp->dev = &pdev->dev; | 1051 | dp->dev = &pdev->dev; |
881 | 1052 | ||
1053 | if (pdev->dev.of_node) { | ||
1054 | pdata = exynos_dp_dt_parse_pdata(&pdev->dev); | ||
1055 | if (IS_ERR(pdata)) | ||
1056 | return PTR_ERR(pdata); | ||
1057 | |||
1058 | ret = exynos_dp_dt_parse_phydata(dp); | ||
1059 | if (ret) | ||
1060 | return ret; | ||
1061 | } else { | ||
1062 | pdata = pdev->dev.platform_data; | ||
1063 | if (!pdata) { | ||
1064 | dev_err(&pdev->dev, "no platform data\n"); | ||
1065 | return -EINVAL; | ||
1066 | } | ||
1067 | } | ||
1068 | |||
882 | dp->clock = devm_clk_get(&pdev->dev, "dp"); | 1069 | dp->clock = devm_clk_get(&pdev->dev, "dp"); |
883 | if (IS_ERR(dp->clock)) { | 1070 | if (IS_ERR(dp->clock)) { |
884 | dev_err(&pdev->dev, "failed to get clock\n"); | 1071 | dev_err(&pdev->dev, "failed to get clock\n"); |
@@ -896,50 +1083,29 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev) | |||
896 | } | 1083 | } |
897 | 1084 | ||
898 | dp->irq = platform_get_irq(pdev, 0); | 1085 | dp->irq = platform_get_irq(pdev, 0); |
899 | if (!dp->irq) { | 1086 | if (dp->irq == -ENXIO) { |
900 | dev_err(&pdev->dev, "failed to get irq\n"); | 1087 | dev_err(&pdev->dev, "failed to get irq\n"); |
901 | return -ENODEV; | 1088 | return -ENODEV; |
902 | } | 1089 | } |
903 | 1090 | ||
904 | ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0, | 1091 | INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug); |
905 | "exynos-dp", dp); | ||
906 | if (ret) { | ||
907 | dev_err(&pdev->dev, "failed to request irq\n"); | ||
908 | return ret; | ||
909 | } | ||
910 | 1092 | ||
911 | dp->video_info = pdata->video_info; | 1093 | dp->video_info = pdata->video_info; |
912 | if (pdata->phy_init) | ||
913 | pdata->phy_init(); | ||
914 | |||
915 | exynos_dp_init_dp(dp); | ||
916 | |||
917 | ret = exynos_dp_detect_hpd(dp); | ||
918 | if (ret) { | ||
919 | dev_err(&pdev->dev, "unable to detect hpd\n"); | ||
920 | return ret; | ||
921 | } | ||
922 | 1094 | ||
923 | exynos_dp_handle_edid(dp); | 1095 | if (pdev->dev.of_node) { |
924 | 1096 | if (dp->phy_addr) | |
925 | ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count, | 1097 | exynos_dp_phy_init(dp); |
926 | dp->video_info->link_rate); | 1098 | } else { |
927 | if (ret) { | 1099 | if (pdata->phy_init) |
928 | dev_err(&pdev->dev, "unable to do link train\n"); | 1100 | pdata->phy_init(); |
929 | return ret; | ||
930 | } | 1101 | } |
931 | 1102 | ||
932 | exynos_dp_enable_scramble(dp, 1); | 1103 | exynos_dp_init_dp(dp); |
933 | exynos_dp_enable_rx_to_enhanced_mode(dp, 1); | ||
934 | exynos_dp_enable_enhanced_mode(dp, 1); | ||
935 | |||
936 | exynos_dp_set_lane_count(dp, dp->video_info->lane_count); | ||
937 | exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate); | ||
938 | 1104 | ||
939 | exynos_dp_init_video(dp); | 1105 | ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0, |
940 | ret = exynos_dp_config_video(dp, dp->video_info); | 1106 | "exynos-dp", dp); |
941 | if (ret) { | 1107 | if (ret) { |
942 | dev_err(&pdev->dev, "unable to config video\n"); | 1108 | dev_err(&pdev->dev, "failed to request irq\n"); |
943 | return ret; | 1109 | return ret; |
944 | } | 1110 | } |
945 | 1111 | ||
@@ -953,23 +1119,41 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev) | |||
953 | struct exynos_dp_platdata *pdata = pdev->dev.platform_data; | 1119 | struct exynos_dp_platdata *pdata = pdev->dev.platform_data; |
954 | struct exynos_dp_device *dp = platform_get_drvdata(pdev); | 1120 | struct exynos_dp_device *dp = platform_get_drvdata(pdev); |
955 | 1121 | ||
956 | if (pdata && pdata->phy_exit) | 1122 | disable_irq(dp->irq); |
957 | pdata->phy_exit(); | 1123 | |
1124 | if (work_pending(&dp->hotplug_work)) | ||
1125 | flush_work(&dp->hotplug_work); | ||
1126 | |||
1127 | if (pdev->dev.of_node) { | ||
1128 | if (dp->phy_addr) | ||
1129 | exynos_dp_phy_exit(dp); | ||
1130 | } else { | ||
1131 | if (pdata->phy_exit) | ||
1132 | pdata->phy_exit(); | ||
1133 | } | ||
958 | 1134 | ||
959 | clk_disable_unprepare(dp->clock); | 1135 | clk_disable_unprepare(dp->clock); |
960 | 1136 | ||
1137 | |||
961 | return 0; | 1138 | return 0; |
962 | } | 1139 | } |
963 | 1140 | ||
964 | #ifdef CONFIG_PM_SLEEP | 1141 | #ifdef CONFIG_PM_SLEEP |
965 | static int exynos_dp_suspend(struct device *dev) | 1142 | static int exynos_dp_suspend(struct device *dev) |
966 | { | 1143 | { |
967 | struct platform_device *pdev = to_platform_device(dev); | 1144 | struct exynos_dp_platdata *pdata = dev->platform_data; |
968 | struct exynos_dp_platdata *pdata = pdev->dev.platform_data; | 1145 | struct exynos_dp_device *dp = dev_get_drvdata(dev); |
969 | struct exynos_dp_device *dp = platform_get_drvdata(pdev); | ||
970 | 1146 | ||
971 | if (pdata && pdata->phy_exit) | 1147 | if (work_pending(&dp->hotplug_work)) |
972 | pdata->phy_exit(); | 1148 | flush_work(&dp->hotplug_work); |
1149 | |||
1150 | if (dev->of_node) { | ||
1151 | if (dp->phy_addr) | ||
1152 | exynos_dp_phy_exit(dp); | ||
1153 | } else { | ||
1154 | if (pdata->phy_exit) | ||
1155 | pdata->phy_exit(); | ||
1156 | } | ||
973 | 1157 | ||
974 | clk_disable_unprepare(dp->clock); | 1158 | clk_disable_unprepare(dp->clock); |
975 | 1159 | ||
@@ -978,32 +1162,22 @@ static int exynos_dp_suspend(struct device *dev) | |||
978 | 1162 | ||
979 | static int exynos_dp_resume(struct device *dev) | 1163 | static int exynos_dp_resume(struct device *dev) |
980 | { | 1164 | { |
981 | struct platform_device *pdev = to_platform_device(dev); | 1165 | struct exynos_dp_platdata *pdata = dev->platform_data; |
982 | struct exynos_dp_platdata *pdata = pdev->dev.platform_data; | 1166 | struct exynos_dp_device *dp = dev_get_drvdata(dev); |
983 | struct exynos_dp_device *dp = platform_get_drvdata(pdev); | ||
984 | 1167 | ||
985 | if (pdata && pdata->phy_init) | 1168 | if (dev->of_node) { |
986 | pdata->phy_init(); | 1169 | if (dp->phy_addr) |
1170 | exynos_dp_phy_init(dp); | ||
1171 | } else { | ||
1172 | if (pdata->phy_init) | ||
1173 | pdata->phy_init(); | ||
1174 | } | ||
987 | 1175 | ||
988 | clk_prepare_enable(dp->clock); | 1176 | clk_prepare_enable(dp->clock); |
989 | 1177 | ||
990 | exynos_dp_init_dp(dp); | 1178 | exynos_dp_init_dp(dp); |
991 | 1179 | ||
992 | exynos_dp_detect_hpd(dp); | 1180 | enable_irq(dp->irq); |
993 | exynos_dp_handle_edid(dp); | ||
994 | |||
995 | exynos_dp_set_link_train(dp, dp->video_info->lane_count, | ||
996 | dp->video_info->link_rate); | ||
997 | |||
998 | exynos_dp_enable_scramble(dp, 1); | ||
999 | exynos_dp_enable_rx_to_enhanced_mode(dp, 1); | ||
1000 | exynos_dp_enable_enhanced_mode(dp, 1); | ||
1001 | |||
1002 | exynos_dp_set_lane_count(dp, dp->video_info->lane_count); | ||
1003 | exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate); | ||
1004 | |||
1005 | exynos_dp_init_video(dp); | ||
1006 | exynos_dp_config_video(dp, dp->video_info); | ||
1007 | 1181 | ||
1008 | return 0; | 1182 | return 0; |
1009 | } | 1183 | } |
@@ -1013,6 +1187,12 @@ static const struct dev_pm_ops exynos_dp_pm_ops = { | |||
1013 | SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume) | 1187 | SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume) |
1014 | }; | 1188 | }; |
1015 | 1189 | ||
1190 | static const struct of_device_id exynos_dp_match[] = { | ||
1191 | { .compatible = "samsung,exynos5-dp" }, | ||
1192 | {}, | ||
1193 | }; | ||
1194 | MODULE_DEVICE_TABLE(of, exynos_dp_match); | ||
1195 | |||
1016 | static struct platform_driver exynos_dp_driver = { | 1196 | static struct platform_driver exynos_dp_driver = { |
1017 | .probe = exynos_dp_probe, | 1197 | .probe = exynos_dp_probe, |
1018 | .remove = __devexit_p(exynos_dp_remove), | 1198 | .remove = __devexit_p(exynos_dp_remove), |
@@ -1020,6 +1200,7 @@ static struct platform_driver exynos_dp_driver = { | |||
1020 | .name = "exynos-dp", | 1200 | .name = "exynos-dp", |
1021 | .owner = THIS_MODULE, | 1201 | .owner = THIS_MODULE, |
1022 | .pm = &exynos_dp_pm_ops, | 1202 | .pm = &exynos_dp_pm_ops, |
1203 | .of_match_table = of_match_ptr(exynos_dp_match), | ||
1023 | }, | 1204 | }, |
1024 | }; | 1205 | }; |
1025 | 1206 | ||
diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h index 57b8a6531c0e..6c567bbf2fb8 100644 --- a/drivers/video/exynos/exynos_dp_core.h +++ b/drivers/video/exynos/exynos_dp_core.h | |||
@@ -13,6 +13,13 @@ | |||
13 | #ifndef _EXYNOS_DP_CORE_H | 13 | #ifndef _EXYNOS_DP_CORE_H |
14 | #define _EXYNOS_DP_CORE_H | 14 | #define _EXYNOS_DP_CORE_H |
15 | 15 | ||
16 | enum dp_irq_type { | ||
17 | DP_IRQ_TYPE_HP_CABLE_IN, | ||
18 | DP_IRQ_TYPE_HP_CABLE_OUT, | ||
19 | DP_IRQ_TYPE_HP_CHANGE, | ||
20 | DP_IRQ_TYPE_UNKNOWN, | ||
21 | }; | ||
22 | |||
16 | struct link_train { | 23 | struct link_train { |
17 | int eq_loop; | 24 | int eq_loop; |
18 | int cr_loop[4]; | 25 | int cr_loop[4]; |
@@ -29,9 +36,12 @@ struct exynos_dp_device { | |||
29 | struct clk *clock; | 36 | struct clk *clock; |
30 | unsigned int irq; | 37 | unsigned int irq; |
31 | void __iomem *reg_base; | 38 | void __iomem *reg_base; |
39 | void __iomem *phy_addr; | ||
40 | unsigned int enable_mask; | ||
32 | 41 | ||
33 | struct video_info *video_info; | 42 | struct video_info *video_info; |
34 | struct link_train link_train; | 43 | struct link_train link_train; |
44 | struct work_struct hotplug_work; | ||
35 | }; | 45 | }; |
36 | 46 | ||
37 | /* exynos_dp_reg.c */ | 47 | /* exynos_dp_reg.c */ |
@@ -50,6 +60,8 @@ void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp, | |||
50 | bool enable); | 60 | bool enable); |
51 | void exynos_dp_init_analog_func(struct exynos_dp_device *dp); | 61 | void exynos_dp_init_analog_func(struct exynos_dp_device *dp); |
52 | void exynos_dp_init_hpd(struct exynos_dp_device *dp); | 62 | void exynos_dp_init_hpd(struct exynos_dp_device *dp); |
63 | enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp); | ||
64 | void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp); | ||
53 | void exynos_dp_reset_aux(struct exynos_dp_device *dp); | 65 | void exynos_dp_reset_aux(struct exynos_dp_device *dp); |
54 | void exynos_dp_init_aux(struct exynos_dp_device *dp); | 66 | void exynos_dp_init_aux(struct exynos_dp_device *dp); |
55 | int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp); | 67 | int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp); |
@@ -107,11 +119,7 @@ u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp); | |||
107 | void exynos_dp_reset_macro(struct exynos_dp_device *dp); | 119 | void exynos_dp_reset_macro(struct exynos_dp_device *dp); |
108 | void exynos_dp_init_video(struct exynos_dp_device *dp); | 120 | void exynos_dp_init_video(struct exynos_dp_device *dp); |
109 | 121 | ||
110 | void exynos_dp_set_video_color_format(struct exynos_dp_device *dp, | 122 | void exynos_dp_set_video_color_format(struct exynos_dp_device *dp); |
111 | u32 color_depth, | ||
112 | u32 color_space, | ||
113 | u32 dynamic_range, | ||
114 | u32 ycbcr_coeff); | ||
115 | int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp); | 123 | int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp); |
116 | void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp, | 124 | void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp, |
117 | enum clock_recovery_m_value_type type, | 125 | enum clock_recovery_m_value_type type, |
@@ -121,8 +129,7 @@ void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type); | |||
121 | void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable); | 129 | void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable); |
122 | void exynos_dp_start_video(struct exynos_dp_device *dp); | 130 | void exynos_dp_start_video(struct exynos_dp_device *dp); |
123 | int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp); | 131 | int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp); |
124 | void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp, | 132 | void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp); |
125 | struct video_info *video_info); | ||
126 | void exynos_dp_enable_scrambling(struct exynos_dp_device *dp); | 133 | void exynos_dp_enable_scrambling(struct exynos_dp_device *dp); |
127 | void exynos_dp_disable_scrambling(struct exynos_dp_device *dp); | 134 | void exynos_dp_disable_scrambling(struct exynos_dp_device *dp); |
128 | 135 | ||
diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c index 3f5ca8a0d5ea..29d9d035c73a 100644 --- a/drivers/video/exynos/exynos_dp_reg.c +++ b/drivers/video/exynos/exynos_dp_reg.c | |||
@@ -19,11 +19,11 @@ | |||
19 | #include "exynos_dp_core.h" | 19 | #include "exynos_dp_core.h" |
20 | #include "exynos_dp_reg.h" | 20 | #include "exynos_dp_reg.h" |
21 | 21 | ||
22 | #define COMMON_INT_MASK_1 (0) | 22 | #define COMMON_INT_MASK_1 0 |
23 | #define COMMON_INT_MASK_2 (0) | 23 | #define COMMON_INT_MASK_2 0 |
24 | #define COMMON_INT_MASK_3 (0) | 24 | #define COMMON_INT_MASK_3 0 |
25 | #define COMMON_INT_MASK_4 (0) | 25 | #define COMMON_INT_MASK_4 (HOTPLUG_CHG | HPD_LOST | PLUG) |
26 | #define INT_STA_MASK (0) | 26 | #define INT_STA_MASK INT_HPD |
27 | 27 | ||
28 | void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable) | 28 | void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable) |
29 | { | 29 | { |
@@ -88,7 +88,7 @@ void exynos_dp_init_analog_param(struct exynos_dp_device *dp) | |||
88 | void exynos_dp_init_interrupt(struct exynos_dp_device *dp) | 88 | void exynos_dp_init_interrupt(struct exynos_dp_device *dp) |
89 | { | 89 | { |
90 | /* Set interrupt pin assertion polarity as high */ | 90 | /* Set interrupt pin assertion polarity as high */ |
91 | writel(INT_POL, dp->reg_base + EXYNOS_DP_INT_CTL); | 91 | writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL); |
92 | 92 | ||
93 | /* Clear pending regisers */ | 93 | /* Clear pending regisers */ |
94 | writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1); | 94 | writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1); |
@@ -324,7 +324,7 @@ void exynos_dp_init_analog_func(struct exynos_dp_device *dp) | |||
324 | writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2); | 324 | writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2); |
325 | } | 325 | } |
326 | 326 | ||
327 | void exynos_dp_init_hpd(struct exynos_dp_device *dp) | 327 | void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp) |
328 | { | 328 | { |
329 | u32 reg; | 329 | u32 reg; |
330 | 330 | ||
@@ -333,12 +333,38 @@ void exynos_dp_init_hpd(struct exynos_dp_device *dp) | |||
333 | 333 | ||
334 | reg = INT_HPD; | 334 | reg = INT_HPD; |
335 | writel(reg, dp->reg_base + EXYNOS_DP_INT_STA); | 335 | writel(reg, dp->reg_base + EXYNOS_DP_INT_STA); |
336 | } | ||
337 | |||
338 | void exynos_dp_init_hpd(struct exynos_dp_device *dp) | ||
339 | { | ||
340 | u32 reg; | ||
341 | |||
342 | exynos_dp_clear_hotplug_interrupts(dp); | ||
336 | 343 | ||
337 | reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3); | 344 | reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3); |
338 | reg &= ~(F_HPD | HPD_CTRL); | 345 | reg &= ~(F_HPD | HPD_CTRL); |
339 | writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3); | 346 | writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3); |
340 | } | 347 | } |
341 | 348 | ||
349 | enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp) | ||
350 | { | ||
351 | u32 reg; | ||
352 | |||
353 | /* Parse hotplug interrupt status register */ | ||
354 | reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4); | ||
355 | |||
356 | if (reg & PLUG) | ||
357 | return DP_IRQ_TYPE_HP_CABLE_IN; | ||
358 | |||
359 | if (reg & HPD_LOST) | ||
360 | return DP_IRQ_TYPE_HP_CABLE_OUT; | ||
361 | |||
362 | if (reg & HOTPLUG_CHG) | ||
363 | return DP_IRQ_TYPE_HP_CHANGE; | ||
364 | |||
365 | return DP_IRQ_TYPE_UNKNOWN; | ||
366 | } | ||
367 | |||
342 | void exynos_dp_reset_aux(struct exynos_dp_device *dp) | 368 | void exynos_dp_reset_aux(struct exynos_dp_device *dp) |
343 | { | 369 | { |
344 | u32 reg; | 370 | u32 reg; |
@@ -491,7 +517,7 @@ int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp, | |||
491 | int i; | 517 | int i; |
492 | int retval; | 518 | int retval; |
493 | 519 | ||
494 | for (i = 0; i < 10; i++) { | 520 | for (i = 0; i < 3; i++) { |
495 | /* Clear AUX CH data buffer */ | 521 | /* Clear AUX CH data buffer */ |
496 | reg = BUF_CLR; | 522 | reg = BUF_CLR; |
497 | writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL); | 523 | writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL); |
@@ -552,7 +578,7 @@ int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp, | |||
552 | else | 578 | else |
553 | cur_data_count = count - start_offset; | 579 | cur_data_count = count - start_offset; |
554 | 580 | ||
555 | for (i = 0; i < 10; i++) { | 581 | for (i = 0; i < 3; i++) { |
556 | /* Select DPCD device address */ | 582 | /* Select DPCD device address */ |
557 | reg = AUX_ADDR_7_0(reg_addr + start_offset); | 583 | reg = AUX_ADDR_7_0(reg_addr + start_offset); |
558 | writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0); | 584 | writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0); |
@@ -617,7 +643,7 @@ int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp, | |||
617 | cur_data_count = count - start_offset; | 643 | cur_data_count = count - start_offset; |
618 | 644 | ||
619 | /* AUX CH Request Transaction process */ | 645 | /* AUX CH Request Transaction process */ |
620 | for (i = 0; i < 10; i++) { | 646 | for (i = 0; i < 3; i++) { |
621 | /* Select DPCD device address */ | 647 | /* Select DPCD device address */ |
622 | reg = AUX_ADDR_7_0(reg_addr + start_offset); | 648 | reg = AUX_ADDR_7_0(reg_addr + start_offset); |
623 | writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0); | 649 | writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0); |
@@ -700,17 +726,15 @@ int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp, | |||
700 | int i; | 726 | int i; |
701 | int retval; | 727 | int retval; |
702 | 728 | ||
703 | for (i = 0; i < 10; i++) { | 729 | for (i = 0; i < 3; i++) { |
704 | /* Clear AUX CH data buffer */ | 730 | /* Clear AUX CH data buffer */ |
705 | reg = BUF_CLR; | 731 | reg = BUF_CLR; |
706 | writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL); | 732 | writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL); |
707 | 733 | ||
708 | /* Select EDID device */ | 734 | /* Select EDID device */ |
709 | retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr); | 735 | retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr); |
710 | if (retval != 0) { | 736 | if (retval != 0) |
711 | dev_err(dp->dev, "Select EDID device fail!\n"); | ||
712 | continue; | 737 | continue; |
713 | } | ||
714 | 738 | ||
715 | /* | 739 | /* |
716 | * Set I2C transaction and read data | 740 | * Set I2C transaction and read data |
@@ -750,7 +774,7 @@ int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp, | |||
750 | int retval = 0; | 774 | int retval = 0; |
751 | 775 | ||
752 | for (i = 0; i < count; i += 16) { | 776 | for (i = 0; i < count; i += 16) { |
753 | for (j = 0; j < 100; j++) { | 777 | for (j = 0; j < 3; j++) { |
754 | /* Clear AUX CH data buffer */ | 778 | /* Clear AUX CH data buffer */ |
755 | reg = BUF_CLR; | 779 | reg = BUF_CLR; |
756 | writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL); | 780 | writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL); |
@@ -1034,24 +1058,20 @@ void exynos_dp_init_video(struct exynos_dp_device *dp) | |||
1034 | writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8); | 1058 | writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8); |
1035 | } | 1059 | } |
1036 | 1060 | ||
1037 | void exynos_dp_set_video_color_format(struct exynos_dp_device *dp, | 1061 | void exynos_dp_set_video_color_format(struct exynos_dp_device *dp) |
1038 | u32 color_depth, | ||
1039 | u32 color_space, | ||
1040 | u32 dynamic_range, | ||
1041 | u32 ycbcr_coeff) | ||
1042 | { | 1062 | { |
1043 | u32 reg; | 1063 | u32 reg; |
1044 | 1064 | ||
1045 | /* Configure the input color depth, color space, dynamic range */ | 1065 | /* Configure the input color depth, color space, dynamic range */ |
1046 | reg = (dynamic_range << IN_D_RANGE_SHIFT) | | 1066 | reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) | |
1047 | (color_depth << IN_BPC_SHIFT) | | 1067 | (dp->video_info->color_depth << IN_BPC_SHIFT) | |
1048 | (color_space << IN_COLOR_F_SHIFT); | 1068 | (dp->video_info->color_space << IN_COLOR_F_SHIFT); |
1049 | writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2); | 1069 | writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2); |
1050 | 1070 | ||
1051 | /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */ | 1071 | /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */ |
1052 | reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3); | 1072 | reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3); |
1053 | reg &= ~IN_YC_COEFFI_MASK; | 1073 | reg &= ~IN_YC_COEFFI_MASK; |
1054 | if (ycbcr_coeff) | 1074 | if (dp->video_info->ycbcr_coeff) |
1055 | reg |= IN_YC_COEFFI_ITU709; | 1075 | reg |= IN_YC_COEFFI_ITU709; |
1056 | else | 1076 | else |
1057 | reg |= IN_YC_COEFFI_ITU601; | 1077 | reg |= IN_YC_COEFFI_ITU601; |
@@ -1178,8 +1198,7 @@ int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp) | |||
1178 | return 0; | 1198 | return 0; |
1179 | } | 1199 | } |
1180 | 1200 | ||
1181 | void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp, | 1201 | void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp) |
1182 | struct video_info *video_info) | ||
1183 | { | 1202 | { |
1184 | u32 reg; | 1203 | u32 reg; |
1185 | 1204 | ||
@@ -1190,17 +1209,17 @@ void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp, | |||
1190 | 1209 | ||
1191 | reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); | 1210 | reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); |
1192 | reg &= ~INTERACE_SCAN_CFG; | 1211 | reg &= ~INTERACE_SCAN_CFG; |
1193 | reg |= (video_info->interlaced << 2); | 1212 | reg |= (dp->video_info->interlaced << 2); |
1194 | writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); | 1213 | writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); |
1195 | 1214 | ||
1196 | reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); | 1215 | reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); |
1197 | reg &= ~VSYNC_POLARITY_CFG; | 1216 | reg &= ~VSYNC_POLARITY_CFG; |
1198 | reg |= (video_info->v_sync_polarity << 1); | 1217 | reg |= (dp->video_info->v_sync_polarity << 1); |
1199 | writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); | 1218 | writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); |
1200 | 1219 | ||
1201 | reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); | 1220 | reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); |
1202 | reg &= ~HSYNC_POLARITY_CFG; | 1221 | reg &= ~HSYNC_POLARITY_CFG; |
1203 | reg |= (video_info->h_sync_polarity << 0); | 1222 | reg |= (dp->video_info->h_sync_polarity << 0); |
1204 | writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); | 1223 | writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); |
1205 | 1224 | ||
1206 | reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE; | 1225 | reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE; |
diff --git a/drivers/video/exynos/exynos_dp_reg.h b/drivers/video/exynos/exynos_dp_reg.h index 1f2f014cfe88..2e9bd0e0b9f2 100644 --- a/drivers/video/exynos/exynos_dp_reg.h +++ b/drivers/video/exynos/exynos_dp_reg.h | |||
@@ -242,7 +242,8 @@ | |||
242 | 242 | ||
243 | /* EXYNOS_DP_INT_CTL */ | 243 | /* EXYNOS_DP_INT_CTL */ |
244 | #define SOFT_INT_CTRL (0x1 << 2) | 244 | #define SOFT_INT_CTRL (0x1 << 2) |
245 | #define INT_POL (0x1 << 0) | 245 | #define INT_POL1 (0x1 << 1) |
246 | #define INT_POL0 (0x1 << 0) | ||
246 | 247 | ||
247 | /* EXYNOS_DP_SYS_CTL_1 */ | 248 | /* EXYNOS_DP_SYS_CTL_1 */ |
248 | #define DET_STA (0x1 << 2) | 249 | #define DET_STA (0x1 << 2) |
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index ede9e55413f8..d3fc92eaee89 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c | |||
@@ -337,13 +337,11 @@ struct mfb_info { | |||
337 | int registered; | 337 | int registered; |
338 | unsigned long pseudo_palette[16]; | 338 | unsigned long pseudo_palette[16]; |
339 | struct diu_ad *ad; | 339 | struct diu_ad *ad; |
340 | int cursor_reset; | ||
341 | unsigned char g_alpha; | 340 | unsigned char g_alpha; |
342 | unsigned int count; | 341 | unsigned int count; |
343 | int x_aoi_d; /* aoi display x offset to physical screen */ | 342 | int x_aoi_d; /* aoi display x offset to physical screen */ |
344 | int y_aoi_d; /* aoi display y offset to physical screen */ | 343 | int y_aoi_d; /* aoi display y offset to physical screen */ |
345 | struct fsl_diu_data *parent; | 344 | struct fsl_diu_data *parent; |
346 | u8 *edid_data; | ||
347 | }; | 345 | }; |
348 | 346 | ||
349 | /** | 347 | /** |
@@ -378,6 +376,8 @@ struct fsl_diu_data { | |||
378 | struct diu_ad ad[NUM_AOIS] __aligned(8); | 376 | struct diu_ad ad[NUM_AOIS] __aligned(8); |
379 | u8 gamma[256 * 3] __aligned(32); | 377 | u8 gamma[256 * 3] __aligned(32); |
380 | u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32); | 378 | u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32); |
379 | uint8_t edid_data[EDID_LENGTH]; | ||
380 | bool has_edid; | ||
381 | } __aligned(32); | 381 | } __aligned(32); |
382 | 382 | ||
383 | /* Determine the DMA address of a member of the fsl_diu_data structure */ | 383 | /* Determine the DMA address of a member of the fsl_diu_data structure */ |
@@ -430,6 +430,22 @@ static struct mfb_info mfb_template[] = { | |||
430 | }, | 430 | }, |
431 | }; | 431 | }; |
432 | 432 | ||
433 | #ifdef DEBUG | ||
434 | static void __attribute__ ((unused)) fsl_diu_dump(struct diu __iomem *hw) | ||
435 | { | ||
436 | mb(); | ||
437 | pr_debug("DIU: desc=%08x,%08x,%08x, gamma=%08x pallete=%08x " | ||
438 | "cursor=%08x curs_pos=%08x diu_mode=%08x bgnd=%08x " | ||
439 | "disp_size=%08x hsyn_para=%08x vsyn_para=%08x syn_pol=%08x " | ||
440 | "thresholds=%08x int_mask=%08x plut=%08x\n", | ||
441 | hw->desc[0], hw->desc[1], hw->desc[2], hw->gamma, | ||
442 | hw->pallete, hw->cursor, hw->curs_pos, hw->diu_mode, | ||
443 | hw->bgnd, hw->disp_size, hw->hsyn_para, hw->vsyn_para, | ||
444 | hw->syn_pol, hw->thresholds, hw->int_mask, hw->plut); | ||
445 | rmb(); | ||
446 | } | ||
447 | #endif | ||
448 | |||
433 | /** | 449 | /** |
434 | * fsl_diu_name_to_port - convert a port name to a monitor port enum | 450 | * fsl_diu_name_to_port - convert a port name to a monitor port enum |
435 | * | 451 | * |
@@ -481,8 +497,7 @@ static void fsl_diu_enable_panel(struct fb_info *info) | |||
481 | 497 | ||
482 | switch (mfbi->index) { | 498 | switch (mfbi->index) { |
483 | case PLANE0: | 499 | case PLANE0: |
484 | if (hw->desc[0] != ad->paddr) | 500 | wr_reg_wa(&hw->desc[0], ad->paddr); |
485 | wr_reg_wa(&hw->desc[0], ad->paddr); | ||
486 | break; | 501 | break; |
487 | case PLANE1_AOI0: | 502 | case PLANE1_AOI0: |
488 | cmfbi = &data->mfb[2]; | 503 | cmfbi = &data->mfb[2]; |
@@ -534,8 +549,7 @@ static void fsl_diu_disable_panel(struct fb_info *info) | |||
534 | 549 | ||
535 | switch (mfbi->index) { | 550 | switch (mfbi->index) { |
536 | case PLANE0: | 551 | case PLANE0: |
537 | if (hw->desc[0] != data->dummy_ad.paddr) | 552 | wr_reg_wa(&hw->desc[0], 0); |
538 | wr_reg_wa(&hw->desc[0], data->dummy_ad.paddr); | ||
539 | break; | 553 | break; |
540 | case PLANE1_AOI0: | 554 | case PLANE1_AOI0: |
541 | cmfbi = &data->mfb[2]; | 555 | cmfbi = &data->mfb[2]; |
@@ -792,7 +806,8 @@ static void update_lcdc(struct fb_info *info) | |||
792 | 806 | ||
793 | hw = data->diu_reg; | 807 | hw = data->diu_reg; |
794 | 808 | ||
795 | diu_ops.set_monitor_port(data->monitor_port); | 809 | if (diu_ops.set_monitor_port) |
810 | diu_ops.set_monitor_port(data->monitor_port); | ||
796 | gamma_table_base = data->gamma; | 811 | gamma_table_base = data->gamma; |
797 | 812 | ||
798 | /* Prep for DIU init - gamma table, cursor table */ | 813 | /* Prep for DIU init - gamma table, cursor table */ |
@@ -811,12 +826,8 @@ static void update_lcdc(struct fb_info *info) | |||
811 | out_be32(&hw->gamma, DMA_ADDR(data, gamma)); | 826 | out_be32(&hw->gamma, DMA_ADDR(data, gamma)); |
812 | out_be32(&hw->cursor, DMA_ADDR(data, cursor)); | 827 | out_be32(&hw->cursor, DMA_ADDR(data, cursor)); |
813 | 828 | ||
814 | out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */ | 829 | out_be32(&hw->bgnd, 0x007F7F7F); /* Set background to grey */ |
815 | out_be32(&hw->bgnd_wb, 0); /* BGND_WB */ | 830 | out_be32(&hw->disp_size, (var->yres << 16) | var->xres); |
816 | out_be32(&hw->disp_size, (var->yres << 16 | var->xres)); | ||
817 | /* DISP SIZE */ | ||
818 | out_be32(&hw->wb_size, 0); /* WB SIZE */ | ||
819 | out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */ | ||
820 | 831 | ||
821 | /* Horizontal and vertical configuration register */ | 832 | /* Horizontal and vertical configuration register */ |
822 | temp = var->left_margin << 22 | /* BP_H */ | 833 | temp = var->left_margin << 22 | /* BP_H */ |
@@ -833,9 +844,20 @@ static void update_lcdc(struct fb_info *info) | |||
833 | 844 | ||
834 | diu_ops.set_pixel_clock(var->pixclock); | 845 | diu_ops.set_pixel_clock(var->pixclock); |
835 | 846 | ||
836 | out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */ | 847 | #ifndef CONFIG_PPC_MPC512x |
837 | out_be32(&hw->int_status, 0); /* INTERRUPT STATUS */ | 848 | /* |
849 | * The PLUT register is defined differently on the MPC5121 than it | ||
850 | * is on other SOCs. Unfortunately, there's no documentation that | ||
851 | * explains how it's supposed to be programmed, so for now, we leave | ||
852 | * it at the default value on the MPC5121. | ||
853 | * | ||
854 | * For other SOCs, program it for the highest priority, which will | ||
855 | * reduce the chance of underrun. Technically, we should scale the | ||
856 | * priority to match the screen resolution, but doing that properly | ||
857 | * requires delicate fine-tuning for each use-case. | ||
858 | */ | ||
838 | out_be32(&hw->plut, 0x01F5F666); | 859 | out_be32(&hw->plut, 0x01F5F666); |
860 | #endif | ||
839 | 861 | ||
840 | /* Enable the DIU */ | 862 | /* Enable the DIU */ |
841 | enable_lcdc(info); | 863 | enable_lcdc(info); |
@@ -965,7 +987,6 @@ static int fsl_diu_set_par(struct fb_info *info) | |||
965 | hw = data->diu_reg; | 987 | hw = data->diu_reg; |
966 | 988 | ||
967 | set_fix(info); | 989 | set_fix(info); |
968 | mfbi->cursor_reset = 1; | ||
969 | 990 | ||
970 | len = info->var.yres_virtual * info->fix.line_length; | 991 | len = info->var.yres_virtual * info->fix.line_length; |
971 | /* Alloc & dealloc each time resolution/bpp change */ | 992 | /* Alloc & dealloc each time resolution/bpp change */ |
@@ -1107,6 +1128,12 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, | |||
1107 | 1128 | ||
1108 | if (!arg) | 1129 | if (!arg) |
1109 | return -EINVAL; | 1130 | return -EINVAL; |
1131 | |||
1132 | dev_dbg(info->dev, "ioctl %08x (dir=%s%s type=%u nr=%u size=%u)\n", cmd, | ||
1133 | _IOC_DIR(cmd) & _IOC_READ ? "R" : "", | ||
1134 | _IOC_DIR(cmd) & _IOC_WRITE ? "W" : "", | ||
1135 | _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd)); | ||
1136 | |||
1110 | switch (cmd) { | 1137 | switch (cmd) { |
1111 | case MFB_SET_PIXFMT_OLD: | 1138 | case MFB_SET_PIXFMT_OLD: |
1112 | dev_warn(info->dev, | 1139 | dev_warn(info->dev, |
@@ -1180,6 +1207,23 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, | |||
1180 | ad->ckmin_b = ck.blue_min; | 1207 | ad->ckmin_b = ck.blue_min; |
1181 | } | 1208 | } |
1182 | break; | 1209 | break; |
1210 | #ifdef CONFIG_PPC_MPC512x | ||
1211 | case MFB_SET_GAMMA: { | ||
1212 | struct fsl_diu_data *data = mfbi->parent; | ||
1213 | |||
1214 | if (copy_from_user(data->gamma, buf, sizeof(data->gamma))) | ||
1215 | return -EFAULT; | ||
1216 | setbits32(&data->diu_reg->gamma, 0); /* Force table reload */ | ||
1217 | break; | ||
1218 | } | ||
1219 | case MFB_GET_GAMMA: { | ||
1220 | struct fsl_diu_data *data = mfbi->parent; | ||
1221 | |||
1222 | if (copy_to_user(buf, data->gamma, sizeof(data->gamma))) | ||
1223 | return -EFAULT; | ||
1224 | break; | ||
1225 | } | ||
1226 | #endif | ||
1183 | default: | 1227 | default: |
1184 | dev_err(info->dev, "unknown ioctl command (0x%08X)\n", cmd); | 1228 | dev_err(info->dev, "unknown ioctl command (0x%08X)\n", cmd); |
1185 | return -ENOIOCTLCMD; | 1229 | return -ENOIOCTLCMD; |
@@ -1206,8 +1250,22 @@ static int fsl_diu_open(struct fb_info *info, int user) | |||
1206 | res = fsl_diu_set_par(info); | 1250 | res = fsl_diu_set_par(info); |
1207 | if (res < 0) | 1251 | if (res < 0) |
1208 | mfbi->count--; | 1252 | mfbi->count--; |
1209 | else | 1253 | else { |
1254 | struct fsl_diu_data *data = mfbi->parent; | ||
1255 | |||
1256 | #ifdef CONFIG_NOT_COHERENT_CACHE | ||
1257 | /* | ||
1258 | * Enable underrun detection and vertical sync | ||
1259 | * interrupts. | ||
1260 | */ | ||
1261 | clrbits32(&data->diu_reg->int_mask, | ||
1262 | INT_UNDRUN | INT_VSYNC); | ||
1263 | #else | ||
1264 | /* Enable underrun detection */ | ||
1265 | clrbits32(&data->diu_reg->int_mask, INT_UNDRUN); | ||
1266 | #endif | ||
1210 | fsl_diu_enable_panel(info); | 1267 | fsl_diu_enable_panel(info); |
1268 | } | ||
1211 | } | 1269 | } |
1212 | 1270 | ||
1213 | spin_unlock(&diu_lock); | 1271 | spin_unlock(&diu_lock); |
@@ -1223,8 +1281,13 @@ static int fsl_diu_release(struct fb_info *info, int user) | |||
1223 | 1281 | ||
1224 | spin_lock(&diu_lock); | 1282 | spin_lock(&diu_lock); |
1225 | mfbi->count--; | 1283 | mfbi->count--; |
1226 | if (mfbi->count == 0) | 1284 | if (mfbi->count == 0) { |
1285 | struct fsl_diu_data *data = mfbi->parent; | ||
1286 | |||
1287 | /* Disable interrupts */ | ||
1288 | out_be32(&data->diu_reg->int_mask, 0xffffffff); | ||
1227 | fsl_diu_disable_panel(info); | 1289 | fsl_diu_disable_panel(info); |
1290 | } | ||
1228 | 1291 | ||
1229 | spin_unlock(&diu_lock); | 1292 | spin_unlock(&diu_lock); |
1230 | return res; | 1293 | return res; |
@@ -1248,6 +1311,7 @@ static int __devinit install_fb(struct fb_info *info) | |||
1248 | { | 1311 | { |
1249 | int rc; | 1312 | int rc; |
1250 | struct mfb_info *mfbi = info->par; | 1313 | struct mfb_info *mfbi = info->par; |
1314 | struct fsl_diu_data *data = mfbi->parent; | ||
1251 | const char *aoi_mode, *init_aoi_mode = "320x240"; | 1315 | const char *aoi_mode, *init_aoi_mode = "320x240"; |
1252 | struct fb_videomode *db = fsl_diu_mode_db; | 1316 | struct fb_videomode *db = fsl_diu_mode_db; |
1253 | unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db); | 1317 | unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db); |
@@ -1264,9 +1328,9 @@ static int __devinit install_fb(struct fb_info *info) | |||
1264 | return rc; | 1328 | return rc; |
1265 | 1329 | ||
1266 | if (mfbi->index == PLANE0) { | 1330 | if (mfbi->index == PLANE0) { |
1267 | if (mfbi->edid_data) { | 1331 | if (data->has_edid) { |
1268 | /* Now build modedb from EDID */ | 1332 | /* Now build modedb from EDID */ |
1269 | fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs); | 1333 | fb_edid_to_monspecs(data->edid_data, &info->monspecs); |
1270 | fb_videomode_to_modelist(info->monspecs.modedb, | 1334 | fb_videomode_to_modelist(info->monspecs.modedb, |
1271 | info->monspecs.modedb_len, | 1335 | info->monspecs.modedb_len, |
1272 | &info->modelist); | 1336 | &info->modelist); |
@@ -1284,7 +1348,7 @@ static int __devinit install_fb(struct fb_info *info) | |||
1284 | * For plane 0 we continue and look into | 1348 | * For plane 0 we continue and look into |
1285 | * driver's internal modedb. | 1349 | * driver's internal modedb. |
1286 | */ | 1350 | */ |
1287 | if ((mfbi->index == PLANE0) && mfbi->edid_data) | 1351 | if ((mfbi->index == PLANE0) && data->has_edid) |
1288 | has_default_mode = 0; | 1352 | has_default_mode = 0; |
1289 | else | 1353 | else |
1290 | return -EINVAL; | 1354 | return -EINVAL; |
@@ -1348,9 +1412,6 @@ static void uninstall_fb(struct fb_info *info) | |||
1348 | if (!mfbi->registered) | 1412 | if (!mfbi->registered) |
1349 | return; | 1413 | return; |
1350 | 1414 | ||
1351 | if (mfbi->index == PLANE0) | ||
1352 | kfree(mfbi->edid_data); | ||
1353 | |||
1354 | unregister_framebuffer(info); | 1415 | unregister_framebuffer(info); |
1355 | unmap_video_memory(info); | 1416 | unmap_video_memory(info); |
1356 | if (&info->cmap) | 1417 | if (&info->cmap) |
@@ -1362,7 +1423,7 @@ static void uninstall_fb(struct fb_info *info) | |||
1362 | static irqreturn_t fsl_diu_isr(int irq, void *dev_id) | 1423 | static irqreturn_t fsl_diu_isr(int irq, void *dev_id) |
1363 | { | 1424 | { |
1364 | struct diu __iomem *hw = dev_id; | 1425 | struct diu __iomem *hw = dev_id; |
1365 | unsigned int status = in_be32(&hw->int_status); | 1426 | uint32_t status = in_be32(&hw->int_status); |
1366 | 1427 | ||
1367 | if (status) { | 1428 | if (status) { |
1368 | /* This is the workaround for underrun */ | 1429 | /* This is the workaround for underrun */ |
@@ -1387,40 +1448,6 @@ static irqreturn_t fsl_diu_isr(int irq, void *dev_id) | |||
1387 | return IRQ_NONE; | 1448 | return IRQ_NONE; |
1388 | } | 1449 | } |
1389 | 1450 | ||
1390 | static int request_irq_local(struct fsl_diu_data *data) | ||
1391 | { | ||
1392 | struct diu __iomem *hw = data->diu_reg; | ||
1393 | u32 ints; | ||
1394 | int ret; | ||
1395 | |||
1396 | /* Read to clear the status */ | ||
1397 | in_be32(&hw->int_status); | ||
1398 | |||
1399 | ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw); | ||
1400 | if (!ret) { | ||
1401 | ints = INT_PARERR | INT_LS_BF_VS; | ||
1402 | #if !defined(CONFIG_NOT_COHERENT_CACHE) | ||
1403 | ints |= INT_VSYNC; | ||
1404 | #endif | ||
1405 | |||
1406 | /* Read to clear the status */ | ||
1407 | in_be32(&hw->int_status); | ||
1408 | out_be32(&hw->int_mask, ints); | ||
1409 | } | ||
1410 | |||
1411 | return ret; | ||
1412 | } | ||
1413 | |||
1414 | static void free_irq_local(struct fsl_diu_data *data) | ||
1415 | { | ||
1416 | struct diu __iomem *hw = data->diu_reg; | ||
1417 | |||
1418 | /* Disable all LCDC interrupt */ | ||
1419 | out_be32(&hw->int_mask, 0x1f); | ||
1420 | |||
1421 | free_irq(data->irq, NULL); | ||
1422 | } | ||
1423 | |||
1424 | #ifdef CONFIG_PM | 1451 | #ifdef CONFIG_PM |
1425 | /* | 1452 | /* |
1426 | * Power management hooks. Note that we won't be called from IRQ context, | 1453 | * Power management hooks. Note that we won't be called from IRQ context, |
@@ -1496,8 +1523,8 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev) | |||
1496 | struct device_node *np = pdev->dev.of_node; | 1523 | struct device_node *np = pdev->dev.of_node; |
1497 | struct mfb_info *mfbi; | 1524 | struct mfb_info *mfbi; |
1498 | struct fsl_diu_data *data; | 1525 | struct fsl_diu_data *data; |
1499 | int diu_mode; | ||
1500 | dma_addr_t dma_addr; /* DMA addr of fsl_diu_data struct */ | 1526 | dma_addr_t dma_addr; /* DMA addr of fsl_diu_data struct */ |
1527 | const void *prop; | ||
1501 | unsigned int i; | 1528 | unsigned int i; |
1502 | int ret; | 1529 | int ret; |
1503 | 1530 | ||
@@ -1541,17 +1568,13 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev) | |||
1541 | memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); | 1568 | memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); |
1542 | mfbi->parent = data; | 1569 | mfbi->parent = data; |
1543 | mfbi->ad = &data->ad[i]; | 1570 | mfbi->ad = &data->ad[i]; |
1571 | } | ||
1544 | 1572 | ||
1545 | if (mfbi->index == PLANE0) { | 1573 | /* Get the EDID data from the device tree, if present */ |
1546 | const u8 *prop; | 1574 | prop = of_get_property(np, "edid", &ret); |
1547 | int len; | 1575 | if (prop && ret == EDID_LENGTH) { |
1548 | 1576 | memcpy(data->edid_data, prop, EDID_LENGTH); | |
1549 | /* Get EDID */ | 1577 | data->has_edid = true; |
1550 | prop = of_get_property(np, "edid", &len); | ||
1551 | if (prop && len == EDID_LENGTH) | ||
1552 | mfbi->edid_data = kmemdup(prop, EDID_LENGTH, | ||
1553 | GFP_KERNEL); | ||
1554 | } | ||
1555 | } | 1578 | } |
1556 | 1579 | ||
1557 | data->diu_reg = of_iomap(np, 0); | 1580 | data->diu_reg = of_iomap(np, 0); |
@@ -1561,10 +1584,6 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev) | |||
1561 | goto error; | 1584 | goto error; |
1562 | } | 1585 | } |
1563 | 1586 | ||
1564 | diu_mode = in_be32(&data->diu_reg->diu_mode); | ||
1565 | if (diu_mode == MFB_MODE0) | ||
1566 | out_be32(&data->diu_reg->diu_mode, 0); /* disable DIU */ | ||
1567 | |||
1568 | /* Get the IRQ of the DIU */ | 1587 | /* Get the IRQ of the DIU */ |
1569 | data->irq = irq_of_parse_and_map(np, 0); | 1588 | data->irq = irq_of_parse_and_map(np, 0); |
1570 | 1589 | ||
@@ -1586,11 +1605,11 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev) | |||
1586 | data->dummy_ad.paddr = DMA_ADDR(data, dummy_ad); | 1605 | data->dummy_ad.paddr = DMA_ADDR(data, dummy_ad); |
1587 | 1606 | ||
1588 | /* | 1607 | /* |
1589 | * Let DIU display splash screen if it was pre-initialized | 1608 | * Let DIU continue to display splash screen if it was pre-initialized |
1590 | * by the bootloader, set dummy area descriptor otherwise. | 1609 | * by the bootloader; otherwise, clear the display. |
1591 | */ | 1610 | */ |
1592 | if (diu_mode == MFB_MODE0) | 1611 | if (in_be32(&data->diu_reg->diu_mode) == MFB_MODE0) |
1593 | out_be32(&data->diu_reg->desc[0], data->dummy_ad.paddr); | 1612 | out_be32(&data->diu_reg->desc[0], 0); |
1594 | 1613 | ||
1595 | out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr); | 1614 | out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr); |
1596 | out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr); | 1615 | out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr); |
@@ -1603,7 +1622,16 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev) | |||
1603 | } | 1622 | } |
1604 | } | 1623 | } |
1605 | 1624 | ||
1606 | if (request_irq_local(data)) { | 1625 | /* |
1626 | * Older versions of U-Boot leave interrupts enabled, so disable | ||
1627 | * all of them and clear the status register. | ||
1628 | */ | ||
1629 | out_be32(&data->diu_reg->int_mask, 0xffffffff); | ||
1630 | in_be32(&data->diu_reg->int_status); | ||
1631 | |||
1632 | ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb", | ||
1633 | &data->diu_reg); | ||
1634 | if (ret) { | ||
1607 | dev_err(&pdev->dev, "could not claim irq\n"); | 1635 | dev_err(&pdev->dev, "could not claim irq\n"); |
1608 | goto error; | 1636 | goto error; |
1609 | } | 1637 | } |
@@ -1638,7 +1666,8 @@ static int fsl_diu_remove(struct platform_device *pdev) | |||
1638 | 1666 | ||
1639 | data = dev_get_drvdata(&pdev->dev); | 1667 | data = dev_get_drvdata(&pdev->dev); |
1640 | disable_lcdc(&data->fsl_diu_info[0]); | 1668 | disable_lcdc(&data->fsl_diu_info[0]); |
1641 | free_irq_local(data); | 1669 | |
1670 | free_irq(data->irq, &data->diu_reg); | ||
1642 | 1671 | ||
1643 | for (i = 0; i < NUM_AOIS; i++) | 1672 | for (i = 0; i < NUM_AOIS; i++) |
1644 | uninstall_fb(&data->fsl_diu_info[i]); | 1673 | uninstall_fb(&data->fsl_diu_info[i]); |
@@ -1741,6 +1770,9 @@ static int __init fsl_diu_init(void) | |||
1741 | coherence_data_size = be32_to_cpup(prop) * 13; | 1770 | coherence_data_size = be32_to_cpup(prop) * 13; |
1742 | coherence_data_size /= 8; | 1771 | coherence_data_size /= 8; |
1743 | 1772 | ||
1773 | pr_debug("fsl-diu-fb: coherence data size is %zu bytes\n", | ||
1774 | coherence_data_size); | ||
1775 | |||
1744 | prop = of_get_property(np, "d-cache-line-size", NULL); | 1776 | prop = of_get_property(np, "d-cache-line-size", NULL); |
1745 | if (prop == NULL) { | 1777 | if (prop == NULL) { |
1746 | pr_err("fsl-diu-fb: missing 'd-cache-line-size' property' " | 1778 | pr_err("fsl-diu-fb: missing 'd-cache-line-size' property' " |
@@ -1750,10 +1782,17 @@ static int __init fsl_diu_init(void) | |||
1750 | } | 1782 | } |
1751 | d_cache_line_size = be32_to_cpup(prop); | 1783 | d_cache_line_size = be32_to_cpup(prop); |
1752 | 1784 | ||
1785 | pr_debug("fsl-diu-fb: cache lines size is %u bytes\n", | ||
1786 | d_cache_line_size); | ||
1787 | |||
1753 | of_node_put(np); | 1788 | of_node_put(np); |
1754 | coherence_data = vmalloc(coherence_data_size); | 1789 | coherence_data = vmalloc(coherence_data_size); |
1755 | if (!coherence_data) | 1790 | if (!coherence_data) { |
1791 | pr_err("fsl-diu-fb: could not allocate coherence data " | ||
1792 | "(size=%zu)\n", coherence_data_size); | ||
1756 | return -ENOMEM; | 1793 | return -ENOMEM; |
1794 | } | ||
1795 | |||
1757 | #endif | 1796 | #endif |
1758 | 1797 | ||
1759 | ret = platform_driver_register(&fsl_diu_driver); | 1798 | ret = platform_driver_register(&fsl_diu_driver); |
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 d94ef9e31a35..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(pdata->version); | 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 a5ab354f267a..05ff2b91d9e8 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c | |||
@@ -33,9 +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> |
38 | #include <linux/sizes.h> | ||
39 | 39 | ||
40 | #include <video/omapdss.h> | 40 | #include <video/omapdss.h> |
41 | 41 | ||
@@ -46,21 +46,6 @@ | |||
46 | /* DISPC */ | 46 | /* DISPC */ |
47 | #define DISPC_SZ_REGS SZ_4K | 47 | #define DISPC_SZ_REGS SZ_4K |
48 | 48 | ||
49 | #define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ | ||
50 | DISPC_IRQ_OCP_ERR | \ | ||
51 | DISPC_IRQ_VID1_FIFO_UNDERFLOW | \ | ||
52 | DISPC_IRQ_VID2_FIFO_UNDERFLOW | \ | ||
53 | DISPC_IRQ_SYNC_LOST | \ | ||
54 | DISPC_IRQ_SYNC_LOST_DIGIT) | ||
55 | |||
56 | #define DISPC_MAX_NR_ISRS 8 | ||
57 | |||
58 | struct omap_dispc_isr_data { | ||
59 | omap_dispc_isr_t isr; | ||
60 | void *arg; | ||
61 | u32 mask; | ||
62 | }; | ||
63 | |||
64 | enum omap_burst_size { | 49 | enum omap_burst_size { |
65 | BURST_SIZE_X2 = 0, | 50 | BURST_SIZE_X2 = 0, |
66 | BURST_SIZE_X4 = 1, | 51 | BURST_SIZE_X4 = 1, |
@@ -73,12 +58,6 @@ enum omap_burst_size { | |||
73 | #define REG_FLD_MOD(idx, val, start, end) \ | 58 | #define REG_FLD_MOD(idx, val, start, end) \ |
74 | 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)) |
75 | 60 | ||
76 | struct dispc_irq_stats { | ||
77 | unsigned long last_reset; | ||
78 | unsigned irq_count; | ||
79 | unsigned irqs[32]; | ||
80 | }; | ||
81 | |||
82 | struct dispc_features { | 61 | struct dispc_features { |
83 | u8 sw_start; | 62 | u8 sw_start; |
84 | u8 fp_start; | 63 | u8 fp_start; |
@@ -86,19 +65,26 @@ struct dispc_features { | |||
86 | u16 sw_max; | 65 | u16 sw_max; |
87 | u16 vp_max; | 66 | u16 vp_max; |
88 | u16 hp_max; | 67 | u16 hp_max; |
89 | 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, | ||
90 | const struct omap_video_timings *mgr_timings, | 73 | const struct omap_video_timings *mgr_timings, |
91 | u16 width, u16 height, u16 out_width, u16 out_height, | 74 | u16 width, u16 height, u16 out_width, u16 out_height, |
92 | enum omap_color_mode color_mode, bool *five_taps, | 75 | enum omap_color_mode color_mode, bool *five_taps, |
93 | 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, |
94 | u16 pos_x, unsigned long *core_clk, bool mem_to_mem); | 77 | u16 pos_x, unsigned long *core_clk, bool mem_to_mem); |
95 | unsigned long (*calc_core_clk) (enum omap_plane plane, | 78 | unsigned long (*calc_core_clk) (unsigned long pclk, |
96 | u16 width, u16 height, u16 out_width, u16 out_height, | 79 | u16 width, u16 height, u16 out_width, u16 out_height, |
97 | bool mem_to_mem); | 80 | bool mem_to_mem); |
98 | u8 num_fifos; | 81 | u8 num_fifos; |
99 | 82 | ||
100 | /* swap GFX & WB fifos */ | 83 | /* swap GFX & WB fifos */ |
101 | 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; | ||
102 | }; | 88 | }; |
103 | 89 | ||
104 | #define DISPC_MAX_NR_FIFOS 5 | 90 | #define DISPC_MAX_NR_FIFOS 5 |
@@ -110,27 +96,15 @@ static struct { | |||
110 | int ctx_loss_cnt; | 96 | int ctx_loss_cnt; |
111 | 97 | ||
112 | int irq; | 98 | int irq; |
113 | struct clk *dss_clk; | ||
114 | 99 | ||
115 | u32 fifo_size[DISPC_MAX_NR_FIFOS]; | 100 | u32 fifo_size[DISPC_MAX_NR_FIFOS]; |
116 | /* maps which plane is using a fifo. fifo-id -> plane-id */ | 101 | /* maps which plane is using a fifo. fifo-id -> plane-id */ |
117 | int fifo_assignment[DISPC_MAX_NR_FIFOS]; | 102 | int fifo_assignment[DISPC_MAX_NR_FIFOS]; |
118 | 103 | ||
119 | spinlock_t irq_lock; | ||
120 | u32 irq_error_mask; | ||
121 | struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS]; | ||
122 | u32 error_irqs; | ||
123 | struct work_struct error_work; | ||
124 | |||
125 | bool ctx_valid; | 104 | bool ctx_valid; |
126 | u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; | 105 | u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; |
127 | 106 | ||
128 | const struct dispc_features *feat; | 107 | const struct dispc_features *feat; |
129 | |||
130 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
131 | spinlock_t irq_stats_lock; | ||
132 | struct dispc_irq_stats irq_stats; | ||
133 | #endif | ||
134 | } dispc; | 108 | } dispc; |
135 | 109 | ||
136 | enum omap_color_component { | 110 | enum omap_color_component { |
@@ -186,7 +160,7 @@ static const struct { | |||
186 | [OMAP_DSS_CHANNEL_DIGIT] = { | 160 | [OMAP_DSS_CHANNEL_DIGIT] = { |
187 | .name = "DIGIT", | 161 | .name = "DIGIT", |
188 | .vsync_irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN, | 162 | .vsync_irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN, |
189 | .framedone_irq = 0, | 163 | .framedone_irq = DISPC_IRQ_FRAMEDONETV, |
190 | .sync_lost_irq = DISPC_IRQ_SYNC_LOST_DIGIT, | 164 | .sync_lost_irq = DISPC_IRQ_SYNC_LOST_DIGIT, |
191 | .reg_desc = { | 165 | .reg_desc = { |
192 | [DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL, 1, 1 }, | 166 | [DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL, 1, 1 }, |
@@ -241,7 +215,6 @@ struct color_conv_coef { | |||
241 | int full_range; | 215 | int full_range; |
242 | }; | 216 | }; |
243 | 217 | ||
244 | static void _omap_dispc_set_irqs(void); | ||
245 | static unsigned long dispc_plane_pclk_rate(enum omap_plane plane); | 218 | static unsigned long dispc_plane_pclk_rate(enum omap_plane plane); |
246 | static unsigned long dispc_plane_lclk_rate(enum omap_plane plane); | 219 | static unsigned long dispc_plane_lclk_rate(enum omap_plane plane); |
247 | 220 | ||
@@ -374,7 +347,7 @@ static void dispc_save_context(void) | |||
374 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | 347 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) |
375 | SR(DIVISOR); | 348 | SR(DIVISOR); |
376 | 349 | ||
377 | dispc.ctx_loss_cnt = dss_get_ctx_loss_count(&dispc.pdev->dev); | 350 | dispc.ctx_loss_cnt = dss_get_ctx_loss_count(); |
378 | dispc.ctx_valid = true; | 351 | dispc.ctx_valid = true; |
379 | 352 | ||
380 | 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); |
@@ -389,7 +362,7 @@ static void dispc_restore_context(void) | |||
389 | if (!dispc.ctx_valid) | 362 | if (!dispc.ctx_valid) |
390 | return; | 363 | return; |
391 | 364 | ||
392 | ctx = dss_get_ctx_loss_count(&dispc.pdev->dev); | 365 | ctx = dss_get_ctx_loss_count(); |
393 | 366 | ||
394 | if (ctx >= 0 && ctx == dispc.ctx_loss_cnt) | 367 | if (ctx >= 0 && ctx == dispc.ctx_loss_cnt) |
395 | return; | 368 | return; |
@@ -496,7 +469,7 @@ static void dispc_restore_context(void) | |||
496 | if (dss_has_feature(FEAT_MGR_LCD3)) | 469 | if (dss_has_feature(FEAT_MGR_LCD3)) |
497 | RR(CONTROL3); | 470 | RR(CONTROL3); |
498 | /* clear spurious SYNC_LOST_DIGIT interrupts */ | 471 | /* clear spurious SYNC_LOST_DIGIT interrupts */ |
499 | dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); | 472 | dispc_clear_irqstatus(DISPC_IRQ_SYNC_LOST_DIGIT); |
500 | 473 | ||
501 | /* | 474 | /* |
502 | * enable last so IRQs won't trigger before | 475 | * enable last so IRQs won't trigger before |
@@ -520,6 +493,7 @@ int dispc_runtime_get(void) | |||
520 | WARN_ON(r < 0); | 493 | WARN_ON(r < 0); |
521 | return r < 0 ? r : 0; | 494 | return r < 0 ? r : 0; |
522 | } | 495 | } |
496 | EXPORT_SYMBOL(dispc_runtime_get); | ||
523 | 497 | ||
524 | void dispc_runtime_put(void) | 498 | void dispc_runtime_put(void) |
525 | { | 499 | { |
@@ -530,16 +504,28 @@ void dispc_runtime_put(void) | |||
530 | r = pm_runtime_put_sync(&dispc.pdev->dev); | 504 | r = pm_runtime_put_sync(&dispc.pdev->dev); |
531 | WARN_ON(r < 0 && r != -ENOSYS); | 505 | WARN_ON(r < 0 && r != -ENOSYS); |
532 | } | 506 | } |
507 | EXPORT_SYMBOL(dispc_runtime_put); | ||
533 | 508 | ||
534 | u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) | 509 | u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) |
535 | { | 510 | { |
536 | return mgr_desc[channel].vsync_irq; | 511 | return mgr_desc[channel].vsync_irq; |
537 | } | 512 | } |
513 | EXPORT_SYMBOL(dispc_mgr_get_vsync_irq); | ||
538 | 514 | ||
539 | u32 dispc_mgr_get_framedone_irq(enum omap_channel channel) | 515 | u32 dispc_mgr_get_framedone_irq(enum omap_channel channel) |
540 | { | 516 | { |
517 | if (channel == OMAP_DSS_CHANNEL_DIGIT && dispc.feat->no_framedone_tv) | ||
518 | return 0; | ||
519 | |||
541 | return mgr_desc[channel].framedone_irq; | 520 | return mgr_desc[channel].framedone_irq; |
542 | } | 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); | ||
543 | 529 | ||
544 | u32 dispc_wb_get_framedone_irq(void) | 530 | u32 dispc_wb_get_framedone_irq(void) |
545 | { | 531 | { |
@@ -550,28 +536,18 @@ bool dispc_mgr_go_busy(enum omap_channel channel) | |||
550 | { | 536 | { |
551 | return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1; | 537 | return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1; |
552 | } | 538 | } |
539 | EXPORT_SYMBOL(dispc_mgr_go_busy); | ||
553 | 540 | ||
554 | void dispc_mgr_go(enum omap_channel channel) | 541 | void dispc_mgr_go(enum omap_channel channel) |
555 | { | 542 | { |
556 | bool enable_bit, go_bit; | 543 | WARN_ON(dispc_mgr_is_enabled(channel) == false); |
557 | 544 | WARN_ON(dispc_mgr_go_busy(channel)); | |
558 | /* if the channel is not enabled, we don't need GO */ | ||
559 | enable_bit = mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE) == 1; | ||
560 | |||
561 | if (!enable_bit) | ||
562 | return; | ||
563 | |||
564 | go_bit = mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1; | ||
565 | |||
566 | if (go_bit) { | ||
567 | DSSERR("GO bit not down for channel %d\n", channel); | ||
568 | return; | ||
569 | } | ||
570 | 545 | ||
571 | DSSDBG("GO %s\n", mgr_desc[channel].name); | 546 | DSSDBG("GO %s\n", mgr_desc[channel].name); |
572 | 547 | ||
573 | mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1); | 548 | mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1); |
574 | } | 549 | } |
550 | EXPORT_SYMBOL(dispc_mgr_go); | ||
575 | 551 | ||
576 | bool dispc_wb_go_busy(void) | 552 | bool dispc_wb_go_busy(void) |
577 | { | 553 | { |
@@ -975,6 +951,7 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel) | |||
975 | } | 951 | } |
976 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); | 952 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); |
977 | } | 953 | } |
954 | EXPORT_SYMBOL(dispc_ovl_set_channel_out); | ||
978 | 955 | ||
979 | 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) |
980 | { | 957 | { |
@@ -1040,7 +1017,7 @@ static void dispc_configure_burst_sizes(void) | |||
1040 | const int burst_size = BURST_SIZE_X8; | 1017 | const int burst_size = BURST_SIZE_X8; |
1041 | 1018 | ||
1042 | /* Configure burst size always to maximum size */ | 1019 | /* Configure burst size always to maximum size */ |
1043 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) | 1020 | for (i = 0; i < dss_feat_get_num_ovls(); ++i) |
1044 | dispc_ovl_set_burst_size(i, burst_size); | 1021 | dispc_ovl_set_burst_size(i, burst_size); |
1045 | } | 1022 | } |
1046 | 1023 | ||
@@ -1074,7 +1051,7 @@ static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable) | |||
1074 | } | 1051 | } |
1075 | 1052 | ||
1076 | static void dispc_mgr_set_cpr_coef(enum omap_channel channel, | 1053 | static void dispc_mgr_set_cpr_coef(enum omap_channel channel, |
1077 | struct omap_dss_cpr_coefs *coefs) | 1054 | const struct omap_dss_cpr_coefs *coefs) |
1078 | { | 1055 | { |
1079 | u32 coef_r, coef_g, coef_b; | 1056 | u32 coef_r, coef_g, coef_b; |
1080 | 1057 | ||
@@ -1122,7 +1099,9 @@ static void dispc_mgr_set_size(enum omap_channel channel, u16 width, | |||
1122 | { | 1099 | { |
1123 | u32 val; | 1100 | u32 val; |
1124 | 1101 | ||
1125 | 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 | |||
1126 | dispc_write_reg(DISPC_SIZE_MGR(channel), val); | 1105 | dispc_write_reg(DISPC_SIZE_MGR(channel), val); |
1127 | } | 1106 | } |
1128 | 1107 | ||
@@ -1244,7 +1223,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, | |||
1244 | 1223 | ||
1245 | if (use_fifomerge) { | 1224 | if (use_fifomerge) { |
1246 | total_fifo_size = 0; | 1225 | total_fifo_size = 0; |
1247 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) | 1226 | for (i = 0; i < dss_feat_get_num_ovls(); ++i) |
1248 | total_fifo_size += dispc_ovl_get_fifo_size(i); | 1227 | total_fifo_size += dispc_ovl_get_fifo_size(i); |
1249 | } else { | 1228 | } else { |
1250 | total_fifo_size = ovl_fifo_size; | 1229 | total_fifo_size = ovl_fifo_size; |
@@ -1989,16 +1968,14 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width, | |||
1989 | * 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 |
1990 | * undocumented horizontal position and timing related limitations. | 1969 | * undocumented horizontal position and timing related limitations. |
1991 | */ | 1970 | */ |
1992 | static int check_horiz_timing_omap3(enum omap_plane plane, | 1971 | static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk, |
1993 | const struct omap_video_timings *t, u16 pos_x, | 1972 | const struct omap_video_timings *t, u16 pos_x, |
1994 | u16 width, u16 height, u16 out_width, u16 out_height) | 1973 | u16 width, u16 height, u16 out_width, u16 out_height) |
1995 | { | 1974 | { |
1996 | int DS = DIV_ROUND_UP(height, out_height); | 1975 | const int ds = DIV_ROUND_UP(height, out_height); |
1997 | unsigned long nonactive; | 1976 | unsigned long nonactive; |
1998 | static const u8 limits[3] = { 8, 10, 20 }; | 1977 | static const u8 limits[3] = { 8, 10, 20 }; |
1999 | u64 val, blank; | 1978 | u64 val, blank; |
2000 | unsigned long pclk = dispc_plane_pclk_rate(plane); | ||
2001 | unsigned long lclk = dispc_plane_lclk_rate(plane); | ||
2002 | int i; | 1979 | int i; |
2003 | 1980 | ||
2004 | 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; |
@@ -2020,8 +1997,8 @@ static int check_horiz_timing_omap3(enum omap_plane plane, | |||
2020 | */ | 1997 | */ |
2021 | val = div_u64((u64)(nonactive - pos_x) * lclk, pclk); | 1998 | val = div_u64((u64)(nonactive - pos_x) * lclk, pclk); |
2022 | 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", |
2023 | val, max(0, DS - 2) * width); | 2000 | val, max(0, ds - 2) * width); |
2024 | if (val < max(0, DS - 2) * width) | 2001 | if (val < max(0, ds - 2) * width) |
2025 | return -EINVAL; | 2002 | return -EINVAL; |
2026 | 2003 | ||
2027 | /* | 2004 | /* |
@@ -2031,21 +2008,20 @@ static int check_horiz_timing_omap3(enum omap_plane plane, | |||
2031 | */ | 2008 | */ |
2032 | val = div_u64((u64)nonactive * lclk, pclk); | 2009 | val = div_u64((u64)nonactive * lclk, pclk); |
2033 | DSSDBG("nonactive * pcd = %llu, max(0, DS - 1) * width = %d\n", | 2010 | DSSDBG("nonactive * pcd = %llu, max(0, DS - 1) * width = %d\n", |
2034 | val, max(0, DS - 1) * width); | 2011 | val, max(0, ds - 1) * width); |
2035 | if (val < max(0, DS - 1) * width) | 2012 | if (val < max(0, ds - 1) * width) |
2036 | return -EINVAL; | 2013 | return -EINVAL; |
2037 | 2014 | ||
2038 | return 0; | 2015 | return 0; |
2039 | } | 2016 | } |
2040 | 2017 | ||
2041 | static unsigned long calc_core_clk_five_taps(enum omap_plane plane, | 2018 | static unsigned long calc_core_clk_five_taps(unsigned long pclk, |
2042 | const struct omap_video_timings *mgr_timings, u16 width, | 2019 | const struct omap_video_timings *mgr_timings, u16 width, |
2043 | u16 height, u16 out_width, u16 out_height, | 2020 | u16 height, u16 out_width, u16 out_height, |
2044 | enum omap_color_mode color_mode) | 2021 | enum omap_color_mode color_mode) |
2045 | { | 2022 | { |
2046 | u32 core_clk = 0; | 2023 | u32 core_clk = 0; |
2047 | u64 tmp; | 2024 | u64 tmp; |
2048 | unsigned long pclk = dispc_plane_pclk_rate(plane); | ||
2049 | 2025 | ||
2050 | if (height <= out_height && width <= out_width) | 2026 | if (height <= out_height && width <= out_width) |
2051 | return (unsigned long) pclk; | 2027 | return (unsigned long) pclk; |
@@ -2079,22 +2055,19 @@ static unsigned long calc_core_clk_five_taps(enum omap_plane plane, | |||
2079 | return core_clk; | 2055 | return core_clk; |
2080 | } | 2056 | } |
2081 | 2057 | ||
2082 | 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, |
2083 | 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) |
2084 | { | 2060 | { |
2085 | unsigned long pclk = dispc_plane_pclk_rate(plane); | ||
2086 | |||
2087 | if (height > out_height && width > out_width) | 2061 | if (height > out_height && width > out_width) |
2088 | return pclk * 4; | 2062 | return pclk * 4; |
2089 | else | 2063 | else |
2090 | return pclk * 2; | 2064 | return pclk * 2; |
2091 | } | 2065 | } |
2092 | 2066 | ||
2093 | 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, |
2094 | 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) |
2095 | { | 2069 | { |
2096 | unsigned int hf, vf; | 2070 | unsigned int hf, vf; |
2097 | unsigned long pclk = dispc_plane_pclk_rate(plane); | ||
2098 | 2071 | ||
2099 | /* | 2072 | /* |
2100 | * FIXME how to determine the 'A' factor | 2073 | * FIXME how to determine the 'A' factor |
@@ -2117,11 +2090,9 @@ static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width, | |||
2117 | return pclk * vf * hf; | 2090 | return pclk * vf * hf; |
2118 | } | 2091 | } |
2119 | 2092 | ||
2120 | 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, |
2121 | 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) |
2122 | { | 2095 | { |
2123 | unsigned long pclk; | ||
2124 | |||
2125 | /* | 2096 | /* |
2126 | * 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 |
2127 | * downscaling limitations with respect to pixel clock, return 1 as | 2098 | * downscaling limitations with respect to pixel clock, return 1 as |
@@ -2131,15 +2102,13 @@ static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width, | |||
2131 | if (mem_to_mem) | 2102 | if (mem_to_mem) |
2132 | return 1; | 2103 | return 1; |
2133 | 2104 | ||
2134 | pclk = dispc_plane_pclk_rate(plane); | ||
2135 | |||
2136 | if (width > out_width) | 2105 | if (width > out_width) |
2137 | return DIV_ROUND_UP(pclk, out_width) * width; | 2106 | return DIV_ROUND_UP(pclk, out_width) * width; |
2138 | else | 2107 | else |
2139 | return pclk; | 2108 | return pclk; |
2140 | } | 2109 | } |
2141 | 2110 | ||
2142 | 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, |
2143 | const struct omap_video_timings *mgr_timings, | 2112 | const struct omap_video_timings *mgr_timings, |
2144 | u16 width, u16 height, u16 out_width, u16 out_height, | 2113 | u16 width, u16 height, u16 out_width, u16 out_height, |
2145 | enum omap_color_mode color_mode, bool *five_taps, | 2114 | enum omap_color_mode color_mode, bool *five_taps, |
@@ -2157,7 +2126,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane, | |||
2157 | do { | 2126 | do { |
2158 | in_height = DIV_ROUND_UP(height, *decim_y); | 2127 | in_height = DIV_ROUND_UP(height, *decim_y); |
2159 | in_width = DIV_ROUND_UP(width, *decim_x); | 2128 | in_width = DIV_ROUND_UP(width, *decim_x); |
2160 | *core_clk = dispc.feat->calc_core_clk(plane, in_width, | 2129 | *core_clk = dispc.feat->calc_core_clk(pclk, in_width, |
2161 | in_height, out_width, out_height, mem_to_mem); | 2130 | in_height, out_width, out_height, mem_to_mem); |
2162 | error = (in_width > maxsinglelinewidth || !*core_clk || | 2131 | error = (in_width > maxsinglelinewidth || !*core_clk || |
2163 | *core_clk > dispc_core_clk_rate()); | 2132 | *core_clk > dispc_core_clk_rate()); |
@@ -2180,7 +2149,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane, | |||
2180 | return 0; | 2149 | return 0; |
2181 | } | 2150 | } |
2182 | 2151 | ||
2183 | 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, |
2184 | const struct omap_video_timings *mgr_timings, | 2153 | const struct omap_video_timings *mgr_timings, |
2185 | u16 width, u16 height, u16 out_width, u16 out_height, | 2154 | u16 width, u16 height, u16 out_width, u16 out_height, |
2186 | enum omap_color_mode color_mode, bool *five_taps, | 2155 | enum omap_color_mode color_mode, bool *five_taps, |
@@ -2196,10 +2165,10 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane, | |||
2196 | do { | 2165 | do { |
2197 | in_height = DIV_ROUND_UP(height, *decim_y); | 2166 | in_height = DIV_ROUND_UP(height, *decim_y); |
2198 | in_width = DIV_ROUND_UP(width, *decim_x); | 2167 | in_width = DIV_ROUND_UP(width, *decim_x); |
2199 | *core_clk = calc_core_clk_five_taps(plane, mgr_timings, | 2168 | *core_clk = calc_core_clk_five_taps(pclk, mgr_timings, |
2200 | in_width, in_height, out_width, out_height, color_mode); | 2169 | in_width, in_height, out_width, out_height, color_mode); |
2201 | 2170 | ||
2202 | error = check_horiz_timing_omap3(plane, mgr_timings, | 2171 | error = check_horiz_timing_omap3(pclk, lclk, mgr_timings, |
2203 | pos_x, in_width, in_height, out_width, | 2172 | pos_x, in_width, in_height, out_width, |
2204 | out_height); | 2173 | out_height); |
2205 | 2174 | ||
@@ -2208,7 +2177,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane, | |||
2208 | in_height < out_height * 2) | 2177 | in_height < out_height * 2) |
2209 | *five_taps = false; | 2178 | *five_taps = false; |
2210 | if (!*five_taps) | 2179 | if (!*five_taps) |
2211 | *core_clk = dispc.feat->calc_core_clk(plane, in_width, | 2180 | *core_clk = dispc.feat->calc_core_clk(pclk, in_width, |
2212 | in_height, out_width, out_height, | 2181 | in_height, out_width, out_height, |
2213 | mem_to_mem); | 2182 | mem_to_mem); |
2214 | 2183 | ||
@@ -2227,8 +2196,8 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane, | |||
2227 | } | 2196 | } |
2228 | } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); | 2197 | } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); |
2229 | 2198 | ||
2230 | 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, |
2231 | out_width, out_height)){ | 2200 | height, out_width, out_height)){ |
2232 | DSSERR("horizontal timing too tight\n"); | 2201 | DSSERR("horizontal timing too tight\n"); |
2233 | return -EINVAL; | 2202 | return -EINVAL; |
2234 | } | 2203 | } |
@@ -2246,7 +2215,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane, | |||
2246 | return 0; | 2215 | return 0; |
2247 | } | 2216 | } |
2248 | 2217 | ||
2249 | 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, |
2250 | const struct omap_video_timings *mgr_timings, | 2219 | const struct omap_video_timings *mgr_timings, |
2251 | u16 width, u16 height, u16 out_width, u16 out_height, | 2220 | u16 width, u16 height, u16 out_width, u16 out_height, |
2252 | enum omap_color_mode color_mode, bool *five_taps, | 2221 | enum omap_color_mode color_mode, bool *five_taps, |
@@ -2258,14 +2227,14 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane, | |||
2258 | u16 in_height = DIV_ROUND_UP(height, *decim_y); | 2227 | u16 in_height = DIV_ROUND_UP(height, *decim_y); |
2259 | const int maxsinglelinewidth = | 2228 | const int maxsinglelinewidth = |
2260 | dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); | 2229 | dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); |
2261 | unsigned long pclk = dispc_plane_pclk_rate(plane); | ||
2262 | const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); | 2230 | const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); |
2263 | 2231 | ||
2264 | if (mem_to_mem) | 2232 | if (mem_to_mem) { |
2265 | in_width_max = DIV_ROUND_UP(out_width, maxdownscale); | 2233 | in_width_max = out_width * maxdownscale; |
2266 | else | 2234 | } else { |
2267 | in_width_max = dispc_core_clk_rate() / | 2235 | in_width_max = dispc_core_clk_rate() / |
2268 | DIV_ROUND_UP(pclk, out_width); | 2236 | DIV_ROUND_UP(pclk, out_width); |
2237 | } | ||
2269 | 2238 | ||
2270 | *decim_x = DIV_ROUND_UP(width, in_width_max); | 2239 | *decim_x = DIV_ROUND_UP(width, in_width_max); |
2271 | 2240 | ||
@@ -2283,12 +2252,12 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane, | |||
2283 | return -EINVAL; | 2252 | return -EINVAL; |
2284 | } | 2253 | } |
2285 | 2254 | ||
2286 | *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, |
2287 | out_width, out_height, mem_to_mem); | 2256 | out_width, out_height, mem_to_mem); |
2288 | return 0; | 2257 | return 0; |
2289 | } | 2258 | } |
2290 | 2259 | ||
2291 | static int dispc_ovl_calc_scaling(enum omap_plane plane, | 2260 | static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, |
2292 | enum omap_overlay_caps caps, | 2261 | enum omap_overlay_caps caps, |
2293 | const struct omap_video_timings *mgr_timings, | 2262 | const struct omap_video_timings *mgr_timings, |
2294 | u16 width, u16 height, u16 out_width, u16 out_height, | 2263 | u16 width, u16 height, u16 out_width, u16 out_height, |
@@ -2307,9 +2276,14 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, | |||
2307 | if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0) | 2276 | if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0) |
2308 | return -EINVAL; | 2277 | return -EINVAL; |
2309 | 2278 | ||
2310 | *x_predecim = max_decim_limit; | 2279 | if (mem_to_mem) { |
2311 | *y_predecim = (rotation_type == OMAP_DSS_ROT_TILER && | 2280 | *x_predecim = *y_predecim = 1; |
2312 | 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 | } | ||
2313 | 2287 | ||
2314 | if (color_mode == OMAP_DSS_COLOR_CLUT1 || | 2288 | if (color_mode == OMAP_DSS_COLOR_CLUT1 || |
2315 | color_mode == OMAP_DSS_COLOR_CLUT2 || | 2289 | color_mode == OMAP_DSS_COLOR_CLUT2 || |
@@ -2330,7 +2304,7 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, | |||
2330 | if (decim_y > *y_predecim || out_height > height * 8) | 2304 | if (decim_y > *y_predecim || out_height > height * 8) |
2331 | return -EINVAL; | 2305 | return -EINVAL; |
2332 | 2306 | ||
2333 | ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height, | 2307 | ret = dispc.feat->calc_scaling(pclk, lclk, mgr_timings, width, height, |
2334 | out_width, out_height, color_mode, five_taps, | 2308 | out_width, out_height, color_mode, five_taps, |
2335 | 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, |
2336 | mem_to_mem); | 2310 | mem_to_mem); |
@@ -2353,6 +2327,47 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, | |||
2353 | return 0; | 2327 | return 0; |
2354 | } | 2328 | } |
2355 | 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 | |||
2356 | static int dispc_ovl_setup_common(enum omap_plane plane, | 2371 | static int dispc_ovl_setup_common(enum omap_plane plane, |
2357 | enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr, | 2372 | enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr, |
2358 | 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, |
@@ -2368,12 +2383,14 @@ static int dispc_ovl_setup_common(enum omap_plane plane, | |||
2368 | unsigned offset0, offset1; | 2383 | unsigned offset0, offset1; |
2369 | s32 row_inc; | 2384 | s32 row_inc; |
2370 | s32 pix_inc; | 2385 | s32 pix_inc; |
2371 | u16 frame_height = height; | 2386 | u16 frame_width, frame_height; |
2372 | unsigned int field_offset = 0; | 2387 | unsigned int field_offset = 0; |
2373 | u16 in_height = height; | 2388 | u16 in_height = height; |
2374 | u16 in_width = width; | 2389 | u16 in_width = width; |
2375 | int x_predecim = 1, y_predecim = 1; | 2390 | int x_predecim = 1, y_predecim = 1; |
2376 | 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); | ||
2377 | 2394 | ||
2378 | if (paddr == 0) | 2395 | if (paddr == 0) |
2379 | return -EINVAL; | 2396 | return -EINVAL; |
@@ -2398,7 +2415,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane, | |||
2398 | if (!dss_feat_color_mode_supported(plane, color_mode)) | 2415 | if (!dss_feat_color_mode_supported(plane, color_mode)) |
2399 | return -EINVAL; | 2416 | return -EINVAL; |
2400 | 2417 | ||
2401 | r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width, | 2418 | r = dispc_ovl_calc_scaling(pclk, lclk, caps, mgr_timings, in_width, |
2402 | in_height, out_width, out_height, color_mode, | 2419 | in_height, out_width, out_height, color_mode, |
2403 | &five_taps, &x_predecim, &y_predecim, pos_x, | 2420 | &five_taps, &x_predecim, &y_predecim, pos_x, |
2404 | rotation_type, mem_to_mem); | 2421 | rotation_type, mem_to_mem); |
@@ -2436,20 +2453,28 @@ static int dispc_ovl_setup_common(enum omap_plane plane, | |||
2436 | row_inc = 0; | 2453 | row_inc = 0; |
2437 | pix_inc = 0; | 2454 | pix_inc = 0; |
2438 | 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 | |||
2439 | if (rotation_type == OMAP_DSS_ROT_TILER) | 2464 | if (rotation_type == OMAP_DSS_ROT_TILER) |
2440 | calc_tiler_rotation_offset(screen_width, in_width, | 2465 | calc_tiler_rotation_offset(screen_width, frame_width, |
2441 | color_mode, fieldmode, field_offset, | 2466 | color_mode, fieldmode, field_offset, |
2442 | &offset0, &offset1, &row_inc, &pix_inc, | 2467 | &offset0, &offset1, &row_inc, &pix_inc, |
2443 | x_predecim, y_predecim); | 2468 | x_predecim, y_predecim); |
2444 | else if (rotation_type == OMAP_DSS_ROT_DMA) | 2469 | else if (rotation_type == OMAP_DSS_ROT_DMA) |
2445 | calc_dma_rotation_offset(rotation, mirror, | 2470 | calc_dma_rotation_offset(rotation, mirror, screen_width, |
2446 | screen_width, in_width, frame_height, | 2471 | frame_width, frame_height, |
2447 | color_mode, fieldmode, field_offset, | 2472 | color_mode, fieldmode, field_offset, |
2448 | &offset0, &offset1, &row_inc, &pix_inc, | 2473 | &offset0, &offset1, &row_inc, &pix_inc, |
2449 | x_predecim, y_predecim); | 2474 | x_predecim, y_predecim); |
2450 | else | 2475 | else |
2451 | calc_vrfb_rotation_offset(rotation, mirror, | 2476 | calc_vrfb_rotation_offset(rotation, mirror, |
2452 | screen_width, in_width, frame_height, | 2477 | screen_width, frame_width, frame_height, |
2453 | color_mode, fieldmode, field_offset, | 2478 | color_mode, fieldmode, field_offset, |
2454 | &offset0, &offset1, &row_inc, &pix_inc, | 2479 | &offset0, &offset1, &row_inc, &pix_inc, |
2455 | x_predecim, y_predecim); | 2480 | x_predecim, y_predecim); |
@@ -2503,7 +2528,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, | |||
2503 | bool mem_to_mem) | 2528 | bool mem_to_mem) |
2504 | { | 2529 | { |
2505 | int r; | 2530 | int r; |
2506 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); | 2531 | enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane); |
2507 | enum omap_channel channel; | 2532 | enum omap_channel channel; |
2508 | 2533 | ||
2509 | channel = dispc_ovl_get_channel_out(plane); | 2534 | channel = dispc_ovl_get_channel_out(plane); |
@@ -2514,7 +2539,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, | |||
2514 | 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, |
2515 | oi->color_mode, oi->rotation, oi->mirror, channel, replication); | 2540 | oi->color_mode, oi->rotation, oi->mirror, channel, replication); |
2516 | 2541 | ||
2517 | 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, |
2518 | 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, |
2519 | oi->out_width, oi->out_height, oi->color_mode, oi->rotation, | 2544 | oi->out_width, oi->out_height, oi->color_mode, oi->rotation, |
2520 | oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha, | 2545 | oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha, |
@@ -2522,6 +2547,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, | |||
2522 | 2547 | ||
2523 | return r; | 2548 | return r; |
2524 | } | 2549 | } |
2550 | EXPORT_SYMBOL(dispc_ovl_setup); | ||
2525 | 2551 | ||
2526 | int dispc_wb_setup(const struct omap_dss_writeback_info *wi, | 2552 | int dispc_wb_setup(const struct omap_dss_writeback_info *wi, |
2527 | bool mem_to_mem, const struct omap_video_timings *mgr_timings) | 2553 | bool mem_to_mem, const struct omap_video_timings *mgr_timings) |
@@ -2582,192 +2608,39 @@ int dispc_ovl_enable(enum omap_plane plane, bool enable) | |||
2582 | 2608 | ||
2583 | return 0; | 2609 | return 0; |
2584 | } | 2610 | } |
2611 | EXPORT_SYMBOL(dispc_ovl_enable); | ||
2585 | 2612 | ||
2586 | static void dispc_disable_isr(void *data, u32 mask) | 2613 | bool dispc_ovl_enabled(enum omap_plane plane) |
2587 | { | 2614 | { |
2588 | struct completion *compl = data; | 2615 | return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0); |
2589 | complete(compl); | ||
2590 | } | 2616 | } |
2617 | EXPORT_SYMBOL(dispc_ovl_enabled); | ||
2591 | 2618 | ||
2592 | static void _enable_lcd_out(enum omap_channel channel, bool enable) | 2619 | void dispc_mgr_enable(enum omap_channel channel, bool enable) |
2593 | { | 2620 | { |
2594 | mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable); | 2621 | mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable); |
2595 | /* flush posted write */ | 2622 | /* flush posted write */ |
2596 | mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); | 2623 | mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); |
2597 | } | 2624 | } |
2598 | 2625 | EXPORT_SYMBOL(dispc_mgr_enable); | |
2599 | static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable) | ||
2600 | { | ||
2601 | struct completion frame_done_completion; | ||
2602 | bool is_on; | ||
2603 | int r; | ||
2604 | u32 irq; | ||
2605 | |||
2606 | /* When we disable LCD output, we need to wait until frame is done. | ||
2607 | * Otherwise the DSS is still working, and turning off the clocks | ||
2608 | * prevents DSS from going to OFF mode */ | ||
2609 | is_on = mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); | ||
2610 | |||
2611 | irq = mgr_desc[channel].framedone_irq; | ||
2612 | |||
2613 | if (!enable && is_on) { | ||
2614 | init_completion(&frame_done_completion); | ||
2615 | |||
2616 | r = omap_dispc_register_isr(dispc_disable_isr, | ||
2617 | &frame_done_completion, irq); | ||
2618 | |||
2619 | if (r) | ||
2620 | DSSERR("failed to register FRAMEDONE isr\n"); | ||
2621 | } | ||
2622 | |||
2623 | _enable_lcd_out(channel, enable); | ||
2624 | |||
2625 | if (!enable && is_on) { | ||
2626 | if (!wait_for_completion_timeout(&frame_done_completion, | ||
2627 | msecs_to_jiffies(100))) | ||
2628 | DSSERR("timeout waiting for FRAME DONE\n"); | ||
2629 | |||
2630 | r = omap_dispc_unregister_isr(dispc_disable_isr, | ||
2631 | &frame_done_completion, irq); | ||
2632 | |||
2633 | if (r) | ||
2634 | DSSERR("failed to unregister FRAMEDONE isr\n"); | ||
2635 | } | ||
2636 | } | ||
2637 | |||
2638 | static void _enable_digit_out(bool enable) | ||
2639 | { | ||
2640 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1); | ||
2641 | /* flush posted write */ | ||
2642 | dispc_read_reg(DISPC_CONTROL); | ||
2643 | } | ||
2644 | |||
2645 | static void dispc_mgr_enable_digit_out(bool enable) | ||
2646 | { | ||
2647 | struct completion frame_done_completion; | ||
2648 | enum dss_hdmi_venc_clk_source_select src; | ||
2649 | int r, i; | ||
2650 | u32 irq_mask; | ||
2651 | int num_irqs; | ||
2652 | |||
2653 | if (REG_GET(DISPC_CONTROL, 1, 1) == enable) | ||
2654 | return; | ||
2655 | |||
2656 | src = dss_get_hdmi_venc_clk_source(); | ||
2657 | |||
2658 | if (enable) { | ||
2659 | unsigned long flags; | ||
2660 | /* When we enable digit output, we'll get an extra digit | ||
2661 | * sync lost interrupt, that we need to ignore */ | ||
2662 | spin_lock_irqsave(&dispc.irq_lock, flags); | ||
2663 | dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT; | ||
2664 | _omap_dispc_set_irqs(); | ||
2665 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | ||
2666 | } | ||
2667 | |||
2668 | /* When we disable digit output, we need to wait until fields are done. | ||
2669 | * Otherwise the DSS is still working, and turning off the clocks | ||
2670 | * prevents DSS from going to OFF mode. And when enabling, we need to | ||
2671 | * wait for the extra sync losts */ | ||
2672 | init_completion(&frame_done_completion); | ||
2673 | |||
2674 | if (src == DSS_HDMI_M_PCLK && enable == false) { | ||
2675 | irq_mask = DISPC_IRQ_FRAMEDONETV; | ||
2676 | num_irqs = 1; | ||
2677 | } else { | ||
2678 | irq_mask = DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD; | ||
2679 | /* XXX I understand from TRM that we should only wait for the | ||
2680 | * current field to complete. But it seems we have to wait for | ||
2681 | * both fields */ | ||
2682 | num_irqs = 2; | ||
2683 | } | ||
2684 | |||
2685 | r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion, | ||
2686 | irq_mask); | ||
2687 | if (r) | ||
2688 | DSSERR("failed to register %x isr\n", irq_mask); | ||
2689 | |||
2690 | _enable_digit_out(enable); | ||
2691 | |||
2692 | for (i = 0; i < num_irqs; ++i) { | ||
2693 | if (!wait_for_completion_timeout(&frame_done_completion, | ||
2694 | msecs_to_jiffies(100))) | ||
2695 | DSSERR("timeout waiting for digit out to %s\n", | ||
2696 | enable ? "start" : "stop"); | ||
2697 | } | ||
2698 | |||
2699 | r = omap_dispc_unregister_isr(dispc_disable_isr, &frame_done_completion, | ||
2700 | irq_mask); | ||
2701 | if (r) | ||
2702 | DSSERR("failed to unregister %x isr\n", irq_mask); | ||
2703 | |||
2704 | if (enable) { | ||
2705 | unsigned long flags; | ||
2706 | spin_lock_irqsave(&dispc.irq_lock, flags); | ||
2707 | dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST_DIGIT; | ||
2708 | dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); | ||
2709 | _omap_dispc_set_irqs(); | ||
2710 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | ||
2711 | } | ||
2712 | } | ||
2713 | 2626 | ||
2714 | bool dispc_mgr_is_enabled(enum omap_channel channel) | 2627 | bool dispc_mgr_is_enabled(enum omap_channel channel) |
2715 | { | 2628 | { |
2716 | return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); | 2629 | return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); |
2717 | } | 2630 | } |
2718 | 2631 | EXPORT_SYMBOL(dispc_mgr_is_enabled); | |
2719 | void dispc_mgr_enable(enum omap_channel channel, bool enable) | ||
2720 | { | ||
2721 | if (dss_mgr_is_lcd(channel)) | ||
2722 | dispc_mgr_enable_lcd_out(channel, enable); | ||
2723 | else if (channel == OMAP_DSS_CHANNEL_DIGIT) | ||
2724 | dispc_mgr_enable_digit_out(enable); | ||
2725 | else | ||
2726 | BUG(); | ||
2727 | } | ||
2728 | 2632 | ||
2729 | void dispc_wb_enable(bool enable) | 2633 | void dispc_wb_enable(bool enable) |
2730 | { | 2634 | { |
2731 | enum omap_plane plane = OMAP_DSS_WB; | 2635 | dispc_ovl_enable(OMAP_DSS_WB, enable); |
2732 | struct completion frame_done_completion; | ||
2733 | bool is_on; | ||
2734 | int r; | ||
2735 | u32 irq; | ||
2736 | |||
2737 | is_on = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0); | ||
2738 | irq = DISPC_IRQ_FRAMEDONEWB; | ||
2739 | |||
2740 | if (!enable && is_on) { | ||
2741 | init_completion(&frame_done_completion); | ||
2742 | |||
2743 | r = omap_dispc_register_isr(dispc_disable_isr, | ||
2744 | &frame_done_completion, irq); | ||
2745 | if (r) | ||
2746 | DSSERR("failed to register FRAMEDONEWB isr\n"); | ||
2747 | } | ||
2748 | |||
2749 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0); | ||
2750 | |||
2751 | if (!enable && is_on) { | ||
2752 | if (!wait_for_completion_timeout(&frame_done_completion, | ||
2753 | msecs_to_jiffies(100))) | ||
2754 | DSSERR("timeout waiting for FRAMEDONEWB\n"); | ||
2755 | |||
2756 | r = omap_dispc_unregister_isr(dispc_disable_isr, | ||
2757 | &frame_done_completion, irq); | ||
2758 | if (r) | ||
2759 | DSSERR("failed to unregister FRAMEDONEWB isr\n"); | ||
2760 | } | ||
2761 | } | 2636 | } |
2762 | 2637 | ||
2763 | bool dispc_wb_is_enabled(void) | 2638 | bool dispc_wb_is_enabled(void) |
2764 | { | 2639 | { |
2765 | enum omap_plane plane = OMAP_DSS_WB; | 2640 | return dispc_ovl_enabled(OMAP_DSS_WB); |
2766 | |||
2767 | return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0); | ||
2768 | } | 2641 | } |
2769 | 2642 | ||
2770 | void dispc_lcd_enable_signal_polarity(bool act_high) | 2643 | static void dispc_lcd_enable_signal_polarity(bool act_high) |
2771 | { | 2644 | { |
2772 | if (!dss_has_feature(FEAT_LCDENABLEPOL)) | 2645 | if (!dss_has_feature(FEAT_LCDENABLEPOL)) |
2773 | return; | 2646 | return; |
@@ -2791,13 +2664,13 @@ void dispc_pck_free_enable(bool enable) | |||
2791 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); | 2664 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); |
2792 | } | 2665 | } |
2793 | 2666 | ||
2794 | void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable) | 2667 | static void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable) |
2795 | { | 2668 | { |
2796 | mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable); | 2669 | mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable); |
2797 | } | 2670 | } |
2798 | 2671 | ||
2799 | 2672 | ||
2800 | void dispc_mgr_set_lcd_type_tft(enum omap_channel channel) | 2673 | static void dispc_mgr_set_lcd_type_tft(enum omap_channel channel) |
2801 | { | 2674 | { |
2802 | mgr_fld_write(channel, DISPC_MGR_FLD_STNTFT, 1); | 2675 | mgr_fld_write(channel, DISPC_MGR_FLD_STNTFT, 1); |
2803 | } | 2676 | } |
@@ -2840,7 +2713,7 @@ static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, | |||
2840 | } | 2713 | } |
2841 | 2714 | ||
2842 | void dispc_mgr_setup(enum omap_channel channel, | 2715 | void dispc_mgr_setup(enum omap_channel channel, |
2843 | struct omap_overlay_manager_info *info) | 2716 | const struct omap_overlay_manager_info *info) |
2844 | { | 2717 | { |
2845 | dispc_mgr_set_default_color(channel, info->default_color); | 2718 | dispc_mgr_set_default_color(channel, info->default_color); |
2846 | 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); |
@@ -2852,8 +2725,9 @@ void dispc_mgr_setup(enum omap_channel channel, | |||
2852 | dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs); | 2725 | dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs); |
2853 | } | 2726 | } |
2854 | } | 2727 | } |
2728 | EXPORT_SYMBOL(dispc_mgr_setup); | ||
2855 | 2729 | ||
2856 | 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) |
2857 | { | 2731 | { |
2858 | int code; | 2732 | int code; |
2859 | 2733 | ||
@@ -2878,7 +2752,7 @@ void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines) | |||
2878 | mgr_fld_write(channel, DISPC_MGR_FLD_TFTDATALINES, code); | 2752 | mgr_fld_write(channel, DISPC_MGR_FLD_TFTDATALINES, code); |
2879 | } | 2753 | } |
2880 | 2754 | ||
2881 | 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) |
2882 | { | 2756 | { |
2883 | u32 l; | 2757 | u32 l; |
2884 | int gpout0, gpout1; | 2758 | int gpout0, gpout1; |
@@ -2907,15 +2781,33 @@ void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode) | |||
2907 | dispc_write_reg(DISPC_CONTROL, l); | 2781 | dispc_write_reg(DISPC_CONTROL, l); |
2908 | } | 2782 | } |
2909 | 2783 | ||
2910 | void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable) | 2784 | static void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable) |
2911 | { | 2785 | { |
2912 | mgr_fld_write(channel, DISPC_MGR_FLD_STALLMODE, enable); | 2786 | mgr_fld_write(channel, DISPC_MGR_FLD_STALLMODE, enable); |
2913 | } | 2787 | } |
2914 | 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 | |||
2915 | static bool _dispc_mgr_size_ok(u16 width, u16 height) | 2807 | static bool _dispc_mgr_size_ok(u16 width, u16 height) |
2916 | { | 2808 | { |
2917 | return width <= dss_feat_get_param_max(FEAT_PARAM_MGR_WIDTH) && | 2809 | return width <= dispc.feat->mgr_width_max && |
2918 | height <= dss_feat_get_param_max(FEAT_PARAM_MGR_HEIGHT); | 2810 | height <= dispc.feat->mgr_height_max; |
2919 | } | 2811 | } |
2920 | 2812 | ||
2921 | 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, |
@@ -3010,7 +2902,7 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, | |||
3010 | 2902 | ||
3011 | /* change name to mode? */ | 2903 | /* change name to mode? */ |
3012 | void dispc_mgr_set_timings(enum omap_channel channel, | 2904 | void dispc_mgr_set_timings(enum omap_channel channel, |
3013 | struct omap_video_timings *timings) | 2905 | const struct omap_video_timings *timings) |
3014 | { | 2906 | { |
3015 | unsigned xtot, ytot; | 2907 | unsigned xtot, ytot; |
3016 | unsigned long ht, vt; | 2908 | unsigned long ht, vt; |
@@ -3049,6 +2941,7 @@ void dispc_mgr_set_timings(enum omap_channel channel, | |||
3049 | 2941 | ||
3050 | dispc_mgr_set_size(channel, t.x_res, t.y_res); | 2942 | dispc_mgr_set_size(channel, t.x_res, t.y_res); |
3051 | } | 2943 | } |
2944 | EXPORT_SYMBOL(dispc_mgr_set_timings); | ||
3052 | 2945 | ||
3053 | 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, |
3054 | u16 pck_div) | 2947 | u16 pck_div) |
@@ -3076,7 +2969,7 @@ unsigned long dispc_fclk_rate(void) | |||
3076 | 2969 | ||
3077 | switch (dss_get_dispc_clk_source()) { | 2970 | switch (dss_get_dispc_clk_source()) { |
3078 | case OMAP_DSS_CLK_SRC_FCK: | 2971 | case OMAP_DSS_CLK_SRC_FCK: |
3079 | r = clk_get_rate(dispc.dss_clk); | 2972 | r = dss_get_dispc_clk_rate(); |
3080 | break; | 2973 | break; |
3081 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: | 2974 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: |
3082 | dsidev = dsi_get_dsidev_from_id(0); | 2975 | dsidev = dsi_get_dsidev_from_id(0); |
@@ -3101,28 +2994,32 @@ unsigned long dispc_mgr_lclk_rate(enum omap_channel channel) | |||
3101 | unsigned long r; | 2994 | unsigned long r; |
3102 | u32 l; | 2995 | u32 l; |
3103 | 2996 | ||
3104 | l = dispc_read_reg(DISPC_DIVISORo(channel)); | 2997 | if (dss_mgr_is_lcd(channel)) { |
2998 | l = dispc_read_reg(DISPC_DIVISORo(channel)); | ||
3105 | 2999 | ||
3106 | lcd = FLD_GET(l, 23, 16); | 3000 | lcd = FLD_GET(l, 23, 16); |
3107 | 3001 | ||
3108 | switch (dss_get_lcd_clk_source(channel)) { | 3002 | switch (dss_get_lcd_clk_source(channel)) { |
3109 | case OMAP_DSS_CLK_SRC_FCK: | 3003 | case OMAP_DSS_CLK_SRC_FCK: |
3110 | r = clk_get_rate(dispc.dss_clk); | 3004 | r = dss_get_dispc_clk_rate(); |
3111 | break; | 3005 | break; |
3112 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: | 3006 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: |
3113 | dsidev = dsi_get_dsidev_from_id(0); | 3007 | dsidev = dsi_get_dsidev_from_id(0); |
3114 | r = dsi_get_pll_hsdiv_dispc_rate(dsidev); | 3008 | r = dsi_get_pll_hsdiv_dispc_rate(dsidev); |
3115 | break; | 3009 | break; |
3116 | case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: | 3010 | case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: |
3117 | dsidev = dsi_get_dsidev_from_id(1); | 3011 | dsidev = dsi_get_dsidev_from_id(1); |
3118 | r = dsi_get_pll_hsdiv_dispc_rate(dsidev); | 3012 | r = dsi_get_pll_hsdiv_dispc_rate(dsidev); |
3119 | break; | 3013 | break; |
3120 | default: | 3014 | default: |
3121 | BUG(); | 3015 | BUG(); |
3122 | return 0; | 3016 | return 0; |
3123 | } | 3017 | } |
3124 | 3018 | ||
3125 | return r / lcd; | 3019 | return r / lcd; |
3020 | } else { | ||
3021 | return dispc_fclk_rate(); | ||
3022 | } | ||
3126 | } | 3023 | } |
3127 | 3024 | ||
3128 | unsigned long dispc_mgr_pclk_rate(enum omap_channel channel) | 3025 | unsigned long dispc_mgr_pclk_rate(enum omap_channel channel) |
@@ -3172,21 +3069,28 @@ unsigned long dispc_core_clk_rate(void) | |||
3172 | 3069 | ||
3173 | static unsigned long dispc_plane_pclk_rate(enum omap_plane plane) | 3070 | static unsigned long dispc_plane_pclk_rate(enum omap_plane plane) |
3174 | { | 3071 | { |
3175 | 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); | ||
3176 | 3078 | ||
3177 | return dispc_mgr_pclk_rate(channel); | 3079 | return dispc_mgr_pclk_rate(channel); |
3178 | } | 3080 | } |
3179 | 3081 | ||
3180 | static unsigned long dispc_plane_lclk_rate(enum omap_plane plane) | 3082 | static unsigned long dispc_plane_lclk_rate(enum omap_plane plane) |
3181 | { | 3083 | { |
3182 | enum omap_channel channel = dispc_ovl_get_channel_out(plane); | 3084 | enum omap_channel channel; |
3183 | 3085 | ||
3184 | if (dss_mgr_is_lcd(channel)) | 3086 | if (plane == OMAP_DSS_WB) |
3185 | return dispc_mgr_lclk_rate(channel); | 3087 | return 0; |
3186 | else | 3088 | |
3187 | return dispc_fclk_rate(); | 3089 | channel = dispc_ovl_get_channel_out(plane); |
3188 | 3090 | ||
3091 | return dispc_mgr_lclk_rate(channel); | ||
3189 | } | 3092 | } |
3093 | |||
3190 | 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) |
3191 | { | 3095 | { |
3192 | int lcd, pcd; | 3096 | int lcd, pcd; |
@@ -3244,64 +3148,6 @@ void dispc_dump_clocks(struct seq_file *s) | |||
3244 | dispc_runtime_put(); | 3148 | dispc_runtime_put(); |
3245 | } | 3149 | } |
3246 | 3150 | ||
3247 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
3248 | void dispc_dump_irqs(struct seq_file *s) | ||
3249 | { | ||
3250 | unsigned long flags; | ||
3251 | struct dispc_irq_stats stats; | ||
3252 | |||
3253 | spin_lock_irqsave(&dispc.irq_stats_lock, flags); | ||
3254 | |||
3255 | stats = dispc.irq_stats; | ||
3256 | memset(&dispc.irq_stats, 0, sizeof(dispc.irq_stats)); | ||
3257 | dispc.irq_stats.last_reset = jiffies; | ||
3258 | |||
3259 | spin_unlock_irqrestore(&dispc.irq_stats_lock, flags); | ||
3260 | |||
3261 | seq_printf(s, "period %u ms\n", | ||
3262 | jiffies_to_msecs(jiffies - stats.last_reset)); | ||
3263 | |||
3264 | seq_printf(s, "irqs %d\n", stats.irq_count); | ||
3265 | #define PIS(x) \ | ||
3266 | seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]); | ||
3267 | |||
3268 | PIS(FRAMEDONE); | ||
3269 | PIS(VSYNC); | ||
3270 | PIS(EVSYNC_EVEN); | ||
3271 | PIS(EVSYNC_ODD); | ||
3272 | PIS(ACBIAS_COUNT_STAT); | ||
3273 | PIS(PROG_LINE_NUM); | ||
3274 | PIS(GFX_FIFO_UNDERFLOW); | ||
3275 | PIS(GFX_END_WIN); | ||
3276 | PIS(PAL_GAMMA_MASK); | ||
3277 | PIS(OCP_ERR); | ||
3278 | PIS(VID1_FIFO_UNDERFLOW); | ||
3279 | PIS(VID1_END_WIN); | ||
3280 | PIS(VID2_FIFO_UNDERFLOW); | ||
3281 | PIS(VID2_END_WIN); | ||
3282 | if (dss_feat_get_num_ovls() > 3) { | ||
3283 | PIS(VID3_FIFO_UNDERFLOW); | ||
3284 | PIS(VID3_END_WIN); | ||
3285 | } | ||
3286 | PIS(SYNC_LOST); | ||
3287 | PIS(SYNC_LOST_DIGIT); | ||
3288 | PIS(WAKEUP); | ||
3289 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
3290 | PIS(FRAMEDONE2); | ||
3291 | PIS(VSYNC2); | ||
3292 | PIS(ACBIAS_COUNT_STAT2); | ||
3293 | PIS(SYNC_LOST2); | ||
3294 | } | ||
3295 | if (dss_has_feature(FEAT_MGR_LCD3)) { | ||
3296 | PIS(FRAMEDONE3); | ||
3297 | PIS(VSYNC3); | ||
3298 | PIS(ACBIAS_COUNT_STAT3); | ||
3299 | PIS(SYNC_LOST3); | ||
3300 | } | ||
3301 | #undef PIS | ||
3302 | } | ||
3303 | #endif | ||
3304 | |||
3305 | static void dispc_dump_regs(struct seq_file *s) | 3151 | static void dispc_dump_regs(struct seq_file *s) |
3306 | { | 3152 | { |
3307 | int i, j; | 3153 | int i, j; |
@@ -3351,7 +3197,7 @@ static void dispc_dump_regs(struct seq_file *s) | |||
3351 | 3197 | ||
3352 | #define DISPC_REG(i, name) name(i) | 3198 | #define DISPC_REG(i, name) name(i) |
3353 | #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], \ |
3354 | 48 - strlen(#r) - strlen(p_names[i]), " ", \ | 3200 | (int)(48 - strlen(#r) - strlen(p_names[i])), " ", \ |
3355 | dispc_read_reg(DISPC_REG(i, r))) | 3201 | dispc_read_reg(DISPC_REG(i, r))) |
3356 | 3202 | ||
3357 | p_names = mgr_names; | 3203 | p_names = mgr_names; |
@@ -3428,7 +3274,7 @@ static void dispc_dump_regs(struct seq_file *s) | |||
3428 | #define DISPC_REG(plane, name, i) name(plane, i) | 3274 | #define DISPC_REG(plane, name, i) name(plane, i) |
3429 | #define DUMPREG(plane, name, i) \ | 3275 | #define DUMPREG(plane, name, i) \ |
3430 | 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], \ |
3431 | 46 - strlen(#name) - strlen(p_names[plane]), " ", \ | 3277 | (int)(46 - strlen(#name) - strlen(p_names[plane])), " ", \ |
3432 | dispc_read_reg(DISPC_REG(plane, name, i))) | 3278 | dispc_read_reg(DISPC_REG(plane, name, i))) |
3433 | 3279 | ||
3434 | /* Video pipeline coefficient registers */ | 3280 | /* Video pipeline coefficient registers */ |
@@ -3531,7 +3377,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, | |||
3531 | } | 3377 | } |
3532 | 3378 | ||
3533 | void dispc_mgr_set_clock_div(enum omap_channel channel, | 3379 | void dispc_mgr_set_clock_div(enum omap_channel channel, |
3534 | struct dispc_clock_info *cinfo) | 3380 | const struct dispc_clock_info *cinfo) |
3535 | { | 3381 | { |
3536 | DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div); | 3382 | DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div); |
3537 | DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); | 3383 | DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); |
@@ -3555,403 +3401,34 @@ int dispc_mgr_get_clock_div(enum omap_channel channel, | |||
3555 | return 0; | 3401 | return 0; |
3556 | } | 3402 | } |
3557 | 3403 | ||
3558 | /* dispc.irq_lock has to be locked by the caller */ | 3404 | u32 dispc_read_irqstatus(void) |
3559 | static void _omap_dispc_set_irqs(void) | ||
3560 | { | 3405 | { |
3561 | u32 mask; | 3406 | return dispc_read_reg(DISPC_IRQSTATUS); |
3562 | u32 old_mask; | ||
3563 | int i; | ||
3564 | struct omap_dispc_isr_data *isr_data; | ||
3565 | |||
3566 | mask = dispc.irq_error_mask; | ||
3567 | |||
3568 | for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { | ||
3569 | isr_data = &dispc.registered_isr[i]; | ||
3570 | |||
3571 | if (isr_data->isr == NULL) | ||
3572 | continue; | ||
3573 | |||
3574 | mask |= isr_data->mask; | ||
3575 | } | ||
3576 | |||
3577 | old_mask = dispc_read_reg(DISPC_IRQENABLE); | ||
3578 | /* clear the irqstatus for newly enabled irqs */ | ||
3579 | dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask); | ||
3580 | |||
3581 | dispc_write_reg(DISPC_IRQENABLE, mask); | ||
3582 | } | ||
3583 | |||
3584 | int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask) | ||
3585 | { | ||
3586 | int i; | ||
3587 | int ret; | ||
3588 | unsigned long flags; | ||
3589 | struct omap_dispc_isr_data *isr_data; | ||
3590 | |||
3591 | if (isr == NULL) | ||
3592 | return -EINVAL; | ||
3593 | |||
3594 | spin_lock_irqsave(&dispc.irq_lock, flags); | ||
3595 | |||
3596 | /* check for duplicate entry */ | ||
3597 | for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { | ||
3598 | isr_data = &dispc.registered_isr[i]; | ||
3599 | if (isr_data->isr == isr && isr_data->arg == arg && | ||
3600 | isr_data->mask == mask) { | ||
3601 | ret = -EINVAL; | ||
3602 | goto err; | ||
3603 | } | ||
3604 | } | ||
3605 | |||
3606 | isr_data = NULL; | ||
3607 | ret = -EBUSY; | ||
3608 | |||
3609 | for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { | ||
3610 | isr_data = &dispc.registered_isr[i]; | ||
3611 | |||
3612 | if (isr_data->isr != NULL) | ||
3613 | continue; | ||
3614 | |||
3615 | isr_data->isr = isr; | ||
3616 | isr_data->arg = arg; | ||
3617 | isr_data->mask = mask; | ||
3618 | ret = 0; | ||
3619 | |||
3620 | break; | ||
3621 | } | ||
3622 | |||
3623 | if (ret) | ||
3624 | goto err; | ||
3625 | |||
3626 | _omap_dispc_set_irqs(); | ||
3627 | |||
3628 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | ||
3629 | |||
3630 | return 0; | ||
3631 | err: | ||
3632 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | ||
3633 | |||
3634 | return ret; | ||
3635 | } | ||
3636 | EXPORT_SYMBOL(omap_dispc_register_isr); | ||
3637 | |||
3638 | int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask) | ||
3639 | { | ||
3640 | int i; | ||
3641 | unsigned long flags; | ||
3642 | int ret = -EINVAL; | ||
3643 | struct omap_dispc_isr_data *isr_data; | ||
3644 | |||
3645 | spin_lock_irqsave(&dispc.irq_lock, flags); | ||
3646 | |||
3647 | for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { | ||
3648 | isr_data = &dispc.registered_isr[i]; | ||
3649 | if (isr_data->isr != isr || isr_data->arg != arg || | ||
3650 | isr_data->mask != mask) | ||
3651 | continue; | ||
3652 | |||
3653 | /* found the correct isr */ | ||
3654 | |||
3655 | isr_data->isr = NULL; | ||
3656 | isr_data->arg = NULL; | ||
3657 | isr_data->mask = 0; | ||
3658 | |||
3659 | ret = 0; | ||
3660 | break; | ||
3661 | } | ||
3662 | |||
3663 | if (ret == 0) | ||
3664 | _omap_dispc_set_irqs(); | ||
3665 | |||
3666 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | ||
3667 | |||
3668 | return ret; | ||
3669 | } | ||
3670 | EXPORT_SYMBOL(omap_dispc_unregister_isr); | ||
3671 | |||
3672 | #ifdef DEBUG | ||
3673 | static void print_irq_status(u32 status) | ||
3674 | { | ||
3675 | if ((status & dispc.irq_error_mask) == 0) | ||
3676 | return; | ||
3677 | |||
3678 | printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status); | ||
3679 | |||
3680 | #define PIS(x) \ | ||
3681 | if (status & DISPC_IRQ_##x) \ | ||
3682 | printk(#x " "); | ||
3683 | PIS(GFX_FIFO_UNDERFLOW); | ||
3684 | PIS(OCP_ERR); | ||
3685 | PIS(VID1_FIFO_UNDERFLOW); | ||
3686 | PIS(VID2_FIFO_UNDERFLOW); | ||
3687 | if (dss_feat_get_num_ovls() > 3) | ||
3688 | PIS(VID3_FIFO_UNDERFLOW); | ||
3689 | PIS(SYNC_LOST); | ||
3690 | PIS(SYNC_LOST_DIGIT); | ||
3691 | if (dss_has_feature(FEAT_MGR_LCD2)) | ||
3692 | PIS(SYNC_LOST2); | ||
3693 | if (dss_has_feature(FEAT_MGR_LCD3)) | ||
3694 | PIS(SYNC_LOST3); | ||
3695 | #undef PIS | ||
3696 | |||
3697 | printk("\n"); | ||
3698 | } | ||
3699 | #endif | ||
3700 | |||
3701 | /* Called from dss.c. Note that we don't touch clocks here, | ||
3702 | * but we presume they are on because we got an IRQ. However, | ||
3703 | * an irq handler may turn the clocks off, so we may not have | ||
3704 | * clock later in the function. */ | ||
3705 | static irqreturn_t omap_dispc_irq_handler(int irq, void *arg) | ||
3706 | { | ||
3707 | int i; | ||
3708 | u32 irqstatus, irqenable; | ||
3709 | u32 handledirqs = 0; | ||
3710 | u32 unhandled_errors; | ||
3711 | struct omap_dispc_isr_data *isr_data; | ||
3712 | struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS]; | ||
3713 | |||
3714 | spin_lock(&dispc.irq_lock); | ||
3715 | |||
3716 | irqstatus = dispc_read_reg(DISPC_IRQSTATUS); | ||
3717 | irqenable = dispc_read_reg(DISPC_IRQENABLE); | ||
3718 | |||
3719 | /* IRQ is not for us */ | ||
3720 | if (!(irqstatus & irqenable)) { | ||
3721 | spin_unlock(&dispc.irq_lock); | ||
3722 | return IRQ_NONE; | ||
3723 | } | ||
3724 | |||
3725 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
3726 | spin_lock(&dispc.irq_stats_lock); | ||
3727 | dispc.irq_stats.irq_count++; | ||
3728 | dss_collect_irq_stats(irqstatus, dispc.irq_stats.irqs); | ||
3729 | spin_unlock(&dispc.irq_stats_lock); | ||
3730 | #endif | ||
3731 | |||
3732 | #ifdef DEBUG | ||
3733 | if (dss_debug) | ||
3734 | print_irq_status(irqstatus); | ||
3735 | #endif | ||
3736 | /* Ack the interrupt. Do it here before clocks are possibly turned | ||
3737 | * off */ | ||
3738 | dispc_write_reg(DISPC_IRQSTATUS, irqstatus); | ||
3739 | /* flush posted write */ | ||
3740 | dispc_read_reg(DISPC_IRQSTATUS); | ||
3741 | |||
3742 | /* make a copy and unlock, so that isrs can unregister | ||
3743 | * themselves */ | ||
3744 | memcpy(registered_isr, dispc.registered_isr, | ||
3745 | sizeof(registered_isr)); | ||
3746 | |||
3747 | spin_unlock(&dispc.irq_lock); | ||
3748 | |||
3749 | for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { | ||
3750 | isr_data = ®istered_isr[i]; | ||
3751 | |||
3752 | if (!isr_data->isr) | ||
3753 | continue; | ||
3754 | |||
3755 | if (isr_data->mask & irqstatus) { | ||
3756 | isr_data->isr(isr_data->arg, irqstatus); | ||
3757 | handledirqs |= isr_data->mask; | ||
3758 | } | ||
3759 | } | ||
3760 | |||
3761 | spin_lock(&dispc.irq_lock); | ||
3762 | |||
3763 | unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask; | ||
3764 | |||
3765 | if (unhandled_errors) { | ||
3766 | dispc.error_irqs |= unhandled_errors; | ||
3767 | |||
3768 | dispc.irq_error_mask &= ~unhandled_errors; | ||
3769 | _omap_dispc_set_irqs(); | ||
3770 | |||
3771 | schedule_work(&dispc.error_work); | ||
3772 | } | ||
3773 | |||
3774 | spin_unlock(&dispc.irq_lock); | ||
3775 | |||
3776 | return IRQ_HANDLED; | ||
3777 | } | ||
3778 | |||
3779 | static void dispc_error_worker(struct work_struct *work) | ||
3780 | { | ||
3781 | int i; | ||
3782 | u32 errors; | ||
3783 | unsigned long flags; | ||
3784 | static const unsigned fifo_underflow_bits[] = { | ||
3785 | DISPC_IRQ_GFX_FIFO_UNDERFLOW, | ||
3786 | DISPC_IRQ_VID1_FIFO_UNDERFLOW, | ||
3787 | DISPC_IRQ_VID2_FIFO_UNDERFLOW, | ||
3788 | DISPC_IRQ_VID3_FIFO_UNDERFLOW, | ||
3789 | }; | ||
3790 | |||
3791 | spin_lock_irqsave(&dispc.irq_lock, flags); | ||
3792 | errors = dispc.error_irqs; | ||
3793 | dispc.error_irqs = 0; | ||
3794 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | ||
3795 | |||
3796 | dispc_runtime_get(); | ||
3797 | |||
3798 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { | ||
3799 | struct omap_overlay *ovl; | ||
3800 | unsigned bit; | ||
3801 | |||
3802 | ovl = omap_dss_get_overlay(i); | ||
3803 | bit = fifo_underflow_bits[i]; | ||
3804 | |||
3805 | if (bit & errors) { | ||
3806 | DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n", | ||
3807 | ovl->name); | ||
3808 | dispc_ovl_enable(ovl->id, false); | ||
3809 | dispc_mgr_go(ovl->manager->id); | ||
3810 | msleep(50); | ||
3811 | } | ||
3812 | } | ||
3813 | |||
3814 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { | ||
3815 | struct omap_overlay_manager *mgr; | ||
3816 | unsigned bit; | ||
3817 | |||
3818 | mgr = omap_dss_get_overlay_manager(i); | ||
3819 | bit = mgr_desc[i].sync_lost_irq; | ||
3820 | |||
3821 | if (bit & errors) { | ||
3822 | struct omap_dss_device *dssdev = mgr->get_device(mgr); | ||
3823 | bool enable; | ||
3824 | |||
3825 | DSSERR("SYNC_LOST on channel %s, restarting the output " | ||
3826 | "with video overlays disabled\n", | ||
3827 | mgr->name); | ||
3828 | |||
3829 | enable = dssdev->state == OMAP_DSS_DISPLAY_ACTIVE; | ||
3830 | dssdev->driver->disable(dssdev); | ||
3831 | |||
3832 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { | ||
3833 | struct omap_overlay *ovl; | ||
3834 | ovl = omap_dss_get_overlay(i); | ||
3835 | |||
3836 | if (ovl->id != OMAP_DSS_GFX && | ||
3837 | ovl->manager == mgr) | ||
3838 | dispc_ovl_enable(ovl->id, false); | ||
3839 | } | ||
3840 | |||
3841 | dispc_mgr_go(mgr->id); | ||
3842 | msleep(50); | ||
3843 | |||
3844 | if (enable) | ||
3845 | dssdev->driver->enable(dssdev); | ||
3846 | } | ||
3847 | } | ||
3848 | |||
3849 | if (errors & DISPC_IRQ_OCP_ERR) { | ||
3850 | DSSERR("OCP_ERR\n"); | ||
3851 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { | ||
3852 | struct omap_overlay_manager *mgr; | ||
3853 | struct omap_dss_device *dssdev; | ||
3854 | |||
3855 | mgr = omap_dss_get_overlay_manager(i); | ||
3856 | dssdev = mgr->get_device(mgr); | ||
3857 | |||
3858 | if (dssdev && dssdev->driver) | ||
3859 | dssdev->driver->disable(dssdev); | ||
3860 | } | ||
3861 | } | ||
3862 | |||
3863 | spin_lock_irqsave(&dispc.irq_lock, flags); | ||
3864 | dispc.irq_error_mask |= errors; | ||
3865 | _omap_dispc_set_irqs(); | ||
3866 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | ||
3867 | |||
3868 | dispc_runtime_put(); | ||
3869 | } | 3407 | } |
3408 | EXPORT_SYMBOL(dispc_read_irqstatus); | ||
3870 | 3409 | ||
3871 | int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout) | 3410 | void dispc_clear_irqstatus(u32 mask) |
3872 | { | 3411 | { |
3873 | void dispc_irq_wait_handler(void *data, u32 mask) | 3412 | dispc_write_reg(DISPC_IRQSTATUS, mask); |
3874 | { | ||
3875 | complete((struct completion *)data); | ||
3876 | } | ||
3877 | |||
3878 | int r; | ||
3879 | DECLARE_COMPLETION_ONSTACK(completion); | ||
3880 | |||
3881 | r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion, | ||
3882 | irqmask); | ||
3883 | |||
3884 | if (r) | ||
3885 | return r; | ||
3886 | |||
3887 | timeout = wait_for_completion_timeout(&completion, timeout); | ||
3888 | |||
3889 | omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask); | ||
3890 | |||
3891 | if (timeout == 0) | ||
3892 | return -ETIMEDOUT; | ||
3893 | |||
3894 | if (timeout == -ERESTARTSYS) | ||
3895 | return -ERESTARTSYS; | ||
3896 | |||
3897 | return 0; | ||
3898 | } | 3413 | } |
3414 | EXPORT_SYMBOL(dispc_clear_irqstatus); | ||
3899 | 3415 | ||
3900 | int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, | 3416 | u32 dispc_read_irqenable(void) |
3901 | unsigned long timeout) | ||
3902 | { | 3417 | { |
3903 | void dispc_irq_wait_handler(void *data, u32 mask) | 3418 | return dispc_read_reg(DISPC_IRQENABLE); |
3904 | { | ||
3905 | complete((struct completion *)data); | ||
3906 | } | ||
3907 | |||
3908 | int r; | ||
3909 | DECLARE_COMPLETION_ONSTACK(completion); | ||
3910 | |||
3911 | r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion, | ||
3912 | irqmask); | ||
3913 | |||
3914 | if (r) | ||
3915 | return r; | ||
3916 | |||
3917 | timeout = wait_for_completion_interruptible_timeout(&completion, | ||
3918 | timeout); | ||
3919 | |||
3920 | omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask); | ||
3921 | |||
3922 | if (timeout == 0) | ||
3923 | return -ETIMEDOUT; | ||
3924 | |||
3925 | if (timeout == -ERESTARTSYS) | ||
3926 | return -ERESTARTSYS; | ||
3927 | |||
3928 | return 0; | ||
3929 | } | 3419 | } |
3420 | EXPORT_SYMBOL(dispc_read_irqenable); | ||
3930 | 3421 | ||
3931 | static void _omap_dispc_initialize_irq(void) | 3422 | void dispc_write_irqenable(u32 mask) |
3932 | { | 3423 | { |
3933 | unsigned long flags; | 3424 | u32 old_mask = dispc_read_reg(DISPC_IRQENABLE); |
3934 | |||
3935 | spin_lock_irqsave(&dispc.irq_lock, flags); | ||
3936 | |||
3937 | memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr)); | ||
3938 | |||
3939 | dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; | ||
3940 | if (dss_has_feature(FEAT_MGR_LCD2)) | ||
3941 | dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2; | ||
3942 | if (dss_has_feature(FEAT_MGR_LCD3)) | ||
3943 | dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST3; | ||
3944 | if (dss_feat_get_num_ovls() > 3) | ||
3945 | dispc.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW; | ||
3946 | |||
3947 | /* there's SYNC_LOST_DIGIT waiting after enabling the DSS, | ||
3948 | * so clear it */ | ||
3949 | dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS)); | ||
3950 | 3425 | ||
3951 | _omap_dispc_set_irqs(); | 3426 | /* clear the irqstatus for newly enabled irqs */ |
3427 | dispc_clear_irqstatus((mask ^ old_mask) & mask); | ||
3952 | 3428 | ||
3953 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | 3429 | dispc_write_reg(DISPC_IRQENABLE, mask); |
3954 | } | 3430 | } |
3431 | EXPORT_SYMBOL(dispc_write_irqenable); | ||
3955 | 3432 | ||
3956 | void dispc_enable_sidle(void) | 3433 | void dispc_enable_sidle(void) |
3957 | { | 3434 | { |
@@ -3998,9 +3475,14 @@ static const struct dispc_features omap24xx_dispc_feats __initconst = { | |||
3998 | .sw_max = 64, | 3475 | .sw_max = 64, |
3999 | .vp_max = 255, | 3476 | .vp_max = 255, |
4000 | .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, | ||
4001 | .calc_scaling = dispc_ovl_calc_scaling_24xx, | 3482 | .calc_scaling = dispc_ovl_calc_scaling_24xx, |
4002 | .calc_core_clk = calc_core_clk_24xx, | 3483 | .calc_core_clk = calc_core_clk_24xx, |
4003 | .num_fifos = 3, | 3484 | .num_fifos = 3, |
3485 | .no_framedone_tv = true, | ||
4004 | }; | 3486 | }; |
4005 | 3487 | ||
4006 | static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = { | 3488 | static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = { |
@@ -4010,9 +3492,14 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = { | |||
4010 | .sw_max = 64, | 3492 | .sw_max = 64, |
4011 | .vp_max = 255, | 3493 | .vp_max = 255, |
4012 | .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, | ||
4013 | .calc_scaling = dispc_ovl_calc_scaling_34xx, | 3499 | .calc_scaling = dispc_ovl_calc_scaling_34xx, |
4014 | .calc_core_clk = calc_core_clk_34xx, | 3500 | .calc_core_clk = calc_core_clk_34xx, |
4015 | .num_fifos = 3, | 3501 | .num_fifos = 3, |
3502 | .no_framedone_tv = true, | ||
4016 | }; | 3503 | }; |
4017 | 3504 | ||
4018 | static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = { | 3505 | static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = { |
@@ -4022,9 +3509,14 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = { | |||
4022 | .sw_max = 256, | 3509 | .sw_max = 256, |
4023 | .vp_max = 4095, | 3510 | .vp_max = 4095, |
4024 | .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, | ||
4025 | .calc_scaling = dispc_ovl_calc_scaling_34xx, | 3516 | .calc_scaling = dispc_ovl_calc_scaling_34xx, |
4026 | .calc_core_clk = calc_core_clk_34xx, | 3517 | .calc_core_clk = calc_core_clk_34xx, |
4027 | .num_fifos = 3, | 3518 | .num_fifos = 3, |
3519 | .no_framedone_tv = true, | ||
4028 | }; | 3520 | }; |
4029 | 3521 | ||
4030 | static const struct dispc_features omap44xx_dispc_feats __initconst = { | 3522 | static const struct dispc_features omap44xx_dispc_feats __initconst = { |
@@ -4034,6 +3526,27 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = { | |||
4034 | .sw_max = 256, | 3526 | .sw_max = 256, |
4035 | .vp_max = 4095, | 3527 | .vp_max = 4095, |
4036 | .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, | ||
4037 | .calc_scaling = dispc_ovl_calc_scaling_44xx, | 3550 | .calc_scaling = dispc_ovl_calc_scaling_44xx, |
4038 | .calc_core_clk = calc_core_clk_44xx, | 3551 | .calc_core_clk = calc_core_clk_44xx, |
4039 | .num_fifos = 5, | 3552 | .num_fifos = 5, |
@@ -4042,7 +3555,6 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = { | |||
4042 | 3555 | ||
4043 | static int __init dispc_init_features(struct platform_device *pdev) | 3556 | static int __init dispc_init_features(struct platform_device *pdev) |
4044 | { | 3557 | { |
4045 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | ||
4046 | const struct dispc_features *src; | 3558 | const struct dispc_features *src; |
4047 | struct dispc_features *dst; | 3559 | struct dispc_features *dst; |
4048 | 3560 | ||
@@ -4052,7 +3564,7 @@ static int __init dispc_init_features(struct platform_device *pdev) | |||
4052 | return -ENOMEM; | 3564 | return -ENOMEM; |
4053 | } | 3565 | } |
4054 | 3566 | ||
4055 | switch (pdata->version) { | 3567 | switch (omapdss_get_version()) { |
4056 | case OMAPDSS_VER_OMAP24xx: | 3568 | case OMAPDSS_VER_OMAP24xx: |
4057 | src = &omap24xx_dispc_feats; | 3569 | src = &omap24xx_dispc_feats; |
4058 | break; | 3570 | break; |
@@ -4074,7 +3586,7 @@ static int __init dispc_init_features(struct platform_device *pdev) | |||
4074 | break; | 3586 | break; |
4075 | 3587 | ||
4076 | case OMAPDSS_VER_OMAP5: | 3588 | case OMAPDSS_VER_OMAP5: |
4077 | src = &omap44xx_dispc_feats; | 3589 | src = &omap54xx_dispc_feats; |
4078 | break; | 3590 | break; |
4079 | 3591 | ||
4080 | default: | 3592 | default: |
@@ -4087,13 +3599,25 @@ static int __init dispc_init_features(struct platform_device *pdev) | |||
4087 | return 0; | 3599 | return 0; |
4088 | } | 3600 | } |
4089 | 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 | |||
4090 | /* DISPC HW IP initialisation */ | 3615 | /* DISPC HW IP initialisation */ |
4091 | static int __init omap_dispchw_probe(struct platform_device *pdev) | 3616 | static int __init omap_dispchw_probe(struct platform_device *pdev) |
4092 | { | 3617 | { |
4093 | u32 rev; | 3618 | u32 rev; |
4094 | int r = 0; | 3619 | int r = 0; |
4095 | struct resource *dispc_mem; | 3620 | struct resource *dispc_mem; |
4096 | struct clk *clk; | ||
4097 | 3621 | ||
4098 | dispc.pdev = pdev; | 3622 | dispc.pdev = pdev; |
4099 | 3623 | ||
@@ -4101,15 +3625,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev) | |||
4101 | if (r) | 3625 | if (r) |
4102 | return r; | 3626 | return r; |
4103 | 3627 | ||
4104 | spin_lock_init(&dispc.irq_lock); | ||
4105 | |||
4106 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
4107 | spin_lock_init(&dispc.irq_stats_lock); | ||
4108 | dispc.irq_stats.last_reset = jiffies; | ||
4109 | #endif | ||
4110 | |||
4111 | INIT_WORK(&dispc.error_work, dispc_error_worker); | ||
4112 | |||
4113 | dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0); | 3628 | dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0); |
4114 | if (!dispc_mem) { | 3629 | if (!dispc_mem) { |
4115 | DSSERR("can't get IORESOURCE_MEM DISPC\n"); | 3630 | DSSERR("can't get IORESOURCE_MEM DISPC\n"); |
@@ -4129,22 +3644,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev) | |||
4129 | return -ENODEV; | 3644 | return -ENODEV; |
4130 | } | 3645 | } |
4131 | 3646 | ||
4132 | r = devm_request_irq(&pdev->dev, dispc.irq, omap_dispc_irq_handler, | ||
4133 | IRQF_SHARED, "OMAP DISPC", dispc.pdev); | ||
4134 | if (r < 0) { | ||
4135 | DSSERR("request_irq failed\n"); | ||
4136 | return r; | ||
4137 | } | ||
4138 | |||
4139 | clk = clk_get(&pdev->dev, "fck"); | ||
4140 | if (IS_ERR(clk)) { | ||
4141 | DSSERR("can't get fck\n"); | ||
4142 | r = PTR_ERR(clk); | ||
4143 | return r; | ||
4144 | } | ||
4145 | |||
4146 | dispc.dss_clk = clk; | ||
4147 | |||
4148 | pm_runtime_enable(&pdev->dev); | 3647 | pm_runtime_enable(&pdev->dev); |
4149 | 3648 | ||
4150 | r = dispc_runtime_get(); | 3649 | r = dispc_runtime_get(); |
@@ -4153,8 +3652,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev) | |||
4153 | 3652 | ||
4154 | _omap_dispc_initial_config(); | 3653 | _omap_dispc_initial_config(); |
4155 | 3654 | ||
4156 | _omap_dispc_initialize_irq(); | ||
4157 | |||
4158 | rev = dispc_read_reg(DISPC_REVISION); | 3655 | rev = dispc_read_reg(DISPC_REVISION); |
4159 | dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n", | 3656 | dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n", |
4160 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | 3657 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); |
@@ -4163,14 +3660,10 @@ static int __init omap_dispchw_probe(struct platform_device *pdev) | |||
4163 | 3660 | ||
4164 | dss_debugfs_create_file("dispc", dispc_dump_regs); | 3661 | dss_debugfs_create_file("dispc", dispc_dump_regs); |
4165 | 3662 | ||
4166 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
4167 | dss_debugfs_create_file("dispc_irq", dispc_dump_irqs); | ||
4168 | #endif | ||
4169 | return 0; | 3663 | return 0; |
4170 | 3664 | ||
4171 | err_runtime_get: | 3665 | err_runtime_get: |
4172 | pm_runtime_disable(&pdev->dev); | 3666 | pm_runtime_disable(&pdev->dev); |
4173 | clk_put(dispc.dss_clk); | ||
4174 | return r; | 3667 | return r; |
4175 | } | 3668 | } |
4176 | 3669 | ||
@@ -4178,8 +3671,6 @@ static int __exit omap_dispchw_remove(struct platform_device *pdev) | |||
4178 | { | 3671 | { |
4179 | pm_runtime_disable(&pdev->dev); | 3672 | pm_runtime_disable(&pdev->dev); |
4180 | 3673 | ||
4181 | clk_put(dispc.dss_clk); | ||
4182 | |||
4183 | return 0; | 3674 | return 0; |
4184 | } | 3675 | } |
4185 | 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 602102cebcbf..054c2a22b3f1 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c | |||
@@ -32,6 +32,7 @@ | |||
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 | ||
@@ -76,6 +77,7 @@ static struct { | |||
76 | 77 | ||
77 | struct clk *dpll4_m4_ck; | 78 | struct clk *dpll4_m4_ck; |
78 | struct clk *dss_clk; | 79 | struct clk *dss_clk; |
80 | unsigned long dss_clk_rate; | ||
79 | 81 | ||
80 | unsigned long cache_req_pck; | 82 | unsigned long cache_req_pck; |
81 | unsigned long cache_prate; | 83 | unsigned long cache_prate; |
@@ -96,6 +98,8 @@ static const char * const dss_generic_clk_source_names[] = { | |||
96 | [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", |
97 | [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", |
98 | [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", | ||
99 | }; | 103 | }; |
100 | 104 | ||
101 | 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) |
@@ -151,6 +155,21 @@ static void dss_restore_context(void) | |||
151 | #undef SR | 155 | #undef SR |
152 | #undef RR | 156 | #undef RR |
153 | 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 | |||
154 | void dss_sdi_init(int datapairs) | 173 | void dss_sdi_init(int datapairs) |
155 | { | 174 | { |
156 | u32 l; | 175 | u32 l; |
@@ -301,7 +320,7 @@ static void dss_dump_regs(struct seq_file *s) | |||
301 | #undef DUMPREG | 320 | #undef DUMPREG |
302 | } | 321 | } |
303 | 322 | ||
304 | 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) |
305 | { | 324 | { |
306 | struct platform_device *dsidev; | 325 | struct platform_device *dsidev; |
307 | int b; | 326 | int b; |
@@ -372,8 +391,10 @@ void dss_select_lcd_clk_source(enum omap_channel channel, | |||
372 | struct platform_device *dsidev; | 391 | struct platform_device *dsidev; |
373 | int b, ix, pos; | 392 | int b, ix, pos; |
374 | 393 | ||
375 | 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); | ||
376 | return; | 396 | return; |
397 | } | ||
377 | 398 | ||
378 | switch (clk_src) { | 399 | switch (clk_src) { |
379 | case OMAP_DSS_CLK_SRC_FCK: | 400 | case OMAP_DSS_CLK_SRC_FCK: |
@@ -429,6 +450,29 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) | |||
429 | } | 450 | } |
430 | } | 451 | } |
431 | 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 | |||
432 | int dss_set_clock_div(struct dss_clock_info *cinfo) | 476 | int dss_set_clock_div(struct dss_clock_info *cinfo) |
433 | { | 477 | { |
434 | if (dss.dpll4_m4_ck) { | 478 | if (dss.dpll4_m4_ck) { |
@@ -446,6 +490,10 @@ int dss_set_clock_div(struct dss_clock_info *cinfo) | |||
446 | return -EINVAL; | 490 | return -EINVAL; |
447 | } | 491 | } |
448 | 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 | |||
449 | DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); | 497 | DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); |
450 | 498 | ||
451 | return 0; | 499 | return 0; |
@@ -459,6 +507,41 @@ unsigned long dss_get_dpll4_rate(void) | |||
459 | return 0; | 507 | return 0; |
460 | } | 508 | } |
461 | 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 | |||
462 | 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, |
463 | struct dispc_clock_info *dispc_cinfo) | 546 | struct dispc_clock_info *dispc_cinfo) |
464 | { | 547 | { |
@@ -748,7 +831,7 @@ static void dss_runtime_put(void) | |||
748 | } | 831 | } |
749 | 832 | ||
750 | /* DEBUGFS */ | 833 | /* DEBUGFS */ |
751 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | 834 | #if defined(CONFIG_OMAP2_DSS_DEBUGFS) |
752 | void dss_debug_dump_clocks(struct seq_file *s) | 835 | void dss_debug_dump_clocks(struct seq_file *s) |
753 | { | 836 | { |
754 | dss_dump_clocks(s); | 837 | dss_dump_clocks(s); |
@@ -796,7 +879,6 @@ static const struct dss_features omap54xx_dss_feats __initconst = { | |||
796 | 879 | ||
797 | static int __init dss_init_features(struct platform_device *pdev) | 880 | static int __init dss_init_features(struct platform_device *pdev) |
798 | { | 881 | { |
799 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | ||
800 | const struct dss_features *src; | 882 | const struct dss_features *src; |
801 | struct dss_features *dst; | 883 | struct dss_features *dst; |
802 | 884 | ||
@@ -806,7 +888,7 @@ static int __init dss_init_features(struct platform_device *pdev) | |||
806 | return -ENOMEM; | 888 | return -ENOMEM; |
807 | } | 889 | } |
808 | 890 | ||
809 | switch (pdata->version) { | 891 | switch (omapdss_get_version()) { |
810 | case OMAPDSS_VER_OMAP24xx: | 892 | case OMAPDSS_VER_OMAP24xx: |
811 | src = &omap24xx_dss_feats; | 893 | src = &omap24xx_dss_feats; |
812 | break; | 894 | break; |
@@ -871,15 +953,23 @@ static int __init omap_dsshw_probe(struct platform_device *pdev) | |||
871 | if (r) | 953 | if (r) |
872 | return r; | 954 | return r; |
873 | 955 | ||
956 | r = dss_setup_default_clock(); | ||
957 | if (r) | ||
958 | goto err_setup_clocks; | ||
959 | |||
874 | pm_runtime_enable(&pdev->dev); | 960 | pm_runtime_enable(&pdev->dev); |
875 | 961 | ||
876 | r = dss_runtime_get(); | 962 | r = dss_runtime_get(); |
877 | if (r) | 963 | if (r) |
878 | goto err_runtime_get; | 964 | goto err_runtime_get; |
879 | 965 | ||
966 | dss.dss_clk_rate = clk_get_rate(dss.dss_clk); | ||
967 | |||
880 | /* Select DPLL */ | 968 | /* Select DPLL */ |
881 | REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); | 969 | REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); |
882 | 970 | ||
971 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); | ||
972 | |||
883 | #ifdef CONFIG_OMAP2_DSS_VENC | 973 | #ifdef CONFIG_OMAP2_DSS_VENC |
884 | REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ | 974 | REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ |
885 | 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 */ |
@@ -903,6 +993,7 @@ static int __init omap_dsshw_probe(struct platform_device *pdev) | |||
903 | 993 | ||
904 | err_runtime_get: | 994 | err_runtime_get: |
905 | pm_runtime_disable(&pdev->dev); | 995 | pm_runtime_disable(&pdev->dev); |
996 | err_setup_clocks: | ||
906 | dss_put_clocks(); | 997 | dss_put_clocks(); |
907 | return r; | 998 | return r; |
908 | } | 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 3e8287c8709d..18688c12e30d 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c | |||
@@ -18,6 +18,7 @@ | |||
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> |
@@ -429,8 +430,6 @@ static const struct dss_param_range omap2_dss_param_range[] = { | |||
429 | * scaler cannot scale a image with width more than 768. | 430 | * scaler cannot scale a image with width more than 768. |
430 | */ | 431 | */ |
431 | [FEAT_PARAM_LINEWIDTH] = { 1, 768 }, | 432 | [FEAT_PARAM_LINEWIDTH] = { 1, 768 }, |
432 | [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 }, | ||
433 | [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 }, | ||
434 | }; | 433 | }; |
435 | 434 | ||
436 | static const struct dss_param_range omap3_dss_param_range[] = { | 435 | static const struct dss_param_range omap3_dss_param_range[] = { |
@@ -445,8 +444,6 @@ static const struct dss_param_range omap3_dss_param_range[] = { | |||
445 | [FEAT_PARAM_DSI_FCK] = { 0, 173000000 }, | 444 | [FEAT_PARAM_DSI_FCK] = { 0, 173000000 }, |
446 | [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, | 445 | [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, |
447 | [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, | 446 | [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, |
448 | [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 }, | ||
449 | [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 }, | ||
450 | }; | 447 | }; |
451 | 448 | ||
452 | static const struct dss_param_range omap4_dss_param_range[] = { | 449 | static const struct dss_param_range omap4_dss_param_range[] = { |
@@ -461,8 +458,6 @@ static const struct dss_param_range omap4_dss_param_range[] = { | |||
461 | [FEAT_PARAM_DSI_FCK] = { 0, 170000000 }, | 458 | [FEAT_PARAM_DSI_FCK] = { 0, 170000000 }, |
462 | [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, | 459 | [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, |
463 | [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, | 460 | [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, |
464 | [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 }, | ||
465 | [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 }, | ||
466 | }; | 461 | }; |
467 | 462 | ||
468 | static const struct dss_param_range omap5_dss_param_range[] = { | 463 | static const struct dss_param_range omap5_dss_param_range[] = { |
@@ -477,8 +472,6 @@ static const struct dss_param_range omap5_dss_param_range[] = { | |||
477 | [FEAT_PARAM_DSI_FCK] = { 0, 170000000 }, | 472 | [FEAT_PARAM_DSI_FCK] = { 0, 170000000 }, |
478 | [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, | 473 | [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, |
479 | [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, | 474 | [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, |
480 | [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 }, | ||
481 | [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 }, | ||
482 | }; | 475 | }; |
483 | 476 | ||
484 | static const enum dss_feat_id omap2_dss_feat_list[] = { | 477 | static const enum dss_feat_id omap2_dss_feat_list[] = { |
@@ -820,6 +813,7 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = { | |||
820 | .audio_start = ti_hdmi_4xxx_audio_start, | 813 | .audio_start = ti_hdmi_4xxx_audio_start, |
821 | .audio_stop = ti_hdmi_4xxx_audio_stop, | 814 | .audio_stop = ti_hdmi_4xxx_audio_stop, |
822 | .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, | ||
823 | #endif | 817 | #endif |
824 | 818 | ||
825 | }; | 819 | }; |
@@ -846,11 +840,13 @@ int dss_feat_get_num_mgrs(void) | |||
846 | { | 840 | { |
847 | return omap_current_dss_features->num_mgrs; | 841 | return omap_current_dss_features->num_mgrs; |
848 | } | 842 | } |
843 | EXPORT_SYMBOL(dss_feat_get_num_mgrs); | ||
849 | 844 | ||
850 | int dss_feat_get_num_ovls(void) | 845 | int dss_feat_get_num_ovls(void) |
851 | { | 846 | { |
852 | return omap_current_dss_features->num_ovls; | 847 | return omap_current_dss_features->num_ovls; |
853 | } | 848 | } |
849 | EXPORT_SYMBOL(dss_feat_get_num_ovls); | ||
854 | 850 | ||
855 | int dss_feat_get_num_wbs(void) | 851 | int dss_feat_get_num_wbs(void) |
856 | { | 852 | { |
@@ -871,16 +867,19 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel | |||
871 | { | 867 | { |
872 | return omap_current_dss_features->supported_displays[channel]; | 868 | return omap_current_dss_features->supported_displays[channel]; |
873 | } | 869 | } |
870 | EXPORT_SYMBOL(dss_feat_get_supported_displays); | ||
874 | 871 | ||
875 | 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) |
876 | { | 873 | { |
877 | return omap_current_dss_features->supported_outputs[channel]; | 874 | return omap_current_dss_features->supported_outputs[channel]; |
878 | } | 875 | } |
876 | EXPORT_SYMBOL(dss_feat_get_supported_outputs); | ||
879 | 877 | ||
880 | 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) |
881 | { | 879 | { |
882 | return omap_current_dss_features->supported_color_modes[plane]; | 880 | return omap_current_dss_features->supported_color_modes[plane]; |
883 | } | 881 | } |
882 | EXPORT_SYMBOL(dss_feat_get_supported_color_modes); | ||
884 | 883 | ||
885 | 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) |
886 | { | 885 | { |
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index fc492ef72a51..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); |
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 0d6d7213a858..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) |
@@ -323,7 +330,6 @@ static void hdmi_runtime_put(void) | |||
323 | 330 | ||
324 | static int __init hdmi_init_display(struct omap_dss_device *dssdev) | 331 | static int __init hdmi_init_display(struct omap_dss_device *dssdev) |
325 | { | 332 | { |
326 | struct omap_dss_board_info *pdata = hdmi.pdev->dev.platform_data; | ||
327 | int r; | 333 | int r; |
328 | 334 | ||
329 | struct gpio gpios[] = { | 335 | struct gpio gpios[] = { |
@@ -334,13 +340,17 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev) | |||
334 | 340 | ||
335 | DSSDBG("init_display\n"); | 341 | DSSDBG("init_display\n"); |
336 | 342 | ||
337 | dss_init_hdmi_ip_ops(&hdmi.ip_data, pdata->version); | 343 | dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version()); |
338 | 344 | ||
339 | if (hdmi.vdda_hdmi_dac_reg == NULL) { | 345 | if (hdmi.vdda_hdmi_dac_reg == NULL) { |
340 | struct regulator *reg; | 346 | struct regulator *reg; |
341 | 347 | ||
342 | reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac"); | 348 | reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac"); |
343 | 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 | |||
344 | if (IS_ERR(reg)) { | 354 | if (IS_ERR(reg)) { |
345 | DSSERR("can't get VDDA_HDMI_DAC regulator\n"); | 355 | DSSERR("can't get VDDA_HDMI_DAC regulator\n"); |
346 | return PTR_ERR(reg); | 356 | return PTR_ERR(reg); |
@@ -356,7 +366,7 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev) | |||
356 | return 0; | 366 | return 0; |
357 | } | 367 | } |
358 | 368 | ||
359 | static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev) | 369 | static void hdmi_uninit_display(struct omap_dss_device *dssdev) |
360 | { | 370 | { |
361 | DSSDBG("uninit_display\n"); | 371 | DSSDBG("uninit_display\n"); |
362 | 372 | ||
@@ -399,7 +409,8 @@ static bool hdmi_timings_compare(struct omap_video_timings *timing1, | |||
399 | { | 409 | { |
400 | int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync; | 410 | int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync; |
401 | 411 | ||
402 | if ((timing2->pixel_clock == timing1->pixel_clock) && | 412 | if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) == |
413 | DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) && | ||
403 | (timing2->x_res == timing1->x_res) && | 414 | (timing2->x_res == timing1->x_res) && |
404 | (timing2->y_res == timing1->y_res)) { | 415 | (timing2->y_res == timing1->y_res)) { |
405 | 416 | ||
@@ -501,12 +512,9 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, | |||
501 | DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); | 512 | DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); |
502 | } | 513 | } |
503 | 514 | ||
504 | static int hdmi_power_on(struct omap_dss_device *dssdev) | 515 | static int hdmi_power_on_core(struct omap_dss_device *dssdev) |
505 | { | 516 | { |
506 | int r; | 517 | int r; |
507 | struct omap_video_timings *p; | ||
508 | struct omap_overlay_manager *mgr = dssdev->output->manager; | ||
509 | unsigned long phy; | ||
510 | 518 | ||
511 | gpio_set_value(hdmi.ct_cp_hpd_gpio, 1); | 519 | gpio_set_value(hdmi.ct_cp_hpd_gpio, 1); |
512 | gpio_set_value(hdmi.ls_oe_gpio, 1); | 520 | gpio_set_value(hdmi.ls_oe_gpio, 1); |
@@ -522,6 +530,38 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
522 | if (r) | 530 | if (r) |
523 | goto err_runtime_get; | 531 | goto err_runtime_get; |
524 | 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 | |||
525 | dss_mgr_disable(mgr); | 565 | dss_mgr_disable(mgr); |
526 | 566 | ||
527 | p = &hdmi.ip_data.cfg.timings; | 567 | p = &hdmi.ip_data.cfg.timings; |
@@ -549,17 +589,6 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
549 | 589 | ||
550 | hdmi.ip_data.ops->video_configure(&hdmi.ip_data); | 590 | hdmi.ip_data.ops->video_configure(&hdmi.ip_data); |
551 | 591 | ||
552 | /* Make selection of HDMI in DSS */ | ||
553 | dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); | ||
554 | |||
555 | /* Select the dispc clock source as PRCM clock, to ensure that it is not | ||
556 | * DSI PLL source as the clock selected by DSI PLL might not be | ||
557 | * sufficient for the resolution selected / that can be changed | ||
558 | * dynamically by user. This can be moved to single location , say | ||
559 | * Boardfile. | ||
560 | */ | ||
561 | dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); | ||
562 | |||
563 | /* bypass TV gamma table */ | 592 | /* bypass TV gamma table */ |
564 | dispc_enable_gamma_table(0); | 593 | dispc_enable_gamma_table(0); |
565 | 594 | ||
@@ -583,16 +612,11 @@ err_vid_enable: | |||
583 | err_phy_enable: | 612 | err_phy_enable: |
584 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); | 613 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); |
585 | err_pll_enable: | 614 | err_pll_enable: |
586 | hdmi_runtime_put(); | 615 | hdmi_power_off_core(dssdev); |
587 | err_runtime_get: | ||
588 | regulator_disable(hdmi.vdda_hdmi_dac_reg); | ||
589 | err_vdac_enable: | ||
590 | gpio_set_value(hdmi.ct_cp_hpd_gpio, 0); | ||
591 | gpio_set_value(hdmi.ls_oe_gpio, 0); | ||
592 | return -EIO; | 616 | return -EIO; |
593 | } | 617 | } |
594 | 618 | ||
595 | static void hdmi_power_off(struct omap_dss_device *dssdev) | 619 | static void hdmi_power_off_full(struct omap_dss_device *dssdev) |
596 | { | 620 | { |
597 | struct omap_overlay_manager *mgr = dssdev->output->manager; | 621 | struct omap_overlay_manager *mgr = dssdev->output->manager; |
598 | 622 | ||
@@ -601,12 +625,8 @@ static void hdmi_power_off(struct omap_dss_device *dssdev) | |||
601 | hdmi.ip_data.ops->video_disable(&hdmi.ip_data); | 625 | hdmi.ip_data.ops->video_disable(&hdmi.ip_data); |
602 | hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); | 626 | hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); |
603 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); | 627 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); |
604 | hdmi_runtime_put(); | ||
605 | |||
606 | regulator_disable(hdmi.vdda_hdmi_dac_reg); | ||
607 | 628 | ||
608 | gpio_set_value(hdmi.ct_cp_hpd_gpio, 0); | 629 | hdmi_power_off_core(dssdev); |
609 | gpio_set_value(hdmi.ls_oe_gpio, 0); | ||
610 | } | 630 | } |
611 | 631 | ||
612 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | 632 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, |
@@ -716,7 +736,7 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) | |||
716 | goto err0; | 736 | goto err0; |
717 | } | 737 | } |
718 | 738 | ||
719 | r = hdmi_power_on(dssdev); | 739 | r = hdmi_power_on_full(dssdev); |
720 | if (r) { | 740 | if (r) { |
721 | DSSERR("failed to power on device\n"); | 741 | DSSERR("failed to power on device\n"); |
722 | goto err1; | 742 | goto err1; |
@@ -738,13 +758,48 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev) | |||
738 | 758 | ||
739 | mutex_lock(&hdmi.lock); | 759 | mutex_lock(&hdmi.lock); |
740 | 760 | ||
741 | hdmi_power_off(dssdev); | 761 | hdmi_power_off_full(dssdev); |
742 | 762 | ||
743 | omap_dss_stop_device(dssdev); | 763 | omap_dss_stop_device(dssdev); |
744 | 764 | ||
745 | mutex_unlock(&hdmi.lock); | 765 | mutex_unlock(&hdmi.lock); |
746 | } | 766 | } |
747 | 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 | |||
748 | static int hdmi_get_clocks(struct platform_device *pdev) | 803 | static int hdmi_get_clocks(struct platform_device *pdev) |
749 | { | 804 | { |
750 | struct clk *clk; | 805 | struct clk *clk; |
@@ -913,7 +968,7 @@ int hdmi_audio_config(struct omap_dss_audio *audio) | |||
913 | 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) |
914 | { | 969 | { |
915 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | 970 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; |
916 | const char *def_disp_name = dss_get_default_display_name(); | 971 | const char *def_disp_name = omapdss_get_default_display_name(); |
917 | struct omap_dss_device *def_dssdev; | 972 | struct omap_dss_device *def_dssdev; |
918 | int i; | 973 | int i; |
919 | 974 | ||
@@ -971,9 +1026,19 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev) | |||
971 | return; | 1026 | return; |
972 | } | 1027 | } |
973 | 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 | |||
974 | r = dss_add_device(dssdev); | 1037 | r = dss_add_device(dssdev); |
975 | if (r) { | 1038 | if (r) { |
976 | 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); | ||
977 | dss_put_device(dssdev); | 1042 | dss_put_device(dssdev); |
978 | return; | 1043 | return; |
979 | } | 1044 | } |
@@ -1000,22 +1065,22 @@ static void __exit hdmi_uninit_output(struct platform_device *pdev) | |||
1000 | /* HDMI HW IP initialisation */ | 1065 | /* HDMI HW IP initialisation */ |
1001 | static int __init omapdss_hdmihw_probe(struct platform_device *pdev) | 1066 | static int __init omapdss_hdmihw_probe(struct platform_device *pdev) |
1002 | { | 1067 | { |
1003 | struct resource *hdmi_mem; | 1068 | struct resource *res; |
1004 | int r; | 1069 | int r; |
1005 | 1070 | ||
1006 | hdmi.pdev = pdev; | 1071 | hdmi.pdev = pdev; |
1007 | 1072 | ||
1008 | mutex_init(&hdmi.lock); | 1073 | mutex_init(&hdmi.lock); |
1074 | mutex_init(&hdmi.ip_data.lock); | ||
1009 | 1075 | ||
1010 | hdmi_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0); | 1076 | res = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0); |
1011 | if (!hdmi_mem) { | 1077 | if (!res) { |
1012 | DSSERR("can't get IORESOURCE_MEM HDMI\n"); | 1078 | DSSERR("can't get IORESOURCE_MEM HDMI\n"); |
1013 | return -EINVAL; | 1079 | return -EINVAL; |
1014 | } | 1080 | } |
1015 | 1081 | ||
1016 | /* Base address taken from platform */ | 1082 | /* Base address taken from platform */ |
1017 | hdmi.ip_data.base_wp = ioremap(hdmi_mem->start, | 1083 | hdmi.ip_data.base_wp = devm_request_and_ioremap(&pdev->dev, res); |
1018 | resource_size(hdmi_mem)); | ||
1019 | if (!hdmi.ip_data.base_wp) { | 1084 | if (!hdmi.ip_data.base_wp) { |
1020 | DSSERR("can't ioremap WP\n"); | 1085 | DSSERR("can't ioremap WP\n"); |
1021 | return -ENOMEM; | 1086 | return -ENOMEM; |
@@ -1023,7 +1088,7 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev) | |||
1023 | 1088 | ||
1024 | r = hdmi_get_clocks(pdev); | 1089 | r = hdmi_get_clocks(pdev); |
1025 | if (r) { | 1090 | if (r) { |
1026 | iounmap(hdmi.ip_data.base_wp); | 1091 | DSSERR("can't get clocks\n"); |
1027 | return r; | 1092 | return r; |
1028 | } | 1093 | } |
1029 | 1094 | ||
@@ -1034,9 +1099,11 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev) | |||
1034 | hdmi.ip_data.pll_offset = HDMI_PLLCTRL; | 1099 | hdmi.ip_data.pll_offset = HDMI_PLLCTRL; |
1035 | hdmi.ip_data.phy_offset = HDMI_PHY; | 1100 | hdmi.ip_data.phy_offset = HDMI_PHY; |
1036 | 1101 | ||
1037 | mutex_init(&hdmi.ip_data.lock); | 1102 | r = hdmi_panel_init(); |
1038 | 1103 | if (r) { | |
1039 | hdmi_panel_init(); | 1104 | DSSERR("can't init panel\n"); |
1105 | goto err_panel_init; | ||
1106 | } | ||
1040 | 1107 | ||
1041 | dss_debugfs_create_file("hdmi", hdmi_dump_regs); | 1108 | dss_debugfs_create_file("hdmi", hdmi_dump_regs); |
1042 | 1109 | ||
@@ -1045,6 +1112,10 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev) | |||
1045 | hdmi_probe_pdata(pdev); | 1112 | hdmi_probe_pdata(pdev); |
1046 | 1113 | ||
1047 | return 0; | 1114 | return 0; |
1115 | |||
1116 | err_panel_init: | ||
1117 | hdmi_put_clocks(); | ||
1118 | return r; | ||
1048 | } | 1119 | } |
1049 | 1120 | ||
1050 | static int __exit hdmi_remove_child(struct device *dev, void *data) | 1121 | static int __exit hdmi_remove_child(struct device *dev, void *data) |
@@ -1068,8 +1139,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) | |||
1068 | 1139 | ||
1069 | hdmi_put_clocks(); | 1140 | hdmi_put_clocks(); |
1070 | 1141 | ||
1071 | iounmap(hdmi.ip_data.base_wp); | ||
1072 | |||
1073 | return 0; | 1142 | return 0; |
1074 | } | 1143 | } |
1075 | 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 532a31b3d96b..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 <video/omapvrfb.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 bc225e46fdd2..ca585ef37f25 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c | |||
@@ -31,7 +31,6 @@ | |||
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/vram.h> | ||
35 | #include <video/omapvrfb.h> | 34 | #include <video/omapvrfb.h> |
36 | 35 | ||
37 | #include "omapfb.h" | 36 | #include "omapfb.h" |
@@ -1258,11 +1257,10 @@ static int omapfb_blank(int blank, struct fb_info *fbi) | |||
1258 | 1257 | ||
1259 | switch (blank) { | 1258 | switch (blank) { |
1260 | case FB_BLANK_UNBLANK: | 1259 | case FB_BLANK_UNBLANK: |
1261 | if (display->state != OMAP_DSS_DISPLAY_SUSPENDED) | 1260 | if (display->state == OMAP_DSS_DISPLAY_ACTIVE) |
1262 | goto exit; | 1261 | goto exit; |
1263 | 1262 | ||
1264 | if (display->driver->resume) | 1263 | r = display->driver->enable(display); |
1265 | r = display->driver->resume(display); | ||
1266 | 1264 | ||
1267 | if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) && | 1265 | if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) && |
1268 | d->update_mode == OMAPFB_AUTO_UPDATE && | 1266 | d->update_mode == OMAPFB_AUTO_UPDATE && |
@@ -1283,8 +1281,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi) | |||
1283 | if (d->auto_update_work_enabled) | 1281 | if (d->auto_update_work_enabled) |
1284 | omapfb_stop_auto_update(fbdev, display); | 1282 | omapfb_stop_auto_update(fbdev, display); |
1285 | 1283 | ||
1286 | if (display->driver->suspend) | 1284 | display->driver->disable(display); |
1287 | r = display->driver->suspend(display); | ||
1288 | 1285 | ||
1289 | break; | 1286 | break; |
1290 | 1287 | ||
@@ -1335,24 +1332,25 @@ static void omapfb_free_fbmem(struct fb_info *fbi) | |||
1335 | 1332 | ||
1336 | rg = ofbi->region; | 1333 | rg = ofbi->region; |
1337 | 1334 | ||
1338 | WARN_ON(atomic_read(&rg->map_count)); | 1335 | if (rg->token == NULL) |
1339 | 1336 | return; | |
1340 | if (rg->paddr) | ||
1341 | if (omap_vram_free(rg->paddr, rg->size)) | ||
1342 | dev_err(fbdev->dev, "VRAM FREE failed\n"); | ||
1343 | 1337 | ||
1344 | if (rg->vaddr) | 1338 | WARN_ON(atomic_read(&rg->map_count)); |
1345 | iounmap(rg->vaddr); | ||
1346 | 1339 | ||
1347 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { | 1340 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { |
1348 | /* unmap the 0 angle rotation */ | 1341 | /* unmap the 0 angle rotation */ |
1349 | if (rg->vrfb.vaddr[0]) { | 1342 | if (rg->vrfb.vaddr[0]) { |
1350 | iounmap(rg->vrfb.vaddr[0]); | 1343 | iounmap(rg->vrfb.vaddr[0]); |
1351 | omap_vrfb_release_ctx(&rg->vrfb); | ||
1352 | rg->vrfb.vaddr[0] = NULL; | 1344 | rg->vrfb.vaddr[0] = NULL; |
1353 | } | 1345 | } |
1346 | |||
1347 | omap_vrfb_release_ctx(&rg->vrfb); | ||
1354 | } | 1348 | } |
1355 | 1349 | ||
1350 | dma_free_attrs(fbdev->dev, rg->size, rg->token, rg->dma_handle, | ||
1351 | &rg->attrs); | ||
1352 | |||
1353 | rg->token = NULL; | ||
1356 | rg->vaddr = NULL; | 1354 | rg->vaddr = NULL; |
1357 | rg->paddr = 0; | 1355 | rg->paddr = 0; |
1358 | rg->alloc = 0; | 1356 | rg->alloc = 0; |
@@ -1387,7 +1385,9 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size, | |||
1387 | struct omapfb_info *ofbi = FB2OFB(fbi); | 1385 | struct omapfb_info *ofbi = FB2OFB(fbi); |
1388 | struct omapfb2_device *fbdev = ofbi->fbdev; | 1386 | struct omapfb2_device *fbdev = ofbi->fbdev; |
1389 | struct omapfb2_mem_region *rg; | 1387 | struct omapfb2_mem_region *rg; |
1390 | void __iomem *vaddr; | 1388 | void *token; |
1389 | DEFINE_DMA_ATTRS(attrs); | ||
1390 | dma_addr_t dma_handle; | ||
1391 | int r; | 1391 | int r; |
1392 | 1392 | ||
1393 | rg = ofbi->region; | 1393 | rg = ofbi->region; |
@@ -1402,42 +1402,40 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size, | |||
1402 | 1402 | ||
1403 | size = PAGE_ALIGN(size); | 1403 | size = PAGE_ALIGN(size); |
1404 | 1404 | ||
1405 | if (!paddr) { | 1405 | dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); |
1406 | DBG("allocating %lu bytes for fb %d\n", size, ofbi->id); | ||
1407 | r = omap_vram_alloc(size, &paddr); | ||
1408 | } else { | ||
1409 | DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr, | ||
1410 | ofbi->id); | ||
1411 | r = omap_vram_reserve(paddr, size); | ||
1412 | } | ||
1413 | 1406 | ||
1414 | 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) { | ||
1415 | dev_err(fbdev->dev, "failed to allocate framebuffer\n"); | 1416 | dev_err(fbdev->dev, "failed to allocate framebuffer\n"); |
1416 | return -ENOMEM; | 1417 | return -ENOMEM; |
1417 | } | 1418 | } |
1418 | 1419 | ||
1419 | if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) { | 1420 | DBG("allocated VRAM paddr %lx, vaddr %p\n", |
1420 | vaddr = ioremap_wc(paddr, size); | 1421 | (unsigned long)dma_handle, token); |
1421 | |||
1422 | if (!vaddr) { | ||
1423 | dev_err(fbdev->dev, "failed to ioremap framebuffer\n"); | ||
1424 | omap_vram_free(paddr, size); | ||
1425 | return -ENOMEM; | ||
1426 | } | ||
1427 | 1422 | ||
1428 | DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr); | 1423 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { |
1429 | } else { | ||
1430 | r = omap_vrfb_request_ctx(&rg->vrfb); | 1424 | r = omap_vrfb_request_ctx(&rg->vrfb); |
1431 | if (r) { | 1425 | if (r) { |
1426 | dma_free_attrs(fbdev->dev, size, token, dma_handle, | ||
1427 | &attrs); | ||
1432 | dev_err(fbdev->dev, "vrfb create ctx failed\n"); | 1428 | dev_err(fbdev->dev, "vrfb create ctx failed\n"); |
1433 | return r; | 1429 | return r; |
1434 | } | 1430 | } |
1435 | |||
1436 | vaddr = NULL; | ||
1437 | } | 1431 | } |
1438 | 1432 | ||
1439 | rg->paddr = paddr; | 1433 | rg->attrs = attrs; |
1440 | 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; | ||
1441 | rg->size = size; | 1439 | rg->size = size; |
1442 | rg->alloc = 1; | 1440 | rg->alloc = 1; |
1443 | 1441 | ||
@@ -1531,6 +1529,9 @@ static int omapfb_parse_vram_param(const char *param, int max_entries, | |||
1531 | 1529 | ||
1532 | } | 1530 | } |
1533 | 1531 | ||
1532 | WARN_ONCE(paddr, | ||
1533 | "reserving memory at predefined address not supported\n"); | ||
1534 | |||
1534 | paddrs[fbnum] = paddr; | 1535 | paddrs[fbnum] = paddr; |
1535 | sizes[fbnum] = size; | 1536 | sizes[fbnum] = size; |
1536 | 1537 | ||
@@ -1610,7 +1611,6 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type) | |||
1610 | { | 1611 | { |
1611 | struct omapfb_info *ofbi = FB2OFB(fbi); | 1612 | struct omapfb_info *ofbi = FB2OFB(fbi); |
1612 | struct omapfb2_device *fbdev = ofbi->fbdev; | 1613 | struct omapfb2_device *fbdev = ofbi->fbdev; |
1613 | struct omap_dss_device *display = fb2display(fbi); | ||
1614 | struct omapfb2_mem_region *rg = ofbi->region; | 1614 | struct omapfb2_mem_region *rg = ofbi->region; |
1615 | unsigned long old_size = rg->size; | 1615 | unsigned long old_size = rg->size; |
1616 | unsigned long old_paddr = rg->paddr; | 1616 | unsigned long old_paddr = rg->paddr; |
@@ -1625,9 +1625,6 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type) | |||
1625 | if (old_size == size && old_type == type) | 1625 | if (old_size == size && old_type == type) |
1626 | return 0; | 1626 | return 0; |
1627 | 1627 | ||
1628 | if (display && display->driver->sync) | ||
1629 | display->driver->sync(display); | ||
1630 | |||
1631 | omapfb_free_fbmem(fbi); | 1628 | omapfb_free_fbmem(fbi); |
1632 | 1629 | ||
1633 | if (size == 0) { | 1630 | if (size == 0) { |
@@ -1882,7 +1879,6 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev) | |||
1882 | } | 1879 | } |
1883 | 1880 | ||
1884 | dev_set_drvdata(fbdev->dev, NULL); | 1881 | dev_set_drvdata(fbdev->dev, NULL); |
1885 | kfree(fbdev); | ||
1886 | } | 1882 | } |
1887 | 1883 | ||
1888 | static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) | 1884 | static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) |
@@ -2258,26 +2254,28 @@ static int omapfb_find_best_mode(struct omap_dss_device *display, | |||
2258 | { | 2254 | { |
2259 | struct fb_monspecs *specs; | 2255 | struct fb_monspecs *specs; |
2260 | u8 *edid; | 2256 | u8 *edid; |
2261 | int r, i, best_xres, best_idx, len; | 2257 | int r, i, best_idx, len; |
2262 | 2258 | ||
2263 | if (!display->driver->read_edid) | 2259 | if (!display->driver->read_edid) |
2264 | return -ENODEV; | 2260 | return -ENODEV; |
2265 | 2261 | ||
2266 | len = 0x80 * 2; | 2262 | len = 0x80 * 2; |
2267 | edid = kmalloc(len, GFP_KERNEL); | 2263 | edid = kmalloc(len, GFP_KERNEL); |
2264 | if (edid == NULL) | ||
2265 | return -ENOMEM; | ||
2268 | 2266 | ||
2269 | r = display->driver->read_edid(display, edid, len); | 2267 | r = display->driver->read_edid(display, edid, len); |
2270 | if (r < 0) | 2268 | if (r < 0) |
2271 | goto err1; | 2269 | goto err1; |
2272 | 2270 | ||
2273 | specs = kzalloc(sizeof(*specs), GFP_KERNEL); | 2271 | specs = kzalloc(sizeof(*specs), GFP_KERNEL); |
2272 | if (specs == NULL) { | ||
2273 | r = -ENOMEM; | ||
2274 | goto err1; | ||
2275 | } | ||
2274 | 2276 | ||
2275 | fb_edid_to_monspecs(edid, specs); | 2277 | fb_edid_to_monspecs(edid, specs); |
2276 | 2278 | ||
2277 | if (edid[126] > 0) | ||
2278 | fb_edid_add_monspecs(edid + 0x80, specs); | ||
2279 | |||
2280 | best_xres = 0; | ||
2281 | best_idx = -1; | 2279 | best_idx = -1; |
2282 | 2280 | ||
2283 | for (i = 0; i < specs->modedb_len; ++i) { | 2281 | for (i = 0; i < specs->modedb_len; ++i) { |
@@ -2293,16 +2291,20 @@ static int omapfb_find_best_mode(struct omap_dss_device *display, | |||
2293 | if (m->xres == 2880 || m->xres == 1440) | 2291 | if (m->xres == 2880 || m->xres == 1440) |
2294 | continue; | 2292 | continue; |
2295 | 2293 | ||
2294 | if (m->vmode & FB_VMODE_INTERLACED || | ||
2295 | m->vmode & FB_VMODE_DOUBLE) | ||
2296 | continue; | ||
2297 | |||
2296 | fb_videomode_to_omap_timings(m, display, &t); | 2298 | fb_videomode_to_omap_timings(m, display, &t); |
2297 | 2299 | ||
2298 | r = display->driver->check_timings(display, &t); | 2300 | r = display->driver->check_timings(display, &t); |
2299 | if (r == 0 && best_xres < m->xres) { | 2301 | if (r == 0) { |
2300 | best_xres = m->xres; | ||
2301 | best_idx = i; | 2302 | best_idx = i; |
2303 | break; | ||
2302 | } | 2304 | } |
2303 | } | 2305 | } |
2304 | 2306 | ||
2305 | if (best_xres == 0) { | 2307 | if (best_idx == -1) { |
2306 | r = -ENOENT; | 2308 | r = -ENOENT; |
2307 | goto err2; | 2309 | goto err2; |
2308 | } | 2310 | } |
@@ -2371,15 +2373,62 @@ static int omapfb_init_display(struct omapfb2_device *fbdev, | |||
2371 | return 0; | 2373 | return 0; |
2372 | } | 2374 | } |
2373 | 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 | |||
2374 | static int __init omapfb_probe(struct platform_device *pdev) | 2425 | static int __init omapfb_probe(struct platform_device *pdev) |
2375 | { | 2426 | { |
2376 | struct omapfb2_device *fbdev = NULL; | 2427 | struct omapfb2_device *fbdev = NULL; |
2377 | int r = 0; | 2428 | int r = 0; |
2378 | int i; | 2429 | int i; |
2379 | struct omap_overlay *ovl; | ||
2380 | struct omap_dss_device *def_display; | 2430 | struct omap_dss_device *def_display; |
2381 | struct omap_dss_device *dssdev; | 2431 | struct omap_dss_device *dssdev; |
2382 | struct omap_dss_device *ovl_device; | ||
2383 | 2432 | ||
2384 | DBG("omapfb_probe\n"); | 2433 | DBG("omapfb_probe\n"); |
2385 | 2434 | ||
@@ -2389,7 +2438,8 @@ static int __init omapfb_probe(struct platform_device *pdev) | |||
2389 | goto err0; | 2438 | goto err0; |
2390 | } | 2439 | } |
2391 | 2440 | ||
2392 | fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL); | 2441 | fbdev = devm_kzalloc(&pdev->dev, sizeof(struct omapfb2_device), |
2442 | GFP_KERNEL); | ||
2393 | if (fbdev == NULL) { | 2443 | if (fbdev == NULL) { |
2394 | r = -ENOMEM; | 2444 | r = -ENOMEM; |
2395 | goto err0; | 2445 | goto err0; |
@@ -2401,13 +2451,15 @@ static int __init omapfb_probe(struct platform_device *pdev) | |||
2401 | "ignoring the module parameter vrfb=y\n"); | 2451 | "ignoring the module parameter vrfb=y\n"); |
2402 | } | 2452 | } |
2403 | 2453 | ||
2454 | r = omapdss_compat_init(); | ||
2455 | if (r) | ||
2456 | goto err0; | ||
2404 | 2457 | ||
2405 | mutex_init(&fbdev->mtx); | 2458 | mutex_init(&fbdev->mtx); |
2406 | 2459 | ||
2407 | fbdev->dev = &pdev->dev; | 2460 | fbdev->dev = &pdev->dev; |
2408 | platform_set_drvdata(pdev, fbdev); | 2461 | platform_set_drvdata(pdev, fbdev); |
2409 | 2462 | ||
2410 | r = 0; | ||
2411 | fbdev->num_displays = 0; | 2463 | fbdev->num_displays = 0; |
2412 | dssdev = NULL; | 2464 | dssdev = NULL; |
2413 | for_each_dss_dev(dssdev) { | 2465 | for_each_dss_dev(dssdev) { |
@@ -2430,9 +2482,6 @@ static int __init omapfb_probe(struct platform_device *pdev) | |||
2430 | d->update_mode = OMAPFB_AUTO_UPDATE; | 2482 | d->update_mode = OMAPFB_AUTO_UPDATE; |
2431 | } | 2483 | } |
2432 | 2484 | ||
2433 | if (r) | ||
2434 | goto cleanup; | ||
2435 | |||
2436 | if (fbdev->num_displays == 0) { | 2485 | if (fbdev->num_displays == 0) { |
2437 | dev_err(&pdev->dev, "no displays\n"); | 2486 | dev_err(&pdev->dev, "no displays\n"); |
2438 | r = -EINVAL; | 2487 | r = -EINVAL; |
@@ -2447,15 +2496,33 @@ static int __init omapfb_probe(struct platform_device *pdev) | |||
2447 | for (i = 0; i < fbdev->num_managers; i++) | 2496 | for (i = 0; i < fbdev->num_managers; i++) |
2448 | fbdev->managers[i] = omap_dss_get_overlay_manager(i); | 2497 | fbdev->managers[i] = omap_dss_get_overlay_manager(i); |
2449 | 2498 | ||
2450 | /* gfx overlay should be the default one. find a display | 2499 | def_display = NULL; |
2451 | * connected to that, and use it as default display */ | 2500 | |
2452 | ovl = omap_dss_get_overlay(0); | 2501 | for (i = 0; i < fbdev->num_displays; ++i) { |
2453 | ovl_device = ovl->get_device(ovl); | 2502 | struct omap_dss_device *dssdev; |
2454 | if (ovl_device) { | 2503 | const char *def_name; |
2455 | def_display = ovl_device; | 2504 | |
2456 | } else { | 2505 | def_name = omapdss_get_default_display_name(); |
2457 | dev_warn(&pdev->dev, "cannot find default display\n"); | 2506 | |
2458 | 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; | ||
2459 | } | 2526 | } |
2460 | 2527 | ||
2461 | if (def_mode && strlen(def_mode) > 0) { | 2528 | if (def_mode && strlen(def_mode) > 0) { |
@@ -2506,6 +2573,7 @@ static int __init omapfb_probe(struct platform_device *pdev) | |||
2506 | 2573 | ||
2507 | cleanup: | 2574 | cleanup: |
2508 | omapfb_free_resources(fbdev); | 2575 | omapfb_free_resources(fbdev); |
2576 | omapdss_compat_uninit(); | ||
2509 | err0: | 2577 | err0: |
2510 | dev_err(&pdev->dev, "failed to setup omapfb\n"); | 2578 | dev_err(&pdev->dev, "failed to setup omapfb\n"); |
2511 | return r; | 2579 | return r; |
@@ -2521,6 +2589,8 @@ static int __exit omapfb_remove(struct platform_device *pdev) | |||
2521 | 2589 | ||
2522 | omapfb_free_resources(fbdev); | 2590 | omapfb_free_resources(fbdev); |
2523 | 2591 | ||
2592 | omapdss_compat_uninit(); | ||
2593 | |||
2524 | return 0; | 2594 | return 0; |
2525 | } | 2595 | } |
2526 | 2596 | ||
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c index 17aa174e187c..18fa9e1d0033 100644 --- a/drivers/video/omap2/omapfb/omapfb-sysfs.c +++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c | |||
@@ -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/s3c-fb.c b/drivers/video/s3c-fb.c index 2ed7b633bbd9..1a00ad241edd 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c | |||
@@ -189,7 +189,7 @@ struct s3c_fb_vsync { | |||
189 | 189 | ||
190 | /** | 190 | /** |
191 | * struct s3c_fb - overall hardware state of the hardware | 191 | * struct s3c_fb - overall hardware state of the hardware |
192 | * @slock: The spinlock protection for this data sturucture. | 192 | * @slock: The spinlock protection for this data structure. |
193 | * @dev: The device that we bound to, for printing, etc. | 193 | * @dev: The device that we bound to, for printing, etc. |
194 | * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. | 194 | * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. |
195 | * @lcd_clk: The clk (sclk) feeding pixclk. | 195 | * @lcd_clk: The clk (sclk) feeding pixclk. |
@@ -268,10 +268,10 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, | |||
268 | case 8: | 268 | case 8: |
269 | if (sfb->variant.palette[win->index] != 0) { | 269 | if (sfb->variant.palette[win->index] != 0) { |
270 | /* non palletised, A:1,R:2,G:3,B:2 mode */ | 270 | /* non palletised, A:1,R:2,G:3,B:2 mode */ |
271 | var->red.offset = 4; | 271 | var->red.offset = 5; |
272 | var->green.offset = 2; | 272 | var->green.offset = 2; |
273 | var->blue.offset = 0; | 273 | var->blue.offset = 0; |
274 | var->red.length = 5; | 274 | var->red.length = 2; |
275 | var->green.length = 3; | 275 | var->green.length = 3; |
276 | var->blue.length = 2; | 276 | var->blue.length = 2; |
277 | var->transp.offset = 7; | 277 | var->transp.offset = 7; |
@@ -288,6 +288,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, | |||
288 | /* 666 with one bit alpha/transparency */ | 288 | /* 666 with one bit alpha/transparency */ |
289 | var->transp.offset = 18; | 289 | var->transp.offset = 18; |
290 | var->transp.length = 1; | 290 | var->transp.length = 1; |
291 | /* drop through */ | ||
291 | case 18: | 292 | case 18: |
292 | var->bits_per_pixel = 32; | 293 | var->bits_per_pixel = 32; |
293 | 294 | ||
@@ -329,6 +330,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, | |||
329 | 330 | ||
330 | default: | 331 | default: |
331 | dev_err(sfb->dev, "invalid bpp\n"); | 332 | dev_err(sfb->dev, "invalid bpp\n"); |
333 | return -EINVAL; | ||
332 | } | 334 | } |
333 | 335 | ||
334 | dev_dbg(sfb->dev, "%s: verified parameters\n", __func__); | 336 | dev_dbg(sfb->dev, "%s: verified parameters\n", __func__); |
@@ -1544,8 +1546,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev) | |||
1544 | #ifdef CONFIG_PM_SLEEP | 1546 | #ifdef CONFIG_PM_SLEEP |
1545 | static int s3c_fb_suspend(struct device *dev) | 1547 | static int s3c_fb_suspend(struct device *dev) |
1546 | { | 1548 | { |
1547 | struct platform_device *pdev = to_platform_device(dev); | 1549 | struct s3c_fb *sfb = dev_get_drvdata(dev); |
1548 | struct s3c_fb *sfb = platform_get_drvdata(pdev); | ||
1549 | struct s3c_fb_win *win; | 1550 | struct s3c_fb_win *win; |
1550 | int win_no; | 1551 | int win_no; |
1551 | 1552 | ||
@@ -1572,8 +1573,7 @@ static int s3c_fb_suspend(struct device *dev) | |||
1572 | 1573 | ||
1573 | static int s3c_fb_resume(struct device *dev) | 1574 | static int s3c_fb_resume(struct device *dev) |
1574 | { | 1575 | { |
1575 | struct platform_device *pdev = to_platform_device(dev); | 1576 | struct s3c_fb *sfb = dev_get_drvdata(dev); |
1576 | struct s3c_fb *sfb = platform_get_drvdata(pdev); | ||
1577 | struct s3c_fb_platdata *pd = sfb->pdata; | 1577 | struct s3c_fb_platdata *pd = sfb->pdata; |
1578 | struct s3c_fb_win *win; | 1578 | struct s3c_fb_win *win; |
1579 | int win_no; | 1579 | int win_no; |
@@ -1623,7 +1623,7 @@ static int s3c_fb_resume(struct device *dev) | |||
1623 | if (!win) | 1623 | if (!win) |
1624 | continue; | 1624 | continue; |
1625 | 1625 | ||
1626 | dev_dbg(&pdev->dev, "resuming window %d\n", win_no); | 1626 | dev_dbg(dev, "resuming window %d\n", win_no); |
1627 | s3c_fb_set_par(win->fbinfo); | 1627 | s3c_fb_set_par(win->fbinfo); |
1628 | } | 1628 | } |
1629 | 1629 | ||
@@ -1636,8 +1636,7 @@ static int s3c_fb_resume(struct device *dev) | |||
1636 | #ifdef CONFIG_PM_RUNTIME | 1636 | #ifdef CONFIG_PM_RUNTIME |
1637 | static int s3c_fb_runtime_suspend(struct device *dev) | 1637 | static int s3c_fb_runtime_suspend(struct device *dev) |
1638 | { | 1638 | { |
1639 | struct platform_device *pdev = to_platform_device(dev); | 1639 | struct s3c_fb *sfb = dev_get_drvdata(dev); |
1640 | struct s3c_fb *sfb = platform_get_drvdata(pdev); | ||
1641 | 1640 | ||
1642 | if (!sfb->variant.has_clksel) | 1641 | if (!sfb->variant.has_clksel) |
1643 | clk_disable_unprepare(sfb->lcd_clk); | 1642 | clk_disable_unprepare(sfb->lcd_clk); |
@@ -1649,8 +1648,7 @@ static int s3c_fb_runtime_suspend(struct device *dev) | |||
1649 | 1648 | ||
1650 | static int s3c_fb_runtime_resume(struct device *dev) | 1649 | static int s3c_fb_runtime_resume(struct device *dev) |
1651 | { | 1650 | { |
1652 | struct platform_device *pdev = to_platform_device(dev); | 1651 | struct s3c_fb *sfb = dev_get_drvdata(dev); |
1653 | struct s3c_fb *sfb = platform_get_drvdata(pdev); | ||
1654 | struct s3c_fb_platdata *pd = sfb->pdata; | 1652 | struct s3c_fb_platdata *pd = sfb->pdata; |
1655 | 1653 | ||
1656 | clk_prepare_enable(sfb->bus_clk); | 1654 | clk_prepare_enable(sfb->bus_clk); |
@@ -1910,7 +1908,7 @@ static struct s3c_fb_driverdata s3c_fb_data_exynos4 = { | |||
1910 | static struct s3c_fb_driverdata s3c_fb_data_exynos5 = { | 1908 | static struct s3c_fb_driverdata s3c_fb_data_exynos5 = { |
1911 | .variant = { | 1909 | .variant = { |
1912 | .nr_windows = 5, | 1910 | .nr_windows = 5, |
1913 | .vidtcon = VIDTCON0, | 1911 | .vidtcon = FIMD_V8_VIDTCON0, |
1914 | .wincon = WINCON(0), | 1912 | .wincon = WINCON(0), |
1915 | .winmap = WINxMAP(0), | 1913 | .winmap = WINxMAP(0), |
1916 | .keycon = WKEYCON, | 1914 | .keycon = WKEYCON, |
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index 3951fdae5f68..f4962292792c 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c | |||
@@ -127,13 +127,12 @@ static void sh_mipi_shutdown(struct platform_device *pdev) | |||
127 | sh_mipi_dsi_enable(mipi, false); | 127 | sh_mipi_dsi_enable(mipi, false); |
128 | } | 128 | } |
129 | 129 | ||
130 | static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata) | 130 | static int sh_mipi_setup(struct sh_mipi *mipi, const struct fb_videomode *mode) |
131 | { | 131 | { |
132 | void __iomem *base = mipi->base; | 132 | void __iomem *base = mipi->base; |
133 | struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan; | 133 | struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data; |
134 | u32 pctype, datatype, pixfmt, linelength, vmctr2; | 134 | u32 pctype, datatype, pixfmt, linelength, vmctr2; |
135 | u32 tmp, top, bottom, delay, div; | 135 | u32 tmp, top, bottom, delay, div; |
136 | bool yuv; | ||
137 | int bpp; | 136 | int bpp; |
138 | 137 | ||
139 | /* | 138 | /* |
@@ -146,95 +145,79 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata) | |||
146 | pctype = 0; | 145 | pctype = 0; |
147 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; | 146 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; |
148 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | 147 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; |
149 | linelength = ch->lcd_modes[0].xres * 3; | 148 | linelength = mode->xres * 3; |
150 | yuv = false; | ||
151 | break; | 149 | break; |
152 | case MIPI_RGB565: | 150 | case MIPI_RGB565: |
153 | pctype = 1; | 151 | pctype = 1; |
154 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; | 152 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; |
155 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | 153 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; |
156 | linelength = ch->lcd_modes[0].xres * 2; | 154 | linelength = mode->xres * 2; |
157 | yuv = false; | ||
158 | break; | 155 | break; |
159 | case MIPI_RGB666_LP: | 156 | case MIPI_RGB666_LP: |
160 | pctype = 2; | 157 | pctype = 2; |
161 | datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; | 158 | datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; |
162 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | 159 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; |
163 | linelength = ch->lcd_modes[0].xres * 3; | 160 | linelength = mode->xres * 3; |
164 | yuv = false; | ||
165 | break; | 161 | break; |
166 | case MIPI_RGB666: | 162 | case MIPI_RGB666: |
167 | pctype = 3; | 163 | pctype = 3; |
168 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; | 164 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; |
169 | pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; | 165 | pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; |
170 | linelength = (ch->lcd_modes[0].xres * 18 + 7) / 8; | 166 | linelength = (mode->xres * 18 + 7) / 8; |
171 | yuv = false; | ||
172 | break; | 167 | break; |
173 | case MIPI_BGR888: | 168 | case MIPI_BGR888: |
174 | pctype = 8; | 169 | pctype = 8; |
175 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; | 170 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; |
176 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | 171 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; |
177 | linelength = ch->lcd_modes[0].xres * 3; | 172 | linelength = mode->xres * 3; |
178 | yuv = false; | ||
179 | break; | 173 | break; |
180 | case MIPI_BGR565: | 174 | case MIPI_BGR565: |
181 | pctype = 9; | 175 | pctype = 9; |
182 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; | 176 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; |
183 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | 177 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; |
184 | linelength = ch->lcd_modes[0].xres * 2; | 178 | linelength = mode->xres * 2; |
185 | yuv = false; | ||
186 | break; | 179 | break; |
187 | case MIPI_BGR666_LP: | 180 | case MIPI_BGR666_LP: |
188 | pctype = 0xa; | 181 | pctype = 0xa; |
189 | datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; | 182 | datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; |
190 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | 183 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; |
191 | linelength = ch->lcd_modes[0].xres * 3; | 184 | linelength = mode->xres * 3; |
192 | yuv = false; | ||
193 | break; | 185 | break; |
194 | case MIPI_BGR666: | 186 | case MIPI_BGR666: |
195 | pctype = 0xb; | 187 | pctype = 0xb; |
196 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; | 188 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; |
197 | pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; | 189 | pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; |
198 | linelength = (ch->lcd_modes[0].xres * 18 + 7) / 8; | 190 | linelength = (mode->xres * 18 + 7) / 8; |
199 | yuv = false; | ||
200 | break; | 191 | break; |
201 | case MIPI_YUYV: | 192 | case MIPI_YUYV: |
202 | pctype = 4; | 193 | pctype = 4; |
203 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; | 194 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; |
204 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | 195 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; |
205 | linelength = ch->lcd_modes[0].xres * 2; | 196 | linelength = mode->xres * 2; |
206 | yuv = true; | ||
207 | break; | 197 | break; |
208 | case MIPI_UYVY: | 198 | case MIPI_UYVY: |
209 | pctype = 5; | 199 | pctype = 5; |
210 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; | 200 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; |
211 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | 201 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; |
212 | linelength = ch->lcd_modes[0].xres * 2; | 202 | linelength = mode->xres * 2; |
213 | yuv = true; | ||
214 | break; | 203 | break; |
215 | case MIPI_YUV420_L: | 204 | case MIPI_YUV420_L: |
216 | pctype = 6; | 205 | pctype = 6; |
217 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; | 206 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; |
218 | pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; | 207 | pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; |
219 | linelength = (ch->lcd_modes[0].xres * 12 + 7) / 8; | 208 | linelength = (mode->xres * 12 + 7) / 8; |
220 | yuv = true; | ||
221 | break; | 209 | break; |
222 | case MIPI_YUV420: | 210 | case MIPI_YUV420: |
223 | pctype = 7; | 211 | pctype = 7; |
224 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; | 212 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; |
225 | pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; | 213 | pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; |
226 | /* Length of U/V line */ | 214 | /* Length of U/V line */ |
227 | linelength = (ch->lcd_modes[0].xres + 1) / 2; | 215 | linelength = (mode->xres + 1) / 2; |
228 | yuv = true; | ||
229 | break; | 216 | break; |
230 | default: | 217 | default: |
231 | return -EINVAL; | 218 | return -EINVAL; |
232 | } | 219 | } |
233 | 220 | ||
234 | if ((yuv && ch->interface_type != YUV422) || | ||
235 | (!yuv && ch->interface_type != RGB24)) | ||
236 | return -EINVAL; | ||
237 | |||
238 | if (!pdata->lane) | 221 | if (!pdata->lane) |
239 | return -EINVAL; | 222 | return -EINVAL; |
240 | 223 | ||
@@ -293,7 +276,7 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata) | |||
293 | */ | 276 | */ |
294 | iowrite32(0x00000006, mipi->linkbase + DTCTR); | 277 | iowrite32(0x00000006, mipi->linkbase + DTCTR); |
295 | /* VSYNC width = 2 (<< 17) */ | 278 | /* VSYNC width = 2 (<< 17) */ |
296 | iowrite32((ch->lcd_modes[0].vsync_len << pdata->vsynw_offset) | | 279 | iowrite32((mode->vsync_len << pdata->vsynw_offset) | |
297 | (pdata->clksrc << 16) | (pctype << 12) | datatype, | 280 | (pdata->clksrc << 16) | (pctype << 12) | datatype, |
298 | mipi->linkbase + VMCTR1); | 281 | mipi->linkbase + VMCTR1); |
299 | 282 | ||
@@ -327,7 +310,7 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata) | |||
327 | top = linelength << 16; /* RGBLEN */ | 310 | top = linelength << 16; /* RGBLEN */ |
328 | bottom = 0x00000001; | 311 | bottom = 0x00000001; |
329 | if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */ | 312 | if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */ |
330 | bottom = (pdata->lane * ch->lcd_modes[0].hsync_len) - 10; | 313 | bottom = (pdata->lane * mode->hsync_len) - 10; |
331 | iowrite32(top | bottom , mipi->linkbase + VMLEN1); | 314 | iowrite32(top | bottom , mipi->linkbase + VMLEN1); |
332 | 315 | ||
333 | /* | 316 | /* |
@@ -347,18 +330,18 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata) | |||
347 | div = 2; | 330 | div = 2; |
348 | 331 | ||
349 | if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */ | 332 | if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */ |
350 | top = ch->lcd_modes[0].hsync_len + ch->lcd_modes[0].left_margin; | 333 | top = mode->hsync_len + mode->left_margin; |
351 | top = ((pdata->lane * top / div) - 10) << 16; | 334 | top = ((pdata->lane * top / div) - 10) << 16; |
352 | } | 335 | } |
353 | if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */ | 336 | if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */ |
354 | bottom = ch->lcd_modes[0].right_margin; | 337 | bottom = mode->right_margin; |
355 | bottom = (pdata->lane * bottom / div) - 12; | 338 | bottom = (pdata->lane * bottom / div) - 12; |
356 | } | 339 | } |
357 | 340 | ||
358 | bpp = linelength / ch->lcd_modes[0].xres; /* byte / pixel */ | 341 | bpp = linelength / mode->xres; /* byte / pixel */ |
359 | if ((pdata->lane / div) > bpp) { | 342 | if ((pdata->lane / div) > bpp) { |
360 | tmp = ch->lcd_modes[0].xres / bpp; /* output cycle */ | 343 | tmp = mode->xres / bpp; /* output cycle */ |
361 | tmp = ch->lcd_modes[0].xres - tmp; /* (input - output) cycle */ | 344 | tmp = mode->xres - tmp; /* (input - output) cycle */ |
362 | delay = (pdata->lane * tmp); | 345 | delay = (pdata->lane * tmp); |
363 | } | 346 | } |
364 | 347 | ||
@@ -369,7 +352,7 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata) | |||
369 | /* setup LCD panel */ | 352 | /* setup LCD panel */ |
370 | 353 | ||
371 | /* cf. drivers/video/omap/lcd_mipid.c */ | 354 | /* cf. drivers/video/omap/lcd_mipid.c */ |
372 | sh_mipi_dcs(ch->chan, MIPI_DCS_EXIT_SLEEP_MODE); | 355 | sh_mipi_dcs(pdata->channel, MIPI_DCS_EXIT_SLEEP_MODE); |
373 | msleep(120); | 356 | msleep(120); |
374 | /* | 357 | /* |
375 | * [7] - Page Address Mode | 358 | * [7] - Page Address Mode |
@@ -381,11 +364,11 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata) | |||
381 | * [1] - Flip Horizontal | 364 | * [1] - Flip Horizontal |
382 | * [0] - Flip Vertical | 365 | * [0] - Flip Vertical |
383 | */ | 366 | */ |
384 | sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_ADDRESS_MODE, 0x00); | 367 | sh_mipi_dcs_param(pdata->channel, MIPI_DCS_SET_ADDRESS_MODE, 0x00); |
385 | /* cf. set_data_lines() */ | 368 | /* cf. set_data_lines() */ |
386 | sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_PIXEL_FORMAT, | 369 | sh_mipi_dcs_param(pdata->channel, MIPI_DCS_SET_PIXEL_FORMAT, |
387 | pixfmt << 4); | 370 | pixfmt << 4); |
388 | sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON); | 371 | sh_mipi_dcs(pdata->channel, MIPI_DCS_SET_DISPLAY_ON); |
389 | 372 | ||
390 | /* Enable timeout counters */ | 373 | /* Enable timeout counters */ |
391 | iowrite32(0x00000f00, base + DSICTRL); | 374 | iowrite32(0x00000f00, base + DSICTRL); |
@@ -405,7 +388,7 @@ static int mipi_display_on(struct sh_mobile_lcdc_entity *entity) | |||
405 | if (ret < 0) | 388 | if (ret < 0) |
406 | goto mipi_display_on_fail1; | 389 | goto mipi_display_on_fail1; |
407 | 390 | ||
408 | ret = sh_mipi_setup(mipi, pdata); | 391 | ret = sh_mipi_setup(mipi, &entity->def_mode); |
409 | if (ret < 0) | 392 | if (ret < 0) |
410 | goto mipi_display_on_fail2; | 393 | goto mipi_display_on_fail2; |
411 | 394 | ||
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 699487c287b2..e78fe4bc1524 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c | |||
@@ -438,7 +438,7 @@ static unsigned long lcdc_sys_read_data(void *handle) | |||
438 | return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK; | 438 | return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK; |
439 | } | 439 | } |
440 | 440 | ||
441 | struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { | 441 | static struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { |
442 | lcdc_sys_write_index, | 442 | lcdc_sys_write_index, |
443 | lcdc_sys_write_data, | 443 | lcdc_sys_write_data, |
444 | lcdc_sys_read_data, | 444 | lcdc_sys_read_data, |
@@ -586,8 +586,8 @@ static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch, | |||
586 | * Just turn on, if we run a resume here, the | 586 | * Just turn on, if we run a resume here, the |
587 | * logo disappears. | 587 | * logo disappears. |
588 | */ | 588 | */ |
589 | info->var.width = monspec->max_x * 10; | 589 | info->var.width = ch->display.width; |
590 | info->var.height = monspec->max_y * 10; | 590 | info->var.height = ch->display.height; |
591 | sh_mobile_lcdc_display_on(ch); | 591 | sh_mobile_lcdc_display_on(ch); |
592 | } else { | 592 | } else { |
593 | /* New monitor or have to wake up */ | 593 | /* New monitor or have to wake up */ |
@@ -1614,6 +1614,15 @@ static int sh_mobile_lcdc_overlay_blank(int blank, struct fb_info *info) | |||
1614 | return 1; | 1614 | return 1; |
1615 | } | 1615 | } |
1616 | 1616 | ||
1617 | static int | ||
1618 | sh_mobile_lcdc_overlay_mmap(struct fb_info *info, struct vm_area_struct *vma) | ||
1619 | { | ||
1620 | struct sh_mobile_lcdc_overlay *ovl = info->par; | ||
1621 | |||
1622 | return dma_mmap_coherent(ovl->channel->lcdc->dev, vma, ovl->fb_mem, | ||
1623 | ovl->dma_handle, ovl->fb_size); | ||
1624 | } | ||
1625 | |||
1617 | static struct fb_ops sh_mobile_lcdc_overlay_ops = { | 1626 | static struct fb_ops sh_mobile_lcdc_overlay_ops = { |
1618 | .owner = THIS_MODULE, | 1627 | .owner = THIS_MODULE, |
1619 | .fb_read = fb_sys_read, | 1628 | .fb_read = fb_sys_read, |
@@ -1626,6 +1635,7 @@ static struct fb_ops sh_mobile_lcdc_overlay_ops = { | |||
1626 | .fb_ioctl = sh_mobile_lcdc_overlay_ioctl, | 1635 | .fb_ioctl = sh_mobile_lcdc_overlay_ioctl, |
1627 | .fb_check_var = sh_mobile_lcdc_overlay_check_var, | 1636 | .fb_check_var = sh_mobile_lcdc_overlay_check_var, |
1628 | .fb_set_par = sh_mobile_lcdc_overlay_set_par, | 1637 | .fb_set_par = sh_mobile_lcdc_overlay_set_par, |
1638 | .fb_mmap = sh_mobile_lcdc_overlay_mmap, | ||
1629 | }; | 1639 | }; |
1630 | 1640 | ||
1631 | static void | 1641 | static void |
@@ -2093,6 +2103,15 @@ static int sh_mobile_lcdc_blank(int blank, struct fb_info *info) | |||
2093 | return 0; | 2103 | return 0; |
2094 | } | 2104 | } |
2095 | 2105 | ||
2106 | static int | ||
2107 | sh_mobile_lcdc_mmap(struct fb_info *info, struct vm_area_struct *vma) | ||
2108 | { | ||
2109 | struct sh_mobile_lcdc_chan *ch = info->par; | ||
2110 | |||
2111 | return dma_mmap_coherent(ch->lcdc->dev, vma, ch->fb_mem, | ||
2112 | ch->dma_handle, ch->fb_size); | ||
2113 | } | ||
2114 | |||
2096 | static struct fb_ops sh_mobile_lcdc_ops = { | 2115 | static struct fb_ops sh_mobile_lcdc_ops = { |
2097 | .owner = THIS_MODULE, | 2116 | .owner = THIS_MODULE, |
2098 | .fb_setcolreg = sh_mobile_lcdc_setcolreg, | 2117 | .fb_setcolreg = sh_mobile_lcdc_setcolreg, |
@@ -2108,6 +2127,7 @@ static struct fb_ops sh_mobile_lcdc_ops = { | |||
2108 | .fb_release = sh_mobile_lcdc_release, | 2127 | .fb_release = sh_mobile_lcdc_release, |
2109 | .fb_check_var = sh_mobile_lcdc_check_var, | 2128 | .fb_check_var = sh_mobile_lcdc_check_var, |
2110 | .fb_set_par = sh_mobile_lcdc_set_par, | 2129 | .fb_set_par = sh_mobile_lcdc_set_par, |
2130 | .fb_mmap = sh_mobile_lcdc_mmap, | ||
2111 | }; | 2131 | }; |
2112 | 2132 | ||
2113 | static void | 2133 | static void |
@@ -2167,7 +2187,7 @@ sh_mobile_lcdc_channel_fb_cleanup(struct sh_mobile_lcdc_chan *ch) | |||
2167 | 2187 | ||
2168 | static int __devinit | 2188 | static int __devinit |
2169 | sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch, | 2189 | sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch, |
2170 | const struct fb_videomode *mode, | 2190 | const struct fb_videomode *modes, |
2171 | unsigned int num_modes) | 2191 | unsigned int num_modes) |
2172 | { | 2192 | { |
2173 | struct sh_mobile_lcdc_priv *priv = ch->lcdc; | 2193 | struct sh_mobile_lcdc_priv *priv = ch->lcdc; |
@@ -2193,7 +2213,7 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch, | |||
2193 | info->pseudo_palette = &ch->pseudo_palette; | 2213 | info->pseudo_palette = &ch->pseudo_palette; |
2194 | info->par = ch; | 2214 | info->par = ch; |
2195 | 2215 | ||
2196 | fb_videomode_to_modelist(mode, num_modes, &info->modelist); | 2216 | fb_videomode_to_modelist(modes, num_modes, &info->modelist); |
2197 | 2217 | ||
2198 | ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); | 2218 | ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); |
2199 | if (ret < 0) { | 2219 | if (ret < 0) { |
@@ -2227,9 +2247,9 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch, | |||
2227 | * default. | 2247 | * default. |
2228 | */ | 2248 | */ |
2229 | var = &info->var; | 2249 | var = &info->var; |
2230 | fb_videomode_to_var(var, mode); | 2250 | fb_videomode_to_var(var, modes); |
2231 | var->width = ch->cfg->panel_cfg.width; | 2251 | var->width = ch->display.width; |
2232 | var->height = ch->cfg->panel_cfg.height; | 2252 | var->height = ch->display.height; |
2233 | var->xres_virtual = ch->xres_virtual; | 2253 | var->xres_virtual = ch->xres_virtual; |
2234 | var->yres_virtual = ch->yres_virtual; | 2254 | var->yres_virtual = ch->yres_virtual; |
2235 | var->activate = FB_ACTIVATE_NOW; | 2255 | var->activate = FB_ACTIVATE_NOW; |
@@ -2262,6 +2282,7 @@ static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev) | |||
2262 | bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) | 2282 | bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) |
2263 | brightness = 0; | 2283 | brightness = 0; |
2264 | 2284 | ||
2285 | ch->bl_brightness = brightness; | ||
2265 | return ch->cfg->bl_info.set_brightness(brightness); | 2286 | return ch->cfg->bl_info.set_brightness(brightness); |
2266 | } | 2287 | } |
2267 | 2288 | ||
@@ -2269,7 +2290,7 @@ static int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev) | |||
2269 | { | 2290 | { |
2270 | struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev); | 2291 | struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev); |
2271 | 2292 | ||
2272 | return ch->cfg->bl_info.get_brightness(); | 2293 | return ch->bl_brightness; |
2273 | } | 2294 | } |
2274 | 2295 | ||
2275 | static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev, | 2296 | static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev, |
@@ -2516,10 +2537,10 @@ static int __devinit sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan * | |||
2516 | } | 2537 | } |
2517 | 2538 | ||
2518 | static int __devinit | 2539 | static int __devinit |
2519 | sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv, | 2540 | sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_overlay *ovl) |
2520 | struct sh_mobile_lcdc_overlay *ovl) | ||
2521 | { | 2541 | { |
2522 | const struct sh_mobile_lcdc_format_info *format; | 2542 | const struct sh_mobile_lcdc_format_info *format; |
2543 | struct device *dev = ovl->channel->lcdc->dev; | ||
2523 | int ret; | 2544 | int ret; |
2524 | 2545 | ||
2525 | if (ovl->cfg->fourcc == 0) | 2546 | if (ovl->cfg->fourcc == 0) |
@@ -2528,7 +2549,7 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv, | |||
2528 | /* Validate the format. */ | 2549 | /* Validate the format. */ |
2529 | format = sh_mobile_format_info(ovl->cfg->fourcc); | 2550 | format = sh_mobile_format_info(ovl->cfg->fourcc); |
2530 | if (format == NULL) { | 2551 | if (format == NULL) { |
2531 | dev_err(priv->dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc); | 2552 | dev_err(dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc); |
2532 | return -EINVAL; | 2553 | return -EINVAL; |
2533 | } | 2554 | } |
2534 | 2555 | ||
@@ -2556,10 +2577,10 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv, | |||
2556 | /* Allocate frame buffer memory. */ | 2577 | /* Allocate frame buffer memory. */ |
2557 | ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres | 2578 | ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres |
2558 | * format->bpp / 8 * 2; | 2579 | * format->bpp / 8 * 2; |
2559 | ovl->fb_mem = dma_alloc_coherent(priv->dev, ovl->fb_size, | 2580 | ovl->fb_mem = dma_alloc_coherent(dev, ovl->fb_size, &ovl->dma_handle, |
2560 | &ovl->dma_handle, GFP_KERNEL); | 2581 | GFP_KERNEL); |
2561 | if (!ovl->fb_mem) { | 2582 | if (!ovl->fb_mem) { |
2562 | dev_err(priv->dev, "unable to allocate buffer\n"); | 2583 | dev_err(dev, "unable to allocate buffer\n"); |
2563 | return -ENOMEM; | 2584 | return -ENOMEM; |
2564 | } | 2585 | } |
2565 | 2586 | ||
@@ -2571,11 +2592,11 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv, | |||
2571 | } | 2592 | } |
2572 | 2593 | ||
2573 | static int __devinit | 2594 | static int __devinit |
2574 | sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv, | 2595 | sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch) |
2575 | struct sh_mobile_lcdc_chan *ch) | ||
2576 | { | 2596 | { |
2577 | const struct sh_mobile_lcdc_format_info *format; | 2597 | const struct sh_mobile_lcdc_format_info *format; |
2578 | const struct sh_mobile_lcdc_chan_cfg *cfg = ch->cfg; | 2598 | const struct sh_mobile_lcdc_chan_cfg *cfg = ch->cfg; |
2599 | struct device *dev = ch->lcdc->dev; | ||
2579 | const struct fb_videomode *max_mode; | 2600 | const struct fb_videomode *max_mode; |
2580 | const struct fb_videomode *mode; | 2601 | const struct fb_videomode *mode; |
2581 | unsigned int num_modes; | 2602 | unsigned int num_modes; |
@@ -2588,7 +2609,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv, | |||
2588 | /* Validate the format. */ | 2609 | /* Validate the format. */ |
2589 | format = sh_mobile_format_info(cfg->fourcc); | 2610 | format = sh_mobile_format_info(cfg->fourcc); |
2590 | if (format == NULL) { | 2611 | if (format == NULL) { |
2591 | dev_err(priv->dev, "Invalid FOURCC %08x.\n", cfg->fourcc); | 2612 | dev_err(dev, "Invalid FOURCC %08x.\n", cfg->fourcc); |
2592 | return -EINVAL; | 2613 | return -EINVAL; |
2593 | } | 2614 | } |
2594 | 2615 | ||
@@ -2604,7 +2625,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv, | |||
2604 | /* NV12/NV21 buffers must have even number of lines */ | 2625 | /* NV12/NV21 buffers must have even number of lines */ |
2605 | if ((cfg->fourcc == V4L2_PIX_FMT_NV12 || | 2626 | if ((cfg->fourcc == V4L2_PIX_FMT_NV12 || |
2606 | cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) { | 2627 | cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) { |
2607 | dev_err(priv->dev, "yres must be multiple of 2 for " | 2628 | dev_err(dev, "yres must be multiple of 2 for " |
2608 | "YCbCr420 mode.\n"); | 2629 | "YCbCr420 mode.\n"); |
2609 | return -EINVAL; | 2630 | return -EINVAL; |
2610 | } | 2631 | } |
@@ -2618,7 +2639,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv, | |||
2618 | if (!max_size) | 2639 | if (!max_size) |
2619 | max_size = MAX_XRES * MAX_YRES; | 2640 | max_size = MAX_XRES * MAX_YRES; |
2620 | else | 2641 | else |
2621 | dev_dbg(priv->dev, "Found largest videomode %ux%u\n", | 2642 | dev_dbg(dev, "Found largest videomode %ux%u\n", |
2622 | max_mode->xres, max_mode->yres); | 2643 | max_mode->xres, max_mode->yres); |
2623 | 2644 | ||
2624 | if (cfg->lcd_modes == NULL) { | 2645 | if (cfg->lcd_modes == NULL) { |
@@ -2652,10 +2673,10 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv, | |||
2652 | 2673 | ||
2653 | /* Allocate frame buffer memory. */ | 2674 | /* Allocate frame buffer memory. */ |
2654 | ch->fb_size = max_size * format->bpp / 8 * 2; | 2675 | ch->fb_size = max_size * format->bpp / 8 * 2; |
2655 | ch->fb_mem = dma_alloc_coherent(priv->dev, ch->fb_size, &ch->dma_handle, | 2676 | ch->fb_mem = dma_alloc_coherent(dev, ch->fb_size, &ch->dma_handle, |
2656 | GFP_KERNEL); | 2677 | GFP_KERNEL); |
2657 | if (ch->fb_mem == NULL) { | 2678 | if (ch->fb_mem == NULL) { |
2658 | dev_err(priv->dev, "unable to allocate buffer\n"); | 2679 | dev_err(dev, "unable to allocate buffer\n"); |
2659 | return -ENOMEM; | 2680 | return -ENOMEM; |
2660 | } | 2681 | } |
2661 | 2682 | ||
@@ -2663,8 +2684,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv, | |||
2663 | if (cfg->tx_dev) { | 2684 | if (cfg->tx_dev) { |
2664 | if (!cfg->tx_dev->dev.driver || | 2685 | if (!cfg->tx_dev->dev.driver || |
2665 | !try_module_get(cfg->tx_dev->dev.driver->owner)) { | 2686 | !try_module_get(cfg->tx_dev->dev.driver->owner)) { |
2666 | dev_warn(priv->dev, | 2687 | dev_warn(dev, "unable to get transmitter device\n"); |
2667 | "unable to get transmitter device\n"); | ||
2668 | return -EINVAL; | 2688 | return -EINVAL; |
2669 | } | 2689 | } |
2670 | ch->tx_dev = platform_get_drvdata(cfg->tx_dev); | 2690 | ch->tx_dev = platform_get_drvdata(cfg->tx_dev); |
@@ -2772,9 +2792,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
2772 | pm_runtime_enable(&pdev->dev); | 2792 | pm_runtime_enable(&pdev->dev); |
2773 | 2793 | ||
2774 | for (i = 0; i < num_channels; i++) { | 2794 | for (i = 0; i < num_channels; i++) { |
2775 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; | 2795 | struct sh_mobile_lcdc_chan *ch = &priv->ch[i]; |
2776 | 2796 | ||
2777 | error = sh_mobile_lcdc_channel_init(priv, ch); | 2797 | error = sh_mobile_lcdc_channel_init(ch); |
2778 | if (error) | 2798 | if (error) |
2779 | goto err1; | 2799 | goto err1; |
2780 | } | 2800 | } |
@@ -2785,7 +2805,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
2785 | ovl->cfg = &pdata->overlays[i]; | 2805 | ovl->cfg = &pdata->overlays[i]; |
2786 | ovl->channel = &priv->ch[0]; | 2806 | ovl->channel = &priv->ch[0]; |
2787 | 2807 | ||
2788 | error = sh_mobile_lcdc_overlay_init(priv, ovl); | 2808 | error = sh_mobile_lcdc_overlay_init(ovl); |
2789 | if (error) | 2809 | if (error) |
2790 | goto err1; | 2810 | goto err1; |
2791 | } | 2811 | } |
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h index 0f92f6544b94..f839adef1d90 100644 --- a/drivers/video/sh_mobile_lcdcfb.h +++ b/drivers/video/sh_mobile_lcdcfb.h | |||
@@ -94,6 +94,7 @@ struct sh_mobile_lcdc_chan { | |||
94 | 94 | ||
95 | /* Backlight */ | 95 | /* Backlight */ |
96 | struct backlight_device *bl; | 96 | struct backlight_device *bl; |
97 | unsigned int bl_brightness; | ||
97 | 98 | ||
98 | /* FB */ | 99 | /* FB */ |
99 | struct fb_info *info; | 100 | struct fb_info *info; |
diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c new file mode 100644 index 000000000000..6101f5c2f62f --- /dev/null +++ b/drivers/video/ssd1307fb.c | |||
@@ -0,0 +1,396 @@ | |||
1 | /* | ||
2 | * Driver for the Solomon SSD1307 OLED controler | ||
3 | * | ||
4 | * Copyright 2012 Free Electrons | ||
5 | * | ||
6 | * Licensed under the GPLv2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/i2c.h> | ||
12 | #include <linux/fb.h> | ||
13 | #include <linux/uaccess.h> | ||
14 | #include <linux/of_device.h> | ||
15 | #include <linux/of_gpio.h> | ||
16 | #include <linux/pwm.h> | ||
17 | #include <linux/delay.h> | ||
18 | |||
19 | #define SSD1307FB_WIDTH 96 | ||
20 | #define SSD1307FB_HEIGHT 16 | ||
21 | |||
22 | #define SSD1307FB_DATA 0x40 | ||
23 | #define SSD1307FB_COMMAND 0x80 | ||
24 | |||
25 | #define SSD1307FB_CONTRAST 0x81 | ||
26 | #define SSD1307FB_SEG_REMAP_ON 0xa1 | ||
27 | #define SSD1307FB_DISPLAY_OFF 0xae | ||
28 | #define SSD1307FB_DISPLAY_ON 0xaf | ||
29 | #define SSD1307FB_START_PAGE_ADDRESS 0xb0 | ||
30 | |||
31 | struct ssd1307fb_par { | ||
32 | struct i2c_client *client; | ||
33 | struct fb_info *info; | ||
34 | struct pwm_device *pwm; | ||
35 | u32 pwm_period; | ||
36 | int reset; | ||
37 | }; | ||
38 | |||
39 | static struct fb_fix_screeninfo ssd1307fb_fix __devinitdata = { | ||
40 | .id = "Solomon SSD1307", | ||
41 | .type = FB_TYPE_PACKED_PIXELS, | ||
42 | .visual = FB_VISUAL_MONO10, | ||
43 | .xpanstep = 0, | ||
44 | .ypanstep = 0, | ||
45 | .ywrapstep = 0, | ||
46 | .line_length = SSD1307FB_WIDTH / 8, | ||
47 | .accel = FB_ACCEL_NONE, | ||
48 | }; | ||
49 | |||
50 | static struct fb_var_screeninfo ssd1307fb_var __devinitdata = { | ||
51 | .xres = SSD1307FB_WIDTH, | ||
52 | .yres = SSD1307FB_HEIGHT, | ||
53 | .xres_virtual = SSD1307FB_WIDTH, | ||
54 | .yres_virtual = SSD1307FB_HEIGHT, | ||
55 | .bits_per_pixel = 1, | ||
56 | }; | ||
57 | |||
58 | static int ssd1307fb_write_array(struct i2c_client *client, u8 type, u8 *cmd, u32 len) | ||
59 | { | ||
60 | u8 *buf; | ||
61 | int ret = 0; | ||
62 | |||
63 | buf = kzalloc(len + 1, GFP_KERNEL); | ||
64 | if (!buf) { | ||
65 | dev_err(&client->dev, "Couldn't allocate sending buffer.\n"); | ||
66 | return -ENOMEM; | ||
67 | } | ||
68 | |||
69 | buf[0] = type; | ||
70 | memcpy(buf + 1, cmd, len); | ||
71 | |||
72 | ret = i2c_master_send(client, buf, len + 1); | ||
73 | if (ret != len + 1) { | ||
74 | dev_err(&client->dev, "Couldn't send I2C command.\n"); | ||
75 | goto error; | ||
76 | } | ||
77 | |||
78 | error: | ||
79 | kfree(buf); | ||
80 | return ret; | ||
81 | } | ||
82 | |||
83 | static inline int ssd1307fb_write_cmd_array(struct i2c_client *client, u8 *cmd, u32 len) | ||
84 | { | ||
85 | return ssd1307fb_write_array(client, SSD1307FB_COMMAND, cmd, len); | ||
86 | } | ||
87 | |||
88 | static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd) | ||
89 | { | ||
90 | return ssd1307fb_write_cmd_array(client, &cmd, 1); | ||
91 | } | ||
92 | |||
93 | static inline int ssd1307fb_write_data_array(struct i2c_client *client, u8 *cmd, u32 len) | ||
94 | { | ||
95 | return ssd1307fb_write_array(client, SSD1307FB_DATA, cmd, len); | ||
96 | } | ||
97 | |||
98 | static inline int ssd1307fb_write_data(struct i2c_client *client, u8 data) | ||
99 | { | ||
100 | return ssd1307fb_write_data_array(client, &data, 1); | ||
101 | } | ||
102 | |||
103 | static void ssd1307fb_update_display(struct ssd1307fb_par *par) | ||
104 | { | ||
105 | u8 *vmem = par->info->screen_base; | ||
106 | int i, j, k; | ||
107 | |||
108 | /* | ||
109 | * The screen is divided in pages, each having a height of 8 | ||
110 | * pixels, and the width of the screen. When sending a byte of | ||
111 | * data to the controller, it gives the 8 bits for the current | ||
112 | * column. I.e, the first byte are the 8 bits of the first | ||
113 | * column, then the 8 bits for the second column, etc. | ||
114 | * | ||
115 | * | ||
116 | * Representation of the screen, assuming it is 5 bits | ||
117 | * wide. Each letter-number combination is a bit that controls | ||
118 | * one pixel. | ||
119 | * | ||
120 | * A0 A1 A2 A3 A4 | ||
121 | * B0 B1 B2 B3 B4 | ||
122 | * C0 C1 C2 C3 C4 | ||
123 | * D0 D1 D2 D3 D4 | ||
124 | * E0 E1 E2 E3 E4 | ||
125 | * F0 F1 F2 F3 F4 | ||
126 | * G0 G1 G2 G3 G4 | ||
127 | * H0 H1 H2 H3 H4 | ||
128 | * | ||
129 | * If you want to update this screen, you need to send 5 bytes: | ||
130 | * (1) A0 B0 C0 D0 E0 F0 G0 H0 | ||
131 | * (2) A1 B1 C1 D1 E1 F1 G1 H1 | ||
132 | * (3) A2 B2 C2 D2 E2 F2 G2 H2 | ||
133 | * (4) A3 B3 C3 D3 E3 F3 G3 H3 | ||
134 | * (5) A4 B4 C4 D4 E4 F4 G4 H4 | ||
135 | */ | ||
136 | |||
137 | for (i = 0; i < (SSD1307FB_HEIGHT / 8); i++) { | ||
138 | ssd1307fb_write_cmd(par->client, SSD1307FB_START_PAGE_ADDRESS + (i + 1)); | ||
139 | ssd1307fb_write_cmd(par->client, 0x00); | ||
140 | ssd1307fb_write_cmd(par->client, 0x10); | ||
141 | |||
142 | for (j = 0; j < SSD1307FB_WIDTH; j++) { | ||
143 | u8 buf = 0; | ||
144 | for (k = 0; k < 8; k++) { | ||
145 | u32 page_length = SSD1307FB_WIDTH * i; | ||
146 | u32 index = page_length + (SSD1307FB_WIDTH * k + j) / 8; | ||
147 | u8 byte = *(vmem + index); | ||
148 | u8 bit = byte & (1 << (7 - (j % 8))); | ||
149 | bit = bit >> (7 - (j % 8)); | ||
150 | buf |= bit << k; | ||
151 | } | ||
152 | ssd1307fb_write_data(par->client, buf); | ||
153 | } | ||
154 | } | ||
155 | } | ||
156 | |||
157 | |||
158 | static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf, | ||
159 | size_t count, loff_t *ppos) | ||
160 | { | ||
161 | struct ssd1307fb_par *par = info->par; | ||
162 | unsigned long total_size; | ||
163 | unsigned long p = *ppos; | ||
164 | u8 __iomem *dst; | ||
165 | |||
166 | total_size = info->fix.smem_len; | ||
167 | |||
168 | if (p > total_size) | ||
169 | return -EINVAL; | ||
170 | |||
171 | if (count + p > total_size) | ||
172 | count = total_size - p; | ||
173 | |||
174 | if (!count) | ||
175 | return -EINVAL; | ||
176 | |||
177 | dst = (void __force *) (info->screen_base + p); | ||
178 | |||
179 | if (copy_from_user(dst, buf, count)) | ||
180 | return -EFAULT; | ||
181 | |||
182 | ssd1307fb_update_display(par); | ||
183 | |||
184 | *ppos += count; | ||
185 | |||
186 | return count; | ||
187 | } | ||
188 | |||
189 | static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | ||
190 | { | ||
191 | struct ssd1307fb_par *par = info->par; | ||
192 | sys_fillrect(info, rect); | ||
193 | ssd1307fb_update_display(par); | ||
194 | } | ||
195 | |||
196 | static void ssd1307fb_copyarea(struct fb_info *info, const struct fb_copyarea *area) | ||
197 | { | ||
198 | struct ssd1307fb_par *par = info->par; | ||
199 | sys_copyarea(info, area); | ||
200 | ssd1307fb_update_display(par); | ||
201 | } | ||
202 | |||
203 | static void ssd1307fb_imageblit(struct fb_info *info, const struct fb_image *image) | ||
204 | { | ||
205 | struct ssd1307fb_par *par = info->par; | ||
206 | sys_imageblit(info, image); | ||
207 | ssd1307fb_update_display(par); | ||
208 | } | ||
209 | |||
210 | static struct fb_ops ssd1307fb_ops = { | ||
211 | .owner = THIS_MODULE, | ||
212 | .fb_read = fb_sys_read, | ||
213 | .fb_write = ssd1307fb_write, | ||
214 | .fb_fillrect = ssd1307fb_fillrect, | ||
215 | .fb_copyarea = ssd1307fb_copyarea, | ||
216 | .fb_imageblit = ssd1307fb_imageblit, | ||
217 | }; | ||
218 | |||
219 | static void ssd1307fb_deferred_io(struct fb_info *info, | ||
220 | struct list_head *pagelist) | ||
221 | { | ||
222 | ssd1307fb_update_display(info->par); | ||
223 | } | ||
224 | |||
225 | static struct fb_deferred_io ssd1307fb_defio = { | ||
226 | .delay = HZ, | ||
227 | .deferred_io = ssd1307fb_deferred_io, | ||
228 | }; | ||
229 | |||
230 | static int __devinit ssd1307fb_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
231 | { | ||
232 | struct fb_info *info; | ||
233 | u32 vmem_size = SSD1307FB_WIDTH * SSD1307FB_HEIGHT / 8; | ||
234 | struct ssd1307fb_par *par; | ||
235 | u8 *vmem; | ||
236 | int ret; | ||
237 | |||
238 | if (!client->dev.of_node) { | ||
239 | dev_err(&client->dev, "No device tree data found!\n"); | ||
240 | return -EINVAL; | ||
241 | } | ||
242 | |||
243 | info = framebuffer_alloc(sizeof(struct ssd1307fb_par), &client->dev); | ||
244 | if (!info) { | ||
245 | dev_err(&client->dev, "Couldn't allocate framebuffer.\n"); | ||
246 | return -ENOMEM; | ||
247 | } | ||
248 | |||
249 | vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL); | ||
250 | if (!vmem) { | ||
251 | dev_err(&client->dev, "Couldn't allocate graphical memory.\n"); | ||
252 | ret = -ENOMEM; | ||
253 | goto fb_alloc_error; | ||
254 | } | ||
255 | |||
256 | info->fbops = &ssd1307fb_ops; | ||
257 | info->fix = ssd1307fb_fix; | ||
258 | info->fbdefio = &ssd1307fb_defio; | ||
259 | |||
260 | info->var = ssd1307fb_var; | ||
261 | info->var.red.length = 1; | ||
262 | info->var.red.offset = 0; | ||
263 | info->var.green.length = 1; | ||
264 | info->var.green.offset = 0; | ||
265 | info->var.blue.length = 1; | ||
266 | info->var.blue.offset = 0; | ||
267 | |||
268 | info->screen_base = (u8 __force __iomem *)vmem; | ||
269 | info->fix.smem_start = (unsigned long)vmem; | ||
270 | info->fix.smem_len = vmem_size; | ||
271 | |||
272 | fb_deferred_io_init(info); | ||
273 | |||
274 | par = info->par; | ||
275 | par->info = info; | ||
276 | par->client = client; | ||
277 | |||
278 | par->reset = of_get_named_gpio(client->dev.of_node, | ||
279 | "reset-gpios", 0); | ||
280 | if (!gpio_is_valid(par->reset)) { | ||
281 | ret = -EINVAL; | ||
282 | goto reset_oled_error; | ||
283 | } | ||
284 | |||
285 | ret = devm_gpio_request_one(&client->dev, par->reset, | ||
286 | GPIOF_OUT_INIT_HIGH, | ||
287 | "oled-reset"); | ||
288 | if (ret) { | ||
289 | dev_err(&client->dev, | ||
290 | "failed to request gpio %d: %d\n", | ||
291 | par->reset, ret); | ||
292 | goto reset_oled_error; | ||
293 | } | ||
294 | |||
295 | par->pwm = pwm_get(&client->dev, NULL); | ||
296 | if (IS_ERR(par->pwm)) { | ||
297 | dev_err(&client->dev, "Could not get PWM from device tree!\n"); | ||
298 | ret = PTR_ERR(par->pwm); | ||
299 | goto pwm_error; | ||
300 | } | ||
301 | |||
302 | par->pwm_period = pwm_get_period(par->pwm); | ||
303 | |||
304 | dev_dbg(&client->dev, "Using PWM%d with a %dns period.\n", par->pwm->pwm, par->pwm_period); | ||
305 | |||
306 | ret = register_framebuffer(info); | ||
307 | if (ret) { | ||
308 | dev_err(&client->dev, "Couldn't register the framebuffer\n"); | ||
309 | goto fbreg_error; | ||
310 | } | ||
311 | |||
312 | i2c_set_clientdata(client, info); | ||
313 | |||
314 | /* Reset the screen */ | ||
315 | gpio_set_value(par->reset, 0); | ||
316 | udelay(4); | ||
317 | gpio_set_value(par->reset, 1); | ||
318 | udelay(4); | ||
319 | |||
320 | /* Enable the PWM */ | ||
321 | pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period); | ||
322 | pwm_enable(par->pwm); | ||
323 | |||
324 | /* Map column 127 of the OLED to segment 0 */ | ||
325 | ret = ssd1307fb_write_cmd(client, SSD1307FB_SEG_REMAP_ON); | ||
326 | if (ret < 0) { | ||
327 | dev_err(&client->dev, "Couldn't remap the screen.\n"); | ||
328 | goto remap_error; | ||
329 | } | ||
330 | |||
331 | /* Turn on the display */ | ||
332 | ret = ssd1307fb_write_cmd(client, SSD1307FB_DISPLAY_ON); | ||
333 | if (ret < 0) { | ||
334 | dev_err(&client->dev, "Couldn't turn the display on.\n"); | ||
335 | goto remap_error; | ||
336 | } | ||
337 | |||
338 | dev_info(&client->dev, "fb%d: %s framebuffer device registered, using %d bytes of video memory\n", info->node, info->fix.id, vmem_size); | ||
339 | |||
340 | return 0; | ||
341 | |||
342 | remap_error: | ||
343 | unregister_framebuffer(info); | ||
344 | pwm_disable(par->pwm); | ||
345 | fbreg_error: | ||
346 | pwm_put(par->pwm); | ||
347 | pwm_error: | ||
348 | reset_oled_error: | ||
349 | fb_deferred_io_cleanup(info); | ||
350 | fb_alloc_error: | ||
351 | framebuffer_release(info); | ||
352 | return ret; | ||
353 | } | ||
354 | |||
355 | static int __devexit ssd1307fb_remove(struct i2c_client *client) | ||
356 | { | ||
357 | struct fb_info *info = i2c_get_clientdata(client); | ||
358 | struct ssd1307fb_par *par = info->par; | ||
359 | |||
360 | unregister_framebuffer(info); | ||
361 | pwm_disable(par->pwm); | ||
362 | pwm_put(par->pwm); | ||
363 | fb_deferred_io_cleanup(info); | ||
364 | framebuffer_release(info); | ||
365 | |||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | static const struct i2c_device_id ssd1307fb_i2c_id[] = { | ||
370 | { "ssd1307fb", 0 }, | ||
371 | { } | ||
372 | }; | ||
373 | MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id); | ||
374 | |||
375 | static const struct of_device_id ssd1307fb_of_match[] = { | ||
376 | { .compatible = "solomon,ssd1307fb-i2c" }, | ||
377 | {}, | ||
378 | }; | ||
379 | MODULE_DEVICE_TABLE(of, ssd1307fb_of_match); | ||
380 | |||
381 | static struct i2c_driver ssd1307fb_driver = { | ||
382 | .probe = ssd1307fb_probe, | ||
383 | .remove = __devexit_p(ssd1307fb_remove), | ||
384 | .id_table = ssd1307fb_i2c_id, | ||
385 | .driver = { | ||
386 | .name = "ssd1307fb", | ||
387 | .of_match_table = of_match_ptr(ssd1307fb_of_match), | ||
388 | .owner = THIS_MODULE, | ||
389 | }, | ||
390 | }; | ||
391 | |||
392 | module_i2c_driver(ssd1307fb_driver); | ||
393 | |||
394 | MODULE_DESCRIPTION("FB driver for the Solomon SSD1307 OLED controler"); | ||
395 | MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); | ||
396 | MODULE_LICENSE("GPL"); | ||
diff --git a/include/linux/fsl-diu-fb.h b/include/linux/fsl-diu-fb.h index 11c16a1fb9e3..a1e8277120c7 100644 --- a/include/linux/fsl-diu-fb.h +++ b/include/linux/fsl-diu-fb.h | |||
@@ -47,6 +47,15 @@ struct aoi_display_offset { | |||
47 | #define MFB_GET_PIXFMT _IOR('M', 8, __u32) | 47 | #define MFB_GET_PIXFMT _IOR('M', 8, __u32) |
48 | 48 | ||
49 | /* | 49 | /* |
50 | * The MPC5121 BSP comes with a gamma_set utility that initializes the | ||
51 | * gamma table. Unfortunately, it uses bad values for the IOCTL commands, | ||
52 | * but there's nothing we can do about it now. These ioctls are only | ||
53 | * supported on the MPC5121. | ||
54 | */ | ||
55 | #define MFB_SET_GAMMA _IOW('M', 1, __u8) | ||
56 | #define MFB_GET_GAMMA _IOR('M', 1, __u8) | ||
57 | |||
58 | /* | ||
50 | * The original definitions of MFB_SET_PIXFMT and MFB_GET_PIXFMT used the | 59 | * The original definitions of MFB_SET_PIXFMT and MFB_GET_PIXFMT used the |
51 | * wrong value for 'size' field of the ioctl. The current macros above use the | 60 | * wrong value for 'size' field of the ioctl. The current macros above use the |
52 | * right size, but we still need to provide backwards compatibility, at least | 61 | * right size, but we still need to provide backwards compatibility, at least |
diff --git a/include/video/da8xx-fb.h b/include/video/da8xx-fb.h index 5a0e4f9efb53..f88825928dd1 100644 --- a/include/video/da8xx-fb.h +++ b/include/video/da8xx-fb.h | |||
@@ -12,10 +12,6 @@ | |||
12 | #ifndef DA8XX_FB_H | 12 | #ifndef DA8XX_FB_H |
13 | #define DA8XX_FB_H | 13 | #define DA8XX_FB_H |
14 | 14 | ||
15 | enum panel_type { | ||
16 | QVGA = 0 | ||
17 | }; | ||
18 | |||
19 | enum panel_shade { | 15 | enum panel_shade { |
20 | MONOCHROME = 0, | 16 | MONOCHROME = 0, |
21 | COLOR_ACTIVE, | 17 | COLOR_ACTIVE, |
@@ -27,13 +23,6 @@ enum raster_load_mode { | |||
27 | LOAD_PALETTE, | 23 | LOAD_PALETTE, |
28 | }; | 24 | }; |
29 | 25 | ||
30 | struct display_panel { | ||
31 | enum panel_type panel_type; /* QVGA */ | ||
32 | int max_bpp; | ||
33 | int min_bpp; | ||
34 | enum panel_shade panel_shade; | ||
35 | }; | ||
36 | |||
37 | struct da8xx_lcdc_platform_data { | 26 | struct da8xx_lcdc_platform_data { |
38 | const char manu_name[10]; | 27 | const char manu_name[10]; |
39 | void *controller_data; | 28 | void *controller_data; |
@@ -42,7 +31,7 @@ struct da8xx_lcdc_platform_data { | |||
42 | }; | 31 | }; |
43 | 32 | ||
44 | struct lcd_ctrl_config { | 33 | struct lcd_ctrl_config { |
45 | const struct display_panel *p_disp_panel; | 34 | enum panel_shade panel_shade; |
46 | 35 | ||
47 | /* AC Bias Pin Frequency */ | 36 | /* AC Bias Pin Frequency */ |
48 | int ac_bias; | 37 | int ac_bias; |
@@ -68,18 +57,9 @@ struct lcd_ctrl_config { | |||
68 | /* Mono 8-bit Mode: 1=D0-D7 or 0=D0-D3 */ | 57 | /* Mono 8-bit Mode: 1=D0-D7 or 0=D0-D3 */ |
69 | unsigned char mono_8bit_mode; | 58 | unsigned char mono_8bit_mode; |
70 | 59 | ||
71 | /* Invert line clock */ | ||
72 | unsigned char invert_line_clock; | ||
73 | |||
74 | /* Invert frame clock */ | ||
75 | unsigned char invert_frm_clock; | ||
76 | |||
77 | /* Horizontal and Vertical Sync Edge: 0=rising 1=falling */ | 60 | /* Horizontal and Vertical Sync Edge: 0=rising 1=falling */ |
78 | unsigned char sync_edge; | 61 | unsigned char sync_edge; |
79 | 62 | ||
80 | /* Horizontal and Vertical Sync: Control: 0=ignore */ | ||
81 | unsigned char sync_ctrl; | ||
82 | |||
83 | /* Raster Data Order Select: 1=Most-to-least 0=Least-to-most */ | 63 | /* Raster Data Order Select: 1=Most-to-least 0=Least-to-most */ |
84 | unsigned char raster_order; | 64 | unsigned char raster_order; |
85 | 65 | ||
@@ -103,5 +83,8 @@ struct lcd_sync_arg { | |||
103 | #define FBIPUT_HSYNC _IOW('F', 9, int) | 83 | #define FBIPUT_HSYNC _IOW('F', 9, int) |
104 | #define FBIPUT_VSYNC _IOW('F', 10, int) | 84 | #define FBIPUT_VSYNC _IOW('F', 10, int) |
105 | 85 | ||
86 | /* Proprietary FB_SYNC_ flags */ | ||
87 | #define FB_SYNC_CLK_INVERT 0x40000000 | ||
88 | |||
106 | #endif /* ifndef DA8XX_FB_H */ | 89 | #endif /* ifndef DA8XX_FB_H */ |
107 | 90 | ||
diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 88c829466fc1..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 { |
@@ -621,10 +622,6 @@ struct omap_dss_device { | |||
621 | struct { | 622 | struct { |
622 | struct omap_video_timings timings; | 623 | struct omap_video_timings timings; |
623 | 624 | ||
624 | int acbi; /* ac-bias pin transitions per interrupt */ | ||
625 | /* Unit: line clocks */ | ||
626 | int acb; /* ac-bias pin frequency */ | ||
627 | |||
628 | enum omap_dss_dsi_pixel_format dsi_pix_fmt; | 625 | enum omap_dss_dsi_pixel_format dsi_pix_fmt; |
629 | enum omap_dss_dsi_mode dsi_mode; | 626 | enum omap_dss_dsi_mode dsi_mode; |
630 | struct omap_dss_dsi_videomode_timings dsi_vm_timings; | 627 | struct omap_dss_dsi_videomode_timings dsi_vm_timings; |
@@ -686,8 +683,6 @@ struct omap_dss_driver { | |||
686 | 683 | ||
687 | int (*enable)(struct omap_dss_device *display); | 684 | int (*enable)(struct omap_dss_device *display); |
688 | void (*disable)(struct omap_dss_device *display); | 685 | void (*disable)(struct omap_dss_device *display); |
689 | int (*suspend)(struct omap_dss_device *display); | ||
690 | int (*resume)(struct omap_dss_device *display); | ||
691 | int (*run_test)(struct omap_dss_device *display, int test); | 686 | int (*run_test)(struct omap_dss_device *display, int test); |
692 | 687 | ||
693 | int (*update)(struct omap_dss_device *dssdev, | 688 | int (*update)(struct omap_dss_device *dssdev, |
@@ -745,6 +740,8 @@ struct omap_dss_driver { | |||
745 | 740 | ||
746 | }; | 741 | }; |
747 | 742 | ||
743 | enum omapdss_version omapdss_get_version(void); | ||
744 | |||
748 | int omap_dss_register_driver(struct omap_dss_driver *); | 745 | int omap_dss_register_driver(struct omap_dss_driver *); |
749 | void omap_dss_unregister_driver(struct omap_dss_driver *); | 746 | void omap_dss_unregister_driver(struct omap_dss_driver *); |
750 | 747 | ||
@@ -754,10 +751,19 @@ void omap_dss_put_device(struct omap_dss_device *dssdev); | |||
754 | 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); |
755 | struct omap_dss_device *omap_dss_find_device(void *data, | 752 | struct omap_dss_device *omap_dss_find_device(void *data, |
756 | 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); | ||
757 | 755 | ||
758 | int omap_dss_start_device(struct omap_dss_device *dssdev); | 756 | int omap_dss_start_device(struct omap_dss_device *dssdev); |
759 | void omap_dss_stop_device(struct omap_dss_device *dssdev); | 757 | void omap_dss_stop_device(struct omap_dss_device *dssdev); |
760 | 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 | |||
761 | int omap_dss_get_num_overlay_managers(void); | 767 | int omap_dss_get_num_overlay_managers(void); |
762 | struct omap_overlay_manager *omap_dss_get_overlay_manager(int num); | 768 | struct omap_overlay_manager *omap_dss_get_overlay_manager(int num); |
763 | 769 | ||
@@ -779,9 +785,43 @@ typedef void (*omap_dispc_isr_t) (void *arg, u32 mask); | |||
779 | 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); |
780 | 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); |
781 | 787 | ||
782 | int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout); | 788 | u32 dispc_read_irqstatus(void); |
783 | int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, | 789 | void dispc_clear_irqstatus(u32 mask); |
784 | 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); | ||
785 | 825 | ||
786 | #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) |
787 | #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) |
@@ -840,4 +880,35 @@ void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev, | |||
840 | void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev, | 880 | void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev, |
841 | struct rfbi_timings *timings); | 881 | struct rfbi_timings *timings); |
842 | 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); | ||
843 | #endif | 914 | #endif |
diff --git a/include/video/samsung_fimd.h b/include/video/samsung_fimd.h index 7ae6c07f2ef8..e7554486a2b7 100644 --- a/include/video/samsung_fimd.h +++ b/include/video/samsung_fimd.h | |||
@@ -24,12 +24,15 @@ | |||
24 | 24 | ||
25 | #define VIDCON0 (0x00) | 25 | #define VIDCON0 (0x00) |
26 | #define VIDCON0_INTERLACE (1 << 29) | 26 | #define VIDCON0_INTERLACE (1 << 29) |
27 | #define VIDCON0_VIDOUT_MASK (0x3 << 26) | 27 | #define VIDCON0_VIDOUT_MASK (0x7 << 26) |
28 | #define VIDCON0_VIDOUT_SHIFT (26) | 28 | #define VIDCON0_VIDOUT_SHIFT (26) |
29 | #define VIDCON0_VIDOUT_RGB (0x0 << 26) | 29 | #define VIDCON0_VIDOUT_RGB (0x0 << 26) |
30 | #define VIDCON0_VIDOUT_TV (0x1 << 26) | 30 | #define VIDCON0_VIDOUT_TV (0x1 << 26) |
31 | #define VIDCON0_VIDOUT_I80_LDI0 (0x2 << 26) | 31 | #define VIDCON0_VIDOUT_I80_LDI0 (0x2 << 26) |
32 | #define VIDCON0_VIDOUT_I80_LDI1 (0x3 << 26) | 32 | #define VIDCON0_VIDOUT_I80_LDI1 (0x3 << 26) |
33 | #define VIDCON0_VIDOUT_WB_RGB (0x4 << 26) | ||
34 | #define VIDCON0_VIDOUT_WB_I80_LDI0 (0x6 << 26) | ||
35 | #define VIDCON0_VIDOUT_WB_I80_LDI1 (0x7 << 26) | ||
33 | 36 | ||
34 | #define VIDCON0_L1_DATA_MASK (0x7 << 23) | 37 | #define VIDCON0_L1_DATA_MASK (0x7 << 23) |
35 | #define VIDCON0_L1_DATA_SHIFT (23) | 38 | #define VIDCON0_L1_DATA_SHIFT (23) |
@@ -77,6 +80,7 @@ | |||
77 | #define VIDCON1_LINECNT_MASK (0x7ff << 16) | 80 | #define VIDCON1_LINECNT_MASK (0x7ff << 16) |
78 | #define VIDCON1_LINECNT_SHIFT (16) | 81 | #define VIDCON1_LINECNT_SHIFT (16) |
79 | #define VIDCON1_LINECNT_GET(_v) (((_v) >> 16) & 0x7ff) | 82 | #define VIDCON1_LINECNT_GET(_v) (((_v) >> 16) & 0x7ff) |
83 | #define VIDCON1_FSTATUS_EVEN (1 << 15) | ||
80 | #define VIDCON1_VSTATUS_MASK (0x3 << 13) | 84 | #define VIDCON1_VSTATUS_MASK (0x3 << 13) |
81 | #define VIDCON1_VSTATUS_SHIFT (13) | 85 | #define VIDCON1_VSTATUS_SHIFT (13) |
82 | #define VIDCON1_VSTATUS_VSYNC (0x0 << 13) | 86 | #define VIDCON1_VSTATUS_VSYNC (0x0 << 13) |
@@ -116,6 +120,7 @@ | |||
116 | 120 | ||
117 | /* VIDTCON0 */ | 121 | /* VIDTCON0 */ |
118 | 122 | ||
123 | #define VIDTCON0 (0x10) | ||
119 | #define VIDTCON0_VBPDE_MASK (0xff << 24) | 124 | #define VIDTCON0_VBPDE_MASK (0xff << 24) |
120 | #define VIDTCON0_VBPDE_SHIFT (24) | 125 | #define VIDTCON0_VBPDE_SHIFT (24) |
121 | #define VIDTCON0_VBPDE_LIMIT (0xff) | 126 | #define VIDTCON0_VBPDE_LIMIT (0xff) |
@@ -138,6 +143,7 @@ | |||
138 | 143 | ||
139 | /* VIDTCON1 */ | 144 | /* VIDTCON1 */ |
140 | 145 | ||
146 | #define VIDTCON1 (0x14) | ||
141 | #define VIDTCON1_VFPDE_MASK (0xff << 24) | 147 | #define VIDTCON1_VFPDE_MASK (0xff << 24) |
142 | #define VIDTCON1_VFPDE_SHIFT (24) | 148 | #define VIDTCON1_VFPDE_SHIFT (24) |
143 | #define VIDTCON1_VFPDE_LIMIT (0xff) | 149 | #define VIDTCON1_VFPDE_LIMIT (0xff) |
@@ -159,6 +165,7 @@ | |||
159 | #define VIDTCON1_HSPW(_x) ((_x) << 0) | 165 | #define VIDTCON1_HSPW(_x) ((_x) << 0) |
160 | 166 | ||
161 | #define VIDTCON2 (0x18) | 167 | #define VIDTCON2 (0x18) |
168 | #define VIDTCON2 (0x18) | ||
162 | #define VIDTCON2_LINEVAL_E(_x) ((((_x) & 0x800) >> 11) << 23) | 169 | #define VIDTCON2_LINEVAL_E(_x) ((((_x) & 0x800) >> 11) << 23) |
163 | #define VIDTCON2_LINEVAL_MASK (0x7ff << 11) | 170 | #define VIDTCON2_LINEVAL_MASK (0x7ff << 11) |
164 | #define VIDTCON2_LINEVAL_SHIFT (11) | 171 | #define VIDTCON2_LINEVAL_SHIFT (11) |
@@ -173,18 +180,27 @@ | |||
173 | 180 | ||
174 | /* WINCONx */ | 181 | /* WINCONx */ |
175 | 182 | ||
176 | 183 | #define WINCON(_win) (0x20 + ((_win) * 4)) | |
184 | #define WINCONx_CSCWIDTH_MASK (0x3 << 26) | ||
185 | #define WINCONx_CSCWIDTH_SHIFT (26) | ||
186 | #define WINCONx_CSCWIDTH_WIDE (0x0 << 26) | ||
187 | #define WINCONx_CSCWIDTH_NARROW (0x3 << 26) | ||
188 | #define WINCONx_ENLOCAL (1 << 22) | ||
189 | #define WINCONx_BUFSTATUS (1 << 21) | ||
190 | #define WINCONx_BUFSEL (1 << 20) | ||
191 | #define WINCONx_BUFAUTOEN (1 << 19) | ||
177 | #define WINCONx_BITSWP (1 << 18) | 192 | #define WINCONx_BITSWP (1 << 18) |
178 | #define WINCONx_BYTSWP (1 << 17) | 193 | #define WINCONx_BYTSWP (1 << 17) |
179 | #define WINCONx_HAWSWP (1 << 16) | 194 | #define WINCONx_HAWSWP (1 << 16) |
180 | #define WINCONx_WSWP (1 << 15) | 195 | #define WINCONx_WSWP (1 << 15) |
196 | #define WINCONx_YCbCr (1 << 13) | ||
181 | #define WINCONx_BURSTLEN_MASK (0x3 << 9) | 197 | #define WINCONx_BURSTLEN_MASK (0x3 << 9) |
182 | #define WINCONx_BURSTLEN_SHIFT (9) | 198 | #define WINCONx_BURSTLEN_SHIFT (9) |
183 | #define WINCONx_BURSTLEN_16WORD (0x0 << 9) | 199 | #define WINCONx_BURSTLEN_16WORD (0x0 << 9) |
184 | #define WINCONx_BURSTLEN_8WORD (0x1 << 9) | 200 | #define WINCONx_BURSTLEN_8WORD (0x1 << 9) |
185 | #define WINCONx_BURSTLEN_4WORD (0x2 << 9) | 201 | #define WINCONx_BURSTLEN_4WORD (0x2 << 9) |
186 | |||
187 | #define WINCONx_ENWIN (1 << 0) | 202 | #define WINCONx_ENWIN (1 << 0) |
203 | |||
188 | #define WINCON0_BPPMODE_MASK (0xf << 2) | 204 | #define WINCON0_BPPMODE_MASK (0xf << 2) |
189 | #define WINCON0_BPPMODE_SHIFT (2) | 205 | #define WINCON0_BPPMODE_SHIFT (2) |
190 | #define WINCON0_BPPMODE_1BPP (0x0 << 2) | 206 | #define WINCON0_BPPMODE_1BPP (0x0 << 2) |
@@ -196,9 +212,8 @@ | |||
196 | #define WINCON0_BPPMODE_18BPP_666 (0x8 << 2) | 212 | #define WINCON0_BPPMODE_18BPP_666 (0x8 << 2) |
197 | #define WINCON0_BPPMODE_24BPP_888 (0xb << 2) | 213 | #define WINCON0_BPPMODE_24BPP_888 (0xb << 2) |
198 | 214 | ||
215 | #define WINCON1_LOCALSEL_CAMIF (1 << 23) | ||
199 | #define WINCON1_BLD_PIX (1 << 6) | 216 | #define WINCON1_BLD_PIX (1 << 6) |
200 | |||
201 | #define WINCON1_ALPHA_SEL (1 << 1) | ||
202 | #define WINCON1_BPPMODE_MASK (0xf << 2) | 217 | #define WINCON1_BPPMODE_MASK (0xf << 2) |
203 | #define WINCON1_BPPMODE_SHIFT (2) | 218 | #define WINCON1_BPPMODE_SHIFT (2) |
204 | #define WINCON1_BPPMODE_1BPP (0x0 << 2) | 219 | #define WINCON1_BPPMODE_1BPP (0x0 << 2) |
@@ -216,6 +231,7 @@ | |||
216 | #define WINCON1_BPPMODE_24BPP_A1887 (0xc << 2) | 231 | #define WINCON1_BPPMODE_24BPP_A1887 (0xc << 2) |
217 | #define WINCON1_BPPMODE_25BPP_A1888 (0xd << 2) | 232 | #define WINCON1_BPPMODE_25BPP_A1888 (0xd << 2) |
218 | #define WINCON1_BPPMODE_28BPP_A4888 (0xd << 2) | 233 | #define WINCON1_BPPMODE_28BPP_A4888 (0xd << 2) |
234 | #define WINCON1_ALPHA_SEL (1 << 1) | ||
219 | 235 | ||
220 | /* S5PV210 */ | 236 | /* S5PV210 */ |
221 | #define SHADOWCON (0x34) | 237 | #define SHADOWCON (0x34) |
@@ -225,6 +241,9 @@ | |||
225 | /* Local input channels (windows 0-2) */ | 241 | /* Local input channels (windows 0-2) */ |
226 | #define SHADOWCON_CHx_LOCAL_ENABLE(_win) (1 << (5 + (_win))) | 242 | #define SHADOWCON_CHx_LOCAL_ENABLE(_win) (1 << (5 + (_win))) |
227 | 243 | ||
244 | /* VIDOSDx */ | ||
245 | |||
246 | #define VIDOSD_BASE (0x40) | ||
228 | #define VIDOSDxA_TOPLEFT_X_E(_x) ((((_x) & 0x800) >> 11) << 23) | 247 | #define VIDOSDxA_TOPLEFT_X_E(_x) ((((_x) & 0x800) >> 11) << 23) |
229 | #define VIDOSDxA_TOPLEFT_X_MASK (0x7ff << 11) | 248 | #define VIDOSDxA_TOPLEFT_X_MASK (0x7ff << 11) |
230 | #define VIDOSDxA_TOPLEFT_X_SHIFT (11) | 249 | #define VIDOSDxA_TOPLEFT_X_SHIFT (11) |
@@ -293,6 +312,7 @@ | |||
293 | 312 | ||
294 | /* Interrupt controls and status */ | 313 | /* Interrupt controls and status */ |
295 | 314 | ||
315 | #define VIDINTCON0 (0x130) | ||
296 | #define VIDINTCON0_FIFOINTERVAL_MASK (0x3f << 20) | 316 | #define VIDINTCON0_FIFOINTERVAL_MASK (0x3f << 20) |
297 | #define VIDINTCON0_FIFOINTERVAL_SHIFT (20) | 317 | #define VIDINTCON0_FIFOINTERVAL_SHIFT (20) |
298 | #define VIDINTCON0_FIFOINTERVAL_LIMIT (0x3f) | 318 | #define VIDINTCON0_FIFOINTERVAL_LIMIT (0x3f) |
@@ -321,6 +341,9 @@ | |||
321 | #define VIDINTCON0_FIFIOSEL_SHIFT (5) | 341 | #define VIDINTCON0_FIFIOSEL_SHIFT (5) |
322 | #define VIDINTCON0_FIFIOSEL_WINDOW0 (0x1 << 5) | 342 | #define VIDINTCON0_FIFIOSEL_WINDOW0 (0x1 << 5) |
323 | #define VIDINTCON0_FIFIOSEL_WINDOW1 (0x2 << 5) | 343 | #define VIDINTCON0_FIFIOSEL_WINDOW1 (0x2 << 5) |
344 | #define VIDINTCON0_FIFIOSEL_WINDOW2 (0x10 << 5) | ||
345 | #define VIDINTCON0_FIFIOSEL_WINDOW3 (0x20 << 5) | ||
346 | #define VIDINTCON0_FIFIOSEL_WINDOW4 (0x40 << 5) | ||
324 | 347 | ||
325 | #define VIDINTCON0_FIFOLEVEL_MASK (0x7 << 2) | 348 | #define VIDINTCON0_FIFOLEVEL_MASK (0x7 << 2) |
326 | #define VIDINTCON0_FIFOLEVEL_SHIFT (2) | 349 | #define VIDINTCON0_FIFOLEVEL_SHIFT (2) |
@@ -357,16 +380,39 @@ | |||
357 | #define WxKEYCON1_COLVAL_LIMIT (0xffffff) | 380 | #define WxKEYCON1_COLVAL_LIMIT (0xffffff) |
358 | #define WxKEYCON1_COLVAL(_x) ((_x) << 0) | 381 | #define WxKEYCON1_COLVAL(_x) ((_x) << 0) |
359 | 382 | ||
383 | /* Dithering control */ | ||
384 | #define DITHMODE (0x170) | ||
385 | #define DITHMODE_R_POS_MASK (0x3 << 5) | ||
386 | #define DITHMODE_R_POS_SHIFT (5) | ||
387 | #define DITHMODE_R_POS_8BIT (0x0 << 5) | ||
388 | #define DITHMODE_R_POS_6BIT (0x1 << 5) | ||
389 | #define DITHMODE_R_POS_5BIT (0x2 << 5) | ||
390 | #define DITHMODE_G_POS_MASK (0x3 << 3) | ||
391 | #define DITHMODE_G_POS_SHIFT (3) | ||
392 | #define DITHMODE_G_POS_8BIT (0x0 << 3) | ||
393 | #define DITHMODE_G_POS_6BIT (0x1 << 3) | ||
394 | #define DITHMODE_G_POS_5BIT (0x2 << 3) | ||
395 | #define DITHMODE_B_POS_MASK (0x3 << 1) | ||
396 | #define DITHMODE_B_POS_SHIFT (1) | ||
397 | #define DITHMODE_B_POS_8BIT (0x0 << 1) | ||
398 | #define DITHMODE_B_POS_6BIT (0x1 << 1) | ||
399 | #define DITHMODE_B_POS_5BIT (0x2 << 1) | ||
400 | #define DITHMODE_DITH_EN (1 << 0) | ||
360 | 401 | ||
361 | /* Window blanking (MAP) */ | 402 | /* Window blanking (MAP) */ |
362 | 403 | #define WINxMAP(_win) (0x180 + ((_win) * 4)) | |
363 | #define WINxMAP_MAP (1 << 24) | 404 | #define WINxMAP_MAP (1 << 24) |
364 | #define WINxMAP_MAP_COLOUR_MASK (0xffffff << 0) | 405 | #define WINxMAP_MAP_COLOUR_MASK (0xffffff << 0) |
365 | #define WINxMAP_MAP_COLOUR_SHIFT (0) | 406 | #define WINxMAP_MAP_COLOUR_SHIFT (0) |
366 | #define WINxMAP_MAP_COLOUR_LIMIT (0xffffff) | 407 | #define WINxMAP_MAP_COLOUR_LIMIT (0xffffff) |
367 | #define WINxMAP_MAP_COLOUR(_x) ((_x) << 0) | 408 | #define WINxMAP_MAP_COLOUR(_x) ((_x) << 0) |
368 | 409 | ||
410 | /* Winodw palette control */ | ||
411 | #define WPALCON (0x1A0) | ||
369 | #define WPALCON_PAL_UPDATE (1 << 9) | 412 | #define WPALCON_PAL_UPDATE (1 << 9) |
413 | #define WPALCON_W4PAL_16BPP_A555 (1 << 8) | ||
414 | #define WPALCON_W3PAL_16BPP_A555 (1 << 7) | ||
415 | #define WPALCON_W2PAL_16BPP_A555 (1 << 6) | ||
370 | #define WPALCON_W1PAL_MASK (0x7 << 3) | 416 | #define WPALCON_W1PAL_MASK (0x7 << 3) |
371 | #define WPALCON_W1PAL_SHIFT (3) | 417 | #define WPALCON_W1PAL_SHIFT (3) |
372 | #define WPALCON_W1PAL_25BPP_A888 (0x0 << 3) | 418 | #define WPALCON_W1PAL_25BPP_A888 (0x0 << 3) |
@@ -376,7 +422,6 @@ | |||
376 | #define WPALCON_W1PAL_18BPP (0x4 << 3) | 422 | #define WPALCON_W1PAL_18BPP (0x4 << 3) |
377 | #define WPALCON_W1PAL_16BPP_A555 (0x5 << 3) | 423 | #define WPALCON_W1PAL_16BPP_A555 (0x5 << 3) |
378 | #define WPALCON_W1PAL_16BPP_565 (0x6 << 3) | 424 | #define WPALCON_W1PAL_16BPP_565 (0x6 << 3) |
379 | |||
380 | #define WPALCON_W0PAL_MASK (0x7 << 0) | 425 | #define WPALCON_W0PAL_MASK (0x7 << 0) |
381 | #define WPALCON_W0PAL_SHIFT (0) | 426 | #define WPALCON_W0PAL_SHIFT (0) |
382 | #define WPALCON_W0PAL_25BPP_A888 (0x0 << 0) | 427 | #define WPALCON_W0PAL_25BPP_A888 (0x0 << 0) |
@@ -394,115 +439,6 @@ | |||
394 | #define BLENDCON_NEW_4BIT_ALPHA_VALUE (0 << 0) | 439 | #define BLENDCON_NEW_4BIT_ALPHA_VALUE (0 << 0) |
395 | 440 | ||
396 | #define S3C_FB_MAX_WIN (5) /* number of hardware windows available. */ | 441 | #define S3C_FB_MAX_WIN (5) /* number of hardware windows available. */ |
397 | #define VIDCON1_FSTATUS_EVEN (1 << 15) | ||
398 | |||
399 | /* Video timing controls */ | ||
400 | #define VIDTCON0 (0x10) | ||
401 | #define VIDTCON1 (0x14) | ||
402 | #define VIDTCON2 (0x18) | ||
403 | |||
404 | /* Window position controls */ | ||
405 | |||
406 | #define WINCON(_win) (0x20 + ((_win) * 4)) | ||
407 | |||
408 | /* OSD1 and OSD4 do not have register D */ | ||
409 | |||
410 | #define VIDOSD_BASE (0x40) | ||
411 | |||
412 | #define VIDINTCON0 (0x130) | ||
413 | |||
414 | /* WINCONx */ | ||
415 | |||
416 | #define WINCONx_CSCWIDTH_MASK (0x3 << 26) | ||
417 | #define WINCONx_CSCWIDTH_SHIFT (26) | ||
418 | #define WINCONx_CSCWIDTH_WIDE (0x0 << 26) | ||
419 | #define WINCONx_CSCWIDTH_NARROW (0x3 << 26) | ||
420 | |||
421 | #define WINCONx_ENLOCAL (1 << 22) | ||
422 | #define WINCONx_BUFSTATUS (1 << 21) | ||
423 | #define WINCONx_BUFSEL (1 << 20) | ||
424 | #define WINCONx_BUFAUTOEN (1 << 19) | ||
425 | #define WINCONx_YCbCr (1 << 13) | ||
426 | |||
427 | #define WINCON1_LOCALSEL_CAMIF (1 << 23) | ||
428 | |||
429 | #define WINCON2_LOCALSEL_CAMIF (1 << 23) | ||
430 | #define WINCON2_BLD_PIX (1 << 6) | ||
431 | |||
432 | #define WINCON2_ALPHA_SEL (1 << 1) | ||
433 | #define WINCON2_BPPMODE_MASK (0xf << 2) | ||
434 | #define WINCON2_BPPMODE_SHIFT (2) | ||
435 | #define WINCON2_BPPMODE_1BPP (0x0 << 2) | ||
436 | #define WINCON2_BPPMODE_2BPP (0x1 << 2) | ||
437 | #define WINCON2_BPPMODE_4BPP (0x2 << 2) | ||
438 | #define WINCON2_BPPMODE_8BPP_1232 (0x4 << 2) | ||
439 | #define WINCON2_BPPMODE_16BPP_565 (0x5 << 2) | ||
440 | #define WINCON2_BPPMODE_16BPP_A1555 (0x6 << 2) | ||
441 | #define WINCON2_BPPMODE_16BPP_I1555 (0x7 << 2) | ||
442 | #define WINCON2_BPPMODE_18BPP_666 (0x8 << 2) | ||
443 | #define WINCON2_BPPMODE_18BPP_A1665 (0x9 << 2) | ||
444 | #define WINCON2_BPPMODE_19BPP_A1666 (0xa << 2) | ||
445 | #define WINCON2_BPPMODE_24BPP_888 (0xb << 2) | ||
446 | #define WINCON2_BPPMODE_24BPP_A1887 (0xc << 2) | ||
447 | #define WINCON2_BPPMODE_25BPP_A1888 (0xd << 2) | ||
448 | #define WINCON2_BPPMODE_28BPP_A4888 (0xd << 2) | ||
449 | |||
450 | #define WINCON3_BLD_PIX (1 << 6) | ||
451 | |||
452 | #define WINCON3_ALPHA_SEL (1 << 1) | ||
453 | #define WINCON3_BPPMODE_MASK (0xf << 2) | ||
454 | #define WINCON3_BPPMODE_SHIFT (2) | ||
455 | #define WINCON3_BPPMODE_1BPP (0x0 << 2) | ||
456 | #define WINCON3_BPPMODE_2BPP (0x1 << 2) | ||
457 | #define WINCON3_BPPMODE_4BPP (0x2 << 2) | ||
458 | #define WINCON3_BPPMODE_16BPP_565 (0x5 << 2) | ||
459 | #define WINCON3_BPPMODE_16BPP_A1555 (0x6 << 2) | ||
460 | #define WINCON3_BPPMODE_16BPP_I1555 (0x7 << 2) | ||
461 | #define WINCON3_BPPMODE_18BPP_666 (0x8 << 2) | ||
462 | #define WINCON3_BPPMODE_18BPP_A1665 (0x9 << 2) | ||
463 | #define WINCON3_BPPMODE_19BPP_A1666 (0xa << 2) | ||
464 | #define WINCON3_BPPMODE_24BPP_888 (0xb << 2) | ||
465 | #define WINCON3_BPPMODE_24BPP_A1887 (0xc << 2) | ||
466 | #define WINCON3_BPPMODE_25BPP_A1888 (0xd << 2) | ||
467 | #define WINCON3_BPPMODE_28BPP_A4888 (0xd << 2) | ||
468 | |||
469 | #define VIDINTCON0_FIFIOSEL_WINDOW2 (0x10 << 5) | ||
470 | #define VIDINTCON0_FIFIOSEL_WINDOW3 (0x20 << 5) | ||
471 | #define VIDINTCON0_FIFIOSEL_WINDOW4 (0x40 << 5) | ||
472 | |||
473 | #define DITHMODE (0x170) | ||
474 | #define WINxMAP(_win) (0x180 + ((_win) * 4)) | ||
475 | |||
476 | |||
477 | #define DITHMODE_R_POS_MASK (0x3 << 5) | ||
478 | #define DITHMODE_R_POS_SHIFT (5) | ||
479 | #define DITHMODE_R_POS_8BIT (0x0 << 5) | ||
480 | #define DITHMODE_R_POS_6BIT (0x1 << 5) | ||
481 | #define DITHMODE_R_POS_5BIT (0x2 << 5) | ||
482 | |||
483 | #define DITHMODE_G_POS_MASK (0x3 << 3) | ||
484 | #define DITHMODE_G_POS_SHIFT (3) | ||
485 | #define DITHMODE_G_POS_8BIT (0x0 << 3) | ||
486 | #define DITHMODE_G_POS_6BIT (0x1 << 3) | ||
487 | #define DITHMODE_G_POS_5BIT (0x2 << 3) | ||
488 | |||
489 | #define DITHMODE_B_POS_MASK (0x3 << 1) | ||
490 | #define DITHMODE_B_POS_SHIFT (1) | ||
491 | #define DITHMODE_B_POS_8BIT (0x0 << 1) | ||
492 | #define DITHMODE_B_POS_6BIT (0x1 << 1) | ||
493 | #define DITHMODE_B_POS_5BIT (0x2 << 1) | ||
494 | |||
495 | #define DITHMODE_DITH_EN (1 << 0) | ||
496 | |||
497 | #define WPALCON (0x1A0) | ||
498 | |||
499 | /* Palette control */ | ||
500 | /* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L), | ||
501 | * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */ | ||
502 | #define WPALCON_W4PAL_16BPP_A555 (1 << 8) | ||
503 | #define WPALCON_W3PAL_16BPP_A555 (1 << 7) | ||
504 | #define WPALCON_W2PAL_16BPP_A555 (1 << 6) | ||
505 | |||
506 | 442 | ||
507 | /* Notes on per-window bpp settings | 443 | /* Notes on per-window bpp settings |
508 | * | 444 | * |
diff --git a/include/video/sh_mipi_dsi.h b/include/video/sh_mipi_dsi.h index 06c67fbc4eee..a01f197e6ac1 100644 --- a/include/video/sh_mipi_dsi.h +++ b/include/video/sh_mipi_dsi.h | |||
@@ -25,8 +25,6 @@ enum sh_mipi_dsi_data_fmt { | |||
25 | MIPI_YUV420, | 25 | MIPI_YUV420, |
26 | }; | 26 | }; |
27 | 27 | ||
28 | struct sh_mobile_lcdc_chan_cfg; | ||
29 | |||
30 | #define SH_MIPI_DSI_HSABM (1 << 0) | 28 | #define SH_MIPI_DSI_HSABM (1 << 0) |
31 | #define SH_MIPI_DSI_HBPBM (1 << 1) | 29 | #define SH_MIPI_DSI_HBPBM (1 << 1) |
32 | #define SH_MIPI_DSI_HFPBM (1 << 2) | 30 | #define SH_MIPI_DSI_HFPBM (1 << 2) |
@@ -47,7 +45,7 @@ struct sh_mobile_lcdc_chan_cfg; | |||
47 | 45 | ||
48 | struct sh_mipi_dsi_info { | 46 | struct sh_mipi_dsi_info { |
49 | enum sh_mipi_dsi_data_fmt data_format; | 47 | enum sh_mipi_dsi_data_fmt data_format; |
50 | struct sh_mobile_lcdc_chan_cfg *lcd_chan; | 48 | int channel; |
51 | int lane; | 49 | int lane; |
52 | unsigned long flags; | 50 | unsigned long flags; |
53 | u32 clksrc; | 51 | u32 clksrc; |
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h index ff43ffc1aab2..2605fa8adb9c 100644 --- a/include/video/sh_mobile_lcdc.h +++ b/include/video/sh_mobile_lcdc.h | |||
@@ -163,7 +163,6 @@ struct sh_mobile_lcdc_bl_info { | |||
163 | const char *name; | 163 | const char *name; |
164 | int max_brightness; | 164 | int max_brightness; |
165 | int (*set_brightness)(int brightness); | 165 | int (*set_brightness)(int brightness); |
166 | int (*get_brightness)(void); | ||
167 | }; | 166 | }; |
168 | 167 | ||
169 | struct sh_mobile_lcdc_overlay_cfg { | 168 | struct sh_mobile_lcdc_overlay_cfg { |