aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/intel_audio.c
diff options
context:
space:
mode:
authorGravatar Takashi Iwai <tiwai@suse.de> 2015-11-12 15:23:41 +0100
committerGravatar Takashi Iwai <tiwai@suse.de> 2015-12-10 13:39:27 +0100
commitcae666ceb8c3f154351f7df29c522f7a7016bdc0 (patch)
treea05689bd2a327fa7cfb67c4e3ca4c0e141eda9c7 /drivers/gpu/drm/i915/intel_audio.c
parentBack merge tag 'v4.4-rc4' into drm-next (diff)
downloadlinux-cae666ceb8c3f154351f7df29c522f7a7016bdc0.tar.gz
linux-cae666ceb8c3f154351f7df29c522f7a7016bdc0.tar.bz2
linux-cae666ceb8c3f154351f7df29c522f7a7016bdc0.zip
drm/i915: Add get_eld audio component
Implement a new i915_audio_component_ops, get_eld(). It's called by the audio driver to fetch the current audio status and ELD of the given HDMI/DP port. It returns the size of expected ELD bytes if it's valid, zero if no valid ELD is found, or a negative error code. The current state of audio on/off is stored in the given pointer, too. Note that the returned size isn't limited to the given max bytes. If the size is greater than the max bytes, it means that only a part of ELD has been copied back. For achieving this implementation, a new field audio_connector is added to struct intel_digital_port. It points to the connector assigned to the given digital port. It's set/reset at each audio enable/disable call in intel_audio.c, and protected with av_mutex. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_audio.c')
-rw-r--r--drivers/gpu/drm/i915/intel_audio.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index 9aa83e71b792..eeac9f763110 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -521,6 +521,10 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
dev_priv->display.audio_codec_enable(connector, intel_encoder,
adjusted_mode);
+ mutex_lock(&dev_priv->av_mutex);
+ intel_dig_port->audio_connector = connector;
+ mutex_unlock(&dev_priv->av_mutex);
+
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
}
@@ -544,6 +548,10 @@ void intel_audio_codec_disable(struct intel_encoder *intel_encoder)
if (dev_priv->display.audio_codec_disable)
dev_priv->display.audio_codec_disable(intel_encoder);
+ mutex_lock(&dev_priv->av_mutex);
+ intel_dig_port->audio_connector = NULL;
+ mutex_unlock(&dev_priv->av_mutex);
+
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
}
@@ -703,6 +711,39 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
return 0;
}
+static int i915_audio_component_get_eld(struct device *dev, int port,
+ bool *enabled,
+ unsigned char *buf, int max_bytes)
+{
+ struct drm_i915_private *dev_priv = dev_to_i915(dev);
+ struct drm_device *drm_dev = dev_priv->dev;
+ struct intel_encoder *intel_encoder;
+ struct intel_digital_port *intel_dig_port;
+ const u8 *eld;
+ int ret = -EINVAL;
+
+ mutex_lock(&dev_priv->av_mutex);
+ for_each_intel_encoder(drm_dev, intel_encoder) {
+ if (intel_encoder->type != INTEL_OUTPUT_DISPLAYPORT &&
+ intel_encoder->type != INTEL_OUTPUT_HDMI)
+ continue;
+ intel_dig_port = enc_to_dig_port(&intel_encoder->base);
+ if (port == intel_dig_port->port) {
+ ret = 0;
+ *enabled = intel_dig_port->audio_connector != NULL;
+ if (!*enabled)
+ break;
+ eld = intel_dig_port->audio_connector->eld;
+ ret = drm_eld_size(eld);
+ memcpy(buf, eld, min(max_bytes, ret));
+ break;
+ }
+ }
+
+ mutex_unlock(&dev_priv->av_mutex);
+ return ret;
+}
+
static const struct i915_audio_component_ops i915_audio_component_ops = {
.owner = THIS_MODULE,
.get_power = i915_audio_component_get_power,
@@ -710,6 +751,7 @@ static const struct i915_audio_component_ops i915_audio_component_ops = {
.codec_wake_override = i915_audio_component_codec_wake_override,
.get_cdclk_freq = i915_audio_component_get_cdclk_freq,
.sync_audio_rate = i915_audio_component_sync_audio_rate,
+ .get_eld = i915_audio_component_get_eld,
};
static int i915_audio_component_bind(struct device *i915_dev,