High Definition Audio

The graphics and audio drivers together support High Definition Audio over HDMI and Display Port. The audio programming sequences are divided into audio codec and controller enable and disable sequences. The graphics driver handles the audio codec sequences, while the audio driver handles the audio controller sequences.

The disable sequences must be performed before disabling the transcoder or port. The enable sequences may only be performed after enabling the transcoder and port, and after completed link training. Therefore the audio enable/disable sequences are part of the modeset sequence.

The codec and controller sequences could be done either parallel or serial, but generally the ELDV/PD change in the codec sequence indicates to the audio driver that the controller sequence should start. Indeed, most of the co-operation between the graphics and audio drivers is handled via audio related registers. (The notable exception is the power management, not covered here.)

The struct i915_audio_component is used to interact between the graphics and audio drivers. The struct i915_audio_component_ops ops in it is defined in graphics driver and called in audio driver. The struct i915_audio_component_audio_ops audio_ops is called from i915 driver.

void intel_audio_codec_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state)

Enable the audio codec for HD audio

Parameters

struct intel_encoder *encoder

encoder on which to enable audio

const struct intel_crtc_state *crtc_state

pointer to the current crtc state.

const struct drm_connector_state *conn_state

pointer to the current connector state.

Description

The enable sequences may only be performed after enabling the transcoder and port, and after completed link training.

void intel_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state)

Disable the audio codec for HD audio

Parameters

struct intel_encoder *encoder

encoder on which to disable audio

const struct intel_crtc_state *old_crtc_state

pointer to the old crtc state.

const struct drm_connector_state *old_conn_state

pointer to the old connector state.

Description

The disable sequences must be performed before disabling the transcoder or port.

void intel_audio_hooks_init(struct intel_display *display)

Set up chip specific audio hooks

Parameters

struct intel_display *display

display device

void intel_audio_component_init(struct intel_display *display)

initialize and register the audio component

Parameters

struct intel_display *display

display device

Description

This will register with the component framework a child component which will bind dynamically to the snd_hda_intel driver’s corresponding master component when the latter is registered. During binding the child initializes an instance of struct i915_audio_component which it receives from the master. The master can then start to use the interface defined by this struct. Each side can break the binding at any point by deregistering its own component after which each side’s component unbind callback is called.

We ignore any error during registration and continue with reduced functionality (i.e. without HDMI audio).

void intel_audio_component_cleanup(struct intel_display *display)

deregister the audio component

Parameters

struct intel_display *display

display device

Description

Deregisters the audio component, breaking any existing binding to the corresponding snd_hda_intel driver’s master component.

void intel_audio_init(struct intel_display *display)

Initialize the audio driver either using component framework or using lpe audio bridge

Parameters

struct intel_display *display

display device

void intel_audio_deinit(struct intel_display *display)

deinitialize the audio driver

Parameters

struct intel_display *display

display device

struct i915_audio_component

Used for direct communication between i915 and hda drivers

Definition:

struct i915_audio_component {
    struct drm_audio_component      base;
    int aud_sample_rate[MAX_PORTS];
};

Members

base

the drm_audio_component base class

aud_sample_rate

the array of audio sample rate per port

Intel HDMI LPE Audio Support

Motivation: Atom platforms (e.g. valleyview and cherryTrail) integrates a DMA-based interface as an alternative to the traditional HDaudio path. While this mode is unrelated to the LPE aka SST audio engine, the documentation refers to this mode as LPE so we keep this notation for the sake of consistency.

The interface is handled by a separate standalone driver maintained in the ALSA subsystem for simplicity. To minimize the interaction between the two subsystems, a bridge is setup between the hdmi-lpe-audio and i915: 1. Create a platform device to share MMIO/IRQ resources 2. Make the platform device child of i915 device for runtime PM. 3. Create IRQ chip to forward the LPE audio irqs. the hdmi-lpe-audio driver probes the lpe audio device and creates a new sound card

Threats: Due to the restriction in Linux platform device model, user need manually uninstall the hdmi-lpe-audio driver before uninstalling i915 module, otherwise we might run into use-after-free issues after i915 removes the platform device: even though hdmi-lpe-audio driver is released, the modules is still in “installed” status.

Implementation: The MMIO/REG platform resources are created according to the registers specification. When forwarding LPE audio irqs, the flow control handler selection depends on the platform, for example on valleyview handle_simple_irq is enough.

void intel_lpe_audio_irq_handler(struct intel_display *display)

forwards the LPE audio irq

Parameters

struct intel_display *display

display device

Description

the LPE Audio irq is forwarded to the irq handler registered by LPE audio driver.

int intel_lpe_audio_init(struct intel_display *display)

detect and setup the bridge between HDMI LPE Audio driver and i915

Parameters

struct intel_display *display

display device

Return

0 if successful. non-zero if detection or llocation/initialization fails

void intel_lpe_audio_teardown(struct intel_display *display)

destroy the bridge between HDMI LPE audio driver and i915

Parameters

struct intel_display *display

display device

Description

release all the resources for LPE audio <-> i915 bridge.

void intel_lpe_audio_notify(struct intel_display *display, enum transcoder cpu_transcoder, enum port port, const void *eld, int ls_clock, bool dp_output)

notify lpe audio event audio driver and i915

Parameters

struct intel_display *display

display device

enum transcoder cpu_transcoder

CPU transcoder

enum port port

port

const void *eld

ELD data

int ls_clock

Link symbol clock in kHz

bool dp_output

Driving a DP output?

Description

Notify lpe audio driver of eld change.