All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/4] More DRM object properties on Tegra
@ 2018-04-16 12:16 Dmitry Osipenko
  2018-04-16 12:16 ` [PATCH v1 1/4] drm/tegra: plane: Implement zPos plane property for older Tegra's Dmitry Osipenko
                   ` (3 more replies)
  0 siblings, 4 replies; 15+ messages in thread
From: Dmitry Osipenko @ 2018-04-16 12:16 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra, linux-kernel

This patchset adds new custom plane / CRTC properties that are very useful
for displaying video overlay, they will be used by Opentegra Xorg driver.
Also generic zPos property is implemented for older Tegra's.

Dmitry Osipenko (4):
  drm/tegra: plane: Implement zPos plane property for older Tegra's
  drm/tegra: dc: Rename supports_blending to legacy_blending
  drm/tegra: plane: Add custom colorkey properties for older Tegra's
  drm/tegra: plane: Add custom CSC BLOB property

 drivers/gpu/drm/tegra/dc.c    | 402 +++++++++++++++++++++++++++++-----
 drivers/gpu/drm/tegra/dc.h    |  31 ++-
 drivers/gpu/drm/tegra/plane.c | 268 ++++++++++++++++++-----
 drivers/gpu/drm/tegra/plane.h |  27 ++-
 include/uapi/drm/tegra_drm.h  |  11 +
 5 files changed, 623 insertions(+), 116 deletions(-)

-- 
2.17.0

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v1 1/4] drm/tegra: plane: Implement zPos plane property for older Tegra's
  2018-04-16 12:16 [PATCH v1 0/4] More DRM object properties on Tegra Dmitry Osipenko
@ 2018-04-16 12:16 ` Dmitry Osipenko
  2018-04-16 12:16 ` [PATCH v1 2/4] drm/tegra: dc: Rename supports_blending to legacy_blending Dmitry Osipenko
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 15+ messages in thread
From: Dmitry Osipenko @ 2018-04-16 12:16 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra, linux-kernel

Older Tegra's do not support planes z position handling in hardware,
but HW provides knobs for zPos implementation in software.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/gpu/drm/tegra/dc.c    | 134 ++++++++++++++++-------
 drivers/gpu/drm/tegra/plane.c | 193 ++++++++++++++++++++++++----------
 drivers/gpu/drm/tegra/plane.h |  13 ++-
 3 files changed, 244 insertions(+), 96 deletions(-)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 9d885d63724d..a2bf216d8854 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -162,29 +162,90 @@ static void tegra_plane_setup_blending_legacy(struct tegra_plane *plane)
 	u32 foreground = BLEND_WEIGHT1(255) | BLEND_WEIGHT0(255) |
 			 BLEND_COLOR_KEY_NONE;
 	u32 blendnokey = BLEND_WEIGHT1(255) | BLEND_WEIGHT0(255);
+	u32 blending[2];
 	struct tegra_plane_state *state;
 	unsigned int i;
 
+	/* disable blending for non-overlapping case */
+	tegra_plane_writel(plane, blendnokey, DC_WIN_BLEND_NOKEY);
+	tegra_plane_writel(plane, foreground, DC_WIN_BLEND_1WIN);
+
 	state = to_tegra_plane_state(plane->base.state);
 
-	/* alpha contribution is 1 minus sum of overlapping windows */
-	for (i = 0; i < 3; i++) {
-		if (state->dependent[i])
-			background[i] |= BLEND_CONTROL_DEPENDENT;
-	}
+	if (state->opaque) {
+		/*
+		 * Since custom fix-weight blending isn't utilized and weight
+		 * of top window is set to max, we can enforce dependent
+		 * blending which in this case results in transparent bottom
+		 * window if top window is opaque and if top window enables
+		 * alpha blending, then bottom window is getting alpha value
+		 * of 1 minus the sum of alpha components of the overlapping
+		 * plane.
+		 */
+		background[0] |= BLEND_CONTROL_DEPENDENT;
+		background[1] |= BLEND_CONTROL_DEPENDENT;
 
-	/* enable alpha blending if pixel format has an alpha component */
-	if (!state->opaque)
+		/*
+		 * The region where three windows overlap is the intersection
+		 * of the two regions where two windows overlap. It contributes
+		 * to the area if all of the windows on top of it have an alpha
+		 * component.
+		 */
+		switch (state->base.normalized_zpos) {
+		case 0:
+			if (state->blending[0].alpha &&
+			    state->blending[1].alpha)
+				background[2] |= BLEND_CONTROL_DEPENDENT;
+			break;
+
+		case 1:
+			background[2] |= BLEND_CONTROL_DEPENDENT;
+			break;
+		}
+	} else {
+		/*
+		 * Enable alpha blending if pixel format has an alpha
+		 * component.
+		 */
 		foreground |= BLEND_CONTROL_ALPHA;
 
-	/*
-	 * Disable blending and assume Window A is the bottom-most window,
-	 * Window C is the top-most window and Window B is in the middle.
-	 */
-	tegra_plane_writel(plane, blendnokey, DC_WIN_BLEND_NOKEY);
-	tegra_plane_writel(plane, foreground, DC_WIN_BLEND_1WIN);
+		/*
+		 * If any of the windows on top of this window is opaque, it
+		 * will completely conceal this window within that area. If
+		 * top window has an alpha component, it is blended over the
+		 * bottom window.
+		 */
+		for (i = 0; i < 2; i++) {
+			if (state->blending[i].alpha &&
+			    state->blending[i].top)
+				background[i] |= BLEND_CONTROL_DEPENDENT;
+		}
+
+		switch (state->base.normalized_zpos) {
+		case 0:
+			if (state->blending[0].alpha &&
+			    state->blending[1].alpha)
+				background[2] |= BLEND_CONTROL_DEPENDENT;
+			break;
+
+		case 1:
+			/*
+			 * When both middle and topmost windows have an alpha,
+			 * these windows a mixed together and then the result
+			 * is blended over the bottom window.
+			 */
+			if ((state->blending[0].alpha &&
+			     state->blending[0].top))
+				background[2] |= BLEND_CONTROL_ALPHA;
 
-	switch (plane->index) {
+			if (state->blending[1].alpha &&
+			    state->blending[1].top)
+				background[2] |= BLEND_CONTROL_ALPHA;
+			break;
+		}
+	}
+
+	switch (state->base.normalized_zpos) {
 	case 0:
 		tegra_plane_writel(plane, background[0], DC_WIN_BLEND_2WIN_X);
 		tegra_plane_writel(plane, background[1], DC_WIN_BLEND_2WIN_Y);
@@ -192,8 +253,21 @@ static void tegra_plane_setup_blending_legacy(struct tegra_plane *plane)
 		break;
 
 	case 1:
-		tegra_plane_writel(plane, foreground, DC_WIN_BLEND_2WIN_X);
-		tegra_plane_writel(plane, background[1], DC_WIN_BLEND_2WIN_Y);
+		/*
+		 * If window B / C is topmost, then X / Y registers are
+		 * matching the order of blending[...] state indices,
+		 * otherwise a swap is required.
+		 */
+		if (!state->blending[0].top && state->blending[1].top) {
+			blending[0] = foreground;
+			blending[1] = background[1];
+		} else {
+			blending[0] = background[0];
+			blending[1] = foreground;
+		}
+
+		tegra_plane_writel(plane, blending[0], DC_WIN_BLEND_2WIN_X);
+		tegra_plane_writel(plane, blending[1], DC_WIN_BLEND_2WIN_Y);
 		tegra_plane_writel(plane, background[2], DC_WIN_BLEND_3WIN_XY);
 		break;
 
@@ -457,14 +531,14 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
 	struct tegra_bo_tiling *tiling = &plane_state->tiling;
 	struct tegra_plane *tegra = to_tegra_plane(plane);
 	struct tegra_dc *dc = to_tegra_dc(state->crtc);
-	unsigned int format;
 	int err;
 
 	/* no need for further checks if the plane is being disabled */
 	if (!state->crtc)
 		return 0;
 
-	err = tegra_plane_format(state->fb->format->format, &format,
+	err = tegra_plane_format(state->fb->format->format,
+				 &plane_state->format,
 				 &plane_state->swap);
 	if (err < 0)
 		return err;
@@ -476,21 +550,11 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
 	 * be emulated by disabling alpha blending for the plane.
 	 */
 	if (!dc->soc->supports_blending) {
-		if (!tegra_plane_format_has_alpha(format)) {
-			err = tegra_plane_format_get_alpha(format, &format);
-			if (err < 0)
-				return err;
-
-			plane_state->opaque = true;
-		} else {
-			plane_state->opaque = false;
-		}
-
-		tegra_plane_check_dependent(tegra, plane_state);
+		err = tegra_plane_setup_legacy_state(tegra, plane_state);
+		if (err < 0)
+			return err;
 	}
 
-	plane_state->format = format;
-
 	err = tegra_fb_get_tiling(state->fb, tiling);
 	if (err < 0)
 		return err;
@@ -698,9 +762,7 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
 	}
 
 	drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
-
-	if (dc->soc->supports_blending)
-		drm_plane_create_zpos_property(&plane->base, 0, 0, 255);
+	drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255);
 
 	return &plane->base;
 }
@@ -979,9 +1041,7 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
 	}
 
 	drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
-
-	if (dc->soc->supports_blending)
-		drm_plane_create_zpos_property(&plane->base, 0, 0, 255);
+	drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255);
 
 	return &plane->base;
 }
diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c
index 176ef46c615c..0406c2ef432c 100644
--- a/drivers/gpu/drm/tegra/plane.c
+++ b/drivers/gpu/drm/tegra/plane.c
@@ -23,6 +23,7 @@ static void tegra_plane_destroy(struct drm_plane *plane)
 
 static void tegra_plane_reset(struct drm_plane *plane)
 {
+	struct tegra_plane *p = to_tegra_plane(plane);
 	struct tegra_plane_state *state;
 
 	if (plane->state)
@@ -35,6 +36,8 @@ static void tegra_plane_reset(struct drm_plane *plane)
 	if (state) {
 		plane->state = &state->base;
 		plane->state->plane = plane;
+		plane->state->zpos = p->index;
+		plane->state->normalized_zpos = p->index;
 	}
 }
 
@@ -55,8 +58,8 @@ tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
 	copy->swap = state->swap;
 	copy->opaque = state->opaque;
 
-	for (i = 0; i < 3; i++)
-		copy->dependent[i] = state->dependent[i];
+	for (i = 0; i < 2; i++)
+		copy->blending[i] = state->blending[i];
 
 	return &copy->base;
 }
@@ -267,24 +270,8 @@ static bool __drm_format_has_alpha(u32 format)
 	return false;
 }
 
