Skip to content

Commit cae666c

Browse files
committed
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>
1 parent e876b41 commit cae666c

File tree

3 files changed

+58
-0
lines changed

3 files changed

+58
-0
lines changed

drivers/gpu/drm/i915/intel_audio.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,10 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
521521
dev_priv->display.audio_codec_enable(connector, intel_encoder,
522522
adjusted_mode);
523523

524+
mutex_lock(&dev_priv->av_mutex);
525+
intel_dig_port->audio_connector = connector;
526+
mutex_unlock(&dev_priv->av_mutex);
527+
524528
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
525529
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
526530
}
@@ -544,6 +548,10 @@ void intel_audio_codec_disable(struct intel_encoder *intel_encoder)
544548
if (dev_priv->display.audio_codec_disable)
545549
dev_priv->display.audio_codec_disable(intel_encoder);
546550

551+
mutex_lock(&dev_priv->av_mutex);
552+
intel_dig_port->audio_connector = NULL;
553+
mutex_unlock(&dev_priv->av_mutex);
554+
547555
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
548556
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
549557
}
@@ -703,13 +711,47 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
703711
return 0;
704712
}
705713

714+
static int i915_audio_component_get_eld(struct device *dev, int port,
715+
bool *enabled,
716+
unsigned char *buf, int max_bytes)
717+
{
718+
struct drm_i915_private *dev_priv = dev_to_i915(dev);
719+
struct drm_device *drm_dev = dev_priv->dev;
720+
struct intel_encoder *intel_encoder;
721+
struct intel_digital_port *intel_dig_port;
722+
const u8 *eld;
723+
int ret = -EINVAL;
724+
725+
mutex_lock(&dev_priv->av_mutex);
726+
for_each_intel_encoder(drm_dev, intel_encoder) {
727+
if (intel_encoder->type != INTEL_OUTPUT_DISPLAYPORT &&
728+
intel_encoder->type != INTEL_OUTPUT_HDMI)
729+
continue;
730+
intel_dig_port = enc_to_dig_port(&intel_encoder->base);
731+
if (port == intel_dig_port->port) {
732+
ret = 0;
733+
*enabled = intel_dig_port->audio_connector != NULL;
734+
if (!*enabled)
735+
break;
736+
eld = intel_dig_port->audio_connector->eld;
737+
ret = drm_eld_size(eld);
738+
memcpy(buf, eld, min(max_bytes, ret));
739+
break;
740+
}
741+
}
742+
743+
mutex_unlock(&dev_priv->av_mutex);
744+
return ret;
745+
}
746+
706747
static const struct i915_audio_component_ops i915_audio_component_ops = {
707748
.owner = THIS_MODULE,
708749
.get_power = i915_audio_component_get_power,
709750
.put_power = i915_audio_component_put_power,
710751
.codec_wake_override = i915_audio_component_codec_wake_override,
711752
.get_cdclk_freq = i915_audio_component_get_cdclk_freq,
712753
.sync_audio_rate = i915_audio_component_sync_audio_rate,
754+
.get_eld = i915_audio_component_get_eld,
713755
};
714756

715757
static int i915_audio_component_bind(struct device *i915_dev,

drivers/gpu/drm/i915/intel_drv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,8 @@ struct intel_digital_port {
814814
struct intel_hdmi hdmi;
815815
enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool);
816816
bool release_cl2_override;
817+
/* for communication with audio component; protected by av_mutex */
818+
const struct drm_connector *audio_connector;
817819
};
818820

819821
struct intel_dp_mst_encoder {

include/drm/i915_component.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,20 @@ struct i915_audio_component_ops {
6565
* sample rate, it will call this function to set n/cts
6666
*/
6767
int (*sync_audio_rate)(struct device *, int port, int rate);
68+
/**
69+
* @get_eld: fill the audio state and ELD bytes for the given port
70+
*
71+
* Called from audio driver to get the HDMI/DP audio state of the given
72+
* digital port, and also fetch ELD bytes to the given pointer.
73+
*
74+
* It returns the byte size of the original ELD (not the actually
75+
* copied size), zero for an invalid ELD, or a negative error code.
76+
*
77+
* Note that the returned size may be over @max_bytes. Then it
78+
* implies that only a part of ELD has been copied to the buffer.
79+
*/
80+
int (*get_eld)(struct device *, int port, bool *enabled,
81+
unsigned char *buf, int max_bytes);
6882
};
6983

7084
/**

0 commit comments

Comments
 (0)