drm/i915: add port power domains
authorImre Deak <imre.deak@intel.com>
Tue, 4 Mar 2014 17:22:57 +0000 (19:22 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 7 Mar 2014 21:36:51 +0000 (22:36 +0100)
Parts that poke port specific HW blocks like the encoder HW state
readout or connector hotplug detect code need a way to check whether
required power domains are on or enable/disable these. For this purpose
add a set of power domains that refer to the port HW blocks. Get the
proper port power domains during modeset.

For now when requesting the power domain for a DDI port get it for a 4
lane configuration. This can be optimized later to request only the 2
lane power domain, when proper support is added on the VLV PHY side for
this. Atm, the PHY setup code assumes a 4 lane config in all cases.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_pm.c

index fbcf536..a90d31c 100644 (file)
@@ -2048,6 +2048,28 @@ static const char *power_domain_str(enum intel_display_power_domain domain)
                return "TRANSCODER_C";
        case POWER_DOMAIN_TRANSCODER_EDP:
                return "TRANSCODER_EDP";
+       case POWER_DOMAIN_PORT_DDI_A_2_LANES:
+               return "PORT_DDI_A_2_LANES";
+       case POWER_DOMAIN_PORT_DDI_A_4_LANES:
+               return "PORT_DDI_A_4_LANES";
+       case POWER_DOMAIN_PORT_DDI_B_2_LANES:
+               return "PORT_DDI_B_2_LANES";
+       case POWER_DOMAIN_PORT_DDI_B_4_LANES:
+               return "PORT_DDI_B_4_LANES";
+       case POWER_DOMAIN_PORT_DDI_C_2_LANES:
+               return "PORT_DDI_C_2_LANES";
+       case POWER_DOMAIN_PORT_DDI_C_4_LANES:
+               return "PORT_DDI_C_4_LANES";
+       case POWER_DOMAIN_PORT_DDI_D_2_LANES:
+               return "PORT_DDI_D_2_LANES";
+       case POWER_DOMAIN_PORT_DDI_D_4_LANES:
+               return "PORT_DDI_D_4_LANES";
+       case POWER_DOMAIN_PORT_DSI:
+               return "PORT_DSI";
+       case POWER_DOMAIN_PORT_CRT:
+               return "PORT_CRT";
+       case POWER_DOMAIN_PORT_OTHER:
+               return "PORT_OTHER";
        case POWER_DOMAIN_VGA:
                return "VGA";
        case POWER_DOMAIN_AUDIO:
index 9e26103..9387c56 100644 (file)
@@ -114,6 +114,17 @@ enum intel_display_power_domain {
        POWER_DOMAIN_TRANSCODER_B,
        POWER_DOMAIN_TRANSCODER_C,
        POWER_DOMAIN_TRANSCODER_EDP,
+       POWER_DOMAIN_PORT_DDI_A_2_LANES,
+       POWER_DOMAIN_PORT_DDI_A_4_LANES,
+       POWER_DOMAIN_PORT_DDI_B_2_LANES,
+       POWER_DOMAIN_PORT_DDI_B_4_LANES,
+       POWER_DOMAIN_PORT_DDI_C_2_LANES,
+       POWER_DOMAIN_PORT_DDI_C_4_LANES,
+       POWER_DOMAIN_PORT_DDI_D_2_LANES,
+       POWER_DOMAIN_PORT_DDI_D_4_LANES,
+       POWER_DOMAIN_PORT_DSI,
+       POWER_DOMAIN_PORT_CRT,
+       POWER_DOMAIN_PORT_OTHER,
        POWER_DOMAIN_VGA,
        POWER_DOMAIN_AUDIO,
        POWER_DOMAIN_INIT,
index ee786c5..414da19 100644 (file)
@@ -3962,9 +3962,49 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc)
        for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)     \
                if ((1 << (domain)) & (mask))
 
