From 5e60f595d6cad3279f4653ea43843a3db91b59e5 Mon Sep 17 00:00:00 2001 From: Fabien DESSENNE Date: Thu, 12 Jan 2017 17:27:35 +0100 Subject: [PATCH 01/11] drm/sti: use atomic_helper for commit Since nonblocking atomic commits are now supported, the driver can now use drm_atomic_helper_commit(). Signed-off-by: Fabien Dessenne Acked-by: Vincent Abriou --- drivers/gpu/drm/sti/sti_drv.c | 84 +++-------------------------------- drivers/gpu/drm/sti/sti_drv.h | 6 --- 2 files changed, 6 insertions(+), 84 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 788feed208d7..9e4d96f7dd1c 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -115,50 +115,13 @@ err: return ret; } -static void sti_atomic_schedule(struct sti_private *private, - struct drm_atomic_state *state) +static void sti_drm_dbg_cleanup(struct drm_minor *minor) { - private->commit.state = state; - schedule_work(&private->commit.work); -} + drm_debugfs_remove_files(sti_drm_dbg_list, + ARRAY_SIZE(sti_drm_dbg_list), minor); -static void sti_atomic_complete(struct sti_private *private, - struct drm_atomic_state *state) -{ - struct drm_device *drm = private->drm_dev; - - /* - * Everything below can be run asynchronously without the need to grab - * any modeset locks at all under one condition: It must be guaranteed - * that the asynchronous work has either been cancelled (if the driver - * supports it, which at least requires that the framebuffers get - * cleaned up with drm_atomic_helper_cleanup_planes()) or completed - * before the new state gets committed on the software side with - * drm_atomic_helper_swap_state(). - * - * This scheme allows new atomic state updates to be prepared and - * checked in parallel to the asynchronous completion of the previous - * update. Which is important since compositors need to figure out the - * composition of the next frame right after having submitted the - * current layout. - */ - - drm_atomic_helper_commit_modeset_disables(drm, state); - drm_atomic_helper_commit_planes(drm, state, 0); - drm_atomic_helper_commit_modeset_enables(drm, state); - - drm_atomic_helper_wait_for_vblanks(drm, state); - - drm_atomic_helper_cleanup_planes(drm, state); - drm_atomic_state_put(state); -} - -static void sti_atomic_work(struct work_struct *work) -{ - struct sti_private *private = container_of(work, - struct sti_private, commit.work); - - sti_atomic_complete(private, private->commit.state); + drm_debugfs_remove_files((struct drm_info_list *)&sti_drm_fps_fops, + 1, minor); } static int sti_atomic_check(struct drm_device *dev, @@ -181,38 +144,6 @@ static int sti_atomic_check(struct drm_device *dev, return ret; } -static int sti_atomic_commit(struct drm_device *drm, - struct drm_atomic_state *state, bool nonblock) -{ - struct sti_private *private = drm->dev_private; - int err; - - err = drm_atomic_helper_prepare_planes(drm, state); - if (err) - return err; - - /* serialize outstanding nonblocking commits */ - mutex_lock(&private->commit.lock); - flush_work(&private->commit.work); - - /* - * This is the point of no return - everything below never fails except - * when the hw goes bonghits. Which means we can commit the new state on - * the software side now. - */ - - drm_atomic_helper_swap_state(state, true); - - drm_atomic_state_get(state); - if (nonblock) - sti_atomic_schedule(private, state); - else - sti_atomic_complete(private, state); - - mutex_unlock(&private->commit.lock); - return 0; -} - static void sti_output_poll_changed(struct drm_device *ddev) { struct sti_private *private = ddev->dev_private; @@ -224,7 +155,7 @@ static const struct drm_mode_config_funcs sti_mode_config_funcs = { .fb_create = drm_fb_cma_create, .output_poll_changed = sti_output_poll_changed, .atomic_check = sti_atomic_check, - .atomic_commit = sti_atomic_commit, + .atomic_commit = drm_atomic_helper_commit, }; static void sti_mode_config_init(struct drm_device *dev) @@ -304,9 +235,6 @@ static int sti_init(struct drm_device *ddev) dev_set_drvdata(ddev->dev, ddev); private->drm_dev = ddev; - mutex_init(&private->commit.lock); - INIT_WORK(&private->commit.work, sti_atomic_work); - drm_mode_config_init(ddev); sti_mode_config_init(ddev); diff --git a/drivers/gpu/drm/sti/sti_drv.h b/drivers/gpu/drm/sti/sti_drv.h index 4c75845cc9ab..6502ed2d3351 100644 --- a/drivers/gpu/drm/sti/sti_drv.h +++ b/drivers/gpu/drm/sti/sti_drv.h @@ -25,12 +25,6 @@ struct sti_private { struct drm_property *plane_zorder_property; struct drm_device *drm_dev; struct drm_fbdev_cma *fbdev; - - struct { - struct drm_atomic_state *state; - struct work_struct work; - struct mutex lock; - } commit; }; extern struct platform_driver sti_tvout_driver; From c62052d1469d283aff31527bfdccd9da08a46005 Mon Sep 17 00:00:00 2001 From: Fabien DESSENNE Date: Thu, 12 Jan 2017 17:27:36 +0100 Subject: [PATCH 02/11] drm/sti: Fix up crtc_state->event handling Use drm-core to handle event. This is required to be able to use the nonblocking helpers. Signed-off-by: Fabien Dessenne Acked-by: Vincent Abriou --- drivers/gpu/drm/sti/sti_crtc.c | 46 ++++++++++----------------------- drivers/gpu/drm/sti/sti_mixer.h | 2 -- 2 files changed, 14 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_crtc.c b/drivers/gpu/drm/sti/sti_crtc.c index e992bed98dcb..d45a4335df5d 100644 --- a/drivers/gpu/drm/sti/sti_crtc.c +++ b/drivers/gpu/drm/sti/sti_crtc.c @@ -134,21 +134,6 @@ sti_crtc_mode_set_nofb(struct drm_crtc *crtc) sti_crtc_mode_set(crtc, &crtc->state->adjusted_mode); } -static void sti_crtc_atomic_begin(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state) -{ - struct sti_mixer *mixer = to_sti_mixer(crtc); - - if (crtc->state->event) { - crtc->state->event->pipe = drm_crtc_index(crtc); - - WARN_ON(drm_crtc_vblank_get(crtc) != 0); - - mixer->pending_event = crtc->state->event; - crtc->state->event = NULL; - } -} - static void sti_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { @@ -156,6 +141,8 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc, struct sti_mixer *mixer = to_sti_mixer(crtc); struct sti_compositor *compo = dev_get_drvdata(mixer->dev); struct drm_plane *p; + struct drm_pending_vblank_event *event; + unsigned long flags; DRM_DEBUG_DRIVER("\n"); @@ -220,13 +207,24 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc, break; } } + + event = crtc->state->event; + 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); + } } static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = { .enable = sti_crtc_enable, .disable = sti_crtc_disabling, .mode_set_nofb = sti_crtc_mode_set_nofb, - .atomic_begin = sti_crtc_atomic_begin, .atomic_flush = sti_crtc_atomic_flush, }; @@ -250,7 +248,6 @@ int sti_crtc_vblank_cb(struct notifier_block *nb, struct sti_compositor *compo; struct drm_crtc *crtc = data; struct sti_mixer *mixer; - unsigned long flags; struct sti_private *priv; unsigned int pipe; @@ -267,14 +264,6 @@ int sti_crtc_vblank_cb(struct notifier_block *nb, drm_crtc_handle_vblank(crtc); - spin_lock_irqsave(&crtc->dev->event_lock, flags); - if (mixer->pending_event) { - drm_crtc_send_vblank_event(crtc, mixer->pending_event); - drm_crtc_vblank_put(crtc); - mixer->pending_event = NULL; - } - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - if (mixer->status == STI_MIXER_DISABLING) { struct drm_plane *p; @@ -317,19 +306,12 @@ void sti_crtc_disable_vblank(struct drm_device *drm_dev, unsigned int pipe) struct sti_private *priv = drm_dev->dev_private; struct sti_compositor *compo = priv->compo; struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb[pipe]; - struct drm_crtc *crtc = &compo->mixer[pipe]->drm_crtc; struct sti_vtg *vtg = compo->vtg[pipe]; DRM_DEBUG_DRIVER("\n"); if (sti_vtg_unregister_client(vtg, vtg_vblank_nb)) DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n"); - - /* free the resources of the pending requests */ - if (compo->mixer[pipe]->pending_event) { - drm_crtc_vblank_put(crtc); - compo->mixer[pipe]->pending_event = NULL; - } } static int sti_crtc_late_register(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/sti/sti_mixer.h b/drivers/gpu/drm/sti/sti_mixer.h index 830a3c42d886..e64a00e61049 100644 --- a/drivers/gpu/drm/sti/sti_mixer.h +++ b/drivers/gpu/drm/sti/sti_mixer.h @@ -28,7 +28,6 @@ enum sti_mixer_status { * @regs: mixer registers * @id: id of the mixer * @drm_crtc: crtc object link to the mixer - * @pending_event: set if a flip event is pending on crtc * @status: to know the status of the mixer */ struct sti_mixer { @@ -36,7 +35,6 @@ struct sti_mixer { void __iomem *regs; int id; struct drm_crtc drm_crtc; - struct drm_pending_vblank_event *pending_event; enum sti_mixer_status status; }; From 6801723b0187c0bb0803758b7b7ef14ba22fdcf2 Mon Sep 17 00:00:00 2001 From: Fabien DESSENNE Date: Thu, 12 Jan 2017 17:27:37 +0100 Subject: [PATCH 03/11] drm/sti: do not check hw scaling if mode is not set Fix a division by 0 case : in some cases, when the HQVDP plane is being disabled atomic_check() is called with "mode->clock = 0". In that case, do not check for scaling capabilities. Signed-off-by: Fabien Dessenne Acked-by: Vincent Abriou --- drivers/gpu/drm/sti/sti_hqvdp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index 4376fd8a8e52..66f843148ef7 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -1037,9 +1037,9 @@ static int sti_hqvdp_atomic_check(struct drm_plane *drm_plane, src_w = state->src_w >> 16; src_h = state->src_h >> 16; - if (!sti_hqvdp_check_hw_scaling(hqvdp, mode, - src_w, src_h, - dst_w, dst_h)) { + if (mode->clock && !sti_hqvdp_check_hw_scaling(hqvdp, mode, + src_w, src_h, + dst_w, dst_h)) { DRM_ERROR("Scaling beyond HW capabilities\n"); return -EINVAL; } From e6d50dc64779026c2e29e764441fd99dfe9a13f3 Mon Sep 17 00:00:00 2001 From: Vincent Abriou Date: Wed, 1 Feb 2017 18:04:00 +0100 Subject: [PATCH 04/11] drm/sti: remove deprecated sink_term config stih416 chip family is no more supported in Linux v4.9. Then sink_term config becomes useless. The field of the register it was referring to is tag as reserved for stih410 chip family. Signed-off-by: Vincent Abriou --- drivers/gpu/drm/sti/sti_hdmi.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index c9151849d604..6862d5911c18 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -95,7 +95,6 @@ #define HDMI_CFG_HDCP_EN BIT(2) #define HDMI_CFG_ESS_NOT_OESS BIT(3) #define HDMI_CFG_H_SYNC_POL_NEG BIT(4) -#define HDMI_CFG_SINK_TERM_DET_EN BIT(5) #define HDMI_CFG_V_SYNC_POL_NEG BIT(6) #define HDMI_CFG_422_EN BIT(8) #define HDMI_CFG_FIFO_OVERRUN_CLR BIT(12) @@ -269,9 +268,6 @@ static void hdmi_config(struct sti_hdmi *hdmi) if (hdmi->hdmi_mode == HDMI_MODE_HDMI) conf |= HDMI_CFG_HDMI_NOT_DVI; - /* Enable sink term detection */ - conf |= HDMI_CFG_SINK_TERM_DET_EN; - /* Set Hsync polarity */ if (hdmi->mode.flags & DRM_MODE_FLAG_NHSYNC) { DRM_DEBUG_DRIVER("H Sync Negative\n"); @@ -607,9 +603,6 @@ static void hdmi_dbg_cfg(struct seq_file *s, int val) tmp = val & HDMI_CFG_ESS_NOT_OESS; DBGFS_PRINT_STR("HDCP mode:", tmp ? "ESS enable" : "OESS enable"); seq_puts(s, "\t\t\t\t\t"); - tmp = val & HDMI_CFG_SINK_TERM_DET_EN; - DBGFS_PRINT_STR("Sink term detection:", tmp ? "enable" : "disable"); - seq_puts(s, "\t\t\t\t\t"); tmp = val & HDMI_CFG_H_SYNC_POL_NEG; DBGFS_PRINT_STR("Hsync polarity:", tmp ? "inverted" : "normal"); seq_puts(s, "\t\t\t\t\t"); From 0c7ff84f7f9db4ea3eeb3da958fcd6d187c8351d Mon Sep 17 00:00:00 2001 From: Vincent Abriou Date: Thu, 2 Feb 2017 09:52:32 +0100 Subject: [PATCH 05/11] drm/sti: remove deprecated legacy vtg slave stih416 chip family is no more supported in Linux v4.9. It is then useless to keep vtg slave field since it not used at all for the stih407/10 chip family supported by sti driver. Signed-off-by: Vincent Abriou --- drivers/gpu/drm/sti/sti_vtg.c | 56 ++++++++--------------------------- 1 file changed, 13 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_vtg.c b/drivers/gpu/drm/sti/sti_vtg.c index c3d9c8ae14af..943bce56692e 100644 --- a/drivers/gpu/drm/sti/sti_vtg.c +++ b/drivers/gpu/drm/sti/sti_vtg.c @@ -17,7 +17,6 @@ #include "sti_vtg.h" #define VTG_MODE_MASTER 0 -#define VTG_MODE_SLAVE_BY_EXT0 1 /* registers offset */ #define VTG_MODE 0x0000 @@ -132,7 +131,6 @@ struct sti_vtg_sync_params { * @irq_status: store the IRQ status value * @notifier_list: notifier callback * @crtc: the CRTC for vblank event - * @slave: slave vtg * @link: List node to link the structure in lookup list */ struct sti_vtg { @@ -144,7 +142,6 @@ struct sti_vtg { u32 irq_status; struct raw_notifier_head notifier_list; struct drm_crtc *crtc; - struct sti_vtg *slave; struct list_head link; }; @@ -166,10 +163,6 @@ struct sti_vtg *of_vtg_find(struct device_node *np) static void vtg_reset(struct sti_vtg *vtg) { - /* reset slave and then master */ - if (vtg->slave) - vtg_reset(vtg->slave); - writel(1, vtg->regs + VTG_DRST_AUTOC); } @@ -259,10 +252,6 @@ static void vtg_set_mode(struct sti_vtg *vtg, { unsigned int i; - if (vtg->slave) - vtg_set_mode(vtg->slave, VTG_MODE_SLAVE_BY_EXT0, - vtg->sync_params, mode); - /* Set the number of clock cycles per line */ writel(mode->htotal, vtg->regs + VTG_CLKLN); @@ -318,11 +307,7 @@ void sti_vtg_set_config(struct sti_vtg *vtg, vtg_reset(vtg); - /* enable irq for the vtg vblank synchro */ - if (vtg->slave) - vtg_enable_irq(vtg->slave); - else - vtg_enable_irq(vtg); + vtg_enable_irq(vtg); } /** @@ -365,18 +350,12 @@ u32 sti_vtg_get_pixel_number(struct drm_display_mode mode, int x) int sti_vtg_register_client(struct sti_vtg *vtg, struct notifier_block *nb, struct drm_crtc *crtc) { - if (vtg->slave) - return sti_vtg_register_client(vtg->slave, nb, crtc); - vtg->crtc = crtc; return raw_notifier_chain_register(&vtg->notifier_list, nb); } int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb) { - if (vtg->slave) - return sti_vtg_unregister_client(vtg->slave, nb); - return raw_notifier_chain_unregister(&vtg->notifier_list, nb); } @@ -434,29 +413,20 @@ static int vtg_probe(struct platform_device *pdev) return -ENOMEM; } - np = of_parse_phandle(pdev->dev.of_node, "st,slave", 0); - if (np) { - vtg->slave = of_vtg_find(np); - of_node_put(np); + vtg->irq = platform_get_irq(pdev, 0); + if (vtg->irq < 0) { + DRM_ERROR("Failed to get VTG interrupt\n"); + return vtg->irq; + } - if (!vtg->slave) - return -EPROBE_DEFER; - } else { - vtg->irq = platform_get_irq(pdev, 0); - if (vtg->irq < 0) { - DRM_ERROR("Failed to get VTG interrupt\n"); - return vtg->irq; - } + RAW_INIT_NOTIFIER_HEAD(&vtg->notifier_list); - RAW_INIT_NOTIFIER_HEAD(&vtg->notifier_list); - - ret = devm_request_threaded_irq(dev, vtg->irq, vtg_irq, - vtg_irq_thread, IRQF_ONESHOT, - dev_name(dev), vtg); - if (ret < 0) { - DRM_ERROR("Failed to register VTG interrupt\n"); - return ret; - } + ret = devm_request_threaded_irq(dev, vtg->irq, vtg_irq, + vtg_irq_thread, IRQF_ONESHOT, + dev_name(dev), vtg); + if (ret < 0) { + DRM_ERROR("Failed to register VTG interrupt\n"); + return ret; } vtg_register(vtg); From 1b7f145123f4d59e6b88a83b507c7981df0ee701 Mon Sep 17 00:00:00 2001 From: Vincent Abriou Date: Thu, 2 Feb 2017 09:47:32 +0100 Subject: [PATCH 06/11] drm/sti: enable gdp pixel clock in atomic_update Set gdp pix clock rate and parent in atomic_check function and enable it in the atomic_update only the first time. Signed-off-by: Vincent Abriou --- drivers/gpu/drm/sti/sti_gdp.c | 70 ++++++++++++++++------------------- 1 file changed, 32 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index 877d053d86f4..7255234670c0 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -610,7 +610,6 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane, struct sti_plane *plane = to_sti_plane(drm_plane); struct sti_gdp *gdp = to_sti_gdp(plane); struct drm_crtc *crtc = state->crtc; - struct sti_compositor *compo = dev_get_drvdata(gdp->dev); struct drm_framebuffer *fb = state->fb; struct drm_crtc_state *crtc_state; struct sti_mixer *mixer; @@ -648,45 +647,30 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane, return -EINVAL; } - if (!gdp->vtg) { - /* Register gdp callback */ - gdp->vtg = compo->vtg[mixer->id]; - if (sti_vtg_register_client(gdp->vtg, - &gdp->vtg_field_nb, crtc)) { - DRM_ERROR("Cannot register VTG notifier\n"); + /* Set gdp clock */ + if (gdp->clk_pix) { + struct clk *clkp; + int rate = mode->clock * 1000; + int res; + + /* + * According to the mixer used, the gdp pixel clock + * should have a different parent clock. + */ + if (mixer->id == STI_MIXER_MAIN) + clkp = gdp->clk_main_parent; + else + clkp = gdp->clk_aux_parent; + + if (clkp) + clk_set_parent(gdp->clk_pix, clkp); + + res = clk_set_rate(gdp->clk_pix, rate); + if (res < 0) { + DRM_ERROR("Cannot set rate (%dHz) for gdp\n", + rate); return -EINVAL; } - - /* Set and enable gdp clock */ - if (gdp->clk_pix) { - struct clk *clkp; - int rate = mode->clock * 1000; - int res; - - /* - * According to the mixer used, the gdp pixel clock - * should have a different parent clock. - */ - if (mixer->id == STI_MIXER_MAIN) - clkp = gdp->clk_main_parent; - else - clkp = gdp->clk_aux_parent; - - if (clkp) - clk_set_parent(gdp->clk_pix, clkp); - - res = clk_set_rate(gdp->clk_pix, rate); - if (res < 0) { - DRM_ERROR("Cannot set rate (%dHz) for gdp\n", - rate); - return -EINVAL; - } - - if (clk_prepare_enable(gdp->clk_pix)) { - DRM_ERROR("Failed to prepare/enable gdp\n"); - return -EINVAL; - } - } } DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n", @@ -724,6 +708,16 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, if (!crtc || !fb) return; + if (!gdp->vtg) { + struct sti_compositor *compo = dev_get_drvdata(gdp->dev); + struct sti_mixer *mixer = to_sti_mixer(crtc); + + /* Register gdp callback */ + gdp->vtg = compo->vtg[mixer->id]; + sti_vtg_register_client(gdp->vtg, &gdp->vtg_field_nb, crtc); + clk_prepare_enable(gdp->clk_pix); + } + mode = &crtc->mode; dst_x = state->crtc_x; dst_y = state->crtc_y; From c5649ee49761f5367c46c5ae6579ab8e8b03575d Mon Sep 17 00:00:00 2001 From: Vincent Abriou Date: Thu, 2 Feb 2017 09:49:02 +0100 Subject: [PATCH 07/11] drm/sti: do not set gdp pixel clock rate if mode is not set Fix a division by 0 case : in some cases, when the GDP plane is being disabled atomic_check() is called with "mode->clock = 0". In that case, do not set parent and pixel clock rate. Signed-off-by: Vincent Abriou --- drivers/gpu/drm/sti/sti_gdp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index 7255234670c0..7f6d0790cca6 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -648,7 +648,7 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane, } /* Set gdp clock */ - if (gdp->clk_pix) { + if (mode->clock && gdp->clk_pix) { struct clk *clkp; int rate = mode->clock * 1000; int res; From e9f494d36fc4cab2ba7e9e7f3bb4edf5b214f651 Mon Sep 17 00:00:00 2001 From: Vincent Abriou Date: Thu, 2 Feb 2017 09:50:48 +0100 Subject: [PATCH 08/11] drm/sti: do not post GDP command if no update Do not process update requests with unmodified parameters. This typically happens when the driver is called with legacy (non-atomic) IOCTL : in that case atomic_update() is called multiple times with the same parameters. Signed-off-by: Vincent Abriou --- drivers/gpu/drm/sti/sti_gdp.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index 7f6d0790cca6..86279f5022c2 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -708,6 +708,21 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, if (!crtc || !fb) return; + if ((oldstate->fb == state->fb) && + (oldstate->crtc_x == state->crtc_x) && + (oldstate->crtc_y == state->crtc_y) && + (oldstate->crtc_w == state->crtc_w) && + (oldstate->crtc_h == state->crtc_h) && + (oldstate->src_x == state->src_x) && + (oldstate->src_y == state->src_y) && + (oldstate->src_w == state->src_w) && + (oldstate->src_h == state->src_h)) { + /* No change since last update, do not post cmd */ + DRM_DEBUG_DRIVER("No change, not posting cmd\n"); + plane->status = STI_PLANE_UPDATED; + return; + } + if (!gdp->vtg) { struct sti_compositor *compo = dev_get_drvdata(gdp->dev); struct sti_mixer *mixer = to_sti_mixer(crtc); From b7e05db3d1ff1adf45e2c028ea331e3a999fb56b Mon Sep 17 00:00:00 2001 From: Vincent Abriou Date: Thu, 2 Feb 2017 09:51:43 +0100 Subject: [PATCH 09/11] drm/sti: unbind all components while driver cleanup Unbind all the components when the STI driver is unregistered. Signed-off-by: Vincent Abriou --- drivers/gpu/drm/sti/sti_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 9e4d96f7dd1c..7cdccb05ee80 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -255,6 +255,7 @@ static void sti_cleanup(struct drm_device *ddev) drm_kms_helper_poll_fini(ddev); drm_vblank_cleanup(ddev); + component_unbind_all(ddev->dev, ddev); kfree(private); ddev->dev_private = NULL; } From 97d7c576302979831c65a2ae8a0ef4f3acf7f107 Mon Sep 17 00:00:00 2001 From: Vincent Abriou Date: Thu, 2 Feb 2017 09:45:48 +0100 Subject: [PATCH 10/11] drm/sti: hdmi: automatically check DVI/HDMI mode Remove the hdmi_mode_property and use drm_detect_hdmi_monitor function to check whether the connected monitor is HDMI capable or DVI only. Signed-off-by: Vincent Abriou --- drivers/gpu/drm/sti/sti_hdmi.c | 31 ++++++------------------------- drivers/gpu/drm/sti/sti_hdmi.h | 17 ++--------------- 2 files changed, 8 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index 6862d5911c18..ce2dcba679d5 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -158,7 +158,6 @@ struct sti_hdmi_connector { struct drm_encoder *encoder; struct sti_hdmi *hdmi; struct drm_property *colorspace_property; - struct drm_property *hdmi_mode_property; }; #define to_sti_hdmi_connector(x) \ @@ -265,7 +264,7 @@ static void hdmi_config(struct sti_hdmi *hdmi) /* Select encryption type and the framing mode */ conf |= HDMI_CFG_ESS_NOT_OESS; - if (hdmi->hdmi_mode == HDMI_MODE_HDMI) + if (hdmi->hdmi_monitor) conf |= HDMI_CFG_HDMI_NOT_DVI; /* Set Hsync polarity */ @@ -970,6 +969,11 @@ static int sti_hdmi_connector_get_modes(struct drm_connector *connector) if (!edid) goto fail; + hdmi->hdmi_monitor = drm_detect_hdmi_monitor(edid); + DRM_DEBUG_KMS("%s : %dx%d cm\n", + (hdmi->hdmi_monitor ? "hdmi monitor" : "dvi monitor"), + edid->width_cm, edid->height_cm); + count = drm_add_edid_modes(connector, edid); drm_mode_connector_update_edid_property(connector, edid); drm_edid_to_eld(connector, edid); @@ -1053,19 +1057,6 @@ static void sti_hdmi_connector_init_property(struct drm_device *drm_dev, } hdmi_connector->colorspace_property = prop; drm_object_attach_property(&connector->base, prop, hdmi->colorspace); - - /* hdmi_mode property */ - hdmi->hdmi_mode = DEFAULT_HDMI_MODE; - prop = drm_property_create_enum(drm_dev, 0, "hdmi_mode", - hdmi_mode_names, - ARRAY_SIZE(hdmi_mode_names)); - if (!prop) { - DRM_ERROR("fails to create colorspace property\n"); - return; - } - hdmi_connector->hdmi_mode_property = prop; - drm_object_attach_property(&connector->base, prop, hdmi->hdmi_mode); - } static int @@ -1083,11 +1074,6 @@ sti_hdmi_connector_set_property(struct drm_connector *connector, return 0; } - if (property == hdmi_connector->hdmi_mode_property) { - hdmi->hdmi_mode = val; - return 0; - } - DRM_ERROR("failed to set hdmi connector property\n"); return -EINVAL; } @@ -1107,11 +1093,6 @@ sti_hdmi_connector_get_property(struct drm_connector *connector, return 0; } - if (property == hdmi_connector->hdmi_mode_property) { - *val = hdmi->hdmi_mode; - return 0; - } - DRM_ERROR("failed to get hdmi connector property\n"); return -EINVAL; } diff --git a/drivers/gpu/drm/sti/sti_hdmi.h b/drivers/gpu/drm/sti/sti_hdmi.h index 119bc3582ac7..407012350f1a 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.h +++ b/drivers/gpu/drm/sti/sti_hdmi.h @@ -30,19 +30,6 @@ struct hdmi_audio_params { struct hdmi_audio_infoframe cea; }; -/* values for the framing mode property */ -enum sti_hdmi_modes { - HDMI_MODE_HDMI, - HDMI_MODE_DVI, -}; - -static const struct drm_prop_enum_list hdmi_mode_names[] = { - { HDMI_MODE_HDMI, "hdmi" }, - { HDMI_MODE_DVI, "dvi" }, -}; - -#define DEFAULT_HDMI_MODE HDMI_MODE_HDMI - static const struct drm_prop_enum_list colorspace_mode_names[] = { { HDMI_COLORSPACE_RGB, "rgb" }, { HDMI_COLORSPACE_YUV422, "yuv422" }, @@ -73,7 +60,7 @@ static const struct drm_prop_enum_list colorspace_mode_names[] = { * @reset: reset control of the hdmi phy * @ddc_adapt: i2c ddc adapter * @colorspace: current colorspace selected - * @hdmi_mode: select framing for HDMI or DVI + * @hdmi_monitor: true if HDMI monitor detected else DVI monitor assumed * @audio_pdev: ASoC hdmi-codec platform device * @audio: hdmi audio parameters. * @drm_connector: hdmi connector @@ -98,7 +85,7 @@ struct sti_hdmi { struct reset_control *reset; struct i2c_adapter *ddc_adapt; enum hdmi_colorspace colorspace; - enum sti_hdmi_modes hdmi_mode; + bool hdmi_monitor; struct platform_device *audio_pdev; struct hdmi_audio_params audio; struct drm_connector *drm_connector; From c462c2f5f5ee5ed77a790c361e6aae807ef923ce Mon Sep 17 00:00:00 2001 From: Vincent Abriou Date: Thu, 2 Feb 2017 09:58:39 +0100 Subject: [PATCH 11/11] drm/sti: debug fps reset Reset the fps debug information when 'fps_show' is updated. Signed-off-by: Fabien Dessenne --- drivers/gpu/drm/sti/sti_drv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 7cdccb05ee80..e6c1646b9c53 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -58,7 +58,9 @@ static int sti_drm_fps_set(void *data, u64 val) list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) { struct sti_plane *plane = to_sti_plane(p); + memset(&plane->fps_info, 0, sizeof(plane->fps_info)); plane->fps_info.output = (val >> i) & 1; + i++; }