Message ID | 20190903165227.6056-3-shashank.sharma@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Enable Nearest-neighbor for Integer mode scaling | expand |
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@intel.com> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> > Cc: Daniel Vetter <daniel.vetter@intel.com> > Cc: Vivi, Rodrigo <rodrigo.vivi@intel.com> > Signed-off-by: Shashank Sharma <shashank.sharma@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@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
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); + } + } +} + 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
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@intel.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Daniel Vetter <daniel.vetter@intel.com> Cc: Vivi, Rodrigo <rodrigo.vivi@intel.com> Signed-off-by: Shashank Sharma <shashank.sharma@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(-)