[Intel-gfx] [RFC 2/2] drm/i915: Pick nearest-neighbor mode for integer scaling ratios
Ramalingam C
ramalingam.c at intel.com
Wed Sep 4 07:54:17 UTC 2019
On 2019-09-03 at 22:22:27 +0530, Shashank Sharma wrote:
> Nearest-neighbor, is a new scaling mode, introduced in GEN11 display HW.
> Nearest-neighbor results in blurless outputs, when upscaling ratio is a
> complete integer ratio like:
>
> - upscaling from 1280x720(HD) to 3840x2160(UHD/4K)
> horizontal upscaling factor = 3840/1280 = 3
> vertical upscaling factor = 2160/720 = 3
>
> This is an example of a scenario with integer scaling ratios, and if we
> can pick nearest-neighbor mode scaling in display, it can produce sharp
> and non-blurry output, compared to the default scaling mode selected by
> I915 ("medium").
>
> PS: NN has been introduced from GEN11 display HW only.
>
> Cc: Jani Nikula <jani.nikula at intel.com>
> Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter at intel.com>
> Cc: Vivi, Rodrigo <rodrigo.vivi at intel.com>
> Signed-off-by: Shashank Sharma <shashank.sharma at intel.com>
> ---
> drivers/gpu/drm/i915/display/intel_display.c | 81 +++++++++++++++++++-
> drivers/gpu/drm/i915/i915_reg.h | 31 ++++++++
> 2 files changed, 111 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 613130db3c05..9808797a92d9 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -5613,6 +5613,74 @@ static void skylake_scaler_disable(struct intel_crtc *crtc)
> skl_detach_scaler(crtc, i);
> }
>
> +static void
> +icl_setup_nearest_neighbor_mode(const struct intel_crtc_state *crtc_state)
> +{
> + int count;
> + int phase;
> + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
> + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> + int scaler_id = crtc_state->scaler_state.scaler_id;
> + enum pipe pipe = crtc->pipe;
> +
> + /*
> + * To setup nearest-neighbor integer scaling mode:
> + * Write 60 dwords: represnting 119 coefficients.
> + *
> + * Seven basic Coefficients are named from An......Gn.
> + * Value of every D'th coefficent must be 1, all others to be 0.
> + *
> + * 17 such phases of 7 such coefficients = 119 coefficients.
> + * Arrange these 119 coefficients in 60 dwords, 2 coefficient
> + * per dword, in the sequence shown below:
> + *
> + *+------------+--------------+
> + *| B0 | A0 |
> + *+---------------------------+
> + *| D0 = 1 | C0 |
> + *+---------------------------+
> + *| F0 | E0 |
> + *+---------------------------+
> + *| A1 | G0 |
> + *+---------------------------+
> + *| C1 | B1 |
> + *+---------------------------+
> + *| E1 | D1 = 1 |
> + *+---------------------------+
> + *| ..... | ..... |
> + *+---------------------------+
> + *| ...... | ...... |
> + *+---------------------------+
> + *| Res | G16 |
> + *+------------+--------------+
> + *
> + */
> +
> + for (phase = 0; phase < 17; phase++) {
> + for (count = 0; count < 7; count++) {
> + u32 val = 0;
> +
> + /* Every D'th entry needs to be 1 */
> + if (count == 3) {
> + if (phase % 2)
> + val = 1;
> + else
> + val = (1 << 16);
> + }
> +
> + I915_WRITE_FW(SKL_PS_COEF_INDEX_SET0(pipe, scaler_id),
> + phase * 17 + count);
> + I915_WRITE_FW(SKL_PS_COEF_DATA_SET0(pipe, scaler_id),
> + val);
> +
> + I915_WRITE_FW(SKL_PS_COEF_INDEX_SET1(pipe, scaler_id),
> + phase * 17 + count);
> + I915_WRITE_FW(SKL_PS_COEF_DATA_SET1(pipe, scaler_id),
> + val);
Shouldn't we take the 16 MSBites of val here? Am I missing something in
macro!
-Ram
> + }
> + }
> +}
> +
> static void skylake_pfit_enable(const struct intel_crtc_state *crtc_state)
> {
> struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
> @@ -5623,6 +5691,7 @@ static void skylake_pfit_enable(const struct intel_crtc_state *crtc_state)
>
> if (crtc_state->pch_pfit.enabled) {
> u16 uv_rgb_hphase, uv_rgb_vphase;
> + u32 scaler_mode = PS_FILTER_MEDIUM;
> int pfit_w, pfit_h, hscale, vscale;
> int id;
>
> @@ -5638,9 +5707,19 @@ static void skylake_pfit_enable(const struct intel_crtc_state *crtc_state)
> uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
> uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
>
> + /*
> + * Pick nearest-neighbor scaler mode over medium, if scaling
> + * is happening at integer ratios.
> + */
> + if (INTEL_GEN(dev_priv) >= 11 &&
> + scaler_state->integer_scaling) {
> + scaler_mode = PS_FILTER_PROGRAMMED;
> + icl_setup_nearest_neighbor_mode(crtc_state);
> + }
> +
> id = scaler_state->scaler_id;
> I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |
> - PS_FILTER_MEDIUM | scaler_state->scalers[id].mode);
> + scaler_mode | scaler_state->scalers[id].mode);
> I915_WRITE_FW(SKL_PS_VPHASE(pipe, id),
> PS_Y_PHASE(0) | PS_UV_RGB_PHASE(uv_rgb_vphase));
> I915_WRITE_FW(SKL_PS_HPHASE(pipe, id),
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index ea2f0fa2402d..42fdff3bbf29 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -7062,6 +7062,7 @@ enum {
> #define PS_PLANE_SEL(plane) (((plane) + 1) << 25)
> #define PS_FILTER_MASK (3 << 23)
> #define PS_FILTER_MEDIUM (0 << 23)
> +#define PS_FILTER_PROGRAMMED (1 << 23)
> #define PS_FILTER_EDGE_ENHANCE (2 << 23)
> #define PS_FILTER_BILINEAR (3 << 23)
> #define PS_VERT3TAP (1 << 21)
> @@ -7138,6 +7139,24 @@ enum {
> #define _PS_ECC_STAT_2B 0x68AD0
> #define _PS_ECC_STAT_1C 0x691D0
>
> +#define _PS_COEF_SET0_INDEX_1A 0x68198
> +#define _PS_COEF_SET0_INDEX_2A 0x68298
> +#define _PS_COEF_SET0_INDEX_1B 0x68998
> +#define _PS_COEF_SET0_INDEX_2B 0x68A98
> +#define _PS_COEF_SET1_INDEX_1A 0x681A0
> +#define _PS_COEF_SET1_INDEX_2A 0x682A0
> +#define _PS_COEF_SET1_INDEX_1B 0x689A0
> +#define _PS_COEF_SET1_INDEX_2B 0x68AA0
> +
> +#define _PS_COEF_SET0_DATA_1A 0x6819C
> +#define _PS_COEF_SET0_DATA_2A 0x6829C
> +#define _PS_COEF_SET0_DATA_1B 0x6899C
> +#define _PS_COEF_SET0_DATA_2B 0x68A9C
> +#define _PS_COEF_SET1_DATA_1A 0x681A4
> +#define _PS_COEF_SET1_DATA_2A 0x682A4
> +#define _PS_COEF_SET1_DATA_1B 0x689A4
> +#define _PS_COEF_SET1_DATA_2B 0x68AA4
> +
> #define _ID(id, a, b) _PICK_EVEN(id, a, b)
> #define SKL_PS_CTRL(pipe, id) _MMIO_PIPE(pipe, \
> _ID(id, _PS_1A_CTRL, _PS_2A_CTRL), \
> @@ -7166,6 +7185,18 @@ enum {
> #define SKL_PS_ECC_STAT(pipe, id) _MMIO_PIPE(pipe, \
> _ID(id, _PS_ECC_STAT_1A, _PS_ECC_STAT_2A), \
> _ID(id, _PS_ECC_STAT_1B, _PS_ECC_STAT_2B))
> +#define SKL_PS_COEF_DATA_SET0(pipe, id) _MMIO_PIPE(pipe, \
> + _ID(id, _PS_COEF_SET0_DATA_1A, _PS_COEF_SET0_DATA_2A), \
> + _ID(id, _PS_COEF_SET0_DATA_1B, _PS_COEF_SET0_DATA_1B))
> +#define SKL_PS_COEF_DATA_SET1(pipe, id) _MMIO_PIPE(pipe, \
> + _ID(id, _PS_COEF_SET1_DATA_1A, _PS_COEF_SET1_DATA_2A), \
> + _ID(id, _PS_COEF_SET1_DATA_1B, _PS_COEF_SET1_DATA_1B))
> +#define SKL_PS_COEF_INDEX_SET0(pipe, id) _MMIO_PIPE(pipe, \
> + _ID(id, _PS_COEF_SET0_INDEX_1A, _PS_COEF_SET0_INDEX_2A), \
> + _ID(id, _PS_COEF_SET0_INDEX_1B, _PS_COEF_SET0_INDEX_1B))
> +#define SKL_PS_COEF_INDEX_SET1(pipe, id) _MMIO_PIPE(pipe, \
> + _ID(id, _PS_COEF_SET1_INDEX_1A, _PS_COEF_SET1_INDEX_2A), \
> + _ID(id, _PS_COEF_SET1_INDEX_1B, _PS_COEF_SET1_INDEX_1B))
>
> /* legacy palette */
> #define _LGC_PALETTE_A 0x4a000
> --
> 2.17.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
More information about the Intel-gfx
mailing list