summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c121
1 files changed, 67 insertions, 54 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4e3f302d86f7..ba9321998a41 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -87,7 +87,8 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config);
static int intel_set_mode(struct drm_crtc *crtc,
- struct drm_atomic_state *state);
+ struct drm_atomic_state *state,
+ bool force_restore);
static int intel_framebuffer_init(struct drm_device *dev,
struct intel_framebuffer *ifb,
struct drm_mode_fb_cmd2 *mode_cmd,
@@ -4853,6 +4854,9 @@ static void intel_crtc_disable_planes(struct drm_crtc *crtc)
struct intel_plane *intel_plane;
int pipe = intel_crtc->pipe;
+ if (!intel_crtc->active)
+ return;
+
intel_crtc_wait_for_pending_flips(crtc);
intel_pre_disable_primary(crtc);
@@ -7886,7 +7890,7 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc,
int pipe = pipe_config->cpu_transcoder;
enum dpio_channel port = vlv_pipe_to_channel(pipe);
intel_clock_t clock;
- u32 cmn_dw13, pll_dw0, pll_dw1, pll_dw2;
+ u32 cmn_dw13, pll_dw0, pll_dw1, pll_dw2, pll_dw3;
int refclk = 100000;
mutex_lock(&dev_priv->sb_lock);
@@ -7894,10 +7898,13 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc,
pll_dw0 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW0(port));
pll_dw1 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW1(port));
pll_dw2 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW2(port));
+ pll_dw3 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port));
mutex_unlock(&dev_priv->sb_lock);
clock.m1 = (pll_dw1 & 0x7) == DPIO_CHV_M1_DIV_BY_2 ? 2 : 0;
- clock.m2 = ((pll_dw0 & 0xff) << 22) | (pll_dw2 & 0x3fffff);
+ clock.m2 = (pll_dw0 & 0xff) << 22;
+ if (pll_dw3 & DPIO_CHV_FRAC_DIV_EN)
+ clock.m2 |= pll_dw2 & 0x3fffff;
clock.n = (pll_dw1 >> DPIO_CHV_N_DIV_SHIFT) & 0xf;
clock.p1 = (cmn_dw13 >> DPIO_CHV_P1_DIV_SHIFT) & 0x7;
clock.p2 = (cmn_dw13 >> DPIO_CHV_P2_DIV_SHIFT) & 0x1f;
@@ -10096,7 +10103,7 @@ retry:
drm_mode_copy(&crtc_state->base.mode, mode);
- if (intel_set_mode(crtc, state)) {
+ if (intel_set_mode(crtc, state, true)) {
DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
if (old->release_fb)
old->release_fb->funcs->destroy(old->release_fb);
@@ -10170,7 +10177,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
if (ret)
goto fail;
- ret = intel_set_mode(crtc, state);
+ ret = intel_set_mode(crtc, state, true);
if (ret)
goto fail;
@@ -11385,10 +11392,6 @@ static void intel_modeset_fixup_state(struct drm_atomic_state *state)
crtc->base.enabled = crtc->base.state->enable;
crtc->config = to_intel_crtc_state(crtc->base.state);
}
-
- /* Copy the new configuration to the staged state, to keep the few
- * pieces of code that haven't been converted yet happy */
- intel_modeset_update_staged_output_state(state->dev);
}
static void
@@ -11870,15 +11873,15 @@ intel_modeset_update_state(struct drm_atomic_state *state)
if (!intel_encoder->base.crtc)
continue;
- for_each_crtc_in_state(state, crtc, crtc_state, i)
- if (crtc == intel_encoder->base.crtc)
- break;
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ if (crtc != intel_encoder->base.crtc)
+ continue;
- if (crtc != intel_encoder->base.crtc)
- continue;
+ if (crtc_state->enable && needs_modeset(crtc_state))
+ intel_encoder->connectors_active = false;
- if (crtc_state->enable && needs_modeset(crtc_state))
- intel_encoder->connectors_active = false;
+ break;
+ }
}
drm_atomic_helper_swap_state(state->dev, state);
@@ -11893,24 +11896,24 @@ intel_modeset_update_state(struct drm_atomic_state *state)
if (!connector->encoder || !connector->encoder->crtc)
continue;
- for_each_crtc_in_state(state, crtc, crtc_state, i)
- if (crtc == connector->encoder->crtc)
- break;
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ if (crtc != connector->encoder->crtc)
+ continue;
- if (crtc != connector->encoder->crtc)
- continue;
+ if (crtc->state->enable && needs_modeset(crtc->state)) {
+ struct drm_property *dpms_property =
+ dev->mode_config.dpms_property;
- if (crtc->state->enable && needs_modeset(crtc->state)) {
- struct drm_property *dpms_property =
- dev->mode_config.dpms_property;
+ connector->dpms = DRM_MODE_DPMS_ON;
+ drm_object_property_set_value(&connector->base,
+ dpms_property,
+ DRM_MODE_DPMS_ON);
- connector->dpms = DRM_MODE_DPMS_ON;
- drm_object_property_set_value(&connector->base,
- dpms_property,
- DRM_MODE_DPMS_ON);
+ intel_encoder = to_intel_encoder(connector->encoder);
+ intel_encoder->connectors_active = true;
+ }
- intel_encoder = to_intel_encoder(connector->encoder);
- intel_encoder->connectors_active = true;
+ break;
}
}
@@ -12646,20 +12649,24 @@ static int __intel_set_mode(struct drm_crtc *modeset_crtc,
}
static int intel_set_mode_with_config(struct drm_crtc *crtc,
- struct intel_crtc_state *pipe_config)
+ struct intel_crtc_state *pipe_config,
+ bool force_restore)
{
int ret;
ret = __intel_set_mode(crtc, pipe_config);
- if (ret == 0)
+ if (ret == 0 && force_restore) {
+ intel_modeset_update_staged_output_state(crtc->dev);
intel_modeset_check_state(crtc->dev);
+ }
return ret;
}
static int intel_set_mode(struct drm_crtc *crtc,
- struct drm_atomic_state *state)
+ struct drm_atomic_state *state,
+ bool force_restore)
{
struct intel_crtc_state *pipe_config;
int ret = 0;
@@ -12670,7 +12677,7 @@ static int intel_set_mode(struct drm_crtc *crtc,
goto out;
}
- ret = intel_set_mode_with_config(crtc, pipe_config);
+ ret = intel_set_mode_with_config(crtc, pipe_config, force_restore);
if (ret)
goto out;
@@ -12682,7 +12689,6 @@ void intel_crtc_restore_mode(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_atomic_state *state;
- struct intel_crtc *intel_crtc;
struct intel_encoder *encoder;
struct intel_connector *connector;
struct drm_connector_state *connector_state;
@@ -12725,29 +12731,23 @@ void intel_crtc_restore_mode(struct drm_crtc *crtc)
}
}
- for_each_intel_crtc(dev, intel_crtc) {
- if (intel_crtc->new_enabled == intel_crtc->base.enabled)
- continue;
-
- crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
- if (IS_ERR(crtc_state)) {
- DRM_DEBUG_KMS("Failed to add [CRTC:%d] to state: %ld\n",
- intel_crtc->base.base.id,
- PTR_ERR(crtc_state));
- continue;
- }
+ crtc_state = intel_atomic_get_crtc_state(state, to_intel_crtc(crtc));
+ if (IS_ERR(crtc_state)) {
+ DRM_DEBUG_KMS("Failed to add [CRTC:%d] to state: %ld\n",
+ crtc->base.id, PTR_ERR(crtc_state));
+ drm_atomic_state_free(state);
+ return;
+ }
- crtc_state->base.active = crtc_state->base.enable =
- intel_crtc->new_enabled;
+ crtc_state->base.active = crtc_state->base.enable =
+ to_intel_crtc(crtc)->new_enabled;
- if (&intel_crtc->base == crtc)
- drm_mode_copy(&crtc_state->base.mode, &crtc->mode);
- }
+ drm_mode_copy(&crtc_state->base.mode, &crtc->mode);
intel_modeset_setup_plane_state(state, crtc, &crtc->mode,
crtc->primary->fb, crtc->x, crtc->y);
- ret = intel_set_mode(crtc, state);
+ ret = intel_set_mode(crtc, state, false);
if (ret)
drm_atomic_state_free(state);
}
@@ -12947,7 +12947,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
primary_plane_was_visible = primary_plane_visible(set->crtc);
- ret = intel_set_mode_with_config(set->crtc, pipe_config);
+ ret = intel_set_mode_with_config(set->crtc, pipe_config, true);
if (ret == 0 &&
pipe_config->base.enable &&
@@ -13276,7 +13276,7 @@ intel_check_primary_plane(struct drm_plane *plane,
if (ret)
return ret;
- if (intel_crtc->active) {
+ if (crtc_state->base.active) {
struct intel_plane_state *old_state =
to_intel_plane_state(plane->state);
@@ -13309,6 +13309,16 @@ intel_check_primary_plane(struct drm_plane *plane,
intel_crtc->atomic.wait_vblank = true;
}
+ /*
+ * FIXME: Actually if we will still have any other plane enabled
+ * on the pipe we could let IPS enabled still, but for
+ * now lets consider that when we make primary invisible
+ * by setting DSPCNTR to 0 on update_primary_plane function
+ * IPS needs to be disable.
+ */
+ if (!state->visible || !fb)
+ intel_crtc->atomic.disable_ips = true;
+
intel_crtc->atomic.fb_bits |=
INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe);
@@ -13406,6 +13416,9 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc)
if (intel_crtc->atomic.disable_fbc)
intel_fbc_disable(dev);
+ if (intel_crtc->atomic.disable_ips)
+ hsw_disable_ips(intel_crtc);
+
if (intel_crtc->atomic.pre_disable_primary)
intel_pre_disable_primary(crtc);
OpenPOWER on IntegriCloud