diff options
author | Abhinav Kumar <abhinavk@codeaurora.org> | 2020-09-12 13:49:32 -0700 |
---|---|---|
committer | Rob Clark <robdclark@chromium.org> | 2020-09-15 10:54:35 -0700 |
commit | 158b9aa74479c9979b7b4806cefdbf0c9a72ba49 (patch) | |
tree | 6768265267b788f69ada719bc8440524ee63b0e8 /drivers/gpu/drm/msm/dp/dp_audio.c | |
parent | bf4a1b3127d34b0b6ee0565b31ff699b3dc9c48e (diff) |
drm/msm/dp: wait for audio notification before disabling clocks
In the current implementation, there is a very small window for
the audio side to safely signal the hdmi_code_shutdown() before
the clocks are disabled.
Add some synchronization between the DP display and DP audio module
to safely disable the clocks to avoid unclocked access from audio
side.
In addition, audio side can open the sound card even if DP monitor
is not connected. Avoid programming hardware registers in this case
and bail out early.
Changes in v4:
- removed some leftover prints
Changes in v5:
- fix crash when user tries to play audio in suspended
state
Changes in v6:
- rebased on top of latest patchset of dependency
Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@chromium.org>
Diffstat (limited to 'drivers/gpu/drm/msm/dp/dp_audio.c')
-rw-r--r-- | drivers/gpu/drm/msm/dp/dp_audio.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c index 11fa5ad7a801..82a8673ab8da 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.c +++ b/drivers/gpu/drm/msm/dp/dp_audio.c @@ -497,8 +497,23 @@ int dp_audio_hw_params(struct device *dev, int rc = 0; struct dp_audio_private *audio; struct platform_device *pdev; + struct msm_dp *dp_display; pdev = to_platform_device(dev); + dp_display = platform_get_drvdata(pdev); + + /* + * there could be cases where sound card can be opened even + * before OR even when DP is not connected . This can cause + * unclocked access as the audio subsystem relies on the DP + * driver to maintain the correct state of clocks. To protect + * such cases check for connection status and bail out if not + * connected. + */ + if (!dp_display->power_on) { + rc = -EINVAL; + goto end; + } audio = dp_audio_get_data(pdev); if (IS_ERR(audio)) { @@ -512,6 +527,8 @@ int dp_audio_hw_params(struct device *dev, dp_audio_setup_acr(audio); dp_audio_safe_to_exit_level(audio); dp_audio_enable(audio, true); + dp_display->audio_enabled = true; + end: return rc; } @@ -520,15 +537,30 @@ static void dp_audio_shutdown(struct device *dev, void *data) { struct dp_audio_private *audio; struct platform_device *pdev; + struct msm_dp *dp_display; pdev = to_platform_device(dev); + dp_display = platform_get_drvdata(pdev); audio = dp_audio_get_data(pdev); if (IS_ERR(audio)) { DRM_ERROR("failed to get audio data\n"); return; } + /* + * if audio was not enabled there is no need + * to execute the shutdown and we can bail out early. + * This also makes sure that we dont cause an unclocked + * access when audio subsystem calls this without DP being + * connected. is_connected cannot be used here as its set + * to false earlier than this call + */ + if (!dp_display->audio_enabled) + return; + dp_audio_enable(audio, false); + /* signal the dp display to safely shutdown clocks */ + dp_display_signal_audio_complete(dp_display); } static const struct hdmi_codec_ops dp_audio_codec_ops = { |