-/*
- * This is applicable to Tegra20 and Tegra30 only where the opaque formats can
- * be emulated using the alpha formats and alpha blending disabled.
- */
-bool tegra_plane_format_has_alpha(unsigned int format)
-{
-	switch (format) {
-	case WIN_COLOR_DEPTH_B5G5R5A1:
-	case WIN_COLOR_DEPTH_A1B5G5R5:
-	case WIN_COLOR_DEPTH_R8G8B8A8:
-	case WIN_COLOR_DEPTH_B8G8R8A8:
-		return true;
-	}
-
-	return false;
-}
-
-int tegra_plane_format_get_alpha(unsigned int opaque, unsigned int *alpha)
+static int tegra_plane_format_get_alpha(unsigned int opaque,
+					unsigned int *alpha)
 {
 	if (tegra_plane_format_is_yuv(opaque, NULL)) {
 		*alpha = opaque;
@@ -316,6 +303,67 @@ int tegra_plane_format_get_alpha(unsigned int opaque, unsigned int *alpha)
 	return -EINVAL;
 }
 
+/*
+ * This is applicable to Tegra20 and Tegra30 only where the opaque formats can
+ * be emulated using the alpha formats and alpha blending disabled.
+ */
+static int tegra_plane_setup_opacity(struct tegra_plane *tegra,
+				     struct tegra_plane_state *state)
+{
+	unsigned int format;
+	int err;
+
+	switch (state->format) {
+	case WIN_COLOR_DEPTH_B5G5R5A1:
+	case WIN_COLOR_DEPTH_A1B5G5R5:
+	case WIN_COLOR_DEPTH_R8G8B8A8:
+	case WIN_COLOR_DEPTH_B8G8R8A8:
+		state->opaque = false;
+		break;
+
+	default:
+		err = tegra_plane_format_get_alpha(state->format, &format);
+		if (err < 0)
+			return err;
+
+		state->format = format;
+		state->opaque = true;
+		break;
+	}
+
+	return 0;
+}
+
+static int tegra_plane_check_transparency(struct tegra_plane *tegra,
+					  struct tegra_plane_state *state)
+{
+	struct drm_plane_state *old, *plane_state;
+	struct drm_plane *plane;
+
+	old = drm_atomic_get_old_plane_state(state->base.state, &tegra->base);
+
+	/* check if zpos / transparency changed */
+	if (old->normalized_zpos == state->base.normalized_zpos &&
+	    to_tegra_plane_state(old)->opaque == state->opaque)
+		return 0;
+
+	/* include all sibling planes into this commit */
+	drm_for_each_plane(plane, tegra->base.dev) {
+		struct tegra_plane *p = to_tegra_plane(plane);
+
+		/* skip this plane and planes on different CRTCs */
+		if (p == tegra || p->dc != tegra->dc)
+			continue;
+
+		plane_state = drm_atomic_get_plane_state(state->base.state,
+							 plane);
+		if (IS_ERR(plane_state))
+			return PTR_ERR(plane_state);
+	}
+
+	return 1;
+}
+
 static unsigned int tegra_plane_get_overlap_index(struct tegra_plane *plane,
 						  struct tegra_plane *other)
 {
@@ -336,61 +384,98 @@ static unsigned int tegra_plane_get_overlap_index(struct tegra_plane *plane,
 	return index;
 }
 
-void tegra_plane_check_dependent(struct tegra_plane *tegra,
-				 struct tegra_plane_state *state)
+static void tegra_plane_update_transparency(struct tegra_plane *tegra,
+					    struct tegra_plane_state *state)
 {
-	struct drm_plane_state *old, *new;
+	struct drm_plane_state *new;
 	struct drm_plane *plane;
-	unsigned int zpos[2];
 	unsigned int i;
 
-	for (i = 0; i < 2; i++)
-		zpos[i] = 0;
-
-	for_each_oldnew_plane_in_state(state->base.state, plane, old, new, i) {
+	for_each_new_plane_in_state(state->base.state, plane, new, i) {
 		struct tegra_plane *p = to_tegra_plane(plane);
 		unsigned index;
 
 		/* skip this plane and planes on different CRTCs */
-		if (p == tegra || new->crtc != state->base.crtc)
+		if (p == tegra || p->dc != tegra->dc)
 			continue;
 
 		index = tegra_plane_get_overlap_index(tegra, p);
 
-		state->dependent[index] = false;
+		if (new->fb && __drm_format_has_alpha(new->fb->format->format))
+			state->blending[index].alpha = true;
+		else
+			state->blending[index].alpha = false;
+
+		if (new->normalized_zpos > state->base.normalized_zpos)
+			state->blending[index].top = true;
+		else
+			state->blending[index].top = false;
 
 		/*
-		 * If any of the other planes is on top of this plane and uses
-		 * a format with an alpha component, mark this plane as being
-		 * dependent, meaning it's alpha value will be 1 minus the sum
-		 * of alpha components of the overlapping planes.
+		 * Missing framebuffer means that plane is disabled, in this
+		 * case mark B / C window as top to be able to differentiate
+		 * windows indices order in regards to zPos for the middle
+		 * window X / Y registers programming.
 		 */
-		if (p->index > tegra->index) {
-			if (__drm_format_has_alpha(new->fb->format->format))
-				state->dependent[index] = true;
-
-			/* keep track of the Z position */
-			zpos[index] = p->index;
-		}
+		if (!new->fb)
+			state->blending[index].top = (index == 1);
 	}
+}
+
+static int tegra_plane_setup_transparency(struct tegra_plane *tegra,
+					  struct tegra_plane_state *state)
+{
+	struct tegra_plane_state *tegra_state;
+	struct drm_plane_state *new;
+	struct drm_plane *plane;
+	int err;
 
 	/*
-	 * The region where three windows overlap is the intersection of the
-	 * two regions where two windows overlap. It contributes to the area
-	 * if any of the windows on top of it have an alpha component.
+	 * If planes zpos / transparency changed, sibling planes blending
+	 * state may require adjustment and in this case they will be included
+	 * into this atom commit, otherwise blending state is unchanged.
 	 */
-	for (i = 0; i < 2; i++)
-		state->dependent[2] = state->dependent[2] ||
-				      state->dependent[i];
+	err = tegra_plane_check_transparency(tegra, state);
+	if (err <= 0)
+		return err;
 
 	/*
-	 * However, if any of the windows on top of this window is opaque, it
-	 * will completely conceal this window within that area, so avoid the
-	 * window from contributing to the area.
+	 * All planes are now in the atomic state, walk them up and update
+	 * transparency state for each plane.
 	 */
-	for (i = 0; i < 2; i++) {
-		if (zpos[i] > tegra->index)
-			state->dependent[2] = state->dependent[2] &&
-					      state->dependent[i];
+	drm_for_each_plane(plane, tegra->base.dev) {
+		struct tegra_plane *p = to_tegra_plane(plane);
+
+		/* skip planes on different CRTCs */
+		if (p->dc != tegra->dc)
+			continue;
+
+		new = drm_atomic_get_new_plane_state(state->base.state, plane);
+		tegra_state = to_tegra_plane_state(new);
+
+		/*
+		 * There is no need to update blending state for the disabled
+		 * plane.
+		 */
+		if (new->fb)
+			tegra_plane_update_transparency(p, tegra_state);
 	}
+
+	return 0;
+}
+
+int tegra_plane_setup_legacy_state(struct tegra_plane *tegra,
+				   struct tegra_plane_state *state)
+{
+	int err;
+
+	err = tegra_plane_setup_opacity(tegra, state);
+	if (err < 0)
+		return err;
+
+	err = tegra_plane_setup_transparency(tegra, state);
+	if (err < 0)
+		return err;
+
+	return 0;
 }
diff --git a/drivers/gpu/drm/tegra/plane.h b/drivers/gpu/drm/tegra/plane.h
index 6938719e7e5d..7360ddfafee8 100644
--- a/drivers/gpu/drm/tegra/plane.h
+++ b/drivers/gpu/drm/tegra/plane.h
@@ -34,6 +34,11 @@ static inline struct tegra_plane *to_tegra_plane(struct drm_plane *plane)
 	return container_of(plane, struct tegra_plane, base);
 }
 
+struct tegra_plane_legacy_blending_state {
+	bool alpha;
+	bool top;
+};
+
 struct tegra_plane_state {
 	struct drm_plane_state base;
 
@@ -42,8 +47,8 @@ struct tegra_plane_state {
 	u32 swap;
 
 	/* used for legacy blending support only */
+	struct tegra_plane_legacy_blending_state blending[2];
 	bool opaque;
-	bool dependent[3];
 };
 
 static inline struct tegra_plane_state *
@@ -62,9 +67,7 @@ int tegra_plane_state_add(struct tegra_plane *plane,
 
 int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap);
 bool tegra_plane_format_is_yuv(unsigned int format, bool *planar);
-bool tegra_plane_format_has_alpha(unsigned int format);
-int tegra_plane_format_get_alpha(unsigned int opaque, unsigned int *alpha);
-void tegra_plane_check_dependent(struct tegra_plane *tegra,
-				 struct tegra_plane_state *state);
+int tegra_plane_setup_legacy_state(struct tegra_plane *tegra,
+				   struct tegra_plane_state *state);
 
 #endif /* TEGRA_PLANE_H */
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v1 2/4] drm/tegra: dc: Rename supports_blending to legacy_blending
  2018-04-16 12:16 [PATCH v1 0/4] More DRM object properties on Tegra Dmitry Osipenko
  2018-04-16 12:16 ` [PATCH v1 1/4] drm/tegra: plane: Implement zPos plane property for older Tegra's Dmitry Osipenko
@ 2018-04-16 12:16 ` Dmitry Osipenko
  2018-04-16 12:16 ` [PATCH v1 3/4] drm/tegra: plane: Add custom colorkey properties for older Tegra's Dmitry Osipenko
  2018-04-16 12:16 ` [PATCH v1 4/4] drm/tegra: plane: Add custom CSC BLOB property Dmitry Osipenko
  3 siblings, 0 replies; 15+ messages in thread
From: Dmitry Osipenko @ 2018-04-16 12:16 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra, linux-kernel

Older Tegra's support blending. Rename SoC info entry supports_blending
to legacy_blending to eliminate confusion.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/gpu/drm/tegra/dc.c | 20 ++++++++++----------
 drivers/gpu/drm/tegra/dc.h |  2 +-
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index a2bf216d8854..a54eefea2513 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -440,10 +440,10 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
 
 	tegra_plane_writel(plane, value, DC_WIN_WIN_OPTIONS);
 
-	if (dc->soc->supports_blending)
-		tegra_plane_setup_blending(plane, window);
-	else
+	if (dc->soc->legacy_blending)
 		tegra_plane_setup_blending_legacy(plane);
+	else
+		tegra_plane_setup_blending(plane, window);
 }
 
 static const u32 tegra20_primary_formats[] = {
@@ -549,7 +549,7 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
 	 * the corresponding opaque formats. However, the opaque formats can
 	 * be emulated by disabling alpha blending for the plane.
 	 */
-	if (!dc->soc->supports_blending) {
+	if (dc->soc->legacy_blending) {
 		err = tegra_plane_setup_legacy_state(tegra, plane_state);
 		if (err < 0)
 			return err;
@@ -2092,7 +2092,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
 	.supports_interlacing = false,
 	.supports_cursor = false,
 	.supports_block_linear = false,
-	.supports_blending = false,
+	.legacy_blending = true,
 	.pitch_align = 8,
 	.has_iommu = false,
 	.has_powergate = false,
@@ -2110,7 +2110,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
 	.supports_interlacing = false,
 	.supports_cursor = false,
 	.supports_block_linear = false,
-	.supports_blending = false,
+	.legacy_blending = true,
 	.pitch_align = 8,
 	.has_iommu = true,
 	.has_powergate = false,
@@ -2128,7 +2128,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
 	.supports_interlacing = false,
 	.supports_cursor = false,
 	.supports_block_linear = false,
-	.supports_blending = false,
+	.legacy_blending = true,
 	.pitch_align = 64,
 	.has_iommu = true,
 	.has_powergate = true,
@@ -2146,7 +2146,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
 	.supports_interlacing = true,
 	.supports_cursor = true,
 	.supports_block_linear = true,
-	.supports_blending = true,
+	.legacy_blending = false,
 	.pitch_align = 64,
 	.has_iommu = true,
 	.has_powergate = true,
@@ -2164,7 +2164,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
 	.supports_interlacing = true,
 	.supports_cursor = true,
 	.supports_block_linear = true,
-	.supports_blending = true,
+	.legacy_blending = false,
 	.pitch_align = 64,
 	.has_iommu = true,
 	.has_powergate = true,
@@ -2216,7 +2216,7 @@ static const struct tegra_dc_soc_info tegra186_dc_soc_info = {
 	.supports_interlacing = true,
 	.supports_cursor = true,
 	.supports_block_linear = true,
-	.supports_blending = true,
+	.legacy_blending = false,
 	.pitch_align = 64,
 	.has_powergate = false,
 	.coupled_pm = false,
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index d0bbcbcde4c1..3156006e75c6 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -55,7 +55,7 @@ struct tegra_dc_soc_info {
 	bool supports_interlacing;
 	bool supports_cursor;
 	bool supports_block_linear;
-	bool supports_blending;
+	bool legacy_blending;
 	unsigned int pitch_align;
 	bool has_iommu;
 	bool has_powergate;
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v1 3/4] drm/tegra: plane: Add custom colorkey properties for older Tegra's
  2018-04-16 12:16 [PATCH v1 0/4] More DRM object properties on Tegra Dmitry Osipenko
  2018-04-16 12:16 ` [PATCH v1 1/4] drm/tegra: plane: Implement zPos plane property for older Tegra's Dmitry Osipenko
  2018-04-16 12:16 ` [PATCH v1 2/4] drm/tegra: dc: Rename supports_blending to legacy_blending Dmitry Osipenko
@ 2018-04-16 12:16 ` Dmitry Osipenko
  2018-04-17  9:00     ` Daniel Vetter
  2018-04-16 12:16 ` [PATCH v1 4/4] drm/tegra: plane: Add custom CSC BLOB property Dmitry Osipenko
  3 siblings, 1 reply; 15+ messages in thread
From: Dmitry Osipenko @ 2018-04-16 12:16 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra, linux-kernel

Colorkey'ing allows to draw on top of overlapping planes, like for example
on top of a video plane. Older Tegra's have a limited colorkey'ing
capability such that blending features are reduced when colorkey'ing is
enabled. In particular dependent weighting isn't possible, meaning that
cursors plane can't be displayed properly. In most cases it is more useful
to display content on top of video overlay, sacrificing mouse cursor
in the area of three planes intersection with colorkey mismatch. This
patch adds a custom colorkey properties to primary plane and CRTC's of
older Tegra's, allowing userspace like Opentegra Xorg driver to implement
colorkey support for XVideo extension.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/gpu/drm/tegra/dc.c    | 166 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/tegra/dc.h    |  18 +++-
 drivers/gpu/drm/tegra/plane.c |  40 ++++++++
 drivers/gpu/drm/tegra/plane.h |   9 +-
 4 files changed, 231 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index a54eefea2513..b19e954a223f 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -172,6 +172,24 @@ static void tegra_plane_setup_blending_legacy(struct tegra_plane *plane)
 
 	state = to_tegra_plane_state(plane->base.state);
 
+	/*
+	 * Assuming default zPos window order, enable color keying for cases
+	 * of overlapping with topping windows, excluding overlap with
+	 * window B. Due to limited HW capabilities, this allows to draw
+	 * primary plane on top of video overlay in areas where key isn't
+	 * matching. Though window C will be completely transparent in a
+	 * region of three windows intersection + key mismatch.
+	 */
+	if (state->ckey0_enabled) {
+		background[0] |= BLEND_COLOR_KEY_0;
+		background[2] |= BLEND_COLOR_KEY_0;
+	}
+
+	if (state->ckey1_enabled) {
+		background[0] |= BLEND_COLOR_KEY_1;
+		background[2] |= BLEND_COLOR_KEY_1;
+	}
+
 	if (state->opaque) {
 		/*
 		 * Since custom fix-weight blending isn't utilized and weight
@@ -729,6 +747,35 @@ static unsigned long tegra_plane_get_possible_crtcs(struct drm_device *drm)
 	return 1 << drm->mode_config.num_crtc;
 }
 
+static void tegra_plane_create_legacy_properties(struct tegra_plane *plane,
+						 struct drm_device *drm)
+{
+	plane->props.color_key0 = drm_property_create_bool(
+						drm, 0, "color key 0");
+	plane->props.color_key1 = drm_property_create_bool(
+						drm, 0, "color key 1");
+
+	if (!plane->props.color_key0 ||
+	    !plane->props.color_key1)
+		goto err_cleanup;
+
+	drm_object_attach_property(&plane->base.base, plane->props.color_key0,
+				   false);
+	drm_object_attach_property(&plane->base.base, plane->props.color_key1,
+				   false);
+
+	return;
+
+err_cleanup:
+	if (plane->props.color_key0)
+		drm_property_destroy(drm, plane->props.color_key0);
+
+	if (plane->props.color_key1)
+		drm_property_destroy(drm, plane->props.color_key1);
+
+	dev_err(plane->dc->dev, "failed to create legacy plane properties\n");
+}
+
 static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
 						    struct tegra_dc *dc)
 {
@@ -764,6 +811,9 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
 	drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
 	drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255);
 
+	if (dc->soc->legacy_blending)
+		tegra_plane_create_legacy_properties(plane, drm);
+
 	return &plane->base;
 }
 
@@ -1153,6 +1203,8 @@ tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
 	copy->pclk = state->pclk;
 	copy->div = state->div;
 	copy->planes = state->planes;
+	copy->ckey0 = state->ckey0;
+	copy->ckey1 = state->ckey1;
 
 	return &copy->base;
 }
@@ -1537,6 +1589,50 @@ static void tegra_dc_disable_vblank(struct drm_crtc *crtc)
 	tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
 }
 
+static int tegra_crtc_atomic_set_property(struct drm_crtc *crtc,
+					  struct drm_crtc_state *state,
+					  struct drm_property *property,
+					  uint64_t value)
+{
+	struct tegra_dc_state *tegra_state = to_dc_state(state);
+	struct tegra_dc *dc = to_tegra_dc(crtc);
+
+	if (property == dc->props.ckey0_lower)
+		tegra_state->ckey0.lower = value;
+	else if (property == dc->props.ckey0_upper)
+		tegra_state->ckey0.upper = value;
+	else if (property == dc->props.ckey1_lower)
+		tegra_state->ckey1.lower = value;
+	else if (property == dc->props.ckey1_upper)
+		tegra_state->ckey1.upper = value;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int tegra_crtc_atomic_get_property(struct drm_crtc *crtc,
+					  const struct drm_crtc_state *state,
+					  struct drm_property *property,
+					  uint64_t *value)
+{
+	struct tegra_dc_state *tegra_state = to_dc_state(state);
+	struct tegra_dc *dc = to_tegra_dc(crtc);
+
+	if (property == dc->props.ckey0_lower)
+		*value = tegra_state->ckey0.lower;
+	else if (property == dc->props.ckey0_upper)
+		*value = tegra_state->ckey0.upper;
+	else if (property == dc->props.ckey1_lower)
+		*value = tegra_state->ckey1.lower;
+	else if (property == dc->props.ckey1_upper)
+		*value = tegra_state->ckey1.upper;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
 static const struct drm_crtc_funcs tegra_crtc_funcs = {
 	.page_flip = drm_atomic_helper_page_flip,
 	.set_config = drm_atomic_helper_set_config,
@@ -1549,6 +1645,8 @@ static const struct drm_crtc_funcs tegra_crtc_funcs = {
 	.get_vblank_counter = tegra_dc_get_vblank_counter,
 	.enable_vblank = tegra_dc_enable_vblank,
 	.disable_vblank = tegra_dc_disable_vblank,
+	.atomic_set_property = tegra_crtc_atomic_set_property,
+	.atomic_get_property = tegra_crtc_atomic_get_property,
 };
 
 static int tegra_dc_set_timings(struct tegra_dc *dc,
@@ -1883,6 +1981,18 @@ static void tegra_crtc_atomic_flush(struct drm_crtc *crtc,
 	struct tegra_dc *dc = to_tegra_dc(crtc);
 	u32 value;
 
+	if (dc->soc->legacy_blending) {
+		tegra_dc_writel(dc, state->ckey0.lower,
+				DC_DISP_COLOR_KEY0_LOWER);
+		tegra_dc_writel(dc, state->ckey0.upper,
+				DC_DISP_COLOR_KEY0_UPPER);
+
+		tegra_dc_writel(dc, state->ckey1.lower,
+				DC_DISP_COLOR_KEY1_LOWER);
+		tegra_dc_writel(dc, state->ckey1.upper,
+				DC_DISP_COLOR_KEY1_UPPER);
+	}
+
 	value = state->planes << 8 | GENERAL_UPDATE;
 	tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
 	value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
@@ -1944,6 +2054,56 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+static int tegra_dc_create_legacy_properties(struct tegra_dc *dc,
+					     struct drm_device *drm)
+{
+	/*
+	 * Each color key value is represented in RGB888 format.
+	 * All planes share the same color key values and free to choose
+	 * among the ckey0 and ckey1.
+	 */
+	dc->props.ckey0_lower = drm_property_create_range(
+			drm, 0, "color key 0 lower margin", 0, 0xffffff);
+	dc->props.ckey0_upper = drm_property_create_range(
+			drm, 0, "color key 0 upper margin", 0, 0xffffff);
+	dc->props.ckey1_lower = drm_property_create_range(
+			drm, 0, "color key 1 lower margin", 0, 0xffffff);
+	dc->props.ckey1_upper = drm_property_create_range(
+			drm, 0, "color key 1 upper margin", 0, 0xffffff);
+
+	if (!dc->props.ckey0_lower ||
+	    !dc->props.ckey0_upper ||
+	    !dc->props.ckey1_lower ||
+	    !dc->props.ckey1_upper)
+		goto err_cleanup;
+
+	drm_object_attach_property(&dc->base.base, dc->props.ckey0_lower,
+				   0x000000);
+	drm_object_attach_property(&dc->base.base, dc->props.ckey0_upper,
+				   0x000000);
+	drm_object_attach_property(&dc->base.base, dc->props.ckey1_lower,
+				   0x000000);
+	drm_object_attach_property(&dc->base.base, dc->props.ckey1_upper,
+				   0x000000);
+
+	return 0;
+
+err_cleanup:
+	if (dc->props.ckey0_lower)
+		drm_property_destroy(drm, dc->props.ckey0_lower);
+
+	if (dc->props.ckey0_upper)
+		drm_property_destroy(drm, dc->props.ckey0_upper);
+
+	if (dc->props.ckey1_lower)
+		drm_property_destroy(drm, dc->props.ckey1_lower);
+
+	if (dc->props.ckey1_upper)
+		drm_property_destroy(drm, dc->props.ckey1_upper);
+
+	return -ENOMEM;
+}
+
 static int tegra_dc_init(struct host1x_client *client)
 {
 	struct drm_device *drm = dev_get_drvdata(client->parent);
@@ -2031,6 +2191,12 @@ static int tegra_dc_init(struct host1x_client *client)
 		goto cleanup;
 	}
 
+	if (dc->soc->legacy_blending) {
+		err = tegra_dc_create_legacy_properties(dc, drm);
+		if (err < 0)
+			dev_err(dc->dev, "failed to create CRTC properties\n");
+	}
+
 	return 0;
 
 cleanup:
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 3156006e75c6..3913d047abac 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -18,6 +18,11 @@
 
 struct tegra_output;
 
+struct tegra_dc_color_key_state {
+	u32 lower;
+	u32 upper;
+};
+
 struct tegra_dc_state {
 	struct drm_crtc_state base;
 
@@ -26,9 +31,13 @@ struct tegra_dc_state {
 	unsigned int div;
 
 	u32 planes;
+
+	struct tegra_dc_color_key_state ckey0;
+	struct tegra_dc_color_key_state ckey1;
 };
 
-static inline struct tegra_dc_state *to_dc_state(struct drm_crtc_state *state)
+static inline struct tegra_dc_state *
+to_dc_state(const struct drm_crtc_state *state)
 {
 	if (state)
 		return container_of(state, struct tegra_dc_state, base);
@@ -94,6 +103,13 @@ struct tegra_dc {
 	const struct tegra_dc_soc_info *soc;
 
 	struct iommu_domain *domain;
+
+	struct {
+		struct drm_property *ckey0_lower;
+		struct drm_property *ckey0_upper;
+		struct drm_property *ckey1_lower;
+		struct drm_property *ckey1_upper;
+	} props;
 };
 
 static inline struct tegra_dc *
diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c
index 0406c2ef432c..4d794f2b44df 100644
--- a/drivers/gpu/drm/tegra/plane.c
+++ b/drivers/gpu/drm/tegra/plane.c
@@ -57,6 +57,8 @@ tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
 	copy->format = state->format;
 	copy->swap = state->swap;
 	copy->opaque = state->opaque;
+	copy->ckey0_enabled = state->ckey0_enabled;
+	copy->ckey1_enabled = state->ckey1_enabled;
 
 	for (i = 0; i < 2; i++)
 		copy->blending[i] = state->blending[i];
@@ -86,6 +88,42 @@ static bool tegra_plane_format_mod_supported(struct drm_plane *plane,
 	return false;
 }
 
+static int tegra_plane_set_property(struct drm_plane *plane,
+				    struct drm_plane_state *state,
+				    struct drm_property *property,
+				    uint64_t value)
+{
+	struct tegra_plane_state *tegra_state = to_tegra_plane_state(state);
+	struct tegra_plane *tegra = to_tegra_plane(plane);
+
+	if (property == tegra->props.color_key0)
+		tegra_state->ckey0_enabled = value;
+	else if (property == tegra->props.color_key1)
+		tegra_state->ckey1_enabled = value;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int tegra_plane_get_property(struct drm_plane *plane,
+				    const struct drm_plane_state *state,
+				    struct drm_property *property,
+				    uint64_t *value)
+{
+	struct tegra_plane_state *tegra_state = to_tegra_plane_state(state);
+	struct tegra_plane *tegra = to_tegra_plane(plane);
+
+	if (property == tegra->props.color_key0)
+		*value = tegra_state->ckey0_enabled;
+	else if (property == tegra->props.color_key1)
+		*value = tegra_state->ckey1_enabled;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
 const struct drm_plane_funcs tegra_plane_funcs = {
 	.update_plane = drm_atomic_helper_update_plane,
 	.disable_plane = drm_atomic_helper_disable_plane,
@@ -94,6 +132,8 @@ const struct drm_plane_funcs tegra_plane_funcs = {
 	.atomic_duplicate_state = tegra_plane_atomic_duplicate_state,
 	.atomic_destroy_state = tegra_plane_atomic_destroy_state,
 	.format_mod_supported = tegra_plane_format_mod_supported,
+	.atomic_set_property = tegra_plane_set_property,
+	.atomic_get_property = tegra_plane_get_property,
 };
 
 int tegra_plane_state_add(struct tegra_plane *plane,
diff --git a/drivers/gpu/drm/tegra/plane.h b/drivers/gpu/drm/tegra/plane.h
index 7360ddfafee8..dafecea73b29 100644
--- a/drivers/gpu/drm/tegra/plane.h
+++ b/drivers/gpu/drm/tegra/plane.h
@@ -19,6 +19,11 @@ struct tegra_plane {
 	struct tegra_dc *dc;
 	unsigned int offset;
 	unsigned int index;
+
+	struct {
+		struct drm_property *color_key0;
+		struct drm_property *color_key1;
+	} props;
 };
 
 struct tegra_cursor {
@@ -49,10 +54,12 @@ struct tegra_plane_state {
 	/* used for legacy blending support only */
 	struct tegra_plane_legacy_blending_state blending[2];
 	bool opaque;
+	bool ckey0_enabled;
+	bool ckey1_enabled;
 };
 
 static inline struct tegra_plane_state *
-to_tegra_plane_state(struct drm_plane_state *state)
+to_tegra_plane_state(const struct drm_plane_state *state)
 {
 	if (state)
 		return container_of(state, struct tegra_plane_state, base);
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v1 4/4] drm/tegra: plane: Add custom CSC BLOB property
  2018-04-16 12:16 [PATCH v1 0/4] More DRM object properties on Tegra Dmitry Osipenko
                   ` (2 preceding siblings ...)
  2018-04-16 12:16 ` [PATCH v1 3/4] drm/tegra: plane: Add custom colorkey properties for older Tegra's Dmitry Osipenko
@ 2018-04-16 12:16 ` Dmitry Osipenko
  2018-04-17  9:01     ` Daniel Vetter
  3 siblings, 1 reply; 15+ messages in thread
From: Dmitry Osipenko @ 2018-04-16 12:16 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra, linux-kernel

This new property allows userspace to apply custom color conversion
coefficients per plane, making possible to utilize display controller
for color adjustments of a video overlay.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/gpu/drm/tegra/dc.c    | 86 +++++++++++++++++++++++++++++++----
 drivers/gpu/drm/tegra/dc.h    | 11 +++++
 drivers/gpu/drm/tegra/plane.c | 35 ++++++++++++++
 drivers/gpu/drm/tegra/plane.h |  5 ++
 include/uapi/drm/tegra_drm.h  | 11 +++++
 5 files changed, 139 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index b19e954a223f..24a1317871d4 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -435,15 +435,15 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
 	value = WIN_ENABLE;
 
 	if (yuv) {
-		/* setup default colorspace conversion coefficients */
-		tegra_plane_writel(plane, 0x00f0, DC_WIN_CSC_YOF);
-		tegra_plane_writel(plane, 0x012a, DC_WIN_CSC_KYRGB);
-		tegra_plane_writel(plane, 0x0000, DC_WIN_CSC_KUR);
-		tegra_plane_writel(plane, 0x0198, DC_WIN_CSC_KVR);
-		tegra_plane_writel(plane, 0x039b, DC_WIN_CSC_KUG);
-		tegra_plane_writel(plane, 0x032f, DC_WIN_CSC_KVG);
-		tegra_plane_writel(plane, 0x0204, DC_WIN_CSC_KUB);
-		tegra_plane_writel(plane, 0x0000, DC_WIN_CSC_KVB);
+		/* setup colorspace conversion coefficients */
+		tegra_plane_writel(plane, window->csc.yof, DC_WIN_CSC_YOF);
+		tegra_plane_writel(plane, window->csc.kyrgb, DC_WIN_CSC_KYRGB);
+		tegra_plane_writel(plane, window->csc.kur, DC_WIN_CSC_KUR);
+		tegra_plane_writel(plane, window->csc.kvr, DC_WIN_CSC_KVR);
+		tegra_plane_writel(plane, window->csc.kug, DC_WIN_CSC_KUG);
+		tegra_plane_writel(plane, window->csc.kvg, DC_WIN_CSC_KVG);
+		tegra_plane_writel(plane, window->csc.kub, DC_WIN_CSC_KUB);
+		tegra_plane_writel(plane, window->csc.kvb, DC_WIN_CSC_KVB);
 
 		value |= CSC_ENABLE;
 	} else if (window->bits_per_pixel < 24) {
@@ -624,6 +624,7 @@ static void tegra_plane_atomic_update(struct drm_plane *plane,
 	struct drm_framebuffer *fb = plane->state->fb;
 	struct tegra_plane *p = to_tegra_plane(plane);
 	struct tegra_dc_window window;
+	const struct drm_tegra_plane_csc_blob *csc;
 	unsigned int i;
 
 	/* rien ne va plus */
@@ -665,6 +666,28 @@ static void tegra_plane_atomic_update(struct drm_plane *plane,
 			window.stride[i] = fb->pitches[i];
 	}
 
+	if (state->csc_blob) {
+		csc = state->csc_blob->data;
+
+		window.csc.yof = csc->yof;
+		window.csc.kyrgb = csc->kyrgb;
+		window.csc.kur = csc->kur;
+		window.csc.kvr = csc->kvr;
+		window.csc.kug = csc->kug;
+		window.csc.kvg = csc->kvg;
+		window.csc.kub = csc->kub;
+		window.csc.kvb = csc->kvb;
+	} else {
+		window.csc.yof = 0x00f0;
+		window.csc.kyrgb = 0x012a;
+		window.csc.kur = 0x0000;
+		window.csc.kvr = 0x0198;
+		window.csc.kug = 0x039b;
+		window.csc.kvg = 0x032f;
+		window.csc.kub = 0x0204;
+		window.csc.kvb = 0x0000;
+	}
+
 	tegra_dc_setup_window(p, &window);
 }
 
@@ -776,6 +799,42 @@ static void tegra_plane_create_legacy_properties(struct tegra_plane *plane,
 	dev_err(plane->dc->dev, "failed to create legacy plane properties\n");
 }
 
+static void tegra_plane_create_csc_property(struct tegra_plane *plane)
+{
+	/* set default colorspace conversion coefficients to ITU-R BT.601 */
+	struct drm_tegra_plane_csc_blob csc_bt601 = {
+		.yof   = 0x00f0,
+		.kyrgb = 0x012a,
+		.kur   = 0x0000,
+		.kvr   = 0x0198,
+		.kug   = 0x039b,
+		.kvg   = 0x032f,
+		.kub   = 0x0204,
+		.kvb   = 0x0000,
+	};
+	struct drm_property_blob *blob;
+
+	blob = drm_property_create_blob(plane->base.dev, sizeof(csc_bt601),
+					&csc_bt601);
+	if (!blob) {
+		dev_err(plane->dc->dev, "failed to create CSC BLOB\n");
+		return;
+	}
+
+	plane->props.csc_blob = drm_property_create(
+		plane->base.dev, DRM_MODE_PROP_BLOB, "YUV to RGB CSC", 0);
+
+	if (!plane->props.csc_blob) {
+		dev_err(plane->dc->dev, "failed to create CSC property\n");
+		drm_property_blob_put(blob);
+		return;
+	}
+
+	drm_object_attach_property(&plane->base.base, plane->props.csc_blob, 0);
+
+	plane->csc_default = blob;
+}
+
 static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
 						    struct tegra_dc *dc)
 {
@@ -814,6 +873,9 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
 	if (dc->soc->legacy_blending)
 		tegra_plane_create_legacy_properties(plane, drm);
 
+	if (dc->soc->has_win_a_csc)
+		tegra_plane_create_csc_property(plane);
+
 	return &plane->base;
 }
 
@@ -1092,6 +1154,7 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
 
 	drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
 	drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255);
+	tegra_plane_create_csc_property(plane);
 
 	return &plane->base;
 }
@@ -2269,6 +2332,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
 	.num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats),
 	.overlay_formats = tegra20_overlay_formats,
 	.modifiers = tegra20_modifiers,
+	.has_win_a_csc = false,
 };
 
 static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
@@ -2287,6 +2351,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
 	.num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats),
 	.overlay_formats = tegra20_overlay_formats,
 	.modifiers = tegra20_modifiers,
+	.has_win_a_csc = false,
 };
 
 static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
@@ -2305,6 +2370,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
 	.num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats),
 	.overlay_formats = tegra114_overlay_formats,
 	.modifiers = tegra20_modifiers,
+	.has_win_a_csc = true,
 };
 
 static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
@@ -2323,6 +2389,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
 	.num_overlay_formats = ARRAY_SIZE(tegra124_overlay_formats),
 	.overlay_formats = tegra124_overlay_formats,
 	.modifiers = tegra124_modifiers,
+	.has_win_a_csc = true,
 };
 
 static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
@@ -2341,6 +2408,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
 	.num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats),
 	.overlay_formats = tegra114_overlay_formats,
 	.modifiers = tegra124_modifiers,
+	.has_win_a_csc = true,
 };
 
 static const struct tegra_windowgroup_soc tegra186_dc_wgrps[] = {
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 3913d047abac..23439eaaa4de 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -77,6 +77,7 @@ struct tegra_dc_soc_info {
 	const u32 *overlay_formats;
 	unsigned int num_overlay_formats;
 	const u64 *modifiers;
+	bool has_win_a_csc;
 };
 
 struct tegra_dc {
@@ -152,6 +153,16 @@ struct tegra_dc_window {
 		unsigned int w;
 		unsigned int h;
 	} dst;
+	struct {
+		unsigned int yof;
+		unsigned int kyrgb;
+		unsigned int kur;
+		unsigned int kvr;
+		unsigned int kug;
+		unsigned int kvg;
+		unsigned int kub;
+		unsigned int kvb;
+	} csc;
 	unsigned int bits_per_pixel;
 	unsigned int stride[2];
 	unsigned long base[3];
diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c
index 4d794f2b44df..c5733c5a66e9 100644
--- a/drivers/gpu/drm/tegra/plane.c
+++ b/drivers/gpu/drm/tegra/plane.c
@@ -17,6 +17,9 @@ static void tegra_plane_destroy(struct drm_plane *plane)
 {
 	struct tegra_plane *p = to_tegra_plane(plane);
 
+	if (p->csc_default)
+		drm_property_blob_put(p->csc_default);
+
 	drm_plane_cleanup(plane);
 	kfree(p);
 }
@@ -38,6 +41,9 @@ static void tegra_plane_reset(struct drm_plane *plane)
 		plane->state->plane = plane;
 		plane->state->zpos = p->index;
 		plane->state->normalized_zpos = p->index;
+
+		if (p->csc_default)
+			state->csc_blob = drm_property_blob_get(p->csc_default);
 	}
 }
 
@@ -63,12 +69,22 @@ tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
 	for (i = 0; i < 2; i++)
 		copy->blending[i] = state->blending[i];
 
+	if (state->csc_blob)
+		copy->csc_blob = drm_property_blob_get(state->csc_blob);
+	else
+		copy->csc_blob = NULL;
+
 	return &copy->base;
 }
 
 static void tegra_plane_atomic_destroy_state(struct drm_plane *plane,
 					     struct drm_plane_state *state)
 {
+	struct tegra_plane_state *tegra = to_tegra_plane_state(state);
+
+	if (tegra->csc_blob)
+		drm_property_blob_put(tegra->csc_blob);
+
 	__drm_atomic_helper_plane_destroy_state(state);
 	kfree(state);
 }
@@ -95,6 +111,23 @@ static int tegra_plane_set_property(struct drm_plane *plane,
 {
 	struct tegra_plane_state *tegra_state = to_tegra_plane_state(state);
 	struct tegra_plane *tegra = to_tegra_plane(plane);
+	struct drm_property_blob *blob;
+
+	if (property == tegra->props.csc_blob) {
+		blob = drm_property_lookup_blob(plane->dev, value);
+		if (!blob)
+			return -EINVAL;
+
+		if (blob->length != sizeof(struct drm_tegra_plane_csc_blob)) {
+			drm_property_blob_put(blob);
+			return -EINVAL;
+		}
+
+		drm_property_blob_put(tegra_state->csc_blob);
+		tegra_state->csc_blob = blob;
+
+		return 0;
+	}
 
 	if (property == tegra->props.color_key0)
 		tegra_state->ckey0_enabled = value;
@@ -118,6 +151,8 @@ static int tegra_plane_get_property(struct drm_plane *plane,
 		*value = tegra_state->ckey0_enabled;
 	else if (property == tegra->props.color_key1)
 		*value = tegra_state->ckey1_enabled;
+	else if (property == tegra->props.csc_blob)
+		*value = tegra_state->csc_blob->base.id;
 	else
 		return -EINVAL;
 
diff --git a/drivers/gpu/drm/tegra/plane.h b/drivers/gpu/drm/tegra/plane.h
index dafecea73b29..dc9efa7be502 100644
--- a/drivers/gpu/drm/tegra/plane.h
+++ b/drivers/gpu/drm/tegra/plane.h
@@ -23,7 +23,10 @@ struct tegra_plane {
 	struct {
 		struct drm_property *color_key0;
 		struct drm_property *color_key1;
+		struct drm_property *csc_blob;
 	} props;
+
+	struct drm_property_blob *csc_default;
 };
 
 struct tegra_cursor {
@@ -51,6 +54,8 @@ struct tegra_plane_state {
 	u32 format;
 	u32 swap;
 
+	struct drm_property_blob *csc_blob;
+
 	/* used for legacy blending support only */
 	struct tegra_plane_legacy_blending_state blending[2];
 	bool opaque;
diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h
index a5da44209a68..a3054ea7b222 100644
--- a/include/uapi/drm/tegra_drm.h
+++ b/include/uapi/drm/tegra_drm.h
@@ -29,6 +29,17 @@
 extern "C" {
 #endif
 
+struct drm_tegra_plane_csc_blob {
+	__u32 yof;
+	__u32 kyrgb;
+	__u32 kur;
+	__u32 kvr;
+	__u32 kug;
+	__u32 kvg;
+	__u32 kub;
+	__u32 kvb;
+};
+
 #define DRM_TEGRA_GEM_CREATE_TILED     (1 << 0)
 #define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1)
 #define DRM_TEGRA_GEM_CREATE_SCATTERED (1 << 2)
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v1 3/4] drm/tegra: plane: Add custom colorkey properties for older Tegra's
  2018-04-16 12:16 ` [PATCH v1 3/4] drm/tegra: plane: Add custom colorkey properties for older Tegra's Dmitry Osipenko
@ 2018-04-17  9:00     ` Daniel Vetter
  0 siblings, 0 replies; 15+ messages in thread
From: Daniel Vetter @ 2018-04-17  9:00 UTC (permalink / raw)
  To: Dmitry Osipenko; +Cc: linux-tegra, Thierry Reding, linux-kernel, dri-devel

On Mon, Apr 16, 2018 at 03:16:27PM +0300, Dmitry Osipenko wrote:
> Colorkey'ing allows to draw on top of overlapping planes, like for example
> on top of a video plane. Older Tegra's have a limited colorkey'ing
> capability such that blending features are reduced when colorkey'ing is
> enabled. In particular dependent weighting isn't possible, meaning that
> cursors plane can't be displayed properly. In most cases it is more useful
> to display content on top of video overlay, sacrificing mouse cursor
> in the area of three planes intersection with colorkey mismatch. This
> patch adds a custom colorkey properties to primary plane and CRTC's of
> older Tegra's, allowing userspace like Opentegra Xorg driver to implement
> colorkey support for XVideo extension.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>

Since this is your own uapi, where's the userspace per

https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#open-source-userspace-requirements

And why wo we need a tegra-private colorkey property here? I thought
other's have been discussing this in the context of other drivers.
-Daniel

> ---
>  drivers/gpu/drm/tegra/dc.c    | 166 ++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/tegra/dc.h    |  18 +++-
>  drivers/gpu/drm/tegra/plane.c |  40 ++++++++
>  drivers/gpu/drm/tegra/plane.h |   9 +-
>  4 files changed, 231 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> index a54eefea2513..b19e954a223f 100644
> --- a/drivers/gpu/drm/tegra/dc.c
> +++ b/drivers/gpu/drm/tegra/dc.c
> @@ -172,6 +172,24 @@ static void tegra_plane_setup_blending_legacy(struct tegra_plane *plane)
>  
>  	state = to_tegra_plane_state(plane->base.state);
>  
> +	/*
> +	 * Assuming default zPos window order, enable color keying for cases
> +	 * of overlapping with topping windows, excluding overlap with
> +	 * window B. Due to limited HW capabilities, this allows to draw
> +	 * primary plane on top of video overlay in areas where key isn't
> +	 * matching. Though window C will be completely transparent in a
> +	 * region of three windows intersection + key mismatch.
> +	 */
> +	if (state->ckey0_enabled) {
> +		background[0] |= BLEND_COLOR_KEY_0;
> +		background[2] |= BLEND_COLOR_KEY_0;
> +	}
> +
> +	if (state->ckey1_enabled) {
> +		background[0] |= BLEND_COLOR_KEY_1;
> +		background[2] |= BLEND_COLOR_KEY_1;
> +	}
> +
>  	if (state->opaque) {
>  		/*
>  		 * Since custom fix-weight blending isn't utilized and weight
> @@ -729,6 +747,35 @@ static unsigned long tegra_plane_get_possible_crtcs(struct drm_device *drm)
>  	return 1 << drm->mode_config.num_crtc;
>  }
>  
> +static void tegra_plane_create_legacy_properties(struct tegra_plane *plane,
> +						 struct drm_device *drm)
> +{
> +	plane->props.color_key0 = drm_property_create_bool(
> +						drm, 0, "color key 0");
> +	plane->props.color_key1 = drm_property_create_bool(
> +						drm, 0, "color key 1");
> +
> +	if (!plane->props.color_key0 ||
> +	    !plane->props.color_key1)
> +		goto err_cleanup;
> +
> +	drm_object_attach_property(&plane->base.base, plane->props.color_key0,
> +				   false);
> +	drm_object_attach_property(&plane->base.base, plane->props.color_key1,
> +				   false);
> +
> +	return;
> +
> +err_cleanup:
> +	if (plane->props.color_key0)
> +		drm_property_destroy(drm, plane->props.color_key0);
> +
> +	if (plane->props.color_key1)
> +		drm_property_destroy(drm, plane->props.color_key1);
> +
> +	dev_err(plane->dc->dev, "failed to create legacy plane properties\n");
> +}
> +
>  static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
>  						    struct tegra_dc *dc)
>  {
> @@ -764,6 +811,9 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
>  	drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
>  	drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255);
>  
> +	if (dc->soc->legacy_blending)
> +		tegra_plane_create_legacy_properties(plane, drm);
> +
>  	return &plane->base;
>  }
>  
> @@ -1153,6 +1203,8 @@ tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
>  	copy->pclk = state->pclk;
>  	copy->div = state->div;
>  	copy->planes = state->planes;
> +	copy->ckey0 = state->ckey0;
> +	copy->ckey1 = state->ckey1;
>  
>  	return &copy->base;
>  }
> @@ -1537,6 +1589,50 @@ static void tegra_dc_disable_vblank(struct drm_crtc *crtc)
>  	tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
>  }
>  
> +static int tegra_crtc_atomic_set_property(struct drm_crtc *crtc,
> +					  struct drm_crtc_state *state,
> +					  struct drm_property *property,
> +					  uint64_t value)
> +{
> +	struct tegra_dc_state *tegra_state = to_dc_state(state);
> +	struct tegra_dc *dc = to_tegra_dc(crtc);
> +
> +	if (property == dc->props.ckey0_lower)
> +		tegra_state->ckey0.lower = value;
> +	else if (property == dc->props.ckey0_upper)
> +		tegra_state->ckey0.upper = value;
> +	else if (property == dc->props.ckey1_lower)
> +		tegra_state->ckey1.lower = value;
> +	else if (property == dc->props.ckey1_upper)
> +		tegra_state->ckey1.upper = value;
> +	else
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int tegra_crtc_atomic_get_property(struct drm_crtc *crtc,
> +					  const struct drm_crtc_state *state,
> +					  struct drm_property *property,
> +					  uint64_t *value)
> +{
> +	struct tegra_dc_state *tegra_state = to_dc_state(state);
> +	struct tegra_dc *dc = to_tegra_dc(crtc);
> +
> +	if (property == dc->props.ckey0_lower)
> +		*value = tegra_state->ckey0.lower;
> +	else if (property == dc->props.ckey0_upper)
> +		*value = tegra_state->ckey0.upper;
> +	else if (property == dc->props.ckey1_lower)
> +		*value = tegra_state->ckey1.lower;
> +	else if (property == dc->props.ckey1_upper)
> +		*value = tegra_state->ckey1.upper;
> +	else
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
>  static const struct drm_crtc_funcs tegra_crtc_funcs = {
>  	.page_flip = drm_atomic_helper_page_flip,
>  	.set_config = drm_atomic_helper_set_config,
> @@ -1549,6 +1645,8 @@ static const struct drm_crtc_funcs tegra_crtc_funcs = {
>  	.get_vblank_counter = tegra_dc_get_vblank_counter,
>  	.enable_vblank = tegra_dc_enable_vblank,
>  	.disable_vblank = tegra_dc_disable_vblank,
> +	.atomic_set_property = tegra_crtc_atomic_set_property,
> +	.atomic_get_property = tegra_crtc_atomic_get_property,
>  };
>  
>  static int tegra_dc_set_timings(struct tegra_dc *dc,
> @@ -1883,6 +1981,18 @@ static void tegra_crtc_atomic_flush(struct drm_crtc *crtc,
>  	struct tegra_dc *dc = to_tegra_dc(crtc);
>  	u32 value;
>  
> +	if (dc->soc->legacy_blending) {
> +		tegra_dc_writel(dc, state->ckey0.lower,
> +				DC_DISP_COLOR_KEY0_LOWER);
> +		tegra_dc_writel(dc, state->ckey0.upper,
> +				DC_DISP_COLOR_KEY0_UPPER);
> +
> +		tegra_dc_writel(dc, state->ckey1.lower,
> +				DC_DISP_COLOR_KEY1_LOWER);
> +		tegra_dc_writel(dc, state->ckey1.upper,
> +				DC_DISP_COLOR_KEY1_UPPER);
> +	}
> +
>  	value = state->planes << 8 | GENERAL_UPDATE;
>  	tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
>  	value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
> @@ -1944,6 +2054,56 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)
>  	return IRQ_HANDLED;
>  }
>  
> +static int tegra_dc_create_legacy_properties(struct tegra_dc *dc,
> +					     struct drm_device *drm)
> +{
> +	/*
> +	 * Each color key value is represented in RGB888 format.
> +	 * All planes share the same color key values and free to choose
> +	 * among the ckey0 and ckey1.
> +	 */
> +	dc->props.ckey0_lower = drm_property_create_range(
> +			drm, 0, "color key 0 lower margin", 0, 0xffffff);
> +	dc->props.ckey0_upper = drm_property_create_range(
> +			drm, 0, "color key 0 upper margin", 0, 0xffffff);
> +	dc->props.ckey1_lower = drm_property_create_range(
> +			drm, 0, "color key 1 lower margin", 0, 0xffffff);
> +	dc->props.ckey1_upper = drm_property_create_range(
> +			drm, 0, "color key 1 upper margin", 0, 0xffffff);
> +
> +	if (!dc->props.ckey0_lower ||
> +	    !dc->props.ckey0_upper ||
> +	    !dc->props.ckey1_lower ||
> +	    !dc->props.ckey1_upper)
> +		goto err_cleanup;
> +
> +	drm_object_attach_property(&dc->base.base, dc->props.ckey0_lower,
> +				   0x000000);
> +	drm_object_attach_property(&dc->base.base, dc->props.ckey0_upper,
> +				   0x000000);
> +	drm_object_attach_property(&dc->base.base, dc->props.ckey1_lower,
> +				   0x000000);
> +	drm_object_attach_property(&dc->base.base, dc->props.ckey1_upper,
> +				   0x000000);
> +
> +	return 0;
> +
> +err_cleanup:
> +	if (dc->props.ckey0_lower)
> +		drm_property_destroy(drm, dc->props.ckey0_lower);
> +
> +	if (dc->props.ckey0_upper)
> +		drm_property_destroy(drm, dc->props.ckey0_upper);
> +
> +	if (dc->props.ckey1_lower)
> +		drm_property_destroy(drm, dc->props.ckey1_lower);
> +
> +	if (dc->props.ckey1_upper)
> +		drm_property_destroy(drm, dc->props.ckey1_upper);
> +
> +	return -ENOMEM;
> +}
> +
>  static int tegra_dc_init(struct host1x_client *client)
>  {
>  	struct drm_device *drm = dev_get_drvdata(client->parent);
> @@ -2031,6 +2191,12 @@ static int tegra_dc_init(struct host1x_client *client)
>  		goto cleanup;
>  	}
>  
> +	if (dc->soc->legacy_blending) {
> +		err = tegra_dc_create_legacy_properties(dc, drm);
> +		if (err < 0)
> +			dev_err(dc->dev, "failed to create CRTC properties\n");
> +	}
> +
>  	return 0;
>  
>  cleanup:
> diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
> index 3156006e75c6..3913d047abac 100644
> --- a/drivers/gpu/drm/tegra/dc.h
> +++ b/drivers/gpu/drm/tegra/dc.h
> @@ -18,6 +18,11 @@
>  
>  struct tegra_output;
>  
> +struct tegra_dc_color_key_state {
> +	u32 lower;
> +	u32 upper;
> +};
> +
>  struct tegra_dc_state {
>  	struct drm_crtc_state base;
>  
> @@ -26,9 +31,13 @@ struct tegra_dc_state {
>  	unsigned int div;
>  
>  	u32 planes;
> +
> +	struct tegra_dc_color_key_state ckey0;
> +	struct tegra_dc_color_key_state ckey1;
>  };
>  
> -static inline struct tegra_dc_state *to_dc_state(struct drm_crtc_state *state)
> +static inline struct tegra_dc_state *
> +to_dc_state(const struct drm_crtc_state *state)
>  {
>  	if (state)
>  		return container_of(state, struct tegra_dc_state, base);
> @@ -94,6 +103,13 @@ struct tegra_dc {
>  	const struct tegra_dc_soc_info *soc;
>  
>  	struct iommu_domain *domain;
> +
> +	struct {
> +		struct drm_property *ckey0_lower;
> +		struct drm_property *ckey0_upper;
> +		struct drm_property *ckey1_lower;
> +		struct drm_property *ckey1_upper;
> +	} props;
>  };
>  
>  static inline struct tegra_dc *
> diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c
> index 0406c2ef432c..4d794f2b44df 100644
> --- a/drivers/gpu/drm/tegra/plane.c
> +++ b/drivers/gpu/drm/tegra/plane.c
> @@ -57,6 +57,8 @@ tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
>  	copy->format = state->format;
>  	copy->swap = state->swap;
>  	copy->opaque = state->opaque;
> +	copy->ckey0_enabled = state->ckey0_enabled;
> +	copy->ckey1_enabled = state->ckey1_enabled;
>  
>  	for (i = 0; i < 2; i++)
>  		copy->blending[i] = state->blending[i];
> @@ -86,6 +88,42 @@ static bool tegra_plane_format_mod_supported(struct drm_plane *plane,
>  	return false;
>  }
>  
> +static int tegra_plane_set_property(struct drm_plane *plane,
> +				    struct drm_plane_state *state,
> +				    struct drm_property *property,
> +				    uint64_t value)
> +{
> +	struct tegra_plane_state *tegra_state = to_tegra_plane_state(state);
> +	struct tegra_plane *tegra = to_tegra_plane(plane);
> +
> +	if (property == tegra->props.color_key0)
> +		tegra_state->ckey0_enabled = value;
> +	else if (property == tegra->props.color_key1)
> +		tegra_state->ckey1_enabled = value;
> +	else
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int tegra_plane_get_property(struct drm_plane *plane,
> +				    const struct drm_plane_state *state,
> +				    struct drm_property *property,
> +				    uint64_t *value)
> +{
> +	struct tegra_plane_state *tegra_state = to_tegra_plane_state(state);
> +	struct tegra_plane *tegra = to_tegra_plane(plane);
> +
> +	if (property == tegra->props.color_key0)
> +		*value = tegra_state->ckey0_enabled;
> +	else if (property == tegra->props.color_key1)
> +		*value = tegra_state->ckey1_enabled;
> +	else
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
>  const struct drm_plane_funcs tegra_plane_funcs = {
>  	.update_plane = drm_atomic_helper_update_plane,
>  	.disable_plane = drm_atomic_helper_disable_plane,
> @@ -94,6 +132,8 @@ const struct drm_plane_funcs tegra_plane_funcs = {
>  	.atomic_duplicate_state = tegra_plane_atomic_duplicate_state,
>  	.atomic_destroy_state = tegra_plane_atomic_destroy_state,
>  	.format_mod_supported = tegra_plane_format_mod_supported,
> +	.atomic_set_property = tegra_plane_set_property,
> +	.atomic_get_property = tegra_plane_get_property,
>  };
>  
>  int tegra_plane_state_add(struct tegra_plane *plane,
> diff --git a/drivers/gpu/drm/tegra/plane.h b/drivers/gpu/drm/tegra/plane.h
> index 7360ddfafee8..dafecea73b29 100644
> --- a/drivers/gpu/drm/tegra/plane.h
> +++ b/drivers/gpu/drm/tegra/plane.h
> @@ -19,6 +19,11 @@ struct tegra_plane {
>  	struct tegra_dc *dc;
>  	unsigned int offset;
>  	unsigned int index;
> +
> +	struct {
> +		struct drm_property *color_key0;
> +		struct drm_property *color_key1;
> +	} props;
>  };
>  
>  struct tegra_cursor {
> @@ -49,10 +54,12 @@ struct tegra_plane_state {
>  	/* used for legacy blending support only */
>  	struct tegra_plane_legacy_blending_state blending[2];
>  	bool opaque;
> +	bool ckey0_enabled;
> +	bool ckey1_enabled;
>  };
>  
>  static inline struct tegra_plane_state *
> -to_tegra_plane_state(struct drm_plane_state *state)
> +to_tegra_plane_state(const struct drm_plane_state *state)
>  {
>  	if (state)
>  		return container_of(state, struct tegra_plane_state, base);
> -- 
> 2.17.0
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v1 3/4] drm/tegra: plane: Add custom colorkey properties for older Tegra's
@ 2018-04-17  9:00     ` Daniel Vetter
  0 siblings, 0 replies; 15+ messages in thread
From: Daniel Vetter @ 2018-04-17  9:00 UTC (permalink / raw)
  To: Dmitry Osipenko; +Cc: Thierry Reding, linux-tegra, linux-kernel, dri-devel

On Mon, Apr 16, 2018 at 03:16:27PM +0300, Dmitry Osipenko wrote:
> Colorkey'ing allows to draw on top of overlapping planes, like for example
> on top of a video plane. Older Tegra's have a limited colorkey'ing
> capability such that blending features are reduced when colorkey'ing is
> enabled. In particular dependent weighting isn't possible, meaning that
> cursors plane can't be displayed properly. In most cases it is more useful
> to display content on top of video overlay, sacrificing mouse cursor
> in the area of three planes intersection with colorkey mismatch. This
> patch adds a custom colorkey properties to primary plane and CRTC's of
> older Tegra's, allowing userspace like Opentegra Xorg driver to implement
> colorkey support for XVideo extension.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>

Since this is your own uapi, where's the userspace per

https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#open-source-userspace-requirements

And why wo we need a tegra-private colorkey property here? I thought
other's have been discussing this in the context of other drivers.
-Daniel

> ---
>  drivers/gpu/drm/tegra/dc.c    | 166 ++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/tegra/dc.h    |  18 +++-
>  drivers/gpu/drm/tegra/plane.c |  40 ++++++++
>  drivers/gpu/drm/tegra/plane.h |   9 +-
>  4 files changed, 231 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> index a54eefea2513..b19e954a223f 100644
> --- a/drivers/gpu/drm/tegra/dc.c
> +++ b/drivers/gpu/drm/tegra/dc.c
> @@ -172,6 +172,24 @@ static void tegra_plane_setup_blending_legacy(struct tegra_plane *plane)
>  
>  	state = to_tegra_plane_state(plane->base.state);
>  
> +	/*
> +	 * Assuming default zPos window order, enable color keying for cases
> +	 * of overlapping with topping windows, excluding overlap with
> +	 * window B. Due to limited HW capabilities, this allows to draw
> +	 * primary plane on top of video overlay in areas where key isn't
> +	 * matching. Though window C will be completely transparent in a
> +	 * region of three windows intersection + key mismatch.
> +	 */
> +	if (state->ckey0_enabled) {
> +		background[0] |= BLEND_COLOR_KEY_0;
> +		background[2] |= BLEND_COLOR_KEY_0;
> +	}
> +
> +	if (state->ckey1_enabled) {
> +		background[0] |= BLEND_COLOR_KEY_1;
> +		background[2] |= BLEND_COLOR_KEY_1;
> +	}
> +
>  	if (state->opaque) {
>  		/*
>  		 * Since custom fix-weight blending isn't utilized and weight
> @@ -729,6 +747,35 @@ static unsigned long tegra_plane_get_possible_crtcs(struct drm_device *drm)
>  	return 1 << drm->mode_config.num_crtc;
>  }
>  
> +static void tegra_plane_create_legacy_properties(struct tegra_plane *plane,
> +						 struct drm_device *drm)
> +{
> +	plane->props.color_key0 = drm_property_create_bool(
> +						drm, 0, "color key 0");
> +	plane->props.color_key1 = drm_property_create_bool(
> +						drm, 0, "color key 1");
> +
> +	if (!plane->props.color_key0 ||
> +	    !plane->props.color_key1)
> +		goto err_cleanup;
> +
> +	drm_object_attach_property(&plane->base.base, plane->props.color_key0,
> +				   false);
> +	drm_object_attach_property(&plane->base.base, plane->props.color_key1,
> +				   false);
> +
> +	return;
> +
> +err_cleanup:
> +	if (plane->props.color_key0)
> +		drm_property_destroy(drm, plane->props.color_key0);
> +
> +	if (plane->props.color_key1)
> +		drm_property_destroy(drm, plane->props.color_key1);
> +
> +	dev_err(plane->dc->dev, "failed to create legacy plane properties\n");
> +}
> +
>  static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
>  						    struct tegra_dc *dc)
>  {
> @@ -764,6 +811,9 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
>  	drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
>  	drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255);
>  
> +	if (dc->soc->legacy_blending)
> +		tegra_plane_create_legacy_properties(plane, drm);
> +
>  	return &plane->base;
>  }
>  
> @@ -1153,6 +1203,8 @@ tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
>  	copy->pclk = state->pclk;
>  	copy->div = state->div;
>  	copy->planes = state->planes;
> +	copy->ckey0 = state->ckey0;
> +	copy->ckey1 = state->ckey1;
>  
>  	return &copy->base;
>  }
> @@ -1537,6 +1589,50 @@ static void tegra_dc_disable_vblank(struct drm_crtc *crtc)
>  	tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
>  }
>  
> +static int tegra_crtc_atomic_set_property(struct drm_crtc *crtc,
> +					  struct drm_crtc_state *state,
> +					  struct drm_property *property,
> +					  uint64_t value)
> +{
> +	struct tegra_dc_state *tegra_state = to_dc_state(state);
> +	struct tegra_dc *dc = to_tegra_dc(crtc);
> +
> +	if (property == dc->props.ckey0_lower)
> +		tegra_state->ckey0.lower = value;
> +	else if (property == dc->props.ckey0_upper)
> +		tegra_state->ckey0.upper = value;
> +	else if (property == dc->props.ckey1_lower)
> +		tegra_state->ckey1.lower = value;
> +	else if (property == dc->props.ckey1_upper)
> +		tegra_state->ckey1.upper = value;
> +	else
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int tegra_crtc_atomic_get_property(struct drm_crtc *crtc,
> +					  const struct drm_crtc_state *state,
> +					  struct drm_property *property,
> +					  uint64_t *value)
> +{
> +	struct tegra_dc_state *tegra_state = to_dc_state(state);
> +	struct tegra_dc *dc = to_tegra_dc(crtc);
> +
> +	if (property == dc->props.ckey0_lower)
> +		*value = tegra_state->ckey0.lower;
> +	else if (property == dc->props.ckey0_upper)
> +		*value = tegra_state->ckey0.upper;
> +	else if (property == dc->props.ckey1_lower)
> +		*value = tegra_state->ckey1.lower;
> +	else if (property == dc->props.ckey1_upper)
> +		*value = tegra_state->ckey1.upper;
> +	else
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
>  static const struct drm_crtc_funcs tegra_crtc_funcs = {
>  	.page_flip = drm_atomic_helper_page_flip,
>  	.set_config = drm_atomic_helper_set_config,
> @@ -1549,6 +1645,8 @@ static const struct drm_crtc_funcs tegra_crtc_funcs = {
>  	.get_vblank_counter = tegra_dc_get_vblank_counter,
>  	.enable_vblank = tegra_dc_enable_vblank,
>  	.disable_vblank = tegra_dc_disable_vblank,
> +	.atomic_set_property = tegra_crtc_atomic_set_property,
> +	.atomic_get_property = tegra_crtc_atomic_get_property,
>  };
>  
>  static int tegra_dc_set_timings(struct tegra_dc *dc,
> @@ -1883,6 +1981,18 @@ static void tegra_crtc_atomic_flush(struct drm_crtc *crtc,
>  	struct tegra_dc *dc = to_tegra_dc(crtc);
>  	u32 value;
>  
> +	if (dc->soc->legacy_blending) {
> +		tegra_dc_writel(dc, state->ckey0.lower,
> +				DC_DISP_COLOR_KEY0_LOWER);
> +		tegra_dc_writel(dc, state->ckey0.upper,
> +				DC_DISP_COLOR_KEY0_UPPER);
> +
> +		tegra_dc_writel(dc, state->ckey1.lower,
> +				DC_DISP_COLOR_KEY1_LOWER);
> +		tegra_dc_writel(dc, state->ckey1.upper,
> +				DC_DISP_COLOR_KEY1_UPPER);
> +	}
> +
>  	value = state->planes << 8 | GENERAL_UPDATE;
>  	tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
>  	value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
> @@ -1944,6 +2054,56 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)
>  	return IRQ_HANDLED;
>  }
>  
> +static int tegra_dc_create_legacy_properties(struct tegra_dc *dc,
> +					     struct drm_device *drm)
> +{
> +	/*
> +	 * Each color key value is represented in RGB888 format.
> +	 * All planes share the same color key values and free to choose
> +	 * among the ckey0 and ckey1.
> +	 */
> +	dc->props.ckey0_lower = drm_property_create_range(
> +			drm, 0, "color key 0 lower margin", 0, 0xffffff);
> +	dc->props.ckey0_upper = drm_property_create_range(
> +			drm, 0, "color key 0 upper margin", 0, 0xffffff);
> +	dc->props.ckey1_lower = drm_property_create_range(
> +			drm, 0, "color key 1 lower margin", 0, 0xffffff);
> +	dc->props.ckey1_upper = drm_property_create_range(
> +			drm, 0, "color key 1 upper margin", 0, 0xffffff);
> +
> +	if (!dc->props.ckey0_lower ||
> +	    !dc->props.ckey0_upper ||
> +	    !dc->props.ckey1_lower ||
> +	    !dc->props.ckey1_upper)
> +		goto err_cleanup;
> +
> +	drm_object_attach_property(&dc->base.base, dc->props.ckey0_lower,
> +				   0x000000);
> +	drm_object_attach_property(&dc->base.base, dc->props.ckey0_upper,
> +				   0x000000);
> +	drm_object_attach_property(&dc->base.base, dc->props.ckey1_lower,
> +				   0x000000);
> +	drm_object_attach_property(&dc->base.base, dc->props.ckey1_upper,
> +				   0x000000);
> +
> +	return 0;
> +
> +err_cleanup:
> +	if (dc->props.ckey0_lower)
> +		drm_property_destroy(drm, dc->props.ckey0_lower);
> +
> +	if (dc->props.ckey0_upper)
> +		drm_property_destroy(drm, dc->props.ckey0_upper);
> +
> +	if (dc->props.ckey1_lower)
> +		drm_property_destroy(drm, dc->props.ckey1_lower);
> +
> +	if (dc->props.ckey1_upper)
> +		drm_property_destroy(drm, dc->props.ckey1_upper);
> +
> +	return -ENOMEM;
> +}
> +
>  static int tegra_dc_init(struct host1x_client *client)
>  {
>  	struct drm_device *drm = dev_get_drvdata(client->parent);
> @@ -2031,6 +2191,12 @@ static int tegra_dc_init(struct host1x_client *client)
>  		goto cleanup;
>  	}
>  
> +	if (dc->soc->legacy_blending) {
> +		err = tegra_dc_create_legacy_properties(dc, drm);
> +		if (err < 0)
> +			dev_err(dc->dev, "failed to create CRTC properties\n");
> +	}
> +
>  	return 0;
>  
>  cleanup:
> diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
> index 3156006e75c6..3913d047abac 100644
> --- a/drivers/gpu/drm/tegra/dc.h
> +++ b/drivers/gpu/drm/tegra/dc.h
> @@ -18,6 +18,11 @@
>  
>  struct tegra_output;
>  
> +struct tegra_dc_color_key_state {
> +	u32 lower;
> +	u32 upper;
> +};
> +
>  struct tegra_dc_state {
>  	struct drm_crtc_state base;
>  
> @@ -26,9 +31,13 @@ struct tegra_dc_state {
>  	unsigned int div;
>  
>  	u32 planes;
> +
> +	struct tegra_dc_color_key_state ckey0;
> +	struct tegra_dc_color_key_state ckey1;
>  };
>  
> -static inline struct tegra_dc_state *to_dc_state(struct drm_crtc_state *state)
> +static inline struct tegra_dc_state *
> +to_dc_state(const struct drm_crtc_state *state)
>  {
>  	if (state)
>  		return container_of(state, struct tegra_dc_state, base);
> @@ -94,6 +103,13 @@ struct tegra_dc {
>  	const struct tegra_dc_soc_info *soc;
>  
>  	struct iommu_domain *domain;
> +
> +	struct {
> +		struct drm_property *ckey0_lower;
> +		struct drm_property *ckey0_upper;
> +		struct drm_property *ckey1_lower;
> +		struct drm_property *ckey1_upper;
> +	} props;
>  };
>  
>  static inline struct tegra_dc *
> diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c
> index 0406c2ef432c..4d794f2b44df 100644
> --- a/drivers/gpu/drm/tegra/plane.c
> +++ b/drivers/gpu/drm/tegra/plane.c
> @@ -57,6 +57,8 @@ tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
>  	copy->format = state->format;
>  	copy->swap = state->swap;
>  	copy->opaque = state->opaque;
> +	copy->ckey0_enabled = state->ckey0_enabled;
> +	copy->ckey1_enabled = state->ckey1_enabled;
>  
>  	for (i = 0; i < 2; i++)
>  		copy->blending[i] = state->blending[i];
> @@ -86,6 +88,42 @@ static bool tegra_plane_format_mod_supported(struct drm_plane *plane,
>  	return false;
>  }
>  
> +static int tegra_plane_set_property(struct drm_plane *plane,
> +				    struct drm_plane_state *state,
> +				    struct drm_property *property,
> +				    uint64_t value)
> +{
> +	struct tegra_plane_state *tegra_state = to_tegra_plane_state(state);
> +	struct tegra_plane *tegra = to_tegra_plane(plane);
> +
> +	if (property == tegra->props.color_key0)
> +		tegra_state->ckey0_enabled = value;
> +	else if (property == tegra->props.color_key1)
> +		tegra_state->ckey1_enabled = value;
> +	else
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int tegra_plane_get_property(struct drm_plane *plane,
> +				    const struct drm_plane_state *state,
> +				    struct drm_property *property,
> +				    uint64_t *value)
> +{
> +	struct tegra_plane_state *tegra_state = to_tegra_plane_state(state);
> +	struct tegra_plane *tegra = to_tegra_plane(plane);
> +
> +	if (property == tegra->props.color_key0)
> +		*value = tegra_state->ckey0_enabled;
> +	else if (property == tegra->props.color_key1)
> +		*value = tegra_state->ckey1_enabled;
> +	else
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
>  const struct drm_plane_funcs tegra_plane_funcs = {
>  	.update_plane = drm_atomic_helper_update_plane,
>  	.disable_plane = drm_atomic_helper_disable_plane,
> @@ -94,6 +132,8 @@ const struct drm_plane_funcs tegra_plane_funcs = {
>  	.atomic_duplicate_state = tegra_plane_atomic_duplicate_state,
>  	.atomic_destroy_state = tegra_plane_atomic_destroy_state,
>  	.format_mod_supported = tegra_plane_format_mod_supported,
> +	.atomic_set_property = tegra_plane_set_property,
> +	.atomic_get_property = tegra_plane_get_property,
>  };
>  
>  int tegra_plane_state_add(struct tegra_plane *plane,
> diff --git a/drivers/gpu/drm/tegra/plane.h b/drivers/gpu/drm/tegra/plane.h
> index 7360ddfafee8..dafecea73b29 100644
> --- a/drivers/gpu/drm/tegra/plane.h
> +++ b/drivers/gpu/drm/tegra/plane.h
> @@ -19,6 +19,11 @@ struct tegra_plane {
>  	struct tegra_dc *dc;
>  	unsigned int offset;
>  	unsigned int index;
> +
> +	struct {
> +		struct drm_property *color_key0;
> +		struct drm_property *color_key1;
> +	} props;
>  };
>  
>  struct tegra_cursor {
> @@ -49,10 +54,12 @@ struct tegra_plane_state {
>  	/* used for legacy blending support only */
>  	struct tegra_plane_legacy_blending_state blending[2];
>  	bool opaque;
> +	bool ckey0_enabled;
> +	bool ckey1_enabled;
>  };
>  
>  static inline struct tegra_plane_state *
> -to_tegra_plane_state(struct drm_plane_state *state)
> +to_tegra_plane_state(const struct drm_plane_state *state)
>  {
>  	if (state)
>  		return container_of(state, struct tegra_plane_state, base);
> -- 
> 2.17.0
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v1 4/4] drm/tegra: plane: Add custom CSC BLOB property
  2018-04-16 12:16 ` [PATCH v1 4/4] drm/tegra: plane: Add custom CSC BLOB property Dmitry Osipenko
@ 2018-04-17  9:01     ` Daniel Vetter
  0 siblings, 0 replies; 15+ messages in thread
From: Daniel Vetter @ 2018-04-17  9:01 UTC (permalink / raw)
  To: Dmitry Osipenko; +Cc: linux-tegra, Thierry Reding, linux-kernel, dri-devel

On Mon, Apr 16, 2018 at 03:16:28PM +0300, Dmitry Osipenko wrote:
> This new property allows userspace to apply custom color conversion
> coefficients per plane, making possible to utilize display controller
> for color adjustments of a video overlay.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>

Same here, this needs corresponding userspace:

https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#open-source-userspace-requirements

And again there's even more people who discussed extending the existing
color management support for crtcs to planes. I think we definitely want a
standard interface for this, not each driver doing their own thing.
-Daniel

> ---
>  drivers/gpu/drm/tegra/dc.c    | 86 +++++++++++++++++++++++++++++++----
>  drivers/gpu/drm/tegra/dc.h    | 11 +++++
>  drivers/gpu/drm/tegra/plane.c | 35 ++++++++++++++
>  drivers/gpu/drm/tegra/plane.h |  5 ++
>  include/uapi/drm/tegra_drm.h  | 11 +++++
>  5 files changed, 139 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> index b19e954a223f..24a1317871d4 100644
> --- a/drivers/gpu/drm/tegra/dc.c
> +++ b/drivers/gpu/drm/tegra/dc.c
> @@ -435,15 +435,15 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
>  	value = WIN_ENABLE;
>  
>  	if (yuv) {
> -		/* setup default colorspace conversion coefficients */
> -		tegra_plane_writel(plane, 0x00f0, DC_WIN_CSC_YOF);
> -		tegra_plane_writel(plane, 0x012a, DC_WIN_CSC_KYRGB);
> -		tegra_plane_writel(plane, 0x0000, DC_WIN_CSC_KUR);
> -		tegra_plane_writel(plane, 0x0198, DC_WIN_CSC_KVR);
> -		tegra_plane_writel(plane, 0x039b, DC_WIN_CSC_KUG);
> -		tegra_plane_writel(plane, 0x032f, DC_WIN_CSC_KVG);
> -		tegra_plane_writel(plane, 0x0204, DC_WIN_CSC_KUB);
> -		tegra_plane_writel(plane, 0x0000, DC_WIN_CSC_KVB);
> +		/* setup colorspace conversion coefficients */
> +		tegra_plane_writel(plane, window->csc.yof, DC_WIN_CSC_YOF);
> +		tegra_plane_writel(plane, window->csc.kyrgb, DC_WIN_CSC_KYRGB);
> +		tegra_plane_writel(plane, window->csc.kur, DC_WIN_CSC_KUR);
> +		tegra_plane_writel(plane, window->csc.kvr, DC_WIN_CSC_KVR);
> +		tegra_plane_writel(plane, window->csc.kug, DC_WIN_CSC_KUG);
> +		tegra_plane_writel(plane, window->csc.kvg, DC_WIN_CSC_KVG);
> +		tegra_plane_writel(plane, window->csc.kub, DC_WIN_CSC_KUB);
> +		tegra_plane_writel(plane, window->csc.kvb, DC_WIN_CSC_KVB);
>  
>  		value |= CSC_ENABLE;
>  	} else if (window->bits_per_pixel < 24) {
> @@ -624,6 +624,7 @@ static void tegra_plane_atomic_update(struct drm_plane *plane,
>  	struct drm_framebuffer *fb = plane->state->fb;
>  	struct tegra_plane *p = to_tegra_plane(plane);
>  	struct tegra_dc_window window;
> +	const struct drm_tegra_plane_csc_blob *csc;
>  	unsigned int i;
>  
>  	/* rien ne va plus */
> @@ -665,6 +666,28 @@ static void tegra_plane_atomic_update(struct drm_plane *plane,
>  			window.stride[i] = fb->pitches[i];
>  	}
>  
> +	if (state->csc_blob) {
> +		csc = state->csc_blob->data;
> +
> +		window.csc.yof = csc->yof;
> +		window.csc.kyrgb = csc->kyrgb;
> +		window.csc.kur = csc->kur;
> +		window.csc.kvr = csc->kvr;
> +		window.csc.kug = csc->kug;
> +		window.csc.kvg = csc->kvg;
> +		window.csc.kub = csc->kub;
> +		window.csc.kvb = csc->kvb;
> +	} else {
> +		window.csc.yof = 0x00f0;
> +		window.csc.kyrgb = 0x012a;
> +		window.csc.kur = 0x0000;
> +		window.csc.kvr = 0x0198;
> +		window.csc.kug = 0x039b;
> +		window.csc.kvg = 0x032f;
> +		window.csc.kub = 0x0204;
> +		window.csc.kvb = 0x0000;
> +	}
> +
>  	tegra_dc_setup_window(p, &window);
>  }
>  
> @@ -776,6 +799,42 @@ static void tegra_plane_create_legacy_properties(struct tegra_plane *plane,
>  	dev_err(plane->dc->dev, "failed to create legacy plane properties\n");
>  }
>  
> +static void tegra_plane_create_csc_property(struct tegra_plane *plane)
> +{
> +	/* set default colorspace conversion coefficients to ITU-R BT.601 */
> +	struct drm_tegra_plane_csc_blob csc_bt601 = {
> +		.yof   = 0x00f0,
> +		.kyrgb = 0x012a,
> +		.kur   = 0x0000,
> +		.kvr   = 0x0198,
> +		.kug   = 0x039b,
> +		.kvg   = 0x032f,
> +		.kub   = 0x0204,
> +		.kvb   = 0x0000,
> +	};
> +	struct drm_property_blob *blob;
> +
> +	blob = drm_property_create_blob(plane->base.dev, sizeof(csc_bt601),
> +					&csc_bt601);
> +	if (!blob) {
> +		dev_err(plane->dc->dev, "failed to create CSC BLOB\n");
> +		return;
> +	}
> +
> +	plane->props.csc_blob = drm_property_create(
> +		plane->base.dev, DRM_MODE_PROP_BLOB, "YUV to RGB CSC", 0);
> +
> +	if (!plane->props.csc_blob) {
> +		dev_err(plane->dc->dev, "failed to create CSC property\n");
> +		drm_property_blob_put(blob);
> +		return;
> +	}
> +
> +	drm_object_attach_property(&plane->base.base, plane->props.csc_blob, 0);
> +
> +	plane->csc_default = blob;
> +}
> +
>  static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
>  						    struct tegra_dc *dc)
>  {
> @@ -814,6 +873,9 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
>  	if (dc->soc->legacy_blending)
>  		tegra_plane_create_legacy_properties(plane, drm);
>  
> +	if (dc->soc->has_win_a_csc)
> +		tegra_plane_create_csc_property(plane);
> +
>  	return &plane->base;
>  }
>  
> @@ -1092,6 +1154,7 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
>  
>  	drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
>  	drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255);
> +	tegra_plane_create_csc_property(plane);
>  
>  	return &plane->base;
>  }
> @@ -2269,6 +2332,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
>  	.num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats),
>  	.overlay_formats = tegra20_overlay_formats,
>  	.modifiers = tegra20_modifiers,
> +	.has_win_a_csc = false,
>  };
>  
>  static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
> @@ -2287,6 +2351,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
>  	.num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats),
>  	.overlay_formats = tegra20_overlay_formats,
>  	.modifiers = tegra20_modifiers,
> +	.has_win_a_csc = false,
>  };
>  
>  static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
> @@ -2305,6 +2370,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
>  	.num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats),
>  	.overlay_formats = tegra114_overlay_formats,
>  	.modifiers = tegra20_modifiers,
> +	.has_win_a_csc = true,
>  };
>  
>  static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
> @@ -2323,6 +2389,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
>  	.num_overlay_formats = ARRAY_SIZE(tegra124_overlay_formats),
>  	.overlay_formats = tegra124_overlay_formats,
>  	.modifiers = tegra124_modifiers,
> +	.has_win_a_csc = true,
>  };
>  
>  static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
> @@ -2341,6 +2408,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
>  	.num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats),
>  	.overlay_formats = tegra114_overlay_formats,
>  	.modifiers = tegra124_modifiers,
> +	.has_win_a_csc = true,
>  };
>  
>  static const struct tegra_windowgroup_soc tegra186_dc_wgrps[] = {
> diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
> index 3913d047abac..23439eaaa4de 100644
> --- a/drivers/gpu/drm/tegra/dc.h
> +++ b/drivers/gpu/drm/tegra/dc.h
> @@ -77,6 +77,7 @@ struct tegra_dc_soc_info {
>  	const u32 *overlay_formats;
>  	unsigned int num_overlay_formats;
>  	const u64 *modifiers;
> +	bool has_win_a_csc;
>  };
>  
>  struct tegra_dc {
> @@ -152,6 +153,16 @@ struct tegra_dc_window {
>  		unsigned int w;
>  		unsigned int h;
>  	} dst;
> +	struct {
> +		unsigned int yof;
> +		unsigned int kyrgb;
> +		unsigned int kur;
> +		unsigned int kvr;
> +		unsigned int kug;
> +		unsigned int kvg;
> +		unsigned int kub;
> +		unsigned int kvb;
> +	} csc;
>  	unsigned int bits_per_pixel;
>  	unsigned int stride[2];
>  	unsigned long base[3];
> diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c
> index 4d794f2b44df..c5733c5a66e9 100644
> --- a/drivers/gpu/drm/tegra/plane.c
> +++ b/drivers/gpu/drm/tegra/plane.c
> @@ -17,6 +17,9 @@ static void tegra_plane_destroy(struct drm_plane *plane)
>  {
>  	struct tegra_plane *p = to_tegra_plane(plane);
>  
> +	if (p->csc_default)
> +		drm_property_blob_put(p->csc_default);
> +
>  	drm_plane_cleanup(plane);
>  	kfree(p);
>  }
> @@ -38,6 +41,9 @@ static void tegra_plane_reset(struct drm_plane *plane)
>  		plane->state->plane = plane;
>  		plane->state->zpos = p->index;
>  		plane->state->normalized_zpos = p->index;
> +
> +		if (p->csc_default)
> +			state->csc_blob = drm_property_blob_get(p->csc_default);
>  	}
>  }
>  
> @@ -63,12 +69,22 @@ tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
>  	for (i = 0; i < 2; i++)
>  		copy->blending[i] = state->blending[i];
>  
> +	if (state->csc_blob)
> +		copy->csc_blob = drm_property_blob_get(state->csc_blob);
> +	else
> +		copy->csc_blob = NULL;
> +
>  	return &copy->base;
>  }
>  
>  static void tegra_plane_atomic_destroy_state(struct drm_plane *plane,
>  					     struct drm_plane_state *state)
>  {
> +	struct tegra_plane_state *tegra = to_tegra_plane_state(state);
> +
> +	if (tegra->csc_blob)
> +		drm_property_blob_put(tegra->csc_blob);
> +
>  	__drm_atomic_helper_plane_destroy_state(state);
>  	kfree(state);
>  }
> @@ -95,6 +111,23 @@ static int tegra_plane_set_property(struct drm_plane *plane,
>  {
>  	struct tegra_plane_state *tegra_state = to_tegra_plane_state(state);
>  	struct tegra_plane *tegra = to_tegra_plane(plane);
> +	struct drm_property_blob *blob;
> +
> +	if (property == tegra->props.csc_blob) {
> +		blob = drm_property_lookup_blob(plane->dev, value);
> +		if (!blob)
> +			return -EINVAL;
> +
> +		if (blob->length != sizeof(struct drm_tegra_plane_csc_blob)) {
> +			drm_property_blob_put(blob);
> +			return -EINVAL;
> +		}
> +
> +		drm_property_blob_put(tegra_state->csc_blob);
> +		tegra_state->csc_blob = blob;
> +
> +		return 0;
> +	}
>  
>  	if (property == tegra->props.color_key0)
>  		tegra_state->ckey0_enabled = value;
> @@ -118,6 +151,8 @@ static int tegra_plane_get_property(struct drm_plane *plane,
>  		*value = tegra_state->ckey0_enabled;
>  	else if (property == tegra->props.color_key1)
>  		*value = tegra_state->ckey1_enabled;
> +	else if (property == tegra->props.csc_blob)
> +		*value = tegra_state->csc_blob->base.id;
>  	else
>  		return -EINVAL;
>  
> diff --git a/drivers/gpu/drm/tegra/plane.h b/drivers/gpu/drm/tegra/plane.h
> index dafecea73b29..dc9efa7be502 100644
> --- a/drivers/gpu/drm/tegra/plane.h
> +++ b/drivers/gpu/drm/tegra/plane.h
> @@ -23,7 +23,10 @@ struct tegra_plane {
>  	struct {
>  		struct drm_property *color_key0;
>  		struct drm_property *color_key1;
> +		struct drm_property *csc_blob;
>  	} props;
> +
> +	struct drm_property_blob *csc_default;
>  };
>  
>  struct tegra_cursor {
> @@ -51,6 +54,8 @@ struct tegra_plane_state {
>  	u32 format;
>  	u32 swap;
>  
> +	struct drm_property_blob *csc_blob;
> +
>  	/* used for legacy blending support only */
>  	struct tegra_plane_legacy_blending_state blending[2];
>  	bool opaque;
> diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h
> index a5da44209a68..a3054ea7b222 100644
> --- a/include/uapi/drm/tegra_drm.h
> +++ b/include/uapi/drm/tegra_drm.h
> @@ -29,6 +29,17 @@
>  extern "C" {
>  #endif
>  
> +struct drm_tegra_plane_csc_blob {
> +	__u32 yof;
> +	__u32 kyrgb;
> +	__u32 kur;
> +	__u32 kvr;
> +	__u32 kug;
> +	__u32 kvg;
> +	__u32 kub;
> +	__u32 kvb;
> +};
> +
>  #define DRM_TEGRA_GEM_CREATE_TILED     (1 << 0)
>  #define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1)
>  #define DRM_TEGRA_GEM_CREATE_SCATTERED (1 << 2)
> -- 
> 2.17.0
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v1 4/4] drm/tegra: plane: Add custom CSC BLOB property
@ 2018-04-17  9:01     ` Daniel Vetter
  0 siblings, 0 replies; 15+ messages in thread
From: Daniel Vetter @ 2018-04-17  9:01 UTC (permalink / raw)
  To: Dmitry Osipenko; +Cc: Thierry Reding, linux-tegra, linux-kernel, dri-devel

On Mon, Apr 16, 2018 at 03:16:28PM +0300, Dmitry Osipenko wrote:
> This new property allows userspace to apply custom color conversion
> coefficients per plane, making possible to utilize display controller
> for color adjustments of a video overlay.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>

Same here, this needs corresponding userspace:

https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#open-source-userspace-requirements

And again there's even more people who discussed extending the existing
color management support for crtcs to planes. I think we definitely want a
standard interface for this, not each driver doing their own thing.
-Daniel

> ---
>  drivers/gpu/drm/tegra/dc.c    | 86 +++++++++++++++++++++++++++++++----
>  drivers/gpu/drm/tegra/dc.h    | 11 +++++
>  drivers/gpu/drm/tegra/plane.c | 35 ++++++++++++++
>  drivers/gpu/drm/tegra/plane.h |  5 ++
>  include/uapi/drm/tegra_drm.h  | 11 +++++
>  5 files changed, 139 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> index b19e954a223f..24a1317871d4 100644
> --- a/drivers/gpu/drm/tegra/dc.c
> +++ b/drivers/gpu/drm/tegra/dc.c
> @@ -435,15 +435,15 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
>  	value = WIN_ENABLE;
>  
>  	if (yuv) {
> -		/* setup default colorspace conversion coefficients */
> -		tegra_plane_writel(plane, 0x00f0, DC_WIN_CSC_YOF);
> -		tegra_plane_writel(plane, 0x012a, DC_WIN_CSC_KYRGB);
> -		tegra_plane_writel(plane, 0x0000, DC_WIN_CSC_KUR);
> -		tegra_plane_writel(plane, 0x0198, DC_WIN_CSC_KVR);
> -		tegra_plane_writel(plane, 0x039b, DC_WIN_CSC_KUG);
> -		tegra_plane_writel(plane, 0x032f, DC_WIN_CSC_KVG);
> -		tegra_plane_writel(plane, 0x0204, DC_WIN_CSC_KUB);
> -		tegra_plane_writel(plane, 0x0000, DC_WIN_CSC_KVB);
> +		/* setup colorspace conversion coefficients */
> +		tegra_plane_writel(plane, window->csc.yof, DC_WIN_CSC_YOF);
> +		tegra_plane_writel(plane, window->csc.kyrgb, DC_WIN_CSC_KYRGB);
> +		tegra_plane_writel(plane, window->csc.kur, DC_WIN_CSC_KUR);
> +		tegra_plane_writel(plane, window->csc.kvr, DC_WIN_CSC_KVR);
> +		tegra_plane_writel(plane, window->csc.kug, DC_WIN_CSC_KUG);
> +		tegra_plane_writel(plane, window->csc.kvg, DC_WIN_CSC_KVG);
> +		tegra_plane_writel(plane, window->csc.kub, DC_WIN_CSC_KUB);
> +		tegra_plane_writel(plane, window->csc.kvb, DC_WIN_CSC_KVB);
>  
>  		value |= CSC_ENABLE;
>  	} else if (window->bits_per_pixel < 24) {
> @@ -624,6 +624,7 @@ static void tegra_plane_atomic_update(struct drm_plane *plane,
>  	struct drm_framebuffer *fb = plane->state->fb;
>  	struct tegra_plane *p = to_tegra_plane(plane);
>  	struct tegra_dc_window window;
> +	const struct drm_tegra_plane_csc_blob *csc;
>  	unsigned int i;
>  
>  	/* rien ne va plus */
> @@ -665,6 +666,28 @@ static void tegra_plane_atomic_update(struct drm_plane *plane,
>  			window.stride[i] = fb->pitches[i];
>  	}
>  
> +	if (state->csc_blob) {
> +		csc = state->csc_blob->data;
> +
> +		window.csc.yof = csc->yof;
> +		window.csc.kyrgb = csc->kyrgb;
> +		window.csc.kur = csc->kur;
> +		window.csc.kvr = csc->kvr;
> +		window.csc.kug = csc->kug;
> +		window.csc.kvg = csc->kvg;
> +		window.csc.kub = csc->kub;
> +		window.csc.kvb = csc->kvb;
> +	} else {
> +		window.csc.yof = 0x00f0;
> +		window.csc.kyrgb = 0x012a;
> +		window.csc.kur = 0x0000;
> +		window.csc.kvr = 0x0198;
> +		window.csc.kug = 0x039b;
> +		window.csc.kvg = 0x032f;
> +		window.csc.kub = 0x0204;
> +		window.csc.kvb = 0x0000;
> +	}
> +
>  	tegra_dc_setup_window(p, &window);
>  }
>  
> @@ -776,6 +799,42 @@ static void tegra_plane_create_legacy_properties(struct tegra_plane *plane,
>  	dev_err(plane->dc->dev, "failed to create legacy plane properties\n");
>  }
>  
> +static void tegra_plane_create_csc_property(struct tegra_plane *plane)
> +{
> +	/* set default colorspace conversion coefficients to ITU-R BT.601 */
> +	struct drm_tegra_plane_csc_blob csc_bt601 = {
> +		.yof   = 0x00f0,
> +		.kyrgb = 0x012a,
> +		.kur   = 0x0000,
> +		.kvr   = 0x0198,
> +		.kug   = 0x039b,
> +		.kvg   = 0x032f,
> +		.kub   = 0x0204,
> +		.kvb   = 0x0000,
> +	};
> +	struct drm_property_blob *blob;
> +
> +	blob = drm_property_create_blob(plane->base.dev, sizeof(csc_bt601),
> +					&csc_bt601);
> +	if (!blob) {
> +		dev_err(plane->dc->dev, "failed to create CSC BLOB\n");
> +		return;
> +	}
> +
> +	plane->props.csc_blob = drm_property_create(
> +		plane->base.dev, DRM_MODE_PROP_BLOB, "YUV to RGB CSC", 0);
> +
> +	if (!plane->props.csc_blob) {
> +		dev_err(plane->dc->dev, "failed to create CSC property\n");
> +		drm_property_blob_put(blob);
> +		return;
> +	}
> +
> +	drm_object_attach_property(&plane->base.base, plane->props.csc_blob, 0);
> +
> +	plane->csc_default = blob;
> +}
> +
>  static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
>  						    struct tegra_dc *dc)
>  {
> @@ -814,6 +873,9 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
>  	if (dc->soc->legacy_blending)
>  		tegra_plane_create_legacy_properties(plane, drm);
>  
> +	if (dc->soc->has_win_a_csc)
> +		tegra_plane_create_csc_property(plane);
> +
>  	return &plane->base;
>  }
>  
> @@ -1092,6 +1154,7 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
>  
>  	drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
>  	drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255);
> +	tegra_plane_create_csc_property(plane);
>  
>  	return &plane->base;
>  }
> @@ -2269,6 +2332,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
>  	.num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats),
>  	.overlay_formats = tegra20_overlay_formats,
>  	.modifiers = tegra20_modifiers,
> +	.has_win_a_csc = false,
>  };
>  
>  static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
> @@ -2287,6 +2351,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
>  	.num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats),
>  	.overlay_formats = tegra20_overlay_formats,
>  	.modifiers = tegra20_modifiers,
> +	.has_win_a_csc = false,
>  };
>  
>  static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
> @@ -2305,6 +2370,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
>  	.num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats),
>  	.overlay_formats = tegra114_overlay_formats,
>  	.modifiers = tegra20_modifiers,
> +	.has_win_a_csc = true,
>  };
>  
>  static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
> @@ -2323,6 +2389,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
>  	.num_overlay_formats = ARRAY_SIZE(tegra124_overlay_formats),
>  	.overlay_formats = tegra124_overlay_formats,
>  	.modifiers = tegra124_modifiers,
> +	.has_win_a_csc = true,
>  };
>  
>  static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
> @@ -2341,6 +2408,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
>  	.num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats),
>  	.overlay_formats = tegra114_overlay_formats,
>  	.modifiers = tegra124_modifiers,
> +	.has_win_a_csc = true,
>  };
>  
>  static const struct tegra_windowgroup_soc tegra186_dc_wgrps[] = {
> diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
> index 3913d047abac..23439eaaa4de 100644
> --- a/drivers/gpu/drm/tegra/dc.h
> +++ b/drivers/gpu/drm/tegra/dc.h
> @@ -77,6 +77,7 @@ struct tegra_dc_soc_info {
>  	const u32 *overlay_formats;
>  	unsigned int num_overlay_formats;
>  	const u64 *modifiers;
> +	bool has_win_a_csc;
>  };
>  
>  struct tegra_dc {
> @@ -152,6 +153,16 @@ struct tegra_dc_window {
>  		unsigned int w;
>  		unsigned int h;
>  	} dst;
> +	struct {
> +		unsigned int yof;
> +		unsigned int kyrgb;
> +		unsigned int kur;
> +		unsigned int kvr;
> +		unsigned int kug;
> +		unsigned int kvg;
> +		unsigned int kub;
> +		unsigned int kvb;
> +	} csc;
>  	unsigned int bits_per_pixel;
>  	unsigned int stride[2];
>  	unsigned long base[3];
> diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c
> index 4d794f2b44df..c5733c5a66e9 100644
> --- a/drivers/gpu/drm/tegra/plane.c
> +++ b/drivers/gpu/drm/tegra/plane.c
> @@ -17,6 +17,9 @@ static void tegra_plane_destroy(struct drm_plane *plane)
>  {
>  	struct tegra_plane *p = to_tegra_plane(plane);
>  
> +	if (p->csc_default)
> +		drm_property_blob_put(p->csc_default);
> +
>  	drm_plane_cleanup(plane);
>  	kfree(p);
>  }
> @@ -38,6 +41,9 @@ static void tegra_plane_reset(struct drm_plane *plane)
>  		plane->state->plane = plane;
>  		plane->state->zpos = p->index;
>  		plane->state->normalized_zpos = p->index;
> +
> +		if (p->csc_default)
> +			state->csc_blob = drm_property_blob_get(p->csc_default);
>  	}
>  }
>  
> @@ -63,12 +69,22 @@ tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
>  	for (i = 0; i < 2; i++)
>  		copy->blending[i] = state->blending[i];
>  
> +	if (state->csc_blob)
> +		copy->csc_blob = drm_property_blob_get(state->csc_blob);
> +	else
> +		copy->csc_blob = NULL;
> +
>  	return &copy->base;
>  }
>  
>  static void tegra_plane_atomic_destroy_state(struct drm_plane *plane,
>  					     struct drm_plane_state *state)
>  {
> +	struct tegra_plane_state *tegra = to_tegra_plane_state(state);
> +
> +	if (tegra->csc_blob)
> +		drm_property_blob_put(tegra->csc_blob);
> +
>  	__drm_atomic_helper_plane_destroy_state(state);
>  	kfree(state);
>  }
> @@ -95,6 +111,23 @@ static int tegra_plane_set_property(struct drm_plane *plane,
>  {
>  	struct tegra_plane_state *tegra_state = to_tegra_plane_state(state);
>  	struct tegra_plane *tegra = to_tegra_plane(plane);
> +	struct drm_property_blob *blob;
> +
> +	if (property == tegra->props.csc_blob) {
> +		blob = drm_property_lookup_blob(plane->dev, value);
> +		if (!blob)
> +			return -EINVAL;
> +
> +		if (blob->length != sizeof(struct drm_tegra_plane_csc_blob)) {
> +			drm_property_blob_put(blob);
> +			return -EINVAL;
> +		}
> +
> +		drm_property_blob_put(tegra_state->csc_blob);
> +		tegra_state->csc_blob = blob;
> +
> +		return 0;
> +	}
>  
>  	if (property == tegra->props.color_key0)
>  		tegra_state->ckey0_enabled = value;
> @@ -118,6 +151,8 @@ static int tegra_plane_get_property(struct drm_plane *plane,
>  		*value = tegra_state->ckey0_enabled;
>  	else if (property == tegra->props.color_key1)
>  		*value = tegra_state->ckey1_enabled;
> +	else if (property == tegra->props.csc_blob)
> +		*value = tegra_state->csc_blob->base.id;
>  	else
>  		return -EINVAL;
>  
> diff --git a/drivers/gpu/drm/tegra/plane.h b/drivers/gpu/drm/tegra/plane.h
> index dafecea73b29..dc9efa7be502 100644
> --- a/drivers/gpu/drm/tegra/plane.h
> +++ b/drivers/gpu/drm/tegra/plane.h
> @@ -23,7 +23,10 @@ struct tegra_plane {
>  	struct {
>  		struct drm_property *color_key0;
>  		struct drm_property *color_key1;
> +		struct drm_property *csc_blob;
>  	} props;
> +
> +	struct drm_property_blob *csc_default;
>  };
>  
>  struct tegra_cursor {
> @@ -51,6 +54,8 @@ struct tegra_plane_state {
>  	u32 format;
>  	u32 swap;
>  
> +	struct drm_property_blob *csc_blob;
> +
>  	/* used for legacy blending support only */
>  	struct tegra_plane_legacy_blending_state blending[2];
>  	bool opaque;
> diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h
> index a5da44209a68..a3054ea7b222 100644
> --- a/include/uapi/drm/tegra_drm.h
> +++ b/include/uapi/drm/tegra_drm.h
> @@ -29,6 +29,17 @@
>  extern "C" {
>  #endif
>  
> +struct drm_tegra_plane_csc_blob {
> +	__u32 yof;
> +	__u32 kyrgb;
> +	__u32 kur;
> +	__u32 kvr;
> +	__u32 kug;
> +	__u32 kvg;
> +	__u32 kub;
> +	__u32 kvb;
> +};
> +
>  #define DRM_TEGRA_GEM_CREATE_TILED     (1 << 0)
>  #define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1)
>  #define DRM_TEGRA_GEM_CREATE_SCATTERED (1 << 2)
> -- 
> 2.17.0
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v1 3/4] drm/tegra: plane: Add custom colorkey properties for older Tegra's
  2018-04-17  9:00     ` Daniel Vetter
  (?)
@ 2018-04-17 17:08     ` Dmitry Osipenko
  2018-04-17 17:21       ` Dmitry Osipenko
  2018-04-20  7:31         ` Daniel Vetter
  -1 siblings, 2 replies; 15+ messages in thread
From: Dmitry Osipenko @ 2018-04-17 17:08 UTC (permalink / raw)
  To: Thierry Reding, linux-tegra, linux-kernel, dri-devel

On 17.04.2018 12:00, Daniel Vetter wrote:
> On Mon, Apr 16, 2018 at 03:16:27PM +0300, Dmitry Osipenko wrote:
>> Colorkey'ing allows to draw on top of overlapping planes, like for example
>> on top of a video plane. Older Tegra's have a limited colorkey'ing
>> capability such that blending features are reduced when colorkey'ing is
>> enabled. In particular dependent weighting isn't possible, meaning that
>> cursors plane can't be displayed properly. In most cases it is more useful
>> to display content on top of video overlay, sacrificing mouse cursor
>> in the area of three planes intersection with colorkey mismatch. This
>> patch adds a custom colorkey properties to primary plane and CRTC's of
>> older Tegra's, allowing userspace like Opentegra Xorg driver to implement
>> colorkey support for XVideo extension.
>>
>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> 
> Since this is your own uapi, where's the userspace per
> 
> https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#open-source-userspace-requirements

Userspace patches for colorkey and CSC utilization are in my personal github
repos for now [0][1]. The longterm plan is to get Opentegra driver / libdrm bits
of [2] to repos on freedesktop.org, which should be considered as upstream. We
have everything depending on libdrm-tegra and it is currently on hold because of
upcoming massive rework of Tegra DRM UAPI with further de-staging of jobs
submission UAPI, that reworking should start with 4.18 kernel.

For now I wanted to get initial input on the patches. Once everyone is in
agreement, I'd like to have colorkey / CSC supported by the upstream DRM driver,
so that at least grate-driver projects could utilize them right now.

> And why wo we need a tegra-private colorkey property here? I thought
> other's have been discussing this in the context of other drivers.

At least older Tegra's have limitations in regards to colorkey, like planes
blending capabilities are reduced a lot when colorkey'ing is enabled. I'm not
sure whether we'd want to have it as a generic property, because generic
userspace should be aware of those limitations, otherwise there is a good chance
to get undesirable result using colorkey. Though I'm not really sure how widely
colorkey property could be utilize by userspace and what kind of applications
that userspace could have for it, maybe having colorkey as a generic property
would be good enough after all.

I've looked up the DRI ML archive and seems the most recent colorkey-related
patches are [3]. These patches are a bit odd to me because by generic property I
assume a property that is HW-agnostic and the patchset does opposite to it.
Maybe I'm misunderstanding what is meant by 'generic' property then? Anyway I've
applied [3] and made Tegra to use that generic property, it works fine. I'll be
happy to switch to a generic property if we'll consider that it is a viable way.

[0] https://github.com/digetx/xf86-video-opentegra/commits/ckey
[1] https://github.com/digetx/libvdpau-tegra/commits/ckey
[2] https://github.com/grate-driver
[3] https://patchwork.kernel.org/patch/10117593/

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v1 3/4] drm/tegra: plane: Add custom colorkey properties for older Tegra's
  2018-04-17 17:08     ` Dmitry Osipenko
@ 2018-04-17 17:21       ` Dmitry Osipenko
  2018-04-20  7:31         ` Daniel Vetter
  1 sibling, 0 replies; 15+ messages in thread
From: Dmitry Osipenko @ 2018-04-17 17:21 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Thierry Reding, linux-tegra, linux-kernel, dri-devel

Daniel,

Oddly thunderbird and gmail webinterface are refusing to add your 'Daniel Vetter
<daniel@ffwll.ch>' to list of recipients automatically.

On 17.04.2018 20:08, Dmitry Osipenko wrote:
> On 17.04.2018 12:00, Daniel Vetter wrote:
>> On Mon, Apr 16, 2018 at 03:16:27PM +0300, Dmitry Osipenko wrote:
>>> Colorkey'ing allows to draw on top of overlapping planes, like for example
>>> on top of a video plane. Older Tegra's have a limited colorkey'ing
>>> capability such that blending features are reduced when colorkey'ing is
>>> enabled. In particular dependent weighting isn't possible, meaning that
>>> cursors plane can't be displayed properly. In most cases it is more useful
>>> to display content on top of video overlay, sacrificing mouse cursor
>>> in the area of three planes intersection with colorkey mismatch. This
>>> patch adds a custom colorkey properties to primary plane and CRTC's of
>>> older Tegra's, allowing userspace like Opentegra Xorg driver to implement
>>> colorkey support for XVideo extension.
>>>
>>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>>
>> Since this is your own uapi, where's the userspace per
>>
>> https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#open-source-userspace-requirements
> 
> Userspace patches for colorkey and CSC utilization are in my personal github
> repos for now [0][1]. The longterm plan is to get Opentegra driver / libdrm bits
> of [2] to repos on freedesktop.org, which should be considered as upstream. We
> have everything depending on libdrm-tegra and it is currently on hold because of
> upcoming massive rework of Tegra DRM UAPI with further de-staging of jobs
> submission UAPI, that reworking should start with 4.18 kernel.
> 
> For now I wanted to get initial input on the patches. Once everyone is in
> agreement, I'd like to have colorkey / CSC supported by the upstream DRM driver,
> so that at least grate-driver projects could utilize them right now.
> 
>> And why wo we need a tegra-private colorkey property here? I thought
>> other's have been discussing this in the context of other drivers.
> 
> At least older Tegra's have limitations in regards to colorkey, like planes
> blending capabilities are reduced a lot when colorkey'ing is enabled. I'm not
> sure whether we'd want to have it as a generic property, because generic
> userspace should be aware of those limitations, otherwise there is a good chance
> to get undesirable result using colorkey. Though I'm not really sure how widely
> colorkey property could be utilize by userspace and what kind of applications
> that userspace could have for it, maybe having colorkey as a generic property
> would be good enough after all.
> 
> I've looked up the DRI ML archive and seems the most recent colorkey-related
> patches are [3]. These patches are a bit odd to me because by generic property I
> assume a property that is HW-agnostic and the patchset does opposite to it.
> Maybe I'm misunderstanding what is meant by 'generic' property then? Anyway I've
> applied [3] and made Tegra to use that generic property, it works fine. I'll be
> happy to switch to a generic property if we'll consider that it is a viable way.
> 
> [0] https://github.com/digetx/xf86-video-opentegra/commits/ckey
> [1] https://github.com/digetx/libvdpau-tegra/commits/ckey
> [2] https://github.com/grate-driver
> [3] https://patchwork.kernel.org/patch/10117593/
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v1 4/4] drm/tegra: plane: Add custom CSC BLOB property
  2018-04-17  9:01     ` Daniel Vetter
  (?)
@ 2018-04-17 17:31     ` Dmitry Osipenko
  2018-04-20  7:34       ` Daniel Vetter
  -1 siblings, 1 reply; 15+ messages in thread
From: Dmitry Osipenko @ 2018-04-17 17:31 UTC (permalink / raw)
  To: Thierry Reding, Daniel Vetter; +Cc: linux-tegra, linux-kernel, dri-devel

On 17.04.2018 12:01, Daniel Vetter wrote:
> On Mon, Apr 16, 2018 at 03:16:28PM +0300, Dmitry Osipenko wrote:
>> This new property allows userspace to apply custom color conversion
>> coefficients per plane, making possible to utilize display controller
>> for color adjustments of a video overlay.
>>
>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> 
> Same here, this needs corresponding userspace:
> 
> https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#open-source-userspace-requirements
> 
> And again there's even more people who discussed extending the existing
> color management support for crtcs to planes. I think we definitely want a
> standard interface for this, not each driver doing their own thing.

Could you please point me to where that discussion is happening?

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v1 3/4] drm/tegra: plane: Add custom colorkey properties for older Tegra's
  2018-04-17 17:08     ` Dmitry Osipenko
@ 2018-04-20  7:31         ` Daniel Vetter
  2018-04-20  7:31         ` Daniel Vetter
  1 sibling, 0 replies; 15+ messages in thread
From: Daniel Vetter @ 2018-04-20  7:31 UTC (permalink / raw)
  To: Dmitry Osipenko; +Cc: linux-tegra, Thierry Reding, linux-kernel, dri-devel

On Tue, Apr 17, 2018 at 08:08:27PM +0300, Dmitry Osipenko wrote:
> On 17.04.2018 12:00, Daniel Vetter wrote:
> > On Mon, Apr 16, 2018 at 03:16:27PM +0300, Dmitry Osipenko wrote:
> >> Colorkey'ing allows to draw on top of overlapping planes, like for example
> >> on top of a video plane. Older Tegra's have a limited colorkey'ing
> >> capability such that blending features are reduced when colorkey'ing is
> >> enabled. In particular dependent weighting isn't possible, meaning that
> >> cursors plane can't be displayed properly. In most cases it is more useful
> >> to display content on top of video overlay, sacrificing mouse cursor
> >> in the area of three planes intersection with colorkey mismatch. This
> >> patch adds a custom colorkey properties to primary plane and CRTC's of
> >> older Tegra's, allowing userspace like Opentegra Xorg driver to implement
> >> colorkey support for XVideo extension.
> >>
> >> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> > 
> > Since this is your own uapi, where's the userspace per
> > 
> > https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#open-source-userspace-requirements
> 
> Userspace patches for colorkey and CSC utilization are in my personal github
> repos for now [0][1]. The longterm plan is to get Opentegra driver / libdrm bits
> of [2] to repos on freedesktop.org, which should be considered as upstream. We
> have everything depending on libdrm-tegra and it is currently on hold because of
> upcoming massive rework of Tegra DRM UAPI with further de-staging of jobs
> submission UAPI, that reworking should start with 4.18 kernel.
> 
> For now I wanted to get initial input on the patches. Once everyone is in
> agreement, I'd like to have colorkey / CSC supported by the upstream DRM driver,
> so that at least grate-driver projects could utilize them right now.
> 
> > And why wo we need a tegra-private colorkey property here? I thought
> > other's have been discussing this in the context of other drivers.
> 
> At least older Tegra's have limitations in regards to colorkey, like planes
> blending capabilities are reduced a lot when colorkey'ing is enabled. I'm not
> sure whether we'd want to have it as a generic property, because generic
> userspace should be aware of those limitations, otherwise there is a good chance
> to get undesirable result using colorkey. Though I'm not really sure how widely
> colorkey property could be utilize by userspace and what kind of applications
> that userspace could have for it, maybe having colorkey as a generic property
> would be good enough after all.
> 
> I've looked up the DRI ML archive and seems the most recent colorkey-related
> patches are [3]. These patches are a bit odd to me because by generic property I
> assume a property that is HW-agnostic and the patchset does opposite to it.
> Maybe I'm misunderstanding what is meant by 'generic' property then? Anyway I've
> applied [3] and made Tegra to use that generic property, it works fine. I'll be
> happy to switch to a generic property if we'll consider that it is a viable way.
> 
> [0] https://github.com/digetx/xf86-video-opentegra/commits/ckey
> [1] https://github.com/digetx/libvdpau-tegra/commits/ckey
> [2] https://github.com/grate-driver
> [3] https://patchwork.kernel.org/patch/10117593/

Yes that's the patches I meant, thanks for surfacing them.

Please work together with Laurent, Maxime and Boris on this (jump on that
thread and Cc them on your own patches for the next round). And pls also
work together on a common userspace for this.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v1 3/4] drm/tegra: plane: Add custom colorkey properties for older Tegra's
@ 2018-04-20  7:31         ` Daniel Vetter
  0 siblings, 0 replies; 15+ messages in thread
From: Daniel Vetter @ 2018-04-20  7:31 UTC (permalink / raw)
  To: Dmitry Osipenko; +Cc: Thierry Reding, linux-tegra, linux-kernel, dri-devel

On Tue, Apr 17, 2018 at 08:08:27PM +0300, Dmitry Osipenko wrote:
> On 17.04.2018 12:00, Daniel Vetter wrote:
> > On Mon, Apr 16, 2018 at 03:16:27PM +0300, Dmitry Osipenko wrote:
> >> Colorkey'ing allows to draw on top of overlapping planes, like for example
> >> on top of a video plane. Older Tegra's have a limited colorkey'ing
> >> capability such that blending features are reduced when colorkey'ing is
> >> enabled. In particular dependent weighting isn't possible, meaning that
> >> cursors plane can't be displayed properly. In most cases it is more useful
> >> to display content on top of video overlay, sacrificing mouse cursor
> >> in the area of three planes intersection with colorkey mismatch. This
> >> patch adds a custom colorkey properties to primary plane and CRTC's of
> >> older Tegra's, allowing userspace like Opentegra Xorg driver to implement
> >> colorkey support for XVideo extension.
> >>
> >> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> > 
> > Since this is your own uapi, where's the userspace per
> > 
> > https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#open-source-userspace-requirements
> 
> Userspace patches for colorkey and CSC utilization are in my personal github
> repos for now [0][1]. The longterm plan is to get Opentegra driver / libdrm bits
> of [2] to repos on freedesktop.org, which should be considered as upstream. We
> have everything depending on libdrm-tegra and it is currently on hold because of
> upcoming massive rework of Tegra DRM UAPI with further de-staging of jobs
> submission UAPI, that reworking should start with 4.18 kernel.
> 
> For now I wanted to get initial input on the patches. Once everyone is in
> agreement, I'd like to have colorkey / CSC supported by the upstream DRM driver,
> so that at least grate-driver projects could utilize them right now.
> 
> > And why wo we need a tegra-private colorkey property here? I thought
> > other's have been discussing this in the context of other drivers.
> 
> At least older Tegra's have limitations in regards to colorkey, like planes
> blending capabilities are reduced a lot when colorkey'ing is enabled. I'm not
> sure whether we'd want to have it as a generic property, because generic
> userspace should be aware of those limitations, otherwise there is a good chance
> to get undesirable result using colorkey. Though I'm not really sure how widely
> colorkey property could be utilize by userspace and what kind of applications
> that userspace could have for it, maybe having colorkey as a generic property
> would be good enough after all.
> 
> I've looked up the DRI ML archive and seems the most recent colorkey-related
> patches are [3]. These patches are a bit odd to me because by generic property I
> assume a property that is HW-agnostic and the patchset does opposite to it.
> Maybe I'm misunderstanding what is meant by 'generic' property then? Anyway I've
> applied [3] and made Tegra to use that generic property, it works fine. I'll be
> happy to switch to a generic property if we'll consider that it is a viable way.
> 
> [0] https://github.com/digetx/xf86-video-opentegra/commits/ckey
> [1] https://github.com/digetx/libvdpau-tegra/commits/ckey
> [2] https://github.com/grate-driver
> [3] https://patchwork.kernel.org/patch/10117593/

Yes that's the patches I meant, thanks for surfacing them.

Please work together with Laurent, Maxime and Boris on this (jump on that
thread and Cc them on your own patches for the next round). And pls also
work together on a common userspace for this.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v1 4/4] drm/tegra: plane: Add custom CSC BLOB property
  2018-04-17 17:31     ` Dmitry Osipenko
@ 2018-04-20  7:34       ` Daniel Vetter
  0 siblings, 0 replies; 15+ messages in thread
From: Daniel Vetter @ 2018-04-20  7:34 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Daniel Vetter, linux-tegra, linux-kernel, dri-devel

On Tue, Apr 17, 2018 at 08:31:11PM +0300, Dmitry Osipenko wrote:
> On 17.04.2018 12:01, Daniel Vetter wrote:
> > On Mon, Apr 16, 2018 at 03:16:28PM +0300, Dmitry Osipenko wrote:
> >> This new property allows userspace to apply custom color conversion
> >> coefficients per plane, making possible to utilize display controller
> >> for color adjustments of a video overlay.
> >>
> >> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> > 
> > Same here, this needs corresponding userspace:
> > 
> > https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#open-source-userspace-requirements
> > 
> > And again there's even more people who discussed extending the existing
> > color management support for crtcs to planes. I think we definitely want a
> > standard interface for this, not each driver doing their own thing.
> 
> Could you please point me to where that discussion is happening?

https://patchwork.freedesktop.org/patch/209469/

is one I've found, but I think there's other efforts.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2018-04-20  7:34 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-16 12:16 [PATCH v1 0/4] More DRM object properties on Tegra Dmitry Osipenko
2018-04-16 12:16 ` [PATCH v1 1/4] drm/tegra: plane: Implement zPos plane property for older Tegra's Dmitry Osipenko
2018-04-16 12:16 ` [PATCH v1 2/4] drm/tegra: dc: Rename supports_blending to legacy_blending Dmitry Osipenko
2018-04-16 12:16 ` [PATCH v1 3/4] drm/tegra: plane: Add custom colorkey properties for older Tegra's Dmitry Osipenko
2018-04-17  9:00   ` Daniel Vetter
2018-04-17  9:00     ` Daniel Vetter
2018-04-17 17:08     ` Dmitry Osipenko
2018-04-17 17:21       ` Dmitry Osipenko
2018-04-20  7:31       ` Daniel Vetter
2018-04-20  7:31         ` Daniel Vetter
2018-04-16 12:16 ` [PATCH v1 4/4] drm/tegra: plane: Add custom CSC BLOB property Dmitry Osipenko
2018-04-17  9:01   ` Daniel Vetter
2018-04-17  9:01     ` Daniel Vetter
2018-04-17 17:31     ` Dmitry Osipenko
2018-04-20  7:34       ` Daniel Vetter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.