Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0f9531e3 authored by Tatenda Chipeperekwa's avatar Tatenda Chipeperekwa Committed by Ajay Singh Parmar
Browse files

msm: mdss: dp: trigger link retraining on link status update



Add support for link retraining in the event of a link status
update. The link status can be updated to show the current state
of clock recovery or channel equalization, and link retraining
needs to be initiated in the case of a failure.

CRs-Fixed: 1076516
Change-Id: If68d029c87db2370f07f279aacbc51d139f00aae
Signed-off-by: default avatarTatenda Chipeperekwa <tatendac@codeaurora.org>
parent 5068a5df
Loading
Loading
Loading
Loading
+79 −21
Original line number Diff line number Diff line
@@ -1303,17 +1303,23 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
	return mdss_dp_on_hpd(dp_drv);
}

static void mdss_dp_reset_test_data(struct mdss_dp_drv_pdata *dp)
static inline void mdss_dp_reset_test_data(struct mdss_dp_drv_pdata *dp)
{
	dp->test_data = (const struct dpcd_test_request){ 0 };
}

static bool mdss_dp_is_link_training_requested(struct mdss_dp_drv_pdata *dp)
static inline bool mdss_dp_is_link_status_updated(struct mdss_dp_drv_pdata *dp)
{
	return dp->link_status.link_status_updated;
}

static inline bool mdss_dp_is_link_training_requested(
		struct mdss_dp_drv_pdata *dp)
{
	return (dp->test_data.test_requested == TEST_LINK_TRAINING);
}

