diff mbox series

drm/i915: Handle YUV subpixel support better

Message ID 20190318140718.1619-1-maarten.lankhorst@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series drm/i915: Handle YUV subpixel support better | expand

Commit Message

Maarten Lankhorst March 18, 2019, 2:07 p.m. UTC
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_sprite.c | 29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)

Comments

Ville Syrjälä March 18, 2019, 2:18 p.m. UTC | #1
On Mon, Mar 18, 2019 at 03:07:18PM +0100, Maarten Lankhorst wrote:
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_sprite.c | 29 +++++++++++++++++++----------
>  1 file changed, 19 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 268fb34ff0e2..862fc172042f 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -269,7 +269,8 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
>  {
>  	const struct drm_framebuffer *fb = plane_state->base.fb;
>  	struct drm_rect *src = &plane_state->base.src;
> -	u32 src_x, src_y, src_w, src_h;
> +	u32 src_x, src_y, src_w, src_h, hsub, vsub;
> +	bool rotated = drm_rotation_90_or_270(plane_state->base.rotation);
>  
>  	/*
>  	 * Hardware doesn't handle subpixel coordinates.
> @@ -287,18 +288,26 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
>  	src->y1 = src_y << 16;
>  	src->y2 = (src_y + src_h) << 16;
>  
> -	if (fb->format->is_yuv &&
> -	    (src_x & 1 || src_w & 1)) {
> -		DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n",
> -			      src_x, src_w);
> +	if (!fb->format->is_yuv)
> +		return 0;
> +
> +	/* YUV specific checks */
> +	if (!rotated) {
> +		hsub = fb->format->hsub;
> +		vsub = fb->format->vsub;
> +	} else {
> +		hsub = vsub = max(fb->format->hsub, fb->format->vsub);

Why this? From the looks of things there should be no need to deal with
rotation in this function at all.

> +	}
> +
> +	if (src_x % hsub || src_w % hsub) {
> +		DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u for %sYUV planes\n",
> +			      src_x, src_w, hsub, rotated ? "rotated " : "");
>  		return -EINVAL;
>  	}
>  
> -	if (fb->format->is_yuv &&
> -	    fb->format->num_planes > 1 &&
> -	    (src_y & 1 || src_h & 1)) {
> -		DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of 2 for planar YUV planes\n",
> -			      src_y, src_h);
> +	if (src_y % vsub || src_h % vsub) {
> +		DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u for %sYUV planes\n",
> +			      src_y, src_h, vsub, rotated ? "rotated " : "");
>  		return -EINVAL;
>  	}
>  
> -- 
> 2.20.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Maarten Lankhorst March 18, 2019, 3:13 p.m. UTC | #2
Op 18-03-2019 om 15:18 schreef Ville Syrjälä:
> On Mon, Mar 18, 2019 at 03:07:18PM +0100, Maarten Lankhorst wrote:
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>> ---
>>  drivers/gpu/drm/i915/intel_sprite.c | 29 +++++++++++++++++++----------
>>  1 file changed, 19 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
>> index 268fb34ff0e2..862fc172042f 100644
>> --- a/drivers/gpu/drm/i915/intel_sprite.c
>> +++ b/drivers/gpu/drm/i915/intel_sprite.c
>> @@ -269,7 +269,8 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
>>  {
>>  	const struct drm_framebuffer *fb = plane_state->base.fb;
>>  	struct drm_rect *src = &plane_state->base.src;
>> -	u32 src_x, src_y, src_w, src_h;
>> +	u32 src_x, src_y, src_w, src_h, hsub, vsub;
>> +	bool rotated = drm_rotation_90_or_270(plane_state->base.rotation);
>>  
>>  	/*
>>  	 * Hardware doesn't handle subpixel coordinates.
>> @@ -287,18 +288,26 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
>>  	src->y1 = src_y << 16;
>>  	src->y2 = (src_y + src_h) << 16;
>>  
>> -	if (fb->format->is_yuv &&
>> -	    (src_x & 1 || src_w & 1)) {
>> -		DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n",
>> -			      src_x, src_w);
>> +	if (!fb->format->is_yuv)
>> +		return 0;
>> +
>> +	/* YUV specific checks */
>> +	if (!rotated) {
>> +		hsub = fb->format->hsub;
>> +		vsub = fb->format->vsub;
>> +	} else {
>> +		hsub = vsub = max(fb->format->hsub, fb->format->vsub);
> Why this? From the looks of things there should be no need to deal with
> rotation in this function at all.

I wrote a dumb test that fails if I rotate YUYV.

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

Corrupted image:

(kms_yuv:1155) igt_kms-DEBUG: display: A.0: plane_set_rotation(90°)
(kms_yuv:1155) igt_kms-DEBUG: display: A.0: src_set_position(18,33)
(kms_yuv:1155) igt_kms-DEBUG: display: A.0: src_set_size(44x65)
(kms_yuv:1155) igt_kms-DEBUG: display: A.0: plane_set_position(64,64)
(kms_yuv:1155) igt_kms-DEBUG: display: A.0: plane_set_size (256x256)

I had a 80x128 fb, only showing the center part which should be white, with a black border around it to cause CRC errors if we mess up clipping.

The scaling works fine, but the clipping does not in this case. I am getting a corrupted plane on screen which is mostly white, but with black dots in each tile.

Scaling just magnifies this corruption. :)
Ville Syrjälä March 18, 2019, 6:15 p.m. UTC | #3
On Mon, Mar 18, 2019 at 04:13:57PM +0100, Maarten Lankhorst wrote:
> Op 18-03-2019 om 15:18 schreef Ville Syrjälä:
> > On Mon, Mar 18, 2019 at 03:07:18PM +0100, Maarten Lankhorst wrote:
> >> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> >> ---
> >>  drivers/gpu/drm/i915/intel_sprite.c | 29 +++++++++++++++++++----------
> >>  1 file changed, 19 insertions(+), 10 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> >> index 268fb34ff0e2..862fc172042f 100644
> >> --- a/drivers/gpu/drm/i915/intel_sprite.c
> >> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> >> @@ -269,7 +269,8 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
> >>  {
> >>  	const struct drm_framebuffer *fb = plane_state->base.fb;
> >>  	struct drm_rect *src = &plane_state->base.src;
> >> -	u32 src_x, src_y, src_w, src_h;
> >> +	u32 src_x, src_y, src_w, src_h, hsub, vsub;
> >> +	bool rotated = drm_rotation_90_or_270(plane_state->base.rotation);
> >>  
> >>  	/*
> >>  	 * Hardware doesn't handle subpixel coordinates.
> >> @@ -287,18 +288,26 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
> >>  	src->y1 = src_y << 16;
> >>  	src->y2 = (src_y + src_h) << 16;
> >>  
> >> -	if (fb->format->is_yuv &&
> >> -	    (src_x & 1 || src_w & 1)) {
> >> -		DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n",
> >> -			      src_x, src_w);
> >> +	if (!fb->format->is_yuv)
> >> +		return 0;
> >> +
> >> +	/* YUV specific checks */
> >> +	if (!rotated) {
> >> +		hsub = fb->format->hsub;
> >> +		vsub = fb->format->vsub;
> >> +	} else {
> >> +		hsub = vsub = max(fb->format->hsub, fb->format->vsub);
> > Why this? From the looks of things there should be no need to deal with
> > rotation in this function at all.
> 
> I wrote a dumb test that fails if I rotate YUYV.
> 
> https://patchwork.freedesktop.org/patch/286170/
> 
> Corrupted image:
> 
> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: plane_set_rotation(90°)
> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: src_set_position(18,33)
> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: src_set_size(44x65)
> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: plane_set_position(64,64)
> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: plane_set_size (256x256)
> 
> I had a 80x128 fb, only showing the center part which should be white, with a black border around it to cause CRC errors if we mess up clipping.
> 
> The scaling works fine, but the clipping does not in this case. I am getting a corrupted plane on screen which is mostly white, but with black dots in each tile.
> 
> Scaling just magnifies this corruption. :)

Hmm. I just poked my KBL a bit and it is also showing curious
behaviour. Even with 90/270 rotation it is in fact the TILEOFF
X coordinate that needs to be even (actually the hw just appears
to ignore the lsb). I can make the Y coordinate odd, and the image
still looks correct to my eyes. So feels like someone forgot to
to remove a (x&~1) from the hw when they added the 90/270 rotation,
and yet they went to the trouble of making odd Y coordinates work
correctly. Quite stange.

Width/height being odd seems to handled just fine by the hw.
Maarten Lankhorst March 19, 2019, 7:28 a.m. UTC | #4
Op 18-03-2019 om 19:15 schreef Ville Syrjälä:
> On Mon, Mar 18, 2019 at 04:13:57PM +0100, Maarten Lankhorst wrote:
>> Op 18-03-2019 om 15:18 schreef Ville Syrjälä:
>>> On Mon, Mar 18, 2019 at 03:07:18PM +0100, Maarten Lankhorst wrote:
>>>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>>>> ---
>>>>  drivers/gpu/drm/i915/intel_sprite.c | 29 +++++++++++++++++++----------
>>>>  1 file changed, 19 insertions(+), 10 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
>>>> index 268fb34ff0e2..862fc172042f 100644
>>>> --- a/drivers/gpu/drm/i915/intel_sprite.c
>>>> +++ b/drivers/gpu/drm/i915/intel_sprite.c
>>>> @@ -269,7 +269,8 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
>>>>  {
>>>>  	const struct drm_framebuffer *fb = plane_state->base.fb;
>>>>  	struct drm_rect *src = &plane_state->base.src;
>>>> -	u32 src_x, src_y, src_w, src_h;
>>>> +	u32 src_x, src_y, src_w, src_h, hsub, vsub;
>>>> +	bool rotated = drm_rotation_90_or_270(plane_state->base.rotation);
>>>>  
>>>>  	/*
>>>>  	 * Hardware doesn't handle subpixel coordinates.
>>>> @@ -287,18 +288,26 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
>>>>  	src->y1 = src_y << 16;
>>>>  	src->y2 = (src_y + src_h) << 16;
>>>>  
>>>> -	if (fb->format->is_yuv &&
>>>> -	    (src_x & 1 || src_w & 1)) {
>>>> -		DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n",
>>>> -			      src_x, src_w);
>>>> +	if (!fb->format->is_yuv)
>>>> +		return 0;
>>>> +
>>>> +	/* YUV specific checks */
>>>> +	if (!rotated) {
>>>> +		hsub = fb->format->hsub;
>>>> +		vsub = fb->format->vsub;
>>>> +	} else {
>>>> +		hsub = vsub = max(fb->format->hsub, fb->format->vsub);
>>> Why this? From the looks of things there should be no need to deal with
>>> rotation in this function at all.
>> I wrote a dumb test that fails if I rotate YUYV.
>>
>> https://patchwork.freedesktop.org/patch/286170/
>>
>> Corrupted image:
>>
>> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: plane_set_rotation(90°)
>> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: src_set_position(18,33)
>> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: src_set_size(44x65)
>> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: plane_set_position(64,64)
>> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: plane_set_size (256x256)
>>
>> I had a 80x128 fb, only showing the center part which should be white, with a black border around it to cause CRC errors if we mess up clipping.
>>
>> The scaling works fine, but the clipping does not in this case. I am getting a corrupted plane on screen which is mostly white, but with black dots in each tile.
>>
>> Scaling just magnifies this corruption. :)
> Hmm. I just poked my KBL a bit and it is also showing curious
> behaviour. Even with 90/270 rotation it is in fact the TILEOFF
> X coordinate that needs to be even (actually the hw just appears
> to ignore the lsb). I can make the Y coordinate odd, and the image
> still looks correct to my eyes. So feels like someone forgot to
> to remove a (x&~1) from the hw when they added the 90/270 rotation,
> and yet they went to the trouble of making odd Y coordinates work
> correctly. Quite stange.
>
> Width/height being odd seems to handled just fine by the hw.
>
Hmm does that mean we should keep the original checks in place while checking format->h/vsub, and on top reject the unrotated Y coordinate being a multiple of hsub when rotating?

~Maarten
Ville Syrjälä March 19, 2019, 11:15 a.m. UTC | #5
On Tue, Mar 19, 2019 at 08:28:58AM +0100, Maarten Lankhorst wrote:
> Op 18-03-2019 om 19:15 schreef Ville Syrjälä:
> > On Mon, Mar 18, 2019 at 04:13:57PM +0100, Maarten Lankhorst wrote:
> >> Op 18-03-2019 om 15:18 schreef Ville Syrjälä:
> >>> On Mon, Mar 18, 2019 at 03:07:18PM +0100, Maarten Lankhorst wrote:
> >>>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> >>>> ---
> >>>>  drivers/gpu/drm/i915/intel_sprite.c | 29 +++++++++++++++++++----------
> >>>>  1 file changed, 19 insertions(+), 10 deletions(-)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> >>>> index 268fb34ff0e2..862fc172042f 100644
> >>>> --- a/drivers/gpu/drm/i915/intel_sprite.c
> >>>> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> >>>> @@ -269,7 +269,8 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
> >>>>  {
> >>>>  	const struct drm_framebuffer *fb = plane_state->base.fb;
> >>>>  	struct drm_rect *src = &plane_state->base.src;
> >>>> -	u32 src_x, src_y, src_w, src_h;
> >>>> +	u32 src_x, src_y, src_w, src_h, hsub, vsub;
> >>>> +	bool rotated = drm_rotation_90_or_270(plane_state->base.rotation);
> >>>>  
> >>>>  	/*
> >>>>  	 * Hardware doesn't handle subpixel coordinates.
> >>>> @@ -287,18 +288,26 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
> >>>>  	src->y1 = src_y << 16;
> >>>>  	src->y2 = (src_y + src_h) << 16;
> >>>>  
> >>>> -	if (fb->format->is_yuv &&
> >>>> -	    (src_x & 1 || src_w & 1)) {
> >>>> -		DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n",
> >>>> -			      src_x, src_w);
> >>>> +	if (!fb->format->is_yuv)
> >>>> +		return 0;
> >>>> +
> >>>> +	/* YUV specific checks */
> >>>> +	if (!rotated) {
> >>>> +		hsub = fb->format->hsub;
> >>>> +		vsub = fb->format->vsub;
> >>>> +	} else {
> >>>> +		hsub = vsub = max(fb->format->hsub, fb->format->vsub);
> >>> Why this? From the looks of things there should be no need to deal with
> >>> rotation in this function at all.
> >> I wrote a dumb test that fails if I rotate YUYV.
> >>
> >> https://patchwork.freedesktop.org/patch/286170/
> >>
> >> Corrupted image:
> >>
> >> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: plane_set_rotation(90°)
> >> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: src_set_position(18,33)
> >> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: src_set_size(44x65)
> >> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: plane_set_position(64,64)
> >> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: plane_set_size (256x256)
> >>
> >> I had a 80x128 fb, only showing the center part which should be white, with a black border around it to cause CRC errors if we mess up clipping.
> >>
> >> The scaling works fine, but the clipping does not in this case. I am getting a corrupted plane on screen which is mostly white, but with black dots in each tile.
> >>
> >> Scaling just magnifies this corruption. :)
> > Hmm. I just poked my KBL a bit and it is also showing curious
> > behaviour. Even with 90/270 rotation it is in fact the TILEOFF
> > X coordinate that needs to be even (actually the hw just appears
> > to ignore the lsb). I can make the Y coordinate odd, and the image
> > still looks correct to my eyes. So feels like someone forgot to
> > to remove a (x&~1) from the hw when they added the 90/270 rotation,
> > and yet they went to the trouble of making odd Y coordinates work
> > correctly. Quite stange.
> >
> > Width/height being odd seems to handled just fine by the hw.
> >
> Hmm does that mean we should keep the original checks in place while checking format->h/vsub, and on top reject the unrotated Y coordinate being a multiple of hsub when rotating?

Not quite sure. Based on what I see we could actually just swap the
coordinates (or do the check after the coordinates are already rotated)
and it should still work. But I didn't check if that would still work
when the scaler is involved.
Ville Syrjälä March 19, 2019, 12:45 p.m. UTC | #6
On Tue, Mar 19, 2019 at 01:15:55PM +0200, Ville Syrjälä wrote:
> On Tue, Mar 19, 2019 at 08:28:58AM +0100, Maarten Lankhorst wrote:
> > Op 18-03-2019 om 19:15 schreef Ville Syrjälä:
> > > On Mon, Mar 18, 2019 at 04:13:57PM +0100, Maarten Lankhorst wrote:
> > >> Op 18-03-2019 om 15:18 schreef Ville Syrjälä:
> > >>> On Mon, Mar 18, 2019 at 03:07:18PM +0100, Maarten Lankhorst wrote:
> > >>>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > >>>> ---
> > >>>>  drivers/gpu/drm/i915/intel_sprite.c | 29 +++++++++++++++++++----------
> > >>>>  1 file changed, 19 insertions(+), 10 deletions(-)
> > >>>>
> > >>>> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> > >>>> index 268fb34ff0e2..862fc172042f 100644
> > >>>> --- a/drivers/gpu/drm/i915/intel_sprite.c
> > >>>> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> > >>>> @@ -269,7 +269,8 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
> > >>>>  {
> > >>>>  	const struct drm_framebuffer *fb = plane_state->base.fb;
> > >>>>  	struct drm_rect *src = &plane_state->base.src;
> > >>>> -	u32 src_x, src_y, src_w, src_h;
> > >>>> +	u32 src_x, src_y, src_w, src_h, hsub, vsub;
> > >>>> +	bool rotated = drm_rotation_90_or_270(plane_state->base.rotation);
> > >>>>  
> > >>>>  	/*
> > >>>>  	 * Hardware doesn't handle subpixel coordinates.
> > >>>> @@ -287,18 +288,26 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
> > >>>>  	src->y1 = src_y << 16;
> > >>>>  	src->y2 = (src_y + src_h) << 16;
> > >>>>  
> > >>>> -	if (fb->format->is_yuv &&
> > >>>> -	    (src_x & 1 || src_w & 1)) {
> > >>>> -		DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n",
> > >>>> -			      src_x, src_w);
> > >>>> +	if (!fb->format->is_yuv)
> > >>>> +		return 0;
> > >>>> +
> > >>>> +	/* YUV specific checks */
> > >>>> +	if (!rotated) {
> > >>>> +		hsub = fb->format->hsub;
> > >>>> +		vsub = fb->format->vsub;
> > >>>> +	} else {
> > >>>> +		hsub = vsub = max(fb->format->hsub, fb->format->vsub);
> > >>> Why this? From the looks of things there should be no need to deal with
> > >>> rotation in this function at all.
> > >> I wrote a dumb test that fails if I rotate YUYV.
> > >>
> > >> https://patchwork.freedesktop.org/patch/286170/
> > >>
> > >> Corrupted image:
> > >>
> > >> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: plane_set_rotation(90°)
> > >> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: src_set_position(18,33)
> > >> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: src_set_size(44x65)
> > >> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: plane_set_position(64,64)
> > >> (kms_yuv:1155) igt_kms-DEBUG: display: A.0: plane_set_size (256x256)
> > >>
> > >> I had a 80x128 fb, only showing the center part which should be white, with a black border around it to cause CRC errors if we mess up clipping.
> > >>
> > >> The scaling works fine, but the clipping does not in this case. I am getting a corrupted plane on screen which is mostly white, but with black dots in each tile.
> > >>
> > >> Scaling just magnifies this corruption. :)
> > > Hmm. I just poked my KBL a bit and it is also showing curious
> > > behaviour. Even with 90/270 rotation it is in fact the TILEOFF
> > > X coordinate that needs to be even (actually the hw just appears
> > > to ignore the lsb). I can make the Y coordinate odd, and the image
> > > still looks correct to my eyes. So feels like someone forgot to
> > > to remove a (x&~1) from the hw when they added the 90/270 rotation,
> > > and yet they went to the trouble of making odd Y coordinates work
> > > correctly. Quite stange.
> > >
> > > Width/height being odd seems to handled just fine by the hw.
> > >
> > Hmm does that mean we should keep the original checks in place while checking format->h/vsub, and on top reject the unrotated Y coordinate being a multiple of hsub when rotating?
> 
> Not quite sure. Based on what I see we could actually just swap the
> coordinates (or do the check after the coordinates are already rotated)
> and it should still work. But I didn't check if that would still work
> when the scaler is involved.

Hmm. The spec disagrees with this observed behaviour of PLANE_OFFSET.
It claims our current code should be fine.

PLANE_SIZE also has this slightly confusing table for GLK+:
PixelFormat		Rotate		Width	Height
YUV 420 Planar - NV12	All		Even	Even
YUV 420 Planar - P01x	All		Even	Even
YUV 422 		All 		Even	Even
RGB565			90, 270		Even	Even

which pretty much matches the w/h part of your patch.
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 268fb34ff0e2..862fc172042f 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -269,7 +269,8 @@  int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
 {
 	const struct drm_framebuffer *fb = plane_state->base.fb;
 	struct drm_rect *src = &plane_state->base.src;
-	u32 src_x, src_y, src_w, src_h;
+	u32 src_x, src_y, src_w, src_h, hsub, vsub;
+	bool rotated = drm_rotation_90_or_270(plane_state->base.rotation);
 
 	/*
 	 * Hardware doesn't handle subpixel coordinates.
@@ -287,18 +288,26 @@  int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
 	src->y1 = src_y << 16;
 	src->y2 = (src_y + src_h) << 16;
 
-	if (fb->format->is_yuv &&
-	    (src_x & 1 || src_w & 1)) {
-		DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n",
-			      src_x, src_w);
+	if (!fb->format->is_yuv)
+		return 0;
+
+	/* YUV specific checks */
+	if (!rotated) {
+		hsub = fb->format->hsub;
+		vsub = fb->format->vsub;
+	} else {
+		hsub = vsub = max(fb->format->hsub, fb->format->vsub);
+	}
+
+	if (src_x % hsub || src_w % hsub) {
+		DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u for %sYUV planes\n",
+			      src_x, src_w, hsub, rotated ? "rotated " : "");
 		return -EINVAL;
 	}
 
-	if (fb->format->is_yuv &&
-	    fb->format->num_planes > 1 &&
-	    (src_y & 1 || src_h & 1)) {
-		DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of 2 for planar YUV planes\n",
-			      src_y, src_h);
+	if (src_y % vsub || src_h % vsub) {
+		DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u for %sYUV planes\n",
+			      src_y, src_h, vsub, rotated ? "rotated " : "");
 		return -EINVAL;
 	}