diff mbox series

drm/komeda: Fix off-by-1 when with readback conn due to rounding

Message ID 20210305163853.66157-1-carsten.haitzler@foss.arm.com (mailing list archive)
State New, archived
Headers show
Series drm/komeda: Fix off-by-1 when with readback conn due to rounding | expand

Commit Message

Carsten Haitzler March 5, 2021, 4:38 p.m. UTC
From: Carsten Haitzler <carsten.haitzler@arm.com>

When setting up a readback conenctor that writes data back to memory
rather than to an actual output device (HDMI etc.), rounding was ses
to round-down. As the DPU uses a higher internal number of bits when
generating a color value, this round-down back to 8bit ended up with
everything being off-by one. e.g. #ffffff became #fefefe. This sets
rounding to "round" so things end up correct by turning on the round
flag (LW_TRC).

Signed-off-by: Carsten Haitzler <carsten.haitzler@arm.com>
---
 drivers/gpu/drm/arm/display/komeda/d71/d71_component.c | 6 +++++-
 drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h      | 1 +
 2 files changed, 6 insertions(+), 1 deletion(-)

Comments

Brian Starkey March 9, 2021, 11:36 a.m. UTC | #1
Hi Carsten, (+James for komeda)

Thanks for typing this up.

On Fri, Mar 05, 2021 at 04:38:53PM +0000, carsten.haitzler@foss.arm.com wrote:
> From: Carsten Haitzler <carsten.haitzler@arm.com>
> 
> When setting up a readback conenctor that writes data back to memory

s/readback conenctor/writeback connector/ (similar in the subject)

> rather than to an actual output device (HDMI etc.), rounding was ses

s/ses/set/

> to round-down. As the DPU uses a higher internal number of bits when

"round-down" isn't really accurate - the rounding mode "rounds" based
on the most-significant discarded bit - so can round-up too.

Come to think of it, I can't explain 0xff becoming 0xfe, but still,
truncation is likely fine.

> generating a color value, this round-down back to 8bit ended up with
> everything being off-by one. e.g. #ffffff became #fefefe. This sets
> rounding to "round" so things end up correct by turning on the round
> flag (LW_TRC).

LW_TRC is the truncation flag. 0: Round, 1: Truncate

> 
> Signed-off-by: Carsten Haitzler <carsten.haitzler@arm.com>
> ---
>  drivers/gpu/drm/arm/display/komeda/d71/d71_component.c | 6 +++++-
>  drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h      | 1 +
>  2 files changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
> index 8a02ade369db..d551e79fa0f1 100644
> --- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
> +++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
> @@ -468,7 +468,11 @@ static void d71_wb_layer_update(struct komeda_component *c,
>  	struct komeda_layer_state *st = to_layer_st(state);
>  	struct drm_connector_state *conn_st = state->wb_conn->state;
>  	struct komeda_fb *kfb = to_kfb(conn_st->writeback_job->fb);
> -	u32 ctrl = L_EN | LW_OFM, mask = L_EN | LW_OFM | LW_TBU_EN;
> +	/* LW_TRC sets rounding to round not truncate which is needed for
> +         * the output of writeback to match the input in the most common
> +         * use cases like RGB888 -> RGB888, so set this bit by default */

/*
 * Comment style should be like this
 */

Same as above though - your description is inverted. By setting the
LW_TRC bit, you're forcing the hardware to truncate instead of round.

> +	u32 ctrl = L_EN | LW_OFM | LW_TRC;
> +	u32 mask = L_EN | LW_OFM | LW_TBU_EN | LW_TRC;

Really nitpicking, but I think it'd be good to keep these in the same
order as the bits in the register: L_EN | LW_TRC | LW_OFM | LW_TBU_EN

Cheers,
-Brian

>  	u32 __iomem *reg = c->reg;
>  
>  	d71_layer_update_fb(c, kfb, st->addr);
> diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h b/drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h
> index e80172a0b320..a8036689d721 100644
> --- a/drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h
> +++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h
> @@ -321,6 +321,7 @@
>  #define LAYER_WR_FORMAT		0x0D8
>  
>  /* Layer_WR control bits */
> +#define LW_TRC			BIT(1)
>  #define LW_OFM			BIT(4)
>  #define LW_LALPHA(x)		(((x) & 0xFF) << 8)
>  #define LW_A_WCACHE(x)		(((x) & 0xF) << 28)
> -- 
> 2.30.0
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
Carsten Haitzler March 11, 2021, 11:55 a.m. UTC | #2
On 3/9/21 11:36 AM, Brian Starkey wrote:
> Hi Carsten, (+James for komeda)
> 
> Thanks for typing this up.
> 
> On Fri, Mar 05, 2021 at 04:38:53PM +0000, carsten.haitzler@foss.arm.com wrote:
>> From: Carsten Haitzler <carsten.haitzler@arm.com>
>>
>> When setting up a readback conenctor that writes data back to memory
> 
> s/readback conenctor/writeback connector/ (similar in the subject)
> 
>> rather than to an actual output device (HDMI etc.), rounding was ses
> 
> s/ses/set/

I swear I re-read the log text... I must be auto-correcting in my head 
as I read. :)