static bool mdss_dp_soft_hpd_reset(struct mdss_dp_drv_pdata *dp)
static inline bool mdss_dp_soft_hpd_reset(struct mdss_dp_drv_pdata *dp)
{
	return mdss_dp_is_link_training_requested(dp) &&
		dp->alt_mode.dp_status.hpd_irq;
@@ -2281,7 +2287,7 @@ end:
 * This function will send the test response to the sink but only after
 * any previous link training has been completed.
 */
static void mdss_dp_send_test_response(struct mdss_dp_drv_pdata *dp)
static inline void mdss_dp_send_test_response(struct mdss_dp_drv_pdata *dp)
{
	mutex_lock(&dp->train_mutex);
	mdss_dp_aux_send_test_response(dp);
@@ -2318,24 +2324,59 @@ static int mdss_dp_hpd_irq_notify_clients(struct mdss_dp_drv_pdata *dp)
}

/**
 * mdss_dp_process_hpd_irq_high() - handle HPD IRQ transition to HIGH
 * mdss_dp_link_retraining() - initiates link retraining
 * @dp: Display Port Driver data
 *
 * This function will handle the HPD IRQ state transitions from HIGH to HIGH
 * or LOW to HIGH, indicating the start of a new test request.
 * This function will initiate link retraining by first notifying
 * DP clients and triggering DP shutdown, and then enabling DP after
 * notification is done successfully.
 */
static void mdss_dp_process_hpd_irq_high(struct mdss_dp_drv_pdata *dp)
static inline void mdss_dp_link_retraining(struct mdss_dp_drv_pdata *dp)
{
	pr_debug("enter: HPD IRQ High\n");
	if (mdss_dp_hpd_irq_notify_clients(dp))
		return;

	dp->hpd_irq_on = true;
	mdss_dp_on_irq(dp);
}

	mdss_dp_aux_parse_sink_status_field(dp);
/**
 * mdss_dp_process_link_status_update() - processes link status updates
 * @dp: Display Port Driver data
 *
 * This function will check for changes in the link status, e.g. clock
 * recovery done on all lanes, and trigger link training if there is a
 * failure/error on the link.
 */
static void mdss_dp_process_link_status_update(struct mdss_dp_drv_pdata *dp)
{
	if (!mdss_dp_is_link_status_updated(dp) ||
			(mdss_dp_aux_channel_eq_done(dp) &&
			mdss_dp_aux_clock_recovery_done(dp)))
		return;

	pr_info("channel_eq_done = %d, clock_recovery_done = %d\n",
			mdss_dp_aux_channel_eq_done(dp),
			mdss_dp_aux_clock_recovery_done(dp));

	mdss_dp_link_retraining(dp);
}

/**
 * mdss_dp_process_link_training_request() - processes new training requests
 * @dp: Display Port Driver data
 *
 * This function will handle new link training requests that are initiated by
 * the sink. In particular, it will update the requested lane count and link
 * link rate, and then trigger the link retraining procedure.
 */
static void mdss_dp_process_link_training_request(struct mdss_dp_drv_pdata *dp)
{
	if (!mdss_dp_is_link_training_requested(dp))
		return;

	if (mdss_dp_is_link_training_requested(dp)) {
	mdss_dp_send_test_response(dp);

		pr_info("%s requested: link rate = 0x%x, lane count = 0x%x\n",
	pr_info("%s link rate = 0x%x, lane count = 0x%x\n",
			mdss_dp_get_test_name(TEST_LINK_TRAINING),
			dp->test_data.test_link_rate,
			dp->test_data.test_lane_count);
@@ -2343,12 +2384,29 @@ static void mdss_dp_process_hpd_irq_high(struct mdss_dp_drv_pdata *dp)
		dp->test_data.test_lane_count;
	dp->link_rate = dp->test_data.test_link_rate;

		if (mdss_dp_hpd_irq_notify_clients(dp))
			return;

		mdss_dp_on_irq(dp);
	mdss_dp_link_retraining(dp);
}

/**
 * mdss_dp_process_hpd_irq_high() - handle HPD IRQ transition to HIGH
 * @dp: Display Port Driver data
 *
 * This function will handle the HPD IRQ state transitions from LOW to HIGH
 * (including cases when there are back to back HPD IRQ HIGH) indicating
 * the start of a new link training request or sink status update.
 */
static void mdss_dp_process_hpd_irq_high(struct mdss_dp_drv_pdata *dp)
{
	pr_debug("enter: HPD IRQ High\n");

	dp->hpd_irq_on = true;

	mdss_dp_aux_parse_sink_status_field(dp);

	mdss_dp_process_link_training_request(dp);

	mdss_dp_process_link_status_update(dp);

	mdss_dp_reset_test_data(dp);

	pr_debug("done\n");
+2 −0
Original line number Diff line number Diff line
@@ -585,5 +585,7 @@ int mdss_dp_aux_set_sink_power_state(struct mdss_dp_drv_pdata *ep, char state);
void mdss_dp_aux_send_test_response(struct mdss_dp_drv_pdata *ep);
void *mdss_dp_get_hdcp_data(struct device *dev);
int mdss_dp_hdcp2p2_init(struct mdss_dp_drv_pdata *dp_drv);
bool mdss_dp_aux_clock_recovery_done(struct mdss_dp_drv_pdata *ep);
bool mdss_dp_aux_channel_eq_done(struct mdss_dp_drv_pdata *ep);

#endif /* MDSS_DP_H */
+8 −8
Original line number Diff line number Diff line
@@ -1238,7 +1238,7 @@ static int dp_train_pattern_set_write(struct mdss_dp_drv_pdata *ep,
	return dp_aux_write_buf(ep, 0x102, buf, 1, 0);
}

static int dp_sink_clock_recovery_done(struct mdss_dp_drv_pdata *ep)
bool mdss_dp_aux_clock_recovery_done(struct mdss_dp_drv_pdata *ep)
{
	u32 mask;
	u32 data;
@@ -1259,12 +1259,12 @@ static int dp_sink_clock_recovery_done(struct mdss_dp_drv_pdata *ep)
	pr_debug("data=%x mask=%x\n", data, mask);
	data &= mask;
	if (data == mask) /* all done */
		return 1;
		return true;

	return 0;
	return false;
}

static int dp_sink_channel_eq_done(struct mdss_dp_drv_pdata *ep)
bool mdss_dp_aux_channel_eq_done(struct mdss_dp_drv_pdata *ep)
{
	u32 mask;
	u32 data;
@@ -1293,9 +1293,9 @@ static int dp_sink_channel_eq_done(struct mdss_dp_drv_pdata *ep)

	data &= mask;
	if (data == mask)/* all done */
		return 1;
		return true;

	return 0;
	return false;
}

void dp_sink_train_set_adjust(struct mdss_dp_drv_pdata *ep)
@@ -1446,7 +1446,7 @@ static int dp_start_link_train_1(struct mdss_dp_drv_pdata *ep)
		usleep_range(usleep_time, usleep_time);

		dp_link_status_read(ep, 6);
		if (dp_sink_clock_recovery_done(ep)) {
		if (mdss_dp_aux_clock_recovery_done(ep)) {
			ret = 0;
			break;
		}
@@ -1499,7 +1499,7 @@ static int dp_start_link_train_2(struct mdss_dp_drv_pdata *ep)

		dp_link_status_read(ep, 6);

		if (dp_sink_channel_eq_done(ep)) {
		if (mdss_dp_aux_channel_eq_done(ep)) {
			ret = 0;
			break;
		}