[Intel-gfx] [PATCH v6 4/5] drm/i915/display: Add Nearest-neighbor based integer scaling support
Ville Syrjälä
ville.syrjala at linux.intel.com
Tue Oct 20 15:02:23 UTC 2020
On Tue, Oct 13, 2020 at 12:11:29AM +0530, Pankaj Bharadiya wrote:
> Integer scaling (IS) is a nearest-neighbor upscaling technique that
> simply scales up the existing pixels by an integer
> (i.e., whole number) multiplier.Nearest-neighbor (NN) interpolation
> works by filling in the missing color values in the upscaled image
> with that of the coordinate-mapped nearest source pixel value.
>
> Both IS and NN preserve the clarity of the original image. Integer
> scaling is particularly useful for pixel art games that rely on
> sharp, blocky images to deliver their distinctive look.
>
> Introduce functions to configure the scaler filter coefficients to
> enable nearest-neighbor filtering.
>
> Bspec: 49247
>
> changes since v4:
> * Make cnl_coef_tap(), cnl_nearest_filter_coef() inline (Uma)
> changes since v3:
> * None
> changes since v2:
> * Move APIs from 5/5 into this patch.
> * Change filter programming related function names to cnl_*, move
> filter select bits related code into inline function (Ville)
> changes since v1:
> * Rearrange skl_scaler_setup_nearest_neighbor_filter() to iterate the
> registers directly instead of the phases and taps (Ville)
>
> changes since RFC:
> * Refine the skl_scaler_setup_nearest_neighbor_filter() logic (Ville)
>
> Reviewed-by: Uma Shankar <uma.shankar at intel.com>
> Signed-off-by: Shashank Sharma <shashank.sharma at intel.com>
> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal at intel.com>
> Signed-off-by: Pankaj Bharadiya <pankaj.laxminarayan.bharadiya at intel.com>
> ---
> drivers/gpu/drm/i915/display/intel_display.c | 99 ++++++++++++++++++++
> drivers/gpu/drm/i915/display/intel_display.h | 4 +
> 2 files changed, 103 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index cf1417ff54d7..871a1f44a2bd 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -6285,6 +6285,105 @@ void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state)
> skl_detach_scaler(crtc, i);
> }
>
> +static inline int cnl_coef_tap(int i)
> +{
> + return i % 7;
> +}
> +
> +static inline u16 cnl_nearest_filter_coef(int t)
> +{
> + return t == 3 ? 0x0800 : 0x3000;
> +}
If the compiler doesn't inline these without manual help then the
compiler is broken. So I'd just drop these pointless inline keywords.
Quick scan over all the rest looks OK.
>From my POV it all looks good so for the series:
Reviewed-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
But please address Simon's concerns about the kernel docs.
> +
> +/**
> + * Theory behind setting nearest-neighbor integer scaling:
> + *
> + * 17 phase of 7 taps requires 119 coefficients in 60 dwords per set.
> + * The letter represents the filter tap (D is the center tap) and the number
> + * represents the coefficient set for a phase (0-16).
> + *
> + * +------------+------------------------+------------------------+
> + * |Index value | Data value coeffient 1 | Data value coeffient 2 |
> + * +------------+------------------------+------------------------+
> + * | 00h | B0 | A0 |
> + * +------------+------------------------+------------------------+
> + * | 01h | D0 | C0 |
> + * +------------+------------------------+------------------------+
> + * | 02h | F0 | E0 |
> + * +------------+------------------------+------------------------+
> + * | 03h | A1 | G0 |
> + * +------------+------------------------+------------------------+
> + * | 04h | C1 | B1 |
> + * +------------+------------------------+------------------------+
> + * | ... | ... | ... |
> + * +------------+------------------------+------------------------+
> + * | 38h | B16 | A16 |
> + * +------------+------------------------+------------------------+
> + * | 39h | D16 | C16 |
> + * +------------+------------------------+------------------------+
> + * | 3Ah | F16 | C16 |
> + * +------------+------------------------+------------------------+
> + * | 3Bh | Reserved | G16 |
> + * +------------+------------------------+------------------------+
> + *
> + * To enable nearest-neighbor scaling: program scaler coefficents with
> + * the center tap (Dxx) values set to 1 and all other values set to 0 as per
> + * SCALER_COEFFICIENT_FORMAT
> + *
> + */
> +
> +static void cnl_program_nearest_filter_coefs(struct drm_i915_private *dev_priv,
> + enum pipe pipe, int id, int set)
> +{
> + int i;
> +
> + intel_de_write_fw(dev_priv, CNL_PS_COEF_INDEX_SET(pipe, id, set),
> + PS_COEE_INDEX_AUTO_INC);
> +
> + for (i = 0; i < 17 * 7; i += 2) {
> + u32 tmp;
> + int t;
> +
> + t = cnl_coef_tap(i);
> + tmp = cnl_nearest_filter_coef(t);
> +
> + t = cnl_coef_tap(i + 1);
> + tmp |= cnl_nearest_filter_coef(t) << 16;
> +
> + intel_de_write_fw(dev_priv, CNL_PS_COEF_DATA_SET(pipe, id, set),
> + tmp);
> + }
> +
> + intel_de_write_fw(dev_priv, CNL_PS_COEF_INDEX_SET(pipe, id, set), 0);
> +}
> +
> +inline u32 skl_scaler_get_filter_select(enum drm_scaling_filter filter, int set)
> +{
> + if (filter == DRM_SCALING_FILTER_NEAREST_NEIGHBOR) {
> + return (PS_FILTER_PROGRAMMED |
> + PS_Y_VERT_FILTER_SELECT(set) |
> + PS_Y_HORZ_FILTER_SELECT(set) |
> + PS_UV_VERT_FILTER_SELECT(set) |
> + PS_UV_HORZ_FILTER_SELECT(set));
> + }
> +
> + return PS_FILTER_MEDIUM;
> +}
> +
> +void skl_scaler_setup_filter(struct drm_i915_private *dev_priv, enum pipe pipe,
> + int id, int set, enum drm_scaling_filter filter)
> +{
> + switch (filter) {
> + case DRM_SCALING_FILTER_DEFAULT:
> + break;
> + case DRM_SCALING_FILTER_NEAREST_NEIGHBOR:
> + cnl_program_nearest_filter_coefs(dev_priv, pipe, id, set);
> + break;
> + default:
> + MISSING_CASE(filter);
> + }
> +}
> +
> static void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
> {
> struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index d10b7c8cde3f..1b946209e06b 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -28,6 +28,7 @@
> #include <drm/drm_util.h>
>
> enum link_m_n_set;
> +enum drm_scaling_filter;
> struct dpll;
> struct drm_connector;
> struct drm_device;
> @@ -599,6 +600,9 @@ void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
>
> u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_center);
> void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state);
> +u32 skl_scaler_get_filter_select(enum drm_scaling_filter filter, int set);
> +void skl_scaler_setup_filter(struct drm_i915_private *dev_priv, enum pipe pipe,
> + int id, int set, enum drm_scaling_filter filter);
> void ilk_pfit_disable(const struct intel_crtc_state *old_crtc_state);
> u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
> const struct intel_plane_state *plane_state);
> --
> 2.23.0
--
Ville Syrjälä
Intel
More information about the Intel-gfx
mailing list