diff mbox series

[6/7] drm/i915/gen11: Program the Y and UV plane for planar mode correctly.

Message ID 20180921173945.6276-7-maarten.lankhorst@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series drm/i915/gen11: Enable planar format support on gen11. | expand

Commit Message

Maarten Lankhorst Sept. 21, 2018, 5:39 p.m. UTC
The UV plane is the master plane that does all color correction etc.
It needs to be programmed with the dimensions for color plane 1 (UV).

The Y plane just feeds the Y pixels to it. Program the scaler from the
master only, and set PLANE_CTL_YUV420_Y_PLANE on the slave plane.

Changes since v1:
- Make a common skl_program_plane, and use it for both plane updates.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h     |  1 +
 drivers/gpu/drm/i915/intel_sprite.c | 50 +++++++++++++++++++++--------
 2 files changed, 38 insertions(+), 13 deletions(-)

Comments

Ville Syrjälä Sept. 21, 2018, 7:01 p.m. UTC | #1
On Fri, Sep 21, 2018 at 07:39:44PM +0200, Maarten Lankhorst wrote:
> The UV plane is the master plane that does all color correction etc.
> It needs to be programmed with the dimensions for color plane 1 (UV).
> 
> The Y plane just feeds the Y pixels to it. Program the scaler from the
> master only, and set PLANE_CTL_YUV420_Y_PLANE on the slave plane.
> 
> Changes since v1:
> - Make a common skl_program_plane, and use it for both plane updates.
> 
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h     |  1 +
>  drivers/gpu/drm/i915/intel_sprite.c | 50 +++++++++++++++++++++--------
>  2 files changed, 38 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index b614a06b66c4..a3129a4c15cc 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -6511,6 +6511,7 @@ enum {
>  #define   PLANE_CTL_KEY_ENABLE_DESTINATION	(2 << 21)
>  #define   PLANE_CTL_ORDER_BGRX			(0 << 20)
>  #define   PLANE_CTL_ORDER_RGBX			(1 << 20)
> +#define   PLANE_CTL_YUV420_Y_PLANE		(1 << 19)
>  #define   PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709	(1 << 18)
>  #define   PLANE_CTL_YUV422_ORDER_MASK		(0x3 << 16)
>  #define   PLANE_CTL_YUV422_YUYV			(0 << 16)
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index c4e05b0b60bf..708d2dfd59d7 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -339,23 +339,23 @@ skl_program_scaler(struct drm_i915_private *dev_priv,
>  		      ((crtc_w + 1) << 16)|(crtc_h + 1));
>  }
>  
> -void
> -skl_update_plane(struct intel_plane *plane,
> -		 const struct intel_crtc_state *crtc_state,
> -		 const struct intel_plane_state *plane_state)
> +static void
> +skl_program_plane(struct intel_plane *plane,
> +		  const struct intel_crtc_state *crtc_state,
> +		  const struct intel_plane_state *plane_state,
> +		  int color_plane, bool slave, u32 plane_ctl)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>  	enum plane_id plane_id = plane->id;
>  	enum pipe pipe = plane->pipe;
> -	u32 plane_ctl = plane_state->ctl;
>  	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> -	u32 surf_addr = plane_state->color_plane[0].offset;
> -	u32 stride = skl_plane_stride(plane_state, 0);
> +	u32 surf_addr = plane_state->color_plane[color_plane].offset;
> +	u32 stride = skl_plane_stride(plane_state, color_plane);
>  	u32 aux_stride = skl_plane_stride(plane_state, 1);
>  	int crtc_x = plane_state->base.dst.x1;
>  	int crtc_y = plane_state->base.dst.y1;
> -	uint32_t x = plane_state->color_plane[0].x;
> -	uint32_t y = plane_state->color_plane[0].y;
> +	uint32_t x = plane_state->color_plane[color_plane].x;
> +	uint32_t y = plane_state->color_plane[color_plane].y;
>  	uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
>  	uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
>  	struct intel_plane *linked = plane_state->linked_plane;
> @@ -409,7 +409,9 @@ skl_update_plane(struct intel_plane *plane,
>  
>  	/* program plane scaler */
>  	if (plane_state->scaler_id >= 0) {
> -		skl_program_scaler(dev_priv, plane, crtc_state, plane_state);
> +		if (!slave)
> +			skl_program_scaler(dev_priv, plane,
> +					   crtc_state, plane_state);
>  
>  		I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0);
>  	} else {
> @@ -424,6 +426,25 @@ skl_update_plane(struct intel_plane *plane,
>  	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
>  }
>  
> +void
> +skl_update_plane(struct intel_plane *plane,
> +		 const struct intel_crtc_state *crtc_state,
> +		 const struct intel_plane_state *plane_state)
> +{
> +	skl_program_plane(plane, crtc_state, plane_state,
> +			  !!plane_state->linked_plane, false,

The !!linked thing is a bit magicy. I'd probably forget what it means
every single time. So IMO deserves to be written out in a bit more
verbose way and/or accompanied by a comment.

> +			  plane_state->ctl);
> +}
> +
> +static void
> +icl_update_slave(struct intel_plane *plane,
> +		 const struct intel_crtc_state *crtc_state,
> +		 const struct intel_plane_state *plane_state)
> +{
> +	skl_program_plane(plane, crtc_state, plane_state, 0, true,
> +			  plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE);

So that one bit is the only difference (apart from the obvious
PLANE_SURF/STRIDE/OFFSET? No need to deal with the chroma vs. luma 
size difference etc?

> +}
> +
>  void
>  skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
>  {
> @@ -1775,6 +1796,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  	const uint64_t *modifiers;
>  	unsigned int supported_rotations;
>  	int num_plane_formats;
> +	enum plane_id plane_id = PLANE_SPRITE0 + plane;
>  	int ret;
>  
>  	intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
> @@ -1794,16 +1816,18 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  		state->scaler_id = -1;
>  
>  		intel_plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe,
> -							 PLANE_SPRITE0 + plane);
> +							 plane_id);
>  
>  		intel_plane->max_stride = skl_plane_max_stride;
>  		intel_plane->update_plane = skl_update_plane;
> +		if (icl_is_nv12_y_plane(plane_id))
> +			intel_plane->update_slave = icl_update_slave;
>  		intel_plane->disable_plane = skl_disable_plane;
>  		intel_plane->get_hw_state = skl_plane_get_hw_state;
>  		intel_plane->check_plane = skl_plane_check;
>  
>  		if (skl_plane_has_planar(dev_priv, pipe,
> -					 PLANE_SPRITE0 + plane)) {
> +					 plane_id)) {
>  			plane_formats = skl_planar_formats;
>  			num_plane_formats = ARRAY_SIZE(skl_planar_formats);
>  		} else {
> @@ -1877,7 +1901,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  
>  	intel_plane->pipe = pipe;
>  	intel_plane->i9xx_plane = plane;
> -	intel_plane->id = PLANE_SPRITE0 + plane;
> +	intel_plane->id = plane_id;
>  	intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, intel_plane->id);
>  
>  	possible_crtcs = (1 << pipe);
> -- 
> 2.18.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Maarten Lankhorst Sept. 22, 2018, 9:37 a.m. UTC | #2
Op 21-09-18 om 21:01 schreef Ville Syrjälä:
> On Fri, Sep 21, 2018 at 07:39:44PM +0200, Maarten Lankhorst wrote:
>> The UV plane is the master plane that does all color correction etc.
>> It needs to be programmed with the dimensions for color plane 1 (UV).
>>
>> The Y plane just feeds the Y pixels to it. Program the scaler from the
>> master only, and set PLANE_CTL_YUV420_Y_PLANE on the slave plane.
>>
>> Changes since v1:
>> - Make a common skl_program_plane, and use it for both plane updates.
>>
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>> ---
>>  drivers/gpu/drm/i915/i915_reg.h     |  1 +
>>  drivers/gpu/drm/i915/intel_sprite.c | 50 +++++++++++++++++++++--------
>>  2 files changed, 38 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
>> index b614a06b66c4..a3129a4c15cc 100644
>> --- a/drivers/gpu/drm/i915/i915_reg.h
>> +++ b/drivers/gpu/drm/i915/i915_reg.h
>> @@ -6511,6 +6511,7 @@ enum {
>>  #define   PLANE_CTL_KEY_ENABLE_DESTINATION	(2 << 21)
>>  #define   PLANE_CTL_ORDER_BGRX			(0 << 20)
>>  #define   PLANE_CTL_ORDER_RGBX			(1 << 20)
>> +#define   PLANE_CTL_YUV420_Y_PLANE		(1 << 19)
>>  #define   PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709	(1 << 18)
>>  #define   PLANE_CTL_YUV422_ORDER_MASK		(0x3 << 16)
>>  #define   PLANE_CTL_YUV422_YUYV			(0 << 16)
>> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
>> index c4e05b0b60bf..708d2dfd59d7 100644
>> --- a/drivers/gpu/drm/i915/intel_sprite.c
>> +++ b/drivers/gpu/drm/i915/intel_sprite.c
>> @@ -339,23 +339,23 @@ skl_program_scaler(struct drm_i915_private *dev_priv,
>>  		      ((crtc_w + 1) << 16)|(crtc_h + 1));
>>  }
>>  
>> -void
>> -skl_update_plane(struct intel_plane *plane,
>> -		 const struct intel_crtc_state *crtc_state,
>> -		 const struct intel_plane_state *plane_state)
>> +static void
>> +skl_program_plane(struct intel_plane *plane,
>> +		  const struct intel_crtc_state *crtc_state,
>> +		  const struct intel_plane_state *plane_state,
>> +		  int color_plane, bool slave, u32 plane_ctl)
>>  {
>>  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>>  	enum plane_id plane_id = plane->id;
>>  	enum pipe pipe = plane->pipe;
>> -	u32 plane_ctl = plane_state->ctl;
>>  	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
>> -	u32 surf_addr = plane_state->color_plane[0].offset;
>> -	u32 stride = skl_plane_stride(plane_state, 0);
>> +	u32 surf_addr = plane_state->color_plane[color_plane].offset;
>> +	u32 stride = skl_plane_stride(plane_state, color_plane);
>>  	u32 aux_stride = skl_plane_stride(plane_state, 1);
>>  	int crtc_x = plane_state->base.dst.x1;
>>  	int crtc_y = plane_state->base.dst.y1;
>> -	uint32_t x = plane_state->color_plane[0].x;
>> -	uint32_t y = plane_state->color_plane[0].y;
>> +	uint32_t x = plane_state->color_plane[color_plane].x;
>> +	uint32_t y = plane_state->color_plane[color_plane].y;
>>  	uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
>>  	uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
>>  	struct intel_plane *linked = plane_state->linked_plane;
>> @@ -409,7 +409,9 @@ skl_update_plane(struct intel_plane *plane,
>>  
>>  	/* program plane scaler */
>>  	if (plane_state->scaler_id >= 0) {
>> -		skl_program_scaler(dev_priv, plane, crtc_state, plane_state);
>> +		if (!slave)
>> +			skl_program_scaler(dev_priv, plane,
>> +					   crtc_state, plane_state);
>>  
>>  		I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0);
>>  	} else {
>> @@ -424,6 +426,25 @@ skl_update_plane(struct intel_plane *plane,
>>  	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
>>  }
>>  
>> +void
>> +skl_update_plane(struct intel_plane *plane,
>> +		 const struct intel_crtc_state *crtc_state,
>> +		 const struct intel_plane_state *plane_state)
>> +{
>> +	skl_program_plane(plane, crtc_state, plane_state,
>> +			  !!plane_state->linked_plane, false,
> The !!linked thing is a bit magicy. I'd probably forget what it means
> every single time. So IMO deserves to be written out in a bit more
> verbose way and/or accompanied by a comment.
I'll just make a variable int color_plane = plane_state->linked_plane ? 1 : 0?
>> +			  plane_state->ctl);
>> +}
>> +
>> +static void
>> +icl_update_slave(struct intel_plane *plane,
>> +		 const struct intel_crtc_state *crtc_state,
>> +		 const struct intel_plane_state *plane_state)
>> +{
>> +	skl_program_plane(plane, crtc_state, plane_state, 0, true,
>> +			  plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE);
> So that one bit is the only difference (apart from the obvious
> PLANE_SURF/STRIDE/OFFSET? No need to deal with the chroma vs. luma 
> size difference etc?
Yes, and all color management is ignored on the Y plane. Still there doesn't seem
to be any harm in programming it, so *shrug*.

Only not so nice thing is I found a CRC mismatch when using chroma upsampling + scaling
vs just using the chroma upsampling. Seems to be a small ~1 or 2 pixel difference in 10 bit.
Need to investigate it a bit more, but with 8 bits you don't notice it. Just an annoying crc mismatch. :)

~Maarten
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index b614a06b66c4..a3129a4c15cc 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -6511,6 +6511,7 @@  enum {
 #define   PLANE_CTL_KEY_ENABLE_DESTINATION	(2 << 21)
 #define   PLANE_CTL_ORDER_BGRX			(0 << 20)
 #define   PLANE_CTL_ORDER_RGBX			(1 << 20)
+#define   PLANE_CTL_YUV420_Y_PLANE		(1 << 19)
 #define   PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709	(1 << 18)
 #define   PLANE_CTL_YUV422_ORDER_MASK		(0x3 << 16)
 #define   PLANE_CTL_YUV422_YUYV			(0 << 16)
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index c4e05b0b60bf..708d2dfd59d7 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -339,23 +339,23 @@  skl_program_scaler(struct drm_i915_private *dev_priv,
 		      ((crtc_w + 1) << 16)|(crtc_h + 1));
 }
 
-void
-skl_update_plane(struct intel_plane *plane,
-		 const struct intel_crtc_state *crtc_state,
-		 const struct intel_plane_state *plane_state)
+static void
+skl_program_plane(struct intel_plane *plane,
+		  const struct intel_crtc_state *crtc_state,
+		  const struct intel_plane_state *plane_state,
+		  int color_plane, bool slave, u32 plane_ctl)
 {
 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 	enum plane_id plane_id = plane->id;
 	enum pipe pipe = plane->pipe;
-	u32 plane_ctl = plane_state->ctl;
 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
-	u32 surf_addr = plane_state->color_plane[0].offset;
-	u32 stride = skl_plane_stride(plane_state, 0);
+	u32 surf_addr = plane_state->color_plane[color_plane].offset;
+	u32 stride = skl_plane_stride(plane_state, color_plane);
 	u32 aux_stride = skl_plane_stride(plane_state, 1);
 	int crtc_x = plane_state->base.dst.x1;
 	int crtc_y = plane_state->base.dst.y1;
-	uint32_t x = plane_state->color_plane[0].x;
-	uint32_t y = plane_state->color_plane[0].y;
+	uint32_t x = plane_state->color_plane[color_plane].x;
+	uint32_t y = plane_state->color_plane[color_plane].y;
 	uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
 	uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
 	struct intel_plane *linked = plane_state->linked_plane;
@@ -409,7 +409,9 @@  skl_update_plane(struct intel_plane *plane,
 
 	/* program plane scaler */
 	if (plane_state->scaler_id >= 0) {
-		skl_program_scaler(dev_priv, plane, crtc_state, plane_state);
+		if (!slave)
+			skl_program_scaler(dev_priv, plane,
+					   crtc_state, plane_state);
 
 		I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0);
 	} else {
@@ -424,6 +426,25 @@  skl_update_plane(struct intel_plane *plane,
 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
+void
+skl_update_plane(struct intel_plane *plane,
+		 const struct intel_crtc_state *crtc_state,
+		 const struct intel_plane_state *plane_state)
+{
+	skl_program_plane(plane, crtc_state, plane_state,
+			  !!plane_state->linked_plane, false,
+			  plane_state->ctl);
+}
+
+static void
+icl_update_slave(struct intel_plane *plane,
+		 const struct intel_crtc_state *crtc_state,
+		 const struct intel_plane_state *plane_state)
+{
+	skl_program_plane(plane, crtc_state, plane_state, 0, true,
+			  plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE);
+}
+
 void
 skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
 {
@@ -1775,6 +1796,7 @@  intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 	const uint64_t *modifiers;
 	unsigned int supported_rotations;
 	int num_plane_formats;
+	enum plane_id plane_id = PLANE_SPRITE0 + plane;
 	int ret;
 
 	intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
@@ -1794,16 +1816,18 @@  intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 		state->scaler_id = -1;
 
 		intel_plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe,
-							 PLANE_SPRITE0 + plane);
+							 plane_id);
 
 		intel_plane->max_stride = skl_plane_max_stride;
 		intel_plane->update_plane = skl_update_plane;
+		if (icl_is_nv12_y_plane(plane_id))
+			intel_plane->update_slave = icl_update_slave;
 		intel_plane->disable_plane = skl_disable_plane;
 		intel_plane->get_hw_state = skl_plane_get_hw_state;
 		intel_plane->check_plane = skl_plane_check;
 
 		if (skl_plane_has_planar(dev_priv, pipe,
-					 PLANE_SPRITE0 + plane)) {
+					 plane_id)) {
 			plane_formats = skl_planar_formats;
 			num_plane_formats = ARRAY_SIZE(skl_planar_formats);
 		} else {
@@ -1877,7 +1901,7 @@  intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 
 	intel_plane->pipe = pipe;
 	intel_plane->i9xx_plane = plane;
-	intel_plane->id = PLANE_SPRITE0 + plane;
+	intel_plane->id = plane_id;
 	intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, intel_plane->id);
 
 	possible_crtcs = (1 << pipe);