[PATCH 25/25] drm/armada: add iturbt_709 plane property to control YUV colorspace

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add the defacto-standard "iturbt_709" property to the overlay plane to
control the YUV to RGB colorspace conversion.  This is mutually
exclusive with the CSC_YUV CRTC property - the last property to be set
determines the resulting colorspace conversion.

Signed-off-by: Russell King <rmk+kernel@xxxxxxxxxxxxxxx>
---
 drivers/gpu/drm/armada/armada_crtc.c    | 26 +++++++++++++++++++++++---
 drivers/gpu/drm/armada/armada_crtc.h    |  2 ++
 drivers/gpu/drm/armada/armada_drm.h     |  1 +
 drivers/gpu/drm/armada/armada_overlay.c | 25 ++++++++++++++++++++++---
 4 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 8b66377a4890..1bf632bb8855 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -535,12 +535,30 @@ static irqreturn_t armada_drm_irq(int irq, void *arg)
 	return IRQ_NONE;
 }
 
+void armada_drm_crtc_set_yuv_colorimetry(struct armada_crtc *dcrtc, u32 csc)
+{
+	armada_updatel(csc, CFG_CSC_YUV_CCIR709,
+		       dcrtc->base + LCD_SPU_IOPAD_CONTROL);
+
+	dcrtc->csc_yuv_ovl_mode = csc == CFG_CSC_YUV_CCIR709 ?
+				CSC_YUV_CCIR709 : CSC_YUV_CCIR601;
+}
+
 static uint32_t armada_drm_crtc_calculate_csc(struct armada_crtc *dcrtc)
 {
 	struct drm_display_mode *adj = &dcrtc->crtc.mode;
-	uint32_t val = 0;
+	u32 val = 0;
+	u8 csc_yuv_mode;
+
+	/*
+	 * If the iturbt_709 overlay plane property is used, it overrides
+	 * the CSC_YUV crtc property until the CSC_YUV property is set.
+	 */
+	csc_yuv_mode = dcrtc->csc_yuv_ovl_mode;
+	if (csc_yuv_mode == CSC_AUTO)
+		csc_yuv_mode = dcrtc->csc_yuv_mode;
 
-	if (dcrtc->csc_yuv_mode == CSC_YUV_CCIR709)
+	if (csc_yuv_mode == CSC_YUV_CCIR709)
 		val |= CFG_CSC_YUV_CCIR709;
 	if (dcrtc->csc_rgb_mode == CSC_RGB_STUDIO)
 		val |= CFG_CSC_RGB_STUDIO;
@@ -555,7 +573,7 @@ static uint32_t armada_drm_crtc_calculate_csc(struct armada_crtc *dcrtc)
 	if ((adj->hdisplay == 1280 && adj->vdisplay == 720 &&
 	     !(adj->flags & DRM_MODE_FLAG_INTERLACE)) ||
 	    (adj->hdisplay == 1920 && adj->vdisplay == 1080)) {
-		if (dcrtc->csc_yuv_mode == CSC_AUTO)
+		if (csc_yuv_mode == CSC_AUTO)
 			val |= CFG_CSC_YUV_CCIR709;
 	}
 
@@ -1094,6 +1112,7 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc,
 
 	if (property == priv->csc_yuv_prop) {
 		dcrtc->csc_yuv_mode = val;
+		dcrtc->csc_yuv_ovl_mode = CSC_AUTO;
 		update_csc = true;
 	} else if (property == priv->csc_rgb_prop) {
 		dcrtc->csc_rgb_mode = val;
@@ -1396,6 +1415,7 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
 	dcrtc->num = drm->mode_config.num_crtc;
 	dcrtc->clk = ERR_PTR(-EINVAL);
 	dcrtc->csc_yuv_mode = CSC_AUTO;
+	dcrtc->csc_yuv_ovl_mode = CSC_AUTO;
 	dcrtc->csc_rgb_mode = CSC_AUTO;
 	dcrtc->cfg_dumb_ctrl = DUMB24_RGB888_0;
 	dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24;
diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h
index 445829b8877a..5d70b4af20b7 100644
--- a/drivers/gpu/drm/armada/armada_crtc.h
+++ b/drivers/gpu/drm/armada/armada_crtc.h
@@ -90,6 +90,7 @@ struct armada_crtc {
 	bool			interlaced;
 	bool			cursor_update;
 	uint8_t			csc_yuv_mode;
+	uint8_t			csc_yuv_ovl_mode;
 	uint8_t			csc_rgb_mode;
 
 	struct drm_plane	*plane;
@@ -113,6 +114,7 @@ struct armada_crtc {
 #define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc)
 
 void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *);
+void armada_drm_crtc_set_yuv_colorimetry(struct armada_crtc *dcrtc, u32 csc);
 
 int armada_drm_plane_disable(struct drm_plane *plane,
 			     struct drm_modeset_acquire_ctx *ctx);
diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
index b064879ecdbd..45d5168d5748 100644
--- a/drivers/gpu/drm/armada/armada_drm.h
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -60,6 +60,7 @@ struct armada_private {
 	struct armada_crtc	*dcrtc[2];
 	struct drm_mm		linear; /* protected by linear_lock */
 	struct mutex		linear_lock;
+	struct drm_property	*iturbt709_prop;
 	struct drm_property	*csc_yuv_prop;
 	struct drm_property	*csc_rgb_prop;
 	struct drm_property	*colorkey_prop;
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index 853f889e84f5..d7a9c79f0ada 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -28,6 +28,8 @@ struct armada_ovl_plane_properties {
 	uint16_t contrast;
 	uint16_t saturation;
 	uint32_t colorkey_mode;
+	uint32_t csc;
+	bool csc_set;
 };
 
 struct armada_ovl_plane {
@@ -252,6 +254,10 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
 	if (!dcrtc->plane) {
 		dcrtc->plane = plane;
 		armada_ovl_update_attr(&dplane->prop, dcrtc);
+		if (dplane->prop.csc_set) {
+			armada_drm_crtc_set_yuv_colorimetry(dcrtc, dplane->prop.csc);
+			dplane->prop.csc_set = false;
+		}
 	}
 
 	/* Queue it for update on the next interrupt if we are enabled */
@@ -332,11 +338,21 @@ static int armada_ovl_plane_set_property(struct drm_plane *plane,
 	} else if (property == priv->saturation_prop) {
 		dplane->prop.saturation = val;
 		update_attr = true;
+	} else if (property == priv->iturbt709_prop) {
+		dplane->prop.csc = val ? CFG_CSC_YUV_CCIR709 :
+					 CFG_CSC_YUV_CCIR601;
+		dplane->prop.csc_set = true;
 	}
 
-	if (update_attr && dplane->base.base.crtc)
-		armada_ovl_update_attr(&dplane->prop,
-				       drm_to_armada_crtc(dplane->base.base.crtc));
+	if (plane->crtc) {
+		struct armada_crtc *dcrtc = drm_to_armada_crtc(plane->crtc);
+		if (update_attr)
+			armada_ovl_update_attr(&dplane->prop, dcrtc);
+		if (dplane->prop.csc_set) {
+			armada_drm_crtc_set_yuv_colorimetry(dcrtc, dplane->prop.csc);
+			dplane->prop.csc_set = false;
+		}
+	}
 
 	return 0;
 }
@@ -407,6 +423,8 @@ static int armada_overlay_create_properties(struct drm_device *dev)
 				"contrast", 0, 0x7fff);
 	priv->saturation_prop = drm_property_create_range(dev, 0,
 				"saturation", 0, 0x7fff);
+	priv->iturbt709_prop = drm_property_create_bool(dev, 0,
+				"iturbt_709");
 
 	if (!priv->colorkey_prop)
 		return -ENOMEM;
@@ -475,6 +493,7 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
 				   dplane->prop.contrast);
 	drm_object_attach_property(mobj, priv->saturation_prop,
 				   dplane->prop.saturation);
+	drm_object_attach_property(mobj, priv->iturbt709_prop, false);
 
 	return 0;
 }
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/dri-devel




[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux