diff options
author | Laurentiu Palcu <laurentiu.palcu@nxp.com> | 2019-02-14 10:39:21 +0200 |
---|---|---|
committer | Laurentiu Palcu <laurentiu.palcu@nxp.com> | 2019-02-19 13:24:14 +0200 |
commit | 453ee22cb16d11bf6357b6d0bd62eee12d368197 (patch) | |
tree | 097f435efc0c358c1ea195b16b55bfb687bdb2df /drivers | |
parent | ad41641effaa6507dfb48013ba8174e35c60263e (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/imx/dcss/dcss-scaler.c | 72 |
1 files changed, 61 insertions, 11 deletions
diff --git a/drivers/gpu/imx/dcss/dcss-scaler.c b/drivers/gpu/imx/dcss/dcss-scaler.c index abddd129169c..051bc4b03f88 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); |