|
@@ -563,6 +563,9 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl)
|
|
|
goto end;
|
|
|
}
|
|
|
|
|
|
+ /* disable FEC before link training */
|
|
|
+ ctrl->catalog->fec_config(ctrl->catalog, false);
|
|
|
+
|
|
|
ret = dp_ctrl_link_training_1(ctrl);
|
|
|
if (ret) {
|
|
|
DP_ERR("link training #1 failed\n");
|
|
@@ -895,6 +898,41 @@ static void dp_ctrl_send_video(struct dp_ctrl_private *ctrl)
|
|
|
ctrl->catalog->state_ctrl(ctrl->catalog, ST_SEND_VIDEO);
|
|
|
}
|
|
|
|
|
|
+static void dp_ctrl_fec_setup(struct dp_ctrl_private *ctrl)
|
|
|
+{
|
|
|
+ u8 fec_sts = 0;
|
|
|
+ int i, max_retries = 3;
|
|
|
+ bool fec_en_detected = false;
|
|
|
+
|
|
|
+ if (!ctrl->fec_mode)
|
|
|
+ return;
|
|
|
+
|
|
|
+ /* FEC should be set only for the first stream */
|
|
|
+ if (ctrl->stream_count > 1)
|
|
|
+ return;
|
|
|
+
|
|
|
+ /* Need to try to enable multiple times due to BS symbols collisions */
|
|
|
+ for (i = 0; i < max_retries; i++) {
|
|
|
+ ctrl->catalog->fec_config(ctrl->catalog, ctrl->fec_mode);
|
|
|
+
|
|
|
+ /* wait for controller to start fec sequence */
|
|
|
+ usleep_range(900, 1000);
|
|
|
+
|
|
|
+ /* read back FEC status and check if it is enabled */
|
|
|
+ drm_dp_dpcd_readb(ctrl->aux->drm_aux, DP_FEC_STATUS, &fec_sts);
|
|
|
+ if (fec_sts & DP_FEC_DECODE_EN_DETECTED) {
|
|
|
+ fec_en_detected = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ SDE_EVT32_EXTERNAL(i, fec_en_detected);
|
|
|
+ DP_DEBUG("retries %d, fec_en_detected %d\n", i, fec_en_detected);
|
|
|
+
|
|
|
+ if (!fec_en_detected)
|
|
|
+ DP_WARN("failed to enable sink fec\n");
|
|
|
+}
|
|
|
+
|
|
|
static int dp_ctrl_link_maintenance(struct dp_ctrl *dp_ctrl)
|
|
|
{
|
|
|
int ret = 0;
|
|
@@ -933,6 +971,7 @@ static int dp_ctrl_link_maintenance(struct dp_ctrl *dp_ctrl)
|
|
|
if (ctrl->stream_count) {
|
|
|
dp_ctrl_send_video(ctrl);
|
|
|
dp_ctrl_wait4video_ready(ctrl);
|
|
|
+ dp_ctrl_fec_setup(ctrl);
|
|
|
}
|
|
|
end:
|
|
|
return ret;
|
|
@@ -1173,38 +1212,14 @@ static void dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl,
|
|
|
lanes, bw_code, x_int, y_frac_enum);
|
|
|
}
|
|
|
|
|
|
-static void dp_ctrl_fec_dsc_setup(struct dp_ctrl_private *ctrl)
|
|
|
+static void dp_ctrl_dsc_setup(struct dp_ctrl_private *ctrl)
|
|
|
{
|
|
|
- u8 fec_sts = 0;
|
|
|
int rlen;
|
|
|
u32 dsc_enable;
|
|
|
- int i, max_retries = 3;
|
|
|
- bool fec_en_detected = false;
|
|
|
|
|
|
if (!ctrl->fec_mode)
|
|
|
return;
|
|
|
|
|
|
- /* Need to try to enable multiple times due to BS symbols collisions */
|
|
|
- for (i = 0; i < max_retries; i++) {
|
|
|
- ctrl->catalog->fec_config(ctrl->catalog, ctrl->fec_mode);
|
|
|
-
|
|
|
- /* wait for controller to start fec sequence */
|
|
|
- usleep_range(900, 1000);
|
|
|
-
|
|
|
- /* read back FEC status and check if it is enabled */
|
|
|
- drm_dp_dpcd_readb(ctrl->aux->drm_aux, DP_FEC_STATUS, &fec_sts);
|
|
|
- if (fec_sts & DP_FEC_DECODE_EN_DETECTED) {
|
|
|
- fec_en_detected = true;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- SDE_EVT32_EXTERNAL(i, fec_en_detected);
|
|
|
- DP_DEBUG("retries %d, fec_en_detected %d\n", i, fec_en_detected);
|
|
|
-
|
|
|
- if (!fec_en_detected)
|
|
|
- DP_WARN("failed to enable sink fec\n");
|
|
|
-
|
|
|
dsc_enable = ctrl->dsc_mode ? 1 : 0;
|
|
|
rlen = drm_dp_dpcd_writeb(ctrl->aux->drm_aux, DP_DSC_ENABLE,
|
|
|
dsc_enable);
|
|
@@ -1257,7 +1272,8 @@ static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel)
|
|
|
DP_DEBUG("mainlink %s\n", link_ready ? "READY" : "NOT READY");
|
|
|
|
|
|
/* wait for link training completion before fec config as per spec */
|
|
|
- dp_ctrl_fec_dsc_setup(ctrl);
|
|
|
+ dp_ctrl_fec_setup(ctrl);
|
|
|
+ dp_ctrl_dsc_setup(ctrl);
|
|
|
|
|
|
return rc;
|
|
|
}
|