Commit 6e8adf6f authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Joonas Lahtinen

drm/i915: Account for scale factor when calculating initial phase

To get the initial phase correct we need to account for the scale
factor as well. I forgot this initially and was mostly looking at
heavily upscaled content where the minor difference between -0.5
and the proper initial phase was not readily apparent.

And let's toss in a comment that tries to explain the formula
a little bit.

v2: The initial phase upper limit is 1.5, not 24.0!

Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Fixes: 0a59952b ("drm/i915: Configure SKL+ scaler initial phase correctly")
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181029181820.21956-1-ville.syrjala@linux.intel.comTested-by: default avatarJuha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
Tested-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> #irc
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> #irc
(cherry picked from commit e7a278a3)
Signed-off-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
parent 27971d61
...@@ -4850,8 +4850,31 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe) ...@@ -4850,8 +4850,31 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe)
* chroma samples for both of the luma samples, and thus we don't * chroma samples for both of the luma samples, and thus we don't
* actually get the expected MPEG2 chroma siting convention :( * actually get the expected MPEG2 chroma siting convention :(
* The same behaviour is observed on pre-SKL platforms as well. * The same behaviour is observed on pre-SKL platforms as well.
*
* Theory behind the formula (note that we ignore sub-pixel
* source coordinates):
* s = source sample position
* d = destination sample position
*
* Downscaling 4:1:
* -0.5
* | 0.0
* | | 1.5 (initial phase)
* | | |
* v v v
* | s | s | s | s |
* | d |
*
* Upscaling 1:4:
* -0.5
* | -0.375 (initial phase)
* | | 0.0
* | | |
* v v v
* | s |
* | d | d | d | d |
*/ */
u16 skl_scaler_calc_phase(int sub, bool chroma_cosited) u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited)
{ {
int phase = -0x8000; int phase = -0x8000;
u16 trip = 0; u16 trip = 0;
...@@ -4859,6 +4882,15 @@ u16 skl_scaler_calc_phase(int sub, bool chroma_cosited) ...@@ -4859,6 +4882,15 @@ u16 skl_scaler_calc_phase(int sub, bool chroma_cosited)
if (chroma_cosited) if (chroma_cosited)
phase += (sub - 1) * 0x8000 / sub; phase += (sub - 1) * 0x8000 / sub;
phase += scale / (2 * sub);
/*
* Hardware initial phase limited to [-0.5:1.5].
* Since the max hardware scale factor is 3.0, we
* should never actually excdeed 1.0 here.
*/
WARN_ON(phase < -0x8000 || phase > 0x18000);
if (phase < 0) if (phase < 0)
phase = 0x10000 + phase; phase = 0x10000 + phase;
else else
...@@ -5067,13 +5099,20 @@ static void skylake_pfit_enable(struct intel_crtc *crtc) ...@@ -5067,13 +5099,20 @@ static void skylake_pfit_enable(struct intel_crtc *crtc)
if (crtc->config->pch_pfit.enabled) { if (crtc->config->pch_pfit.enabled) {
u16 uv_rgb_hphase, uv_rgb_vphase; u16 uv_rgb_hphase, uv_rgb_vphase;
int pfit_w, pfit_h, hscale, vscale;
int id; int id;
if (WARN_ON(crtc->config->scaler_state.scaler_id < 0)) if (WARN_ON(crtc->config->scaler_state.scaler_id < 0))
return; return;
uv_rgb_hphase = skl_scaler_calc_phase(1, false); pfit_w = (crtc->config->pch_pfit.size >> 16) & 0xFFFF;
uv_rgb_vphase = skl_scaler_calc_phase(1, false); pfit_h = crtc->config->pch_pfit.size & 0xFFFF;
hscale = (crtc->config->pipe_src_w << 16) / pfit_w;
vscale = (crtc->config->pipe_src_h << 16) / pfit_h;
uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
id = scaler_state->scaler_id; id = scaler_state->scaler_id;
I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN | I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |
......
...@@ -1646,7 +1646,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode, ...@@ -1646,7 +1646,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc, void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
struct intel_crtc_state *crtc_state); struct intel_crtc_state *crtc_state);
u16 skl_scaler_calc_phase(int sub, bool chroma_center); u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_center);
int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state); int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
int skl_max_scale(const struct intel_crtc_state *crtc_state, int skl_max_scale(const struct intel_crtc_state *crtc_state,
u32 pixel_format); u32 pixel_format);
......
...@@ -318,22 +318,30 @@ skl_program_scaler(struct intel_plane *plane, ...@@ -318,22 +318,30 @@ skl_program_scaler(struct intel_plane *plane,
uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
u16 y_hphase, uv_rgb_hphase; u16 y_hphase, uv_rgb_hphase;
u16 y_vphase, uv_rgb_vphase; u16 y_vphase, uv_rgb_vphase;
int hscale, vscale;
hscale = drm_rect_calc_hscale(&plane_state->base.src,
&plane_state->base.dst,
0, INT_MAX);
vscale = drm_rect_calc_vscale(&plane_state->base.src,
&plane_state->base.dst,
0, INT_MAX);
/* TODO: handle sub-pixel coordinates */ /* TODO: handle sub-pixel coordinates */
if (plane_state->base.fb->format->format == DRM_FORMAT_NV12) { if (plane_state->base.fb->format->format == DRM_FORMAT_NV12) {
y_hphase = skl_scaler_calc_phase(1, false); y_hphase = skl_scaler_calc_phase(1, hscale, false);
y_vphase = skl_scaler_calc_phase(1, false); y_vphase = skl_scaler_calc_phase(1, vscale, false);
/* MPEG2 chroma siting convention */ /* MPEG2 chroma siting convention */
uv_rgb_hphase = skl_scaler_calc_phase(2, true); uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
uv_rgb_vphase = skl_scaler_calc_phase(2, false); uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
} else { } else {
/* not used */ /* not used */
y_hphase = 0; y_hphase = 0;
y_vphase = 0; y_vphase = 0;
uv_rgb_hphase = skl_scaler_calc_phase(1, false); uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
uv_rgb_vphase = skl_scaler_calc_phase(1, false); uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
} }
I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id), I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment