[PATCH v10 04/16] drm/mediatek: gamma: Improve and simplify HW LUT calculation

AngeloGioacchino Del Regno posted 16 patches 1 year, 3 months ago
There is a newer version of this series
[PATCH v10 04/16] drm/mediatek: gamma: Improve and simplify HW LUT calculation
Posted by AngeloGioacchino Del Regno 1 year, 3 months ago
Use drm_color_lut_extract() to avoid open-coding the bits reduction
calculations for each color channel and use a struct drm_color_lut
to temporarily store the information instead of an array of u32.

Also, slightly improve the precision of the HW LUT calculation in the
LUT DIFF case by performing the subtractions on the 16-bits values and
doing the 10 bits conversion later.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Jason-JH.Lin <jason-jh.lin@mediatek.com>
Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
---
 drivers/gpu/drm/mediatek/mtk_disp_gamma.c | 30 +++++++++++++++--------
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_gamma.c b/drivers/gpu/drm/mediatek/mtk_disp_gamma.c
index 7575237625d2..fd6a75a64a9f 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_gamma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_gamma.c
@@ -74,7 +74,6 @@ void mtk_gamma_set_common(struct device *dev, void __iomem *regs, struct drm_crt
 	bool lut_diff;
 	u16 lut_size;
 	u32 word;
-	u32 diff[3] = {0};
 
 	/* If there's no gamma lut there's nothing to do here. */
 	if (!state->gamma_lut)
@@ -97,18 +96,29 @@ void mtk_gamma_set_common(struct device *dev, void __iomem *regs, struct drm_crt
 	lut_base = regs + DISP_GAMMA_LUT;
 	lut = (struct drm_color_lut *)state->gamma_lut->data;
 	for (i = 0; i < lut_size; i++) {
+		struct drm_color_lut diff, hwlut;
+
+		hwlut.red = drm_color_lut_extract(lut[i].red, 10);
+		hwlut.green = drm_color_lut_extract(lut[i].green, 10);
+		hwlut.blue = drm_color_lut_extract(lut[i].blue, 10);
+
 		if (!lut_diff || (i % 2 == 0)) {
-			word = (((lut[i].red >> 6) & LUT_10BIT_MASK) << 20) +
-				(((lut[i].green >> 6) & LUT_10BIT_MASK) << 10) +
-				((lut[i].blue >> 6) & LUT_10BIT_MASK);
+			word = hwlut.red << 20 +
+			       hwlut.green << 10 +
+			       hwlut.red;
 		} else {
-			diff[0] = (lut[i].red >> 6) - (lut[i - 1].red >> 6);
-			diff[1] = (lut[i].green >> 6) - (lut[i - 1].green >> 6);
-			diff[2] = (lut[i].blue >> 6) - (lut[i - 1].blue >> 6);
+			diff.red = lut[i].red - lut[i - 1].red;
+			diff.red = drm_color_lut_extract(diff.red, 10);
+
+			diff.green = lut[i].green - lut[i - 1].green;
+			diff.green = drm_color_lut_extract(diff.green, 10);
+
+			diff.blue = lut[i].blue - lut[i - 1].blue;
+			diff.blue = drm_color_lut_extract(diff.blue, 10);
 
-			word = ((diff[0] & LUT_10BIT_MASK) << 20) +
-				((diff[1] & LUT_10BIT_MASK) << 10) +
-				(diff[2] & LUT_10BIT_MASK);
+			word = diff.blue << 20 +
+			       diff.green << 10 +
+			       diff.red;
 		}
 		writel(word, (lut_base + i * 4));
 	}
-- 
2.41.0
Re: [PATCH v10 04/16] drm/mediatek: gamma: Improve and simplify HW LUT calculation
Posted by CK Hu (胡俊光) 1 year, 1 month ago
Hi, Angelo:

On Fri, 2023-08-04 at 09:28 +0200, AngeloGioacchino Del Regno wrote:
> Use drm_color_lut_extract() to avoid open-coding the bits reduction
> calculations for each color channel and use a struct drm_color_lut
> to temporarily store the information instead of an array of u32.
> 
> Also, slightly improve the precision of the HW LUT calculation in the
> LUT DIFF case by performing the subtractions on the 16-bits values
> and
> doing the 10 bits conversion later.
> 
> Signed-off-by: AngeloGioacchino Del Regno <
> angelogioacchino.delregno@collabora.com>
> Reviewed-by: Jason-JH.Lin <jason-jh.lin@mediatek.com>
> Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_disp_gamma.c | 30 +++++++++++++++----
> ----
>  1 file changed, 20 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_gamma.c
> b/drivers/gpu/drm/mediatek/mtk_disp_gamma.c
> index 7575237625d2..fd6a75a64a9f 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_gamma.c
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_gamma.c
> @@ -74,7 +74,6 @@ void mtk_gamma_set_common(struct device *dev, void
> __iomem *regs, struct drm_crt
>  	bool lut_diff;
>  	u16 lut_size;
>  	u32 word;
> -	u32 diff[3] = {0};
>  
>  	/* If there's no gamma lut there's nothing to do here. */
>  	if (!state->gamma_lut)
> @@ -97,18 +96,29 @@ void mtk_gamma_set_common(struct device *dev,
> void __iomem *regs, struct drm_crt
>  	lut_base = regs + DISP_GAMMA_LUT;
>  	lut = (struct drm_color_lut *)state->gamma_lut->data;
>  	for (i = 0; i < lut_size; i++) {
> +		struct drm_color_lut diff, hwlut;
> +
> +		hwlut.red = drm_color_lut_extract(lut[i].red, 10);
> +		hwlut.green = drm_color_lut_extract(lut[i].green, 10);
> +		hwlut.blue = drm_color_lut_extract(lut[i].blue, 10);
> +
>  		if (!lut_diff || (i % 2 == 0)) {
> -			word = (((lut[i].red >> 6) & LUT_10BIT_MASK) <<
> 20) +

After removing definition of LUT_10BIT_MASK,

Reviewed-by: CK Hu <ck.hu@mediatek.com>

> -				(((lut[i].green >> 6) & LUT_10BIT_MASK)
> << 10) +
> -				((lut[i].blue >> 6) & LUT_10BIT_MASK);
> +			word = hwlut.red << 20 +
> +			       hwlut.green << 10 +
> +			       hwlut.red;
>  		} else {
> -			diff[0] = (lut[i].red >> 6) - (lut[i - 1].red
> >> 6);
> -			diff[1] = (lut[i].green >> 6) - (lut[i -
> 1].green >> 6);
> -			diff[2] = (lut[i].blue >> 6) - (lut[i - 1].blue
> >> 6);
> +			diff.red = lut[i].red - lut[i - 1].red;
> +			diff.red = drm_color_lut_extract(diff.red, 10);
> +
> +			diff.green = lut[i].green - lut[i - 1].green;
> +			diff.green = drm_color_lut_extract(diff.green,
> 10);
> +
> +			diff.blue = lut[i].blue - lut[i - 1].blue;
> +			diff.blue = drm_color_lut_extract(diff.blue,
> 10);
>  
> -			word = ((diff[0] & LUT_10BIT_MASK) << 20) +
> -				((diff[1] & LUT_10BIT_MASK) << 10) +
> -				(diff[2] & LUT_10BIT_MASK);
> +			word = diff.blue << 20 +
> +			       diff.green << 10 +
> +			       diff.red;
>  		}
>  		writel(word, (lut_base + i * 4));
>  	}