summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLaurentiu Palcu <laurentiu.palcu@nxp.com>2019-02-14 10:39:21 +0200
committerLaurentiu Palcu <laurentiu.palcu@nxp.com>2019-02-19 13:24:14 +0200
commit453ee22cb16d11bf6357b6d0bd62eee12d368197 (patch)
tree097f435efc0c358c1ea195b16b55bfb687bdb2df /drivers
parentad41641effaa6507dfb48013ba8174e35c60263e (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.c72
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);