Skip to content

Commit

Permalink
drm/i915/audio: Do the vblank waits
Browse files Browse the repository at this point in the history
The spec tells us to do a bunch of vblank waits in the audio
enable/disable sequences. Make it so.

The FIXMEs are nonsense since we do the audio disable very
early and enable very late, so vblank interrupts are in fact
enabled when we do this.

TODO not sure we actually want these since we don't even rely
on the hw ELD buffer, and these might be there just to give
the audio side a bit of time to respond to the unsol events.
OTOH they might be really needed for some other reason.

Cc: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
Cc: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Cc: Takashi Iwai <tiwai@suse.de>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221026170150.2654-15-ville.syrjala@linux.intel.com
  • Loading branch information
Ville Syrjälä committed Oct 27, 2022
1 parent cbbda2f commit c3c5dc1
Showing 1 changed file with 18 additions and 13 deletions.
31 changes: 18 additions & 13 deletions drivers/gpu/drm/i915/display/intel_audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,21 +319,28 @@ static void g4x_audio_codec_disable(struct intel_encoder *encoder,
const struct drm_connector_state *old_conn_state)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);

/* Invalidate ELD */
intel_de_rmw(i915, G4X_AUD_CNTL_ST,
G4X_ELD_VALID, 0);

intel_crtc_wait_for_next_vblank(crtc);
intel_crtc_wait_for_next_vblank(crtc);
}

static void g4x_audio_codec_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_connector *connector = conn_state->connector;
const u32 *eld = (const u32 *)connector->eld;
int eld_buffer_size, len, i;

intel_crtc_wait_for_next_vblank(crtc);

intel_de_rmw(i915, G4X_AUD_CNTL_ST,
G4X_ELD_VALID | G4X_ELD_ADDRESS_MASK, 0);

Expand Down Expand Up @@ -468,6 +475,7 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder,
const struct drm_connector_state *old_conn_state)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;

mutex_lock(&i915->display.audio.mutex);
Expand All @@ -485,6 +493,9 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder,
intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD,
AUDIO_ELD_VALID(cpu_transcoder), 0);

intel_crtc_wait_for_next_vblank(crtc);
intel_crtc_wait_for_next_vblank(crtc);

/* Disable audio presence detect */
intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD,
AUDIO_OUTPUT_ENABLE(cpu_transcoder), 0);
Expand Down Expand Up @@ -606,6 +617,7 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder,
const struct drm_connector_state *conn_state)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_connector *connector = conn_state->connector;
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
const u32 *eld = (const u32 *)connector->eld;
Expand All @@ -621,17 +633,12 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder,
intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD,
0, AUDIO_OUTPUT_ENABLE(cpu_transcoder));

intel_crtc_wait_for_next_vblank(crtc);

/* Invalidate ELD */
intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD,
AUDIO_ELD_VALID(cpu_transcoder), 0);

/*
* FIXME: We're supposed to wait for vblank here, but we have vblanks
* disabled during the mode set. The proper fix would be to push the
* rest of the setup into a vblank work item, queued here, but the
* infrastructure is not there yet.
*/

/* Reset ELD address */
intel_de_rmw(i915, HSW_AUD_DIP_ELD_CTRL(cpu_transcoder),
IBX_ELD_ADDRESS_MASK, 0);
Expand Down Expand Up @@ -729,6 +736,9 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder,
IBX_ELD_VALID(port), 0);

mutex_unlock(&i915->display.audio.mutex);

intel_crtc_wait_for_next_vblank(crtc);
intel_crtc_wait_for_next_vblank(crtc);
}

static void ilk_audio_codec_enable(struct intel_encoder *encoder,
Expand All @@ -747,12 +757,7 @@ static void ilk_audio_codec_enable(struct intel_encoder *encoder,
if (drm_WARN_ON(&i915->drm, port == PORT_A))
return;

/*
* FIXME: We're supposed to wait for vblank here, but we have vblanks
* disabled during the mode set. The proper fix would be to push the
* rest of the setup into a vblank work item, queued here, but the
* infrastructure is not there yet.
*/
intel_crtc_wait_for_next_vblank(crtc);

ilk_audio_regs_init(i915, pipe, &regs);

Expand Down

0 comments on commit c3c5dc1

Please sign in to comment.