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>
This commit is contained in:
parent
9fd466f54f
commit
d664b851eb
|
@ -229,6 +229,8 @@ static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = {
|
|||
static int hdlcd_plane_atomic_check(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
int i;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
u32 src_h = state->src_h >> 16;
|
||||
|
||||
|
@ -238,20 +240,17 @@ static int hdlcd_plane_atomic_check(struct drm_plane *plane,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!state->fb || !state->crtc)
|
||||
return 0;
|
||||
|
||||
crtc_state = drm_atomic_get_existing_crtc_state(state->state,
|
||||
state->crtc);
|
||||
if (!crtc_state) {
|
||||
DRM_DEBUG_KMS("Invalid crtc state\n");
|
||||
return -EINVAL;
|
||||
for_each_new_crtc_in_state(state->state, crtc, crtc_state, i) {
|
||||
/* we cannot disable the plane while the CRTC is active */
|
||||
if (!state->fb && crtc_state->active)
|
||||
return -EINVAL;
|
||||
return drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
false, true);
|
||||
}
|
||||
|
||||
return drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
false, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hdlcd_plane_atomic_update(struct drm_plane *plane,
|
||||
|
|
|
@ -325,6 +325,7 @@ static int hdlcd_drm_bind(struct device *dev)
|
|||
err_vblank:
|
||||
pm_runtime_disable(drm->dev);
|
||||
err_pm_active:
|
||||
drm_atomic_helper_shutdown(drm);
|
||||
component_unbind_all(dev, drm);
|
||||
err_unload:
|
||||
of_node_put(hdlcd->crtc.port);
|
||||
|
@ -350,16 +351,18 @@ static void hdlcd_drm_unbind(struct device *dev)
|
|||
component_unbind_all(dev, drm);
|
||||
of_node_put(hdlcd->crtc.port);
|
||||
hdlcd->crtc.port = NULL;
|
||||
pm_runtime_get_sync(drm->dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
drm_crtc_vblank_off(&hdlcd->crtc);
|
||||
drm_irq_uninstall(drm);
|
||||
pm_runtime_put_sync(drm->dev);
|
||||
pm_runtime_disable(drm->dev);
|
||||
of_reserved_mem_device_release(drm->dev);
|
||||
drm_atomic_helper_shutdown(drm);
|
||||
pm_runtime_put(dev);
|
||||
if (pm_runtime_enabled(dev))
|
||||
pm_runtime_disable(dev);
|
||||
of_reserved_mem_device_release(dev);
|
||||
drm_mode_config_cleanup(drm);
|
||||
drm_dev_put(drm);
|
||||
drm->dev_private = NULL;
|
||||
dev_set_drvdata(dev, NULL);
|
||||
drm_dev_put(drm);
|
||||
}
|
||||
|
||||
static const struct component_master_ops hdlcd_master_ops = {
|
||||
|
|
Loading…
Reference in New Issue