aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiviu Dudau <Liviu.Dudau@arm.com>2018-07-23 07:05:53 -0400
committerLiviu Dudau <Liviu.Dudau@arm.com>2018-07-31 11:31:50 -0400
commitd664b851eb2bcdf84a3c063cf59457bb15bc6120 (patch)
treeaf8a44c9ef7edb2205f7d9d51aef14ff2fce456a
parent9fd466f54f89fc3a2dc6f86fce2ea0b993ff83bd (diff)
drm/arm/hdlcd: Reject atomic commits that disable only the plane
The HDLCD engine needs an active plane while the CRTC is active, as it will start scanning out data from HDLCD_REG_FB_BASE once it gets enabled. Make sure that the only available plane doesn't get disabled while the CRTC remains active, as this will scanout invalid data. Signed-off-by: Liviu Dudau <liviu.dudau@arm.com>
-rw-r--r--drivers/gpu/drm/arm/hdlcd_crtc.c23
-rw-r--r--drivers/gpu/drm/arm/hdlcd_drv.c13
2 files changed, 19 insertions, 17 deletions
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index 8978d82159e5..e4d67b70244d 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -229,6 +229,8 @@ static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = {
229static int hdlcd_plane_atomic_check(struct drm_plane *plane, 229static int hdlcd_plane_atomic_check(struct drm_plane *plane,
230 struct drm_plane_state *state) 230 struct drm_plane_state *state)
231{ 231{
232 int i;
233 struct drm_crtc *crtc;
232 struct drm_crtc_state *crtc_state; 234 struct drm_crtc_state *crtc_state;
233 u32 src_h = state->src_h >> 16; 235 u32 src_h = state->src_h >> 16;
234 236
@@ -238,20 +240,17 @@ static int hdlcd_plane_atomic_check(struct drm_plane *plane,
238 return -EINVAL; 240 return -EINVAL;
239 } 241 }
240 242
241 if (!state->fb || !state->crtc) 243 for_each_new_crtc_in_state(state->state, crtc, crtc_state, i) {
242 return 0; 244 /* we cannot disable the plane while the CRTC is active */
243 245 if (!state->fb && crtc_state->active)
244 crtc_state = drm_atomic_get_existing_crtc_state(state->state, 246 return -EINVAL;
245 state->crtc); 247 return drm_atomic_helper_check_plane_state(state, crtc_state,
246 if (!crtc_state) { 248 DRM_PLANE_HELPER_NO_SCALING,
247 DRM_DEBUG_KMS("Invalid crtc state\n"); 249 DRM_PLANE_HELPER_NO_SCALING,
248 return -EINVAL; 250 false, true);
249 } 251 }
250 252
251 return drm_atomic_helper_check_plane_state(state, crtc_state, 253 return 0;
252 DRM_PLANE_HELPER_NO_SCALING,
253 DRM_PLANE_HELPER_NO_SCALING,
254 false, true);
255} 254}
256 255
257static void hdlcd_plane_atomic_update(struct drm_plane *plane, 256static void hdlcd_plane_atomic_update(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index 70fca288313a..0ed1cde98cf8 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -325,6 +325,7 @@ err_fbdev:
325err_vblank: 325err_vblank:
326 pm_runtime_disable(drm->dev); 326 pm_runtime_disable(drm->dev);
327err_pm_active: 327err_pm_active:
328 drm_atomic_helper_shutdown(drm);
328 component_unbind_all(dev, drm); 329 component_unbind_all(dev, drm);
329err_unload: 330err_unload:
330 of_node_put(hdlcd->crtc.port); 331 of_node_put(hdlcd->crtc.port);
@@ -350,16 +351,18 @@ static void hdlcd_drm_unbind(struct device *dev)
350 component_unbind_all(dev, drm); 351 component_unbind_all(dev, drm);
351 of_node_put(hdlcd->crtc.port); 352 of_node_put(hdlcd->crtc.port);
352 hdlcd->crtc.port = NULL; 353 hdlcd->crtc.port = NULL;
353 pm_runtime_get_sync(drm->dev); 354 pm_runtime_get_sync(dev);
355 drm_crtc_vblank_off(&hdlcd->crtc);
354 drm_irq_uninstall(drm); 356 drm_irq_uninstall(drm);
355 pm_runtime_put_sync(drm->dev);
356 pm_runtime_disable(drm->dev);
357 of_reserved_mem_device_release(drm->dev);
358 drm_atomic_helper_shutdown(drm); 357 drm_atomic_helper_shutdown(drm);
358 pm_runtime_put(dev);
359 if (pm_runtime_enabled(dev))
360 pm_runtime_disable(dev);
361 of_reserved_mem_device_release(dev);
359 drm_mode_config_cleanup(drm); 362 drm_mode_config_cleanup(drm);
360 drm_dev_put(drm);
361 drm->dev_private = NULL; 363 drm->dev_private = NULL;
362 dev_set_drvdata(dev, NULL); 364 dev_set_drvdata(dev, NULL);
365 drm_dev_put(drm);
363} 366}
364 367
365static const struct component_master_ops hdlcd_master_ops = { 368static const struct component_master_ops hdlcd_master_ops = {