[PATCH 3/3] drm/tiny: ssd16xx: reject rotation changes without a matching mode

LiangCheng Wang <[email protected]>
Newsgroups org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Portrait orientations are implemented by packing the framebuffer
column-major into the same physical RAM layout, so they need the
transposed mode that ssd16xx_connector_get_modes() reports, and a
framebuffer to match.

Setting the rotation property to 90 or 270 on its own provides neither:
the client keeps the mode and framebuffer it had while the driver switches
to portrait packing, and the result is displayed as garbage.  Nothing
reports an error, and data_size is identical either way so no size check
catches it.

Reject the combination in the CRTC atomic check, so userspace gets -EINVAL
and can re-probe and do a full modeset instead.  Rotation set through the
DT "rotation" property is unaffected, since probe() swaps the mode
dimensions before the connector is registered.

Tested on a Mayqueen PIXPAPER 4.26m (SSD1677, 800x480): rotation 90 at
runtime now fails with -EINVAL instead of corrupting the display, 180 still
applies, and DT rotation = <90> still comes up as 480x800.

Signed-off-by: LiangCheng Wang <[email protected]>
---
 drivers/gpu/drm/tiny/ssd16xx.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/drivers/gpu/drm/tiny/ssd16xx.c b/drivers/gpu/drm/tiny/ssd16xx.c
index d311720bbfbe0dd288dbd588be02c79b5eab3eab..1224a3d4ce2cbe70406dfa6e550fc85a2ea62682 100644
--- a/drivers/gpu/drm/tiny/ssd16xx.c
+++ b/drivers/gpu/drm/tiny/ssd16xx.c
@@ -1730,6 +1730,40 @@ static enum drm_mode_status ssd16xx_crtc_mode_valid(struct drm_crtc *crtc,
 static int ssd16xx_crtc_atomic_check(struct drm_crtc *crtc,
 				     struct drm_atomic_commit *state)
 {
+	struct ssd16xx_device *device = crtc_to_ssd16xx_device(crtc);
+	struct drm_crtc_state *new_crtc_state =
+		drm_atomic_get_new_crtc_state(state, crtc);
+	struct drm_connector_state *new_conn_state;
+	unsigned int orientation;
+	bool want_portrait, mode_is_portrait;
+
+	if (!new_crtc_state->enable)
+		return 0;
+
+	new_conn_state = drm_atomic_get_new_connector_state(state,
+							    &device->connector);
+	if (!new_conn_state)
+		return 0;
+
+	/*
+	 * Portrait packing needs the transposed mode that
+	 * ssd16xx_connector_get_modes() reports; without it the client keeps a
+	 * framebuffer that would be packed with the wrong geometry.
+	 */
+	orientation = to_ssd16xx_connector_state(new_conn_state)->orientation;
+	want_portrait = (orientation == 90 || orientation == 270);
+	mode_is_portrait = new_crtc_state->mode.hdisplay <
+			   new_crtc_state->mode.vdisplay;
+
+	if (want_portrait != mode_is_portrait) {
+		drm_dbg(&device->drm,
+			"atomic_check: %u° orientation needs a %s mode, but %ux%u is set\n",
+			orientation, want_portrait ? "portrait" : "landscape",
+			new_crtc_state->mode.hdisplay,
+			new_crtc_state->mode.vdisplay);
+		return -EINVAL;
+	}
+
 	return 0;
 }
 

-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.