Esempio n. 1
0
static int edp_ctrl_training(struct edp_ctrl *ctrl)
{
	int ret;

	/* Do link training only when power is on */
	if (!ctrl->power_on)
		return -EINVAL;

train_start:
	ret = edp_do_link_train(ctrl);
	if (ret == EDP_TRAIN_RECONFIG) {
		/* Re-configure main link */
		edp_ctrl_irq_enable(ctrl, 0);
		edp_ctrl_link_enable(ctrl, 0);
		msm_edp_phy_ctrl(ctrl->phy, 0);

		/* Make sure link is fully disabled */
		wmb();
		usleep_range(500, 1000);

		msm_edp_phy_ctrl(ctrl->phy, 1);
		edp_ctrl_link_enable(ctrl, 1);
		edp_ctrl_irq_enable(ctrl, 1);
		goto train_start;
	}

	return ret;
}
Esempio n. 2
0
bool msm_edp_ctrl_panel_connected(struct edp_ctrl *ctrl)
{
	mutex_lock(&ctrl->dev_mutex);
	DBG("connect status = %d", ctrl->edp_connected);
	if (ctrl->edp_connected) {
		mutex_unlock(&ctrl->dev_mutex);
		return true;
	}

	if (!ctrl->power_on) {
		edp_ctrl_phy_aux_enable(ctrl, 1);
		edp_ctrl_irq_enable(ctrl, 1);
	}

	if (drm_dp_dpcd_read(ctrl->drm_aux, DP_DPCD_REV, ctrl->dpcd,
				DP_RECEIVER_CAP_SIZE) < DP_RECEIVER_CAP_SIZE) {
		pr_err("%s: AUX channel is NOT ready\n", __func__);
		memset(ctrl->dpcd, 0, DP_RECEIVER_CAP_SIZE);
	} else {
		ctrl->edp_connected = true;
	}

	if (!ctrl->power_on) {
		edp_ctrl_irq_enable(ctrl, 0);
		edp_ctrl_phy_aux_enable(ctrl, 0);
	}

	DBG("exit: connect status=%d", ctrl->edp_connected);

	mutex_unlock(&ctrl->dev_mutex);

	return ctrl->edp_connected;
}
Esempio n. 3
0
int msm_edp_ctrl_get_panel_info(struct edp_ctrl *ctrl,
		struct drm_connector *connector, struct edid **edid)
{
	int ret = 0;

	mutex_lock(&ctrl->dev_mutex);

	if (ctrl->edid) {
		if (edid) {
			DBG("Just return edid buffer");
			*edid = ctrl->edid;
		}
		goto unlock_ret;
	}

	if (!ctrl->power_on) {
		edp_ctrl_phy_aux_enable(ctrl, 1);
		edp_ctrl_irq_enable(ctrl, 1);
	}

	ret = drm_dp_link_probe(ctrl->drm_aux, &ctrl->dp_link);
	if (ret) {
		pr_err("%s: read dpcd cap failed, %d\n", __func__, ret);
		goto disable_ret;
	}

	/* Initialize link rate as panel max link rate */
	ctrl->link_rate = drm_dp_link_rate_to_bw_code(ctrl->dp_link.rate);

	ctrl->edid = drm_get_edid(connector, &ctrl->drm_aux->ddc);
	if (!ctrl->edid) {
		pr_err("%s: edid read fail\n", __func__);
		goto disable_ret;
	}

	if (edid)
		*edid = ctrl->edid;

disable_ret:
	if (!ctrl->power_on) {
		edp_ctrl_irq_enable(ctrl, 0);
		edp_ctrl_phy_aux_enable(ctrl, 0);
	}
unlock_ret:
	mutex_unlock(&ctrl->dev_mutex);
	return ret;
}
Esempio n. 4
0
static void edp_ctrl_on_worker(struct work_struct *work)
{
	struct edp_ctrl *ctrl = container_of(
				work, struct edp_ctrl, on_work);
	int ret;

	mutex_lock(&ctrl->dev_mutex);

	if (ctrl->power_on) {
		DBG("already on");
		goto unlock_ret;
	}

	edp_ctrl_phy_aux_enable(ctrl, 1);
	edp_ctrl_link_enable(ctrl, 1);

	edp_ctrl_irq_enable(ctrl, 1);
	ret = drm_dp_link_power_up(ctrl->drm_aux, &ctrl->dp_link);
	if (ret)
		goto fail;

	ctrl->power_on = true;

	/* Start link training */
	ret = edp_ctrl_training(ctrl);
	if (ret != EDP_TRAIN_SUCCESS)
		goto fail;

	DBG("DONE");
	goto unlock_ret;

fail:
	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);
}
Esempio n. 5
0
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);
}