static void edp_ctrl_off_worker(struct work_struct *work) { struct edp_ctrl *ctrl = container_of( work, struct edp_ctrl, off_work); int ret; mutex_lock(&ctrl->dev_mutex); if (!ctrl->power_on) { DBG("already off"); goto unlock_ret; } reinit_completion(&ctrl->idle_comp); edp_state_ctrl(ctrl, EDP_STATE_CTRL_PUSH_IDLE); ret = wait_for_completion_timeout(&ctrl->idle_comp, msecs_to_jiffies(500)); if (ret <= 0) DBG("%s: idle pattern timedout, %d\n", __func__, ret); edp_state_ctrl(ctrl, 0); drm_dp_link_power_down(ctrl->drm_aux, &ctrl->dp_link); edp_ctrl_irq_enable(ctrl, 0); edp_ctrl_link_enable(ctrl, 0); edp_ctrl_phy_aux_enable(ctrl, 0); ctrl->power_on = false; unlock_ret: mutex_unlock(&ctrl->dev_mutex); }
static void edp_host_train_set(struct edp_ctrl *ctrl, u32 train) { int cnt = 10; u32 data; u32 shift = train - 1; DBG("train=%d", train); edp_state_ctrl(ctrl, EDP_STATE_CTRL_TRAIN_PATTERN_1 << shift); while (--cnt) { data = edp_read(ctrl->base + REG_EDP_MAINLINK_READY); if (data & (EDP_MAINLINK_READY_TRAIN_PATTERN_1_READY << shift)) break; } if (cnt == 0) pr_err("%s: set link_train=%d failed\n", __func__, train); }
static int edp_do_link_train(struct edp_ctrl *ctrl) { int ret; struct drm_dp_link dp_link; DBG(""); /* * Set the current link rate and lane cnt to panel. They may have been * adjusted and the values are different from them in DPCD CAP */ dp_link.num_lanes = ctrl->lane_cnt; dp_link.rate = drm_dp_bw_code_to_link_rate(ctrl->link_rate); dp_link.capabilities = ctrl->dp_link.capabilities; if (drm_dp_link_configure(ctrl->drm_aux, &dp_link) < 0) return EDP_TRAIN_FAIL; ctrl->v_level = 0; /* start from default level */ ctrl->p_level = 0; edp_state_ctrl(ctrl, 0); if (edp_clear_training_pattern(ctrl)) return EDP_TRAIN_FAIL; ret = edp_start_link_train_1(ctrl); if (ret < 0) { if (edp_link_rate_down_shift(ctrl) == 0) { DBG("link reconfig"); ret = EDP_TRAIN_RECONFIG; goto clear; } else { pr_err("%s: Training 1 failed", __func__); ret = EDP_TRAIN_FAIL; goto clear; } } DBG("Training 1 completed successfully"); edp_state_ctrl(ctrl, 0); if (edp_clear_training_pattern(ctrl)) return EDP_TRAIN_FAIL; ret = edp_start_link_train_2(ctrl); if (ret < 0) { if (edp_link_rate_down_shift(ctrl) == 0) { DBG("link reconfig"); ret = EDP_TRAIN_RECONFIG; goto clear; } else { pr_err("%s: Training 2 failed", __func__); ret = EDP_TRAIN_FAIL; goto clear; } } DBG("Training 2 completed successfully"); edp_state_ctrl(ctrl, EDP_STATE_CTRL_SEND_VIDEO); clear: edp_clear_training_pattern(ctrl); return ret; }