Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d664b851 authored by Liviu Dudau's avatar Liviu Dudau
Browse files

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: default avatarLiviu Dudau <liviu.dudau@arm.com>
parent 9fd466f5
Loading
Loading
Loading
Loading
+11 −12
Original line number Diff line number Diff line
@@ -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,22 +240,19 @@ 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");
	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 0;
}

static void hdlcd_plane_atomic_update(struct drm_plane *plane,
				      struct drm_plane_state *state)
{
+8 −5
Original line number Diff line number Diff line
@@ -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 = {