drm/msm/dp: protect audio functionality during link maintenance

Link maintenance request from sink can be issued asynchronously
along with audio on/off functionalities. Link maintenance may
switch off and on the clocks needed for audio functionalities.
Protect the audio functionalities using lock to make sure the
required clocks are on.

CRs-Fixed: 2123895
Change-Id: I33e977b1e18feb205427a76171fd9b41fe463262
Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
[cohens@codeaurora.org: Corrected a spelling mistake in
        comment block reported by checkpatch]
Signed-off-by: Steve Cohen <cohens@codeaurora.org>
tirimbino
Ajay Singh Parmar 7 years ago committed by Steve Cohen
parent 063c0d545e
commit 75ceff9acc
  1. 9
      drivers/gpu/drm/msm/dp/dp_audio.c
  2. 2
      drivers/gpu/drm/msm/dp/dp_audio.h
  3. 20
      drivers/gpu/drm/msm/dp/dp_ctrl.c
  4. 2
      drivers/gpu/drm/msm/dp/dp_ctrl.h
  5. 15
      drivers/gpu/drm/msm/dp/dp_display.c

@ -465,12 +465,16 @@ static int dp_audio_info_setup(struct platform_device *pdev,
goto end;
}
mutex_lock(&audio->dp_audio.ops_lock);
audio->channels = params->num_of_channels;
dp_audio_setup_sdp(audio);
dp_audio_setup_acr(audio);
dp_audio_safe_to_exit_level(audio);
dp_audio_enable(audio, true);
mutex_unlock(&audio->dp_audio.ops_lock);
end:
return rc;
}
@ -545,7 +549,9 @@ static void dp_audio_teardown_done(struct platform_device *pdev)
if (IS_ERR(audio))
return;
mutex_lock(&audio->dp_audio.ops_lock);
dp_audio_enable(audio, false);
mutex_unlock(&audio->dp_audio.ops_lock);
complete_all(&audio->hpd_comp);
@ -756,6 +762,8 @@ struct dp_audio *dp_audio_get(struct platform_device *pdev,
dp_audio = &audio->dp_audio;
mutex_init(&dp_audio->ops_lock);
dp_audio->on = dp_audio_on;
dp_audio->off = dp_audio_off;
@ -780,6 +788,7 @@ void dp_audio_put(struct dp_audio *dp_audio)
return;
audio = container_of(dp_audio, struct dp_audio_private, dp_audio);
mutex_destroy(&dp_audio->ops_lock);
devm_kfree(&audio->pdev->dev, audio);
}

@ -29,6 +29,8 @@ struct dp_audio {
u32 lane_count;
u32 bw_code;
struct mutex ops_lock;
/**
* on()
*

@ -1262,31 +1262,43 @@ static void dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl)
dp_link_get_phy_test_pattern(pattern_requested));
}
static void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl)
static bool dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl)
{
struct dp_ctrl_private *ctrl;
u32 sink_request = 0x0;
bool req_handled = false;
if (!dp_ctrl) {
pr_err("invalid input\n");
return;
goto end;
}
ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
sink_request = ctrl->link->sink_request;
if (sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
pr_info("PHY_TEST_PATTERN request\n");
pr_info("PHY_TEST_PATTERN\n");
dp_ctrl_process_phy_test_request(ctrl);
req_handled = true;
}
if (sink_request & DP_LINK_STATUS_UPDATED)
if (sink_request & DP_LINK_STATUS_UPDATED) {
pr_info("DP_LINK_STATUS_UPDATED\n");
dp_ctrl_link_maintenance(ctrl);
req_handled = true;
}
if (sink_request & DP_TEST_LINK_TRAINING) {
pr_info("DP_TEST_LINK_TRAINING\n");
ctrl->link->send_test_response(ctrl->link);
dp_ctrl_link_maintenance(ctrl);
req_handled = true;
}
end:
return req_handled;
}
static void dp_ctrl_reset(struct dp_ctrl *dp_ctrl)

@ -31,7 +31,7 @@ struct dp_ctrl {
void (*push_idle)(struct dp_ctrl *dp_ctrl);
void (*abort)(struct dp_ctrl *dp_ctrl);
void (*isr)(struct dp_ctrl *dp_ctrl);
void (*handle_sink_request)(struct dp_ctrl *dp_ctrl);
bool (*handle_sink_request)(struct dp_ctrl *dp_ctrl);
};
struct dp_ctrl_in {

@ -671,6 +671,8 @@ static void dp_display_handle_video_request(struct dp_display_private *dp)
static int dp_display_handle_hpd_irq(struct dp_display_private *dp)
{
bool req_handled;
if (dp->link->sink_request & DS_PORT_STATUS_CHANGED) {
dp_display_send_hpd_notification(dp, false);
@ -682,7 +684,18 @@ static int dp_display_handle_hpd_irq(struct dp_display_private *dp)
return dp_display_process_hpd_high(dp);
}
dp->ctrl->handle_sink_request(dp->ctrl);
mutex_lock(&dp->audio->ops_lock);
req_handled = dp->ctrl->handle_sink_request(dp->ctrl);
mutex_unlock(&dp->audio->ops_lock);
/*
* reconfigure audio if test was executed
* which could have changed the controller's state
*/
if (req_handled && dp->audio_supported) {
dp->audio->off(dp->audio);
dp->audio->on(dp->audio);
}
dp_display_handle_video_request(dp);

Loading…
Cancel
Save