|
@@ -4752,6 +4752,39 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * The hardware phase 0.0 refers to the center of the pixel.
|
|
|
|
+ * We want to start from the top/left edge which is phase
|
|
|
|
+ * -0.5. That matches how the hardware calculates the scaling
|
|
|
|
+ * factors (from top-left of the first pixel to bottom-right
|
|
|
|
+ * of the last pixel, as opposed to the pixel centers).
|
|
|
|
+ *
|
|
|
|
+ * For 4:2:0 subsampled chroma planes we obviously have to
|
|
|
|
+ * adjust that so that the chroma sample position lands in
|
|
|
|
+ * the right spot.
|
|
|
|
+ *
|
|
|
|
+ * Note that for packed YCbCr 4:2:2 formats there is no way to
|
|
|
|
+ * control chroma siting. The hardware simply replicates the
|
|
|
|
+ * chroma samples for both of the luma samples, and thus we don't
|
|
|
|
+ * actually get the expected MPEG2 chroma siting convention :(
|
|
|
|
+ * The same behaviour is observed on pre-SKL platforms as well.
|
|
|
|
+ */
|
|
|
|
+u16 skl_scaler_calc_phase(int sub, bool chroma_cosited)
|
|
|
|
+{
|
|
|
|
+ int phase = -0x8000;
|
|
|
|
+ u16 trip = 0;
|
|
|
|
+
|
|
|
|
+ if (chroma_cosited)
|
|
|
|
+ phase += (sub - 1) * 0x8000 / sub;
|
|
|
|
+
|
|
|
|
+ if (phase < 0)
|
|
|
|
+ phase = 0x10000 + phase;
|
|
|
|
+ else
|
|
|
|
+ trip = PS_PHASE_TRIP;
|
|
|
|
+
|
|
|
|
+ return ((phase >> 2) & PS_PHASE_MASK) | trip;
|
|
|
|
+}
|
|
|
|
+
|
|
static int
|
|
static int
|
|
skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
|
|
skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
|
|
unsigned int scaler_user, int *scaler_id,
|
|
unsigned int scaler_user, int *scaler_id,
|
|
@@ -4951,14 +4984,22 @@ static void skylake_pfit_enable(struct intel_crtc *crtc)
|
|
&crtc->config->scaler_state;
|
|
&crtc->config->scaler_state;
|
|
|
|
|
|
if (crtc->config->pch_pfit.enabled) {
|
|
if (crtc->config->pch_pfit.enabled) {
|
|
|
|
+ u16 uv_rgb_hphase, uv_rgb_vphase;
|
|
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);
|
|
|
|
+ uv_rgb_vphase = skl_scaler_calc_phase(1, 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 |
|
|
PS_FILTER_MEDIUM | scaler_state->scalers[id].mode);
|
|
PS_FILTER_MEDIUM | 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),
|
|
|
|
+ PS_Y_PHASE(0) | PS_UV_RGB_PHASE(uv_rgb_hphase));
|
|
I915_WRITE(SKL_PS_WIN_POS(pipe, id), crtc->config->pch_pfit.pos);
|
|
I915_WRITE(SKL_PS_WIN_POS(pipe, id), crtc->config->pch_pfit.pos);
|
|
I915_WRITE(SKL_PS_WIN_SZ(pipe, id), crtc->config->pch_pfit.size);
|
|
I915_WRITE(SKL_PS_WIN_SZ(pipe, id), crtc->config->pch_pfit.size);
|
|
}
|
|
}
|