Merge "msm: mdss: dp: fix handling of link training mutex"
This commit is contained in:
commit
1cb457387d
5 changed files with 323 additions and 25 deletions
|
@ -1211,16 +1211,20 @@ static int mdss_dp_on_irq(struct mdss_dp_drv_pdata *dp_drv)
|
|||
|
||||
ret = mdss_dp_get_lane_mapping(dp_drv, dp_drv->orientation,
|
||||
&ln_map);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
mutex_unlock(&dp_drv->train_mutex);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mdss_dp_phy_share_lane_config(&dp_drv->phy_io,
|
||||
dp_drv->orientation,
|
||||
dp_drv->dpcd.max_lane_count);
|
||||
|
||||
ret = mdss_dp_enable_mainlink_clocks(dp_drv);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
mutex_unlock(&dp_drv->train_mutex);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mdss_dp_mainlink_reset(&dp_drv->ctrl_io);
|
||||
|
||||
|
@ -1238,7 +1242,6 @@ static int mdss_dp_on_irq(struct mdss_dp_drv_pdata *dp_drv)
|
|||
pr_debug("end\n");
|
||||
|
||||
exit:
|
||||
mutex_unlock(&dp_drv->train_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1351,9 +1354,16 @@ static inline bool mdss_dp_is_link_training_requested(
|
|||
return (dp->test_data.test_requested == TEST_LINK_TRAINING);
|
||||
}
|
||||
|
||||
static inline bool mdss_dp_is_phy_test_pattern_requested(
|
||||
struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
return (dp->test_data.test_requested == PHY_TEST_PATTERN);
|
||||
}
|
||||
|
||||
static inline bool mdss_dp_soft_hpd_reset(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
return mdss_dp_is_link_training_requested(dp) &&
|
||||
return (mdss_dp_is_link_training_requested(dp) ||
|
||||
mdss_dp_is_phy_test_pattern_requested(dp)) &&
|
||||
dp->alt_mode.dp_status.hpd_irq;
|
||||
}
|
||||
|
||||
|
@ -2500,6 +2510,57 @@ static int mdss_dp_process_link_training_request(struct mdss_dp_drv_pdata *dp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_process_phy_test_pattern_request() - process new phy test requests
|
||||
* @dp: Display Port Driver data
|
||||
*
|
||||
* This function will handle new phy test pattern requests that are initiated
|
||||
* by the sink. The function will return 0 if a phy test pattern has been
|
||||
* processed, otherwise it will return -EINVAL.
|
||||
*/
|
||||
static int mdss_dp_process_phy_test_pattern_request(
|
||||
struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
u32 test_link_rate = 0, test_lane_count = 0;
|
||||
|
||||
if (!mdss_dp_is_phy_test_pattern_requested(dp))
|
||||
return -EINVAL;
|
||||
|
||||
mdss_dp_send_test_response(dp);
|
||||
|
||||
test_link_rate = dp->test_data.test_link_rate;
|
||||
test_lane_count = dp->test_data.test_lane_count;
|
||||
|
||||
pr_info("%s link rate = 0x%x, lane count = 0x%x\n",
|
||||
mdss_dp_get_test_name(TEST_LINK_TRAINING),
|
||||
test_link_rate, test_lane_count);
|
||||
|
||||
/**
|
||||
* Retrain the mainlink if there is a change in link rate or lane
|
||||
* count.
|
||||
*/
|
||||
if (mdss_dp_aux_is_link_rate_valid(test_link_rate) &&
|
||||
mdss_dp_aux_is_lane_count_valid(test_lane_count) &&
|
||||
((dp->dpcd.max_lane_count != test_lane_count) ||
|
||||
(dp->link_rate != test_link_rate))) {
|
||||
|
||||
pr_info("updated link rate or lane count, retraining.\n");
|
||||
|
||||
dp->dpcd.max_lane_count = dp->test_data.test_lane_count;
|
||||
dp->link_rate = dp->test_data.test_link_rate;
|
||||
|
||||
mdss_dp_link_retraining(dp);
|
||||
}
|
||||
|
||||
mdss_dp_config_ctrl(dp);
|
||||
|
||||
mdss_dp_aux_update_voltage_and_pre_emphasis_lvl(dp);
|
||||
|
||||
mdss_dp_phy_send_test_pattern(dp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_process_downstream_port_status_change() - process port status changes
|
||||
* @dp: Display Port Driver data
|
||||
|
@ -2548,6 +2609,9 @@ static int mdss_dp_process_hpd_irq_high(struct mdss_dp_drv_pdata *dp)
|
|||
if (!ret)
|
||||
goto exit;
|
||||
|
||||
ret = mdss_dp_process_phy_test_pattern_request(dp);
|
||||
if (!ret)
|
||||
goto exit;
|
||||
pr_debug("done\n");
|
||||
exit:
|
||||
mdss_dp_reset_test_data(dp);
|
||||
|
|
|
@ -268,6 +268,7 @@ struct dpcd_test_request {
|
|||
u32 test_requested;
|
||||
u32 test_link_rate;
|
||||
u32 test_lane_count;
|
||||
u32 phy_test_pattern_sel;
|
||||
u32 response;
|
||||
};
|
||||
|
||||
|
@ -509,6 +510,51 @@ enum dp_lane_count {
|
|||
DP_LANE_COUNT_4 = 4,
|
||||
};
|
||||
|
||||
enum phy_test_pattern {
|
||||
PHY_TEST_PATTERN_NONE,
|
||||
PHY_TEST_PATTERN_D10_2_NO_SCRAMBLING,
|
||||
PHY_TEST_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT,
|
||||
PHY_TEST_PATTERN_PRBS7,
|
||||
PHY_TEST_PATTERN_80_BIT_CUSTOM_PATTERN,
|
||||
PHY_TEST_PATTERN_HBR2_CTS_EYE_PATTERN,
|
||||
};
|
||||
|
||||
static inline char *mdss_dp_get_phy_test_pattern(u32 phy_test_pattern_sel)
|
||||
{
|
||||
switch (phy_test_pattern_sel) {
|
||||
case PHY_TEST_PATTERN_NONE:
|
||||
return DP_ENUM_STR(PHY_TEST_PATTERN_NONE);
|
||||
case PHY_TEST_PATTERN_D10_2_NO_SCRAMBLING:
|
||||
return DP_ENUM_STR(PHY_TEST_PATTERN_D10_2_NO_SCRAMBLING);
|
||||
case PHY_TEST_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT:
|
||||
return DP_ENUM_STR(PHY_TEST_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT);
|
||||
case PHY_TEST_PATTERN_PRBS7:
|
||||
return DP_ENUM_STR(PHY_TEST_PATTERN_PRBS7);
|
||||
case PHY_TEST_PATTERN_80_BIT_CUSTOM_PATTERN:
|
||||
return DP_ENUM_STR(PHY_TEST_PATTERN_80_BIT_CUSTOM_PATTERN);
|
||||
case PHY_TEST_PATTERN_HBR2_CTS_EYE_PATTERN:
|
||||
return DP_ENUM_STR(PHY_TEST_PATTERN_HBR2_CTS_EYE_PATTERN);
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool mdss_dp_is_phy_test_pattern_supported(
|
||||
u32 phy_test_pattern_sel)
|
||||
{
|
||||
switch (phy_test_pattern_sel) {
|
||||
case PHY_TEST_PATTERN_NONE:
|
||||
case PHY_TEST_PATTERN_D10_2_NO_SCRAMBLING:
|
||||
case PHY_TEST_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT:
|
||||
case PHY_TEST_PATTERN_PRBS7:
|
||||
case PHY_TEST_PATTERN_80_BIT_CUSTOM_PATTERN:
|
||||
case PHY_TEST_PATTERN_HBR2_CTS_EYE_PATTERN:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
enum dp_aux_error {
|
||||
EDP_AUX_ERR_NONE = 0,
|
||||
EDP_AUX_ERR_ADDR = -1,
|
||||
|
@ -561,7 +607,7 @@ static inline char *mdss_dp_get_test_response(u32 test_response)
|
|||
enum test_type {
|
||||
UNKNOWN_TEST = 0,
|
||||
TEST_LINK_TRAINING = BIT(0),
|
||||
TEST_PATTERN = BIT(1),
|
||||
PHY_TEST_PATTERN = BIT(3),
|
||||
TEST_EDID_READ = BIT(2),
|
||||
};
|
||||
|
||||
|
@ -569,7 +615,7 @@ static inline char *mdss_dp_get_test_name(u32 test_requested)
|
|||
{
|
||||
switch (test_requested) {
|
||||
case TEST_LINK_TRAINING: return DP_ENUM_STR(TEST_LINK_TRAINING);
|
||||
case TEST_PATTERN: return DP_ENUM_STR(TEST_PATTERN);
|
||||
case PHY_TEST_PATTERN: return DP_ENUM_STR(PHY_TEST_PATTERN);
|
||||
case TEST_EDID_READ: return DP_ENUM_STR(TEST_EDID_READ);
|
||||
default: return "unknown";
|
||||
}
|
||||
|
@ -640,5 +686,10 @@ 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);
|
||||
bool mdss_dp_aux_is_link_rate_valid(u32 link_rate);
|
||||
bool mdss_dp_aux_is_lane_count_valid(u32 lane_count);
|
||||
int mdss_dp_aux_link_status_read(struct mdss_dp_drv_pdata *ep, int len);
|
||||
void mdss_dp_aux_update_voltage_and_pre_emphasis_lvl(
|
||||
struct mdss_dp_drv_pdata *dp);
|
||||
|
||||
#endif /* MDSS_DP_H */
|
||||
|
|
|
@ -537,8 +537,9 @@ char mdss_dp_gen_link_clk(struct mdss_panel_info *pinfo, char lane_cnt)
|
|||
else if (min_link_rate <= DP_LINK_RATE_540)
|
||||
calc_link_rate = DP_LINK_RATE_540;
|
||||
else {
|
||||
pr_err("link_rate = %d is unsupported\n", min_link_rate);
|
||||
calc_link_rate = 0;
|
||||
/* Cap the link rate to the max supported rate */
|
||||
pr_debug("link_rate = %d is unsupported\n", min_link_rate);
|
||||
calc_link_rate = DP_LINK_RATE_540;
|
||||
}
|
||||
|
||||
return calc_link_rate;
|
||||
|
@ -960,7 +961,7 @@ static void dp_sink_capability_read(struct mdss_dp_drv_pdata *ep,
|
|||
dp_sink_parse_sink_count(ep);
|
||||
}
|
||||
|
||||
static int dp_link_status_read(struct mdss_dp_drv_pdata *ep, int len)
|
||||
int mdss_dp_aux_link_status_read(struct mdss_dp_drv_pdata *ep, int len)
|
||||
{
|
||||
char *bp;
|
||||
char data;
|
||||
|
@ -1031,12 +1032,12 @@ void mdss_dp_aux_send_test_response(struct mdss_dp_drv_pdata *dp)
|
|||
}
|
||||
|
||||
/**
|
||||
* dp_is_link_rate_valid() - validates the link rate
|
||||
* mdss_dp_aux_is_link_rate_valid() - validates the link rate
|
||||
* @lane_rate: link rate requested by the sink
|
||||
*
|
||||
* Returns true if the requested link rate is supported.
|
||||
*/
|
||||
static bool dp_is_link_rate_valid(u32 link_rate)
|
||||
bool mdss_dp_aux_is_link_rate_valid(u32 link_rate)
|
||||
{
|
||||
return (link_rate == DP_LINK_RATE_162) ||
|
||||
(link_rate == DP_LINK_RATE_270) ||
|
||||
|
@ -1044,12 +1045,12 @@ static bool dp_is_link_rate_valid(u32 link_rate)
|
|||
}
|
||||
|
||||
/**
|
||||
* dp_is_lane_count_valid() - validates the lane count
|
||||
* mdss_dp_aux_is_lane_count_valid() - validates the lane count
|
||||
* @lane_count: lane count requested by the sink
|
||||
*
|
||||
* Returns true if the requested lane count is supported.
|
||||
*/
|
||||
static bool dp_is_lane_count_valid(u32 lane_count)
|
||||
bool mdss_dp_aux_is_lane_count_valid(u32 lane_count)
|
||||
{
|
||||
return (lane_count == DP_LANE_COUNT_1) ||
|
||||
(lane_count == DP_LANE_COUNT_2) ||
|
||||
|
@ -1086,7 +1087,7 @@ static int dp_parse_link_training_params(struct mdss_dp_drv_pdata *ep)
|
|||
bp = rp->data;
|
||||
data = *bp++;
|
||||
|
||||
if (!dp_is_link_rate_valid(data)) {
|
||||
if (!mdss_dp_aux_is_link_rate_valid(data)) {
|
||||
pr_err("invalid link rate = 0x%x\n", data);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
|
@ -1108,7 +1109,7 @@ static int dp_parse_link_training_params(struct mdss_dp_drv_pdata *ep)
|
|||
data = *bp++;
|
||||
data &= 0x1F;
|
||||
|
||||
if (!dp_is_lane_count_valid(data)) {
|
||||
if (!mdss_dp_aux_is_lane_count_valid(data)) {
|
||||
pr_err("invalid lane count = 0x%x\n", data);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
|
@ -1156,6 +1157,53 @@ static void dp_sink_parse_sink_count(struct mdss_dp_drv_pdata *ep)
|
|||
ep->sink_count.count, ep->sink_count.cp_ready);
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_parse_phy_test_params() - parses the phy test parameters
|
||||
* @ep: Display Port Driver data
|
||||
*
|
||||
* Parses the DPCD (Byte 0x248) for the DP PHY test pattern that is being
|
||||
* requested.
|
||||
*/
|
||||
static int dp_parse_phy_test_params(struct mdss_dp_drv_pdata *ep)
|
||||
{
|
||||
char *bp;
|
||||
char data;
|
||||
struct edp_buf *rp;
|
||||
int rlen;
|
||||
int const param_len = 0x1;
|
||||
int const phy_test_pattern_addr = 0x248;
|
||||
int const dpcd_version_1_2 = 0x12;
|
||||
int ret = 0;
|
||||
|
||||
rlen = dp_aux_read_buf(ep, phy_test_pattern_addr, param_len, 0);
|
||||
if (rlen < param_len) {
|
||||
pr_err("failed to read phy test pattern\n");
|
||||
ret = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
rp = &ep->rxp;
|
||||
bp = rp->data;
|
||||
data = *bp++;
|
||||
|
||||
if (ep->dpcd.major == dpcd_version_1_2)
|
||||
data = data & 0x7;
|
||||
else
|
||||
data = data & 0x3;
|
||||
|
||||
ep->test_data.phy_test_pattern_sel = data;
|
||||
|
||||
pr_debug("phy_test_pattern_sel = %s\n",
|
||||
mdss_dp_get_phy_test_pattern(data));
|
||||
|
||||
if (!mdss_dp_is_phy_test_pattern_supported(data))
|
||||
ret = -EINVAL;
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* dp_is_test_supported() - checks if test requested by sink is supported
|
||||
* @test_requested: test requested by the sink
|
||||
|
@ -1165,7 +1213,8 @@ static void dp_sink_parse_sink_count(struct mdss_dp_drv_pdata *ep)
|
|||
static bool dp_is_test_supported(u32 test_requested)
|
||||
{
|
||||
return (test_requested == TEST_LINK_TRAINING) ||
|
||||
(test_requested == TEST_EDID_READ);
|
||||
(test_requested == TEST_EDID_READ) ||
|
||||
(test_requested == PHY_TEST_PATTERN);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1229,8 +1278,19 @@ static void dp_sink_parse_test_request(struct mdss_dp_drv_pdata *ep)
|
|||
pr_debug("%s requested\n", mdss_dp_get_test_name(data));
|
||||
ep->test_data.test_requested = data;
|
||||
|
||||
if (ep->test_data.test_requested == TEST_LINK_TRAINING)
|
||||
switch (ep->test_data.test_requested) {
|
||||
case PHY_TEST_PATTERN:
|
||||
ret = dp_parse_phy_test_params(ep);
|
||||
if (ret)
|
||||
break;
|
||||
case TEST_LINK_TRAINING:
|
||||
ret = dp_parse_link_training_params(ep);
|
||||
break;
|
||||
default:
|
||||
pr_debug("test 0x%x not supported\n",
|
||||
ep->test_data.test_requested);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a TEST_ACK if all test parameters are valid, otherwise send
|
||||
|
@ -1453,7 +1513,8 @@ char vm_voltage_swing[4][4] = {
|
|||
{0x1E, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */
|
||||
};
|
||||
|
||||
static void dp_voltage_pre_emphasise_set(struct mdss_dp_drv_pdata *dp)
|
||||
static void dp_aux_set_voltage_and_pre_emphasis_lvl(
|
||||
struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
u32 value0 = 0;
|
||||
u32 value1 = 0;
|
||||
|
@ -1488,6 +1549,38 @@ static void dp_voltage_pre_emphasise_set(struct mdss_dp_drv_pdata *dp)
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_aux_update_voltage_and_pre_emphasis_lvl() - updates DP PHY settings
|
||||
* @ep: Display Port Driver data
|
||||
*
|
||||
* Updates the DP PHY with the requested voltage swing and pre-emphasis
|
||||
* levels if they are different from the current settings.
|
||||
*/
|
||||
void mdss_dp_aux_update_voltage_and_pre_emphasis_lvl(
|
||||
struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
int const num_bytes = 6;
|
||||
struct dpcd_link_status *status = &dp->link_status;
|
||||
|
||||
/* Read link status for updated voltage and pre-emphasis levels. */
|
||||
mdss_dp_aux_link_status_read(dp, num_bytes);
|
||||
|
||||
pr_info("Current: v_level = %d, p_level = %d\n",
|
||||
dp->v_level, dp->p_level);
|
||||
pr_info("Requested: v_level = %d, p_level = %d\n",
|
||||
status->req_voltage_swing[0],
|
||||
status->req_pre_emphasis[0]);
|
||||
|
||||
if ((status->req_voltage_swing[0] != dp->v_level) ||
|
||||
(status->req_pre_emphasis[0] != dp->p_level)) {
|
||||
dp->v_level = status->req_voltage_swing[0];
|
||||
dp->p_level = status->req_pre_emphasis[0];
|
||||
|
||||
dp_aux_set_voltage_and_pre_emphasis_lvl(dp);
|
||||
}
|
||||
|
||||
pr_debug("end\n");
|
||||
}
|
||||
static int dp_start_link_train_1(struct mdss_dp_drv_pdata *ep)
|
||||
{
|
||||
int tries, old_v_level;
|
||||
|
@ -1500,7 +1593,7 @@ static int dp_start_link_train_1(struct mdss_dp_drv_pdata *ep)
|
|||
dp_host_train_set(ep, 0x01); /* train_1 */
|
||||
dp_cap_lane_rate_set(ep);
|
||||
dp_train_pattern_set_write(ep, 0x21); /* train_1 */
|
||||
dp_voltage_pre_emphasise_set(ep);
|
||||
dp_aux_set_voltage_and_pre_emphasis_lvl(ep);
|
||||
|
||||
tries = 0;
|
||||
old_v_level = ep->v_level;
|
||||
|
@ -1508,7 +1601,7 @@ static int dp_start_link_train_1(struct mdss_dp_drv_pdata *ep)
|
|||
usleep_time = ep->dpcd.training_read_interval;
|
||||
usleep_range(usleep_time, usleep_time);
|
||||
|
||||
dp_link_status_read(ep, 6);
|
||||
mdss_dp_aux_link_status_read(ep, 6);
|
||||
if (mdss_dp_aux_clock_recovery_done(ep)) {
|
||||
ret = 0;
|
||||
break;
|
||||
|
@ -1531,7 +1624,7 @@ static int dp_start_link_train_1(struct mdss_dp_drv_pdata *ep)
|
|||
}
|
||||
|
||||
dp_sink_train_set_adjust(ep);
|
||||
dp_voltage_pre_emphasise_set(ep);
|
||||
dp_aux_set_voltage_and_pre_emphasis_lvl(ep);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -1555,13 +1648,13 @@ static int dp_start_link_train_2(struct mdss_dp_drv_pdata *ep)
|
|||
dp_train_pattern_set_write(ep, pattern | 0x20);/* train_2 */
|
||||
|
||||
do {
|
||||
dp_voltage_pre_emphasise_set(ep);
|
||||
dp_aux_set_voltage_and_pre_emphasis_lvl(ep);
|
||||
dp_host_train_set(ep, pattern);
|
||||
|
||||
usleep_time = ep->dpcd.training_read_interval;
|
||||
usleep_range(usleep_time, usleep_time);
|
||||
|
||||
dp_link_status_read(ep, 6);
|
||||
mdss_dp_aux_link_status_read(ep, 6);
|
||||
|
||||
if (mdss_dp_aux_channel_eq_done(ep)) {
|
||||
ret = 0;
|
||||
|
@ -1698,7 +1791,7 @@ void mdss_dp_aux_parse_sink_status_field(struct mdss_dp_drv_pdata *ep)
|
|||
{
|
||||
dp_sink_parse_sink_count(ep);
|
||||
dp_sink_parse_test_request(ep);
|
||||
dp_link_status_read(ep, 6);
|
||||
mdss_dp_aux_link_status_read(ep, 6);
|
||||
}
|
||||
|
||||
int mdss_dp_dpcd_status_read(struct mdss_dp_drv_pdata *ep)
|
||||
|
@ -1706,7 +1799,7 @@ int mdss_dp_dpcd_status_read(struct mdss_dp_drv_pdata *ep)
|
|||
struct dpcd_link_status *sp;
|
||||
int ret = 0; /* not sync */
|
||||
|
||||
ret = dp_link_status_read(ep, 6);
|
||||
ret = mdss_dp_aux_link_status_read(ep, 6);
|
||||
|
||||
if (ret) {
|
||||
sp = &ep->link_status;
|
||||
|
|
|
@ -892,3 +892,87 @@ void mdss_dp_audio_enable(struct dss_io_data *ctrl_io, bool enable)
|
|||
|
||||
writel_relaxed(audio_ctrl, ctrl_io->base + MMSS_DP_AUDIO_CFG);
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_phy_send_test_pattern() - sends the requested PHY test pattern
|
||||
* @ep: Display Port Driver data
|
||||
*
|
||||
* Updates the DP controller state and sends the requested PHY test pattern
|
||||
* to the sink.
|
||||
*/
|
||||
void mdss_dp_phy_send_test_pattern(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
struct dss_io_data *io = &dp->ctrl_io;
|
||||
u32 phy_test_pattern_sel = dp->test_data.phy_test_pattern_sel;
|
||||
u32 value = 0x0;
|
||||
|
||||
if (!mdss_dp_is_phy_test_pattern_supported(phy_test_pattern_sel)) {
|
||||
pr_err("test pattern 0x%x not supported\n",
|
||||
phy_test_pattern_sel);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disable mainlink */
|
||||
writel_relaxed(0x0, io->base + DP_MAINLINK_CTRL);
|
||||
|
||||
/* Reset mainlink */
|
||||
mdss_dp_mainlink_reset(io);
|
||||
|
||||
/* Enable mainlink */
|
||||
writel_relaxed(0x0, io->base + DP_MAINLINK_CTRL);
|
||||
|
||||
/* Initialize DP state control */
|
||||
mdss_dp_state_ctrl(io, 0x00);
|
||||
|
||||
pr_debug("phy_test_pattern_sel = %s\n",
|
||||
mdss_dp_get_phy_test_pattern(phy_test_pattern_sel));
|
||||
|
||||
switch (phy_test_pattern_sel) {
|
||||
case PHY_TEST_PATTERN_D10_2_NO_SCRAMBLING:
|
||||
mdss_dp_state_ctrl(io, BIT(0));
|
||||
break;
|
||||
case PHY_TEST_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT:
|
||||
value = readl_relaxed(io->base +
|
||||
DP_HBR2_COMPLIANCE_SCRAMBLER_RESET);
|
||||
value &= ~(1 << 16);
|
||||
writel_relaxed(value, io->base +
|
||||
DP_HBR2_COMPLIANCE_SCRAMBLER_RESET);
|
||||
value |= 0xFC;
|
||||
writel_relaxed(value, io->base +
|
||||
DP_HBR2_COMPLIANCE_SCRAMBLER_RESET);
|
||||
writel_relaxed(0x2, io->base + DP_MAINLINK_LEVELS);
|
||||
mdss_dp_state_ctrl(io, BIT(4));
|
||||
break;
|
||||
case PHY_TEST_PATTERN_PRBS7:
|
||||
mdss_dp_state_ctrl(io, BIT(5));
|
||||
break;
|
||||
case PHY_TEST_PATTERN_80_BIT_CUSTOM_PATTERN:
|
||||
mdss_dp_state_ctrl(io, BIT(6));
|
||||
/* 00111110000011111000001111100000 */
|
||||
writel_relaxed(0x3E0F83E0, io->base +
|
||||
DP_TEST_80BIT_CUSTOM_PATTERN_REG0);
|
||||
/* 00001111100000111110000011111000 */
|
||||
writel_relaxed(0x0F83E0F8, io->base +
|
||||
DP_TEST_80BIT_CUSTOM_PATTERN_REG1);
|
||||
/* 1111100000111110 */
|
||||
writel_relaxed(0x0000F83E, io->base +
|
||||
DP_TEST_80BIT_CUSTOM_PATTERN_REG2);
|
||||
break;
|
||||
case PHY_TEST_PATTERN_HBR2_CTS_EYE_PATTERN:
|
||||
value = readl_relaxed(io->base +
|
||||
DP_HBR2_COMPLIANCE_SCRAMBLER_RESET);
|
||||
value |= BIT(16);
|
||||
writel_relaxed(value, io->base +
|
||||
DP_HBR2_COMPLIANCE_SCRAMBLER_RESET);
|
||||
value |= 0xFC;
|
||||
writel_relaxed(value, io->base +
|
||||
DP_HBR2_COMPLIANCE_SCRAMBLER_RESET);
|
||||
writel_relaxed(0x2, io->base + DP_MAINLINK_LEVELS);
|
||||
mdss_dp_state_ctrl(io, BIT(4));
|
||||
break;
|
||||
default:
|
||||
pr_debug("No valid test pattern requested: 0x%x\n",
|
||||
phy_test_pattern_sel);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,11 @@
|
|||
#define DP_MAINLINK_LEVELS (0x00000444)
|
||||
#define DP_TU (0x0000044C)
|
||||
|
||||
#define DP_HBR2_COMPLIANCE_SCRAMBLER_RESET (0x00000454)
|
||||
#define DP_TEST_80BIT_CUSTOM_PATTERN_REG0 (0x000004C0)
|
||||
#define DP_TEST_80BIT_CUSTOM_PATTERN_REG1 (0x000004C4)
|
||||
#define DP_TEST_80BIT_CUSTOM_PATTERN_REG2 (0x000004C8)
|
||||
|
||||
#define MMSS_DP_AUDIO_TIMING_GEN (0x00000480)
|
||||
#define MMSS_DP_AUDIO_TIMING_RBR_32 (0x00000484)
|
||||
#define MMSS_DP_AUDIO_TIMING_HBR_32 (0x00000488)
|
||||
|
@ -315,5 +320,6 @@ void mdss_dp_audio_set_sample_rate(struct dss_io_data *ctrl_io,
|
|||
void mdss_dp_set_safe_to_exit_level(struct dss_io_data *ctrl_io,
|
||||
uint32_t lane_cnt);
|
||||
int mdss_dp_aux_read_rx_status(struct mdss_dp_drv_pdata *dp, u8 *rx_status);
|
||||
void mdss_dp_phy_send_test_pattern(struct mdss_dp_drv_pdata *dp);
|
||||
|
||||
#endif /* __DP_UTIL_H__ */
|
||||
|
|
Loading…
Add table
Reference in a new issue