|
@@ -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
|
|
|
* actually get the expected MPEG2 chroma siting convention :(
|
|
|
* 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;
|
|
|
u16 trip = 0;
|
|
@@ -4859,6 +4882,15 @@ u16 skl_scaler_calc_phase(int sub, bool chroma_cosited)
|
|
|
if (chroma_cosited)
|
|
|
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)
|
|
|
phase = 0x10000 + phase;
|
|
|
else
|
|
@@ -5067,13 +5099,20 @@ static void skylake_pfit_enable(struct intel_crtc *crtc)
|
|
|
|
|
|
if (crtc->config->pch_pfit.enabled) {
|
|
|
u16 uv_rgb_hphase, uv_rgb_vphase;
|
|
|
+ int pfit_w, pfit_h, hscale, vscale;
|
|
|
int id;
|
|
|
|
|
|
if (WARN_ON(crtc->config->scaler_state.scaler_id < 0))
|
|
|
return;
|
|
|
|
|
|
- uv_rgb_hphase = skl_scaler_calc_phase(1, false);
|
|
|
- uv_rgb_vphase = skl_scaler_calc_phase(1, false);
|
|
|
+ pfit_w = (crtc->config->pch_pfit.size >> 16) & 0xFFFF;
|
|
|
+ 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;
|
|
|
I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |
|