>> to round-down. As the DPU uses a higher internal number of bits when
> 
> "round-down" isn't really accurate - the rounding mode "rounds" based
> on the most-significant discarded bit - so can round-up too.
> 
> Come to think of it, I can't explain 0xff becoming 0xfe, but still,
> truncation is likely fine.

Actually it was the other way - I mixed up the src/dest, but TRC does 
fix it which is the important bit.

>> generating a color value, this round-down back to 8bit ended up with
>> everything being off-by one. e.g. #ffffff became #fefefe. This sets
>> rounding to "round" so things end up correct by turning on the round
>> flag (LW_TRC).
> 
> LW_TRC is the truncation flag. 0: Round, 1: Truncate
> 
>>
>> Signed-off-by: Carsten Haitzler <carsten.haitzler@arm.com>
>> ---
>>   drivers/gpu/drm/arm/display/komeda/d71/d71_component.c | 6 +++++-
>>   drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h      | 1 +
>>   2 files changed, 6 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
>> index 8a02ade369db..d551e79fa0f1 100644
>> --- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
>> +++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
>> @@ -468,7 +468,11 @@ static void d71_wb_layer_update(struct komeda_component *c,
>>   	struct komeda_layer_state *st = to_layer_st(state);
>>   	struct drm_connector_state *conn_st = state->wb_conn->state;
>>   	struct komeda_fb *kfb = to_kfb(conn_st->writeback_job->fb);
>> -	u32 ctrl = L_EN | LW_OFM, mask = L_EN | LW_OFM | LW_TBU_EN;
>> +	/* LW_TRC sets rounding to round not truncate which is needed for
>> +         * the output of writeback to match the input in the most common
>> +         * use cases like RGB888 -> RGB888, so set this bit by default */
> 
> /*
>   * Comment style should be like this
>   */
> 
> Same as above though - your description is inverted. By setting the
> LW_TRC bit, you're forcing the hardware to truncate instead of round.

Yeah - inverted. But the source does have mixed comment styles with some
/*
  * xxxx
  */

and some

/* xxxx */

and some

/* xxxx
  */

with the last 2 most common.

>> +	u32 ctrl = L_EN | LW_OFM | LW_TRC;
>> +	u32 mask = L_EN | LW_OFM | LW_TBU_EN | LW_TRC;
> 
> Really nitpicking, but I think it'd be good to keep these in the same
> order as the bits in the register: L_EN | LW_TRC | LW_OFM | LW_TBU_EN

I can do that. I'll send another with the above.

> Cheers,
> -Brian
> 
>>   	u32 __iomem *reg = c->reg;
>>   
>>   	d71_layer_update_fb(c, kfb, st->addr);
>> diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h b/drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h
>> index e80172a0b320..a8036689d721 100644
>> --- a/drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h
>> +++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h
>> @@ -321,6 +321,7 @@
>>   #define LAYER_WR_FORMAT		0x0D8
>>   
>>   /* Layer_WR control bits */
>> +#define LW_TRC			BIT(1)
>>   #define LW_OFM			BIT(4)
>>   #define LW_LALPHA(x)		(((x) & 0xFF) << 8)
>>   #define LW_A_WCACHE(x)		(((x) & 0xF) << 28)
>> -- 
>> 2.30.0
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
diff mbox series

Patch

diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
index 8a02ade369db..d551e79fa0f1 100644
--- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
+++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
@@ -468,7 +468,11 @@  static void d71_wb_layer_update(struct komeda_component *c,
 	struct komeda_layer_state *st = to_layer_st(state);
 	struct drm_connector_state *conn_st = state->wb_conn->state;
 	struct komeda_fb *kfb = to_kfb(conn_st->writeback_job->fb);
-	u32 ctrl = L_EN | LW_OFM, mask = L_EN | LW_OFM | LW_TBU_EN;
+	/* LW_TRC sets rounding to round not truncate which is needed for
+         * the output of writeback to match the input in the most common
+         * use cases like RGB888 -> RGB888, so set this bit by default */
+	u32 ctrl = L_EN | LW_OFM | LW_TRC;
+	u32 mask = L_EN | LW_OFM | LW_TBU_EN | LW_TRC;
 	u32 __iomem *reg = c->reg;
 
 	d71_layer_update_fb(c, kfb, st->addr);
diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h b/drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h
index e80172a0b320..a8036689d721 100644
--- a/drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h
+++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h
@@ -321,6 +321,7 @@ 
 #define LAYER_WR_FORMAT		0x0D8
 
 /* Layer_WR control bits */
+#define LW_TRC			BIT(1)
 #define LW_OFM			BIT(4)
 #define LW_LALPHA(x)		(((x) & 0xFF) << 8)
 #define LW_A_WCACHE(x)		(((x) & 0xF) << 28)