From 453ee22cb16d11bf6357b6d0bd62eee12d368197 Mon Sep 17 00:00:00 2001 From: Laurentiu Palcu <laurentiu.palcu@nxp.com> Date: Thu, 14 Feb 2019 10:39:21 +0200 Subject: [PATCH] MLK-20931: drm/imx/dcss: Add scaler 5 tap filter back for YUV The following commit: 459a5fac54d - MLK-20263: drm/imx/dcss: fix channel-0 line shift removed the 5 tap filter for vertical luma/chroma when YUV formats were used. Problem is that when the 7 tap filter is used for vertical luma/chroma, artifacts can be seen on screen when scaling. RGB can, however, function correctly with only 7 tap filter. This patch partially reverts the above patch and also does some cosmetic changes when calling the dcss_scaler_filter_design() using false/true instead of 0/1 for use_5_taps argument. Signed-off-by: Laurentiu Palcu <laurentiu.palcu@nxp.com> --- drivers/gpu/imx/dcss/dcss-scaler.c | 72 +++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/imx/dcss/dcss-scaler.c b/drivers/gpu/imx/dcss/dcss-scaler.c index abddd129169ced..051bc4b03f8864 100644 --- a/drivers/gpu/imx/dcss/dcss-scaler.c +++ b/drivers/gpu/imx/dcss/dcss-scaler.c @@ -657,6 +657,46 @@ bool dcss_scaler_can_scale(struct dcss_soc *dcss, int ch_num, } EXPORT_SYMBOL(dcss_scaler_can_scale); +static void dcss_scaler_program_5_coef_set(struct dcss_soc *dcss, int ch_num, + int base_addr, + int coef[][PSC_NUM_TAPS]) +{ + int i, phase; + + for (i = 0; i < PSC_STORED_PHASES; i++) { + dcss_scaler_write(dcss->scaler_priv, ch_num, + ((coef[i][1] & 0xfff) << 16 | + (coef[i][2] & 0xfff) << 4 | + (coef[i][3] & 0xf00) >> 8), + base_addr + i * sizeof(u32)); + dcss_scaler_write(dcss->scaler_priv, ch_num, + ((coef[i][3] & 0x0ff) << 20 | + (coef[i][4] & 0xfff) << 8 | + (coef[i][5] & 0xff0) >> 4), + base_addr + 0x40 + i * sizeof(u32)); + dcss_scaler_write(dcss->scaler_priv, ch_num, + ((coef[i][5] & 0x00f) << 24), + base_addr + 0x80 + i * sizeof(u32)); + } + + /* reverse both phase and tap orderings */ + for (phase = (PSC_NUM_PHASES >> 1) - 1; i < PSC_NUM_PHASES; i++, phase--) { + dcss_scaler_write(dcss->scaler_priv, ch_num, + ((coef[phase][5] & 0xfff) << 16 | + (coef[phase][4] & 0xfff) << 4 | + (coef[phase][3] & 0xf00) >> 8), + base_addr + i * sizeof(u32)); + dcss_scaler_write(dcss->scaler_priv, ch_num, + ((coef[phase][3] & 0x0ff) << 20 | + (coef[phase][2] & 0xfff) << 8 | + (coef[phase][1] & 0xff0) >> 4), + base_addr + 0x40 + i * sizeof(u32)); + dcss_scaler_write(dcss->scaler_priv, ch_num, + ((coef[phase][1] & 0x00f) << 24), + base_addr + 0x80 + i * sizeof(u32)); + } +} + static void dcss_scaler_program_7_coef_set(struct dcss_soc *dcss, int ch_num, int base_addr, int coef[][PSC_NUM_TAPS]) @@ -710,19 +750,26 @@ static void dcss_scaler_yuv_coef_set(struct dcss_soc *dcss, int ch_num, { struct dcss_scaler_ch *ch = &dcss->scaler_priv->ch[ch_num]; int coef[PSC_STORED_PHASES][PSC_NUM_TAPS]; + bool program_5_taps = use_5_taps || + (dst_format == BUF_FMT_YUV422 && + src_format == BUF_FMT_ARGB8888_YUV444); /* horizontal luma */ - dcss_scaler_filter_design(src_xres, dst_xres, 0, + dcss_scaler_filter_design(src_xres, dst_xres, false, src_xres == dst_xres, coef); dcss_scaler_program_7_coef_set(dcss, ch_num, DCSS_SCALER_COEF_HLUM, coef); /* vertical luma */ - dcss_scaler_filter_design(src_yres, dst_yres, use_5_taps, + dcss_scaler_filter_design(src_yres, dst_yres, program_5_taps, src_yres == dst_yres, coef); - dcss_scaler_program_7_coef_set(dcss, ch_num, - DCSS_SCALER_COEF_VLUM, coef); + if (program_5_taps) + dcss_scaler_program_5_coef_set(dcss, ch_num, + DCSS_SCALER_COEF_VLUM, coef); + else + dcss_scaler_program_7_coef_set(dcss, ch_num, + DCSS_SCALER_COEF_VLUM, coef); /* adjust chroma resolution */ if (src_format != BUF_FMT_ARGB8888_YUV444) @@ -735,7 +782,7 @@ static void dcss_scaler_yuv_coef_set(struct dcss_soc *dcss, int ch_num, dst_yres >>= 1; /* horizontal chroma */ - dcss_scaler_filter_design(src_xres, dst_xres, 0, + dcss_scaler_filter_design(src_xres, dst_xres, false, (src_xres == dst_xres) && (ch->c_hstart == 0), coef); @@ -743,12 +790,15 @@ static void dcss_scaler_yuv_coef_set(struct dcss_soc *dcss, int ch_num, DCSS_SCALER_COEF_HCHR, coef); /* vertical chroma */ - dcss_scaler_filter_design(src_yres, dst_yres, use_5_taps, + dcss_scaler_filter_design(src_yres, dst_yres, program_5_taps, (src_yres == dst_yres) && (ch->c_vstart == 0), coef); - - dcss_scaler_program_7_coef_set(dcss, ch_num, - DCSS_SCALER_COEF_VCHR, coef); + if (program_5_taps) + dcss_scaler_program_5_coef_set(dcss, ch_num, + DCSS_SCALER_COEF_VCHR, coef); + else + dcss_scaler_program_7_coef_set(dcss, ch_num, + DCSS_SCALER_COEF_VCHR, coef); } static void dcss_scaler_rgb_coef_set(struct dcss_soc *dcss, int ch_num, @@ -758,13 +808,13 @@ static void dcss_scaler_rgb_coef_set(struct dcss_soc *dcss, int ch_num, int coef[PSC_STORED_PHASES][PSC_NUM_TAPS]; /* horizontal RGB */ - dcss_scaler_filter_design(src_xres, dst_xres, 0, + dcss_scaler_filter_design(src_xres, dst_xres, false, src_xres == dst_xres, coef); dcss_scaler_program_7_coef_set(dcss, ch_num, DCSS_SCALER_COEF_HLUM, coef); /* vertical RGB */ - dcss_scaler_filter_design(src_yres, dst_yres, 1, + dcss_scaler_filter_design(src_yres, dst_yres, false, src_yres == dst_yres, coef); dcss_scaler_program_7_coef_set(dcss, ch_num, DCSS_SCALER_COEF_VLUM, coef); -- GitLab