diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_psr.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_psr.c | 155 |
1 files changed, 130 insertions, 25 deletions
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 576ad0222221..30f341ace83d 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c | |||
@@ -61,6 +61,17 @@ static bool is_edp_psr(struct intel_dp *intel_dp) | |||
61 | return intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED; | 61 | return intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED; |
62 | } | 62 | } |
63 | 63 | ||
64 | static bool vlv_is_psr_active_on_pipe(struct drm_device *dev, int pipe) | ||
65 | { | ||
66 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
67 | uint32_t val; | ||
68 | |||
69 | val = I915_READ(VLV_PSRSTAT(pipe)) & | ||
70 | VLV_EDP_PSR_CURR_STATE_MASK; | ||
71 | return (val == VLV_EDP_PSR_ACTIVE_NORFB_UP) || | ||
72 | (val == VLV_EDP_PSR_ACTIVE_SF_UPDATE); | ||
73 | } | ||
74 | |||
64 | static void intel_psr_write_vsc(struct intel_dp *intel_dp, | 75 | static void intel_psr_write_vsc(struct intel_dp *intel_dp, |
65 | struct edp_vsc_psr *vsc_psr) | 76 | struct edp_vsc_psr *vsc_psr) |
66 | { | 77 | { |
@@ -90,7 +101,23 @@ static void intel_psr_write_vsc(struct intel_dp *intel_dp, | |||
90 | POSTING_READ(ctl_reg); | 101 | POSTING_READ(ctl_reg); |
91 | } | 102 | } |
92 | 103 | ||
93 | static void intel_psr_setup_vsc(struct intel_dp *intel_dp) | 104 | static void vlv_psr_setup_vsc(struct intel_dp *intel_dp) |
105 | { | ||
106 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | ||
107 | struct drm_device *dev = intel_dig_port->base.base.dev; | ||
108 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
109 | struct drm_crtc *crtc = intel_dig_port->base.base.crtc; | ||
110 | enum pipe pipe = to_intel_crtc(crtc)->pipe; | ||
111 | uint32_t val; | ||
112 | |||
113 | /* VLV auto-generate VSC package as per EDP 1.3 spec, Table 3.10 */ | ||
114 | val = I915_READ(VLV_VSCSDP(pipe)); | ||
115 | val &= ~VLV_EDP_PSR_SDP_FREQ_MASK; | ||
116 | val |= VLV_EDP_PSR_SDP_FREQ_EVFRAME; | ||
117 | I915_WRITE(VLV_VSCSDP(pipe), val); | ||
118 | } | ||
119 | |||
120 | static void hsw_psr_setup_vsc(struct intel_dp *intel_dp) | ||
94 | { | 121 | { |
95 | struct edp_vsc_psr psr_vsc; | 122 | struct edp_vsc_psr psr_vsc; |
96 | 123 | ||
@@ -103,7 +130,13 @@ static void intel_psr_setup_vsc(struct intel_dp *intel_dp) | |||
103 | intel_psr_write_vsc(intel_dp, &psr_vsc); | 130 | intel_psr_write_vsc(intel_dp, &psr_vsc); |
104 | } | 131 | } |
105 | 132 | ||
106 | static void intel_psr_enable_sink(struct intel_dp *intel_dp) | 133 | static void vlv_psr_enable_sink(struct intel_dp *intel_dp) |
134 | { | ||
135 | drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, | ||
136 | DP_PSR_ENABLE); | ||
137 | } | ||
138 | |||
139 | static void hsw_psr_enable_sink(struct intel_dp *intel_dp) | ||
107 | { | 140 | { |
108 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); | 141 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
109 | struct drm_device *dev = dig_port->base.base.dev; | 142 | struct drm_device *dev = dig_port->base.base.dev; |
@@ -147,7 +180,22 @@ static void intel_psr_enable_sink(struct intel_dp *intel_dp) | |||
147 | (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT)); | 180 | (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT)); |
148 | } | 181 | } |
149 | 182 | ||
150 | static void intel_psr_enable_source(struct intel_dp *intel_dp) | 183 | static void vlv_psr_enable_source(struct intel_dp *intel_dp) |
184 | { | ||
185 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); | ||
186 | struct drm_device *dev = dig_port->base.base.dev; | ||
187 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
188 | struct drm_crtc *crtc = dig_port->base.base.crtc; | ||
189 | enum pipe pipe = to_intel_crtc(crtc)->pipe; | ||
190 | |||
191 | /* Transition from PSR_state 0 to PSR_state 1, i.e. PSR Inactive */ | ||
192 | I915_WRITE(VLV_PSRCTL(pipe), | ||
193 | VLV_EDP_PSR_MODE_SW_TIMER | | ||
194 | VLV_EDP_PSR_SRC_TRANSMITTER_STATE | | ||
195 | VLV_EDP_PSR_ENABLE); | ||
196 | } | ||
197 | |||
198 | static void hsw_psr_enable_source(struct intel_dp *intel_dp) | ||
151 | { | 199 | { |
152 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); | 200 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
153 | struct drm_device *dev = dig_port->base.base.dev; | 201 | struct drm_device *dev = dig_port->base.base.dev; |
@@ -225,7 +273,7 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) | |||
225 | return true; | 273 | return true; |
226 | } | 274 | } |
227 | 275 | ||
228 | static void intel_psr_do_enable(struct intel_dp *intel_dp) | 276 | static void intel_psr_activate(struct intel_dp *intel_dp) |
229 | { | 277 | { |
230 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | 278 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
231 | struct drm_device *dev = intel_dig_port->base.base.dev; | 279 | struct drm_device *dev = intel_dig_port->base.base.dev; |
@@ -235,9 +283,12 @@ static void intel_psr_do_enable(struct intel_dp *intel_dp) | |||
235 | WARN_ON(dev_priv->psr.active); | 283 | WARN_ON(dev_priv->psr.active); |
236 | lockdep_assert_held(&dev_priv->psr.lock); | 284 | lockdep_assert_held(&dev_priv->psr.lock); |
237 | 285 | ||
238 | /* Enable/Re-enable PSR on the host */ | 286 | /* Enable/Re-enable PSR on the host |
239 | intel_psr_enable_source(intel_dp); | 287 | * On HSW+ after we enable PSR on source it will activate it |
240 | 288 | * as soon as it match configure idle_frame count. So | |
289 | * we just actually enable it here on activation time. | ||
290 | */ | ||
291 | hsw_psr_enable_source(intel_dp); | ||
241 | dev_priv->psr.active = true; | 292 | dev_priv->psr.active = true; |
242 | } | 293 | } |
243 | 294 | ||
@@ -274,37 +325,67 @@ void intel_psr_enable(struct intel_dp *intel_dp) | |||
274 | 325 | ||
275 | dev_priv->psr.busy_frontbuffer_bits = 0; | 326 | dev_priv->psr.busy_frontbuffer_bits = 0; |
276 | 327 | ||
277 | intel_psr_setup_vsc(intel_dp); | 328 | if (HAS_DDI(dev)) { |
329 | hsw_psr_setup_vsc(intel_dp); | ||
278 | 330 | ||
279 | /* Avoid continuous PSR exit by masking memup and hpd */ | 331 | /* Avoid continuous PSR exit by masking memup and hpd */ |
280 | I915_WRITE(EDP_PSR_DEBUG_CTL(dev), EDP_PSR_DEBUG_MASK_MEMUP | | 332 | I915_WRITE(EDP_PSR_DEBUG_CTL(dev), EDP_PSR_DEBUG_MASK_MEMUP | |
281 | EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP); | 333 | EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP); |
282 | 334 | ||
283 | /* Enable PSR on the panel */ | 335 | /* Enable PSR on the panel */ |
284 | intel_psr_enable_sink(intel_dp); | 336 | hsw_psr_enable_sink(intel_dp); |
337 | } else { | ||
338 | vlv_psr_setup_vsc(intel_dp); | ||
339 | |||
340 | /* Enable PSR on the panel */ | ||
341 | vlv_psr_enable_sink(intel_dp); | ||
342 | |||
343 | /* On HSW+ enable_source also means go to PSR entry/active | ||
344 | * state as soon as idle_frame achieved and here would be | ||
345 | * to soon. However on VLV enable_source just enable PSR | ||
346 | * but let it on inactive state. So we might do this prior | ||
347 | * to active transition, i.e. here. | ||
348 | */ | ||
349 | vlv_psr_enable_source(intel_dp); | ||
350 | } | ||
285 | 351 | ||
286 | dev_priv->psr.enabled = intel_dp; | 352 | dev_priv->psr.enabled = intel_dp; |
287 | unlock: | 353 | unlock: |
288 | mutex_unlock(&dev_priv->psr.lock); | 354 | mutex_unlock(&dev_priv->psr.lock); |
289 | } | 355 | } |
290 | 356 | ||
291 | /** | 357 | static void vlv_psr_disable(struct intel_dp *intel_dp) |
292 | * intel_psr_disable - Disable PSR | ||
293 | * @intel_dp: Intel DP | ||
294 | * | ||
295 | * This function needs to be called before disabling pipe. | ||
296 | */ | ||
297 | void intel_psr_disable(struct intel_dp *intel_dp) | ||
298 | { | 358 | { |
299 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | 359 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
300 | struct drm_device *dev = intel_dig_port->base.base.dev; | 360 | struct drm_device *dev = intel_dig_port->base.base.dev; |
301 | struct drm_i915_private *dev_priv = dev->dev_private; | 361 | struct drm_i915_private *dev_priv = dev->dev_private; |
362 | struct intel_crtc *intel_crtc = | ||
363 | to_intel_crtc(intel_dig_port->base.base.crtc); | ||
364 | uint32_t val; | ||
302 | 365 | ||
303 | mutex_lock(&dev_priv->psr.lock); | 366 | if (dev_priv->psr.active) { |
304 | if (!dev_priv->psr.enabled) { | 367 | /* Put VLV PSR back to PSR_state 0 that is PSR Disabled. */ |
305 | mutex_unlock(&dev_priv->psr.lock); | 368 | if (wait_for((I915_READ(VLV_PSRSTAT(intel_crtc->pipe)) & |
306 | return; | 369 | VLV_EDP_PSR_IN_TRANS) == 0, 1)) |
370 | WARN(1, "PSR transition took longer than expected\n"); | ||
371 | |||
372 | val = I915_READ(VLV_PSRCTL(intel_crtc->pipe)); | ||
373 | val &= ~VLV_EDP_PSR_ACTIVE_ENTRY; | ||
374 | val &= ~VLV_EDP_PSR_ENABLE; | ||
375 | val &= ~VLV_EDP_PSR_MODE_MASK; | ||
376 | I915_WRITE(VLV_PSRCTL(intel_crtc->pipe), val); | ||
377 | |||
378 | dev_priv->psr.active = false; | ||
379 | } else { | ||
380 | WARN_ON(vlv_is_psr_active_on_pipe(dev, intel_crtc->pipe)); | ||
307 | } | 381 | } |
382 | } | ||
383 | |||
384 | static void hsw_psr_disable(struct intel_dp *intel_dp) | ||
385 | { | ||
386 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | ||
387 | struct drm_device *dev = intel_dig_port->base.base.dev; | ||
388 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
308 | 389 | ||
309 | if (dev_priv->psr.active) { | 390 | if (dev_priv->psr.active) { |
310 | I915_WRITE(EDP_PSR_CTL(dev), | 391 | I915_WRITE(EDP_PSR_CTL(dev), |
@@ -319,6 +400,30 @@ void intel_psr_disable(struct intel_dp *intel_dp) | |||
319 | } else { | 400 | } else { |
320 | WARN_ON(I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE); | 401 | WARN_ON(I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE); |
321 | } | 402 | } |
403 | } | ||
404 | |||
405 | /** | ||
406 | * intel_psr_disable - Disable PSR | ||
407 | * @intel_dp: Intel DP | ||
408 | * | ||
409 | * This function needs to be called before disabling pipe. | ||
410 | */ | ||
411 | void intel_psr_disable(struct intel_dp *intel_dp) | ||
412 | { | ||
413 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | ||
414 | struct drm_device *dev = intel_dig_port->base.base.dev; | ||
415 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
416 | |||
417 | mutex_lock(&dev_priv->psr.lock); | ||
418 | if (!dev_priv->psr.enabled) { | ||
419 | mutex_unlock(&dev_priv->psr.lock); | ||
420 | return; | ||
421 | } | ||
422 | |||
423 | if (HAS_DDI(dev)) | ||
424 | hsw_psr_disable(intel_dp); | ||
425 | else | ||
426 | vlv_psr_disable(intel_dp); | ||
322 | 427 | ||
323 | dev_priv->psr.enabled = NULL; | 428 | dev_priv->psr.enabled = NULL; |
324 | mutex_unlock(&dev_priv->psr.lock); | 429 | mutex_unlock(&dev_priv->psr.lock); |
@@ -357,7 +462,7 @@ static void intel_psr_work(struct work_struct *work) | |||
357 | if (dev_priv->psr.busy_frontbuffer_bits) | 462 | if (dev_priv->psr.busy_frontbuffer_bits) |
358 | goto unlock; | 463 | goto unlock; |
359 | 464 | ||
360 | intel_psr_do_enable(intel_dp); | 465 | intel_psr_activate(intel_dp); |
361 | unlock: | 466 | unlock: |
362 | mutex_unlock(&dev_priv->psr.lock); | 467 | mutex_unlock(&dev_priv->psr.lock); |
363 | } | 468 | } |