drm/i915: Introduce a gmbus power domain
Currently the gmbus code uses intel_aux_display_runtime_get/put in an effort to make sure the hardware is powered up sufficiently for gmbus. That function only takes the runtime PM reference which on VLV/CHV/BXT is not enough. We need the disp2d/pipe-a well on VLV/CHV and power well 2 on BXT. So add a new power domnain for gmbus and kill off the now unused intel_aux_display_runtime_get/put. And change intel_hdmi_set_edid() to use the gmbus power domain too since that's all we need there. Also toss in a BUILD_BUG_ON() to catch problems if we run out of bits for power domains. We're already really close to the limit... [Patrik: Add gmbus string to debugfs output] Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Patrik Jakobsson <patrik.jakobsson@linux.intel.com> Signed-off-by: Imre Deak <imre.deak@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1447084107-8521-5-git-send-email-patrik.jakobsson@linux.intel.com
This commit is contained in:
parent
25f78f58e5
commit
f0ab43e6c3
@ -2745,6 +2745,8 @@ static const char *power_domain_str(enum intel_display_power_domain domain)
|
|||||||
return "AUX_C";
|
return "AUX_C";
|
||||||
case POWER_DOMAIN_AUX_D:
|
case POWER_DOMAIN_AUX_D:
|
||||||
return "AUX_D";
|
return "AUX_D";
|
||||||
|
case POWER_DOMAIN_GMBUS:
|
||||||
|
return "GMBUS";
|
||||||
case POWER_DOMAIN_INIT:
|
case POWER_DOMAIN_INIT:
|
||||||
return "INIT";
|
return "INIT";
|
||||||
default:
|
default:
|
||||||
|
@ -199,6 +199,7 @@ enum intel_display_power_domain {
|
|||||||
POWER_DOMAIN_AUX_B,
|
POWER_DOMAIN_AUX_B,
|
||||||
POWER_DOMAIN_AUX_C,
|
POWER_DOMAIN_AUX_C,
|
||||||
POWER_DOMAIN_AUX_D,
|
POWER_DOMAIN_AUX_D,
|
||||||
|
POWER_DOMAIN_GMBUS,
|
||||||
POWER_DOMAIN_INIT,
|
POWER_DOMAIN_INIT,
|
||||||
|
|
||||||
POWER_DOMAIN_NUM,
|
POWER_DOMAIN_NUM,
|
||||||
|
@ -1428,8 +1428,6 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
|
|||||||
enum intel_display_power_domain domain);
|
enum intel_display_power_domain domain);
|
||||||
void intel_display_power_put(struct drm_i915_private *dev_priv,
|
void intel_display_power_put(struct drm_i915_private *dev_priv,
|
||||||
enum intel_display_power_domain domain);
|
enum intel_display_power_domain domain);
|
||||||
void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
|
|
||||||
void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
|
|
||||||
void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
|
void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
|
||||||
void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv);
|
void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv);
|
||||||
void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
|
void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
|
||||||
|
@ -1346,21 +1346,17 @@ intel_hdmi_set_edid(struct drm_connector *connector, bool force)
|
|||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
|
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
|
||||||
struct intel_encoder *intel_encoder =
|
|
||||||
&hdmi_to_dig_port(intel_hdmi)->base;
|
|
||||||
enum intel_display_power_domain power_domain;
|
|
||||||
struct edid *edid = NULL;
|
struct edid *edid = NULL;
|
||||||
bool connected = false;
|
bool connected = false;
|
||||||
|
|
||||||
power_domain = intel_display_port_power_domain(intel_encoder);
|
intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
|
||||||
intel_display_power_get(dev_priv, power_domain);
|
|
||||||
|
|
||||||
if (force)
|
if (force)
|
||||||
edid = drm_get_edid(connector,
|
edid = drm_get_edid(connector,
|
||||||
intel_gmbus_get_adapter(dev_priv,
|
intel_gmbus_get_adapter(dev_priv,
|
||||||
intel_hdmi->ddc_bus));
|
intel_hdmi->ddc_bus));
|
||||||
|
|
||||||
intel_display_power_put(dev_priv, power_domain);
|
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
|
||||||
|
|
||||||
to_intel_connector(connector)->detect_edid = edid;
|
to_intel_connector(connector)->detect_edid = edid;
|
||||||
if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
|
if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
|
||||||
|
@ -483,7 +483,7 @@ gmbus_xfer(struct i2c_adapter *adapter,
|
|||||||
int i = 0, inc, try = 0;
|
int i = 0, inc, try = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
intel_aux_display_runtime_get(dev_priv);
|
intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
|
||||||
mutex_lock(&dev_priv->gmbus_mutex);
|
mutex_lock(&dev_priv->gmbus_mutex);
|
||||||
|
|
||||||
if (bus->force_bit) {
|
if (bus->force_bit) {
|
||||||
@ -595,7 +595,9 @@ timeout:
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&dev_priv->gmbus_mutex);
|
mutex_unlock(&dev_priv->gmbus_mutex);
|
||||||
intel_aux_display_runtime_put(dev_priv);
|
|
||||||
|
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,6 +341,7 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
|
|||||||
BIT(POWER_DOMAIN_AUX_C) | \
|
BIT(POWER_DOMAIN_AUX_C) | \
|
||||||
BIT(POWER_DOMAIN_AUDIO) | \
|
BIT(POWER_DOMAIN_AUDIO) | \
|
||||||
BIT(POWER_DOMAIN_VGA) | \
|
BIT(POWER_DOMAIN_VGA) | \
|
||||||
|
BIT(POWER_DOMAIN_GMBUS) | \
|
||||||
BIT(POWER_DOMAIN_INIT))
|
BIT(POWER_DOMAIN_INIT))
|
||||||
#define BXT_DISPLAY_POWERWELL_1_POWER_DOMAINS ( \
|
#define BXT_DISPLAY_POWERWELL_1_POWER_DOMAINS ( \
|
||||||
BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS | \
|
BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS | \
|
||||||
@ -1438,6 +1439,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
|
|||||||
BIT(POWER_DOMAIN_AUX_B) | \
|
BIT(POWER_DOMAIN_AUX_B) | \
|
||||||
BIT(POWER_DOMAIN_AUX_C) | \
|
BIT(POWER_DOMAIN_AUX_C) | \
|
||||||
BIT(POWER_DOMAIN_AUX_D) | \
|
BIT(POWER_DOMAIN_AUX_D) | \
|
||||||
|
BIT(POWER_DOMAIN_GMBUS) | \
|
||||||
BIT(POWER_DOMAIN_INIT))
|
BIT(POWER_DOMAIN_INIT))
|
||||||
#define HSW_DISPLAY_POWER_DOMAINS ( \
|
#define HSW_DISPLAY_POWER_DOMAINS ( \
|
||||||
(POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS) | \
|
(POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS) | \
|
||||||
@ -1814,6 +1816,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
|
|||||||
{
|
{
|
||||||
struct i915_power_domains *power_domains = &dev_priv->power_domains;
|
struct i915_power_domains *power_domains = &dev_priv->power_domains;
|
||||||
|
|
||||||
|
BUILD_BUG_ON(POWER_DOMAIN_NUM > 31);
|
||||||
|
|
||||||
mutex_init(&power_domains->lock);
|
mutex_init(&power_domains->lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2085,36 +2089,6 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv)
|
|||||||
intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
|
intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* intel_aux_display_runtime_get - grab an auxiliary power domain reference
|
|
||||||
* @dev_priv: i915 device instance
|
|
||||||
*
|
|
||||||
* This function grabs a power domain reference for the auxiliary power domain
|
|
||||||
* (for access to the GMBUS and DP AUX blocks) and ensures that it and all its
|
|
||||||
* parents are powered up. Therefore users should only grab a reference to the
|
|
||||||
* innermost power domain they need.
|
|
||||||
*
|
|
||||||
* Any power domain reference obtained by this function must have a symmetric
|
|
||||||
* call to intel_aux_display_runtime_put() to release the reference again.
|
|
||||||
*/
|
|
||||||
void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv)
|
|
||||||
{
|
|
||||||
intel_runtime_pm_get(dev_priv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* intel_aux_display_runtime_put - release an auxiliary power domain reference
|
|
||||||
* @dev_priv: i915 device instance
|
|
||||||
*
|
|
||||||
* This function drops the auxiliary power domain reference obtained by
|
|
||||||
* intel_aux_display_runtime_get() and might power down the corresponding
|
|
||||||
* hardware block right away if this is the last reference.
|
|
||||||
*/
|
|
||||||
void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv)
|
|
||||||
{
|
|
||||||
intel_runtime_pm_put(dev_priv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* intel_runtime_pm_get - grab a runtime pm reference
|
* intel_runtime_pm_get - grab a runtime pm reference
|
||||||
* @dev_priv: i915 device instance
|
* @dev_priv: i915 device instance
|
||||||
|
Loading…
x
Reference in New Issue
Block a user