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