diff options
author | Liviu Dudau <Liviu.Dudau@arm.com> | 2018-07-23 07:05:53 -0400 |
---|---|---|
committer | Liviu Dudau <Liviu.Dudau@arm.com> | 2018-07-31 11:31:50 -0400 |
commit | d664b851eb2bcdf84a3c063cf59457bb15bc6120 (patch) | |
tree | af8a44c9ef7edb2205f7d9d51aef14ff2fce456a | |
parent | 9fd466f54f89fc3a2dc6f86fce2ea0b993ff83bd (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.c | 23 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/hdlcd_drv.c | 13 |
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 = { | |||
229 | static int hdlcd_plane_atomic_check(struct drm_plane *plane, | 229 | static 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 | ||
257 | static void hdlcd_plane_atomic_update(struct drm_plane *plane, | 256 | static 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: | |||
325 | err_vblank: | 325 | err_vblank: |
326 | pm_runtime_disable(drm->dev); | 326 | pm_runtime_disable(drm->dev); |
327 | err_pm_active: | 327 | err_pm_active: |
328 | drm_atomic_helper_shutdown(drm); | ||
328 | component_unbind_all(dev, drm); | 329 | component_unbind_all(dev, drm); |
329 | err_unload: | 330 | err_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 | ||
365 | static const struct component_master_ops hdlcd_master_ops = { | 368 | static const struct component_master_ops hdlcd_master_ops = { |