@@ -88,6 +88,20 @@ enum port {
};
#define port_name(p) ((p) + 'A')
+enum intel_display_power_domain {
+ POWER_DOMAIN_PIPE_A_PANEL_FITTER,
+ POWER_DOMAIN_PIPE_A,
+ POWER_DOMAIN_PIPE_B,
+ POWER_DOMAIN_PIPE_C,
+ POWER_DOMAIN_TRANSCODER_A,
+ POWER_DOMAIN_TRANSCODER_B,
+ POWER_DOMAIN_TRANSCODER_C,
+ POWER_DOMAIN_TRANSCODER_EDP = POWER_DOMAIN_TRANSCODER_A + 0xF,
+};
+
+#define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A)
+#define POWER_DOMAIN_TRANSCODER(tran) ((tran) + POWER_DOMAIN_TRANSCODER_A)
+
enum hpd_pin {
HPD_NONE = 0,
HPD_PORT_A = HPD_NONE, /* PORT_A is internal */
@@ -1215,8 +1215,8 @@ void assert_pipe(struct drm_i915_private *dev_priv,
if (pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
state = true;
- if (!intel_using_power_well(dev_priv->dev) &&
- cpu_transcoder != TRANSCODER_EDP) {
+ if (!intel_display_power_enabled(dev_priv->dev,
+ POWER_DOMAIN_TRANSCODER(cpu_transcoder))) {
cur_state = false;
} else {
reg = PIPECONF(cpu_transcoder);
@@ -3597,6 +3597,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
int pipe = intel_crtc->pipe;
int plane = intel_crtc->plane;
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
+ enum intel_display_power_domain domain;
if (!intel_crtc->active)
return;
@@ -3622,7 +3623,12 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
/* XXX: Once we have proper panel fitter state tracking implemented with
* hardware state read/check support we should switch to only disable
* the panel fitter when we know it's used. */
- if (intel_using_power_well(dev)) {
+ if (pipe == PIPE_A)
+ domain = POWER_DOMAIN_PIPE_A_PANEL_FITTER;
+ else
+ domain = POWER_DOMAIN_PIPE(pipe);
+
+ if (intel_display_power_enabled(dev, domain)) {
I915_WRITE(PF_CTL(pipe), 0);
I915_WRITE(PF_WIN_SZ(pipe), 0);
}
@@ -5981,8 +5987,8 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
enum transcoder cpu_transcoder = crtc->config.cpu_transcoder;
uint32_t tmp;
- if (!intel_using_power_well(dev_priv->dev) &&
- cpu_transcoder != TRANSCODER_EDP)
+ if (!intel_display_power_enabled(dev,
+ POWER_DOMAIN_TRANSCODER(cpu_transcoder)))
return false;
tmp = I915_READ(PIPECONF(cpu_transcoder));
@@ -721,7 +721,8 @@ extern void intel_update_fbc(struct drm_device *dev);
extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
extern void intel_gpu_ips_teardown(void);
-extern bool intel_using_power_well(struct drm_device *dev);
+extern bool intel_display_power_enabled(struct drm_device *dev,
+ enum intel_display_power_domain domain);
extern void intel_init_power_well(struct drm_device *dev);
extern void intel_set_power_well(struct drm_device *dev, bool enable);
extern void intel_enable_gt_powersave(struct drm_device *dev);
@@ -4287,15 +4287,32 @@ void intel_init_clock_gating(struct drm_device *dev)
* enable it, so check if it's enabled and also check if we've requested it to
* be enabled.
*/
-bool intel_using_power_well(struct drm_device *dev)
+bool intel_display_power_enabled(struct drm_device *dev,
+ enum intel_display_power_domain domain)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ bool power_well_enabled;
- if (IS_HASWELL(dev))
- return I915_READ(HSW_PWR_WELL_DRIVER) ==
- (HSW_PWR_WELL_ENABLE | HSW_PWR_WELL_STATE);
- else
+ if (!HAS_POWER_WELL(dev))
+ return true;
+
+ power_well_enabled = I915_READ(HSW_PWR_WELL_DRIVER) ==
+ (HSW_PWR_WELL_ENABLE | HSW_PWR_WELL_STATE);
+
+ switch (domain) {
+ case POWER_DOMAIN_PIPE_A:
+ case POWER_DOMAIN_TRANSCODER_EDP:
return true;
+ case POWER_DOMAIN_PIPE_A_PANEL_FITTER:
+ case POWER_DOMAIN_PIPE_B:
+ case POWER_DOMAIN_PIPE_C:
+ case POWER_DOMAIN_TRANSCODER_A:
+ case POWER_DOMAIN_TRANSCODER_B:
+ case POWER_DOMAIN_TRANSCODER_C:
+ return power_well_enabled;
+ default:
+ BUG();
+ }
}
void intel_set_power_well(struct drm_device *dev, bool enable)