-static unsigned long get_pipe_power_domains(struct drm_device *dev,
-                                           enum pipe pipe, bool pfit_enabled)
+enum intel_display_power_domain
+intel_display_port_power_domain(struct intel_encoder *intel_encoder)
+{
+       struct drm_device *dev = intel_encoder->base.dev;
+       struct intel_digital_port *intel_dig_port;
+
+       switch (intel_encoder->type) {
+       case INTEL_OUTPUT_UNKNOWN:
+               /* Only DDI platforms should ever use this output type */
+               WARN_ON_ONCE(!HAS_DDI(dev));
+       case INTEL_OUTPUT_DISPLAYPORT:
+       case INTEL_OUTPUT_HDMI:
+       case INTEL_OUTPUT_EDP:
+               intel_dig_port = enc_to_dig_port(&intel_encoder->base);
+               switch (intel_dig_port->port) {
+               case PORT_A:
+                       return POWER_DOMAIN_PORT_DDI_A_4_LANES;
+               case PORT_B:
+                       return POWER_DOMAIN_PORT_DDI_B_4_LANES;
+               case PORT_C:
+                       return POWER_DOMAIN_PORT_DDI_C_4_LANES;
+               case PORT_D:
+                       return POWER_DOMAIN_PORT_DDI_D_4_LANES;
+               default:
+                       WARN_ON_ONCE(1);
+                       return POWER_DOMAIN_PORT_OTHER;
+               }
+       case INTEL_OUTPUT_ANALOG:
+               return POWER_DOMAIN_PORT_CRT;
+       case INTEL_OUTPUT_DSI:
+               return POWER_DOMAIN_PORT_DSI;
+       default:
+               return POWER_DOMAIN_PORT_OTHER;
+       }
+}
+
+static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
 {
+       struct drm_device *dev = crtc->dev;
+       struct intel_encoder *intel_encoder;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       enum pipe pipe = intel_crtc->pipe;
+       bool pfit_enabled = intel_crtc->config.pch_pfit.enabled;
        unsigned long mask;
        enum transcoder transcoder;
 
@@ -3975,6 +4015,9 @@ static unsigned long get_pipe_power_domains(struct drm_device *dev,
        if (pfit_enabled)
                mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
 
+       for_each_encoder_on_crtc(dev, crtc, intel_encoder)
+               mask |= BIT(intel_display_port_power_domain(intel_encoder));
+
        return mask;
 }
 
@@ -4008,9 +4051,7 @@ static void modeset_update_crtc_power_domains(struct drm_device *dev)
                if (!crtc->base.enabled)
                        continue;
 
-               pipe_domains[crtc->pipe] = get_pipe_power_domains(dev,
-                                               crtc->pipe,
-                                               crtc->config.pch_pfit.enabled);
+               pipe_domains[crtc->pipe] = get_crtc_power_domains(&crtc->base);
 
                for_each_power_domain(domain, pipe_domains[crtc->pipe])
                        intel_display_power_get(dev_priv, domain);
index 6042797..e31eb1e 100644 (file)
@@ -733,6 +733,8 @@ bool intel_crtc_active(struct drm_crtc *crtc);
 void hsw_enable_ips(struct intel_crtc *crtc);
 void hsw_disable_ips(struct intel_crtc *crtc);
 void intel_display_set_init_power(struct drm_i915_private *dev, bool enable);
+enum intel_display_power_domain
+intel_display_port_power_domain(struct intel_encoder *intel_encoder);
 int valleyview_get_vco(struct drm_i915_private *dev_priv);
 void intel_mode_from_pipe_config(struct drm_display_mode *mode,
                                 struct intel_crtc_config *pipe_config);
index 37f1621..a4c0ff1 100644 (file)
@@ -5483,6 +5483,15 @@ EXPORT_SYMBOL_GPL(i915_release_power_well);
 #define HSW_ALWAYS_ON_POWER_DOMAINS (                  \
        BIT(POWER_DOMAIN_PIPE_A) |                      \
        BIT(POWER_DOMAIN_TRANSCODER_EDP) |              \
+       BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) |          \
+       BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) |          \
+       BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) |          \
+       BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) |          \
+       BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) |          \
+       BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |          \
+       BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) |          \
+       BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) |          \
+       BIT(POWER_DOMAIN_PORT_CRT) |                    \
        BIT(POWER_DOMAIN_INIT))
 #define HSW_DISPLAY_POWER_DOMAINS (                            \
        (POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS) |    \