/** * DOC: High Definition Audio over HDMI and Display Port * * 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.
*/
/* Appendix C - N & CTS values for deep color from HDMI 2.0 spec*/ /* HDMI N/CTS table for 10 bit deep color(30 bpp)*/ #define TMDS_371M 371250 #define TMDS_370M 370878
/* * WA_14020863754: Implement Audio Workaround * Corner case with Min Hblank Fix can cause audio hang
*/ staticbool needs_wa_14020863754(struct intel_display *display)
{ return DISPLAY_VERx100(display) == 3000 ||
DISPLAY_VERx100(display) == 2000 ||
DISPLAY_VERx100(display) == 1401;
}
/* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ static u32 audio_config_hdmi_pixel_clock(conststruct intel_crtc_state *crtc_state)
{ struct intel_display *display = to_intel_display(crtc_state); conststruct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode; int i;
for (i = 0; i < ARRAY_SIZE(hdmi_audio_clock); i++) { if (adjusted_mode->crtc_clock == hdmi_audio_clock[i].clock) break;
}
if (DISPLAY_VER(display) < 12 && adjusted_mode->crtc_clock > 148500)
i = ARRAY_SIZE(hdmi_audio_clock);
if (i == ARRAY_SIZE(hdmi_audio_clock)) {
drm_dbg_kms(display->drm, "HDMI audio pixel clock setting for %d not found, falling back to defaults\n",
adjusted_mode->crtc_clock);
i = 1;
}
eld_buffer_size = g4x_eld_buffer_size(display);
len = min(drm_eld_size(crtc_state->eld) / 4, eld_buffer_size);
for (i = 0; i < len; i++)
intel_de_write(display, G4X_HDMIW_HDMIEDID, eld[i]); for (; i < eld_buffer_size; i++)
intel_de_write(display, G4X_HDMIW_HDMIEDID, 0);
if (DISPLAY_VER(display) == 11)
val |= HBLANK_EARLY_ENABLE_ICL(cpu_transcoder); elseif (DISPLAY_VER(display) >= 12)
val |= HBLANK_EARLY_ENABLE_TGL(cpu_transcoder);
if (crtc_state->dsc.compression_enable &&
crtc_state->hw.adjusted_mode.hdisplay >= 3840 &&
crtc_state->hw.adjusted_mode.vdisplay >= 2160) { /* Get hblank early enable value required */
val &= ~HBLANK_START_COUNT_MASK(cpu_transcoder);
hblank_early_prog = calc_hblank_early_prog(encoder, crtc_state); if (hblank_early_prog < 32)
val |= HBLANK_START_COUNT(cpu_transcoder, HBLANK_START_COUNT_32); elseif (hblank_early_prog < 64)
val |= HBLANK_START_COUNT(cpu_transcoder, HBLANK_START_COUNT_64); elseif (hblank_early_prog < 96)
val |= HBLANK_START_COUNT(cpu_transcoder, HBLANK_START_COUNT_96); else
val |= HBLANK_START_COUNT(cpu_transcoder, HBLANK_START_COUNT_128);
/* Get samples room value required */
val &= ~NUMBER_SAMPLES_PER_LINE_MASK(cpu_transcoder);
samples_room = calc_samples_room(crtc_state); if (samples_room < 3)
val |= NUMBER_SAMPLES_PER_LINE(cpu_transcoder, samples_room); else/* Program 0 i.e "All Samples available in buffer" */
val |= NUMBER_SAMPLES_PER_LINE(cpu_transcoder, 0x0);
}
/** * intel_audio_codec_enable - Enable the audio codec for HD audio * @encoder: encoder on which to enable audio * @crtc_state: pointer to the current crtc state. * @conn_state: pointer to the current connector state. * * The enable sequences may only be performed after enabling the transcoder and * port, and after completed link training.
*/ void intel_audio_codec_enable(struct intel_encoder *encoder, conststruct intel_crtc_state *crtc_state, conststruct drm_connector_state *conn_state)
{ struct intel_display *display = to_intel_display(encoder); struct i915_audio_component *acomp = display->audio.component; struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_connector *connector = to_intel_connector(conn_state->connector); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; struct intel_audio_state *audio_state; enum port port = encoder->port;
/** * intel_audio_codec_disable - Disable the audio codec for HD audio * @encoder: encoder on which to disable audio * @old_crtc_state: pointer to the old crtc state. * @old_conn_state: pointer to the old connector state. * * The disable sequences must be performed before disabling the transcoder or * port.
*/ void intel_audio_codec_disable(struct intel_encoder *encoder, conststruct intel_crtc_state *old_crtc_state, conststruct drm_connector_state *old_conn_state)
{ struct intel_display *display = to_intel_display(encoder); struct i915_audio_component *acomp = display->audio.component; struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct intel_connector *connector = to_intel_connector(old_conn_state->connector); enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; struct intel_audio_state *audio_state; enum port port = encoder->port;
/* need to hold at least one crtc lock for the global state */
ret = drm_modeset_lock(&crtc->base.mutex, state->base.acquire_ctx); if (ret) return ret;
cdclk_state = intel_atomic_get_cdclk_state(state); if (IS_ERR(cdclk_state)) return PTR_ERR(cdclk_state);
int intel_audio_min_cdclk(conststruct intel_crtc_state *crtc_state)
{ struct intel_display *display = to_intel_display(crtc_state); int min_cdclk = 0;
if (!crtc_state->has_audio) return 0;
/* BSpec says "Do not use DisplayPort with CDCLK less than 432 MHz, * audio enabled, port width x4, and link rate HBR2 (5.4 GHz), or else * there may be audio corruption or screen corruption." This cdclk * restriction for GLK is 316.8 MHz.
*/ if (intel_crtc_has_dp_encoder(crtc_state) &&
crtc_state->port_clock >= 540000 &&
crtc_state->lane_count == 4) { if (DISPLAY_VER(display) == 10) { /* Display WA #1145: glk */
min_cdclk = max(min_cdclk, 316800);
} elseif (DISPLAY_VER(display) == 9 || display->platform.broadwell) { /* Display WA #1144: skl,bxt */
min_cdclk = max(min_cdclk, 432000);
}
}
/* * According to BSpec, "The CD clock frequency must be at least twice * the frequency of the Azalia BCLK." and BCLK is 96 MHz by default.
*/ if (DISPLAY_VER(display) >= 9)
min_cdclk = max(min_cdclk, 2 * 96000);
/* * "For DP audio configuration, cdclk frequency shall be set to * meet the following requirements: * DP Link Frequency(MHz) | Cdclk frequency(MHz) * 270 | 320 or higher * 162 | 200 or higher"
*/ if ((display->platform.valleyview || display->platform.cherryview) &&
intel_crtc_has_dp_encoder(crtc_state))
min_cdclk = max(min_cdclk, crtc_state->port_clock);
/* Stop forcing CDCLK to 2*BCLK if no need for audio to be powered. */ if (--display->audio.power_refcount == 0) if (display->platform.geminilake)
glk_force_audio_cdclk(display, false);
/* * Enable/disable generating the codec wake signal, overriding the * internal logic to generate the codec wake to controller.
*/
intel_de_rmw(display, HSW_AUD_CHICKENBIT,
SKL_AUD_CODEC_WAKE_SIGNAL, 0);
usleep_range(1000, 1500);
if (enable) {
intel_de_rmw(display, HSW_AUD_CHICKENBIT,
0, SKL_AUD_CODEC_WAKE_SIGNAL);
usleep_range(1000, 1500);
}
intel_audio_component_put_power(kdev, cookie);
}
/* Get CDCLK in kHz */ staticint intel_audio_component_get_cdclk_freq(struct device *kdev)
{ struct intel_display *display = to_intel_display(kdev);
if (drm_WARN_ON_ONCE(display->drm, !HAS_DDI(display))) return -ENODEV;
return display->cdclk.hw.cdclk;
}
/* * get the intel audio state according to the parameter port and cpu_transcoder * MST & (cpu_transcoder >= 0): return the audio.state[cpu_transcoder].encoder], * when port is matched * MST & (cpu_transcoder < 0): this is invalid * Non-MST & (cpu_transcoder >= 0): only cpu_transcoder = 0 (the first device entry) * will get the right intel_encoder with port matched * Non-MST & (cpu_transcoder < 0): get the right intel_encoder with port matched
*/ staticstruct intel_audio_state *find_audio_state(struct intel_display *display, int port, int cpu_transcoder)
{ /* MST */ if (cpu_transcoder >= 0) { struct intel_audio_state *audio_state; struct intel_encoder *encoder;
if (drm_WARN_ON(display->drm,
cpu_transcoder >= ARRAY_SIZE(display->audio.state))) return NULL;
/** * intel_audio_component_init - initialize and register the audio component * @display: display device * * 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).
*/ staticvoid intel_audio_component_init(struct intel_display *display)
{
u32 aud_freq, aud_freq_init;
if (DISPLAY_VER(display) >= 9) {
aud_freq_init = intel_de_read(display, AUD_FREQ_CNTRL);
/* use BIOS provided value for TGL and RKL unless it is a known bad value */ if ((display->platform.tigerlake || display->platform.rocketlake) &&
aud_freq_init != AUD_FREQ_TGL_BROKEN)
aud_freq = aud_freq_init;
drm_dbg_kms(display->drm, "use AUD_FREQ_CNTRL of 0x%x (init value 0x%x)\n",
aud_freq, aud_freq_init);
display->audio.freq_cntrl = aud_freq;
}
/* init with current cdclk */
intel_audio_cdclk_change_post(display);
}
staticvoid intel_audio_component_register(struct intel_display *display)
{ int ret;
ret = component_add_typed(display->drm->dev,
&intel_audio_component_bind_ops,
I915_COMPONENT_AUDIO); if (ret < 0) {
drm_err(display->drm, "failed to add audio component (%d)\n", ret); /* continue with reduced functionality */ return;
}
display->audio.component_registered = true;
}
/** * intel_audio_component_cleanup - deregister the audio component * @display: display device * * Deregisters the audio component, breaking any existing binding to the * corresponding snd_hda_intel driver's master component.
*/ staticvoid intel_audio_component_cleanup(struct intel_display *display)
{ if (!display->audio.component_registered) return;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.