diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 103 |
1 files changed, 88 insertions, 15 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9741cc419e1b..c9878dd1f7cd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2890,6 +2890,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, return; valid_fb: + intel_state->base.rotation = plane_config->rotation; intel_fill_fb_ggtt_view(&intel_state->view, fb, intel_state->base.rotation); intel_state->color_plane[0].stride = @@ -4850,8 +4851,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 +4883,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 +5100,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 | @@ -7843,8 +7883,15 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, plane_config->tiling = I915_TILING_X; fb->modifier = I915_FORMAT_MOD_X_TILED; } + + if (val & DISPPLANE_ROTATE_180) + plane_config->rotation = DRM_MODE_ROTATE_180; } + if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B && + val & DISPPLANE_MIRROR) + plane_config->rotation |= DRM_MODE_REFLECT_X; + pixel_format = val & DISPPLANE_PIXFORMAT_MASK; fourcc = i9xx_format_to_fourcc(pixel_format); fb->format = drm_format_info(fourcc); @@ -8913,6 +8960,29 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, goto error; } + /* + * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr + * while i915 HW rotation is clockwise, thats why this swapping. + */ + switch (val & PLANE_CTL_ROTATE_MASK) { + case PLANE_CTL_ROTATE_0: + plane_config->rotation = DRM_MODE_ROTATE_0; + break; + case PLANE_CTL_ROTATE_90: + plane_config->rotation = DRM_MODE_ROTATE_270; + break; + case PLANE_CTL_ROTATE_180: + plane_config->rotation = DRM_MODE_ROTATE_180; + break; + case PLANE_CTL_ROTATE_270: + plane_config->rotation = DRM_MODE_ROTATE_90; + break; + } + + if (INTEL_GEN(dev_priv) >= 10 && + val & PLANE_CTL_FLIP_HORIZONTAL) + plane_config->rotation |= DRM_MODE_REFLECT_X; + base = I915_READ(PLANE_SURF(pipe, plane_id)) & 0xfffff000; plane_config->base = base; @@ -12768,17 +12838,12 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) intel_check_cpu_fifo_underruns(dev_priv); intel_check_pch_fifo_underruns(dev_priv); - if (!new_crtc_state->active) { - /* - * Make sure we don't call initial_watermarks - * for ILK-style watermark updates. - * - * No clue what this is supposed to achieve. - */ - if (INTEL_GEN(dev_priv) >= 9) - dev_priv->display.initial_watermarks(intel_state, - to_intel_crtc_state(new_crtc_state)); - } + /* FIXME unify this for all platforms */ + if (!new_crtc_state->active && + !HAS_GMCH_DISPLAY(dev_priv) && + dev_priv->display.initial_watermarks) + dev_priv->display.initial_watermarks(intel_state, + to_intel_crtc_state(new_crtc_state)); } } @@ -14646,7 +14711,7 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb, fb->height < SKL_MIN_YUV_420_SRC_H || (fb->width % 4) != 0 || (fb->height % 4) != 0)) { DRM_DEBUG_KMS("src dimensions not correct for NV12\n"); - return -EINVAL; + goto err; } for (i = 0; i < fb->format->num_planes; i++) { @@ -15233,6 +15298,14 @@ retry: ret = drm_atomic_add_affected_planes(state, crtc); if (ret) goto out; + + /* + * FIXME hack to force a LUT update to avoid the + * plane update forcing the pipe gamma on without + * having a proper LUT loaded. Remove once we + * have readout for pipe gamma enable. + */ + crtc_state->color_mgmt_changed = true; } } |