[Intel-gfx] [PATCH v2 4/5] drm/i915/display: Add Nearest-neighbor based integer scaling support
Ville Syrjälä
ville.syrjala at linux.intel.com
Mon Mar 23 14:41:37 UTC 2020
On Thu, Mar 19, 2020 at 03:51:02PM +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 skl_scaler_setup_nearest_neighbor_filter() function which
> configures the scaler filter coefficients to enable nearest-neighbor
> filtering.
>
> Bspec: 49247
>
> 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)
>
> 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 | 72 ++++++++++++++++++++
> drivers/gpu/drm/i915/display/intel_display.h | 2 +
> 2 files changed, 74 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 8f23c4d51c33..791dd908aa89 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -6237,6 +6237,78 @@ void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state)
> skl_detach_scaler(crtc, i);
> }
>
> +static int skl_coef_tap(int i)
> +{
> + return i % 7;
> +}
> +
> +static u16 skl_nearest_filter_coef(int t)
> +{
> + return t == 3 ? 0x0800 : 0x3000;
> +}
> +
> +/**
> + * 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
> + *
> + */
> +
> +void skl_scaler_setup_nearest_neighbor_filter(struct drm_i915_private *dev_priv,
> + enum pipe pipe, int id, int set)
> +{
> + int i;
> +
> + /*enable the index auto increment.*/
Pointless comment, and also misformatted.
> + intel_de_write_fw(dev_priv,
> + SKL_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 = skl_coef_tap(i);
> + tmp = skl_nearest_filter_coef(t);
> +
> + t = skl_coef_tap(i+1);
> + tmp |= skl_nearest_filter_coef(t)<<16;
Missing spaces.
> +
> + intel_de_write_fw(dev_priv, SKL_PS_COEF_DATA_SET(pipe, id, set),
> + tmp);
> + }
I'd maybe reset the index back to 0 here and disable the auto-increment
bit.
> +}
> +
> 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 adb1225a3480..88f3c77f6806 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -587,6 +587,8 @@ void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
> u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_center);
> int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
> void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state);
> +void skl_scaler_setup_nearest_neighbor_filter(struct drm_i915_private *dev_priv,
> + enum pipe pipe, int id, int set);
> 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