diff options
author | Dave Airlie <airlied@redhat.com> | 2016-05-04 03:37:20 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-05-04 03:37:20 -0400 |
commit | 00c1beab15df9216cf39818a437b34f296423ac4 (patch) | |
tree | bdd83f80022f4c921853c92e46193cb9c873eab1 | |
parent | acff058f8625022bbc37a3521f8208810a42c4ef (diff) | |
parent | b5bf0f1ea3658254bd72ef64abc97786e8a32255 (diff) |
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next
Summary:
- Support for pipeline clock between KMS drivers.
. Exynos SoC is required to control clocks across KMS drivers
according to Exynos SoC version. So this patch refactos
some relevant codes and provides generic solution for it.
- Add Exynos5433 SoC support to HDMI parts - HDMI and DECON-TV.
- Add HW trigger mode support to CRTC drivers.
. In case of using i80 Panel, some Exynos SoC supports HW trigger
mode so this patch makes trigger mode - HW or SW trigger - to be
set according to SoC version properly.
- And some cleanups and regression fixups.
* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: (39 commits)
drm/exynos: clean up register definions for fimd and decon
drm/exynos: decon: clean up interface type
drm/exynos: fimd: add HW trigger support
drm/exynos: clean up wait_for_vblank
drm/exynos: mixer: use generic of_device_get_match_data helper
drm/exynos: mixer: remove support for non-dt platforms
drm/exynos: hdmi: use generic of_device_get_match_data helper
drm/exynos: rotator: use generic of_device_get_match_data helper
drm/exynos: fimd: use generic of_device_get_match_data helper
drm/exynos: dsi: use generic of_device_get_match_data helper
drm/exynos: exynos5433_decon: use generic of_device_get_match_data helper
drm/exynos: convert clock_enable crtc callback to pipeline clock
drm/exynos/mixer: enable HDMI-PHY before configuring MIXER
drm/exynos/decon5433: enable HDMI-PHY before configuring DECON
drm/exynos: add support for pipeline clock to the framework
drm/exynos: add helper to get crtc from pipe
drm/exynos/decon5433: do not protect window in plane disable
drm/exynos/decon5433: reset decon on start
drm/exynos/decon5433: fix DECON standalone update
drm/exynos/hdmi: remove registry dump
...
22 files changed, 572 insertions, 623 deletions
diff --git a/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt b/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt index 377afbf5122a..c9fd7b3807e7 100644 --- a/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt +++ b/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt | |||
@@ -5,7 +5,8 @@ Exynos series of SoCs which transfers the image data from a video memory | |||
5 | buffer to an external LCD interface. | 5 | buffer to an external LCD interface. |
6 | 6 | ||
7 | Required properties: | 7 | Required properties: |
8 | - compatible: value should be "samsung,exynos5433-decon"; | 8 | - compatible: value should be one of: |
9 | "samsung,exynos5433-decon", "samsung,exynos5433-decon-tv"; | ||
9 | - reg: physical base address and length of the DECON registers set. | 10 | - reg: physical base address and length of the DECON registers set. |
10 | - interrupts: should contain a list of all DECON IP block interrupts in the | 11 | - interrupts: should contain a list of all DECON IP block interrupts in the |
11 | order: VSYNC, LCD_SYSTEM. The interrupt specifier format | 12 | order: VSYNC, LCD_SYSTEM. The interrupt specifier format |
@@ -16,7 +17,7 @@ Required properties: | |||
16 | - clocks: must include clock specifiers corresponding to entries in the | 17 | - clocks: must include clock specifiers corresponding to entries in the |
17 | clock-names property. | 18 | clock-names property. |
18 | - clock-names: list of clock names sorted in the same order as the clocks | 19 | - clock-names: list of clock names sorted in the same order as the clocks |
19 | property. Must contain "aclk_decon", "aclk_smmu_decon0x", | 20 | property. Must contain "pclk", "aclk_decon", "aclk_smmu_decon0x", |
20 | "aclk_xiu_decon0x", "pclk_smmu_decon0x", clk_decon_vclk", | 21 | "aclk_xiu_decon0x", "pclk_smmu_decon0x", clk_decon_vclk", |
21 | "sclk_decon_eclk" | 22 | "sclk_decon_eclk" |
22 | - ports: contains a port which is connected to mic node. address-cells and | 23 | - ports: contains a port which is connected to mic node. address-cells and |
diff --git a/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt b/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt index d474f59be6d6..a2ec4c1c9382 100644 --- a/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt +++ b/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt | |||
@@ -5,6 +5,7 @@ Required properties: | |||
5 | 1) "samsung,exynos4210-hdmi" | 5 | 1) "samsung,exynos4210-hdmi" |
6 | 2) "samsung,exynos4212-hdmi" | 6 | 2) "samsung,exynos4212-hdmi" |
7 | 3) "samsung,exynos5420-hdmi" | 7 | 3) "samsung,exynos5420-hdmi" |
8 | 4) "samsung,exynos5433-hdmi" | ||
8 | - reg: physical base address of the hdmi and length of memory mapped | 9 | - reg: physical base address of the hdmi and length of memory mapped |
9 | region. | 10 | region. |
10 | - interrupts: interrupt number to the cpu. | 11 | - interrupts: interrupt number to the cpu. |
@@ -12,6 +13,11 @@ Required properties: | |||
12 | a) phandle of the gpio controller node. | 13 | a) phandle of the gpio controller node. |
13 | b) pin number within the gpio controller. | 14 | b) pin number within the gpio controller. |
14 | c) optional flags and pull up/down. | 15 | c) optional flags and pull up/down. |
16 | - ddc: phandle to the hdmi ddc node | ||
17 | - phy: phandle to the hdmi phy node | ||
18 | - samsung,syscon-phandle: phandle for system controller node for PMU. | ||
19 | |||
20 | Required properties for Exynos 4210, 4212, 5420 and 5433: | ||
15 | - clocks: list of clock IDs from SoC clock driver. | 21 | - clocks: list of clock IDs from SoC clock driver. |
16 | a) hdmi: Gate of HDMI IP bus clock. | 22 | a) hdmi: Gate of HDMI IP bus clock. |
17 | b) sclk_hdmi: Gate of HDMI special clock. | 23 | b) sclk_hdmi: Gate of HDMI special clock. |
@@ -25,9 +31,24 @@ Required properties: | |||
25 | sclk_pixel. | 31 | sclk_pixel. |
26 | - clock-names: aliases as per driver requirements for above clock IDs: | 32 | - clock-names: aliases as per driver requirements for above clock IDs: |
27 | "hdmi", "sclk_hdmi", "sclk_pixel", "sclk_hdmiphy" and "mout_hdmi". | 33 | "hdmi", "sclk_hdmi", "sclk_pixel", "sclk_hdmiphy" and "mout_hdmi". |
28 | - ddc: phandle to the hdmi ddc node | 34 | |
29 | - phy: phandle to the hdmi phy node | 35 | Required properties for Exynos 5433: |
30 | - samsung,syscon-phandle: phandle for system controller node for PMU. | 36 | - clocks: list of clock specifiers according to common clock bindings. |
37 | a) hdmi_pclk: Gate of HDMI IP APB bus. | ||
38 | b) hdmi_i_pclk: Gate of HDMI-PHY IP APB bus. | ||
39 | d) i_tmds_clk: Gate of HDMI TMDS clock. | ||
40 | e) i_pixel_clk: Gate of HDMI pixel clock. | ||
41 | f) i_spdif_clk: Gate of HDMI SPDIF clock. | ||
42 | g) oscclk: Oscillator clock, used as parent of following *_user clocks | ||
43 | in case HDMI-PHY is not operational. | ||
44 | h) tmds_clko: TMDS clock generated by HDMI-PHY. | ||
45 | i) tmds_clko_user: MUX used to switch between oscclk and tmds_clko, | ||
46 | respectively if HDMI-PHY is off and operational. | ||
47 | j) pixel_clko: Pixel clock generated by HDMI-PHY. | ||
48 | k) pixel_clko_user: MUX used to switch between oscclk and pixel_clko, | ||
49 | respectively if HDMI-PHY is off and operational. | ||
50 | - clock-names: aliases for above clock specfiers. | ||
51 | - samsung,sysreg: handle to syscon used to control the system registers. | ||
31 | 52 | ||
32 | Example: | 53 | Example: |
33 | 54 | ||
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 2fadd8275fa5..d814b3048ee5 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig | |||
@@ -95,7 +95,7 @@ comment "Sub-drivers" | |||
95 | 95 | ||
96 | config DRM_EXYNOS_G2D | 96 | config DRM_EXYNOS_G2D |
97 | bool "G2D" | 97 | bool "G2D" |
98 | depends on !VIDEO_SAMSUNG_S5P_G2D | 98 | depends on VIDEO_SAMSUNG_S5P_G2D=n |
99 | select FRAME_VECTOR | 99 | select FRAME_VECTOR |
100 | help | 100 | help |
101 | Choose this option if you want to use Exynos G2D for DRM. | 101 | Choose this option if you want to use Exynos G2D for DRM. |
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile index 126b0a1915db..f663490e949d 100644 --- a/drivers/gpu/drm/exynos/Makefile +++ b/drivers/gpu/drm/exynos/Makefile | |||
@@ -2,10 +2,10 @@ | |||
2 | # Makefile for the drm device driver. This driver provides support for the | 2 | # Makefile for the drm device driver. This driver provides support for the |
3 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. | 3 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. |
4 | 4 | ||
5 | exynosdrm-y := exynos_drm_drv.o exynos_drm_crtc.o exynos_drm_fbdev.o \ | 5 | exynosdrm-y := exynos_drm_drv.o exynos_drm_crtc.o exynos_drm_fb.o \ |
6 | exynos_drm_fb.o exynos_drm_gem.o exynos_drm_core.o \ | 6 | exynos_drm_gem.o exynos_drm_core.o exynos_drm_plane.o |
7 | exynos_drm_plane.o | ||
8 | 7 | ||
8 | exynosdrm-$(CONFIG_DRM_FBDEV_EMULATION) += exynos_drm_fbdev.o | ||
9 | exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o | 9 | exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o |
10 | exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o | 10 | exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o |
11 | exynosdrm-$(CONFIG_DRM_EXYNOS5433_DECON) += exynos5433_drm_decon.o | 11 | exynosdrm-$(CONFIG_DRM_EXYNOS5433_DECON) += exynos5433_drm_decon.o |
diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 5245bc5e82e9..4ab5bfc23647 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c | |||
@@ -28,6 +28,10 @@ | |||
28 | #define WINDOWS_NR 3 | 28 | #define WINDOWS_NR 3 |
29 | #define MIN_FB_WIDTH_FOR_16WORD_BURST 128 | 29 | #define MIN_FB_WIDTH_FOR_16WORD_BURST 128 |
30 | 30 | ||
31 | #define IFTYPE_I80 (1 << 0) | ||
32 | #define I80_HW_TRG (1 << 1) | ||
33 | #define IFTYPE_HDMI (1 << 2) | ||
34 | |||
31 | static const char * const decon_clks_name[] = { | 35 | static const char * const decon_clks_name[] = { |
32 | "pclk", | 36 | "pclk", |
33 | "aclk_decon", | 37 | "aclk_decon", |
@@ -38,12 +42,6 @@ static const char * const decon_clks_name[] = { | |||
38 | "sclk_decon_eclk", | 42 | "sclk_decon_eclk", |
39 | }; | 43 | }; |
40 | 44 | ||
41 | enum decon_iftype { | ||
42 | IFTYPE_RGB, | ||
43 | IFTYPE_I80, | ||
44 | IFTYPE_HDMI | ||
45 | }; | ||
46 | |||
47 | enum decon_flag_bits { | 45 | enum decon_flag_bits { |
48 | BIT_CLKS_ENABLED, | 46 | BIT_CLKS_ENABLED, |
49 | BIT_IRQS_ENABLED, | 47 | BIT_IRQS_ENABLED, |
@@ -61,7 +59,7 @@ struct decon_context { | |||
61 | struct clk *clks[ARRAY_SIZE(decon_clks_name)]; | 59 | struct clk *clks[ARRAY_SIZE(decon_clks_name)]; |
62 | int pipe; | 60 | int pipe; |
63 | unsigned long flags; | 61 | unsigned long flags; |
64 | enum decon_iftype out_type; | 62 | unsigned long out_type; |
65 | int first_win; | 63 | int first_win; |
66 | }; | 64 | }; |
67 | 65 | ||
@@ -95,7 +93,7 @@ static int decon_enable_vblank(struct exynos_drm_crtc *crtc) | |||
95 | 93 | ||
96 | if (!test_and_set_bit(BIT_IRQS_ENABLED, &ctx->flags)) { | 94 | if (!test_and_set_bit(BIT_IRQS_ENABLED, &ctx->flags)) { |
97 | val = VIDINTCON0_INTEN; | 95 | val = VIDINTCON0_INTEN; |
98 | if (ctx->out_type == IFTYPE_I80) | 96 | if (ctx->out_type & IFTYPE_I80) |
99 | val |= VIDINTCON0_FRAMEDONE; | 97 | val |= VIDINTCON0_FRAMEDONE; |
100 | else | 98 | else |
101 | val |= VIDINTCON0_INTFRMEN; | 99 | val |= VIDINTCON0_INTFRMEN; |
@@ -119,11 +117,11 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc) | |||
119 | 117 | ||
120 | static void decon_setup_trigger(struct decon_context *ctx) | 118 | static void decon_setup_trigger(struct decon_context *ctx) |
121 | { | 119 | { |
122 | u32 val = (ctx->out_type != IFTYPE_HDMI) | 120 | u32 val = !(ctx->out_type & I80_HW_TRG) |
123 | ? TRIGCON_TRIGEN_PER_F | TRIGCON_TRIGEN_F | | 121 | ? TRIGCON_TRIGEN_PER_F | TRIGCON_TRIGEN_F | |
124 | TRIGCON_TE_AUTO_MASK | TRIGCON_SWTRIGEN | 122 | TRIGCON_TE_AUTO_MASK | TRIGCON_SWTRIGEN |
125 | : TRIGCON_TRIGEN_PER_F | TRIGCON_TRIGEN_F | | 123 | : TRIGCON_TRIGEN_PER_F | TRIGCON_TRIGEN_F | |
126 | TRIGCON_HWTRIGMASK_I80_RGB | TRIGCON_HWTRIGEN_I80_RGB; | 124 | TRIGCON_HWTRIGMASK | TRIGCON_HWTRIGEN; |
127 | writel(val, ctx->addr + DECON_TRIGCON); | 125 | writel(val, ctx->addr + DECON_TRIGCON); |
128 | } | 126 | } |
129 | 127 | ||
@@ -136,7 +134,7 @@ static void decon_commit(struct exynos_drm_crtc *crtc) | |||
136 | if (test_bit(BIT_SUSPENDED, &ctx->flags)) | 134 | if (test_bit(BIT_SUSPENDED, &ctx->flags)) |
137 | return; | 135 | return; |
138 | 136 | ||
139 | if (ctx->out_type == IFTYPE_HDMI) { | 137 | if (ctx->out_type & IFTYPE_HDMI) { |
140 | m->crtc_hsync_start = m->crtc_hdisplay + 10; | 138 | m->crtc_hsync_start = m->crtc_hdisplay + 10; |
141 | m->crtc_hsync_end = m->crtc_htotal - 92; | 139 | m->crtc_hsync_end = m->crtc_htotal - 92; |
142 | m->crtc_vsync_start = m->crtc_vdisplay + 1; | 140 | m->crtc_vsync_start = m->crtc_vdisplay + 1; |
@@ -151,17 +149,20 @@ static void decon_commit(struct exynos_drm_crtc *crtc) | |||
151 | 149 | ||
152 | /* lcd on and use command if */ | 150 | /* lcd on and use command if */ |
153 | val = VIDOUT_LCD_ON; | 151 | val = VIDOUT_LCD_ON; |
154 | if (ctx->out_type == IFTYPE_I80) | 152 | if (ctx->out_type & IFTYPE_I80) { |
155 | val |= VIDOUT_COMMAND_IF; | 153 | val |= VIDOUT_COMMAND_IF; |
156 | else | 154 | decon_setup_trigger(ctx); |
155 | } else { | ||
157 | val |= VIDOUT_RGB_IF; | 156 | val |= VIDOUT_RGB_IF; |
157 | } | ||
158 | |||
158 | writel(val, ctx->addr + DECON_VIDOUTCON0); | 159 | writel(val, ctx->addr + DECON_VIDOUTCON0); |
159 | 160 | ||
160 | val = VIDTCON2_LINEVAL(m->vdisplay - 1) | | 161 | val = VIDTCON2_LINEVAL(m->vdisplay - 1) | |
161 | VIDTCON2_HOZVAL(m->hdisplay - 1); | 162 | VIDTCON2_HOZVAL(m->hdisplay - 1); |
162 | writel(val, ctx->addr + DECON_VIDTCON2); | 163 | writel(val, ctx->addr + DECON_VIDTCON2); |
163 | 164 | ||
164 | if (ctx->out_type != IFTYPE_I80) { | 165 | if (!(ctx->out_type & IFTYPE_I80)) { |
165 | val = VIDTCON00_VBPD_F( | 166 | val = VIDTCON00_VBPD_F( |
166 | m->crtc_vtotal - m->crtc_vsync_end - 1) | | 167 | m->crtc_vtotal - m->crtc_vsync_end - 1) | |
167 | VIDTCON00_VFPD_F( | 168 | VIDTCON00_VFPD_F( |
@@ -183,10 +184,10 @@ static void decon_commit(struct exynos_drm_crtc *crtc) | |||
183 | writel(val, ctx->addr + DECON_VIDTCON11); | 184 | writel(val, ctx->addr + DECON_VIDTCON11); |
184 | } | 185 | } |
185 | 186 | ||
186 | decon_setup_trigger(ctx); | ||
187 | |||
188 | /* enable output and display signal */ | 187 | /* enable output and display signal */ |
189 | decon_set_bits(ctx, DECON_VIDCON0, VIDCON0_ENVID | VIDCON0_ENVID_F, ~0); | 188 | decon_set_bits(ctx, DECON_VIDCON0, VIDCON0_ENVID | VIDCON0_ENVID_F, ~0); |
189 | |||
190 | decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); | ||
190 | } | 191 | } |
191 | 192 | ||
192 | static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, | 193 | static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, |
@@ -300,7 +301,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, | |||
300 | val = dma_addr + pitch * state->src.h; | 301 | val = dma_addr + pitch * state->src.h; |
301 | writel(val, ctx->addr + DECON_VIDW0xADD1B0(win)); | 302 | writel(val, ctx->addr + DECON_VIDW0xADD1B0(win)); |
302 | 303 | ||
303 | if (ctx->out_type != IFTYPE_HDMI) | 304 | if (!(ctx->out_type & IFTYPE_HDMI)) |
304 | val = BIT_VAL(pitch - state->crtc.w * bpp, 27, 14) | 305 | val = BIT_VAL(pitch - state->crtc.w * bpp, 27, 14) |
305 | | BIT_VAL(state->crtc.w * bpp, 13, 0); | 306 | | BIT_VAL(state->crtc.w * bpp, 13, 0); |
306 | else | 307 | else |
@@ -312,9 +313,6 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, | |||
312 | 313 | ||
313 | /* window enable */ | 314 | /* window enable */ |
314 | decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, ~0); | 315 | decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, ~0); |
315 | |||
316 | /* standalone update */ | ||
317 | decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); | ||
318 | } | 316 | } |
319 | 317 | ||
320 | static void decon_disable_plane(struct exynos_drm_crtc *crtc, | 318 | static void decon_disable_plane(struct exynos_drm_crtc *crtc, |
@@ -326,15 +324,7 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc, | |||
326 | if (test_bit(BIT_SUSPENDED, &ctx->flags)) | 324 | if (test_bit(BIT_SUSPENDED, &ctx->flags)) |
327 | return; | 325 | return; |
328 | 326 | ||
329 | decon_shadow_protect_win(ctx, win, true); | ||
330 | |||
331 | /* window disable */ | ||
332 | decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, 0); | 327 | decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, 0); |
333 | |||
334 | decon_shadow_protect_win(ctx, win, false); | ||
335 | |||
336 | /* standalone update */ | ||
337 | decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); | ||
338 | } | 328 | } |
339 | 329 | ||
340 | static void decon_atomic_flush(struct exynos_drm_crtc *crtc) | 330 | static void decon_atomic_flush(struct exynos_drm_crtc *crtc) |
@@ -348,7 +338,10 @@ static void decon_atomic_flush(struct exynos_drm_crtc *crtc) | |||
348 | for (i = ctx->first_win; i < WINDOWS_NR; i++) | 338 | for (i = ctx->first_win; i < WINDOWS_NR; i++) |
349 | decon_shadow_protect_win(ctx, i, false); | 339 | decon_shadow_protect_win(ctx, i, false); |
350 | 340 | ||
351 | if (ctx->out_type == IFTYPE_I80) | 341 | /* standalone update */ |
342 | decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); | ||
343 | |||
344 | if (ctx->out_type & IFTYPE_I80) | ||
352 | set_bit(BIT_WIN_UPDATED, &ctx->flags); | 345 | set_bit(BIT_WIN_UPDATED, &ctx->flags); |
353 | } | 346 | } |
354 | 347 | ||
@@ -374,7 +367,7 @@ static void decon_swreset(struct decon_context *ctx) | |||
374 | 367 | ||
375 | WARN(tries == 0, "failed to software reset DECON\n"); | 368 | WARN(tries == 0, "failed to software reset DECON\n"); |
376 | 369 | ||
377 | if (ctx->out_type != IFTYPE_HDMI) | 370 | if (!(ctx->out_type & IFTYPE_HDMI)) |
378 | return; | 371 | return; |
379 | 372 | ||
380 | writel(VIDCON0_CLKVALUP | VIDCON0_VLCKFREE, ctx->addr + DECON_VIDCON0); | 373 | writel(VIDCON0_CLKVALUP | VIDCON0_VLCKFREE, ctx->addr + DECON_VIDCON0); |
@@ -383,7 +376,9 @@ static void decon_swreset(struct decon_context *ctx) | |||
383 | writel(VIDCON1_VCLK_RUN_VDEN_DISABLE, ctx->addr + DECON_VIDCON1); | 376 | writel(VIDCON1_VCLK_RUN_VDEN_DISABLE, ctx->addr + DECON_VIDCON1); |
384 | writel(CRCCTRL_CRCEN | CRCCTRL_CRCSTART_F | CRCCTRL_CRCCLKEN, | 377 | writel(CRCCTRL_CRCEN | CRCCTRL_CRCSTART_F | CRCCTRL_CRCCLKEN, |
385 | ctx->addr + DECON_CRCCTRL); | 378 | ctx->addr + DECON_CRCCTRL); |
386 | decon_setup_trigger(ctx); | 379 | |
380 | if (ctx->out_type & IFTYPE_I80) | ||
381 | decon_setup_trigger(ctx); | ||
387 | } | 382 | } |
388 | 383 | ||
389 | static void decon_enable(struct exynos_drm_crtc *crtc) | 384 | static void decon_enable(struct exynos_drm_crtc *crtc) |
@@ -395,8 +390,12 @@ static void decon_enable(struct exynos_drm_crtc *crtc) | |||
395 | 390 | ||
396 | pm_runtime_get_sync(ctx->dev); | 391 | pm_runtime_get_sync(ctx->dev); |
397 | 392 | ||
393 | exynos_drm_pipe_clk_enable(crtc, true); | ||
394 | |||
398 | set_bit(BIT_CLKS_ENABLED, &ctx->flags); | 395 | set_bit(BIT_CLKS_ENABLED, &ctx->flags); |
399 | 396 | ||
397 | decon_swreset(ctx); | ||
398 | |||
400 | /* if vblank was enabled status, enable it again. */ | 399 | /* if vblank was enabled status, enable it again. */ |
401 | if (test_and_clear_bit(BIT_IRQS_ENABLED, &ctx->flags)) | 400 | if (test_and_clear_bit(BIT_IRQS_ENABLED, &ctx->flags)) |
402 | decon_enable_vblank(ctx->crtc); | 401 | decon_enable_vblank(ctx->crtc); |
@@ -424,6 +423,8 @@ static void decon_disable(struct exynos_drm_crtc *crtc) | |||
424 | 423 | ||
425 | clear_bit(BIT_CLKS_ENABLED, &ctx->flags); | 424 | clear_bit(BIT_CLKS_ENABLED, &ctx->flags); |
426 | 425 | ||
426 | exynos_drm_pipe_clk_enable(crtc, false); | ||
427 | |||
427 | pm_runtime_put_sync(ctx->dev); | 428 | pm_runtime_put_sync(ctx->dev); |
428 | 429 | ||
429 | set_bit(BIT_SUSPENDED, &ctx->flags); | 430 | set_bit(BIT_SUSPENDED, &ctx->flags); |
@@ -459,8 +460,10 @@ static void decon_clear_channels(struct exynos_drm_crtc *crtc) | |||
459 | decon_shadow_protect_win(ctx, win, true); | 460 | decon_shadow_protect_win(ctx, win, true); |
460 | decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, 0); | 461 | decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, 0); |
461 | decon_shadow_protect_win(ctx, win, false); | 462 | decon_shadow_protect_win(ctx, win, false); |
462 | decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); | ||
463 | } | 463 | } |
464 | |||
465 | decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); | ||
466 | |||
464 | /* TODO: wait for possible vsync */ | 467 | /* TODO: wait for possible vsync */ |
465 | msleep(50); | 468 | msleep(50); |
466 | 469 | ||
@@ -509,7 +512,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data) | |||
509 | } | 512 | } |
510 | 513 | ||
511 | exynos_plane = &ctx->planes[ctx->first_win]; | 514 | exynos_plane = &ctx->planes[ctx->first_win]; |
512 | out_type = (ctx->out_type == IFTYPE_HDMI) ? EXYNOS_DISPLAY_TYPE_HDMI | 515 | out_type = (ctx->out_type & IFTYPE_HDMI) ? EXYNOS_DISPLAY_TYPE_HDMI |
513 | : EXYNOS_DISPLAY_TYPE_LCD; | 516 | : EXYNOS_DISPLAY_TYPE_LCD; |
514 | ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base, | 517 | ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base, |
515 | ctx->pipe, out_type, | 518 | ctx->pipe, out_type, |
@@ -617,11 +620,11 @@ static const struct dev_pm_ops exynos5433_decon_pm_ops = { | |||
617 | static const struct of_device_id exynos5433_decon_driver_dt_match[] = { | 620 | static const struct of_device_id exynos5433_decon_driver_dt_match[] = { |
618 | { | 621 | { |
619 | .compatible = "samsung,exynos5433-decon", | 622 | .compatible = "samsung,exynos5433-decon", |
620 | .data = (void *)IFTYPE_RGB | 623 | .data = (void *)I80_HW_TRG |
621 | }, | 624 | }, |
622 | { | 625 | { |
623 | .compatible = "samsung,exynos5433-decon-tv", | 626 | .compatible = "samsung,exynos5433-decon-tv", |
624 | .data = (void *)IFTYPE_HDMI | 627 | .data = (void *)(I80_HW_TRG | IFTYPE_HDMI) |
625 | }, | 628 | }, |
626 | {}, | 629 | {}, |
627 | }; | 630 | }; |
@@ -629,7 +632,6 @@ MODULE_DEVICE_TABLE(of, exynos5433_decon_driver_dt_match); | |||
629 | 632 | ||
630 | static int exynos5433_decon_probe(struct platform_device *pdev) | 633 | static int exynos5433_decon_probe(struct platform_device *pdev) |
631 | { | 634 | { |
632 | const struct of_device_id *of_id; | ||
633 | struct device *dev = &pdev->dev; | 635 | struct device *dev = &pdev->dev; |
634 | struct decon_context *ctx; | 636 | struct decon_context *ctx; |
635 | struct resource *res; | 637 | struct resource *res; |
@@ -642,14 +644,14 @@ static int exynos5433_decon_probe(struct platform_device *pdev) | |||
642 | 644 | ||
643 | __set_bit(BIT_SUSPENDED, &ctx->flags); | 645 | __set_bit(BIT_SUSPENDED, &ctx->flags); |
644 | ctx->dev = dev; | 646 | ctx->dev = dev; |
647 | ctx->out_type = (unsigned long)of_device_get_match_data(dev); | ||
645 | 648 | ||
646 | of_id = of_match_device(exynos5433_decon_driver_dt_match, &pdev->dev); | 649 | if (ctx->out_type & IFTYPE_HDMI) { |
647 | ctx->out_type = (enum decon_iftype)of_id->data; | ||
648 | |||
649 | if (ctx->out_type == IFTYPE_HDMI) | ||
650 | ctx->first_win = 1; | 650 | ctx->first_win = 1; |
651 | else if (of_get_child_by_name(dev->of_node, "i80-if-timings")) | ||
652 | ctx->out_type = IFTYPE_I80; | 651 | ctx->out_type = IFTYPE_I80; |
652 | } else if (of_get_child_by_name(dev->of_node, "i80-if-timings")) { | ||
653 | ctx->out_type = IFTYPE_I80; | ||
654 | } | ||
653 | 655 | ||
654 | for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) { | 656 | for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) { |
655 | struct clk *clk; | 657 | struct clk *clk; |
@@ -674,7 +676,7 @@ static int exynos5433_decon_probe(struct platform_device *pdev) | |||
674 | } | 676 | } |
675 | 677 | ||
676 | res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, | 678 | res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, |
677 | (ctx->out_type == IFTYPE_I80) ? "lcd_sys" : "vsync"); | 679 | (ctx->out_type & IFTYPE_I80) ? "lcd_sys" : "vsync"); |
678 | if (!res) { | 680 | if (!res) { |
679 | dev_err(dev, "cannot find IRQ resource\n"); | 681 | dev_err(dev, "cannot find IRQ resource\n"); |
680 | return -ENXIO; | 682 | return -ENXIO; |
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index 93361073af9a..f6223f907c15 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c | |||
@@ -593,7 +593,6 @@ static const struct exynos_drm_crtc_ops decon_crtc_ops = { | |||
593 | .commit = decon_commit, | 593 | .commit = decon_commit, |
594 | .enable_vblank = decon_enable_vblank, | 594 | .enable_vblank = decon_enable_vblank, |
595 | .disable_vblank = decon_disable_vblank, | 595 | .disable_vblank = decon_disable_vblank, |
596 | .wait_for_vblank = decon_wait_for_vblank, | ||
597 | .atomic_begin = decon_atomic_begin, | 596 | .atomic_begin = decon_atomic_begin, |
598 | .update_plane = decon_update_plane, | 597 | .update_plane = decon_update_plane, |
599 | .disable_plane = decon_disable_plane, | 598 | .disable_plane = decon_disable_plane, |
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c index 8ae3d51b5b33..468498e3fec1 100644 --- a/drivers/gpu/drm/exynos/exynos_dp.c +++ b/drivers/gpu/drm/exynos/exynos_dp.c | |||
@@ -48,14 +48,11 @@ int exynos_dp_crtc_clock_enable(struct analogix_dp_plat_data *plat_data, | |||
48 | { | 48 | { |
49 | struct exynos_dp_device *dp = to_dp(plat_data); | 49 | struct exynos_dp_device *dp = to_dp(plat_data); |
50 | struct drm_encoder *encoder = &dp->encoder; | 50 | struct drm_encoder *encoder = &dp->encoder; |
51 | struct exynos_drm_crtc *crtc; | ||
52 | 51 | ||
53 | if (!encoder) | 52 | if (!encoder->crtc) |
54 | return -1; | 53 | return -EPERM; |
55 | 54 | ||
56 | crtc = to_exynos_crtc(encoder->crtc); | 55 | exynos_drm_pipe_clk_enable(to_exynos_crtc(encoder->crtc), enable); |
57 | if (crtc && crtc->ops && crtc->ops->clock_enable) | ||
58 | crtc->ops->clock_enable(crtc, enable); | ||
59 | 56 | ||
60 | return 0; | 57 | return 0; |
61 | } | 58 | } |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c index 7f55ba6771c6..011211e4167d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_core.c +++ b/drivers/gpu/drm/exynos/exynos_drm_core.c | |||
@@ -101,7 +101,7 @@ int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file) | |||
101 | return 0; | 101 | return 0; |
102 | 102 | ||
103 | err: | 103 | err: |
104 | list_for_each_entry_reverse(subdrv, &subdrv->list, list) { | 104 | list_for_each_entry_continue_reverse(subdrv, &exynos_drm_subdrv_list, list) { |
105 | if (subdrv->close) | 105 | if (subdrv->close) |
106 | subdrv->close(dev, subdrv->dev, file); | 106 | subdrv->close(dev, subdrv->dev, file); |
107 | } | 107 | } |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index e36579c1c025..50dd33d5045d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c | |||
@@ -157,9 +157,8 @@ err_crtc: | |||
157 | 157 | ||
158 | int exynos_drm_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe) | 158 | int exynos_drm_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe) |
159 | { | 159 | { |
160 | struct exynos_drm_private *private = dev->dev_private; | 160 | struct exynos_drm_crtc *exynos_crtc = exynos_drm_crtc_from_pipe(dev, |
161 | struct exynos_drm_crtc *exynos_crtc = | 161 | pipe); |
162 | to_exynos_crtc(private->crtc[pipe]); | ||
163 | 162 | ||
164 | if (exynos_crtc->ops->enable_vblank) | 163 | if (exynos_crtc->ops->enable_vblank) |
165 | return exynos_crtc->ops->enable_vblank(exynos_crtc); | 164 | return exynos_crtc->ops->enable_vblank(exynos_crtc); |
@@ -169,9 +168,8 @@ int exynos_drm_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe) | |||
169 | 168 | ||
170 | void exynos_drm_crtc_disable_vblank(struct drm_device *dev, unsigned int pipe) | 169 | void exynos_drm_crtc_disable_vblank(struct drm_device *dev, unsigned int pipe) |
171 | { | 170 | { |
172 | struct exynos_drm_private *private = dev->dev_private; | 171 | struct exynos_drm_crtc *exynos_crtc = exynos_drm_crtc_from_pipe(dev, |
173 | struct exynos_drm_crtc *exynos_crtc = | 172 | pipe); |
174 | to_exynos_crtc(private->crtc[pipe]); | ||
175 | 173 | ||
176 | if (exynos_crtc->ops->disable_vblank) | 174 | if (exynos_crtc->ops->disable_vblank) |
177 | exynos_crtc->ops->disable_vblank(exynos_crtc); | 175 | exynos_crtc->ops->disable_vblank(exynos_crtc); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 502f750bad2a..2ca719cc3e2a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h | |||
@@ -120,8 +120,6 @@ struct exynos_drm_plane_config { | |||
120 | * @commit: set current hw specific display mode to hw. | 120 | * @commit: set current hw specific display mode to hw. |
121 | * @enable_vblank: specific driver callback for enabling vblank interrupt. | 121 | * @enable_vblank: specific driver callback for enabling vblank interrupt. |
122 | * @disable_vblank: specific driver callback for disabling vblank interrupt. | 122 | * @disable_vblank: specific driver callback for disabling vblank interrupt. |
123 | * @wait_for_vblank: wait for vblank interrupt to make sure that | ||
124 | * hardware overlay is updated. | ||
125 | * @atomic_check: validate state | 123 | * @atomic_check: validate state |
126 | * @atomic_begin: prepare device to receive an update | 124 | * @atomic_begin: prepare device to receive an update |
127 | * @atomic_flush: mark the end of device update | 125 | * @atomic_flush: mark the end of device update |
@@ -129,10 +127,6 @@ struct exynos_drm_plane_config { | |||
129 | * @disable_plane: disable hardware specific overlay. | 127 | * @disable_plane: disable hardware specific overlay. |
130 | * @te_handler: trigger to transfer video image at the tearing effect | 128 | * @te_handler: trigger to transfer video image at the tearing effect |
131 | * synchronization signal if there is a page flip request. | 129 | * synchronization signal if there is a page flip request. |
132 | * @clock_enable: optional function enabling/disabling display domain clock, | ||
133 | * called from exynos-dp driver before powering up (with | ||
134 | * 'enable' argument as true) and after powering down (with | ||
135 | * 'enable' as false). | ||
136 | */ | 130 | */ |
137 | struct exynos_drm_crtc; | 131 | struct exynos_drm_crtc; |
138 | struct exynos_drm_crtc_ops { | 132 | struct exynos_drm_crtc_ops { |
@@ -141,7 +135,6 @@ struct exynos_drm_crtc_ops { | |||
141 | void (*commit)(struct exynos_drm_crtc *crtc); | 135 | void (*commit)(struct exynos_drm_crtc *crtc); |
142 | int (*enable_vblank)(struct exynos_drm_crtc *crtc); | 136 | int (*enable_vblank)(struct exynos_drm_crtc *crtc); |
143 | void (*disable_vblank)(struct exynos_drm_crtc *crtc); | 137 | void (*disable_vblank)(struct exynos_drm_crtc *crtc); |
144 | void (*wait_for_vblank)(struct exynos_drm_crtc *crtc); | ||
145 | int (*atomic_check)(struct exynos_drm_crtc *crtc, | 138 | int (*atomic_check)(struct exynos_drm_crtc *crtc, |
146 | struct drm_crtc_state *state); | 139 | struct drm_crtc_state *state); |
147 | void (*atomic_begin)(struct exynos_drm_crtc *crtc); | 140 | void (*atomic_begin)(struct exynos_drm_crtc *crtc); |
@@ -151,7 +144,10 @@ struct exynos_drm_crtc_ops { | |||
151 | struct exynos_drm_plane *plane); | 144 | struct exynos_drm_plane *plane); |
152 | void (*atomic_flush)(struct exynos_drm_crtc *crtc); | 145 | void (*atomic_flush)(struct exynos_drm_crtc *crtc); |
153 | void (*te_handler)(struct exynos_drm_crtc *crtc); | 146 | void (*te_handler)(struct exynos_drm_crtc *crtc); |
154 | void (*clock_enable)(struct exynos_drm_crtc *crtc, bool enable); | 147 | }; |
148 | |||
149 | struct exynos_drm_clk { | ||
150 | void (*enable)(struct exynos_drm_clk *clk, bool enable); | ||
155 | }; | 151 | }; |
156 | 152 | ||
157 | /* | 153 | /* |
@@ -182,8 +178,16 @@ struct exynos_drm_crtc { | |||
182 | atomic_t pending_update; | 178 | atomic_t pending_update; |
183 | const struct exynos_drm_crtc_ops *ops; | 179 | const struct exynos_drm_crtc_ops *ops; |
184 | void *ctx; | 180 | void *ctx; |
181 | struct exynos_drm_clk *pipe_clk; | ||
185 | }; | 182 | }; |
186 | 183 | ||
184 | static inline void exynos_drm_pipe_clk_enable(struct exynos_drm_crtc *crtc, | ||
185 | bool enable) | ||
186 | { | ||
187 | if (crtc->pipe_clk) | ||
188 | crtc->pipe_clk->enable(crtc->pipe_clk, enable); | ||
189 | } | ||
190 | |||
187 | struct exynos_drm_g2d_private { | 191 | struct exynos_drm_g2d_private { |
188 | struct device *dev; | 192 | struct device *dev; |
189 | struct list_head inuse_cmdlist; | 193 | struct list_head inuse_cmdlist; |
@@ -232,6 +236,14 @@ struct exynos_drm_private { | |||
232 | wait_queue_head_t wait; | 236 | wait_queue_head_t wait; |
233 | }; | 237 | }; |
234 | 238 | ||
239 | static inline struct exynos_drm_crtc * | ||
240 | exynos_drm_crtc_from_pipe(struct drm_device *dev, int pipe) | ||
241 | { | ||
242 | struct exynos_drm_private *private = dev->dev_private; | ||
243 | |||
244 | return to_exynos_crtc(private->crtc[pipe]); | ||
245 | } | ||
246 | |||
235 | static inline struct device *to_dma_dev(struct drm_device *dev) | 247 | static inline struct device *to_dma_dev(struct drm_device *dev) |
236 | { | 248 | { |
237 | struct exynos_drm_private *priv = dev->dev_private; | 249 | struct exynos_drm_private *priv = dev->dev_private; |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 63c84a106c0b..72c3565d22ee 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c | |||
@@ -280,7 +280,7 @@ struct exynos_dsi { | |||
280 | spinlock_t transfer_lock; /* protects transfer_list */ | 280 | spinlock_t transfer_lock; /* protects transfer_list */ |
281 | struct list_head transfer_list; | 281 | struct list_head transfer_list; |
282 | 282 | ||
283 | struct exynos_dsi_driver_data *driver_data; | 283 | const struct exynos_dsi_driver_data *driver_data; |
284 | struct device_node *bridge_node; | 284 | struct device_node *bridge_node; |
285 | }; | 285 | }; |
286 | 286 | ||
@@ -532,15 +532,6 @@ static const struct of_device_id exynos_dsi_of_match[] = { | |||
532 | { } | 532 | { } |
533 | }; | 533 | }; |
534 | 534 | ||
535 | static inline struct exynos_dsi_driver_data *exynos_dsi_get_driver_data( | ||
536 | struct platform_device *pdev) | ||
537 | { | ||
538 | const struct of_device_id *of_id = | ||
539 | of_match_device(exynos_dsi_of_match, &pdev->dev); | ||
540 | |||
541 | return (struct exynos_dsi_driver_data *)of_id->data; | ||
542 | } | ||
543 | |||
544 | static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi) | 535 | static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi) |
545 | { | 536 | { |
546 | if (wait_for_completion_timeout(&dsi->completed, msecs_to_jiffies(300))) | 537 | if (wait_for_completion_timeout(&dsi->completed, msecs_to_jiffies(300))) |
@@ -564,7 +555,7 @@ static void exynos_dsi_reset(struct exynos_dsi *dsi) | |||
564 | static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi, | 555 | static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi, |
565 | unsigned long fin, unsigned long fout, u8 *p, u16 *m, u8 *s) | 556 | unsigned long fin, unsigned long fout, u8 *p, u16 *m, u8 *s) |
566 | { | 557 | { |
567 | struct exynos_dsi_driver_data *driver_data = dsi->driver_data; | 558 | const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; |
568 | unsigned long best_freq = 0; | 559 | unsigned long best_freq = 0; |
569 | u32 min_delta = 0xffffffff; | 560 | u32 min_delta = 0xffffffff; |
570 | u8 p_min, p_max; | 561 | u8 p_min, p_max; |
@@ -618,7 +609,7 @@ static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi, | |||
618 | static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi, | 609 | static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi, |
619 | unsigned long freq) | 610 | unsigned long freq) |
620 | { | 611 | { |
621 | struct exynos_dsi_driver_data *driver_data = dsi->driver_data; | 612 | const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; |
622 | unsigned long fin, fout; | 613 | unsigned long fin, fout; |
623 | int timeout; | 614 | int timeout; |
624 | u8 p, s; | 615 | u8 p, s; |
@@ -712,7 +703,7 @@ static int exynos_dsi_enable_clock(struct exynos_dsi *dsi) | |||
712 | 703 | ||
713 | static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi) | 704 | static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi) |
714 | { | 705 | { |
715 | struct exynos_dsi_driver_data *driver_data = dsi->driver_data; | 706 | const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; |
716 | const unsigned int *reg_values = driver_data->reg_values; | 707 | const unsigned int *reg_values = driver_data->reg_values; |
717 | u32 reg; | 708 | u32 reg; |
718 | 709 | ||
@@ -790,7 +781,7 @@ static void exynos_dsi_enable_lane(struct exynos_dsi *dsi, u32 lane) | |||
790 | 781 | ||
791 | static int exynos_dsi_init_link(struct exynos_dsi *dsi) | 782 | static int exynos_dsi_init_link(struct exynos_dsi *dsi) |
792 | { | 783 | { |
793 | struct exynos_dsi_driver_data *driver_data = dsi->driver_data; | 784 | const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; |
794 | int timeout; | 785 | int timeout; |
795 | u32 reg; | 786 | u32 reg; |
796 | u32 lanes_mask; | 787 | u32 lanes_mask; |
@@ -1334,7 +1325,7 @@ static void exynos_dsi_disable_irq(struct exynos_dsi *dsi) | |||
1334 | 1325 | ||
1335 | static int exynos_dsi_init(struct exynos_dsi *dsi) | 1326 | static int exynos_dsi_init(struct exynos_dsi *dsi) |
1336 | { | 1327 | { |
1337 | struct exynos_dsi_driver_data *driver_data = dsi->driver_data; | 1328 | const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; |
1338 | 1329 | ||
1339 | exynos_dsi_reset(dsi); | 1330 | exynos_dsi_reset(dsi); |
1340 | exynos_dsi_enable_irq(dsi); | 1331 | exynos_dsi_enable_irq(dsi); |
@@ -1833,7 +1824,7 @@ static int exynos_dsi_probe(struct platform_device *pdev) | |||
1833 | dsi->dsi_host.dev = dev; | 1824 | dsi->dsi_host.dev = dev; |
1834 | 1825 | ||
1835 | dsi->dev = dev; | 1826 | dsi->dev = dev; |
1836 | dsi->driver_data = exynos_dsi_get_driver_data(pdev); | 1827 | dsi->driver_data = of_device_get_match_data(dev); |
1837 | 1828 | ||
1838 | ret = exynos_dsi_parse_dt(dsi); | 1829 | ret = exynos_dsi_parse_dt(dsi); |
1839 | if (ret) | 1830 | if (ret) |
@@ -1917,7 +1908,7 @@ static int __maybe_unused exynos_dsi_suspend(struct device *dev) | |||
1917 | { | 1908 | { |
1918 | struct drm_encoder *encoder = dev_get_drvdata(dev); | 1909 | struct drm_encoder *encoder = dev_get_drvdata(dev); |
1919 | struct exynos_dsi *dsi = encoder_to_dsi(encoder); | 1910 | struct exynos_dsi *dsi = encoder_to_dsi(encoder); |
1920 | struct exynos_dsi_driver_data *driver_data = dsi->driver_data; | 1911 | const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; |
1921 | int ret, i; | 1912 | int ret, i; |
1922 | 1913 | ||
1923 | usleep_range(10000, 20000); | 1914 | usleep_range(10000, 20000); |
@@ -1948,7 +1939,7 @@ static int __maybe_unused exynos_dsi_resume(struct device *dev) | |||
1948 | { | 1939 | { |
1949 | struct drm_encoder *encoder = dev_get_drvdata(dev); | 1940 | struct drm_encoder *encoder = dev_get_drvdata(dev); |
1950 | struct exynos_dsi *dsi = encoder_to_dsi(encoder); | 1941 | struct exynos_dsi *dsi = encoder_to_dsi(encoder); |
1951 | struct exynos_dsi_driver_data *driver_data = dsi->driver_data; | 1942 | const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; |
1952 | int ret, i; | 1943 | int ret, i; |
1953 | 1944 | ||
1954 | ret = regulator_bulk_enable(ARRAY_SIZE(dsi->supplies), dsi->supplies); | 1945 | ret = regulator_bulk_enable(ARRAY_SIZE(dsi->supplies), dsi->supplies); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index d614194644c8..81cc5537cf25 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c | |||
@@ -199,17 +199,6 @@ dma_addr_t exynos_drm_fb_dma_addr(struct drm_framebuffer *fb, int index) | |||
199 | return exynos_fb->dma_addr[index]; | 199 | return exynos_fb->dma_addr[index]; |
200 | } | 200 | } |
201 | 201 | ||
202 | static void exynos_drm_output_poll_changed(struct drm_device *dev) | ||
203 | { | ||
204 | struct exynos_drm_private *private = dev->dev_private; | ||
205 | struct drm_fb_helper *fb_helper = private->fb_helper; | ||
206 | |||
207 | if (fb_helper) | ||
208 | drm_fb_helper_hotplug_event(fb_helper); | ||
209 | else | ||
210 | exynos_drm_fbdev_init(dev); | ||
211 | } | ||
212 | |||
213 | static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = { | 202 | static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = { |
214 | .fb_create = exynos_user_fb_create, | 203 | .fb_create = exynos_user_fb_create, |
215 | .output_poll_changed = exynos_drm_output_poll_changed, | 204 | .output_poll_changed = exynos_drm_output_poll_changed, |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 4656cd6e7083..67dcd6831291 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c | |||
@@ -311,3 +311,14 @@ void exynos_drm_fbdev_restore_mode(struct drm_device *dev) | |||
311 | 311 | ||
312 | drm_fb_helper_restore_fbdev_mode_unlocked(private->fb_helper); | 312 | drm_fb_helper_restore_fbdev_mode_unlocked(private->fb_helper); |
313 | } | 313 | } |
314 | |||
315 | void exynos_drm_output_poll_changed(struct drm_device *dev) | ||
316 | { | ||
317 | struct exynos_drm_private *private = dev->dev_private; | ||
318 | struct drm_fb_helper *fb_helper = private->fb_helper; | ||
319 | |||
320 | if (fb_helper) | ||
321 | drm_fb_helper_hotplug_event(fb_helper); | ||
322 | else | ||
323 | exynos_drm_fbdev_init(dev); | ||
324 | } | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.h b/drivers/gpu/drm/exynos/exynos_drm_fbdev.h index e16d7f0ae192..330eef87f718 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.h +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.h | |||
@@ -15,9 +15,30 @@ | |||
15 | #ifndef _EXYNOS_DRM_FBDEV_H_ | 15 | #ifndef _EXYNOS_DRM_FBDEV_H_ |
16 | #define _EXYNOS_DRM_FBDEV_H_ | 16 | #define _EXYNOS_DRM_FBDEV_H_ |
17 | 17 | ||
18 | #ifdef CONFIG_DRM_FBDEV_EMULATION | ||
19 | |||
18 | int exynos_drm_fbdev_init(struct drm_device *dev); | 20 | int exynos_drm_fbdev_init(struct drm_device *dev); |
19 | int exynos_drm_fbdev_reinit(struct drm_device *dev); | ||
20 | void exynos_drm_fbdev_fini(struct drm_device *dev); | 21 | void exynos_drm_fbdev_fini(struct drm_device *dev); |
21 | void exynos_drm_fbdev_restore_mode(struct drm_device *dev); | 22 | void exynos_drm_fbdev_restore_mode(struct drm_device *dev); |
23 | void exynos_drm_output_poll_changed(struct drm_device *dev); | ||
24 | |||
25 | #else | ||
26 | |||
27 | static inline int exynos_drm_fbdev_init(struct drm_device *dev) | ||
28 | { | ||
29 | return 0; | ||
30 | } | ||
31 | |||
32 | static inline void exynos_drm_fbdev_fini(struct drm_device *dev) | ||
33 | { | ||
34 | } | ||
35 | |||
36 | static inline void exynos_drm_fbdev_restore_mode(struct drm_device *dev) | ||
37 | { | ||
38 | } | ||
39 | |||
40 | #define exynos_drm_output_poll_changed (NULL) | ||
41 | |||
42 | #endif | ||
22 | 43 | ||
23 | #endif | 44 | #endif |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 51d484ae9f49..547d759a0a6f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c | |||
@@ -68,10 +68,15 @@ | |||
68 | /* color key value register for hardware window 1 ~ 4. */ | 68 | /* color key value register for hardware window 1 ~ 4. */ |
69 | #define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + ((x - 1) * 8)) | 69 | #define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + ((x - 1) * 8)) |
70 | 70 | ||
71 | /* I80 / RGB trigger control register */ | 71 | /* I80 trigger control register */ |
72 | #define TRIGCON 0x1A4 | 72 | #define TRIGCON 0x1A4 |
73 | #define TRGMODE_I80_RGB_ENABLE_I80 (1 << 0) | 73 | #define TRGMODE_ENABLE (1 << 0) |
74 | #define SWTRGCMD_I80_RGB_ENABLE (1 << 1) | 74 | #define SWTRGCMD_ENABLE (1 << 1) |
75 | /* Exynos3250, 3472, 4415, 5260 5410, 5420 and 5422 only supported. */ | ||
76 | #define HWTRGEN_ENABLE (1 << 3) | ||
77 | #define HWTRGMASK_ENABLE (1 << 4) | ||
78 | /* Exynos3250, 3472, 4415, 5260, 5420 and 5422 only supported. */ | ||
79 | #define HWTRIGEN_PER_ENABLE (1 << 31) | ||
75 | 80 | ||
76 | /* display mode change control register except exynos4 */ | 81 | /* display mode change control register except exynos4 */ |
77 | #define VIDOUT_CON 0x000 | 82 | #define VIDOUT_CON 0x000 |
@@ -89,12 +94,16 @@ | |||
89 | /* FIMD has totally five hardware windows. */ | 94 | /* FIMD has totally five hardware windows. */ |
90 | #define WINDOWS_NR 5 | 95 | #define WINDOWS_NR 5 |
91 | 96 | ||
97 | /* HW trigger flag on i80 panel. */ | ||
98 | #define I80_HW_TRG (1 << 1) | ||
99 | |||
92 | struct fimd_driver_data { | 100 | struct fimd_driver_data { |
93 | unsigned int timing_base; | 101 | unsigned int timing_base; |
94 | unsigned int lcdblk_offset; | 102 | unsigned int lcdblk_offset; |
95 | unsigned int lcdblk_vt_shift; | 103 | unsigned int lcdblk_vt_shift; |
96 | unsigned int lcdblk_bypass_shift; | 104 | unsigned int lcdblk_bypass_shift; |
97 | unsigned int lcdblk_mic_bypass_shift; | 105 | unsigned int lcdblk_mic_bypass_shift; |
106 | unsigned int trg_type; | ||
98 | 107 | ||
99 | unsigned int has_shadowcon:1; | 108 | unsigned int has_shadowcon:1; |
100 | unsigned int has_clksel:1; | 109 | unsigned int has_clksel:1; |
@@ -102,20 +111,26 @@ struct fimd_driver_data { | |||
102 | unsigned int has_vidoutcon:1; | 111 | unsigned int has_vidoutcon:1; |
103 | unsigned int has_vtsel:1; | 112 | unsigned int has_vtsel:1; |
104 | unsigned int has_mic_bypass:1; | 113 | unsigned int has_mic_bypass:1; |
114 | unsigned int has_dp_clk:1; | ||
115 | unsigned int has_hw_trigger:1; | ||
116 | unsigned int has_trigger_per_te:1; | ||
105 | }; | 117 | }; |
106 | 118 | ||
107 | static struct fimd_driver_data s3c64xx_fimd_driver_data = { | 119 | static struct fimd_driver_data s3c64xx_fimd_driver_data = { |
108 | .timing_base = 0x0, | 120 | .timing_base = 0x0, |
109 | .has_clksel = 1, | 121 | .has_clksel = 1, |
110 | .has_limited_fmt = 1, | 122 | .has_limited_fmt = 1, |
123 | .has_hw_trigger = 1, | ||
111 | }; | 124 | }; |
112 | 125 | ||
113 | static struct fimd_driver_data exynos3_fimd_driver_data = { | 126 | static struct fimd_driver_data exynos3_fimd_driver_data = { |
114 | .timing_base = 0x20000, | 127 | .timing_base = 0x20000, |
115 | .lcdblk_offset = 0x210, | 128 | .lcdblk_offset = 0x210, |
116 | .lcdblk_bypass_shift = 1, | 129 | .lcdblk_bypass_shift = 1, |
130 | .trg_type = I80_HW_TRG, | ||
117 | .has_shadowcon = 1, | 131 | .has_shadowcon = 1, |
118 | .has_vidoutcon = 1, | 132 | .has_vidoutcon = 1, |
133 | .has_trigger_per_te = 1, | ||
119 | }; | 134 | }; |
120 | 135 | ||
121 | static struct fimd_driver_data exynos4_fimd_driver_data = { | 136 | static struct fimd_driver_data exynos4_fimd_driver_data = { |
@@ -132,9 +147,11 @@ static struct fimd_driver_data exynos4415_fimd_driver_data = { | |||
132 | .lcdblk_offset = 0x210, | 147 | .lcdblk_offset = 0x210, |
133 | .lcdblk_vt_shift = 10, | 148 | .lcdblk_vt_shift = 10, |
134 | .lcdblk_bypass_shift = 1, | 149 | .lcdblk_bypass_shift = 1, |
150 | .trg_type = I80_HW_TRG, | ||
135 | .has_shadowcon = 1, | 151 | .has_shadowcon = 1, |
136 | .has_vidoutcon = 1, | 152 | .has_vidoutcon = 1, |
137 | .has_vtsel = 1, | 153 | .has_vtsel = 1, |
154 | .has_trigger_per_te = 1, | ||
138 | }; | 155 | }; |
139 | 156 | ||
140 | static struct fimd_driver_data exynos5_fimd_driver_data = { | 157 | static struct fimd_driver_data exynos5_fimd_driver_data = { |
@@ -145,6 +162,7 @@ static struct fimd_driver_data exynos5_fimd_driver_data = { | |||
145 | .has_shadowcon = 1, | 162 | .has_shadowcon = 1, |
146 | .has_vidoutcon = 1, | 163 | .has_vidoutcon = 1, |
147 | .has_vtsel = 1, | 164 | .has_vtsel = 1, |
165 | .has_dp_clk = 1, | ||
148 | }; | 166 | }; |
149 | 167 | ||
150 | static struct fimd_driver_data exynos5420_fimd_driver_data = { | 168 | static struct fimd_driver_data exynos5420_fimd_driver_data = { |
@@ -153,10 +171,14 @@ static struct fimd_driver_data exynos5420_fimd_driver_data = { | |||
153 | .lcdblk_vt_shift = 24, | 171 | .lcdblk_vt_shift = 24, |
154 | .lcdblk_bypass_shift = 15, | 172 | .lcdblk_bypass_shift = 15, |
155 | .lcdblk_mic_bypass_shift = 11, | 173 | .lcdblk_mic_bypass_shift = 11, |
174 | .trg_type = I80_HW_TRG, | ||
156 | .has_shadowcon = 1, | 175 | .has_shadowcon = 1, |
157 | .has_vidoutcon = 1, | 176 | .has_vidoutcon = 1, |
158 | .has_vtsel = 1, | 177 | .has_vtsel = 1, |
159 | .has_mic_bypass = 1, | 178 | .has_mic_bypass = 1, |
179 | .has_dp_clk = 1, | ||
180 | .has_hw_trigger = 1, | ||
181 | .has_trigger_per_te = 1, | ||
160 | }; | 182 | }; |
161 | 183 | ||
162 | struct fimd_context { | 184 | struct fimd_context { |
@@ -182,8 +204,9 @@ struct fimd_context { | |||
182 | atomic_t win_updated; | 204 | atomic_t win_updated; |
183 | atomic_t triggering; | 205 | atomic_t triggering; |
184 | 206 | ||
185 | struct fimd_driver_data *driver_data; | 207 | const struct fimd_driver_data *driver_data; |
186 | struct drm_encoder *encoder; | 208 | struct drm_encoder *encoder; |
209 | struct exynos_drm_clk dp_clk; | ||
187 | }; | 210 | }; |
188 | 211 | ||
189 | static const struct of_device_id fimd_driver_dt_match[] = { | 212 | static const struct of_device_id fimd_driver_dt_match[] = { |
@@ -219,15 +242,6 @@ static const uint32_t fimd_formats[] = { | |||
219 | DRM_FORMAT_ARGB8888, | 242 | DRM_FORMAT_ARGB8888, |
220 | }; | 243 | }; |
221 | 244 | ||
222 | static inline struct fimd_driver_data *drm_fimd_get_driver_data( | ||
223 | struct platform_device *pdev) | ||
224 | { | ||
225 | const struct of_device_id *of_id = | ||
226 | of_match_device(fimd_driver_dt_match, &pdev->dev); | ||
227 | |||
228 | return (struct fimd_driver_data *)of_id->data; | ||
229 | } | ||
230 | |||
231 | static int fimd_enable_vblank(struct exynos_drm_crtc *crtc) | 245 | static int fimd_enable_vblank(struct exynos_drm_crtc *crtc) |
232 | { | 246 | { |
233 | struct fimd_context *ctx = crtc->ctx; | 247 | struct fimd_context *ctx = crtc->ctx; |
@@ -400,11 +414,31 @@ static u32 fimd_calc_clkdiv(struct fimd_context *ctx, | |||
400 | return (clkdiv < 0x100) ? clkdiv : 0xff; | 414 | return (clkdiv < 0x100) ? clkdiv : 0xff; |
401 | } | 415 | } |
402 | 416 | ||
417 | static void fimd_setup_trigger(struct fimd_context *ctx) | ||
418 | { | ||
419 | void __iomem *timing_base = ctx->regs + ctx->driver_data->timing_base; | ||
420 | u32 trg_type = ctx->driver_data->trg_type; | ||
421 | u32 val = readl(timing_base + TRIGCON); | ||
422 | |||
423 | val &= ~(TRGMODE_ENABLE); | ||
424 | |||
425 | if (trg_type == I80_HW_TRG) { | ||
426 | if (ctx->driver_data->has_hw_trigger) | ||
427 | val |= HWTRGEN_ENABLE | HWTRGMASK_ENABLE; | ||
428 | if (ctx->driver_data->has_trigger_per_te) | ||
429 | val |= HWTRIGEN_PER_ENABLE; | ||
430 | } else { | ||
431 | val |= TRGMODE_ENABLE; | ||
432 | } | ||
433 | |||
434 | writel(val, timing_base + TRIGCON); | ||
435 | } | ||
436 | |||
403 | static void fimd_commit(struct exynos_drm_crtc *crtc) | 437 | static void fimd_commit(struct exynos_drm_crtc *crtc) |
404 | { | 438 | { |
405 | struct fimd_context *ctx = crtc->ctx; | 439 | struct fimd_context *ctx = crtc->ctx; |
406 | struct drm_display_mode *mode = &crtc->base.state->adjusted_mode; | 440 | struct drm_display_mode *mode = &crtc->base.state->adjusted_mode; |
407 | struct fimd_driver_data *driver_data = ctx->driver_data; | 441 | const struct fimd_driver_data *driver_data = ctx->driver_data; |
408 | void *timing_base = ctx->regs + driver_data->timing_base; | 442 | void *timing_base = ctx->regs + driver_data->timing_base; |
409 | u32 val, clkdiv; | 443 | u32 val, clkdiv; |
410 | 444 | ||
@@ -495,6 +529,8 @@ static void fimd_commit(struct exynos_drm_crtc *crtc) | |||
495 | VIDTCON2_HOZVAL_E(mode->hdisplay - 1); | 529 | VIDTCON2_HOZVAL_E(mode->hdisplay - 1); |
496 | writel(val, ctx->regs + driver_data->timing_base + VIDTCON2); | 530 | writel(val, ctx->regs + driver_data->timing_base + VIDTCON2); |
497 | 531 | ||
532 | fimd_setup_trigger(ctx); | ||
533 | |||
498 | /* | 534 | /* |
499 | * fields of register with prefix '_F' would be updated | 535 | * fields of register with prefix '_F' would be updated |
500 | * at vsync(same as dma start) | 536 | * at vsync(same as dma start) |
@@ -827,7 +863,7 @@ static void fimd_disable(struct exynos_drm_crtc *crtc) | |||
827 | static void fimd_trigger(struct device *dev) | 863 | static void fimd_trigger(struct device *dev) |
828 | { | 864 | { |
829 | struct fimd_context *ctx = dev_get_drvdata(dev); | 865 | struct fimd_context *ctx = dev_get_drvdata(dev); |
830 | struct fimd_driver_data *driver_data = ctx->driver_data; | 866 | const struct fimd_driver_data *driver_data = ctx->driver_data; |
831 | void *timing_base = ctx->regs + driver_data->timing_base; | 867 | void *timing_base = ctx->regs + driver_data->timing_base; |
832 | u32 reg; | 868 | u32 reg; |
833 | 869 | ||
@@ -842,7 +878,7 @@ static void fimd_trigger(struct device *dev) | |||
842 | atomic_set(&ctx->triggering, 1); | 878 | atomic_set(&ctx->triggering, 1); |
843 | 879 | ||
844 | reg = readl(timing_base + TRIGCON); | 880 | reg = readl(timing_base + TRIGCON); |
845 | reg |= (TRGMODE_I80_RGB_ENABLE_I80 | SWTRGCMD_I80_RGB_ENABLE); | 881 | reg |= (TRGMODE_ENABLE | SWTRGCMD_ENABLE); |
846 | writel(reg, timing_base + TRIGCON); | 882 | writel(reg, timing_base + TRIGCON); |
847 | 883 | ||
848 | /* | 884 | /* |
@@ -856,11 +892,15 @@ static void fimd_trigger(struct device *dev) | |||
856 | static void fimd_te_handler(struct exynos_drm_crtc *crtc) | 892 | static void fimd_te_handler(struct exynos_drm_crtc *crtc) |
857 | { | 893 | { |
858 | struct fimd_context *ctx = crtc->ctx; | 894 | struct fimd_context *ctx = crtc->ctx; |
895 | u32 trg_type = ctx->driver_data->trg_type; | ||
859 | 896 | ||
860 | /* Checks the crtc is detached already from encoder */ | 897 | /* Checks the crtc is detached already from encoder */ |
861 | if (ctx->pipe < 0 || !ctx->drm_dev) | 898 | if (ctx->pipe < 0 || !ctx->drm_dev) |
862 | return; | 899 | return; |
863 | 900 | ||
901 | if (trg_type == I80_HW_TRG) | ||
902 | goto out; | ||
903 | |||
864 | /* | 904 | /* |
865 | * If there is a page flip request, triggers and handles the page flip | 905 | * If there is a page flip request, triggers and handles the page flip |
866 | * event so that current fb can be updated into panel GRAM. | 906 | * event so that current fb can be updated into panel GRAM. |
@@ -868,6 +908,7 @@ static void fimd_te_handler(struct exynos_drm_crtc *crtc) | |||
868 | if (atomic_add_unless(&ctx->win_updated, -1, 0)) | 908 | if (atomic_add_unless(&ctx->win_updated, -1, 0)) |
869 | fimd_trigger(ctx->dev); | 909 | fimd_trigger(ctx->dev); |
870 | 910 | ||
911 | out: | ||
871 | /* Wakes up vsync event queue */ | 912 | /* Wakes up vsync event queue */ |
872 | if (atomic_read(&ctx->wait_vsync_event)) { | 913 | if (atomic_read(&ctx->wait_vsync_event)) { |
873 | atomic_set(&ctx->wait_vsync_event, 0); | 914 | atomic_set(&ctx->wait_vsync_event, 0); |
@@ -878,21 +919,12 @@ static void fimd_te_handler(struct exynos_drm_crtc *crtc) | |||
878 | drm_crtc_handle_vblank(&ctx->crtc->base); | 919 | drm_crtc_handle_vblank(&ctx->crtc->base); |
879 | } | 920 | } |
880 | 921 | ||
881 | static void fimd_dp_clock_enable(struct exynos_drm_crtc *crtc, bool enable) | 922 | static void fimd_dp_clock_enable(struct exynos_drm_clk *clk, bool enable) |
882 | { | 923 | { |
883 | struct fimd_context *ctx = crtc->ctx; | 924 | struct fimd_context *ctx = container_of(clk, struct fimd_context, |
884 | u32 val; | 925 | dp_clk); |
926 | u32 val = enable ? DP_MIE_CLK_DP_ENABLE : DP_MIE_CLK_DISABLE; | ||
885 | 927 | ||
886 | /* | ||
887 | * Only Exynos 5250, 5260, 5410 and 542x requires enabling DP/MIE | ||
888 | * clock. On these SoCs the bootloader may enable it but any | ||
889 | * power domain off/on will reset it to disable state. | ||
890 | */ | ||
891 | if (ctx->driver_data != &exynos5_fimd_driver_data || | ||
892 | ctx->driver_data != &exynos5420_fimd_driver_data) | ||
893 | return; | ||
894 | |||
895 | val = enable ? DP_MIE_CLK_DP_ENABLE : DP_MIE_CLK_DISABLE; | ||
896 | writel(val, ctx->regs + DP_MIE_CLKCON); | 928 | writel(val, ctx->regs + DP_MIE_CLKCON); |
897 | } | 929 | } |
898 | 930 | ||
@@ -902,13 +934,11 @@ static const struct exynos_drm_crtc_ops fimd_crtc_ops = { | |||
902 | .commit = fimd_commit, | 934 | .commit = fimd_commit, |
903 | .enable_vblank = fimd_enable_vblank, | 935 | .enable_vblank = fimd_enable_vblank, |
904 | .disable_vblank = fimd_disable_vblank, | 936 | .disable_vblank = fimd_disable_vblank, |
905 | .wait_for_vblank = fimd_wait_for_vblank, | ||
906 | .atomic_begin = fimd_atomic_begin, | 937 | .atomic_begin = fimd_atomic_begin, |
907 | .update_plane = fimd_update_plane, | 938 | .update_plane = fimd_update_plane, |
908 | .disable_plane = fimd_disable_plane, | 939 | .disable_plane = fimd_disable_plane, |
909 | .atomic_flush = fimd_atomic_flush, | 940 | .atomic_flush = fimd_atomic_flush, |
910 | .te_handler = fimd_te_handler, | 941 | .te_handler = fimd_te_handler, |
911 | .clock_enable = fimd_dp_clock_enable, | ||
912 | }; | 942 | }; |
913 | 943 | ||
914 | static irqreturn_t fimd_irq_handler(int irq, void *dev_id) | 944 | static irqreturn_t fimd_irq_handler(int irq, void *dev_id) |
@@ -987,6 +1017,11 @@ static int fimd_bind(struct device *dev, struct device *master, void *data) | |||
987 | if (IS_ERR(ctx->crtc)) | 1017 | if (IS_ERR(ctx->crtc)) |
988 | return PTR_ERR(ctx->crtc); | 1018 | return PTR_ERR(ctx->crtc); |
989 | 1019 | ||
1020 | if (ctx->driver_data->has_dp_clk) { | ||
1021 | ctx->dp_clk.enable = fimd_dp_clock_enable; | ||
1022 | ctx->crtc->pipe_clk = &ctx->dp_clk; | ||
1023 | } | ||
1024 | |||
990 | if (ctx->encoder) | 1025 | if (ctx->encoder) |
991 | exynos_dpi_bind(drm_dev, ctx->encoder); | 1026 | exynos_dpi_bind(drm_dev, ctx->encoder); |
992 | 1027 | ||
@@ -1035,7 +1070,7 @@ static int fimd_probe(struct platform_device *pdev) | |||
1035 | 1070 | ||
1036 | ctx->dev = dev; | 1071 | ctx->dev = dev; |
1037 | ctx->suspended = true; | 1072 | ctx->suspended = true; |
1038 | ctx->driver_data = drm_fimd_get_driver_data(pdev); | 1073 | ctx->driver_data = of_device_get_match_data(dev); |
1039 | 1074 | ||
1040 | if (of_property_read_bool(dev->of_node, "samsung,invert-vden")) | 1075 | if (of_property_read_bool(dev->of_node, "samsung,invert-vden")) |
1041 | ctx->vidcon1 |= VIDCON1_INV_VDEN; | 1076 | ctx->vidcon1 |= VIDCON1_INV_VDEN; |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c index 9869d70e9e54..a0def0be6d65 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_mic.c +++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c | |||
@@ -129,7 +129,7 @@ static void mic_set_path(struct exynos_mic *mic, bool enable) | |||
129 | } else | 129 | } else |
130 | val &= ~(MIC0_RGB_MUX | MIC0_I80_MUX | MIC0_ON_MUX); | 130 | val &= ~(MIC0_RGB_MUX | MIC0_I80_MUX | MIC0_ON_MUX); |
131 | 131 | ||
132 | regmap_write(mic->sysreg, DSD_CFG_MUX, val); | 132 | ret = regmap_write(mic->sysreg, DSD_CFG_MUX, val); |
133 | if (ret) | 133 | if (ret) |
134 | DRM_ERROR("mic: Failed to read system register\n"); | 134 | DRM_ERROR("mic: Failed to read system register\n"); |
135 | } | 135 | } |
@@ -457,6 +457,7 @@ static int exynos_mic_probe(struct platform_device *pdev) | |||
457 | "samsung,disp-syscon"); | 457 | "samsung,disp-syscon"); |
458 | if (IS_ERR(mic->sysreg)) { | 458 | if (IS_ERR(mic->sysreg)) { |
459 | DRM_ERROR("mic: Failed to get system register.\n"); | 459 | DRM_ERROR("mic: Failed to get system register.\n"); |
460 | ret = PTR_ERR(mic->sysreg); | ||
460 | goto err; | 461 | goto err; |
461 | } | 462 | } |
462 | 463 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index d86227236f55..50185ac347b2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c | |||
@@ -11,9 +11,10 @@ | |||
11 | 11 | ||
12 | #include <drm/drmP.h> | 12 | #include <drm/drmP.h> |
13 | 13 | ||
14 | #include <drm/exynos_drm.h> | 14 | #include <drm/drm_atomic.h> |
15 | #include <drm/drm_plane_helper.h> | ||
16 | #include <drm/drm_atomic_helper.h> | 15 | #include <drm/drm_atomic_helper.h> |
16 | #include <drm/drm_plane_helper.h> | ||
17 | #include <drm/exynos_drm.h> | ||
17 | #include "exynos_drm_drv.h" | 18 | #include "exynos_drm_drv.h" |
18 | #include "exynos_drm_crtc.h" | 19 | #include "exynos_drm_crtc.h" |
19 | #include "exynos_drm_fb.h" | 20 | #include "exynos_drm_fb.h" |
@@ -57,11 +58,12 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last) | |||
57 | } | 58 | } |
58 | 59 | ||
59 | static void exynos_plane_mode_set(struct exynos_drm_plane_state *exynos_state) | 60 | static void exynos_plane_mode_set(struct exynos_drm_plane_state *exynos_state) |
60 | |||
61 | { | 61 | { |
62 | struct drm_plane_state *state = &exynos_state->base; | 62 | struct drm_plane_state *state = &exynos_state->base; |
63 | struct drm_crtc *crtc = exynos_state->base.crtc; | 63 | struct drm_crtc *crtc = state->crtc; |
64 | struct drm_display_mode *mode = &crtc->state->adjusted_mode; | 64 | struct drm_crtc_state *crtc_state = |
65 | drm_atomic_get_existing_crtc_state(state->state, crtc); | ||
66 | struct drm_display_mode *mode = &crtc_state->adjusted_mode; | ||
65 | int crtc_x, crtc_y; | 67 | int crtc_x, crtc_y; |
66 | unsigned int crtc_w, crtc_h; | 68 | unsigned int crtc_w, crtc_h; |
67 | unsigned int src_x, src_y; | 69 | unsigned int src_x, src_y; |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c index f18fbe43f55f..404367a430b5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c +++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/of_device.h> | ||
18 | #include <linux/pm_runtime.h> | 19 | #include <linux/pm_runtime.h> |
19 | 20 | ||
20 | #include <drm/drmP.h> | 21 | #include <drm/drmP.h> |
@@ -696,7 +697,6 @@ static int rotator_probe(struct platform_device *pdev) | |||
696 | struct device *dev = &pdev->dev; | 697 | struct device *dev = &pdev->dev; |
697 | struct rot_context *rot; | 698 | struct rot_context *rot; |
698 | struct exynos_drm_ippdrv *ippdrv; | 699 | struct exynos_drm_ippdrv *ippdrv; |
699 | const struct of_device_id *match; | ||
700 | int ret; | 700 | int ret; |
701 | 701 | ||
702 | if (!dev->of_node) { | 702 | if (!dev->of_node) { |
@@ -708,13 +708,8 @@ static int rotator_probe(struct platform_device *pdev) | |||
708 | if (!rot) | 708 | if (!rot) |
709 | return -ENOMEM; | 709 | return -ENOMEM; |
710 | 710 | ||
711 | match = of_match_node(exynos_rotator_match, dev->of_node); | 711 | rot->limit_tbl = (struct rot_limit_table *) |
712 | if (!match) { | 712 | of_device_get_match_data(dev); |
713 | dev_err(dev, "failed to match node\n"); | ||
714 | return -ENODEV; | ||
715 | } | ||
716 | rot->limit_tbl = (struct rot_limit_table *)match->data; | ||
717 | |||
718 | rot->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 713 | rot->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
719 | rot->regs = devm_ioremap_resource(dev, rot->regs_res); | 714 | rot->regs = devm_ioremap_resource(dev, rot->regs_res); |
720 | if (IS_ERR(rot->regs)) | 715 | if (IS_ERR(rot->regs)) |
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index e148d728e28c..0f87acb4cf21 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c | |||
@@ -7,9 +7,9 @@ | |||
7 | * | 7 | * |
8 | * Based on drivers/media/video/s5p-tv/hdmi_drv.c | 8 | * Based on drivers/media/video/s5p-tv/hdmi_drv.c |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify it | 10 | * This program is free software; you can redistribute it and/or modify it |
11 | * under the terms of the GNU General Public License as published by the | 11 | * under the terms of the GNU General Public License as published by the |
12 | * Free Software Foundation; either version 2 of the License, or (at your | 12 | * Free Software Foundation; either version 2 of the License, or (at your |
13 | * option) any later version. | 13 | * option) any later version. |
14 | * | 14 | * |
15 | */ | 15 | */ |
@@ -49,14 +49,16 @@ | |||
49 | 49 | ||
50 | /* AVI header and aspect ratio */ | 50 | /* AVI header and aspect ratio */ |
51 | #define HDMI_AVI_VERSION 0x02 | 51 | #define HDMI_AVI_VERSION 0x02 |
52 | #define HDMI_AVI_LENGTH 0x0D | 52 | #define HDMI_AVI_LENGTH 0x0d |
53 | 53 | ||
54 | /* AUI header info */ | 54 | /* AUI header info */ |
55 | #define HDMI_AUI_VERSION 0x01 | 55 | #define HDMI_AUI_VERSION 0x01 |
56 | #define HDMI_AUI_LENGTH 0x0A | 56 | #define HDMI_AUI_LENGTH 0x0a |
57 | #define AVI_SAME_AS_PIC_ASPECT_RATIO 0x8 | 57 | |
58 | #define AVI_4_3_CENTER_RATIO 0x9 | 58 | /* AVI active format aspect ratio */ |
59 | #define AVI_16_9_CENTER_RATIO 0xa | 59 | #define AVI_SAME_AS_PIC_ASPECT_RATIO 0x08 |
60 | #define AVI_4_3_CENTER_RATIO 0x09 | ||
61 | #define AVI_16_9_CENTER_RATIO 0x0a | ||
60 | 62 | ||
61 | enum hdmi_type { | 63 | enum hdmi_type { |
62 | HDMI_TYPE13, | 64 | HDMI_TYPE13, |
@@ -90,11 +92,34 @@ static const char * const supply[] = { | |||
90 | "vdd_pll", | 92 | "vdd_pll", |
91 | }; | 93 | }; |
92 | 94 | ||
95 | struct hdmiphy_config { | ||
96 | int pixel_clock; | ||
97 | u8 conf[32]; | ||
98 | }; | ||
99 | |||
100 | struct hdmiphy_configs { | ||
101 | int count; | ||
102 | const struct hdmiphy_config *data; | ||
103 | }; | ||
104 | |||
105 | struct string_array_spec { | ||
106 | int count; | ||
107 | const char * const *data; | ||
108 | }; | ||
109 | |||
110 | #define INIT_ARRAY_SPEC(a) { .count = ARRAY_SIZE(a), .data = a } | ||
111 | |||
93 | struct hdmi_driver_data { | 112 | struct hdmi_driver_data { |
94 | unsigned int type; | 113 | unsigned int type; |
95 | const struct hdmiphy_config *phy_confs; | ||
96 | unsigned int phy_conf_count; | ||
97 | unsigned int is_apb_phy:1; | 114 | unsigned int is_apb_phy:1; |
115 | unsigned int has_sysreg:1; | ||
116 | struct hdmiphy_configs phy_confs; | ||
117 | struct string_array_spec clk_gates; | ||
118 | /* | ||
119 | * Array of triplets (p_off, p_on, clock), where p_off and p_on are | ||
120 | * required parents of clock when HDMI-PHY is respectively off or on. | ||
121 | */ | ||
122 | struct string_array_spec clk_muxes; | ||
98 | }; | 123 | }; |
99 | 124 | ||
100 | struct hdmi_context { | 125 | struct hdmi_context { |
@@ -116,11 +141,9 @@ struct hdmi_context { | |||
116 | struct gpio_desc *hpd_gpio; | 141 | struct gpio_desc *hpd_gpio; |
117 | int irq; | 142 | int irq; |
118 | struct regmap *pmureg; | 143 | struct regmap *pmureg; |
119 | struct clk *hdmi; | 144 | struct regmap *sysreg; |
120 | struct clk *sclk_hdmi; | 145 | struct clk **clk_gates; |
121 | struct clk *sclk_pixel; | 146 | struct clk **clk_muxes; |
122 | struct clk *sclk_hdmiphy; | ||
123 | struct clk *mout_hdmi; | ||
124 | struct regulator_bulk_data regul_bulk[ARRAY_SIZE(supply)]; | 147 | struct regulator_bulk_data regul_bulk[ARRAY_SIZE(supply)]; |
125 | struct regulator *reg_hdmi_en; | 148 | struct regulator *reg_hdmi_en; |
126 | }; | 149 | }; |
@@ -135,12 +158,6 @@ static inline struct hdmi_context *connector_to_hdmi(struct drm_connector *c) | |||
135 | return container_of(c, struct hdmi_context, connector); | 158 | return container_of(c, struct hdmi_context, connector); |
136 | } | 159 | } |
137 | 160 | ||
138 | struct hdmiphy_config { | ||
139 | int pixel_clock; | ||
140 | u8 conf[32]; | ||
141 | }; | ||
142 | |||
143 | /* list of phy config settings */ | ||
144 | static const struct hdmiphy_config hdmiphy_v13_configs[] = { | 161 | static const struct hdmiphy_config hdmiphy_v13_configs[] = { |
145 | { | 162 | { |
146 | .pixel_clock = 27000000, | 163 | .pixel_clock = 27000000, |
@@ -501,25 +518,136 @@ static const struct hdmiphy_config hdmiphy_5420_configs[] = { | |||
501 | }, | 518 | }, |
502 | }; | 519 | }; |
503 | 520 | ||
504 | static struct hdmi_driver_data exynos5420_hdmi_driver_data = { | 521 | static const struct hdmiphy_config hdmiphy_5433_configs[] = { |
522 | { | ||
523 | .pixel_clock = 27000000, | ||
524 | .conf = { | ||
525 | 0x01, 0x51, 0x22, 0x51, 0x08, 0xfc, 0x88, 0x46, | ||
526 | 0x72, 0x50, 0x24, 0x0c, 0x24, 0x0f, 0x7c, 0xa5, | ||
527 | 0xd4, 0x2b, 0x87, 0x00, 0x00, 0x04, 0x00, 0x30, | ||
528 | 0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40, | ||
529 | }, | ||
530 | }, | ||
531 | { | ||
532 | .pixel_clock = 27027000, | ||
533 | .conf = { | ||
534 | 0x01, 0x51, 0x2d, 0x72, 0x64, 0x09, 0x88, 0xc3, | ||
535 | 0x71, 0x50, 0x24, 0x14, 0x24, 0x0f, 0x7c, 0xa5, | ||
536 | 0xd4, 0x2b, 0x87, 0x00, 0x00, 0x04, 0x00, 0x30, | ||
537 | 0x28, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40, | ||
538 | }, | ||
539 | }, | ||
540 | { | ||
541 | .pixel_clock = 40000000, | ||
542 | .conf = { | ||
543 | 0x01, 0x51, 0x32, 0x55, 0x01, 0x00, 0x88, 0x02, | ||
544 | 0x4d, 0x50, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC, | ||
545 | 0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30, | ||
546 | 0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40, | ||
547 | }, | ||
548 | }, | ||
549 | { | ||
550 | .pixel_clock = 50000000, | ||
551 | .conf = { | ||
552 | 0x01, 0x51, 0x34, 0x40, 0x64, 0x09, 0x88, 0xc3, | ||
553 | 0x3d, 0x50, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC, | ||
554 | 0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30, | ||
555 | 0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40, | ||
556 | }, | ||
557 | }, | ||
558 | { | ||
559 | .pixel_clock = 65000000, | ||
560 | .conf = { | ||
561 | 0x01, 0x51, 0x36, 0x31, 0x40, 0x10, 0x04, 0xc6, | ||
562 | 0x2e, 0xe8, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC, | ||
563 | 0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30, | ||
564 | 0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40, | ||
565 | }, | ||
566 | }, | ||
567 | { | ||
568 | .pixel_clock = 74176000, | ||
569 | .conf = { | ||
570 | 0x01, 0x51, 0x3E, 0x35, 0x5B, 0xDE, 0x88, 0x42, | ||
571 | 0x53, 0x51, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC, | ||
572 | 0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30, | ||
573 | 0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40, | ||
574 | }, | ||
575 | }, | ||
576 | { | ||
577 | .pixel_clock = 74250000, | ||
578 | .conf = { | ||
579 | 0x01, 0x51, 0x3E, 0x35, 0x40, 0xF0, 0x88, 0xC2, | ||
580 | 0x52, 0x51, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC, | ||
581 | 0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30, | ||
582 | 0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40, | ||
583 | }, | ||
584 | }, | ||
585 | { | ||
586 | .pixel_clock = 108000000, | ||
587 | .conf = { | ||
588 | 0x01, 0x51, 0x2d, 0x15, 0x01, 0x00, 0x88, 0x02, | ||
589 | 0x72, 0x52, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC, | ||
590 | 0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30, | ||
591 | 0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40, | ||
592 | }, | ||
593 | }, | ||
594 | { | ||
595 | .pixel_clock = 148500000, | ||
596 | .conf = { | ||
597 | 0x01, 0x51, 0x1f, 0x00, 0x40, 0xf8, 0x88, 0xc1, | ||
598 | 0x52, 0x52, 0x24, 0x0c, 0x24, 0x0f, 0x7c, 0xa5, | ||
599 | 0xd4, 0x2b, 0x87, 0x00, 0x00, 0x04, 0x00, 0x30, | ||
600 | 0x08, 0x10, 0x01, 0x01, 0x48, 0x4a, 0x00, 0x40, | ||
601 | }, | ||
602 | }, | ||
603 | }; | ||
604 | |||
605 | static const char * const hdmi_clk_gates4[] = { | ||
606 | "hdmi", "sclk_hdmi" | ||
607 | }; | ||
608 | |||
609 | static const char * const hdmi_clk_muxes4[] = { | ||
610 | "sclk_pixel", "sclk_hdmiphy", "mout_hdmi" | ||
611 | }; | ||
612 | |||
613 | static const char * const hdmi_clk_gates5433[] = { | ||
614 | "hdmi_pclk", "hdmi_i_pclk", "i_tmds_clk", "i_pixel_clk", "i_spdif_clk" | ||
615 | }; | ||
616 | |||
617 | static const char * const hdmi_clk_muxes5433[] = { | ||
618 | "oscclk", "tmds_clko", "tmds_clko_user", | ||
619 | "oscclk", "pixel_clko", "pixel_clko_user" | ||
620 | }; | ||
621 | |||
622 | static const struct hdmi_driver_data exynos4210_hdmi_driver_data = { | ||
623 | .type = HDMI_TYPE13, | ||
624 | .phy_confs = INIT_ARRAY_SPEC(hdmiphy_v13_configs), | ||
625 | .clk_gates = INIT_ARRAY_SPEC(hdmi_clk_gates4), | ||
626 | .clk_muxes = INIT_ARRAY_SPEC(hdmi_clk_muxes4), | ||
627 | }; | ||
628 | |||
629 | static const struct hdmi_driver_data exynos4212_hdmi_driver_data = { | ||
505 | .type = HDMI_TYPE14, | 630 | .type = HDMI_TYPE14, |
506 | .phy_confs = hdmiphy_5420_configs, | 631 | .phy_confs = INIT_ARRAY_SPEC(hdmiphy_v14_configs), |
507 | .phy_conf_count = ARRAY_SIZE(hdmiphy_5420_configs), | 632 | .clk_gates = INIT_ARRAY_SPEC(hdmi_clk_gates4), |
508 | .is_apb_phy = 1, | 633 | .clk_muxes = INIT_ARRAY_SPEC(hdmi_clk_muxes4), |
509 | }; | 634 | }; |
510 | 635 | ||
511 | static struct hdmi_driver_data exynos4212_hdmi_driver_data = { | 636 | static const struct hdmi_driver_data exynos5420_hdmi_driver_data = { |
512 | .type = HDMI_TYPE14, | 637 | .type = HDMI_TYPE14, |
513 | .phy_confs = hdmiphy_v14_configs, | 638 | .is_apb_phy = 1, |
514 | .phy_conf_count = ARRAY_SIZE(hdmiphy_v14_configs), | 639 | .phy_confs = INIT_ARRAY_SPEC(hdmiphy_5420_configs), |
515 | .is_apb_phy = 0, | 640 | .clk_gates = INIT_ARRAY_SPEC(hdmi_clk_gates4), |
641 | .clk_muxes = INIT_ARRAY_SPEC(hdmi_clk_muxes4), | ||
516 | }; | 642 | }; |
517 | 643 | ||
518 | static struct hdmi_driver_data exynos4210_hdmi_driver_data = { | 644 | static const struct hdmi_driver_data exynos5433_hdmi_driver_data = { |
519 | .type = HDMI_TYPE13, | 645 | .type = HDMI_TYPE14, |
520 | .phy_confs = hdmiphy_v13_configs, | 646 | .is_apb_phy = 1, |
521 | .phy_conf_count = ARRAY_SIZE(hdmiphy_v13_configs), | 647 | .has_sysreg = 1, |
522 | .is_apb_phy = 0, | 648 | .phy_confs = INIT_ARRAY_SPEC(hdmiphy_5433_configs), |
649 | .clk_gates = INIT_ARRAY_SPEC(hdmi_clk_gates5433), | ||
650 | .clk_muxes = INIT_ARRAY_SPEC(hdmi_clk_muxes5433), | ||
523 | }; | 651 | }; |
524 | 652 | ||
525 | static inline u32 hdmi_map_reg(struct hdmi_context *hdata, u32 reg_id) | 653 | static inline u32 hdmi_map_reg(struct hdmi_context *hdata, u32 reg_id) |
@@ -585,266 +713,52 @@ static int hdmiphy_reg_write_buf(struct hdmi_context *hdata, | |||
585 | } | 713 | } |
586 | } | 714 | } |
587 | 715 | ||
588 | static void hdmi_v13_regs_dump(struct hdmi_context *hdata, char *prefix) | 716 | static int hdmi_clk_enable_gates(struct hdmi_context *hdata) |
589 | { | 717 | { |
590 | #define DUMPREG(reg_id) \ | 718 | int i, ret; |
591 | DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \ | 719 | |
592 | readl(hdata->regs + reg_id)) | 720 | for (i = 0; i < hdata->drv_data->clk_gates.count; ++i) { |
593 | DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix); | 721 | ret = clk_prepare_enable(hdata->clk_gates[i]); |
594 | DUMPREG(HDMI_INTC_FLAG); | 722 | if (!ret) |
595 | DUMPREG(HDMI_INTC_CON); | 723 | continue; |
596 | DUMPREG(HDMI_HPD_STATUS); | 724 | |
597 | DUMPREG(HDMI_V13_PHY_RSTOUT); | 725 | dev_err(hdata->dev, "Cannot enable clock '%s', %d\n", |
598 | DUMPREG(HDMI_V13_PHY_VPLL); | 726 | hdata->drv_data->clk_gates.data[i], ret); |
599 | DUMPREG(HDMI_V13_PHY_CMU); | 727 | while (i--) |
600 | DUMPREG(HDMI_V13_CORE_RSTOUT); | 728 | clk_disable_unprepare(hdata->clk_gates[i]); |
601 | 729 | return ret; | |
602 | DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix); | 730 | } |
603 | DUMPREG(HDMI_CON_0); | 731 | |
604 | DUMPREG(HDMI_CON_1); | 732 | return 0; |
605 | DUMPREG(HDMI_CON_2); | ||
606 | DUMPREG(HDMI_SYS_STATUS); | ||
607 | DUMPREG(HDMI_V13_PHY_STATUS); | ||
608 | DUMPREG(HDMI_STATUS_EN); | ||
609 | DUMPREG(HDMI_HPD); | ||
610 | DUMPREG(HDMI_MODE_SEL); | ||
611 | DUMPREG(HDMI_V13_HPD_GEN); | ||
612 | DUMPREG(HDMI_V13_DC_CONTROL); | ||
613 | DUMPREG(HDMI_V13_VIDEO_PATTERN_GEN); | ||
614 | |||
615 | DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix); | ||
616 | DUMPREG(HDMI_H_BLANK_0); | ||
617 | DUMPREG(HDMI_H_BLANK_1); | ||
618 | DUMPREG(HDMI_V13_V_BLANK_0); | ||
619 | DUMPREG(HDMI_V13_V_BLANK_1); | ||
620 | DUMPREG(HDMI_V13_V_BLANK_2); | ||
621 | DUMPREG(HDMI_V13_H_V_LINE_0); | ||
622 | DUMPREG(HDMI_V13_H_V_LINE_1); | ||
623 | DUMPREG(HDMI_V13_H_V_LINE_2); | ||
624 | DUMPREG(HDMI_VSYNC_POL); | ||
625 | DUMPREG(HDMI_INT_PRO_MODE); | ||
626 | DUMPREG(HDMI_V13_V_BLANK_F_0); | ||
627 | DUMPREG(HDMI_V13_V_BLANK_F_1); | ||
628 | DUMPREG(HDMI_V13_V_BLANK_F_2); | ||
629 | DUMPREG(HDMI_V13_H_SYNC_GEN_0); | ||
630 | DUMPREG(HDMI_V13_H_SYNC_GEN_1); | ||
631 | DUMPREG(HDMI_V13_H_SYNC_GEN_2); | ||
632 | DUMPREG(HDMI_V13_V_SYNC_GEN_1_0); | ||
633 | DUMPREG(HDMI_V13_V_SYNC_GEN_1_1); | ||
634 | DUMPREG(HDMI_V13_V_SYNC_GEN_1_2); | ||
635 | DUMPREG(HDMI_V13_V_SYNC_GEN_2_0); | ||
636 | DUMPREG(HDMI_V13_V_SYNC_GEN_2_1); | ||
637 | DUMPREG(HDMI_V13_V_SYNC_GEN_2_2); | ||
638 | DUMPREG(HDMI_V13_V_SYNC_GEN_3_0); | ||
639 | DUMPREG(HDMI_V13_V_SYNC_GEN_3_1); | ||
640 | DUMPREG(HDMI_V13_V_SYNC_GEN_3_2); | ||
641 | |||
642 | DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix); | ||
643 | DUMPREG(HDMI_TG_CMD); | ||
644 | DUMPREG(HDMI_TG_H_FSZ_L); | ||
645 | DUMPREG(HDMI_TG_H_FSZ_H); | ||
646 | DUMPREG(HDMI_TG_HACT_ST_L); | ||
647 | DUMPREG(HDMI_TG_HACT_ST_H); | ||
648 | DUMPREG(HDMI_TG_HACT_SZ_L); | ||
649 | DUMPREG(HDMI_TG_HACT_SZ_H); | ||
650 | DUMPREG(HDMI_TG_V_FSZ_L); | ||
651 | DUMPREG(HDMI_TG_V_FSZ_H); | ||
652 | DUMPREG(HDMI_TG_VSYNC_L); | ||
653 | DUMPREG(HDMI_TG_VSYNC_H); | ||
654 | DUMPREG(HDMI_TG_VSYNC2_L); | ||
655 | DUMPREG(HDMI_TG_VSYNC2_H); | ||
656 | DUMPREG(HDMI_TG_VACT_ST_L); | ||
657 | DUMPREG(HDMI_TG_VACT_ST_H); | ||
658 | DUMPREG(HDMI_TG_VACT_SZ_L); | ||
659 | DUMPREG(HDMI_TG_VACT_SZ_H); | ||
660 | DUMPREG(HDMI_TG_FIELD_CHG_L); | ||
661 | DUMPREG(HDMI_TG_FIELD_CHG_H); | ||
662 | DUMPREG(HDMI_TG_VACT_ST2_L); | ||
663 | DUMPREG(HDMI_TG_VACT_ST2_H); | ||
664 | DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L); | ||
665 | DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H); | ||
666 | DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L); | ||
667 | DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H); | ||
668 | DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L); | ||
669 | DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H); | ||
670 | DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L); | ||
671 | DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H); | ||
672 | #undef DUMPREG | ||
673 | } | 733 | } |
674 | 734 | ||
675 | static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix) | 735 | static void hdmi_clk_disable_gates(struct hdmi_context *hdata) |
676 | { | 736 | { |
677 | int i; | 737 | int i = hdata->drv_data->clk_gates.count; |
678 | 738 | ||
679 | #define DUMPREG(reg_id) \ | 739 | while (i--) |
680 | DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \ | 740 | clk_disable_unprepare(hdata->clk_gates[i]); |
681 | readl(hdata->regs + reg_id)) | ||
682 | |||
683 | DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix); | ||
684 | DUMPREG(HDMI_INTC_CON); | ||
685 | DUMPREG(HDMI_INTC_FLAG); | ||
686 | DUMPREG(HDMI_HPD_STATUS); | ||
687 | DUMPREG(HDMI_INTC_CON_1); | ||
688 | DUMPREG(HDMI_INTC_FLAG_1); | ||
689 | DUMPREG(HDMI_PHY_STATUS_0); | ||
690 | DUMPREG(HDMI_PHY_STATUS_PLL); | ||
691 | DUMPREG(HDMI_PHY_CON_0); | ||
692 | DUMPREG(HDMI_V14_PHY_RSTOUT); | ||
693 | DUMPREG(HDMI_PHY_VPLL); | ||
694 | DUMPREG(HDMI_PHY_CMU); | ||
695 | DUMPREG(HDMI_CORE_RSTOUT); | ||
696 | |||
697 | DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix); | ||
698 | DUMPREG(HDMI_CON_0); | ||
699 | DUMPREG(HDMI_CON_1); | ||
700 | DUMPREG(HDMI_CON_2); | ||
701 | DUMPREG(HDMI_SYS_STATUS); | ||
702 | DUMPREG(HDMI_PHY_STATUS_0); | ||
703 | DUMPREG(HDMI_STATUS_EN); | ||
704 | DUMPREG(HDMI_HPD); | ||
705 | DUMPREG(HDMI_MODE_SEL); | ||
706 | DUMPREG(HDMI_ENC_EN); | ||
707 | DUMPREG(HDMI_DC_CONTROL); | ||
708 | DUMPREG(HDMI_VIDEO_PATTERN_GEN); | ||
709 | |||
710 | DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix); | ||
711 | DUMPREG(HDMI_H_BLANK_0); | ||
712 | DUMPREG(HDMI_H_BLANK_1); | ||
713 | DUMPREG(HDMI_V2_BLANK_0); | ||
714 | DUMPREG(HDMI_V2_BLANK_1); | ||
715 | DUMPREG(HDMI_V1_BLANK_0); | ||
716 | DUMPREG(HDMI_V1_BLANK_1); | ||
717 | DUMPREG(HDMI_V_LINE_0); | ||
718 | DUMPREG(HDMI_V_LINE_1); | ||
719 | DUMPREG(HDMI_H_LINE_0); | ||
720 | DUMPREG(HDMI_H_LINE_1); | ||
721 | DUMPREG(HDMI_HSYNC_POL); | ||
722 | |||
723 | DUMPREG(HDMI_VSYNC_POL); | ||
724 | DUMPREG(HDMI_INT_PRO_MODE); | ||
725 | DUMPREG(HDMI_V_BLANK_F0_0); | ||
726 | DUMPREG(HDMI_V_BLANK_F0_1); | ||
727 | DUMPREG(HDMI_V_BLANK_F1_0); | ||
728 | DUMPREG(HDMI_V_BLANK_F1_1); | ||
729 | |||
730 | DUMPREG(HDMI_H_SYNC_START_0); | ||
731 | DUMPREG(HDMI_H_SYNC_START_1); | ||
732 | DUMPREG(HDMI_H_SYNC_END_0); | ||
733 | DUMPREG(HDMI_H_SYNC_END_1); | ||
734 | |||
735 | DUMPREG(HDMI_V_SYNC_LINE_BEF_2_0); | ||
736 | DUMPREG(HDMI_V_SYNC_LINE_BEF_2_1); | ||
737 | DUMPREG(HDMI_V_SYNC_LINE_BEF_1_0); | ||
738 | DUMPREG(HDMI_V_SYNC_LINE_BEF_1_1); | ||
739 | |||
740 | DUMPREG(HDMI_V_SYNC_LINE_AFT_2_0); | ||
741 | DUMPREG(HDMI_V_SYNC_LINE_AFT_2_1); | ||
742 | DUMPREG(HDMI_V_SYNC_LINE_AFT_1_0); | ||
743 | DUMPREG(HDMI_V_SYNC_LINE_AFT_1_1); | ||
744 | |||
745 | DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_0); | ||
746 | DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_1); | ||
747 | DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_0); | ||
748 | DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_1); | ||
749 | |||
750 | DUMPREG(HDMI_V_BLANK_F2_0); | ||
751 | DUMPREG(HDMI_V_BLANK_F2_1); | ||
752 | DUMPREG(HDMI_V_BLANK_F3_0); | ||
753 | DUMPREG(HDMI_V_BLANK_F3_1); | ||
754 | DUMPREG(HDMI_V_BLANK_F4_0); | ||
755 | DUMPREG(HDMI_V_BLANK_F4_1); | ||
756 | DUMPREG(HDMI_V_BLANK_F5_0); | ||
757 | DUMPREG(HDMI_V_BLANK_F5_1); | ||
758 | |||
759 | DUMPREG(HDMI_V_SYNC_LINE_AFT_3_0); | ||
760 | DUMPREG(HDMI_V_SYNC_LINE_AFT_3_1); | ||
761 | DUMPREG(HDMI_V_SYNC_LINE_AFT_4_0); | ||
762 | DUMPREG(HDMI_V_SYNC_LINE_AFT_4_1); | ||
763 | DUMPREG(HDMI_V_SYNC_LINE_AFT_5_0); | ||
764 | DUMPREG(HDMI_V_SYNC_LINE_AFT_5_1); | ||
765 | DUMPREG(HDMI_V_SYNC_LINE_AFT_6_0); | ||
766 | DUMPREG(HDMI_V_SYNC_LINE_AFT_6_1); | ||
767 | |||
768 | DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_0); | ||
769 | DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_1); | ||
770 | DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_0); | ||
771 | DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_1); | ||
772 | DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_0); | ||
773 | DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_1); | ||
774 | DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_0); | ||
775 | DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_1); | ||
776 | |||
777 | DUMPREG(HDMI_VACT_SPACE_1_0); | ||
778 | DUMPREG(HDMI_VACT_SPACE_1_1); | ||
779 | DUMPREG(HDMI_VACT_SPACE_2_0); | ||
780 | DUMPREG(HDMI_VACT_SPACE_2_1); | ||
781 | DUMPREG(HDMI_VACT_SPACE_3_0); | ||
782 | DUMPREG(HDMI_VACT_SPACE_3_1); | ||
783 | DUMPREG(HDMI_VACT_SPACE_4_0); | ||
784 | DUMPREG(HDMI_VACT_SPACE_4_1); | ||
785 | DUMPREG(HDMI_VACT_SPACE_5_0); | ||
786 | DUMPREG(HDMI_VACT_SPACE_5_1); | ||
787 | DUMPREG(HDMI_VACT_SPACE_6_0); | ||
788 | DUMPREG(HDMI_VACT_SPACE_6_1); | ||
789 | |||
790 | DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix); | ||
791 | DUMPREG(HDMI_TG_CMD); | ||
792 | DUMPREG(HDMI_TG_H_FSZ_L); | ||
793 | DUMPREG(HDMI_TG_H_FSZ_H); | ||
794 | DUMPREG(HDMI_TG_HACT_ST_L); | ||
795 | DUMPREG(HDMI_TG_HACT_ST_H); | ||
796 | DUMPREG(HDMI_TG_HACT_SZ_L); | ||
797 | DUMPREG(HDMI_TG_HACT_SZ_H); | ||
798 | DUMPREG(HDMI_TG_V_FSZ_L); | ||
799 | DUMPREG(HDMI_TG_V_FSZ_H); | ||
800 | DUMPREG(HDMI_TG_VSYNC_L); | ||
801 | DUMPREG(HDMI_TG_VSYNC_H); | ||
802 | DUMPREG(HDMI_TG_VSYNC2_L); | ||
803 | DUMPREG(HDMI_TG_VSYNC2_H); | ||
804 | DUMPREG(HDMI_TG_VACT_ST_L); | ||
805 | DUMPREG(HDMI_TG_VACT_ST_H); | ||
806 | DUMPREG(HDMI_TG_VACT_SZ_L); | ||
807 | DUMPREG(HDMI_TG_VACT_SZ_H); | ||
808 | DUMPREG(HDMI_TG_FIELD_CHG_L); | ||
809 | DUMPREG(HDMI_TG_FIELD_CHG_H); | ||
810 | DUMPREG(HDMI_TG_VACT_ST2_L); | ||
811 | DUMPREG(HDMI_TG_VACT_ST2_H); | ||
812 | DUMPREG(HDMI_TG_VACT_ST3_L); | ||
813 | DUMPREG(HDMI_TG_VACT_ST3_H); | ||
814 | DUMPREG(HDMI_TG_VACT_ST4_L); | ||
815 | DUMPREG(HDMI_TG_VACT_ST4_H); | ||
816 | DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L); | ||
817 | DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H); | ||
818 | DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L); | ||
819 | DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H); | ||
820 | DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L); | ||
821 | DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H); | ||
822 | DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L); | ||
823 | DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H); | ||
824 | DUMPREG(HDMI_TG_3D); | ||
825 | |||
826 | DRM_DEBUG_KMS("%s: ---- PACKET REGISTERS ----\n", prefix); | ||
827 | DUMPREG(HDMI_AVI_CON); | ||
828 | DUMPREG(HDMI_AVI_HEADER0); | ||
829 | DUMPREG(HDMI_AVI_HEADER1); | ||
830 | DUMPREG(HDMI_AVI_HEADER2); | ||
831 | DUMPREG(HDMI_AVI_CHECK_SUM); | ||
832 | DUMPREG(HDMI_VSI_CON); | ||
833 | DUMPREG(HDMI_VSI_HEADER0); | ||
834 | DUMPREG(HDMI_VSI_HEADER1); | ||
835 | DUMPREG(HDMI_VSI_HEADER2); | ||
836 | for (i = 0; i < 7; ++i) | ||
837 | DUMPREG(HDMI_VSI_DATA(i)); | ||
838 | |||
839 | #undef DUMPREG | ||
840 | } | 741 | } |
841 | 742 | ||
842 | static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix) | 743 | static int hdmi_clk_set_parents(struct hdmi_context *hdata, bool to_phy) |
843 | { | 744 | { |
844 | if (hdata->drv_data->type == HDMI_TYPE13) | 745 | struct device *dev = hdata->dev; |
845 | hdmi_v13_regs_dump(hdata, prefix); | 746 | int ret = 0; |
846 | else | 747 | int i; |
847 | hdmi_v14_regs_dump(hdata, prefix); | 748 | |
749 | for (i = 0; i < hdata->drv_data->clk_muxes.count; i += 3) { | ||
750 | struct clk **c = &hdata->clk_muxes[i]; | ||
751 | |||
752 | ret = clk_set_parent(c[2], c[to_phy]); | ||
753 | if (!ret) | ||
754 | continue; | ||
755 | |||
756 | dev_err(dev, "Cannot set clock parent of '%s' to '%s', %d\n", | ||
757 | hdata->drv_data->clk_muxes.data[i + 2], | ||
758 | hdata->drv_data->clk_muxes.data[i + to_phy], ret); | ||
759 | } | ||
760 | |||
761 | return ret; | ||
848 | } | 762 | } |
849 | 763 | ||
850 | static u8 hdmi_chksum(struct hdmi_context *hdata, | 764 | static u8 hdmi_chksum(struct hdmi_context *hdata, |
@@ -993,10 +907,11 @@ static int hdmi_get_modes(struct drm_connector *connector) | |||
993 | 907 | ||
994 | static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock) | 908 | static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock) |
995 | { | 909 | { |
910 | const struct hdmiphy_configs *confs = &hdata->drv_data->phy_confs; | ||
996 | int i; | 911 | int i; |
997 | 912 | ||
998 | for (i = 0; i < hdata->drv_data->phy_conf_count; i++) | 913 | for (i = 0; i < confs->count; i++) |
999 | if (hdata->drv_data->phy_confs[i].pixel_clock == pixel_clock) | 914 | if (confs->data[i].pixel_clock == pixel_clock) |
1000 | return i; | 915 | return i; |
1001 | 916 | ||
1002 | DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock); | 917 | DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock); |
@@ -1078,13 +993,11 @@ static bool hdmi_mode_fixup(struct drm_encoder *encoder, | |||
1078 | 993 | ||
1079 | mode_ok = hdmi_mode_valid(connector, adjusted_mode); | 994 | mode_ok = hdmi_mode_valid(connector, adjusted_mode); |
1080 | 995 | ||
1081 | /* just return if user desired mode exists. */ | ||
1082 | if (mode_ok == MODE_OK) | 996 | if (mode_ok == MODE_OK) |
1083 | return true; | 997 | return true; |
1084 | 998 | ||
1085 | /* | 999 | /* |
1086 | * otherwise, find the most suitable mode among modes and change it | 1000 | * Find the most suitable mode and copy it to adjusted_mode. |
1087 | * to adjusted_mode. | ||
1088 | */ | 1001 | */ |
1089 | list_for_each_entry(m, &connector->modes, head) { | 1002 | list_for_each_entry(m, &connector->modes, head) { |
1090 | mode_ok = hdmi_mode_valid(connector, m); | 1003 | mode_ok = hdmi_mode_valid(connector, m); |
@@ -1129,15 +1042,15 @@ static void hdmi_audio_init(struct hdmi_context *hdata) | |||
1129 | switch (bits_per_sample) { | 1042 | switch (bits_per_sample) { |
1130 | case 20: | 1043 | case 20: |
1131 | data_num = 2; | 1044 | data_num = 2; |
1132 | bit_ch = 1; | 1045 | bit_ch = 1; |
1133 | break; | 1046 | break; |
1134 | case 24: | 1047 | case 24: |
1135 | data_num = 3; | 1048 | data_num = 3; |
1136 | bit_ch = 1; | 1049 | bit_ch = 1; |
1137 | break; | 1050 | break; |
1138 | default: | 1051 | default: |
1139 | data_num = 1; | 1052 | data_num = 1; |
1140 | bit_ch = 0; | 1053 | bit_ch = 0; |
1141 | break; | 1054 | break; |
1142 | } | 1055 | } |
1143 | 1056 | ||
@@ -1230,13 +1143,12 @@ static void hdmi_conf_init(struct hdmi_context *hdata) | |||
1230 | /* choose HDMI mode */ | 1143 | /* choose HDMI mode */ |
1231 | hdmi_reg_writemask(hdata, HDMI_MODE_SEL, | 1144 | hdmi_reg_writemask(hdata, HDMI_MODE_SEL, |
1232 | HDMI_MODE_HDMI_EN, HDMI_MODE_MASK); | 1145 | HDMI_MODE_HDMI_EN, HDMI_MODE_MASK); |
1233 | /* Apply Video preable and Guard band in HDMI mode only */ | 1146 | /* apply video pre-amble and guard band in HDMI mode only */ |
1234 | hdmi_reg_writeb(hdata, HDMI_CON_2, 0); | 1147 | hdmi_reg_writeb(hdata, HDMI_CON_2, 0); |
1235 | /* disable bluescreen */ | 1148 | /* disable bluescreen */ |
1236 | hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN); | 1149 | hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN); |
1237 | 1150 | ||
1238 | if (hdata->dvi_mode) { | 1151 | if (hdata->dvi_mode) { |
1239 | /* choose DVI mode */ | ||
1240 | hdmi_reg_writemask(hdata, HDMI_MODE_SEL, | 1152 | hdmi_reg_writemask(hdata, HDMI_MODE_SEL, |
1241 | HDMI_MODE_DVI_EN, HDMI_MODE_MASK); | 1153 | HDMI_MODE_DVI_EN, HDMI_MODE_MASK); |
1242 | hdmi_reg_writeb(hdata, HDMI_CON_2, | 1154 | hdmi_reg_writeb(hdata, HDMI_CON_2, |
@@ -1308,7 +1220,7 @@ static void hdmi_v13_mode_apply(struct hdmi_context *hdata) | |||
1308 | 1220 | ||
1309 | val = (m->hsync_start - m->hdisplay - 2); | 1221 | val = (m->hsync_start - m->hdisplay - 2); |
1310 | val |= ((m->hsync_end - m->hdisplay - 2) << 10); | 1222 | val |= ((m->hsync_end - m->hdisplay - 2) << 10); |
1311 | val |= ((m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0)<<20; | 1223 | val |= ((m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0)<<20; |
1312 | hdmi_reg_writev(hdata, HDMI_V13_H_SYNC_GEN_0, 3, val); | 1224 | hdmi_reg_writev(hdata, HDMI_V13_H_SYNC_GEN_0, 3, val); |
1313 | 1225 | ||
1314 | /* | 1226 | /* |
@@ -1319,7 +1231,6 @@ static void hdmi_v13_mode_apply(struct hdmi_context *hdata) | |||
1319 | 1231 | ||
1320 | /* Following values & calculations differ for different type of modes */ | 1232 | /* Following values & calculations differ for different type of modes */ |
1321 | if (m->flags & DRM_MODE_FLAG_INTERLACE) { | 1233 | if (m->flags & DRM_MODE_FLAG_INTERLACE) { |
1322 | /* Interlaced Mode */ | ||
1323 | val = ((m->vsync_end - m->vdisplay) / 2); | 1234 | val = ((m->vsync_end - m->vdisplay) / 2); |
1324 | val |= ((m->vsync_start - m->vdisplay) / 2) << 12; | 1235 | val |= ((m->vsync_start - m->vdisplay) / 2) << 12; |
1325 | hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_1_0, 3, val); | 1236 | hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_1_0, 3, val); |
@@ -1348,8 +1259,6 @@ static void hdmi_v13_mode_apply(struct hdmi_context *hdata) | |||
1348 | 1259 | ||
1349 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x249); | 1260 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x249); |
1350 | } else { | 1261 | } else { |
1351 | /* Progressive Mode */ | ||
1352 | |||
1353 | val = m->vtotal; | 1262 | val = m->vtotal; |
1354 | val |= (m->vtotal - m->vdisplay) << 11; | 1263 | val |= (m->vtotal - m->vdisplay) << 11; |
1355 | hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_0, 3, val); | 1264 | hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_0, 3, val); |
@@ -1365,21 +1274,12 @@ static void hdmi_v13_mode_apply(struct hdmi_context *hdata) | |||
1365 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2, | 1274 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2, |
1366 | m->vtotal - m->vdisplay); | 1275 | m->vtotal - m->vdisplay); |
1367 | hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay); | 1276 | hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay); |
1368 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x248); | ||
1369 | } | 1277 | } |
1370 | 1278 | ||
1371 | /* Timing generator registers */ | ||
1372 | hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal); | 1279 | hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal); |
1373 | hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay); | 1280 | hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay); |
1374 | hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay); | 1281 | hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay); |
1375 | hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal); | 1282 | hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal); |
1376 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC_L, 2, 0x1); | ||
1377 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC2_L, 2, 0x233); | ||
1378 | hdmi_reg_writev(hdata, HDMI_TG_FIELD_CHG_L, 2, 0x233); | ||
1379 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, 2, 0x1); | ||
1380 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, 2, 0x233); | ||
1381 | hdmi_reg_writev(hdata, HDMI_TG_FIELD_TOP_HDMI_L, 2, 0x1); | ||
1382 | hdmi_reg_writev(hdata, HDMI_TG_FIELD_BOT_HDMI_L, 2, 0x233); | ||
1383 | } | 1283 | } |
1384 | 1284 | ||
1385 | static void hdmi_v14_mode_apply(struct hdmi_context *hdata) | 1285 | static void hdmi_v14_mode_apply(struct hdmi_context *hdata) |
@@ -1390,7 +1290,7 @@ static void hdmi_v14_mode_apply(struct hdmi_context *hdata) | |||
1390 | hdmi_reg_writev(hdata, HDMI_V_LINE_0, 2, m->vtotal); | 1290 | hdmi_reg_writev(hdata, HDMI_V_LINE_0, 2, m->vtotal); |
1391 | hdmi_reg_writev(hdata, HDMI_H_LINE_0, 2, m->htotal); | 1291 | hdmi_reg_writev(hdata, HDMI_H_LINE_0, 2, m->htotal); |
1392 | hdmi_reg_writev(hdata, HDMI_HSYNC_POL, 1, | 1292 | hdmi_reg_writev(hdata, HDMI_HSYNC_POL, 1, |
1393 | (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0); | 1293 | (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0); |
1394 | hdmi_reg_writev(hdata, HDMI_VSYNC_POL, 1, | 1294 | hdmi_reg_writev(hdata, HDMI_VSYNC_POL, 1, |
1395 | (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0); | 1295 | (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0); |
1396 | hdmi_reg_writev(hdata, HDMI_INT_PRO_MODE, 1, | 1296 | hdmi_reg_writev(hdata, HDMI_INT_PRO_MODE, 1, |
@@ -1404,7 +1304,6 @@ static void hdmi_v14_mode_apply(struct hdmi_context *hdata) | |||
1404 | 1304 | ||
1405 | /* Following values & calculations differ for different type of modes */ | 1305 | /* Following values & calculations differ for different type of modes */ |
1406 | if (m->flags & DRM_MODE_FLAG_INTERLACE) { | 1306 | if (m->flags & DRM_MODE_FLAG_INTERLACE) { |
1407 | /* Interlaced Mode */ | ||
1408 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2, | 1307 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2, |
1409 | (m->vsync_end - m->vdisplay) / 2); | 1308 | (m->vsync_end - m->vdisplay) / 2); |
1410 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2, | 1309 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2, |
@@ -1437,7 +1336,6 @@ static void hdmi_v14_mode_apply(struct hdmi_context *hdata) | |||
1437 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST3_L, 2, 0x0); | 1336 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST3_L, 2, 0x0); |
1438 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST4_L, 2, 0x0); | 1337 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST4_L, 2, 0x0); |
1439 | } else { | 1338 | } else { |
1440 | /* Progressive Mode */ | ||
1441 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2, | 1339 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2, |
1442 | m->vsync_end - m->vdisplay); | 1340 | m->vsync_end - m->vdisplay); |
1443 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2, | 1341 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2, |
@@ -1454,15 +1352,8 @@ static void hdmi_v14_mode_apply(struct hdmi_context *hdata) | |||
1454 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2, | 1352 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2, |
1455 | m->vtotal - m->vdisplay); | 1353 | m->vtotal - m->vdisplay); |
1456 | hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay); | 1354 | hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay); |
1457 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x248); | ||
1458 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST3_L, 2, 0x47b); | ||
1459 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST4_L, 2, 0x6ae); | ||
1460 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC2_L, 2, 0x233); | ||
1461 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, 2, 0x233); | ||
1462 | hdmi_reg_writev(hdata, HDMI_TG_FIELD_BOT_HDMI_L, 2, 0x233); | ||
1463 | } | 1355 | } |
1464 | 1356 | ||
1465 | /* Following values & calculations are same irrespective of mode type */ | ||
1466 | hdmi_reg_writev(hdata, HDMI_H_SYNC_START_0, 2, | 1357 | hdmi_reg_writev(hdata, HDMI_H_SYNC_START_0, 2, |
1467 | m->hsync_start - m->hdisplay - 2); | 1358 | m->hsync_start - m->hdisplay - 2); |
1468 | hdmi_reg_writev(hdata, HDMI_H_SYNC_END_0, 2, | 1359 | hdmi_reg_writev(hdata, HDMI_H_SYNC_END_0, 2, |
@@ -1486,16 +1377,12 @@ static void hdmi_v14_mode_apply(struct hdmi_context *hdata) | |||
1486 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0, 2, 0xffff); | 1377 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0, 2, 0xffff); |
1487 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0, 2, 0xffff); | 1378 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0, 2, 0xffff); |
1488 | 1379 | ||
1489 | /* Timing generator registers */ | ||
1490 | hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal); | 1380 | hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal); |
1491 | hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay); | 1381 | hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay); |
1492 | hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay); | 1382 | hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay); |
1493 | hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal); | 1383 | hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal); |
1494 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC_L, 2, 0x1); | 1384 | if (hdata->drv_data == &exynos5433_hdmi_driver_data) |
1495 | hdmi_reg_writev(hdata, HDMI_TG_FIELD_CHG_L, 2, 0x233); | 1385 | hdmi_reg_writeb(hdata, HDMI_TG_DECON_EN, 1); |
1496 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, 2, 0x1); | ||
1497 | hdmi_reg_writev(hdata, HDMI_TG_FIELD_TOP_HDMI_L, 2, 0x1); | ||
1498 | hdmi_reg_writev(hdata, HDMI_TG_3D, 1, 0x0); | ||
1499 | } | 1386 | } |
1500 | 1387 | ||
1501 | static void hdmi_mode_apply(struct hdmi_context *hdata) | 1388 | static void hdmi_mode_apply(struct hdmi_context *hdata) |
@@ -1505,62 +1392,65 @@ static void hdmi_mode_apply(struct hdmi_context *hdata) | |||
1505 | else | 1392 | else |
1506 | hdmi_v14_mode_apply(hdata); | 1393 | hdmi_v14_mode_apply(hdata); |
1507 | 1394 | ||
1508 | hdmiphy_wait_for_pll(hdata); | ||
1509 | |||
1510 | clk_set_parent(hdata->mout_hdmi, hdata->sclk_hdmiphy); | ||
1511 | |||
1512 | /* enable HDMI and timing generator */ | ||
1513 | hdmi_start(hdata, true); | 1395 | hdmi_start(hdata, true); |
1514 | } | 1396 | } |
1515 | 1397 | ||
1516 | static void hdmiphy_conf_reset(struct hdmi_context *hdata) | 1398 | static void hdmiphy_conf_reset(struct hdmi_context *hdata) |
1517 | { | 1399 | { |
1518 | clk_set_parent(hdata->mout_hdmi, hdata->sclk_pixel); | 1400 | hdmi_reg_writemask(hdata, HDMI_CORE_RSTOUT, 0, 1); |
1519 | 1401 | usleep_range(10000, 12000); | |
1520 | /* reset hdmiphy */ | 1402 | hdmi_reg_writemask(hdata, HDMI_CORE_RSTOUT, ~0, 1); |
1403 | usleep_range(10000, 12000); | ||
1521 | hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT); | 1404 | hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT); |
1522 | usleep_range(10000, 12000); | 1405 | usleep_range(10000, 12000); |
1523 | hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, 0, HDMI_PHY_SW_RSTOUT); | 1406 | hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, 0, HDMI_PHY_SW_RSTOUT); |
1524 | usleep_range(10000, 12000); | 1407 | usleep_range(10000, 12000); |
1525 | } | 1408 | } |
1526 | 1409 | ||
1410 | static void hdmiphy_enable_mode_set(struct hdmi_context *hdata, bool enable) | ||
1411 | { | ||
1412 | u8 v = enable ? HDMI_PHY_ENABLE_MODE_SET : HDMI_PHY_DISABLE_MODE_SET; | ||
1413 | |||
1414 | if (hdata->drv_data == &exynos5433_hdmi_driver_data) | ||
1415 | writel(v, hdata->regs_hdmiphy + HDMIPHY5433_MODE_SET_DONE); | ||
1416 | } | ||
1417 | |||
1527 | static void hdmiphy_conf_apply(struct hdmi_context *hdata) | 1418 | static void hdmiphy_conf_apply(struct hdmi_context *hdata) |
1528 | { | 1419 | { |
1529 | int ret; | 1420 | int ret; |
1530 | int i; | 1421 | const u8 *phy_conf; |
1531 | 1422 | ||
1532 | /* pixel clock */ | 1423 | ret = hdmi_find_phy_conf(hdata, hdata->current_mode.clock * 1000); |
1533 | i = hdmi_find_phy_conf(hdata, hdata->current_mode.clock * 1000); | 1424 | if (ret < 0) { |
1534 | if (i < 0) { | ||
1535 | DRM_ERROR("failed to find hdmiphy conf\n"); | 1425 | DRM_ERROR("failed to find hdmiphy conf\n"); |
1536 | return; | 1426 | return; |
1537 | } | 1427 | } |
1428 | phy_conf = hdata->drv_data->phy_confs.data[ret].conf; | ||
1429 | |||
1430 | hdmi_clk_set_parents(hdata, false); | ||
1431 | |||
1432 | hdmiphy_conf_reset(hdata); | ||
1538 | 1433 | ||
1539 | ret = hdmiphy_reg_write_buf(hdata, 0, | 1434 | hdmiphy_enable_mode_set(hdata, true); |
1540 | hdata->drv_data->phy_confs[i].conf, 32); | 1435 | ret = hdmiphy_reg_write_buf(hdata, 0, phy_conf, 32); |
1541 | if (ret) { | 1436 | if (ret) { |
1542 | DRM_ERROR("failed to configure hdmiphy\n"); | 1437 | DRM_ERROR("failed to configure hdmiphy\n"); |
1543 | return; | 1438 | return; |
1544 | } | 1439 | } |
1545 | 1440 | hdmiphy_enable_mode_set(hdata, false); | |
1441 | hdmi_clk_set_parents(hdata, true); | ||
1546 | usleep_range(10000, 12000); | 1442 | usleep_range(10000, 12000); |
1443 | hdmiphy_wait_for_pll(hdata); | ||
1547 | } | 1444 | } |
1548 | 1445 | ||
1549 | static void hdmi_conf_apply(struct hdmi_context *hdata) | 1446 | static void hdmi_conf_apply(struct hdmi_context *hdata) |
1550 | { | 1447 | { |
1551 | hdmiphy_conf_reset(hdata); | ||
1552 | hdmiphy_conf_apply(hdata); | 1448 | hdmiphy_conf_apply(hdata); |
1553 | |||
1554 | hdmi_start(hdata, false); | 1449 | hdmi_start(hdata, false); |
1555 | hdmi_conf_init(hdata); | 1450 | hdmi_conf_init(hdata); |
1556 | |||
1557 | hdmi_audio_init(hdata); | 1451 | hdmi_audio_init(hdata); |
1558 | |||
1559 | /* setting core registers */ | ||
1560 | hdmi_mode_apply(hdata); | 1452 | hdmi_mode_apply(hdata); |
1561 | hdmi_audio_control(hdata, true); | 1453 | hdmi_audio_control(hdata, true); |
1562 | |||
1563 | hdmi_regs_dump(hdata, "start"); | ||
1564 | } | 1454 | } |
1565 | 1455 | ||
1566 | static void hdmi_mode_set(struct drm_encoder *encoder, | 1456 | static void hdmi_mode_set(struct drm_encoder *encoder, |
@@ -1579,6 +1469,15 @@ static void hdmi_mode_set(struct drm_encoder *encoder, | |||
1579 | hdata->cea_video_id = drm_match_cea_mode(mode); | 1469 | hdata->cea_video_id = drm_match_cea_mode(mode); |
1580 | } | 1470 | } |
1581 | 1471 | ||
1472 | static void hdmi_set_refclk(struct hdmi_context *hdata, bool on) | ||
1473 | { | ||
1474 | if (!hdata->sysreg) | ||
1475 | return; | ||
1476 | |||
1477 | regmap_update_bits(hdata->sysreg, EXYNOS5433_SYSREG_DISP_HDMI_PHY, | ||
1478 | SYSREG_HDMI_REFCLK_INT_CLK, on ? ~0 : 0); | ||
1479 | } | ||
1480 | |||
1582 | static void hdmi_enable(struct drm_encoder *encoder) | 1481 | static void hdmi_enable(struct drm_encoder *encoder) |
1583 | { | 1482 | { |
1584 | struct hdmi_context *hdata = encoder_to_hdmi(encoder); | 1483 | struct hdmi_context *hdata = encoder_to_hdmi(encoder); |
@@ -1591,10 +1490,13 @@ static void hdmi_enable(struct drm_encoder *encoder) | |||
1591 | if (regulator_bulk_enable(ARRAY_SIZE(supply), hdata->regul_bulk)) | 1490 | if (regulator_bulk_enable(ARRAY_SIZE(supply), hdata->regul_bulk)) |
1592 | DRM_DEBUG_KMS("failed to enable regulator bulk\n"); | 1491 | DRM_DEBUG_KMS("failed to enable regulator bulk\n"); |
1593 | 1492 | ||
1594 | /* set pmu hdmiphy control bit to enable hdmiphy */ | ||
1595 | regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL, | 1493 | regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL, |
1596 | PMU_HDMI_PHY_ENABLE_BIT, 1); | 1494 | PMU_HDMI_PHY_ENABLE_BIT, 1); |
1597 | 1495 | ||
1496 | hdmi_set_refclk(hdata, true); | ||
1497 | |||
1498 | hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0, HDMI_PHY_POWER_OFF_EN); | ||
1499 | |||
1598 | hdmi_conf_apply(hdata); | 1500 | hdmi_conf_apply(hdata); |
1599 | 1501 | ||
1600 | hdata->powered = true; | 1502 | hdata->powered = true; |
@@ -1623,12 +1525,14 @@ static void hdmi_disable(struct drm_encoder *encoder) | |||
1623 | if (funcs && funcs->disable) | 1525 | if (funcs && funcs->disable) |
1624 | (*funcs->disable)(crtc); | 1526 | (*funcs->disable)(crtc); |
1625 | 1527 | ||
1626 | /* HDMI System Disable */ | ||
1627 | hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_EN); | 1528 | hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_EN); |
1628 | 1529 | ||
1629 | cancel_delayed_work(&hdata->hotplug_work); | 1530 | cancel_delayed_work(&hdata->hotplug_work); |
1630 | 1531 | ||
1631 | /* reset pmu hdmiphy control bit to disable hdmiphy */ | 1532 | hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0, HDMI_PHY_POWER_OFF_EN); |
1533 | |||
1534 | hdmi_set_refclk(hdata, false); | ||
1535 | |||
1632 | regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL, | 1536 | regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL, |
1633 | PMU_HDMI_PHY_ENABLE_BIT, 0); | 1537 | PMU_HDMI_PHY_ENABLE_BIT, 0); |
1634 | 1538 | ||
@@ -1670,6 +1574,57 @@ static irqreturn_t hdmi_irq_thread(int irq, void *arg) | |||
1670 | return IRQ_HANDLED; | 1574 | return IRQ_HANDLED; |
1671 | } | 1575 | } |
1672 | 1576 | ||
1577 | static int hdmi_clks_get(struct hdmi_context *hdata, | ||
1578 | const struct string_array_spec *names, | ||
1579 | struct clk **clks) | ||
1580 | { | ||
1581 | struct device *dev = hdata->dev; | ||
1582 | int i; | ||
1583 | |||
1584 | for (i = 0; i < names->count; ++i) { | ||
1585 | struct clk *clk = devm_clk_get(dev, names->data[i]); | ||
1586 | |||
1587 | if (IS_ERR(clk)) { | ||
1588 | int ret = PTR_ERR(clk); | ||
1589 | |||
1590 | dev_err(dev, "Cannot get clock %s, %d\n", | ||
1591 | names->data[i], ret); | ||
1592 | |||
1593 | return ret; | ||
1594 | } | ||
1595 | |||
1596 | clks[i] = clk; | ||
1597 | } | ||
1598 | |||
1599 | return 0; | ||
1600 | } | ||
1601 | |||
1602 | static int hdmi_clk_init(struct hdmi_context *hdata) | ||
1603 | { | ||
1604 | const struct hdmi_driver_data *drv_data = hdata->drv_data; | ||
1605 | int count = drv_data->clk_gates.count + drv_data->clk_muxes.count; | ||
1606 | struct device *dev = hdata->dev; | ||
1607 | struct clk **clks; | ||
1608 | int ret; | ||
1609 | |||
1610 | if (!count) | ||
1611 | return 0; | ||
1612 | |||
1613 | clks = devm_kzalloc(dev, sizeof(*clks) * count, GFP_KERNEL); | ||
1614 | if (!clks) | ||
1615 | return -ENOMEM; | ||
1616 | |||
1617 | hdata->clk_gates = clks; | ||
1618 | hdata->clk_muxes = clks + drv_data->clk_gates.count; | ||
1619 | |||
1620 | ret = hdmi_clks_get(hdata, &drv_data->clk_gates, hdata->clk_gates); | ||
1621 | if (ret) | ||
1622 | return ret; | ||
1623 | |||
1624 | return hdmi_clks_get(hdata, &drv_data->clk_muxes, hdata->clk_muxes); | ||
1625 | } | ||
1626 | |||
1627 | |||
1673 | static int hdmi_resources_init(struct hdmi_context *hdata) | 1628 | static int hdmi_resources_init(struct hdmi_context *hdata) |
1674 | { | 1629 | { |
1675 | struct device *dev = hdata->dev; | 1630 | struct device *dev = hdata->dev; |
@@ -1688,39 +1643,14 @@ static int hdmi_resources_init(struct hdmi_context *hdata) | |||
1688 | DRM_ERROR("failed to get GPIO irq\n"); | 1643 | DRM_ERROR("failed to get GPIO irq\n"); |
1689 | return hdata->irq; | 1644 | return hdata->irq; |
1690 | } | 1645 | } |
1691 | /* get clocks, power */ | ||
1692 | hdata->hdmi = devm_clk_get(dev, "hdmi"); | ||
1693 | if (IS_ERR(hdata->hdmi)) { | ||
1694 | DRM_ERROR("failed to get clock 'hdmi'\n"); | ||
1695 | ret = PTR_ERR(hdata->hdmi); | ||
1696 | goto fail; | ||
1697 | } | ||
1698 | hdata->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi"); | ||
1699 | if (IS_ERR(hdata->sclk_hdmi)) { | ||
1700 | DRM_ERROR("failed to get clock 'sclk_hdmi'\n"); | ||
1701 | ret = PTR_ERR(hdata->sclk_hdmi); | ||
1702 | goto fail; | ||
1703 | } | ||
1704 | hdata->sclk_pixel = devm_clk_get(dev, "sclk_pixel"); | ||
1705 | if (IS_ERR(hdata->sclk_pixel)) { | ||
1706 | DRM_ERROR("failed to get clock 'sclk_pixel'\n"); | ||
1707 | ret = PTR_ERR(hdata->sclk_pixel); | ||
1708 | goto fail; | ||
1709 | } | ||
1710 | hdata->sclk_hdmiphy = devm_clk_get(dev, "sclk_hdmiphy"); | ||
1711 | if (IS_ERR(hdata->sclk_hdmiphy)) { | ||
1712 | DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n"); | ||
1713 | ret = PTR_ERR(hdata->sclk_hdmiphy); | ||
1714 | goto fail; | ||
1715 | } | ||
1716 | hdata->mout_hdmi = devm_clk_get(dev, "mout_hdmi"); | ||
1717 | if (IS_ERR(hdata->mout_hdmi)) { | ||
1718 | DRM_ERROR("failed to get clock 'mout_hdmi'\n"); | ||
1719 | ret = PTR_ERR(hdata->mout_hdmi); | ||
1720 | goto fail; | ||
1721 | } | ||
1722 | 1646 | ||
1723 | clk_set_parent(hdata->mout_hdmi, hdata->sclk_pixel); | 1647 | ret = hdmi_clk_init(hdata); |
1648 | if (ret) | ||
1649 | return ret; | ||
1650 | |||
1651 | ret = hdmi_clk_set_parents(hdata, false); | ||
1652 | if (ret) | ||
1653 | return ret; | ||
1724 | 1654 | ||
1725 | for (i = 0; i < ARRAY_SIZE(supply); ++i) { | 1655 | for (i = 0; i < ARRAY_SIZE(supply); ++i) { |
1726 | hdata->regul_bulk[i].supply = supply[i]; | 1656 | hdata->regul_bulk[i].supply = supply[i]; |
@@ -1745,9 +1675,6 @@ static int hdmi_resources_init(struct hdmi_context *hdata) | |||
1745 | DRM_ERROR("failed to enable hdmi-en regulator\n"); | 1675 | DRM_ERROR("failed to enable hdmi-en regulator\n"); |
1746 | 1676 | ||
1747 | return ret; | 1677 | return ret; |
1748 | fail: | ||
1749 | DRM_ERROR("HDMI resource init - failed\n"); | ||
1750 | return ret; | ||
1751 | } | 1678 | } |
1752 | 1679 | ||
1753 | static struct of_device_id hdmi_match_types[] = { | 1680 | static struct of_device_id hdmi_match_types[] = { |
@@ -1761,6 +1688,9 @@ static struct of_device_id hdmi_match_types[] = { | |||
1761 | .compatible = "samsung,exynos5420-hdmi", | 1688 | .compatible = "samsung,exynos5420-hdmi", |
1762 | .data = &exynos5420_hdmi_driver_data, | 1689 | .data = &exynos5420_hdmi_driver_data, |
1763 | }, { | 1690 | }, { |
1691 | .compatible = "samsung,exynos5433-hdmi", | ||
1692 | .data = &exynos5433_hdmi_driver_data, | ||
1693 | }, { | ||
1764 | /* end node */ | 1694 | /* end node */ |
1765 | } | 1695 | } |
1766 | }; | 1696 | }; |
@@ -1830,7 +1760,6 @@ static struct device_node *hdmi_legacy_phy_dt_binding(struct device *dev) | |||
1830 | static int hdmi_probe(struct platform_device *pdev) | 1760 | static int hdmi_probe(struct platform_device *pdev) |
1831 | { | 1761 | { |
1832 | struct device_node *ddc_node, *phy_node; | 1762 | struct device_node *ddc_node, *phy_node; |
1833 | const struct of_device_id *match; | ||
1834 | struct device *dev = &pdev->dev; | 1763 | struct device *dev = &pdev->dev; |
1835 | struct hdmi_context *hdata; | 1764 | struct hdmi_context *hdata; |
1836 | struct resource *res; | 1765 | struct resource *res; |
@@ -1840,11 +1769,7 @@ static int hdmi_probe(struct platform_device *pdev) | |||
1840 | if (!hdata) | 1769 | if (!hdata) |
1841 | return -ENOMEM; | 1770 | return -ENOMEM; |
1842 | 1771 | ||
1843 | match = of_match_device(hdmi_match_types, dev); | 1772 | hdata->drv_data = of_device_get_match_data(dev); |
1844 | if (!match) | ||
1845 | return -ENODEV; | ||
1846 | |||
1847 | hdata->drv_data = match->data; | ||
1848 | 1773 | ||
1849 | platform_set_drvdata(pdev, hdata); | 1774 | platform_set_drvdata(pdev, hdata); |
1850 | 1775 | ||
@@ -1867,7 +1792,6 @@ static int hdmi_probe(struct platform_device *pdev) | |||
1867 | if (ddc_node) | 1792 | if (ddc_node) |
1868 | goto out_get_ddc_adpt; | 1793 | goto out_get_ddc_adpt; |
1869 | 1794 | ||
1870 | /* DDC i2c driver */ | ||
1871 | ddc_node = of_parse_phandle(dev->of_node, "ddc", 0); | 1795 | ddc_node = of_parse_phandle(dev->of_node, "ddc", 0); |
1872 | if (!ddc_node) { | 1796 | if (!ddc_node) { |
1873 | DRM_ERROR("Failed to find ddc node in device tree\n"); | 1797 | DRM_ERROR("Failed to find ddc node in device tree\n"); |
@@ -1885,7 +1809,6 @@ out_get_ddc_adpt: | |||
1885 | if (phy_node) | 1809 | if (phy_node) |
1886 | goto out_get_phy_port; | 1810 | goto out_get_phy_port; |
1887 | 1811 | ||
1888 | /* hdmiphy i2c driver */ | ||
1889 | phy_node = of_parse_phandle(dev->of_node, "phy", 0); | 1812 | phy_node = of_parse_phandle(dev->of_node, "phy", 0); |
1890 | if (!phy_node) { | 1813 | if (!phy_node) { |
1891 | DRM_ERROR("Failed to find hdmiphy node in device tree\n"); | 1814 | DRM_ERROR("Failed to find hdmiphy node in device tree\n"); |
@@ -1929,6 +1852,16 @@ out_get_phy_port: | |||
1929 | goto err_hdmiphy; | 1852 | goto err_hdmiphy; |
1930 | } | 1853 | } |
1931 | 1854 | ||
1855 | if (hdata->drv_data->has_sysreg) { | ||
1856 | hdata->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node, | ||
1857 | "samsung,sysreg-phandle"); | ||
1858 | if (IS_ERR(hdata->sysreg)) { | ||
1859 | DRM_ERROR("sysreg regmap lookup failed.\n"); | ||
1860 | ret = -EPROBE_DEFER; | ||
1861 | goto err_hdmiphy; | ||
1862 | } | ||
1863 | } | ||
1864 | |||
1932 | pm_runtime_enable(dev); | 1865 | pm_runtime_enable(dev); |
1933 | 1866 | ||
1934 | ret = component_add(&pdev->dev, &hdmi_component_ops); | 1867 | ret = component_add(&pdev->dev, &hdmi_component_ops); |
@@ -1975,8 +1908,7 @@ static int exynos_hdmi_suspend(struct device *dev) | |||
1975 | { | 1908 | { |
1976 | struct hdmi_context *hdata = dev_get_drvdata(dev); | 1909 | struct hdmi_context *hdata = dev_get_drvdata(dev); |
1977 | 1910 | ||
1978 | clk_disable_unprepare(hdata->sclk_hdmi); | 1911 | hdmi_clk_disable_gates(hdata); |
1979 | clk_disable_unprepare(hdata->hdmi); | ||
1980 | 1912 | ||
1981 | return 0; | 1913 | return 0; |
1982 | } | 1914 | } |
@@ -1986,17 +1918,9 @@ static int exynos_hdmi_resume(struct device *dev) | |||
1986 | struct hdmi_context *hdata = dev_get_drvdata(dev); | 1918 | struct hdmi_context *hdata = dev_get_drvdata(dev); |
1987 | int ret; | 1919 | int ret; |
1988 | 1920 | ||
1989 | ret = clk_prepare_enable(hdata->hdmi); | 1921 | ret = hdmi_clk_enable_gates(hdata); |
1990 | if (ret < 0) { | 1922 | if (ret < 0) |
1991 | DRM_ERROR("Failed to prepare_enable the hdmi clk [%d]\n", ret); | ||
1992 | return ret; | ||
1993 | } | ||
1994 | ret = clk_prepare_enable(hdata->sclk_hdmi); | ||
1995 | if (ret < 0) { | ||
1996 | DRM_ERROR("Failed to prepare_enable the sclk_mixer clk [%d]\n", | ||
1997 | ret); | ||
1998 | return ret; | 1923 | return ret; |
1999 | } | ||
2000 | 1924 | ||
2001 | return 0; | 1925 | return 0; |
2002 | } | 1926 | } |
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 0a5a60005f7e..74a4269cc1b0 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/clk.h> | 31 | #include <linux/clk.h> |
32 | #include <linux/regulator/consumer.h> | 32 | #include <linux/regulator/consumer.h> |
33 | #include <linux/of.h> | 33 | #include <linux/of.h> |
34 | #include <linux/of_device.h> | ||
34 | #include <linux/component.h> | 35 | #include <linux/component.h> |
35 | 36 | ||
36 | #include <drm/exynos_drm.h> | 37 | #include <drm/exynos_drm.h> |
@@ -103,8 +104,6 @@ struct mixer_context { | |||
103 | 104 | ||
104 | struct mixer_resources mixer_res; | 105 | struct mixer_resources mixer_res; |
105 | enum mixer_version_id mxr_ver; | 106 | enum mixer_version_id mxr_ver; |
106 | wait_queue_head_t wait_vsync_queue; | ||
107 | atomic_t wait_vsync_event; | ||
108 | }; | 107 | }; |
109 | 108 | ||
110 | struct mixer_drv_data { | 109 | struct mixer_drv_data { |
@@ -787,12 +786,6 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg) | |||
787 | 786 | ||
788 | exynos_drm_crtc_finish_update(ctx->crtc, plane); | 787 | exynos_drm_crtc_finish_update(ctx->crtc, plane); |
789 | } | 788 | } |
790 | |||
791 | /* set wait vsync event to zero and wake up queue. */ | ||
792 | if (atomic_read(&ctx->wait_vsync_event)) { | ||
793 | atomic_set(&ctx->wait_vsync_event, 0); | ||
794 | wake_up(&ctx->wait_vsync_queue); | ||
795 | } | ||
796 | } | 789 | } |
797 | 790 | ||
798 | out: | 791 | out: |
@@ -1027,34 +1020,6 @@ static void mixer_atomic_flush(struct exynos_drm_crtc *crtc) | |||
1027 | mixer_vsync_set_update(mixer_ctx, true); | 1020 | mixer_vsync_set_update(mixer_ctx, true); |
1028 | } | 1021 | } |
1029 | 1022 | ||
1030 | static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc) | ||
1031 | { | ||
1032 | struct mixer_context *mixer_ctx = crtc->ctx; | ||
1033 | int err; | ||
1034 | |||
1035 | if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) | ||
1036 | return; | ||
1037 | |||
1038 | err = drm_vblank_get(mixer_ctx->drm_dev, mixer_ctx->pipe); | ||
1039 | if (err < 0) { | ||
1040 | DRM_DEBUG_KMS("failed to acquire vblank counter\n"); | ||
1041 | return; | ||
1042 | } | ||
1043 | |||
1044 | atomic_set(&mixer_ctx->wait_vsync_event, 1); | ||
1045 | |||
1046 | /* | ||
1047 | * wait for MIXER to signal VSYNC interrupt or return after | ||
1048 | * timeout which is set to 50ms (refresh rate of 20). | ||
1049 | */ | ||
1050 | if (!wait_event_timeout(mixer_ctx->wait_vsync_queue, | ||
1051 | !atomic_read(&mixer_ctx->wait_vsync_event), | ||
1052 | HZ/20)) | ||
1053 | DRM_DEBUG_KMS("vblank wait timed out.\n"); | ||
1054 | |||
1055 | drm_vblank_put(mixer_ctx->drm_dev, mixer_ctx->pipe); | ||
1056 | } | ||
1057 | |||
1058 | static void mixer_enable(struct exynos_drm_crtc *crtc) | 1023 | static void mixer_enable(struct exynos_drm_crtc *crtc) |
1059 | { | 1024 | { |
1060 | struct mixer_context *ctx = crtc->ctx; | 1025 | struct mixer_context *ctx = crtc->ctx; |
@@ -1065,6 +1030,8 @@ static void mixer_enable(struct exynos_drm_crtc *crtc) | |||
1065 | 1030 | ||
1066 | pm_runtime_get_sync(ctx->dev); | 1031 | pm_runtime_get_sync(ctx->dev); |
1067 | 1032 | ||
1033 | exynos_drm_pipe_clk_enable(crtc, true); | ||
1034 | |||
1068 | mixer_vsync_set_update(ctx, false); | 1035 | mixer_vsync_set_update(ctx, false); |
1069 | 1036 | ||
1070 | mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET); | 1037 | mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET); |
@@ -1094,6 +1061,8 @@ static void mixer_disable(struct exynos_drm_crtc *crtc) | |||
1094 | for (i = 0; i < MIXER_WIN_NR; i++) | 1061 | for (i = 0; i < MIXER_WIN_NR; i++) |
1095 | mixer_disable_plane(crtc, &ctx->planes[i]); | 1062 | mixer_disable_plane(crtc, &ctx->planes[i]); |
1096 | 1063 | ||
1064 | exynos_drm_pipe_clk_enable(crtc, false); | ||
1065 | |||
1097 | pm_runtime_put(ctx->dev); | 1066 | pm_runtime_put(ctx->dev); |
1098 | 1067 | ||
1099 | clear_bit(MXR_BIT_POWERED, &ctx->flags); | 1068 | clear_bit(MXR_BIT_POWERED, &ctx->flags); |
@@ -1126,7 +1095,6 @@ static const struct exynos_drm_crtc_ops mixer_crtc_ops = { | |||
1126 | .disable = mixer_disable, | 1095 | .disable = mixer_disable, |
1127 | .enable_vblank = mixer_enable_vblank, | 1096 | .enable_vblank = mixer_enable_vblank, |
1128 | .disable_vblank = mixer_disable_vblank, | 1097 | .disable_vblank = mixer_disable_vblank, |
1129 | .wait_for_vblank = mixer_wait_for_vblank, | ||
1130 | .atomic_begin = mixer_atomic_begin, | 1098 | .atomic_begin = mixer_atomic_begin, |
1131 | .update_plane = mixer_update_plane, | 1099 | .update_plane = mixer_update_plane, |
1132 | .disable_plane = mixer_disable_plane, | 1100 | .disable_plane = mixer_disable_plane, |
@@ -1155,18 +1123,6 @@ static struct mixer_drv_data exynos4210_mxr_drv_data = { | |||
1155 | .has_sclk = 1, | 1123 | .has_sclk = 1, |
1156 | }; | 1124 | }; |
1157 | 1125 | ||
1158 | static const struct platform_device_id mixer_driver_types[] = { | ||
1159 | { | ||
1160 | .name = "s5p-mixer", | ||
1161 | .driver_data = (unsigned long)&exynos4210_mxr_drv_data, | ||
1162 | }, { | ||
1163 | .name = "exynos5-mixer", | ||
1164 | .driver_data = (unsigned long)&exynos5250_mxr_drv_data, | ||
1165 | }, { | ||
1166 | /* end node */ | ||
1167 | } | ||
1168 | }; | ||
1169 | |||
1170 | static struct of_device_id mixer_match_types[] = { | 1126 | static struct of_device_id mixer_match_types[] = { |
1171 | { | 1127 | { |
1172 | .compatible = "samsung,exynos4210-mixer", | 1128 | .compatible = "samsung,exynos4210-mixer", |
@@ -1243,7 +1199,7 @@ static const struct component_ops mixer_component_ops = { | |||
1243 | static int mixer_probe(struct platform_device *pdev) | 1199 | static int mixer_probe(struct platform_device *pdev) |
1244 | { | 1200 | { |
1245 | struct device *dev = &pdev->dev; | 1201 | struct device *dev = &pdev->dev; |
1246 | struct mixer_drv_data *drv; | 1202 | const struct mixer_drv_data *drv; |
1247 | struct mixer_context *ctx; | 1203 | struct mixer_context *ctx; |
1248 | int ret; | 1204 | int ret; |
1249 | 1205 | ||
@@ -1253,23 +1209,13 @@ static int mixer_probe(struct platform_device *pdev) | |||
1253 | return -ENOMEM; | 1209 | return -ENOMEM; |
1254 | } | 1210 | } |
1255 | 1211 | ||
1256 | if (dev->of_node) { | 1212 | drv = of_device_get_match_data(dev); |
1257 | const struct of_device_id *match; | ||
1258 | |||
1259 | match = of_match_node(mixer_match_types, dev->of_node); | ||
1260 | drv = (struct mixer_drv_data *)match->data; | ||
1261 | } else { | ||
1262 | drv = (struct mixer_drv_data *) | ||
1263 | platform_get_device_id(pdev)->driver_data; | ||
1264 | } | ||
1265 | 1213 | ||
1266 | ctx->pdev = pdev; | 1214 | ctx->pdev = pdev; |
1267 | ctx->dev = dev; | 1215 | ctx->dev = dev; |
1268 | ctx->vp_enabled = drv->is_vp_enabled; | 1216 | ctx->vp_enabled = drv->is_vp_enabled; |
1269 | ctx->has_sclk = drv->has_sclk; | 1217 | ctx->has_sclk = drv->has_sclk; |
1270 | ctx->mxr_ver = drv->version; | 1218 | ctx->mxr_ver = drv->version; |
1271 | init_waitqueue_head(&ctx->wait_vsync_queue); | ||
1272 | atomic_set(&ctx->wait_vsync_event, 0); | ||
1273 | 1219 | ||
1274 | platform_set_drvdata(pdev, ctx); | 1220 | platform_set_drvdata(pdev, ctx); |
1275 | 1221 | ||
@@ -1355,5 +1301,4 @@ struct platform_driver mixer_driver = { | |||
1355 | }, | 1301 | }, |
1356 | .probe = mixer_probe, | 1302 | .probe = mixer_probe, |
1357 | .remove = mixer_remove, | 1303 | .remove = mixer_remove, |
1358 | .id_table = mixer_driver_types, | ||
1359 | }; | 1304 | }; |
diff --git a/drivers/gpu/drm/exynos/regs-hdmi.h b/drivers/gpu/drm/exynos/regs-hdmi.h index 8c891e59be21..169667a22bdc 100644 --- a/drivers/gpu/drm/exynos/regs-hdmi.h +++ b/drivers/gpu/drm/exynos/regs-hdmi.h | |||
@@ -586,10 +586,12 @@ | |||
586 | #define HDMI_TG_VACT_ST4_L HDMI_TG_BASE(0x0070) | 586 | #define HDMI_TG_VACT_ST4_L HDMI_TG_BASE(0x0070) |
587 | #define HDMI_TG_VACT_ST4_H HDMI_TG_BASE(0x0074) | 587 | #define HDMI_TG_VACT_ST4_H HDMI_TG_BASE(0x0074) |
588 | #define HDMI_TG_3D HDMI_TG_BASE(0x00F0) | 588 | #define HDMI_TG_3D HDMI_TG_BASE(0x00F0) |
589 | #define HDMI_TG_DECON_EN HDMI_TG_BASE(0x01e0) | ||
589 | 590 | ||
590 | /* HDMI PHY Registers Offsets*/ | 591 | /* HDMI PHY Registers Offsets*/ |
591 | #define HDMIPHY_POWER (0x74 >> 2) | 592 | #define HDMIPHY_POWER 0x74 |
592 | #define HDMIPHY_MODE_SET_DONE (0x7c >> 2) | 593 | #define HDMIPHY_MODE_SET_DONE 0x7c |
594 | #define HDMIPHY5433_MODE_SET_DONE 0x84 | ||
593 | 595 | ||
594 | /* HDMI PHY Values */ | 596 | /* HDMI PHY Values */ |
595 | #define HDMI_PHY_POWER_ON 0x80 | 597 | #define HDMI_PHY_POWER_ON 0x80 |
@@ -603,4 +605,7 @@ | |||
603 | #define PMU_HDMI_PHY_CONTROL 0x700 | 605 | #define PMU_HDMI_PHY_CONTROL 0x700 |
604 | #define PMU_HDMI_PHY_ENABLE_BIT BIT(0) | 606 | #define PMU_HDMI_PHY_ENABLE_BIT BIT(0) |
605 | 607 | ||
608 | #define EXYNOS5433_SYSREG_DISP_HDMI_PHY 0x1008 | ||
609 | #define SYSREG_HDMI_REFCLK_INT_CLK 1 | ||
610 | |||
606 | #endif /* SAMSUNG_REGS_HDMI_H */ | 611 | #endif /* SAMSUNG_REGS_HDMI_H */ |
diff --git a/include/video/exynos5433_decon.h b/include/video/exynos5433_decon.h index c1c1ca18abc0..0098a522d9f4 100644 --- a/include/video/exynos5433_decon.h +++ b/include/video/exynos5433_decon.h | |||
@@ -179,9 +179,9 @@ | |||
179 | #define TRIGCON_TRIGMODE_W1BUF (1 << 10) | 179 | #define TRIGCON_TRIGMODE_W1BUF (1 << 10) |
180 | #define TRIGCON_SWTRIGCMD_W0BUF (1 << 6) | 180 | #define TRIGCON_SWTRIGCMD_W0BUF (1 << 6) |
181 | #define TRIGCON_TRIGMODE_W0BUF (1 << 5) | 181 | #define TRIGCON_TRIGMODE_W0BUF (1 << 5) |
182 | #define TRIGCON_HWTRIGMASK_I80_RGB (1 << 4) | 182 | #define TRIGCON_HWTRIGMASK (1 << 4) |
183 | #define TRIGCON_HWTRIGEN_I80_RGB (1 << 3) | 183 | #define TRIGCON_HWTRIGEN (1 << 3) |
184 | #define TRIGCON_HWTRIG_INV_I80_RGB (1 << 2) | 184 | #define TRIGCON_HWTRIG_INV (1 << 2) |
185 | #define TRIGCON_SWTRIGCMD (1 << 1) | 185 | #define TRIGCON_SWTRIGCMD (1 << 1) |
186 | #define TRIGCON_SWTRIGEN (1 << 0) | 186 | #define TRIGCON_SWTRIGEN (1 << 0) |
187 | 187 | ||