From e5fd91f1ef340da553f7a79da9540c3db711c937 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Tue, 8 Sep 2015 01:01:14 -0300 Subject: Linux-libre 4.2-gnu --- drivers/gpu/drm/exynos/exynos_mixer.c | 139 ++++++++++++++-------------------- 1 file changed, 57 insertions(+), 82 deletions(-) (limited to 'drivers/gpu/drm/exynos/exynos_mixer.c') diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 8874c1fcb..4706b5690 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -718,6 +718,10 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg) /* handling VSYNC */ if (val & MXR_INT_STATUS_VSYNC) { + /* vsync interrupt use different bit for read and clear */ + val |= MXR_INT_CLEAR_VSYNC; + val &= ~MXR_INT_STATUS_VSYNC; + /* interlace scan need to check shadow register */ if (ctx->interlace) { base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0)); @@ -743,11 +747,6 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg) out: /* clear interrupts */ - if (~val & MXR_INT_EN_VSYNC) { - /* vsync interrupt use different bit for read and clear */ - val &= ~MXR_INT_EN_VSYNC; - val |= MXR_INT_CLEAR_VSYNC; - } mixer_reg_write(res, MXR_INT_STATUS, val); spin_unlock(&res->reg_slock); @@ -882,10 +881,12 @@ static int mixer_initialize(struct mixer_context *mixer_ctx, } } - if (!is_drm_iommu_supported(mixer_ctx->drm_dev)) - return 0; + ret = drm_iommu_attach_device_if_possible(mixer_ctx->crtc, drm_dev, + mixer_ctx->dev); + if (ret) + priv->pipe--; - return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev); + return ret; } static void mixer_ctx_remove(struct mixer_context *mixer_ctx) @@ -905,8 +906,8 @@ static int mixer_enable_vblank(struct exynos_drm_crtc *crtc) } /* enable vsync interrupt */ - mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC, - MXR_INT_EN_VSYNC); + mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC); + mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC); return 0; } @@ -916,7 +917,13 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc) struct mixer_context *mixer_ctx = crtc->ctx; struct mixer_resources *res = &mixer_ctx->mixer_res; + if (!mixer_ctx->powered) { + mixer_ctx->int_en &= MXR_INT_EN_VSYNC; + return; + } + /* disable vsync interrupt */ + mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC); mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); } @@ -937,8 +944,6 @@ static void mixer_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) vp_video_buffer(mixer_ctx, win); else mixer_graph_buffer(mixer_ctx, win); - - mixer_ctx->planes[win].enabled = true; } static void mixer_win_disable(struct exynos_drm_crtc *crtc, unsigned int win) @@ -952,7 +957,6 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, unsigned int win) mutex_lock(&mixer_ctx->mixer_mutex); if (!mixer_ctx->powered) { mutex_unlock(&mixer_ctx->mixer_mutex); - mixer_ctx->planes[win].resume = false; return; } mutex_unlock(&mixer_ctx->mixer_mutex); @@ -964,8 +968,6 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, unsigned int win) mixer_vsync_set_update(mixer_ctx, true); spin_unlock_irqrestore(&res->reg_slock, flags); - - mixer_ctx->planes[win].enabled = false; } static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc) @@ -1000,36 +1002,11 @@ static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc) drm_vblank_put(mixer_ctx->drm_dev, mixer_ctx->pipe); } -static void mixer_window_suspend(struct mixer_context *ctx) -{ - struct exynos_drm_plane *plane; - int i; - - for (i = 0; i < MIXER_WIN_NR; i++) { - plane = &ctx->planes[i]; - plane->resume = plane->enabled; - mixer_win_disable(ctx->crtc, i); - } - mixer_wait_for_vblank(ctx->crtc); -} - -static void mixer_window_resume(struct mixer_context *ctx) -{ - struct exynos_drm_plane *plane; - int i; - - for (i = 0; i < MIXER_WIN_NR; i++) { - plane = &ctx->planes[i]; - plane->enabled = plane->resume; - plane->resume = false; - if (plane->enabled) - mixer_win_commit(ctx->crtc, i); - } -} - -static void mixer_poweron(struct mixer_context *ctx) +static void mixer_enable(struct exynos_drm_crtc *crtc) { + struct mixer_context *ctx = crtc->ctx; struct mixer_resources *res = &ctx->mixer_res; + int ret; mutex_lock(&ctx->mixer_mutex); if (ctx->powered) { @@ -1041,12 +1018,32 @@ static void mixer_poweron(struct mixer_context *ctx) pm_runtime_get_sync(ctx->dev); - clk_prepare_enable(res->mixer); - clk_prepare_enable(res->hdmi); + ret = clk_prepare_enable(res->mixer); + if (ret < 0) { + DRM_ERROR("Failed to prepare_enable the mixer clk [%d]\n", ret); + return; + } + ret = clk_prepare_enable(res->hdmi); + if (ret < 0) { + DRM_ERROR("Failed to prepare_enable the hdmi clk [%d]\n", ret); + return; + } if (ctx->vp_enabled) { - clk_prepare_enable(res->vp); - if (ctx->has_sclk) - clk_prepare_enable(res->sclk_mixer); + ret = clk_prepare_enable(res->vp); + if (ret < 0) { + DRM_ERROR("Failed to prepare_enable the vp clk [%d]\n", + ret); + return; + } + if (ctx->has_sclk) { + ret = clk_prepare_enable(res->sclk_mixer); + if (ret < 0) { + DRM_ERROR("Failed to prepare_enable the " \ + "sclk_mixer clk [%d]\n", + ret); + return; + } + } } mutex_lock(&ctx->mixer_mutex); @@ -1055,15 +1052,17 @@ static void mixer_poweron(struct mixer_context *ctx) mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET); + if (ctx->int_en & MXR_INT_EN_VSYNC) + mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC); mixer_reg_write(res, MXR_INT_EN, ctx->int_en); mixer_win_reset(ctx); - - mixer_window_resume(ctx); } -static void mixer_poweroff(struct mixer_context *ctx) +static void mixer_disable(struct exynos_drm_crtc *crtc) { + struct mixer_context *ctx = crtc->ctx; struct mixer_resources *res = &ctx->mixer_res; + int i; mutex_lock(&ctx->mixer_mutex); if (!ctx->powered) { @@ -1074,7 +1073,9 @@ static void mixer_poweroff(struct mixer_context *ctx) mixer_stop(ctx); mixer_regs_dump(ctx); - mixer_window_suspend(ctx); + + for (i = 0; i < MIXER_WIN_NR; i++) + mixer_win_disable(crtc, i); ctx->int_en = mixer_reg_read(res, MXR_INT_EN); @@ -1093,23 +1094,6 @@ static void mixer_poweroff(struct mixer_context *ctx) pm_runtime_put_sync(ctx->dev); } -static void mixer_dpms(struct exynos_drm_crtc *crtc, int mode) -{ - switch (mode) { - case DRM_MODE_DPMS_ON: - mixer_poweron(crtc->ctx); - break; - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - case DRM_MODE_DPMS_OFF: - mixer_poweroff(crtc->ctx); - break; - default: - DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); - break; - } -} - /* Only valid for Mixer version 16.0.33.0 */ int mixer_check_mode(struct drm_display_mode *mode) { @@ -1131,7 +1115,8 @@ int mixer_check_mode(struct drm_display_mode *mode) } static const struct exynos_drm_crtc_ops mixer_crtc_ops = { - .dpms = mixer_dpms, + .enable = mixer_enable, + .disable = mixer_disable, .enable_vblank = mixer_enable_vblank, .disable_vblank = mixer_disable_vblank, .wait_for_vblank = mixer_wait_for_vblank, @@ -1280,18 +1265,9 @@ static int mixer_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ctx); - ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC, - EXYNOS_DISPLAY_TYPE_HDMI); - if (ret) - return ret; - ret = component_add(&pdev->dev, &mixer_component_ops); - if (ret) { - exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC); - return ret; - } - - pm_runtime_enable(dev); + if (!ret) + pm_runtime_enable(dev); return ret; } @@ -1301,7 +1277,6 @@ static int mixer_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); component_del(&pdev->dev, &mixer_component_ops); - exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC); return 0; } -- cgit v1.2.3-54-g00ecf