diff mbox

[08/10] drm/imx: ipuv3-plane: add support for YUV 4:2:2 and 4:4:4, NV12, and NV16 formats

Message ID 1476872477-29493-8-git-send-email-p.zabel@pengutronix.de (mailing list archive)
State New, archived
Headers show

Commit Message

Philipp Zabel Oct. 19, 2016, 10:21 a.m. UTC
Hook up support for DRM_FORMAT_YUV422, DRM_FORMAT_YVU422,
DRM_FORMAT_YUV444, DRM_FORMAT_YVU444, DRM_FORMAT_NV12,
and DRM_FORMAT_NV16.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
Changes since v1:
 - Make UBO/VBO swap for YVU formats more obvious in ipu_plane_atomic_update
---
 drivers/gpu/drm/imx/ipuv3-plane.c | 60 ++++++++++++++++++++++++++++++---------
 1 file changed, 47 insertions(+), 13 deletions(-)

Comments

Ying Liu Oct. 20, 2016, 6:21 a.m. UTC | #1
On Wed, Oct 19, 2016 at 6:21 PM, Philipp Zabel <p.zabel@pengutronix.de> wrote:
> Hook up support for DRM_FORMAT_YUV422, DRM_FORMAT_YVU422,
> DRM_FORMAT_YUV444, DRM_FORMAT_YVU444, DRM_FORMAT_NV12,
> and DRM_FORMAT_NV16.
>
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>

Acked-by: Liu Ying <gnuiyl@gmail.com>

> ---
> Changes since v1:
>  - Make UBO/VBO swap for YVU formats more obvious in ipu_plane_atomic_update
> ---
>  drivers/gpu/drm/imx/ipuv3-plane.c | 60 ++++++++++++++++++++++++++++++---------
>  1 file changed, 47 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
> index 52784cb..6a97e396 100644
> --- a/drivers/gpu/drm/imx/ipuv3-plane.c
> +++ b/drivers/gpu/drm/imx/ipuv3-plane.c
> @@ -50,6 +50,12 @@ static const uint32_t ipu_plane_formats[] = {
>         DRM_FORMAT_YVYU,
>         DRM_FORMAT_YUV420,
>         DRM_FORMAT_YVU420,
> +       DRM_FORMAT_YUV422,
> +       DRM_FORMAT_YVU422,
> +       DRM_FORMAT_YUV444,
> +       DRM_FORMAT_YVU444,
> +       DRM_FORMAT_NV12,
> +       DRM_FORMAT_NV16,
>         DRM_FORMAT_RGB565,
>  };
>
> @@ -292,6 +298,10 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
>         switch (fb->pixel_format) {
>         case DRM_FORMAT_YUV420:
>         case DRM_FORMAT_YVU420:
> +       case DRM_FORMAT_YUV422:
> +       case DRM_FORMAT_YVU422:
> +       case DRM_FORMAT_YUV444:
> +       case DRM_FORMAT_YVU444:
>                 /*
>                  * Multiplanar formats have to meet the following restrictions:
>                  * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
> @@ -300,25 +310,34 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
>                  * - Only EBA may be changed while scanout is active
>                  * - The strides of U and V planes must be identical.
>                  */
> -               ubo = drm_plane_state_to_ubo(state);
>                 vbo = drm_plane_state_to_vbo(state);
>
> -               if ((ubo & 0x7) || (vbo & 0x7))
> -                       return -EINVAL;
> -
> -               if ((ubo > 0xfffff8) || (vbo > 0xfffff8))
> +               if (vbo & 0x7 || vbo > 0xfffff8)
>                         return -EINVAL;
>
>                 if (old_fb && (fb->pixel_format == old_fb->pixel_format)) {
> -                       old_ubo = drm_plane_state_to_ubo(old_state);
>                         old_vbo = drm_plane_state_to_vbo(old_state);
> -                       if (ubo != old_ubo || vbo != old_vbo)
> +                       if (vbo != old_vbo)
>                                 crtc_state->mode_changed = true;
>                 }
>
>                 if (fb->pitches[1] != fb->pitches[2])
>                         return -EINVAL;
>
> +               /* fall-through */
> +       case DRM_FORMAT_NV12:
> +       case DRM_FORMAT_NV16:
> +               ubo = drm_plane_state_to_ubo(state);
> +
> +               if (ubo & 0x7 || ubo > 0xfffff8)
> +                       return -EINVAL;
> +
> +               if (old_fb && (fb->pixel_format == old_fb->pixel_format)) {
> +                       old_ubo = drm_plane_state_to_ubo(old_state);
> +                       if (ubo != old_ubo)
> +                               crtc_state->mode_changed = true;
> +               }
> +
>                 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384)
>                         return -EINVAL;
>
> @@ -409,20 +428,35 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
>         switch (fb->pixel_format) {
>         case DRM_FORMAT_YUV420:
>         case DRM_FORMAT_YVU420:
> +       case DRM_FORMAT_YUV422:
> +       case DRM_FORMAT_YVU422:
> +       case DRM_FORMAT_YUV444:
> +       case DRM_FORMAT_YVU444:
>                 ubo = drm_plane_state_to_ubo(state);
>                 vbo = drm_plane_state_to_vbo(state);
> +               if (fb->pixel_format == DRM_FORMAT_YVU420 ||
> +                   fb->pixel_format == DRM_FORMAT_YVU422 ||
> +                   fb->pixel_format == DRM_FORMAT_YVU444)
> +                       swap(ubo, vbo);
>
> -               if (fb->pixel_format == DRM_FORMAT_YUV420)
> -                       ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
> -                                                     fb->pitches[1], ubo, vbo);
> -               else
> -                       ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
> -                                                     fb->pitches[1], vbo, ubo);
> +               ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
> +                                             fb->pitches[1], ubo, vbo);
>
>                 dev_dbg(ipu_plane->base.dev->dev,
>                         "phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo,
>                         state->src_x >> 16, state->src_y >> 16);
>                 break;
> +       case DRM_FORMAT_NV12:
> +       case DRM_FORMAT_NV16:
> +               ubo = drm_plane_state_to_ubo(state);
> +
> +               ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
> +                                             fb->pitches[1], ubo, ubo);
> +
> +               dev_dbg(ipu_plane->base.dev->dev,
> +                       "phy = %lu %lu, x = %d, y = %d", eba, ubo,
> +                       state->src_x >> 16, state->src_y >> 16);
> +               break;
>         default:
>                 dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d",
>                         eba, state->src_x >> 16, state->src_y >> 16);
> --
> 2.9.3
>
diff mbox

