Loading drivers/gpu/drm/msm/dp/dp_ctrl.c +34 −27 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ struct dp_ctrl_private { atomic_t aborted; u32 vic; u32 stream_count; struct dp_mst_channel_info mst_ch_info; }; Loading Loading @@ -150,7 +151,7 @@ static void dp_ctrl_push_idle(struct dp_ctrl_private *ctrl, if (!wait_for_completion_timeout(&ctrl->idle_comp, idle_pattern_completion_timeout_ms)) pr_warn("time out\n"); else pr_debug("mainlink off done\n"); } Loading @@ -176,17 +177,10 @@ static void dp_ctrl_configure_source_link_params(struct dp_ctrl_private *ctrl, } } static int dp_ctrl_wait4video_ready(struct dp_ctrl_private *ctrl) static void dp_ctrl_wait4video_ready(struct dp_ctrl_private *ctrl) { int ret = 0; ret = wait_for_completion_timeout(&ctrl->video_comp, HZ / 2); if (ret <= 0) { pr_err("SEND_VIDEO time out (%d)\n", ret); return -EINVAL; } return 0; if (!wait_for_completion_timeout(&ctrl->video_comp, HZ / 2)) pr_warn("SEND_VIDEO time out\n"); } static int dp_ctrl_update_sink_vx_px(struct dp_ctrl_private *ctrl, Loading Loading @@ -567,7 +561,7 @@ static void dp_ctrl_disable_link_clock(struct dp_ctrl_private *ctrl) ctrl->power->clk_enable(ctrl->power, DP_LINK_PM, false); } static int dp_ctrl_link_setup(struct dp_ctrl_private *ctrl) static int dp_ctrl_link_setup(struct dp_ctrl_private *ctrl, bool shallow) { int rc = -EINVAL; u32 link_train_max_retries = 100; Loading @@ -585,13 +579,26 @@ static int dp_ctrl_link_setup(struct dp_ctrl_private *ctrl) pr_debug("bw_code=%d, lane_count=%d\n", link_params->bw_code, link_params->lane_count); dp_ctrl_enable_link_clock(ctrl); rc = dp_ctrl_enable_link_clock(ctrl); if (rc) break; dp_ctrl_configure_source_link_params(ctrl, true); rc = dp_ctrl_setup_main_link(ctrl); if (!rc) break; /* * Shallow means link training failure is not important. * If it fails, we still keep the link clocks on. * In this mode, the system expects DP to be up * even though the cable is removed. Disconnect interrupt * will eventually trigger and shutdown DP. */ if (shallow) break; dp_ctrl_link_rate_down_shift(ctrl); dp_ctrl_configure_source_link_params(ctrl, false); Loading Loading @@ -748,8 +755,10 @@ static int dp_ctrl_link_maintenance(struct dp_ctrl *dp_ctrl) ctrl->aux->state |= DP_STATE_LINK_MAINTENANCE_COMPLETED; if (ctrl->stream_count) { dp_ctrl_send_video(ctrl); ret = dp_ctrl_wait4video_ready(ctrl); dp_ctrl_wait4video_ready(ctrl); } end: return ret; } Loading Loading @@ -785,7 +794,7 @@ static void dp_ctrl_process_phy_test_request(struct dp_ctrl *dp_ctrl) ctrl->aux->init(ctrl->aux, ctrl->parser->aux_cfg); ret = ctrl->dp_ctrl.on(&ctrl->dp_ctrl, ctrl->mst_mode); ret = ctrl->dp_ctrl.on(&ctrl->dp_ctrl, ctrl->mst_mode, false); if (ret) pr_err("failed to enable DP controller\n"); Loading Loading @@ -1008,18 +1017,14 @@ static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) dp_ctrl_mst_send_act(ctrl); rc = dp_ctrl_wait4video_ready(ctrl); if (rc) goto error; dp_ctrl_wait4video_ready(ctrl); ctrl->stream_count++; link_ready = ctrl->catalog->mainlink_ready(ctrl->catalog); pr_debug("mainlink %s\n", link_ready ? "READY" : "NOT READY"); return rc; error: dp_ctrl_disable_stream_clocks(ctrl, panel); return rc; } static void dp_ctrl_mst_stream_pre_off(struct dp_ctrl *dp_ctrl, Loading Loading @@ -1083,9 +1088,10 @@ static void dp_ctrl_stream_off(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) panel->hw_cfg(panel, false); dp_ctrl_disable_stream_clocks(ctrl, panel); ctrl->stream_count--; } static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode) static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode, bool shallow) { int rc = 0; struct dp_ctrl_private *ctrl; Loading Loading @@ -1117,8 +1123,9 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode) ctrl->link->link_params.bw_code, ctrl->link->link_params.lane_count); rc = dp_ctrl_link_setup(ctrl); if (rc) rc = dp_ctrl_link_setup(ctrl, shallow); /* Ignore errors in case of shallow processing */ if (!shallow && rc) goto end; ctrl->power_on = true; Loading drivers/gpu/drm/msm/dp/dp_ctrl.h +1 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ struct dp_ctrl { int (*init)(struct dp_ctrl *dp_ctrl, bool flip, bool reset); void (*deinit)(struct dp_ctrl *dp_ctrl); int (*on)(struct dp_ctrl *dp_ctrl, bool mst_mode); int (*on)(struct dp_ctrl *dp_ctrl, bool mst_mode, bool shallow); void (*off)(struct dp_ctrl *dp_ctrl); void (*abort)(struct dp_ctrl *dp_ctrl); void (*isr)(struct dp_ctrl *dp_ctrl); Loading drivers/gpu/drm/msm/dp/dp_display.c +20 −40 Original line number Diff line number Diff line Loading @@ -495,14 +495,8 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp) dp->aux->state |= DP_STATE_NOTIFICATION_SENT; if (!dp->mst.mst_active) { if (dp->dp_display.is_sst_connected == hpd) { pr_debug("SKIPPED:hpd:%d\n", hpd); goto skip_wait; } if (!dp->mst.mst_active) dp->dp_display.is_sst_connected = hpd; } reinit_completion(&dp->notification_comp); dp_display_send_hpd_event(dp); Loading Loading @@ -566,31 +560,6 @@ static void dp_display_host_init(struct dp_display_private *dp) dp->core_initialized = true; } static int dp_display_update_pclk(struct dp_display_private *dp) { int rc = 0; u32 rate, max_pclk_khz; u32 const enc_factx10 = 8; u32 const default_bpp = 30; if (dp->debug->max_pclk_khz) { dp->dp_display.max_pclk_khz = dp->debug->max_pclk_khz; goto end; } rate = drm_dp_bw_code_to_link_rate(dp->link->link_params.bw_code); rate /= default_bpp; max_pclk_khz = dp->link->link_params.lane_count * rate * enc_factx10; dp->dp_display.max_pclk_khz = min(dp->parser->max_pclk_khz, max_pclk_khz); pr_debug("dp max_pclk_khz = %d\n", dp->dp_display.max_pclk_khz); end: return rc; } static void dp_display_host_deinit(struct dp_display_private *dp) { if (!dp->core_initialized) { Loading Loading @@ -623,6 +592,8 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp->is_connected = true; dp->dp_display.max_pclk_khz = dp->parser->max_pclk_khz; dp_display_host_init(dp); if (dp->debug->psm_enabled) { Loading @@ -648,13 +619,7 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp_display_process_mst_hpd_high(dp); mutex_lock(&dp->session_lock); rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active); if (rc) { mutex_unlock(&dp->session_lock); goto end; } rc = dp_display_update_pclk(dp); rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active, false); if (rc) { mutex_unlock(&dp->session_lock); goto end; Loading Loading @@ -958,6 +923,11 @@ static int dp_display_usbpd_attention_cb(struct device *dev) dp->power_on); if (!dp->hpd->hpd_high) { if (!dp->is_connected) { pr_debug("already disconnected\n"); return 0; } /* cancel any pending request */ atomic_set(&dp->aborted, 1); dp->ctrl->abort(dp->ctrl); Loading Loading @@ -1285,7 +1255,17 @@ static int dp_display_prepare(struct dp_display *dp_display, void *panel) dp_display_host_init(dp); rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active); /* * Execute the dp controller power on in shallow mode here. * In normal cases, controller should have been powered on * by now. In some cases like suspend/resume or framework * reboot, we end up here without a powered on controller. * Cable may have been removed in suspended state. In that * case, link training is bound to fail on system resume. * So, we execute in shallow mode here to do only minimal * and required things. */ rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active, true); if (rc) goto end; Loading Loading
drivers/gpu/drm/msm/dp/dp_ctrl.c +34 −27 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ struct dp_ctrl_private { atomic_t aborted; u32 vic; u32 stream_count; struct dp_mst_channel_info mst_ch_info; }; Loading Loading @@ -150,7 +151,7 @@ static void dp_ctrl_push_idle(struct dp_ctrl_private *ctrl, if (!wait_for_completion_timeout(&ctrl->idle_comp, idle_pattern_completion_timeout_ms)) pr_warn("time out\n"); else pr_debug("mainlink off done\n"); } Loading @@ -176,17 +177,10 @@ static void dp_ctrl_configure_source_link_params(struct dp_ctrl_private *ctrl, } } static int dp_ctrl_wait4video_ready(struct dp_ctrl_private *ctrl) static void dp_ctrl_wait4video_ready(struct dp_ctrl_private *ctrl) { int ret = 0; ret = wait_for_completion_timeout(&ctrl->video_comp, HZ / 2); if (ret <= 0) { pr_err("SEND_VIDEO time out (%d)\n", ret); return -EINVAL; } return 0; if (!wait_for_completion_timeout(&ctrl->video_comp, HZ / 2)) pr_warn("SEND_VIDEO time out\n"); } static int dp_ctrl_update_sink_vx_px(struct dp_ctrl_private *ctrl, Loading Loading @@ -567,7 +561,7 @@ static void dp_ctrl_disable_link_clock(struct dp_ctrl_private *ctrl) ctrl->power->clk_enable(ctrl->power, DP_LINK_PM, false); } static int dp_ctrl_link_setup(struct dp_ctrl_private *ctrl) static int dp_ctrl_link_setup(struct dp_ctrl_private *ctrl, bool shallow) { int rc = -EINVAL; u32 link_train_max_retries = 100; Loading @@ -585,13 +579,26 @@ static int dp_ctrl_link_setup(struct dp_ctrl_private *ctrl) pr_debug("bw_code=%d, lane_count=%d\n", link_params->bw_code, link_params->lane_count); dp_ctrl_enable_link_clock(ctrl); rc = dp_ctrl_enable_link_clock(ctrl); if (rc) break; dp_ctrl_configure_source_link_params(ctrl, true); rc = dp_ctrl_setup_main_link(ctrl); if (!rc) break; /* * Shallow means link training failure is not important. * If it fails, we still keep the link clocks on. * In this mode, the system expects DP to be up * even though the cable is removed. Disconnect interrupt * will eventually trigger and shutdown DP. */ if (shallow) break; dp_ctrl_link_rate_down_shift(ctrl); dp_ctrl_configure_source_link_params(ctrl, false); Loading Loading @@ -748,8 +755,10 @@ static int dp_ctrl_link_maintenance(struct dp_ctrl *dp_ctrl) ctrl->aux->state |= DP_STATE_LINK_MAINTENANCE_COMPLETED; if (ctrl->stream_count) { dp_ctrl_send_video(ctrl); ret = dp_ctrl_wait4video_ready(ctrl); dp_ctrl_wait4video_ready(ctrl); } end: return ret; } Loading Loading @@ -785,7 +794,7 @@ static void dp_ctrl_process_phy_test_request(struct dp_ctrl *dp_ctrl) ctrl->aux->init(ctrl->aux, ctrl->parser->aux_cfg); ret = ctrl->dp_ctrl.on(&ctrl->dp_ctrl, ctrl->mst_mode); ret = ctrl->dp_ctrl.on(&ctrl->dp_ctrl, ctrl->mst_mode, false); if (ret) pr_err("failed to enable DP controller\n"); Loading Loading @@ -1008,18 +1017,14 @@ static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) dp_ctrl_mst_send_act(ctrl); rc = dp_ctrl_wait4video_ready(ctrl); if (rc) goto error; dp_ctrl_wait4video_ready(ctrl); ctrl->stream_count++; link_ready = ctrl->catalog->mainlink_ready(ctrl->catalog); pr_debug("mainlink %s\n", link_ready ? "READY" : "NOT READY"); return rc; error: dp_ctrl_disable_stream_clocks(ctrl, panel); return rc; } static void dp_ctrl_mst_stream_pre_off(struct dp_ctrl *dp_ctrl, Loading Loading @@ -1083,9 +1088,10 @@ static void dp_ctrl_stream_off(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) panel->hw_cfg(panel, false); dp_ctrl_disable_stream_clocks(ctrl, panel); ctrl->stream_count--; } static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode) static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode, bool shallow) { int rc = 0; struct dp_ctrl_private *ctrl; Loading Loading @@ -1117,8 +1123,9 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode) ctrl->link->link_params.bw_code, ctrl->link->link_params.lane_count); rc = dp_ctrl_link_setup(ctrl); if (rc) rc = dp_ctrl_link_setup(ctrl, shallow); /* Ignore errors in case of shallow processing */ if (!shallow && rc) goto end; ctrl->power_on = true; Loading
drivers/gpu/drm/msm/dp/dp_ctrl.h +1 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ struct dp_ctrl { int (*init)(struct dp_ctrl *dp_ctrl, bool flip, bool reset); void (*deinit)(struct dp_ctrl *dp_ctrl); int (*on)(struct dp_ctrl *dp_ctrl, bool mst_mode); int (*on)(struct dp_ctrl *dp_ctrl, bool mst_mode, bool shallow); void (*off)(struct dp_ctrl *dp_ctrl); void (*abort)(struct dp_ctrl *dp_ctrl); void (*isr)(struct dp_ctrl *dp_ctrl); Loading
drivers/gpu/drm/msm/dp/dp_display.c +20 −40 Original line number Diff line number Diff line Loading @@ -495,14 +495,8 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp) dp->aux->state |= DP_STATE_NOTIFICATION_SENT; if (!dp->mst.mst_active) { if (dp->dp_display.is_sst_connected == hpd) { pr_debug("SKIPPED:hpd:%d\n", hpd); goto skip_wait; } if (!dp->mst.mst_active) dp->dp_display.is_sst_connected = hpd; } reinit_completion(&dp->notification_comp); dp_display_send_hpd_event(dp); Loading Loading @@ -566,31 +560,6 @@ static void dp_display_host_init(struct dp_display_private *dp) dp->core_initialized = true; } static int dp_display_update_pclk(struct dp_display_private *dp) { int rc = 0; u32 rate, max_pclk_khz; u32 const enc_factx10 = 8; u32 const default_bpp = 30; if (dp->debug->max_pclk_khz) { dp->dp_display.max_pclk_khz = dp->debug->max_pclk_khz; goto end; } rate = drm_dp_bw_code_to_link_rate(dp->link->link_params.bw_code); rate /= default_bpp; max_pclk_khz = dp->link->link_params.lane_count * rate * enc_factx10; dp->dp_display.max_pclk_khz = min(dp->parser->max_pclk_khz, max_pclk_khz); pr_debug("dp max_pclk_khz = %d\n", dp->dp_display.max_pclk_khz); end: return rc; } static void dp_display_host_deinit(struct dp_display_private *dp) { if (!dp->core_initialized) { Loading Loading @@ -623,6 +592,8 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp->is_connected = true; dp->dp_display.max_pclk_khz = dp->parser->max_pclk_khz; dp_display_host_init(dp); if (dp->debug->psm_enabled) { Loading @@ -648,13 +619,7 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp_display_process_mst_hpd_high(dp); mutex_lock(&dp->session_lock); rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active); if (rc) { mutex_unlock(&dp->session_lock); goto end; } rc = dp_display_update_pclk(dp); rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active, false); if (rc) { mutex_unlock(&dp->session_lock); goto end; Loading Loading @@ -958,6 +923,11 @@ static int dp_display_usbpd_attention_cb(struct device *dev) dp->power_on); if (!dp->hpd->hpd_high) { if (!dp->is_connected) { pr_debug("already disconnected\n"); return 0; } /* cancel any pending request */ atomic_set(&dp->aborted, 1); dp->ctrl->abort(dp->ctrl); Loading Loading @@ -1285,7 +1255,17 @@ static int dp_display_prepare(struct dp_display *dp_display, void *panel) dp_display_host_init(dp); rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active); /* * Execute the dp controller power on in shallow mode here. * In normal cases, controller should have been powered on * by now. In some cases like suspend/resume or framework * reboot, we end up here without a powered on controller. * Cable may have been removed in suspended state. In that * case, link training is bound to fail on system resume. * So, we execute in shallow mode here to do only minimal * and required things. */ rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active, true); if (rc) goto end; Loading