summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm/dp/dp_audio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/msm/dp/dp_audio.c')
-rw-r--r--drivers/gpu/drm/msm/dp/dp_audio.c32
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 = {