Patch

diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index 52784cb..6a97e396 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -50,6 +50,12 @@  static const uint32_t ipu_plane_formats[] = {
 	DRM_FORMAT_YVYU,
 	DRM_FORMAT_YUV420,
 	DRM_FORMAT_YVU420,
+	DRM_FORMAT_YUV422,
+	DRM_FORMAT_YVU422,
+	DRM_FORMAT_YUV444,
+	DRM_FORMAT_YVU444,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV16,
 	DRM_FORMAT_RGB565,
 };
 
@@ -292,6 +298,10 @@  static int ipu_plane_atomic_check(struct drm_plane *plane,
 	switch (fb->pixel_format) {
 	case DRM_FORMAT_YUV420:
 	case DRM_FORMAT_YVU420:
+	case DRM_FORMAT_YUV422:
+	case DRM_FORMAT_YVU422:
+	case DRM_FORMAT_YUV444:
+	case DRM_FORMAT_YVU444:
 		/*
 		 * Multiplanar formats have to meet the following restrictions:
 		 * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
@@ -300,25 +310,34 @@  static int ipu_plane_atomic_check(struct drm_plane *plane,
 		 * - Only EBA may be changed while scanout is active
 		 * - The strides of U and V planes must be identical.
 		 */
-		ubo = drm_plane_state_to_ubo(state);
 		vbo = drm_plane_state_to_vbo(state);
 
-		if ((ubo & 0x7) || (vbo & 0x7))
-			return -EINVAL;
-
-		if ((ubo > 0xfffff8) || (vbo > 0xfffff8))
+		if (vbo & 0x7 || vbo > 0xfffff8)
 			return -EINVAL;
 
 		if (old_fb && (fb->pixel_format == old_fb->pixel_format)) {
-			old_ubo = drm_plane_state_to_ubo(old_state);
 			old_vbo = drm_plane_state_to_vbo(old_state);
-			if (ubo != old_ubo || vbo != old_vbo)
+			if (vbo != old_vbo)
 				crtc_state->mode_changed = true;
 		}
 
 		if (fb->pitches[1] != fb->pitches[2])
 			return -EINVAL;
 
+		/* fall-through */
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV16:
+		ubo = drm_plane_state_to_ubo(state);
+
+		if (ubo & 0x7 || ubo > 0xfffff8)
+			return -EINVAL;
+
+		if (old_fb && (fb->pixel_format == old_fb->pixel_format)) {
+			old_ubo = drm_plane_state_to_ubo(old_state);
+			if (ubo != old_ubo)
+				crtc_state->mode_changed = true;
+		}
+
 		if (fb->pitches[1] < 1 || fb->pitches[1] > 16384)
 			return -EINVAL;
 
@@ -409,20 +428,35 @@  static void ipu_plane_atomic_update(struct drm_plane *plane,
 	switch (fb->pixel_format) {
 	case DRM_FORMAT_YUV420:
 	case DRM_FORMAT_YVU420:
+	case DRM_FORMAT_YUV422:
+	case DRM_FORMAT_YVU422:
+	case DRM_FORMAT_YUV444:
+	case DRM_FORMAT_YVU444:
 		ubo = drm_plane_state_to_ubo(state);
 		vbo = drm_plane_state_to_vbo(state);
+		if (fb->pixel_format == DRM_FORMAT_YVU420 ||
+		    fb->pixel_format == DRM_FORMAT_YVU422 ||
+		    fb->pixel_format == DRM_FORMAT_YVU444)
+			swap(ubo, vbo);
 
-		if (fb->pixel_format == DRM_FORMAT_YUV420)
-			ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
-						      fb->pitches[1], ubo, vbo);
-		else
-			ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
-						      fb->pitches[1], vbo, ubo);
+		ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
+					      fb->pitches[1], ubo, vbo);
 
 		dev_dbg(ipu_plane->base.dev->dev,
 			"phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo,
 			state->src_x >> 16, state->src_y >> 16);
 		break;
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV16:
+		ubo = drm_plane_state_to_ubo(state);
+
+		ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
+					      fb->pitches[1], ubo, ubo);
+
+		dev_dbg(ipu_plane->base.dev->dev,
+			"phy = %lu %lu, x = %d, y = %d", eba, ubo,
+			state->src_x >> 16, state->src_y >> 16);
+		break;
 	default:
 		dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d",
 			eba, state->src_x >> 16, state->src_y >> 16);