From c5d3a57a17df27eb5b360966072d5440b3d792f0 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Wed, 14 Aug 2024 16:41:07 +0100
Subject: [PATCH] drm/vc4: txp: Add a rotation property to the writeback
 connector

The txp block can implement transpose as it writes out the image
data, so expose that through the new connector rotation property.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
 drivers/gpu/drm/vc4/vc4_txp.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -15,6 +15,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_blend.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_fb_dma_helper.h>
@@ -259,10 +260,15 @@ static int vc4_txp_connector_atomic_chec
 	crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
 
 	fb = conn_state->writeback_job->fb;
-	if (fb->width != crtc_state->mode.hdisplay ||
-	    fb->height != crtc_state->mode.vdisplay) {
-		DRM_DEBUG_KMS("Invalid framebuffer size %ux%u\n",
-			      fb->width, fb->height);
+	if ((conn_state->rotation == DRM_MODE_ROTATE_0 &&
+	     fb->width != crtc_state->mode.hdisplay &&
+	     fb->height != crtc_state->mode.vdisplay) ||
+	    (conn_state->rotation == (DRM_MODE_ROTATE_0 | DRM_MODE_TRANSPOSE) &&
+	     fb->width != crtc_state->mode.vdisplay &&
+	     fb->height != crtc_state->mode.hdisplay)) {
+		DRM_DEBUG_KMS("Invalid framebuffer size %ux%u vs mode %ux%u\n",
+			      fb->width, fb->height,
+			      crtc_state->mode.hdisplay, crtc_state->mode.vdisplay);
 		return -EINVAL;
 	}
 
@@ -330,6 +336,9 @@ static void vc4_txp_connector_atomic_com
 		 */
 		ctrl |= TXP_ALPHA_INVERT;
 
+	if (conn_state->rotation & DRM_MODE_TRANSPOSE)
+		ctrl |= TXP_TRANSPOSE;
+
 	if (!drm_dev_enter(drm, &idx))
 		return;
 
@@ -608,6 +617,10 @@ static int vc4_txp_bind(struct device *d
 	if (ret)
 		return ret;
 
+	drm_connector_create_rotation_property(&txp->connector.base, DRM_MODE_ROTATE_0,
+					       DRM_MODE_ROTATE_0 |
+					       DRM_MODE_TRANSPOSE);
+
 	ret = devm_request_irq(dev, irq, vc4_txp_interrupt, 0,
 			       dev_name(dev), txp);
 	if (ret)
