From 4013ef48798ae954530bdb8971d3794333e46526 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 8 Mar 2017 15:12:53 +0100 Subject: [PATCH 01/27] drm/exynos: Merge pre/postclose hooks Again no apparent explanation for the split except hysterical raisins. Cc: Inki Dae Cc: Joonyoung Shim Cc: Seung-Woo Kim Cc: Kyungmin Park Signed-off-by: Daniel Vetter Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_drv.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 09d3c4c3c858..50294a7bd29d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -82,14 +82,9 @@ err_file_priv_free: return ret; } -static void exynos_drm_preclose(struct drm_device *dev, - struct drm_file *file) -{ - exynos_drm_subdrv_close(dev, file); -} - static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) { + exynos_drm_subdrv_close(dev, file); kfree(file->driver_priv); file->driver_priv = NULL; } @@ -145,7 +140,6 @@ static struct drm_driver exynos_drm_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC | DRIVER_RENDER, .open = exynos_drm_open, - .preclose = exynos_drm_preclose, .lastclose = exynos_drm_lastclose, .postclose = exynos_drm_postclose, .gem_free_object_unlocked = exynos_drm_gem_free_object, From f2921d8c4899a3d9d7c6326315c24efea2c9efd9 Mon Sep 17 00:00:00 2001 From: Hoegeun Kwon Date: Thu, 13 Apr 2017 15:05:26 +0900 Subject: [PATCH 02/27] drm/exynos: dsi: Fix the parse_dt function The dsi + panel is a parental relationship, so OF grpah is not needed. Therefore, the current dsi_parse_dt function will throw an error, because there is no linked OF graph for the case fimd + dsi + panel. Parse the Pll burst and esc clock frequency properties in dsi_parse_dt() and create a bridge_node only if there is an OF graph associated with dsi. Signed-off-by: Hoegeun Kwon Reviewed-by: Andrzej Hajda Reviewed-by: Andi Shyti Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index fc4fda738906..24ab77c674ec 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1633,7 +1633,6 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi) { struct device *dev = dsi->dev; struct device_node *node = dev->of_node; - struct device_node *ep; int ret; ret = exynos_dsi_of_read_u32(node, "samsung,pll-clock-frequency", @@ -1641,32 +1640,21 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi) if (ret < 0) return ret; - ep = of_graph_get_endpoint_by_regs(node, DSI_PORT_OUT, 0); - if (!ep) { - dev_err(dev, "no output port with endpoint specified\n"); - return -EINVAL; - } - - ret = exynos_dsi_of_read_u32(ep, "samsung,burst-clock-frequency", + ret = exynos_dsi_of_read_u32(node, "samsung,burst-clock-frequency", &dsi->burst_clk_rate); if (ret < 0) - goto end; + return ret; - ret = exynos_dsi_of_read_u32(ep, "samsung,esc-clock-frequency", + ret = exynos_dsi_of_read_u32(node, "samsung,esc-clock-frequency", &dsi->esc_clk_rate); if (ret < 0) - goto end; - - of_node_put(ep); + return ret; dsi->bridge_node = of_graph_get_remote_node(node, DSI_PORT_OUT, 0); if (!dsi->bridge_node) return -EINVAL; -end: - of_node_put(ep); - - return ret; + return 0; } static int exynos_dsi_bind(struct device *dev, struct device *master, From 70505c2ef94b7584dc24d6eaaeb0fc335b99813a Mon Sep 17 00:00:00 2001 From: Hoegeun Kwon Date: Fri, 26 May 2017 10:02:01 +0900 Subject: [PATCH 03/27] drm/exynos: dsi: Remove bridge node reference in removal Since bridge node is referenced during in the probe, it should be released on removal. Suggested-by: Andrzej Hajda Signed-off-by: Hoegeun Kwon Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 24ab77c674ec..d404de86d5f9 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1805,6 +1805,10 @@ static int exynos_dsi_probe(struct platform_device *pdev) static int exynos_dsi_remove(struct platform_device *pdev) { + struct exynos_dsi *dsi = platform_get_drvdata(pdev); + + of_node_put(dsi->bridge_node); + pm_runtime_disable(&pdev->dev); component_del(&pdev->dev, &exynos_dsi_component_ops); From e379cbee79a8abb8e9b4da63187884939852ddb4 Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Mon, 29 May 2017 09:59:05 +0900 Subject: [PATCH 04/27] drm/exynos: clean up description of exynos_drm_crtc This patch removes unnecessary descriptions on exynos_drm_crtc structure and adds one description which specifies what pipe_clk member does. pipe_clk support had been added by below patch without any description, drm/exynos: add support for pipeline clock to the framework Commit-id : f26b9343f582f44ec920474d71b4b2220b1ed9a8 Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_drv.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index cb3176930596..39c740572034 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -160,12 +160,9 @@ struct exynos_drm_clk { * drm framework doesn't support multiple irq yet. * we can refer to the crtc to current hardware interrupt occurred through * this pipe value. - * @enabled: if the crtc is enabled or not - * @event: vblank event that is currently queued for flip - * @wait_update: wait all pending planes updates to finish - * @pending_update: number of pending plane updates in this crtc * @ops: pointer to callbacks for exynos drm specific functionality * @ctx: A pointer to the crtc's implementation specific context + * @pipe_clk: A pointer to the crtc's pipeline clock. */ struct exynos_drm_crtc { struct drm_crtc base; From 73b7b44fbd93509d3f30c83ca53c79a5534b0d68 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 15 Mar 2017 15:41:01 +0100 Subject: [PATCH 05/27] drm/exynos: simplify completion event handling All Exynos CRTC drivers shouldn't fail at referencing vblank events, alternate path is actually dead code. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 0620d3ca2d06..918497404aec 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -105,16 +105,15 @@ void exynos_crtc_handle_event(struct exynos_drm_crtc *exynos_crtc) struct drm_pending_vblank_event *event = crtc->state->event; unsigned long flags; - if (event) { - crtc->state->event = NULL; - spin_lock_irqsave(&crtc->dev->event_lock, flags); - if (drm_crtc_vblank_get(crtc) == 0) - drm_crtc_arm_vblank_event(crtc, event); - else - drm_crtc_send_vblank_event(crtc, event); - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - } + if (!event) + return; + crtc->state->event = NULL; + WARN_ON(drm_crtc_vblank_get(crtc) != 0); + + spin_lock_irqsave(&crtc->dev->event_lock, flags); + drm_crtc_arm_vblank_event(crtc, event); + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); } static void exynos_drm_crtc_destroy(struct drm_crtc *crtc) From 0586feba322e1de05075700eb4b835c8b683e62b Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 15 Mar 2017 15:41:02 +0100 Subject: [PATCH 06/27] drm/exynos/decon5433: implement frame counter DECON in Exynos5433 has frame counter, it can be used to implement get_vblank_counter callback. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 12 ++++++++++++ drivers/gpu/drm/exynos/exynos_drm_crtc.c | 11 +++++++++++ drivers/gpu/drm/exynos/exynos_drm_drv.h | 1 + 3 files changed, 24 insertions(+) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index c0e8d3302292..bae3eb5eb2fa 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -166,6 +166,16 @@ static u32 decon_get_frame_count(struct decon_context *ctx, bool end) return frm; } +static u32 decon_get_vblank_counter(struct exynos_drm_crtc *crtc) +{ + struct decon_context *ctx = crtc->ctx; + + if (test_bit(BIT_SUSPENDED, &ctx->flags)) + return 0; + + return decon_get_frame_count(ctx, false); +} + static void decon_setup_trigger(struct decon_context *ctx) { if (!(ctx->out_type & (IFTYPE_I80 | I80_HW_TRG))) @@ -564,6 +574,7 @@ static const struct exynos_drm_crtc_ops decon_crtc_ops = { .disable = decon_disable, .enable_vblank = decon_enable_vblank, .disable_vblank = decon_disable_vblank, + .get_vblank_counter = decon_get_vblank_counter, .atomic_begin = decon_atomic_begin, .update_plane = decon_update_plane, .disable_plane = decon_disable_plane, @@ -583,6 +594,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data) ctx->drm_dev = drm_dev; ctx->pipe = priv->pipe++; + drm_dev->max_vblank_count = 0xffffffff; for (win = ctx->first_win; win < WINDOWS_NR; win++) { int tmp = (win == ctx->first_win) ? 0 : win; diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 918497404aec..c02378b91332 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -142,6 +142,16 @@ static void exynos_drm_crtc_disable_vblank(struct drm_crtc *crtc) exynos_crtc->ops->disable_vblank(exynos_crtc); } +static u32 exynos_drm_crtc_get_vblank_counter(struct drm_crtc *crtc) +{ + struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); + + if (exynos_crtc->ops->get_vblank_counter) + return exynos_crtc->ops->get_vblank_counter(exynos_crtc); + + return 0; +} + static const struct drm_crtc_funcs exynos_crtc_funcs = { .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, @@ -151,6 +161,7 @@ static const struct drm_crtc_funcs exynos_crtc_funcs = { .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, .enable_vblank = exynos_drm_crtc_enable_vblank, .disable_vblank = exynos_drm_crtc_disable_vblank, + .get_vblank_counter = exynos_drm_crtc_get_vblank_counter, }; struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 39c740572034..24ce016914e0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -133,6 +133,7 @@ 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); + u32 (*get_vblank_counter)(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); From d644951c2b2b013751e7dd5efe886340e196fab4 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 29 May 2017 10:05:25 +0900 Subject: [PATCH 07/27] drm/exynos: kill exynos_drm_crtc::pipe Since crtc index is stored in drm_crtc pipe field became redundant. The patch beside removing the field simplifies also exynos_drm_crtc_get_pipe_from_type. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 3 +-- drivers/gpu/drm/exynos/exynos7_drm_decon.c | 3 +-- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 12 +++--------- drivers/gpu/drm/exynos/exynos_drm_crtc.h | 1 - drivers/gpu/drm/exynos/exynos_drm_drv.h | 8 -------- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 3 +-- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 3 +-- drivers/gpu/drm/exynos/exynos_mixer.c | 3 +-- 8 files changed, 8 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index bae3eb5eb2fa..70677bbf3ca6 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -614,8 +614,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data) 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, - &decon_crtc_ops, ctx); + out_type, &decon_crtc_ops, ctx); if (IS_ERR(ctx->crtc)) { ret = PTR_ERR(ctx->crtc); goto err; diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index 48811806fa27..0ccb33473903 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -656,8 +656,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data) exynos_plane = &ctx->planes[DEFAULT_WIN]; ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base, - ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD, - &decon_crtc_ops, ctx); + EXYNOS_DISPLAY_TYPE_LCD, &decon_crtc_ops, ctx); if (IS_ERR(ctx->crtc)) { decon_ctx_remove(ctx); return PTR_ERR(ctx->crtc); diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index c02378b91332..2d0aa11f19ef 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -166,7 +166,6 @@ static const struct drm_crtc_funcs exynos_crtc_funcs = { struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, struct drm_plane *plane, - int pipe, enum exynos_drm_output_type type, const struct exynos_drm_crtc_ops *ops, void *ctx) @@ -179,7 +178,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, if (!exynos_crtc) return ERR_PTR(-ENOMEM); - exynos_crtc->pipe = pipe; exynos_crtc->type = type; exynos_crtc->ops = ops; exynos_crtc->ctx = ctx; @@ -206,13 +204,9 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, { struct drm_crtc *crtc; - list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head) { - struct exynos_drm_crtc *exynos_crtc; - - exynos_crtc = to_exynos_crtc(crtc); - if (exynos_crtc->type == out_type) - return exynos_crtc->pipe; - } + drm_for_each_crtc(crtc, drm_dev) + if (to_exynos_crtc(crtc)->type == out_type) + return drm_crtc_index(crtc); return -EPERM; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h index 9634fe5ad5fe..ef58b64e3d2d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h @@ -19,7 +19,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, struct drm_plane *plane, - int pipe, enum exynos_drm_output_type type, const struct exynos_drm_crtc_ops *ops, void *context); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 24ce016914e0..006cfa8b40c2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -154,13 +154,6 @@ struct exynos_drm_clk { * * @base: crtc object. * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. - * @pipe: a crtc index created at load() with a new crtc object creation - * and the crtc object would be set to private->crtc array - * to get a crtc object corresponding to this pipe from private->crtc - * array when irq interrupt occurred. the reason of using this pipe is that - * drm framework doesn't support multiple irq yet. - * we can refer to the crtc to current hardware interrupt occurred through - * this pipe value. * @ops: pointer to callbacks for exynos drm specific functionality * @ctx: A pointer to the crtc's implementation specific context * @pipe_clk: A pointer to the crtc's pipeline clock. @@ -168,7 +161,6 @@ struct exynos_drm_clk { struct exynos_drm_crtc { struct drm_crtc base; enum exynos_drm_output_type type; - unsigned int pipe; const struct exynos_drm_crtc_ops *ops; void *ctx; struct exynos_drm_clk *pipe_clk; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 3f04d72c448d..93bdfbb51275 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -1003,8 +1003,7 @@ static int fimd_bind(struct device *dev, struct device *master, void *data) exynos_plane = &ctx->planes[DEFAULT_WIN]; ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base, - ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD, - &fimd_crtc_ops, ctx); + EXYNOS_DISPLAY_TYPE_LCD, &fimd_crtc_ops, ctx); if (IS_ERR(ctx->crtc)) return PTR_ERR(ctx->crtc); diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index ef86dbf1cc29..5e37bb004573 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -416,8 +416,7 @@ static int vidi_bind(struct device *dev, struct device *master, void *data) exynos_plane = &ctx->planes[DEFAULT_WIN]; ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base, - ctx->pipe, EXYNOS_DISPLAY_TYPE_VIDI, - &vidi_crtc_ops, ctx); + EXYNOS_DISPLAY_TYPE_VIDI, &vidi_crtc_ops, ctx); if (IS_ERR(ctx->crtc)) { DRM_ERROR("failed to create crtc.\n"); return PTR_ERR(ctx->crtc); diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 25edb635a197..3fb8cf3f1a43 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -1165,8 +1165,7 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data) exynos_plane = &ctx->planes[DEFAULT_WIN]; ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base, - ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI, - &mixer_crtc_ops, ctx); + EXYNOS_DISPLAY_TYPE_HDMI, &mixer_crtc_ops, ctx); if (IS_ERR(ctx->crtc)) { mixer_ctx_remove(ctx); ret = PTR_ERR(ctx->crtc); From f44d3d2f84d6bc6b685f40a18e08b4bdcaf3d1ef Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 15 Mar 2017 15:41:04 +0100 Subject: [PATCH 08/27] drm/exynos: kill exynos_drm_private::pipe The field duplicates drm_dev->mode_config.num_crtc. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 18 ++++-------------- drivers/gpu/drm/exynos/exynos7_drm_decon.c | 11 ++--------- drivers/gpu/drm/exynos/exynos_drm_drv.h | 3 --- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 9 ++------- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 4 +--- drivers/gpu/drm/exynos/exynos_mixer.c | 8 ++------ 6 files changed, 11 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 70677bbf3ca6..dd5cbd553f76 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -586,14 +586,13 @@ static int decon_bind(struct device *dev, struct device *master, void *data) { struct decon_context *ctx = dev_get_drvdata(dev); struct drm_device *drm_dev = data; - struct exynos_drm_private *priv = drm_dev->dev_private; struct exynos_drm_plane *exynos_plane; enum exynos_drm_output_type out_type; unsigned int win; int ret; ctx->drm_dev = drm_dev; - ctx->pipe = priv->pipe++; + ctx->pipe = drm_dev->mode_config.num_crtc; drm_dev->max_vblank_count = 0xffffffff; for (win = ctx->first_win; win < WINDOWS_NR; win++) { @@ -615,21 +614,12 @@ static int decon_bind(struct device *dev, struct device *master, void *data) : EXYNOS_DISPLAY_TYPE_LCD; ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base, out_type, &decon_crtc_ops, ctx); - if (IS_ERR(ctx->crtc)) { - ret = PTR_ERR(ctx->crtc); - goto err; - } + if (IS_ERR(ctx->crtc)) + return PTR_ERR(ctx->crtc); decon_clear_channels(ctx->crtc); - ret = drm_iommu_attach_device(drm_dev, dev); - if (ret) - goto err; - - return ret; -err: - priv->pipe--; - return ret; + return drm_iommu_attach_device(drm_dev, dev); } static void decon_unbind(struct device *dev, struct device *master, void *data) diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index 0ccb33473903..206e779e6acb 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -130,19 +130,12 @@ static void decon_clear_channels(struct exynos_drm_crtc *crtc) static int decon_ctx_initialize(struct decon_context *ctx, struct drm_device *drm_dev) { - struct exynos_drm_private *priv = drm_dev->dev_private; - int ret; - ctx->drm_dev = drm_dev; - ctx->pipe = priv->pipe++; + ctx->pipe = drm_dev->mode_config.num_crtc; decon_clear_channels(ctx->crtc); - ret = drm_iommu_attach_device(drm_dev, ctx->dev); - if (ret) - priv->pipe--; - - return ret; + return drm_iommu_attach_device(drm_dev, ctx->dev); } static void decon_ctx_remove(struct decon_context *ctx) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 006cfa8b40c2..226ed308c098 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -193,7 +193,6 @@ struct drm_exynos_file_private { * otherwise default one. * @da_space_size: size of device address space. * if 0 then default value is used for it. - * @pipe: the pipe number for this crtc/manager. * @pending: the crtcs that have pending updates to finish * @lock: protect access to @pending * @wait: wait an atomic commit to finish @@ -204,8 +203,6 @@ struct exynos_drm_private { struct device *dma_dev; void *mapping; - unsigned int pipe; - /* for atomic commit */ u32 pending; spinlock_t lock; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 93bdfbb51275..fc4ff9bdca4a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -982,13 +982,12 @@ static int fimd_bind(struct device *dev, struct device *master, void *data) { struct fimd_context *ctx = dev_get_drvdata(dev); struct drm_device *drm_dev = data; - struct exynos_drm_private *priv = drm_dev->dev_private; struct exynos_drm_plane *exynos_plane; unsigned int i; int ret; ctx->drm_dev = drm_dev; - ctx->pipe = priv->pipe++; + ctx->pipe = drm_dev->mode_config.num_crtc; for (i = 0; i < WINDOWS_NR; i++) { ctx->configs[i].pixel_formats = fimd_formats; @@ -1018,11 +1017,7 @@ static int fimd_bind(struct device *dev, struct device *master, void *data) if (is_drm_iommu_supported(drm_dev)) fimd_clear_channels(ctx->crtc); - ret = drm_iommu_attach_device(drm_dev, dev); - if (ret) - priv->pipe--; - - return ret; + return drm_iommu_attach_device(drm_dev, dev); } static void fimd_unbind(struct device *dev, struct device *master, diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 5e37bb004573..68870a938442 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -156,10 +156,8 @@ static void vidi_disable(struct exynos_drm_crtc *crtc) static int vidi_ctx_initialize(struct vidi_context *ctx, struct drm_device *drm_dev) { - struct exynos_drm_private *priv = drm_dev->dev_private; - ctx->drm_dev = drm_dev; - ctx->pipe = priv->pipe++; + ctx->pipe = drm_dev->mode_config.num_crtc; return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 3fb8cf3f1a43..1474982e94a9 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -900,7 +900,7 @@ static int mixer_initialize(struct mixer_context *mixer_ctx, priv = drm_dev->dev_private; mixer_ctx->drm_dev = drm_dev; - mixer_ctx->pipe = priv->pipe++; + mixer_ctx->pipe = drm_dev->mode_config.num_crtc; /* acquire resources: regs, irqs, clocks */ ret = mixer_resources_init(mixer_ctx); @@ -918,11 +918,7 @@ static int mixer_initialize(struct mixer_context *mixer_ctx, } } - ret = drm_iommu_attach_device(drm_dev, mixer_ctx->dev); - if (ret) - priv->pipe--; - - return ret; + return drm_iommu_attach_device(drm_dev, mixer_ctx->dev); } static void mixer_ctx_remove(struct mixer_context *mixer_ctx) From 2c82607b56ad7035077dbb0d37093d8f2b21e235 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 15 Mar 2017 15:41:05 +0100 Subject: [PATCH 09/27] drm/exynos: set plane possible_crtcs in exynos_plane_init All Exynos planes are assigned to exactly one CRTC, it allows to simplify initialization by moving setting of possible_crtcs to exynos_plane_init. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 2 +- drivers/gpu/drm/exynos/exynos7_drm_decon.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_plane.c | 5 ++--- drivers/gpu/drm/exynos/exynos_drm_plane.h | 1 - drivers/gpu/drm/exynos/exynos_drm_vidi.c | 2 +- drivers/gpu/drm/exynos/exynos_mixer.c | 2 +- 7 files changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index dd5cbd553f76..8a3aa8ef940a 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -604,7 +604,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data) ctx->configs[win].type = decon_win_types[tmp]; ret = exynos_plane_init(drm_dev, &ctx->planes[win], win, - 1 << ctx->pipe, &ctx->configs[win]); + &ctx->configs[win]); if (ret) return ret; } diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index 206e779e6acb..4320b3bbc4c0 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -642,7 +642,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data) ctx->configs[i].type = decon_win_types[i]; ret = exynos_plane_init(drm_dev, &ctx->planes[i], i, - 1 << ctx->pipe, &ctx->configs[i]); + &ctx->configs[i]); if (ret) return ret; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index fc4ff9bdca4a..969145fd8083 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -995,7 +995,7 @@ static int fimd_bind(struct device *dev, struct device *master, void *data) ctx->configs[i].zpos = i; ctx->configs[i].type = fimd_win_types[i]; ret = exynos_plane_init(drm_dev, &ctx->planes[i], i, - 1 << ctx->pipe, &ctx->configs[i]); + &ctx->configs[i]); if (ret) return ret; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index c2f17f30afab..611b6fd65433 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -273,14 +273,13 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane, } int exynos_plane_init(struct drm_device *dev, - struct exynos_drm_plane *exynos_plane, - unsigned int index, unsigned long possible_crtcs, + struct exynos_drm_plane *exynos_plane, unsigned int index, const struct exynos_drm_plane_config *config) { int err; err = drm_universal_plane_init(dev, &exynos_plane->base, - possible_crtcs, + 1 << dev->mode_config.num_crtc, &exynos_plane_funcs, config->pixel_formats, config->num_pixel_formats, diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h index 9aafad164cdf..497047b19614 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.h +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h @@ -11,5 +11,4 @@ int exynos_plane_init(struct drm_device *dev, struct exynos_drm_plane *exynos_plane, unsigned int index, - unsigned long possible_crtcs, const struct exynos_drm_plane_config *config); diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 68870a938442..92ebeaf50cdb 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -407,7 +407,7 @@ static int vidi_bind(struct device *dev, struct device *master, void *data) plane_config.type = vidi_win_types[i]; ret = exynos_plane_init(drm_dev, &ctx->planes[i], i, - 1 << ctx->pipe, &plane_config); + &plane_config); if (ret) return ret; } diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 1474982e94a9..3722b5ffabd1 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -1154,7 +1154,7 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data) continue; ret = exynos_plane_init(drm_dev, &ctx->planes[i], i, - 1 << ctx->pipe, &plane_configs[i]); + &plane_configs[i]); if (ret) return ret; } From 2949390eb1be95633afdc39923f53ea5b326242a Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 15 Mar 2017 15:41:06 +0100 Subject: [PATCH 10/27] drm/exynos: kill pipe field from drivers contexts Since possible_crtcs are set by Exynos core helper pipe fields have no raison d'etre. The only place it was used, as a hack, is fimd_clear_channels, to avoid calling drm_crtc_handle_vblank, but DRM core has already other protection mechanism (vblank->enabled), so it could be safely removed. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 2 -- drivers/gpu/drm/exynos/exynos7_drm_decon.c | 4 +--- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 11 ++--------- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 15 +-------------- drivers/gpu/drm/exynos/exynos_mixer.c | 2 -- 5 files changed, 4 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 8a3aa8ef940a..21ab839ea29a 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -64,7 +64,6 @@ struct decon_context { void __iomem *addr; struct regmap *sysreg; struct clk *clks[ARRAY_SIZE(decon_clks_name)]; - int pipe; unsigned long flags; unsigned long out_type; int first_win; @@ -592,7 +591,6 @@ static int decon_bind(struct device *dev, struct device *master, void *data) int ret; ctx->drm_dev = drm_dev; - ctx->pipe = drm_dev->mode_config.num_crtc; drm_dev->max_vblank_count = 0xffffffff; for (win = ctx->first_win; win < WINDOWS_NR; win++) { diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index 4320b3bbc4c0..1ffb0b13fbdc 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -55,7 +55,6 @@ struct decon_context { unsigned long irq_flags; bool i80_if; bool suspended; - int pipe; wait_queue_head_t wait_vsync_queue; atomic_t wait_vsync_event; @@ -131,7 +130,6 @@ static int decon_ctx_initialize(struct decon_context *ctx, struct drm_device *drm_dev) { ctx->drm_dev = drm_dev; - ctx->pipe = drm_dev->mode_config.num_crtc; decon_clear_channels(ctx->crtc); @@ -605,7 +603,7 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id) writel(clear_bit, ctx->regs + VIDINTCON1); /* check the crtc is detached already from encoder */ - if (ctx->pipe < 0 || !ctx->drm_dev) + if (!ctx->drm_dev) goto out; if (!ctx->i80_if) { diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 969145fd8083..6d073e2e7453 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -179,7 +179,6 @@ struct fimd_context { u32 i80ifcon; bool i80_if; bool suspended; - int pipe; wait_queue_head_t wait_vsync_queue; atomic_t wait_vsync_event; atomic_t win_updated; @@ -354,18 +353,13 @@ static void fimd_clear_channels(struct exynos_drm_crtc *crtc) /* Wait for vsync, as disable channel takes effect at next vsync */ if (ch_enabled) { - int pipe = ctx->pipe; - - /* ensure that vblank interrupt won't be reported to core */ ctx->suspended = false; - ctx->pipe = -1; fimd_enable_vblank(ctx->crtc); fimd_wait_for_vblank(ctx->crtc); fimd_disable_vblank(ctx->crtc); ctx->suspended = true; - ctx->pipe = pipe; } clk_disable_unprepare(ctx->lcd_clk); @@ -899,7 +893,7 @@ static void fimd_te_handler(struct exynos_drm_crtc *crtc) u32 trg_type = ctx->driver_data->trg_type; /* Checks the crtc is detached already from encoder */ - if (ctx->pipe < 0 || !ctx->drm_dev) + if (!ctx->drm_dev) return; if (trg_type == I80_HW_TRG) @@ -957,7 +951,7 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id) writel(clear_bit, ctx->regs + VIDINTCON1); /* check the crtc is detached already from encoder */ - if (ctx->pipe < 0 || !ctx->drm_dev) + if (!ctx->drm_dev) goto out; if (!ctx->i80_if) @@ -987,7 +981,6 @@ static int fimd_bind(struct device *dev, struct device *master, void *data) int ret; ctx->drm_dev = drm_dev; - ctx->pipe = drm_dev->mode_config.num_crtc; for (i = 0; i < WINDOWS_NR; i++) { ctx->configs[i].pixel_formats = fimd_formats; diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 92ebeaf50cdb..cb8a72842537 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -51,7 +51,6 @@ struct vidi_context { bool suspended; struct timer_list timer; struct mutex lock; - int pipe; }; static inline struct vidi_context *encoder_to_vidi(struct drm_encoder *e) @@ -153,15 +152,6 @@ static void vidi_disable(struct exynos_drm_crtc *crtc) mutex_unlock(&ctx->lock); } -static int vidi_ctx_initialize(struct vidi_context *ctx, - struct drm_device *drm_dev) -{ - ctx->drm_dev = drm_dev; - ctx->pipe = drm_dev->mode_config.num_crtc; - - return 0; -} - static const struct exynos_drm_crtc_ops vidi_crtc_ops = { .enable = vidi_enable, .disable = vidi_disable, @@ -175,9 +165,6 @@ static void vidi_fake_vblank_timer(unsigned long arg) { struct vidi_context *ctx = (void *)arg; - if (ctx->pipe < 0) - return; - if (drm_crtc_handle_vblank(&ctx->crtc->base)) mod_timer(&ctx->timer, jiffies + msecs_to_jiffies(VIDI_REFRESH_TIME) - 1); @@ -397,7 +384,7 @@ static int vidi_bind(struct device *dev, struct device *master, void *data) unsigned int i; int pipe, ret; - vidi_ctx_initialize(ctx, drm_dev); + ctx->drm_dev = drm_dev; plane_config.pixel_formats = formats; plane_config.num_pixel_formats = ARRAY_SIZE(formats); diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 3722b5ffabd1..1cd84cb8d3fb 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -99,7 +99,6 @@ struct mixer_context { struct drm_device *drm_dev; struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[MIXER_WIN_NR]; - int pipe; unsigned long flags; struct mixer_resources mixer_res; @@ -900,7 +899,6 @@ static int mixer_initialize(struct mixer_context *mixer_ctx, priv = drm_dev->dev_private; mixer_ctx->drm_dev = drm_dev; - mixer_ctx->pipe = drm_dev->mode_config.num_crtc; /* acquire resources: regs, irqs, clocks */ ret = mixer_resources_init(mixer_ctx); From c7954aa6f79b1fff83453e33edb359c236eea5df Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 15 Mar 2017 15:41:07 +0100 Subject: [PATCH 11/27] drm/exynos: kill mode_set_nofb callback All Exynos CRTCs are fully configured by .enable callback. The only users of mode_set_nofb actually did nothing in their callbacks - they immediately returned because devices were in suspend state - mode_set_nofb is always called on disabled device. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos7_drm_decon.c | 1 - drivers/gpu/drm/exynos/exynos_drm_crtc.c | 10 ---------- drivers/gpu/drm/exynos/exynos_drm_drv.h | 2 -- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 1 - 4 files changed, 14 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index 1ffb0b13fbdc..3e88269fdc2e 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -581,7 +581,6 @@ static void decon_disable(struct exynos_drm_crtc *crtc) static const struct exynos_drm_crtc_ops decon_crtc_ops = { .enable = decon_enable, .disable = decon_disable, - .commit = decon_commit, .enable_vblank = decon_enable_vblank, .disable_vblank = decon_disable_vblank, .atomic_begin = decon_atomic_begin, diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 2d0aa11f19ef..d72777f6411a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -49,15 +49,6 @@ static void exynos_drm_crtc_disable(struct drm_crtc *crtc) } } -static void -exynos_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) -{ - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - - if (exynos_crtc->ops->commit) - exynos_crtc->ops->commit(exynos_crtc); -} - static int exynos_crtc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { @@ -93,7 +84,6 @@ static void exynos_crtc_atomic_flush(struct drm_crtc *crtc, static const struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { .enable = exynos_drm_crtc_enable, .disable = exynos_drm_crtc_disable, - .mode_set_nofb = exynos_drm_crtc_mode_set_nofb, .atomic_check = exynos_crtc_atomic_check, .atomic_begin = exynos_crtc_atomic_begin, .atomic_flush = exynos_crtc_atomic_flush, diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 226ed308c098..a93de321706b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -115,7 +115,6 @@ struct exynos_drm_plane_config { * * @enable: enable the device * @disable: disable the device - * @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. * @atomic_check: validate state @@ -130,7 +129,6 @@ struct exynos_drm_crtc; struct exynos_drm_crtc_ops { void (*enable)(struct exynos_drm_crtc *crtc); void (*disable)(struct exynos_drm_crtc *crtc); - void (*commit)(struct exynos_drm_crtc *crtc); int (*enable_vblank)(struct exynos_drm_crtc *crtc); void (*disable_vblank)(struct exynos_drm_crtc *crtc); u32 (*get_vblank_counter)(struct exynos_drm_crtc *crtc); diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 6d073e2e7453..60f93cad6643 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -928,7 +928,6 @@ static void fimd_dp_clock_enable(struct exynos_drm_clk *clk, bool enable) static const struct exynos_drm_crtc_ops fimd_crtc_ops = { .enable = fimd_enable, .disable = fimd_disable, - .commit = fimd_commit, .enable_vblank = fimd_enable_vblank, .disable_vblank = fimd_disable_vblank, .atomic_begin = fimd_atomic_begin, From f8172eb3b28b2a497fcbabd7b2d9048ca2b585fc Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 15 Mar 2017 15:41:08 +0100 Subject: [PATCH 12/27] drm/exynos/decon5433: kill DECON_UPDATE workaround Since fixing CMU code (drm/exynos/decon5433: fix CMU programming) DECON started behave predictable and does not need special care during DECON_UPDATE writes. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 21ab839ea29a..b4853053cad0 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -51,8 +51,7 @@ enum decon_flag_bits { BIT_CLKS_ENABLED, BIT_IRQS_ENABLED, BIT_WIN_UPDATED, - BIT_SUSPENDED, - BIT_REQUEST_UPDATE + BIT_SUSPENDED }; struct decon_context { @@ -399,7 +398,6 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, /* window enable */ decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, ~0); - set_bit(BIT_REQUEST_UPDATE, &ctx->flags); } static void decon_disable_plane(struct exynos_drm_crtc *crtc, @@ -412,7 +410,6 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc, return; decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, 0); - set_bit(BIT_REQUEST_UPDATE, &ctx->flags); } static void decon_atomic_flush(struct exynos_drm_crtc *crtc) @@ -429,8 +426,7 @@ 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 (test_and_clear_bit(BIT_REQUEST_UPDATE, &ctx->flags)) - decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); + decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); if (ctx->out_type & IFTYPE_I80) set_bit(BIT_WIN_UPDATED, &ctx->flags); From 3ba808456b3fe77dc4e17de22bb317b70465903d Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 15 Mar 2017 15:41:09 +0100 Subject: [PATCH 13/27] drm/exynos/decon5433: kill BIT_IRQS_ENABLED BIT_IRQS_ENABLED flag duplicates drm_vblank_crtc::refcount, it could be safely removed. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index b4853053cad0..3bae2fc8dcb6 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -49,7 +49,6 @@ static const char * const decon_clks_name[] = { enum decon_flag_bits { BIT_CLKS_ENABLED, - BIT_IRQS_ENABLED, BIT_WIN_UPDATED, BIT_SUSPENDED }; @@ -98,15 +97,13 @@ static int decon_enable_vblank(struct exynos_drm_crtc *crtc) if (test_bit(BIT_SUSPENDED, &ctx->flags)) return -EPERM; - if (!test_and_set_bit(BIT_IRQS_ENABLED, &ctx->flags)) { - val = VIDINTCON0_INTEN; - if (ctx->out_type & IFTYPE_I80) - val |= VIDINTCON0_FRAMEDONE; - else - val |= VIDINTCON0_INTFRMEN | VIDINTCON0_FRAMESEL_FP; + val = VIDINTCON0_INTEN; + if (ctx->out_type & IFTYPE_I80) + val |= VIDINTCON0_FRAMEDONE; + else + val |= VIDINTCON0_INTFRMEN | VIDINTCON0_FRAMESEL_FP; - writel(val, ctx->addr + DECON_VIDINTCON0); - } + writel(val, ctx->addr + DECON_VIDINTCON0); return 0; } @@ -118,8 +115,7 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc) if (test_bit(BIT_SUSPENDED, &ctx->flags)) return; - if (test_and_clear_bit(BIT_IRQS_ENABLED, &ctx->flags)) - writel(0, ctx->addr + DECON_VIDINTCON0); + writel(0, ctx->addr + DECON_VIDINTCON0); } /* return number of starts/ends of frame transmissions since reset */ @@ -489,10 +485,6 @@ static void decon_enable(struct exynos_drm_crtc *crtc) 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); - decon_commit(ctx->crtc); } From b2adc5307514abe5872185351f772b95cfdce2ff Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 15 Mar 2017 15:41:10 +0100 Subject: [PATCH 14/27] drm/exynos/decon5433: simplify shadow protect code There is no point in protecting only particular windows during update. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 20 +++++++------------ include/video/exynos5433_decon.h | 1 + 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 3bae2fc8dcb6..42e8f8c74bb0 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -313,23 +313,20 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, writel(val, ctx->addr + DECON_WINCONx(win)); } -static void decon_shadow_protect_win(struct decon_context *ctx, int win, - bool protect) +static void decon_shadow_protect(struct decon_context *ctx, bool protect) { - decon_set_bits(ctx, DECON_SHADOWCON, SHADOWCON_Wx_PROTECT(win), + decon_set_bits(ctx, DECON_SHADOWCON, SHADOWCON_PROTECT_MASK, protect ? ~0 : 0); } static void decon_atomic_begin(struct exynos_drm_crtc *crtc) { struct decon_context *ctx = crtc->ctx; - int i; if (test_bit(BIT_SUSPENDED, &ctx->flags)) return; - for (i = ctx->first_win; i < WINDOWS_NR; i++) - decon_shadow_protect_win(ctx, i, true); + decon_shadow_protect(ctx, true); } #define BIT_VAL(x, e, s) (((x) & ((1 << ((e) - (s) + 1)) - 1)) << (s)) @@ -412,15 +409,13 @@ static void decon_atomic_flush(struct exynos_drm_crtc *crtc) { struct decon_context *ctx = crtc->ctx; unsigned long flags; - int i; if (test_bit(BIT_SUSPENDED, &ctx->flags)) return; spin_lock_irqsave(&ctx->vblank_lock, flags); - for (i = ctx->first_win; i < WINDOWS_NR; i++) - decon_shadow_protect_win(ctx, i, false); + decon_shadow_protect(ctx, false); decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); @@ -540,11 +535,10 @@ static void decon_clear_channels(struct exynos_drm_crtc *crtc) goto err; } - for (win = 0; win < WINDOWS_NR; win++) { - decon_shadow_protect_win(ctx, win, true); + decon_shadow_protect(ctx, true); + for (win = 0; win < WINDOWS_NR; win++) decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, 0); - decon_shadow_protect_win(ctx, win, false); - } + decon_shadow_protect(ctx, false); decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); diff --git a/include/video/exynos5433_decon.h b/include/video/exynos5433_decon.h index 6b083d327e98..78957c9626f5 100644 --- a/include/video/exynos5433_decon.h +++ b/include/video/exynos5433_decon.h @@ -118,6 +118,7 @@ #define WINCONx_ENWIN_F (1 << 0) /* SHADOWCON */ +#define SHADOWCON_PROTECT_MASK GENMASK(14, 10) #define SHADOWCON_Wx_PROTECT(n) (1 << (10 + (n))) /* VIDOSDxD */ From 625e63e27c5bec5bbcec8aeaea82d0b1975d2cf4 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Fri, 19 May 2017 17:27:08 +0900 Subject: [PATCH 15/27] drm/exynos/hdmi: fix pipeline disable order Hardware require that MIXER(crtc) should be disabled prior to HDMI(encoder). It was achieved by disabling crtc from encoder disable callback, bypassing drm core. As a result drm core tried to call vblank related routines on disabled crtc. The patch fixes it by simplifying hdmi_disable routine - now it only cancels hotplug worker. Hardware will be disabled in proper moment during pipe clock disable. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_hdmi.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 1ff6ab6371e8..06bfbe400cf1 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -1486,8 +1486,6 @@ static void hdmi_enable(struct drm_encoder *encoder) static void hdmi_disable(struct drm_encoder *encoder) { struct hdmi_context *hdata = encoder_to_hdmi(encoder); - struct drm_crtc *crtc = encoder->crtc; - const struct drm_crtc_helper_funcs *funcs = NULL; if (!hdata->powered) return; @@ -1498,16 +1496,11 @@ static void hdmi_disable(struct drm_encoder *encoder) * to disable TV Subsystem should be as following, * VP -> Mixer -> HDMI * - * Below codes will try to disable Mixer and VP(if used) - * prior to disabling HDMI. + * To achieve such sequence HDMI is disabled together with HDMI PHY, via + * pipe clock callback. */ - if (crtc) - funcs = crtc->helper_private; - if (funcs && funcs->disable) - (*funcs->disable)(crtc); - - cec_notifier_set_phys_addr(hdata->notifier, CEC_PHYS_ADDR_INVALID); cancel_delayed_work(&hdata->hotplug_work); + cec_notifier_set_phys_addr(hdata->notifier, CEC_PHYS_ADDR_INVALID); hdmiphy_disable(hdata); } From 526b4d3e8b5af7195a2aba596b8ec1622c8da564 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Thu, 13 Apr 2017 16:19:50 +0900 Subject: [PATCH 16/27] drm/exynos/dsi: fix bridge_node DT parsing DSIM uses MIC bridge which is between DECON and DSIM, so the driver should expect bridge node on input side. Fixes: 86418f9 ("drm: convert drivers to use of_graph_get_remote_node") Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index d404de86d5f9..a11b79596e2f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1650,7 +1650,7 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi) if (ret < 0) return ret; - dsi->bridge_node = of_graph_get_remote_node(node, DSI_PORT_OUT, 0); + dsi->bridge_node = of_graph_get_remote_node(node, DSI_PORT_IN, 0); if (!dsi->bridge_node) return -EINVAL; From 2a39db01361ec378718648de90a6e817f891b8d4 Mon Sep 17 00:00:00 2001 From: Tobias Jakobi Date: Fri, 10 Mar 2017 14:30:16 +0100 Subject: [PATCH 17/27] drm/exynos: mixer: simplify mixer_cfg_rgb_fmt() Convert if-statements to switch statement. Removes duplicated code. Reviewed-by: Andrzej Hajda Signed-off-by: Tobias Jakobi Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_mixer.c | 30 +++++++-------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 1cd84cb8d3fb..7f4410296921 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -381,29 +381,14 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) struct mixer_resources *res = &ctx->mixer_res; u32 val; - if (height == 480) { + switch (height) { + case 480: + case 576: val = MXR_CFG_RGB601_0_255; - } else if (height == 576) { - val = MXR_CFG_RGB601_0_255; - } else if (height == 720) { - val = MXR_CFG_RGB709_16_235; - mixer_reg_write(res, MXR_CM_COEFF_Y, - (1 << 30) | (94 << 20) | (314 << 10) | - (32 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CB, - (972 << 20) | (851 << 10) | (225 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CR, - (225 << 20) | (820 << 10) | (1004 << 0)); - } else if (height == 1080) { - val = MXR_CFG_RGB709_16_235; - mixer_reg_write(res, MXR_CM_COEFF_Y, - (1 << 30) | (94 << 20) | (314 << 10) | - (32 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CB, - (972 << 20) | (851 << 10) | (225 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CR, - (225 << 20) | (820 << 10) | (1004 << 0)); - } else { + break; + case 720: + case 1080: + default: val = MXR_CFG_RGB709_16_235; mixer_reg_write(res, MXR_CM_COEFF_Y, (1 << 30) | (94 << 20) | (314 << 10) | @@ -412,6 +397,7 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) (972 << 20) | (851 << 10) | (225 << 0)); mixer_reg_write(res, MXR_CM_COEFF_CR, (225 << 20) | (820 << 10) | (1004 << 0)); + break; } mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); From 2a6e4cd53c498c6762d9fa69745b84ff99815905 Mon Sep 17 00:00:00 2001 From: Tobias Jakobi Date: Fri, 10 Mar 2017 15:21:54 +0100 Subject: [PATCH 18/27] drm/exynos: mixer: document YCbCr magic numbers The output stage of the mixer uses YCbCr for the internal computations, which is the reason that some registers take YCbCr related data as input. In particular this applies to MXR_BG_COLOR{0,1,2} and MXR_CM_COEFF_{Y,CB,CR}. Document the formatting of the data which we write to these registers. While at it, unify wording of comments in the register header. Reviewed-by: Andrzej Hajda Signed-off-by: Tobias Jakobi Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_mixer.c | 33 ++++++++++++++++++++------- drivers/gpu/drm/exynos/regs-mixer.h | 7 ++++-- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 7f4410296921..6bed4f3ffcd6 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -45,6 +45,22 @@ #define MIXER_WIN_NR 3 #define VP_DEFAULT_WIN 2 +/* + * Mixer color space conversion coefficient triplet. + * Used for CSC from RGB to YCbCr. + * Each coefficient is a 10-bit fixed point number with + * sign and no integer part, i.e. + * [0:8] = fractional part (representing a value y = x / 2^9) + * [9] = sign + * Negative values are encoded with two's complement. + */ +#define MXR_CSC_C(x) ((int)((x) * 512.0) & 0x3ff) +#define MXR_CSC_CT(a0, a1, a2) \ + ((MXR_CSC_C(a0) << 20) | (MXR_CSC_C(a1) << 10) | (MXR_CSC_C(a2) << 0)) + +/* YCbCr value, used for mixer background color configuration. */ +#define MXR_YCBCR_VAL(y, cb, cr) (((y) << 16) | ((cb) << 8) | ((cr) << 0)) + /* The pixelformats that are natively supported by the mixer. */ #define MXR_FORMAT_RGB565 4 #define MXR_FORMAT_ARGB1555 5 @@ -390,13 +406,14 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) case 1080: default: val = MXR_CFG_RGB709_16_235; + /* Configure the BT.709 CSC matrix for full range RGB. */ mixer_reg_write(res, MXR_CM_COEFF_Y, - (1 << 30) | (94 << 20) | (314 << 10) | - (32 << 0)); + MXR_CSC_CT( 0.184, 0.614, 0.063) | + MXR_CM_COEFF_RGB_FULL); mixer_reg_write(res, MXR_CM_COEFF_CB, - (972 << 20) | (851 << 10) | (225 << 0)); + MXR_CSC_CT(-0.102, -0.338, 0.440)); mixer_reg_write(res, MXR_CM_COEFF_CR, - (225 << 20) | (820 << 10) | (1004 << 0)); + MXR_CSC_CT( 0.440, -0.399, -0.040)); break; } @@ -714,10 +731,10 @@ static void mixer_win_reset(struct mixer_context *ctx) /* reset default layer priority */ mixer_reg_write(res, MXR_LAYER_CFG, 0); - /* setting background color */ - mixer_reg_write(res, MXR_BG_COLOR0, 0x008080); - mixer_reg_write(res, MXR_BG_COLOR1, 0x008080); - mixer_reg_write(res, MXR_BG_COLOR2, 0x008080); + /* set all background colors to RGB (0,0,0) */ + mixer_reg_write(res, MXR_BG_COLOR0, MXR_YCBCR_VAL(0, 128, 128)); + mixer_reg_write(res, MXR_BG_COLOR1, MXR_YCBCR_VAL(0, 128, 128)); + mixer_reg_write(res, MXR_BG_COLOR2, MXR_YCBCR_VAL(0, 128, 128)); if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { /* configuration of Video Processor Registers */ diff --git a/drivers/gpu/drm/exynos/regs-mixer.h b/drivers/gpu/drm/exynos/regs-mixer.h index 7f22df5bf707..c311f571bdf9 100644 --- a/drivers/gpu/drm/exynos/regs-mixer.h +++ b/drivers/gpu/drm/exynos/regs-mixer.h @@ -140,11 +140,11 @@ #define MXR_INT_EN_VSYNC (1 << 11) #define MXR_INT_EN_ALL (0x0f << 8) -/* bit for MXR_INT_STATUS */ +/* bits for MXR_INT_STATUS */ #define MXR_INT_CLEAR_VSYNC (1 << 11) #define MXR_INT_STATUS_VSYNC (1 << 0) -/* bit for MXR_LAYER_CFG */ +/* bits for MXR_LAYER_CFG */ #define MXR_LAYER_CFG_GRP1_VAL(x) MXR_MASK_VAL(x, 11, 8) #define MXR_LAYER_CFG_GRP1_MASK MXR_LAYER_CFG_GRP1_VAL(~0) #define MXR_LAYER_CFG_GRP0_VAL(x) MXR_MASK_VAL(x, 7, 4) @@ -152,5 +152,8 @@ #define MXR_LAYER_CFG_VP_VAL(x) MXR_MASK_VAL(x, 3, 0) #define MXR_LAYER_CFG_VP_MASK MXR_LAYER_CFG_VP_VAL(~0) +/* bits for MXR_CM_COEFF_Y */ +#define MXR_CM_COEFF_RGB_FULL (1 << 30) + #endif /* SAMSUNG_REGS_MIXER_H */ From 366dcad34c2fe1684bd93892d06e774e44600f34 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 5 Apr 2017 09:28:29 +0200 Subject: [PATCH 19/27] drm/exynos/decon5433: always do sw-trigger when vblanks enabled When vblanks are enabled userspace and/or kernel can expect vblank interrupt at declared period of time. To generate vblank interrupt image transfer must be triggered. This patch fixes vblank timeouts in case of sw-trigger mode. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 42e8f8c74bb0..028a6575f7d5 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -49,6 +49,7 @@ static const char * const decon_clks_name[] = { enum decon_flag_bits { BIT_CLKS_ENABLED, + BIT_IRQS_ENABLED, BIT_WIN_UPDATED, BIT_SUSPENDED }; @@ -104,6 +105,7 @@ static int decon_enable_vblank(struct exynos_drm_crtc *crtc) val |= VIDINTCON0_INTFRMEN | VIDINTCON0_FRAMESEL_FP; writel(val, ctx->addr + DECON_VIDINTCON0); + set_bit(BIT_IRQS_ENABLED, &ctx->flags); return 0; } @@ -112,6 +114,7 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc) { struct decon_context *ctx = crtc->ctx; + clear_bit(BIT_IRQS_ENABLED, &ctx->flags); if (test_bit(BIT_SUSPENDED, &ctx->flags)) return; @@ -518,7 +521,8 @@ static void decon_te_irq_handler(struct exynos_drm_crtc *crtc) (ctx->out_type & I80_HW_TRG)) return; - if (test_and_clear_bit(BIT_WIN_UPDATED, &ctx->flags)) + if (test_and_clear_bit(BIT_WIN_UPDATED, &ctx->flags) || + test_bit(BIT_IRQS_ENABLED, &ctx->flags)) decon_set_bits(ctx, DECON_TRIGCON, TRIGCON_SWTRIGCMD, ~0); } From a8875f8214b6644e3c08d6b7ce1d419fdfb2b4f4 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 5 Apr 2017 09:28:30 +0200 Subject: [PATCH 20/27] dt-bindings: exynos5433-decon: fix interrupts bindings DECON requires different interrupts depending on mode of work, which depends on panel it is connected to. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- .../bindings/display/exynos/exynos5433-decon.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt b/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt index c9fd7b3807e7..ba6be99cb794 100644 --- a/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt +++ b/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt @@ -8,12 +8,12 @@ Required properties: - 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 - depends on the interrupt controller used. -- interrupt-names: should contain the interrupt names: "vsync", "lcd_sys" - in the same order as they were listed in the interrupts - property. +- interrupt-names: should contain the interrupt names depending on mode of work: + video mode: "vsync", + command mode: "lcd_sys". +- interrupts or interrupts-extended: list of interrupt specifiers corresponding + to names privided in interrupt-names, as described in + interrupt-controller/interrupts.txt - 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 From f8b7f1f86fbebe81d996dcb51231bc0536569a4f Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 5 Apr 2017 09:28:31 +0200 Subject: [PATCH 21/27] dt-bindings: exynos5433-decon: add TE interrupt binding DECON command mode can use hardware trigger where transmission is triggered automatically, or software trigger - where TE interrupt handler should trigger transmission. DECON will use software trigger if TE interrupt is specified. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- .../devicetree/bindings/display/exynos/exynos5433-decon.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt b/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt index ba6be99cb794..549c538b38a5 100644 --- a/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt +++ b/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt @@ -10,7 +10,8 @@ Required properties: - reg: physical base address and length of the DECON registers set. - interrupt-names: should contain the interrupt names depending on mode of work: video mode: "vsync", - command mode: "lcd_sys". + command mode: "lcd_sys", + command mode with software trigger: "lcd_sys", "te". - interrupts or interrupts-extended: list of interrupt specifiers corresponding to names privided in interrupt-names, as described in interrupt-controller/interrupts.txt From b37d53a0382c03064e6fee3ea1fdc77caf4906c6 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 5 Apr 2017 09:28:32 +0200 Subject: [PATCH 22/27] drm/exynos/decon5433: move TE handling to DECON DECON is the only user of TE signal, moving all TE related code to DECON driver allows to precise control of IRQ handlers. This control allows to fix race between IRQ handler and DECON disable code - now it is possible to disable DECON during IRQ handling which can result in kernel crash. Beside race fixing this change allows further code simplification. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 94 ++++++++++++++----- 1 file changed, 71 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 028a6575f7d5..5bdf1a0ec862 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -63,6 +63,8 @@ struct decon_context { void __iomem *addr; struct regmap *sysreg; struct clk *clks[ARRAY_SIZE(decon_clks_name)]; + unsigned int irq; + unsigned int te_irq; unsigned long flags; unsigned long out_type; int first_win; @@ -105,6 +107,11 @@ static int decon_enable_vblank(struct exynos_drm_crtc *crtc) val |= VIDINTCON0_INTFRMEN | VIDINTCON0_FRAMESEL_FP; writel(val, ctx->addr + DECON_VIDINTCON0); + + enable_irq(ctx->irq); + if (!(ctx->out_type & I80_HW_TRG)) + enable_irq(ctx->te_irq); + set_bit(BIT_IRQS_ENABLED, &ctx->flags); return 0; @@ -118,6 +125,10 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc) if (test_bit(BIT_SUSPENDED, &ctx->flags)) return; + if (!(ctx->out_type & I80_HW_TRG)) + disable_irq_nosync(ctx->te_irq); + disable_irq_nosync(ctx->irq); + writel(0, ctx->addr + DECON_VIDINTCON0); } @@ -491,6 +502,10 @@ static void decon_disable(struct exynos_drm_crtc *crtc) struct decon_context *ctx = crtc->ctx; int i; + if (!(ctx->out_type & I80_HW_TRG)) + synchronize_irq(ctx->te_irq); + synchronize_irq(ctx->irq); + if (test_bit(BIT_SUSPENDED, &ctx->flags)) return; @@ -513,17 +528,19 @@ static void decon_disable(struct exynos_drm_crtc *crtc) set_bit(BIT_SUSPENDED, &ctx->flags); } -static void decon_te_irq_handler(struct exynos_drm_crtc *crtc) +static irqreturn_t decon_te_irq_handler(int irq, void *dev_id) { - struct decon_context *ctx = crtc->ctx; + struct decon_context *ctx = dev_id; if (!test_bit(BIT_CLKS_ENABLED, &ctx->flags) || (ctx->out_type & I80_HW_TRG)) - return; + return IRQ_HANDLED; if (test_and_clear_bit(BIT_WIN_UPDATED, &ctx->flags) || test_bit(BIT_IRQS_ENABLED, &ctx->flags)) decon_set_bits(ctx, DECON_TRIGCON, TRIGCON_SWTRIGCMD, ~0); + + return IRQ_HANDLED; } static void decon_clear_channels(struct exynos_drm_crtc *crtc) @@ -564,7 +581,6 @@ static const struct exynos_drm_crtc_ops decon_crtc_ops = { .update_plane = decon_update_plane, .disable_plane = decon_disable_plane, .atomic_flush = decon_atomic_flush, - .te_handler = decon_te_irq_handler, }; static int decon_bind(struct device *dev, struct device *master, void *data) @@ -717,6 +733,31 @@ static const struct of_device_id exynos5433_decon_driver_dt_match[] = { }; MODULE_DEVICE_TABLE(of, exynos5433_decon_driver_dt_match); +static int decon_conf_irq(struct decon_context *ctx, const char *name, + irq_handler_t handler, unsigned long int flags, bool required) +{ + struct platform_device *pdev = to_platform_device(ctx->dev); + int ret, irq = platform_get_irq_byname(pdev, name); + + if (irq < 0) { + if (irq == -EPROBE_DEFER) + return irq; + if (required) + dev_err(ctx->dev, "cannot get %s IRQ\n", name); + else + irq = 0; + return irq; + } + irq_set_status_flags(irq, IRQ_NOAUTOEN); + ret = devm_request_irq(ctx->dev, irq, handler, flags, "drm_decon", ctx); + if (ret < 0) { + dev_err(ctx->dev, "IRQ %s request failed\n", name); + return ret; + } + + return irq; +} + static int exynos5433_decon_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -740,15 +781,6 @@ static int exynos5433_decon_probe(struct platform_device *pdev) ctx->out_type |= IFTYPE_I80; } - if (ctx->out_type & I80_HW_TRG) { - ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node, - "samsung,disp-sysreg"); - if (IS_ERR(ctx->sysreg)) { - dev_err(dev, "failed to get system register\n"); - return PTR_ERR(ctx->sysreg); - } - } - for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) { struct clk *clk; @@ -771,18 +803,34 @@ static int exynos5433_decon_probe(struct platform_device *pdev) return PTR_ERR(ctx->addr); } - res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, - (ctx->out_type & IFTYPE_I80) ? "lcd_sys" : "vsync"); - if (!res) { - dev_err(dev, "cannot find IRQ resource\n"); - return -ENXIO; + if (ctx->out_type & IFTYPE_I80) { + ret = decon_conf_irq(ctx, "lcd_sys", decon_irq_handler, 0, true); + if (ret < 0) + return ret; + ctx->irq = ret; + + ret = decon_conf_irq(ctx, "te", decon_te_irq_handler, + IRQF_TRIGGER_RISING, false); + if (ret < 0) + return ret; + if (ret) { + ctx->te_irq = ret; + ctx->out_type &= ~I80_HW_TRG; + } + } else { + ret = decon_conf_irq(ctx, "vsync", decon_irq_handler, 0, true); + if (ret < 0) + return ret; + ctx->irq = ret; } - ret = devm_request_irq(dev, res->start, decon_irq_handler, 0, - "drm_decon", ctx); - if (ret < 0) { - dev_err(dev, "lcd_sys irq request failed\n"); - return ret; + if (ctx->out_type & I80_HW_TRG) { + ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node, + "samsung,disp-sysreg"); + if (IS_ERR(ctx->sysreg)) { + dev_err(dev, "failed to get system register\n"); + return PTR_ERR(ctx->sysreg); + } } platform_set_drvdata(pdev, ctx); From 358eccc0eec8d76db7221f6d51d7d528c656ef46 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 5 Apr 2017 09:28:33 +0200 Subject: [PATCH 23/27] drm/exynos/decon5433: kill BIT_IRQS_ENABLED flag Since DECON uses enable_irq/disable_irq to full control IRQs, there is no point in having flags to trace it separately. As a bonus condition for software trigger becomes always true, so it can be removed. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 5bdf1a0ec862..dc2e69a9cf13 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -49,7 +49,6 @@ static const char * const decon_clks_name[] = { enum decon_flag_bits { BIT_CLKS_ENABLED, - BIT_IRQS_ENABLED, BIT_WIN_UPDATED, BIT_SUSPENDED }; @@ -112,8 +111,6 @@ static int decon_enable_vblank(struct exynos_drm_crtc *crtc) if (!(ctx->out_type & I80_HW_TRG)) enable_irq(ctx->te_irq); - set_bit(BIT_IRQS_ENABLED, &ctx->flags); - return 0; } @@ -121,7 +118,6 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc) { struct decon_context *ctx = crtc->ctx; - clear_bit(BIT_IRQS_ENABLED, &ctx->flags); if (test_bit(BIT_SUSPENDED, &ctx->flags)) return; @@ -536,9 +532,7 @@ static irqreturn_t decon_te_irq_handler(int irq, void *dev_id) (ctx->out_type & I80_HW_TRG)) return IRQ_HANDLED; - if (test_and_clear_bit(BIT_WIN_UPDATED, &ctx->flags) || - test_bit(BIT_IRQS_ENABLED, &ctx->flags)) - decon_set_bits(ctx, DECON_TRIGCON, TRIGCON_SWTRIGCMD, ~0); + decon_set_bits(ctx, DECON_TRIGCON, TRIGCON_SWTRIGCMD, ~0); return IRQ_HANDLED; } From 3643e758744dc2c336387fb2cb79c93c3242f18f Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 5 Apr 2017 09:28:34 +0200 Subject: [PATCH 24/27] drm/exynos/decon5433: kill BIT_CLKS_ENABLED flag The flag was used to check if IRQ handlers can touch HW. Since driver enables IRQs only if hardware is enabled the flag becomes redundant. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index dc2e69a9cf13..2629a59fc7bb 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -48,7 +48,6 @@ static const char * const decon_clks_name[] = { }; enum decon_flag_bits { - BIT_CLKS_ENABLED, BIT_WIN_UPDATED, BIT_SUSPENDED }; @@ -486,8 +485,6 @@ static void decon_enable(struct exynos_drm_crtc *crtc) exynos_drm_pipe_clk_enable(crtc, true); - set_bit(BIT_CLKS_ENABLED, &ctx->flags); - decon_swreset(ctx); decon_commit(ctx->crtc); @@ -515,8 +512,6 @@ static void decon_disable(struct exynos_drm_crtc *crtc) decon_swreset(ctx); - clear_bit(BIT_CLKS_ENABLED, &ctx->flags); - exynos_drm_pipe_clk_enable(crtc, false); pm_runtime_put_sync(ctx->dev); @@ -528,8 +523,7 @@ static irqreturn_t decon_te_irq_handler(int irq, void *dev_id) { struct decon_context *ctx = dev_id; - if (!test_bit(BIT_CLKS_ENABLED, &ctx->flags) || - (ctx->out_type & I80_HW_TRG)) + if (ctx->out_type & I80_HW_TRG) return IRQ_HANDLED; decon_set_bits(ctx, DECON_TRIGCON, TRIGCON_SWTRIGCMD, ~0); @@ -654,9 +648,6 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id) struct decon_context *ctx = dev_id; u32 val; - if (!test_bit(BIT_CLKS_ENABLED, &ctx->flags)) - goto out; - val = readl(ctx->addr + DECON_VIDINTCON1); val &= VIDINTCON1_INTFRMDONEPEND | VIDINTCON1_INTFRMPEND; @@ -672,7 +663,6 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id) decon_handle_vblank(ctx); } -out: return IRQ_HANDLED; } From a48ff5010153946355d6d7e171807977e712c9c8 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 5 Apr 2017 09:28:35 +0200 Subject: [PATCH 25/27] drm/exynos/decon5433: kill BIT_WIN_UPDATED flag The flag was used to trigger software update in TE IRQ handler only if framebuffers were replaced. Since TE update is triggered always when VBLANKs are enabled and after framebuffer replacement VBLANKs are always enabled the flag becomes redundant. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 2629a59fc7bb..b81c12b1f857 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -48,7 +48,6 @@ static const char * const decon_clks_name[] = { }; enum decon_flag_bits { - BIT_WIN_UPDATED, BIT_SUSPENDED }; @@ -428,9 +427,6 @@ static void decon_atomic_flush(struct exynos_drm_crtc *crtc) decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); - if (ctx->out_type & IFTYPE_I80) - set_bit(BIT_WIN_UPDATED, &ctx->flags); - ctx->frame_id = decon_get_frame_count(ctx, true); exynos_crtc_handle_event(crtc); From 2073ddb4ff8492dcd2c5f3a9f01252ce7f5a2974 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 5 Apr 2017 09:28:36 +0200 Subject: [PATCH 26/27] drm/exynos/decon5433: kill BIT_SUSPENDED flag Exynos tracked suspend state to prevent touching disabled HW. After fixing disable order in HDMI and moving TE handling to DECON it is not needed anymore - all IRQ handlers and callbacks touching HW are called only with enabled DECON. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 38 ------------------- 1 file changed, 38 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index b81c12b1f857..1cb4b86eb33c 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -47,10 +47,6 @@ static const char * const decon_clks_name[] = { "sclk_decon_eclk", }; -enum decon_flag_bits { - BIT_SUSPENDED -}; - struct decon_context { struct device *dev; struct drm_device *drm_dev; @@ -62,7 +58,6 @@ struct decon_context { struct clk *clks[ARRAY_SIZE(decon_clks_name)]; unsigned int irq; unsigned int te_irq; - unsigned long flags; unsigned long out_type; int first_win; spinlock_t vblank_lock; @@ -94,9 +89,6 @@ static int decon_enable_vblank(struct exynos_drm_crtc *crtc) struct decon_context *ctx = crtc->ctx; u32 val; - if (test_bit(BIT_SUSPENDED, &ctx->flags)) - return -EPERM; - val = VIDINTCON0_INTEN; if (ctx->out_type & IFTYPE_I80) val |= VIDINTCON0_FRAMEDONE; @@ -116,9 +108,6 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc) { struct decon_context *ctx = crtc->ctx; - if (test_bit(BIT_SUSPENDED, &ctx->flags)) - return; - if (!(ctx->out_type & I80_HW_TRG)) disable_irq_nosync(ctx->te_irq); disable_irq_nosync(ctx->irq); @@ -172,9 +161,6 @@ static u32 decon_get_vblank_counter(struct exynos_drm_crtc *crtc) { struct decon_context *ctx = crtc->ctx; - if (test_bit(BIT_SUSPENDED, &ctx->flags)) - return 0; - return decon_get_frame_count(ctx, false); } @@ -205,9 +191,6 @@ static void decon_commit(struct exynos_drm_crtc *crtc) bool interlaced = false; u32 val; - if (test_bit(BIT_SUSPENDED, &ctx->flags)) - return; - if (ctx->out_type & IFTYPE_HDMI) { m->crtc_hsync_start = m->crtc_hdisplay + 10; m->crtc_hsync_end = m->crtc_htotal - 92; @@ -331,9 +314,6 @@ static void decon_atomic_begin(struct exynos_drm_crtc *crtc) { struct decon_context *ctx = crtc->ctx; - if (test_bit(BIT_SUSPENDED, &ctx->flags)) - return; - decon_shadow_protect(ctx, true); } @@ -354,9 +334,6 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, dma_addr_t dma_addr = exynos_drm_fb_dma_addr(fb, 0); u32 val; - if (test_bit(BIT_SUSPENDED, &ctx->flags)) - return; - if (crtc->base.mode.flags & DRM_MODE_FLAG_INTERLACE) { val = COORDINATE_X(state->crtc.x) | COORDINATE_Y(state->crtc.y / 2); @@ -407,9 +384,6 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc, struct decon_context *ctx = crtc->ctx; unsigned int win = plane->index; - if (test_bit(BIT_SUSPENDED, &ctx->flags)) - return; - decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, 0); } @@ -418,9 +392,6 @@ static void decon_atomic_flush(struct exynos_drm_crtc *crtc) struct decon_context *ctx = crtc->ctx; unsigned long flags; - if (test_bit(BIT_SUSPENDED, &ctx->flags)) - return; - spin_lock_irqsave(&ctx->vblank_lock, flags); decon_shadow_protect(ctx, false); @@ -474,9 +445,6 @@ static void decon_enable(struct exynos_drm_crtc *crtc) { struct decon_context *ctx = crtc->ctx; - if (!test_and_clear_bit(BIT_SUSPENDED, &ctx->flags)) - return; - pm_runtime_get_sync(ctx->dev); exynos_drm_pipe_clk_enable(crtc, true); @@ -495,9 +463,6 @@ static void decon_disable(struct exynos_drm_crtc *crtc) synchronize_irq(ctx->te_irq); synchronize_irq(ctx->irq); - if (test_bit(BIT_SUSPENDED, &ctx->flags)) - return; - /* * We need to make sure that all windows are disabled before we * suspend that connector. Otherwise we might try to scan from @@ -511,8 +476,6 @@ static void decon_disable(struct exynos_drm_crtc *crtc) exynos_drm_pipe_clk_enable(crtc, false); pm_runtime_put_sync(ctx->dev); - - set_bit(BIT_SUSPENDED, &ctx->flags); } static irqreturn_t decon_te_irq_handler(int irq, void *dev_id) @@ -750,7 +713,6 @@ static int exynos5433_decon_probe(struct platform_device *pdev) if (!ctx) return -ENOMEM; - __set_bit(BIT_SUSPENDED, &ctx->flags); ctx->dev = dev; ctx->out_type = (unsigned long)of_device_get_match_data(dev); spin_lock_init(&ctx->vblank_lock); From ce42cf4b03e6ad1a6316b2a74a4ceae4b70adcac Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 5 Apr 2017 09:28:37 +0200 Subject: [PATCH 27/27] drm/exynos/decon5433: remove useless check TE IRQ is enabled only in case of sw-trigger, so trigger check is redundant. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 1cb4b86eb33c..5792ca88ab7a 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -482,9 +482,6 @@ static irqreturn_t decon_te_irq_handler(int irq, void *dev_id) { struct decon_context *ctx = dev_id; - if (ctx->out_type & I80_HW_TRG) - return IRQ_HANDLED; - decon_set_bits(ctx, DECON_TRIGCON, TRIGCON_SWTRIGCMD, ~0); return IRQ_HANDLED;