diff options
| author | Dave Airlie <airlied@redhat.com> | 2016-05-04 17:37:20 +1000 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2016-05-04 17:37:20 +1000 |
| commit | 00c1beab15df9216cf39818a437b34f296423ac4 (patch) | |
| tree | bdd83f80022f4c921853c92e46193cb9c873eab1 | |
| parent | acff058f8625022bbc37a3521f8208810a42c4ef (diff) | |
| parent | b5bf0f1ea3658254bd72ef64abc97786e8a32255 (diff) | |
| download | linux-00c1beab15df9216cf39818a437b34f296423ac4.tar.gz linux-00c1beab15df9216cf39818a437b34f296423ac4.tar.bz2 linux-00c1beab15df9216cf39818a437b34f296423ac4.zip | |
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 buffer to an external LCD interface. Required properties: -- compatible: value should be "samsung,exynos5433-decon"; +- compatible: value should be one of: + "samsung,exynos5433-decon", "samsung,exynos5433-decon-tv"; - reg: physical base address and length of the DECON registers set. - interrupts: should contain a list of all DECON IP block interrupts in the order: VSYNC, LCD_SYSTEM. The interrupt specifier format @@ -16,7 +17,7 @@ Required properties: - clocks: must include clock specifiers corresponding to entries in the clock-names property. - clock-names: list of clock names sorted in the same order as the clocks - property. Must contain "aclk_decon", "aclk_smmu_decon0x", + property. Must contain "pclk", "aclk_decon", "aclk_smmu_decon0x", "aclk_xiu_decon0x", "pclk_smmu_decon0x", clk_decon_vclk", "sclk_decon_eclk" - 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: 1) "samsung,exynos4210-hdmi" 2) "samsung,exynos4212-hdmi" 3) "samsung,exynos5420-hdmi" + 4) "samsung,exynos5433-hdmi" - reg: physical base address of the hdmi and length of memory mapped region. - interrupts: interrupt number to the cpu. @@ -12,6 +13,11 @@ Required properties: a) phandle of the gpio controller node. b) pin number within the gpio controller. c) optional flags and pull up/down. +- ddc: phandle to the hdmi ddc node +- phy: phandle to the hdmi phy node +- samsung,syscon-phandle: phandle for system controller node for PMU. + +Required properties for Exynos 4210, 4212, 5420 and 5433: - clocks: list of clock IDs from SoC clock driver. a) hdmi: Gate of HDMI IP bus clock. b) sclk_hdmi: Gate of HDMI special clock. @@ -25,9 +31,24 @@ Required properties: sclk_pixel. - clock-names: aliases as per driver requirements for above clock IDs: "hdmi", "sclk_hdmi", "sclk_pixel", "sclk_hdmiphy" and "mout_hdmi". -- ddc: phandle to the hdmi ddc node -- phy: phandle to the hdmi phy node -- samsung,syscon-phandle: phandle for system controller node for PMU. + +Required properties for Exynos 5433: +- clocks: list of clock specifiers according to common clock bindings. + a) hdmi_pclk: Gate of HDMI IP APB bus. + b) hdmi_i_pclk: Gate of HDMI-PHY IP APB bus. + d) i_tmds_clk: Gate of HDMI TMDS clock. + e) i_pixel_clk: Gate of HDMI pixel clock. + f) i_spdif_clk: Gate of HDMI SPDIF clock. + g) oscclk: Oscillator clock, used as parent of following *_user clocks + in case HDMI-PHY is not operational. + h) tmds_clko: TMDS clock generated by HDMI-PHY. + i) tmds_clko_user: MUX used to switch between oscclk and tmds_clko, + respectively if HDMI-PHY is off and operational. + j) pixel_clko: Pixel clock generated by HDMI-PHY. + k) pixel_clko_user: MUX used to switch between oscclk and pixel_clko, + respectively if HDMI-PHY is off and operational. +- clock-names: aliases for above clock specfiers. +- samsung,sysreg: handle to syscon used to control the system registers. Example: 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" config DRM_EXYNOS_G2D bool "G2D" - depends on !VIDEO_SAMSUNG_S5P_G2D + depends on VIDEO_SAMSUNG_S5P_G2D=n select FRAME_VECTOR help 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 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -exynosdrm-y := exynos_drm_drv.o exynos_drm_crtc.o exynos_drm_fbdev.o \ - exynos_drm_fb.o exynos_drm_gem.o exynos_drm_core.o \ - exynos_drm_plane.o +exynosdrm-y := exynos_drm_drv.o exynos_drm_crtc.o exynos_drm_fb.o \ + exynos_drm_gem.o exynos_drm_core.o exynos_drm_plane.o +exynosdrm-$(CONFIG_DRM_FBDEV_EMULATION) += exynos_drm_fbdev.o exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o 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 @@ #define WINDOWS_NR 3 #define MIN_FB_WIDTH_FOR_16WORD_BURST 128 +#define IFTYPE_I80 (1 << 0) +#define I80_HW_TRG (1 << 1) +#define IFTYPE_HDMI (1 << 2) + static const char * const decon_clks_name[] = { "pclk", "aclk_decon", @@ -38,12 +42,6 @@ static const char * const decon_clks_name[] = { "sclk_decon_eclk", }; -enum decon_iftype { - IFTYPE_RGB, - IFTYPE_I80, - IFTYPE_HDMI -}; - enum decon_flag_bits { BIT_CLKS_ENABLED, BIT_IRQS_ENABLED, @@ -61,7 +59,7 @@ struct decon_context { struct clk *clks[ARRAY_SIZE(decon_clks_name)]; int pipe; unsigned long flags; - enum decon_iftype out_type; + unsigned long out_type; int first_win; }; @@ -95,7 +93,7 @@ static int decon_enable_vblank(struct exynos_drm_crtc *crtc) if (!test_and_set_bit(BIT_IRQS_ENABLED, &ctx->flags)) { val = VIDINTCON0_INTEN; - if (ctx->out_type == IFTYPE_I80) + if (ctx->out_type & IFTYPE_I80) val |= VIDINTCON0_FRAMEDONE; else val |= VIDINTCON0_INTFRMEN; @@ -119,11 +117,11 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc) static void decon_setup_trigger(struct decon_context *ctx) { - u32 val = (ctx->out_type != IFTYPE_HDMI) + u32 val = !(ctx->out_type & I80_HW_TRG) ? TRIGCON_TRIGEN_PER_F | TRIGCON_TRIGEN_F | TRIGCON_TE_AUTO_MASK | TRIGCON_SWTRIGEN : TRIGCON_TRIGEN_PER_F | TRIGCON_TRIGEN_F | - TRIGCON_HWTRIGMASK_I80_RGB | TRIGCON_HWTRIGEN_I80_RGB; + TRIGCON_HWTRIGMASK | TRIGCON_HWTRIGEN; writel(val, ctx->addr + DECON_TRIGCON); } @@ -136,7 +134,7 @@ static void decon_commit(struct exynos_drm_crtc *crtc) if (test_bit(BIT_SUSPENDED, &ctx->flags)) return; - if (ctx->out_type == IFTYPE_HDMI) { + if (ctx->out_type & IFTYPE_HDMI) { m->crtc_hsync_start = m->crtc_hdisplay + 10; m->crtc_hsync_end = m->crtc_htotal - 92; m->crtc_vsync_start = m->crtc_vdisplay + 1; @@ -151,17 +149,20 @@ static void decon_commit(struct exynos_drm_crtc *crtc) /* lcd on and use command if */ val = VIDOUT_LCD_ON; - if (ctx->out_type == IFTYPE_I80) + if (ctx->out_type & IFTYPE_I80) { val |= VIDOUT_COMMAND_IF; - else + decon_setup_trigger(ctx); + } else { val |= VIDOUT_RGB_IF; + } + writel(val, ctx->addr + DECON_VIDOUTCON0); val = VIDTCON2_LINEVAL(m->vdisplay - 1) | VIDTCON2_HOZVAL(m->hdisplay - 1); writel(val, ctx->addr + DECON_VIDTCON2); - if (ctx->out_type != IFTYPE_I80) { + if (!(ctx->out_type & IFTYPE_I80)) { val = VIDTCON00_VBPD_F( m->crtc_vtotal - m->crtc_vsync_end - 1) | VIDTCON00_VFPD_F( @@ -183,10 +184,10 @@ static void decon_commit(struct exynos_drm_crtc *crtc) writel(val, ctx->addr + DECON_VIDTCON11); } - decon_setup_trigger(ctx); - /* enable output and display signal */ decon_set_bits(ctx, DECON_VIDCON0, VIDCON0_ENVID | VIDCON0_ENVID_F, ~0); + + decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); } 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, val = dma_addr + pitch * state->src.h; writel(val, ctx->addr + DECON_VIDW0xADD1B0(win)); - if (ctx->out_type != IFTYPE_HDMI) + if (!(ctx->out_type & IFTYPE_HDMI)) val = BIT_VAL(pitch - state->crtc.w * bpp, 27, 14) | BIT_VAL(state->crtc.w * bpp, 13, 0); else @@ -312,9 +313,6 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, /* window enable */ decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, ~0); - - /* standalone update */ - decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); } static void decon_disable_plane(struct exynos_drm_crtc *crtc, @@ -326,15 +324,7 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc, if (test_bit(BIT_SUSPENDED, &ctx->flags)) return; - decon_shadow_protect_win(ctx, win, true); - - /* window disable */ decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, 0); - - decon_shadow_protect_win(ctx, win, false); - - /* standalone update */ - decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); } static void decon_atomic_flush(struct exynos_drm_crtc *crtc) @@ -348,7 +338,10 @@ static void decon_atomic_flush(struct exynos_drm_crtc *crtc) for (i = ctx->first_win; i < WINDOWS_NR; i++) decon_shadow_protect_win(ctx, i, false); - if (ctx->out_type == IFTYPE_I80) + /* standalone update */ + decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); + + if (ctx->out_type & IFTYPE_I80) set_bit(BIT_WIN_UPDATED, &ctx->flags); } @@ -374,7 +367,7 @@ static void decon_swreset(struct decon_context *ctx) WARN(tries == 0, "failed to software reset DECON\n"); - if (ctx->out_type != IFTYPE_HDMI) + if (!(ctx->out_type & IFTYPE_HDMI)) return; writel(VIDCON0_CLKVALUP | VIDCON0_VLCKFREE, ctx->addr + DECON_VIDCON0); @@ -383,7 +376,9 @@ static void decon_swreset(struct decon_context *ctx) writel(VIDCON1_VCLK_RUN_VDEN_DISABLE, ctx->addr + DECON_VIDCON1); writel(CRCCTRL_CRCEN | CRCCTRL_CRCSTART_F | CRCCTRL_CRCCLKEN, ctx->addr + DECON_CRCCTRL); - decon_setup_trigger(ctx); + + if (ctx->out_type & IFTYPE_I80) + decon_setup_trigger(ctx); } static void decon_enable(struct exynos_drm_crtc *crtc) @@ -395,8 +390,12 @@ static void decon_enable(struct exynos_drm_crtc *crtc) pm_runtime_get_sync(ctx->dev); + exynos_drm_pipe_clk_enable(crtc, true); + set_bit(BIT_CLKS_ENABLED, &ctx->flags); + decon_swreset(ctx); + /* if vblank was enabled status, enable it again. */ if (test_and_clear_bit(BIT_IRQS_ENABLED, &ctx->flags)) decon_enable_vblank(ctx->crtc); @@ -424,6 +423,8 @@ static void decon_disable(struct exynos_drm_crtc *crtc) clear_bit(BIT_CLKS_ENABLED, &ctx->flags); + exynos_drm_pipe_clk_enable(crtc, false); + pm_runtime_put_sync(ctx->dev); set_bit(BIT_SUSPENDED, &ctx->flags); @@ -459,8 +460,10 @@ static void decon_clear_channels(struct exynos_drm_crtc *crtc) decon_shadow_protect_win(ctx, win, true); decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, 0); decon_shadow_protect_win(ctx, win, false); - decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); } + + decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); + /* TODO: wait for possible vsync */ msleep(50); @@ -509,7 +512,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data) } exynos_plane = &ctx->planes[ctx->first_win]; - out_type = (ctx->out_type == IFTYPE_HDMI) ? EXYNOS_DISPLAY_TYPE_HDMI + out_type = (ctx->out_type & IFTYPE_HDMI) ? EXYNOS_DISPLAY_TYPE_HDMI : EXYNOS_DISPLAY_TYPE_LCD; ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base, ctx->pipe, out_type, @@ -617,11 +620,11 @@ static const struct dev_pm_ops exynos5433_decon_pm_ops = { static const struct of_device_id exynos5433_decon_driver_dt_match[] = { { .compatible = "samsung,exynos5433-decon", - .data = (void *)IFTYPE_RGB + .data = (void *)I80_HW_TRG }, { .compatible = "samsung,exynos5433-decon-tv", - .data = (void *)IFTYPE_HDMI + .data = (void *)(I80_HW_TRG | IFTYPE_HDMI) }, {}, }; @@ -629,7 +632,6 @@ MODULE_DEVICE_TABLE(of, exynos5433_decon_driver_dt_match); static int exynos5433_decon_probe(struct platform_device *pdev) { - const struct of_device_id *of_id; struct device *dev = &pdev->dev; struct decon_context *ctx; struct resource *res; @@ -642,14 +644,14 @@ static int exynos5433_decon_probe(struct platform_device *pdev) __set_bit(BIT_SUSPENDED, &ctx->flags); ctx->dev = dev; + ctx->out_type = (unsigned long)of_device_get_match_data(dev); - of_id = of_match_device(exynos5433_decon_driver_dt_match, &pdev->dev); - ctx->out_type = (enum decon_iftype)of_id->data; - - if (ctx->out_type == IFTYPE_HDMI) + if (ctx->out_type & IFTYPE_HDMI) { ctx->first_win = 1; - else if (of_get_child_by_name(dev->of_node, "i80-if-timings")) ctx->out_type = IFTYPE_I80; + } else if (of_get_child_by_name(dev->of_node, "i80-if-timings")) { + ctx->out_type = IFTYPE_I80; + } for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) { struct clk *clk; @@ -674,7 +676,7 @@ static int exynos5433_decon_probe(struct platform_device *pdev) } res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, - (ctx->out_type == IFTYPE_I80) ? "lcd_sys" : "vsync"); + (ctx->out_type & IFTYPE_I80) ? "lcd_sys" : "vsync"); if (!res) { dev_err(dev, "cannot find IRQ resource\n"); 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 = { .commit = decon_commit, .enable_vblank = decon_enable_vblank, .disable_vblank = decon_disable_vblank, - .wait_for_vblank = decon_wait_for_vblank, .atomic_begin = decon_atomic_begin, .update_plane = decon_update_plane, .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, { struct exynos_dp_device *dp = to_dp(plat_data); struct drm_encoder *encoder = &dp->encoder; - struct exynos_drm_crtc *crtc; - if (!encoder) - return -1; + if (!encoder->crtc) + return -EPERM; - crtc = to_exynos_crtc(encoder->crtc); - if (crtc && crtc->ops && crtc->ops->clock_enable) - crtc->ops->clock_enable(crtc, enable); + exynos_drm_pipe_clk_enable(to_exynos_crtc(encoder->crtc), enable); return 0; } 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) return 0; err: - list_for_each_entry_reverse(subdrv, &subdrv->list, list) { + list_for_each_entry_continue_reverse(subdrv, &exynos_drm_subdrv_list, list) { if (subdrv->close) subdrv->close(dev, subdrv->dev, file); } 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: int exynos_drm_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe) { - struct exynos_drm_private *private = dev->dev_private; - struct exynos_drm_crtc *exynos_crtc = - to_exynos_crtc(private->crtc[pipe]); + struct exynos_drm_crtc *exynos_crtc = exynos_drm_crtc_from_pipe(dev, + pipe); if (exynos_crtc->ops->enable_vblank) 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) void exynos_drm_crtc_disable_vblank(struct drm_device *dev, unsigned int pipe) { - struct exynos_drm_private *private = dev->dev_private; - struct exynos_drm_crtc *exynos_crtc = - to_exynos_crtc(private->crtc[pipe]); + struct exynos_drm_crtc *exynos_crtc = exynos_drm_crtc_from_pipe(dev, + pipe); if (exynos_crtc->ops->disable_vblank) 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 { * @commit: set current hw specific display mode to hw. * @enable_vblank: specific driver callback for enabling vblank interrupt. * @disable_vblank: specific driver callback for disabling vblank interrupt. - * @wait_for_vblank: wait for vblank interrupt to make sure that - * hardware overlay is updated. * @atomic_check: validate state * @atomic_begin: prepare device to receive an update * @atomic_flush: mark the end of device update @@ -129,10 +127,6 @@ struct exynos_drm_plane_config { * @disable_plane: disable hardware specific overlay. * @te_handler: trigger to transfer video image at the tearing effect * synchronization signal if there is a page flip request. - * @clock_enable: optional function enabling/disabling display domain clock, - * called from exynos-dp driver before powering up (with - * 'enable' argument as true) and after powering down (with - * 'enable' as false). */ struct exynos_drm_crtc; struct exynos_drm_crtc_ops { @@ -141,7 +135,6 @@ struct exynos_drm_crtc_ops { void (*commit)(struct exynos_drm_crtc *crtc); int (*enable_vblank)(struct exynos_drm_crtc *crtc); void (*disable_vblank)(struct exynos_drm_crtc *crtc); - void (*wait_for_vblank)(struct exynos_drm_crtc *crtc); int (*atomic_check)(struct exynos_drm_crtc *crtc, struct drm_crtc_state *state); void (*atomic_begin)(struct exynos_drm_crtc *crtc); @@ -151,7 +144,10 @@ struct exynos_drm_crtc_ops { struct exynos_drm_plane *plane); void (*atomic_flush)(struct exynos_drm_crtc *crtc); void (*te_handler)(struct exynos_drm_crtc *crtc); - void (*clock_enable)(struct exynos_drm_crtc *crtc, bool enable); +}; + +struct exynos_drm_clk { + void (*enable)(struct exynos_drm_clk *clk, bool enable); }; /* @@ -182,8 +178,16 @@ struct exynos_drm_crtc { atomic_t pending_update; const struct exynos_drm_crtc_ops *ops; void *ctx; + struct exynos_drm_clk *pipe_clk; }; +static inline void exynos_drm_pipe_clk_enable(struct exynos_drm_crtc *crtc, + bool enable) +{ + if (crtc->pipe_clk) + crtc->pipe_clk->enable(crtc->pipe_clk, enable); +} + struct exynos_drm_g2d_private { struct device *dev; struct list_head inuse_cmdlist; @@ -232,6 +236,14 @@ struct exynos_drm_private { wait_queue_head_t wait; }; +static inline struct exynos_drm_crtc * +exynos_drm_crtc_from_pipe(struct drm_device *dev, int pipe) +{ + struct exynos_drm_private *private = dev->dev_private; + + return to_exynos_crtc(private->crtc[pipe]); +} + static inline struct device *to_dma_dev(struct drm_device *dev) { 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 { spinlock_t transfer_lock; /* protects transfer_list */ struct list_head transfer_list; - struct exynos_dsi_driver_data *driver_data; + const struct exynos_dsi_driver_data *driver_data; struct device_node *bridge_node; }; @@ -532,15 +532,6 @@ static const struct of_device_id exynos_dsi_of_match[] = { { } }; -static inline struct exynos_dsi_driver_data *exynos_dsi_get_driver_data( - struct platform_device *pdev) -{ - const struct of_device_id *of_id = - of_match_device(exynos_dsi_of_match, &pdev->dev); - - return (struct exynos_dsi_driver_data *)of_id->data; -} - static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi) { if (wait_for_completion_timeout(&dsi->completed, msecs_to_jiffies(300))) @@ -564,7 +555,7 @@ static void exynos_dsi_reset(struct exynos_dsi *dsi) static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi, unsigned long fin, unsigned long fout, u8 *p, u16 *m, u8 *s) { - struct exynos_dsi_driver_data *driver_data = dsi->driver_data; + const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; unsigned long best_freq = 0; u32 min_delta = 0xffffffff; u8 p_min, p_max; @@ -618,7 +609,7 @@ static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi, static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi, unsigned long freq) { - struct exynos_dsi_driver_data *driver_data = dsi->driver_data; + const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; unsigned long fin, fout; int timeout; u8 p, s; @@ -712,7 +703,7 @@ static int exynos_dsi_enable_clock(struct exynos_dsi *dsi) static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi) { - struct exynos_dsi_driver_data *driver_data = dsi->driver_data; + const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; const unsigned int *reg_values = driver_data->reg_values; u32 reg; @@ -790,7 +781,7 @@ static void exynos_dsi_enable_lane(struct exynos_dsi *dsi, u32 lane) static int exynos_dsi_init_link(struct exynos_dsi *dsi) { - struct exynos_dsi_driver_data *driver_data = dsi->driver_data; + const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; int timeout; u32 reg; u32 lanes_mask; @@ -1334,7 +1325,7 @@ static void exynos_dsi_disable_irq(struct exynos_dsi *dsi) static int exynos_dsi_init(struct exynos_dsi *dsi) { - struct exynos_dsi_driver_data *driver_data = dsi->driver_data; + const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; exynos_dsi_reset(dsi); exynos_dsi_enable_irq(dsi); @@ -1833,7 +1824,7 @@ static int exynos_dsi_probe(struct platform_device *pdev) dsi->dsi_host.dev = dev; dsi->dev = dev; - dsi->driver_data = exynos_dsi_get_driver_data(pdev); + dsi->driver_data = of_device_get_match_data(dev); ret = exynos_dsi_parse_dt(dsi); if (ret) @@ -1917,7 +1908,7 @@ static int __maybe_unused exynos_dsi_suspend(struct device *dev) { struct drm_encoder *encoder = dev_get_drvdata(dev); struct exynos_dsi *dsi = encoder_to_dsi(encoder); - struct exynos_dsi_driver_data *driver_data = dsi->driver_data; + const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; int ret, i; usleep_range(10000, 20000); @@ -1948,7 +1939,7 @@ static int __maybe_unused exynos_dsi_resume(struct device *dev) { struct drm_encoder *encoder = dev_get_drvdata(dev); struct exynos_dsi *dsi = encoder_to_dsi(encoder); - struct exynos_dsi_driver_data *driver_data = dsi->driver_data; + const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; int ret, i; 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) return exynos_fb->dma_addr[index]; } -static void exynos_drm_output_poll_changed(struct drm_device *dev) -{ - struct exynos_drm_private *private = dev->dev_private; - struct drm_fb_helper *fb_helper = private->fb_helper; - - if (fb_helper) - drm_fb_helper_hotplug_event(fb_helper); - else - exynos_drm_fbdev_init(dev); -} - static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = { .fb_create = exynos_user_fb_create, .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) drm_fb_helper_restore_fbdev_mode_unlocked(private->fb_helper); } + +void exynos_drm_output_poll_changed(struct drm_device *dev) +{ + struct exynos_drm_private *private = dev->dev_private; + struct drm_fb_helper *fb_helper = private->fb_helper; + + if (fb_helper) + drm_fb_helper_hotplug_event(fb_helper); + else + exynos_drm_fbdev_init(dev); +} 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 @@ #ifndef _EXYNOS_DRM_FBDEV_H_ #define _EXYNOS_DRM_FBDEV_H_ +#ifdef CONFIG_DRM_FBDEV_EMULATION + int exynos_drm_fbdev_init(struct drm_device *dev); -int exynos_drm_fbdev_reinit(struct drm_device *dev); void exynos_drm_fbdev_fini(struct drm_device *dev); void exynos_drm_fbdev_restore_mode(struct drm_device *dev); +void exynos_drm_output_poll_changed(struct drm_device *dev); + +#else + +static inline int exynos_drm_fbdev_init(struct drm_device *dev) +{ + return 0; +} + +static inline void exynos_drm_fbdev_fini(struct drm_device *dev) +{ +} + +static inline void exynos_drm_fbdev_restore_mode(struct drm_device *dev) +{ +} + +#define exynos_drm_output_poll_changed (NULL) + +#endif #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 @@ /* color key value register for hardware window 1 ~ 4. */ #define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + ((x - 1) * 8)) -/* I80 / RGB trigger control register */ +/* I80 trigger control register */ #define TRIGCON 0x1A4 -#define TRGMODE_I80_RGB_ENABLE_I80 (1 << 0) -#define SWTRGCMD_I80_RGB_ENABLE (1 << 1) +#define TRGMODE_ENABLE (1 << 0) +#define SWTRGCMD_ENABLE (1 << 1) +/* Exynos3250, 3472, 4415, 5260 5410, 5420 and 5422 only supported. */ +#define HWTRGEN_ENABLE (1 << 3) +#define HWTRGMASK_ENABLE (1 << 4) +/* Exynos3250, 3472, 4415, 5260, 5420 and 5422 only supported. */ +#define HWTRIGEN_PER_ENABLE (1 << 31) /* display mode change control register except exynos4 */ #define VIDOUT_CON 0x000 @@ -89,12 +94,16 @@ /* FIMD has totally five hardware windows. */ #define WINDOWS_NR 5 +/* HW tr |
