msm: mdss: dp: add support for automated video pattern tests
Add support for parsing parameters in the automated CTS mode when the test type is set to TEST_VIDEO_PATTERN. The parameters parsed are the color bit depth, colorimetry and the test pattern type. Configure the source accordingly and transmit the requested video pattern. CRs-Fixed: 1109812 Change-Id: I552a50e86dc299b4cf7955992ad82dee19f35cbc Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
This commit is contained in:
parent
9be29e6aaa
commit
b8aa537775
5 changed files with 742 additions and 124 deletions
|
@ -60,6 +60,48 @@ static inline void mdss_dp_link_retraining(struct mdss_dp_drv_pdata *dp);
|
|||
static void mdss_dp_handle_attention(struct mdss_dp_drv_pdata *dp_drv);
|
||||
static void dp_send_events(struct mdss_dp_drv_pdata *dp, u32 events);
|
||||
|
||||
static inline void mdss_dp_reset_test_data(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
dp->test_data = (const struct dpcd_test_request){ 0 };
|
||||
dp->test_data.test_bit_depth = DP_TEST_BIT_DEPTH_UNKNOWN;
|
||||
}
|
||||
|
||||
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_downstream_port_status_changed(
|
||||
struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
return dp->link_status.downstream_port_status_changed;
|
||||
}
|
||||
|
||||
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 inline bool mdss_dp_is_video_pattern_requested(
|
||||
struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
return (dp->test_data.test_requested == TEST_VIDEO_PATTERN);
|
||||
}
|
||||
|
||||
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) ||
|
||||
mdss_dp_is_phy_test_pattern_requested(dp)) &&
|
||||
dp->alt_mode.dp_status.hpd_irq;
|
||||
}
|
||||
|
||||
static void mdss_dp_put_dt_clk_data(struct device *dev,
|
||||
struct dss_module_power *module_power)
|
||||
{
|
||||
|
@ -798,9 +840,11 @@ void mdss_dp_config_ctrl(struct mdss_dp_drv_pdata *dp)
|
|||
{
|
||||
struct dpcd_cap *cap;
|
||||
struct display_timing_desc *timing;
|
||||
struct mdss_panel_info *pinfo;
|
||||
u32 data = 0;
|
||||
|
||||
timing = &dp->edid.timing[0];
|
||||
pinfo = &dp->panel_data.panel_info;
|
||||
|
||||
cap = &dp->dpcd;
|
||||
|
||||
|
@ -823,8 +867,8 @@ void mdss_dp_config_ctrl(struct mdss_dp_drv_pdata *dp)
|
|||
if (cap->scrambler_reset)
|
||||
data |= (1 << 10);
|
||||
|
||||
if (dp->edid.color_depth != 6)
|
||||
data |= 0x100; /* Default: 8 bits */
|
||||
/* Bits per components */
|
||||
data |= (mdss_dp_bpp_to_test_bit_depth(pinfo->bpp) << 8);
|
||||
|
||||
/* Num of Lanes */
|
||||
data |= ((dp->lane_cnt - 1) << 4);
|
||||
|
@ -983,6 +1027,55 @@ end:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static u32 mdss_dp_get_bpp(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
u32 bpp;
|
||||
u32 bit_depth;
|
||||
|
||||
/*
|
||||
* Set bpp value based on whether a test video pattern is requested.
|
||||
* For test pattern, the test data has the bit depth per color
|
||||
* component. Otherwise, set it based on EDID.
|
||||
*/
|
||||
if (mdss_dp_is_video_pattern_requested(dp))
|
||||
bit_depth = dp->test_data.test_bit_depth;
|
||||
else
|
||||
bit_depth = dp->edid.color_depth;
|
||||
|
||||
if (!mdss_dp_is_test_bit_depth_valid(bit_depth)) {
|
||||
pr_debug("invalid bit_depth=%d. fall back to default\n",
|
||||
bit_depth);
|
||||
bit_depth = DP_TEST_BIT_DEPTH_8; /* default to 24bpp */
|
||||
}
|
||||
|
||||
bpp = mdss_dp_test_bit_depth_to_bpp(bit_depth);
|
||||
return bpp;
|
||||
}
|
||||
|
||||
static u32 mdss_dp_get_colorimetry_config(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
u32 cc;
|
||||
enum dynamic_range dr;
|
||||
|
||||
/* unless a video pattern CTS test is ongoing, use CEA_VESA */
|
||||
if (mdss_dp_is_video_pattern_requested(dp))
|
||||
dr = dp->test_data.test_dyn_range;
|
||||
else
|
||||
dr = DP_DYNAMIC_RANGE_RGB_VESA;
|
||||
|
||||
/* Only RGB_VESA nd RGB_CEA supported for now */
|
||||
switch (dr) {
|
||||
case DP_DYNAMIC_RANGE_RGB_CEA:
|
||||
cc = BIT(3);
|
||||
break;
|
||||
case DP_DYNAMIC_RANGE_RGB_VESA:
|
||||
default:
|
||||
cc = 0;
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv, u32 vic)
|
||||
{
|
||||
struct mdss_panel_info *pinfo;
|
||||
|
@ -1023,7 +1116,6 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv, u32 vic)
|
|||
pinfo->type = DP_PANEL;
|
||||
pinfo->pdest = DISPLAY_4;
|
||||
pinfo->wait_cycle = 0;
|
||||
pinfo->bpp = 24;
|
||||
pinfo->fb_num = 1;
|
||||
|
||||
pinfo->lcdc.border_clr = 0; /* blk */
|
||||
|
@ -1031,8 +1123,8 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv, u32 vic)
|
|||
pinfo->lcdc.hsync_skew = 0;
|
||||
pinfo->is_pluggable = true;
|
||||
|
||||
dp_drv->bpp = pinfo->bpp;
|
||||
|
||||
pinfo->bpp = mdss_dp_get_bpp(dp_drv);
|
||||
pr_debug("bpp=%d\n", pinfo->bpp);
|
||||
pr_debug("update res. vic= %d, pclk_rate = %llu\n",
|
||||
dp_drv->vic, pinfo->clk_rate);
|
||||
|
||||
|
@ -1157,6 +1249,9 @@ static void mdss_dp_configure_source_params(struct mdss_dp_drv_pdata *dp,
|
|||
mdss_dp_fill_link_cfg(dp);
|
||||
mdss_dp_mainlink_ctrl(&dp->ctrl_io, true);
|
||||
mdss_dp_config_ctrl(dp);
|
||||
mdss_dp_config_misc(dp,
|
||||
mdss_dp_bpp_to_test_bit_depth(mdss_dp_get_bpp(dp)),
|
||||
mdss_dp_get_colorimetry_config(dp));
|
||||
mdss_dp_sw_config_msa(&dp->ctrl_io, dp->link_rate, &dp->dp_cc_io);
|
||||
mdss_dp_timing_cfg(&dp->ctrl_io, &dp->panel_data.panel_info);
|
||||
}
|
||||
|
@ -1347,44 +1442,14 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
|
|||
dp_drv = container_of(pdata, struct mdss_dp_drv_pdata,
|
||||
panel_data);
|
||||
|
||||
if (dp_drv->power_on) {
|
||||
pr_debug("Link already setup, return\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mdss_dp_on_hpd(dp_drv);
|
||||
}
|
||||
|
||||
static inline void mdss_dp_reset_test_data(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
dp->test_data = (const struct dpcd_test_request){ 0 };
|
||||
}
|
||||
|
||||
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_downstream_port_status_changed(
|
||||
struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
return dp->link_status.downstream_port_status_changed;
|
||||
}
|
||||
|
||||
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 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) ||
|
||||
mdss_dp_is_phy_test_pattern_requested(dp)) &&
|
||||
dp->alt_mode.dp_status.hpd_irq;
|
||||
}
|
||||
|
||||
static int mdss_dp_off_irq(struct mdss_dp_drv_pdata *dp_drv)
|
||||
{
|
||||
if (!dp_drv->power_on) {
|
||||
|
@ -1504,11 +1569,6 @@ end:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp, bool enable)
|
||||
{
|
||||
return mdss_dp_send_cable_notification(dp, enable);
|
||||
}
|
||||
|
||||
static void mdss_dp_set_default_resolution(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
hdmi_edid_set_video_resolution(dp->panel_data.panel_info.edid_data,
|
||||
|
@ -1617,6 +1677,93 @@ vreg_error:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_notify_clients() - notifies DP clients of cable connection
|
||||
* @dp: Display Port Driver data
|
||||
* @status: HPD notification status requested
|
||||
*
|
||||
* This function will send a notification to display/audio clients of change
|
||||
* in DP connection status.
|
||||
*/
|
||||
static int mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp,
|
||||
enum notification_status status)
|
||||
{
|
||||
const int irq_comp_timeout = HZ * 2;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&dp->pd_msg_mutex);
|
||||
if (status == dp->hpd_notification_status) {
|
||||
pr_debug("No change in status %s --> %s\n",
|
||||
mdss_dp_notification_status_to_string(status),
|
||||
mdss_dp_notification_status_to_string(
|
||||
dp->hpd_notification_status));
|
||||
goto end;
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case NOTIFY_CONNECT_IRQ_HPD:
|
||||
if (dp->hpd_notification_status != NOTIFY_DISCONNECT_IRQ_HPD)
|
||||
goto invalid_request;
|
||||
/* Follow the same programming as for NOTIFY_CONNECT */
|
||||
mdss_dp_host_init(&dp->panel_data);
|
||||
mdss_dp_send_cable_notification(dp, true);
|
||||
break;
|
||||
case NOTIFY_CONNECT:
|
||||
if ((dp->hpd_notification_status == NOTIFY_CONNECT_IRQ_HPD) ||
|
||||
(dp->hpd_notification_status ==
|
||||
NOTIFY_DISCONNECT_IRQ_HPD))
|
||||
goto invalid_request;
|
||||
mdss_dp_host_init(&dp->panel_data);
|
||||
mdss_dp_send_cable_notification(dp, true);
|
||||
break;
|
||||
case NOTIFY_DISCONNECT:
|
||||
mdss_dp_send_cable_notification(dp, false);
|
||||
break;
|
||||
case NOTIFY_DISCONNECT_IRQ_HPD:
|
||||
if (dp->hpd_notification_status == NOTIFY_DISCONNECT)
|
||||
goto invalid_request;
|
||||
|
||||
mdss_dp_send_cable_notification(dp, false);
|
||||
if (!IS_ERR_VALUE(ret) && ret) {
|
||||
reinit_completion(&dp->irq_comp);
|
||||
ret = wait_for_completion_timeout(&dp->irq_comp,
|
||||
irq_comp_timeout);
|
||||
if (ret <= 0) {
|
||||
pr_warn("irq_comp timed out\n");
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pr_err("Invalid notification status = %d\n", status);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
goto end;
|
||||
|
||||
invalid_request:
|
||||
pr_err("Invalid request %s --> %s\n",
|
||||
mdss_dp_notification_status_to_string(
|
||||
dp->hpd_notification_status),
|
||||
mdss_dp_notification_status_to_string(status));
|
||||
ret = -EINVAL;
|
||||
|
||||
end:
|
||||
if (!ret) {
|
||||
pr_debug("Successfully sent notification %s --> %s\n",
|
||||
mdss_dp_notification_status_to_string(
|
||||
dp->hpd_notification_status),
|
||||
mdss_dp_notification_status_to_string(status));
|
||||
dp->hpd_notification_status = status;
|
||||
}
|
||||
|
||||
mutex_unlock(&dp->pd_msg_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mdss_dp_process_hpd_high(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
int ret;
|
||||
|
@ -1643,7 +1790,7 @@ static int mdss_dp_process_hpd_high(struct mdss_dp_drv_pdata *dp)
|
|||
dp->sink_info_read = true;
|
||||
end:
|
||||
mdss_dp_update_cable_status(dp, true);
|
||||
mdss_dp_notify_clients(dp, true);
|
||||
mdss_dp_notify_clients(dp, NOTIFY_CONNECT);
|
||||
|
||||
return ret;
|
||||
|
||||
|
@ -1885,7 +2032,7 @@ static ssize_t mdss_dp_sysfs_rda_s3d_mode(struct device *dev,
|
|||
|
||||
static bool mdss_dp_is_test_ongoing(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
return dp->hpd_irq_clients_notified;
|
||||
return (dp->hpd_notification_status == NOTIFY_DISCONNECT_IRQ_HPD);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1927,7 +2074,7 @@ static int mdss_dp_psm_config(struct mdss_dp_drv_pdata *dp, bool enable)
|
|||
mdss_dp_mainlink_push_idle(&dp->panel_data);
|
||||
mdss_dp_off_irq(dp);
|
||||
} else {
|
||||
mdss_dp_notify_clients(dp, false);
|
||||
mdss_dp_notify_clients(dp, NOTIFY_DISCONNECT);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
|
@ -1942,7 +2089,7 @@ static int mdss_dp_psm_config(struct mdss_dp_drv_pdata *dp, bool enable)
|
|||
mdss_dp_link_retraining(dp);
|
||||
} else {
|
||||
mdss_dp_host_init(&dp->panel_data);
|
||||
mdss_dp_notify_clients(dp, true);
|
||||
mdss_dp_notify_clients(dp, NOTIFY_CONNECT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2032,7 +2179,7 @@ static ssize_t mdss_dp_wta_hpd(struct device *dev,
|
|||
dp_send_events(dp, EV_USBPD_DISCOVER_MODES);
|
||||
}
|
||||
} else if (!dp->hpd && dp->power_on) {
|
||||
mdss_dp_notify_clients(dp, false);
|
||||
mdss_dp_notify_clients(dp, NOTIFY_DISCONNECT);
|
||||
}
|
||||
end:
|
||||
return ret;
|
||||
|
@ -2577,7 +2724,7 @@ static void usbpd_disconnect_callback(struct usbpd_svid_handler *hdlr)
|
|||
pr_debug("cable disconnected\n");
|
||||
mdss_dp_update_cable_status(dp_drv, false);
|
||||
dp_drv->alt_mode.current_state = UNKNOWN_STATE;
|
||||
mdss_dp_notify_clients(dp_drv, false);
|
||||
mdss_dp_notify_clients(dp_drv, NOTIFY_DISCONNECT);
|
||||
}
|
||||
|
||||
static int mdss_dp_validate_callback(u8 cmd,
|
||||
|
@ -2633,41 +2780,6 @@ static inline void mdss_dp_send_test_response(struct mdss_dp_drv_pdata *dp)
|
|||
mutex_unlock(&dp->train_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_hpd_irq_notify_clients() - notifies DP clients of HPD IRQ tear down
|
||||
* @dp: Display Port Driver data
|
||||
*
|
||||
* This function will send a notification to display/audio clients of DP tear
|
||||
* down during an HPD IRQ. This happens only if HPD IRQ is toggled,
|
||||
* in which case the user space proceeds with shutdown of DP driver, including
|
||||
* mainlink disable, and pushing the controller into idle state.
|
||||
*/
|
||||
static int mdss_dp_hpd_irq_notify_clients(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
const int irq_comp_timeout = HZ * 2;
|
||||
int ret = 0;
|
||||
|
||||
if (dp->hpd_irq_toggled) {
|
||||
dp->hpd_irq_clients_notified = true;
|
||||
|
||||
ret = mdss_dp_notify_clients(dp, false);
|
||||
|
||||
if (!IS_ERR_VALUE(ret) && ret) {
|
||||
reinit_completion(&dp->irq_comp);
|
||||
ret = wait_for_completion_timeout(&dp->irq_comp,
|
||||
irq_comp_timeout);
|
||||
if (ret <= 0) {
|
||||
pr_warn("irq_comp timed out\n");
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_link_retraining() - initiates link retraining
|
||||
* @dp: Display Port Driver data
|
||||
|
@ -2678,7 +2790,7 @@ static int mdss_dp_hpd_irq_notify_clients(struct mdss_dp_drv_pdata *dp)
|
|||
*/
|
||||
static inline void mdss_dp_link_retraining(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
if (mdss_dp_hpd_irq_notify_clients(dp))
|
||||
if (mdss_dp_notify_clients(dp, NOTIFY_DISCONNECT_IRQ_HPD))
|
||||
return;
|
||||
|
||||
mdss_dp_on_irq(dp);
|
||||
|
@ -2813,6 +2925,41 @@ static int mdss_dp_process_downstream_port_status_change(
|
|||
return mdss_dp_edid_read(dp);
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_process_video_pattern_request() - process new video pattern request
|
||||
* @dp: Display Port Driver data
|
||||
*
|
||||
* This function will handle a new video pattern request that are initiated by
|
||||
* the sink. This is acheieved by first sending a disconnect notification to
|
||||
* the sink followed by a subsequent connect notification to the user modules,
|
||||
* where it is expected that the user modules would draw the required test
|
||||
* pattern.
|
||||
*/
|
||||
static int mdss_dp_process_video_pattern_request(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
if (!mdss_dp_is_video_pattern_requested(dp))
|
||||
return -EINVAL;
|
||||
|
||||
pr_info("%s: bit depth=%d(%d bpp) pattern=%s\n",
|
||||
mdss_dp_get_test_name(TEST_VIDEO_PATTERN),
|
||||
dp->test_data.test_bit_depth,
|
||||
mdss_dp_test_bit_depth_to_bpp(dp->test_data.test_bit_depth),
|
||||
mdss_dp_test_video_pattern_to_string(
|
||||
dp->test_data.test_video_pattern));
|
||||
|
||||
/* Send a disconnect notification */
|
||||
mdss_dp_notify_clients(dp, NOTIFY_DISCONNECT_IRQ_HPD);
|
||||
|
||||
mdss_dp_off_irq(dp);
|
||||
|
||||
/* Send a connect notification */
|
||||
mdss_dp_notify_clients(dp, NOTIFY_CONNECT_IRQ_HPD);
|
||||
|
||||
mdss_dp_send_test_response(dp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_process_hpd_irq_high() - handle HPD IRQ transition to HIGH
|
||||
* @dp: Display Port Driver data
|
||||
|
@ -2827,6 +2974,8 @@ static int mdss_dp_process_hpd_irq_high(struct mdss_dp_drv_pdata *dp)
|
|||
|
||||
dp->hpd_irq_on = true;
|
||||
|
||||
mdss_dp_reset_test_data(dp);
|
||||
|
||||
mdss_dp_aux_parse_sink_status_field(dp);
|
||||
|
||||
ret = mdss_dp_process_link_training_request(dp);
|
||||
|
@ -2844,10 +2993,14 @@ static int mdss_dp_process_hpd_irq_high(struct mdss_dp_drv_pdata *dp)
|
|||
ret = mdss_dp_process_phy_test_pattern_request(dp);
|
||||
if (!ret)
|
||||
goto exit;
|
||||
pr_debug("done\n");
|
||||
exit:
|
||||
mdss_dp_reset_test_data(dp);
|
||||
|
||||
ret = mdss_dp_process_video_pattern_request(dp);
|
||||
if (!ret)
|
||||
goto exit;
|
||||
|
||||
pr_debug("done\n");
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2860,17 +3013,21 @@ exit:
|
|||
*/
|
||||
static int mdss_dp_process_hpd_irq_low(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
if (!dp->hpd_irq_clients_notified)
|
||||
if (!dp->hpd_irq_on)
|
||||
return -EINVAL;
|
||||
|
||||
pr_debug("enter: HPD IRQ low\n");
|
||||
|
||||
dp->hpd_irq_on = false;
|
||||
dp->hpd_irq_clients_notified = false;
|
||||
if (dp->hpd_notification_status == NOTIFY_CONNECT_IRQ_HPD) {
|
||||
mdss_dp_notify_clients(dp, NOTIFY_DISCONNECT);
|
||||
} else {
|
||||
/* Clients already notified, so shudown interface directly */
|
||||
mdss_dp_update_cable_status(dp, false);
|
||||
mdss_dp_mainlink_push_idle(&dp->panel_data);
|
||||
mdss_dp_off_hpd(dp);
|
||||
}
|
||||
|
||||
mdss_dp_update_cable_status(dp, false);
|
||||
mdss_dp_mainlink_push_idle(&dp->panel_data);
|
||||
mdss_dp_off_hpd(dp);
|
||||
dp->hpd_irq_on = false;
|
||||
|
||||
mdss_dp_reset_test_data(dp);
|
||||
|
||||
|
@ -2977,7 +3134,7 @@ static void mdss_dp_process_attention(struct mdss_dp_drv_pdata *dp_drv)
|
|||
}
|
||||
|
||||
mdss_dp_update_cable_status(dp_drv, false);
|
||||
mdss_dp_notify_clients(dp_drv, false);
|
||||
mdss_dp_notify_clients(dp_drv, NOTIFY_DISCONNECT);
|
||||
pr_debug("Attention: Notified clients\n");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -269,6 +269,21 @@ struct dpcd_test_request {
|
|||
u32 test_link_rate;
|
||||
u32 test_lane_count;
|
||||
u32 phy_test_pattern_sel;
|
||||
u32 test_video_pattern;
|
||||
u32 test_bit_depth;
|
||||
u32 test_dyn_range;
|
||||
u32 test_h_total;
|
||||
u32 test_v_total;
|
||||
u32 test_h_start;
|
||||
u32 test_v_start;
|
||||
u32 test_hsync_pol;
|
||||
u32 test_hsync_width;
|
||||
u32 test_vsync_pol;
|
||||
u32 test_vsync_width;
|
||||
u32 test_h_width;
|
||||
u32 test_v_height;
|
||||
u32 test_rr_d;
|
||||
u32 test_rr_n;
|
||||
u32 response;
|
||||
};
|
||||
|
||||
|
@ -493,11 +508,10 @@ struct mdss_dp_drv_pdata {
|
|||
char tu_desired;
|
||||
char valid_boundary;
|
||||
char delay_start;
|
||||
u32 bpp;
|
||||
struct dp_statistic dp_stat;
|
||||
bool hpd_irq_on;
|
||||
bool hpd_irq_toggled;
|
||||
bool hpd_irq_clients_notified;
|
||||
u32 hpd_notification_status;
|
||||
|
||||
struct mdss_dp_event_data dp_event;
|
||||
struct task_struct *ev_thread;
|
||||
|
@ -623,6 +637,7 @@ static inline char *mdss_dp_get_test_response(u32 test_response)
|
|||
enum test_type {
|
||||
UNKNOWN_TEST = 0,
|
||||
TEST_LINK_TRAINING = BIT(0),
|
||||
TEST_VIDEO_PATTERN = BIT(1),
|
||||
PHY_TEST_PATTERN = BIT(3),
|
||||
TEST_EDID_READ = BIT(2),
|
||||
};
|
||||
|
@ -631,6 +646,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_VIDEO_PATTERN: return DP_ENUM_STR(TEST_VIDEO_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";
|
||||
|
@ -694,6 +710,222 @@ static inline char *mdss_dp_ev_event_to_string(int event)
|
|||
}
|
||||
}
|
||||
|
||||
enum dynamic_range {
|
||||
DP_DYNAMIC_RANGE_RGB_VESA = 0x00,
|
||||
DP_DYNAMIC_RANGE_RGB_CEA = 0x01,
|
||||
DP_DYNAMIC_RANGE_UNKNOWN = 0xFFFFFFFF,
|
||||
};
|
||||
|
||||
static inline char *mdss_dp_dynamic_range_to_string(u32 dr)
|
||||
{
|
||||
switch (dr) {
|
||||
case DP_DYNAMIC_RANGE_RGB_VESA:
|
||||
return DP_ENUM_STR(DP_DYNAMIC_RANGE_RGB_VESA);
|
||||
case DP_DYNAMIC_RANGE_RGB_CEA:
|
||||
return DP_ENUM_STR(DP_DYNAMIC_RANGE_RGB_CEA);
|
||||
case DP_DYNAMIC_RANGE_UNKNOWN:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_is_dynamic_range_valid() - validates the dynamic range
|
||||
* @bit_depth: the dynamic range value to be checked
|
||||
*
|
||||
* Returns true if the dynamic range value is supported.
|
||||
*/
|
||||
static inline bool mdss_dp_is_dynamic_range_valid(u32 dr)
|
||||
{
|
||||
switch (dr) {
|
||||
case DP_DYNAMIC_RANGE_RGB_VESA:
|
||||
case DP_DYNAMIC_RANGE_RGB_CEA:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
enum test_bit_depth {
|
||||
DP_TEST_BIT_DEPTH_6 = 0x00,
|
||||
DP_TEST_BIT_DEPTH_8 = 0x01,
|
||||
DP_TEST_BIT_DEPTH_10 = 0x02,
|
||||
DP_TEST_BIT_DEPTH_UNKNOWN = 0xFFFFFFFF,
|
||||
};
|
||||
|
||||
static inline char *mdss_dp_test_bit_depth_to_string(u32 tbd)
|
||||
{
|
||||
switch (tbd) {
|
||||
case DP_TEST_BIT_DEPTH_6:
|
||||
return DP_ENUM_STR(DP_TEST_BIT_DEPTH_6);
|
||||
case DP_TEST_BIT_DEPTH_8:
|
||||
return DP_ENUM_STR(DP_TEST_BIT_DEPTH_8);
|
||||
case DP_TEST_BIT_DEPTH_10:
|
||||
return DP_ENUM_STR(DP_TEST_BIT_DEPTH_10);
|
||||
case DP_TEST_BIT_DEPTH_UNKNOWN:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_is_test_bit_depth_valid() - validates the bit depth requested
|
||||
* @bit_depth: bit depth requested by the sink
|
||||
*
|
||||
* Returns true if the requested bit depth is supported.
|
||||
*/
|
||||
static inline bool mdss_dp_is_test_bit_depth_valid(u32 tbd)
|
||||
{
|
||||
/* DP_TEST_VIDEO_PATTERN_NONE is treated as invalid */
|
||||
switch (tbd) {
|
||||
case DP_TEST_BIT_DEPTH_6:
|
||||
case DP_TEST_BIT_DEPTH_8:
|
||||
case DP_TEST_BIT_DEPTH_10:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_test_bit_depth_to_bpp() - convert test bit depth to bpp
|
||||
* @tbd: test bit depth
|
||||
*
|
||||
* Returns the bits per pixel (bpp) to be used corresponding to the
|
||||
* git bit depth value. This function assumes that bit depth has
|
||||
* already been validated.
|
||||
*/
|
||||
static inline u32 mdss_dp_test_bit_depth_to_bpp(enum test_bit_depth tbd)
|
||||
{
|
||||
u32 bpp;
|
||||
|
||||
/*
|
||||
* Few simplistic rules and assumptions made here:
|
||||
* 1. Bit depth is per color component
|
||||
* 2. If bit depth is unknown return 0
|
||||
* 3. Assume 3 color components
|
||||
*/
|
||||
switch (tbd) {
|
||||
case DP_TEST_BIT_DEPTH_6:
|
||||
bpp = 18;
|
||||
break;
|
||||
case DP_TEST_BIT_DEPTH_8:
|
||||
bpp = 24;
|
||||
break;
|
||||
case DP_TEST_BIT_DEPTH_10:
|
||||
bpp = 30;
|
||||
break;
|
||||
case DP_TEST_BIT_DEPTH_UNKNOWN:
|
||||
default:
|
||||
bpp = 0;
|
||||
}
|
||||
|
||||
return bpp;
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_bpp_to_test_bit_depth() - convert bpp to test bit depth
|
||||
* &bpp: the bpp to be converted
|
||||
*
|
||||
* Return the bit depth per color component to used with the video
|
||||
* test pattern data based on the bits per pixel value.
|
||||
*/
|
||||
static inline u32 mdss_dp_bpp_to_test_bit_depth(u32 bpp)
|
||||
{
|
||||
enum test_bit_depth tbd;
|
||||
|
||||
/*
|
||||
* Few simplistic rules and assumptions made here:
|
||||
* 1. Test bit depth is bit depth per color component
|
||||
* 2. Assume 3 color components
|
||||
*/
|
||||
switch (bpp) {
|
||||
case 18:
|
||||
tbd = DP_TEST_BIT_DEPTH_6;
|
||||
break;
|
||||
case 24:
|
||||
tbd = DP_TEST_BIT_DEPTH_8;
|
||||
break;
|
||||
case 30:
|
||||
tbd = DP_TEST_BIT_DEPTH_10;
|
||||
break;
|
||||
default:
|
||||
tbd = DP_TEST_BIT_DEPTH_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
return tbd;
|
||||
}
|
||||
|
||||
enum test_video_pattern {
|
||||
DP_TEST_VIDEO_PATTERN_NONE = 0x00,
|
||||
DP_TEST_VIDEO_PATTERN_COLOR_RAMPS = 0x01,
|
||||
DP_TEST_VIDEO_PATTERN_BW_VERT_LINES = 0x02,
|
||||
DP_TEST_VIDEO_PATTERN_COLOR_SQUARE = 0x03,
|
||||
};
|
||||
|
||||
static inline char *mdss_dp_test_video_pattern_to_string(u32 test_video_pattern)
|
||||
{
|
||||
switch (test_video_pattern) {
|
||||
case DP_TEST_VIDEO_PATTERN_NONE:
|
||||
return DP_ENUM_STR(DP_TEST_VIDEO_PATTERN_NONE);
|
||||
case DP_TEST_VIDEO_PATTERN_COLOR_RAMPS:
|
||||
return DP_ENUM_STR(DP_TEST_VIDEO_PATTERN_COLOR_RAMPS);
|
||||
case DP_TEST_VIDEO_PATTERN_BW_VERT_LINES:
|
||||
return DP_ENUM_STR(DP_TEST_VIDEO_PATTERN_BW_VERT_LINES);
|
||||
case DP_TEST_VIDEO_PATTERN_COLOR_SQUARE:
|
||||
return DP_ENUM_STR(DP_TEST_VIDEO_PATTERN_COLOR_SQUARE);
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_is_test_video_pattern_valid() - validates the video pattern
|
||||
* @pattern: video pattern requested by the sink
|
||||
*
|
||||
* Returns true if the requested video pattern is supported.
|
||||
*/
|
||||
static inline bool mdss_dp_is_test_video_pattern_valid(u32 pattern)
|
||||
{
|
||||
switch (pattern) {
|
||||
case DP_TEST_VIDEO_PATTERN_NONE:
|
||||
case DP_TEST_VIDEO_PATTERN_COLOR_RAMPS:
|
||||
case DP_TEST_VIDEO_PATTERN_BW_VERT_LINES:
|
||||
case DP_TEST_VIDEO_PATTERN_COLOR_SQUARE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
enum notification_status {
|
||||
NOTIFY_UNKNOWN,
|
||||
NOTIFY_CONNECT,
|
||||
NOTIFY_DISCONNECT,
|
||||
NOTIFY_CONNECT_IRQ_HPD,
|
||||
NOTIFY_DISCONNECT_IRQ_HPD,
|
||||
};
|
||||
|
||||
static inline char const *mdss_dp_notification_status_to_string(
|
||||
enum notification_status status)
|
||||
{
|
||||
switch (status) {
|
||||
case NOTIFY_UNKNOWN:
|
||||
return DP_ENUM_STR(NOTIFY_UNKNOWN);
|
||||
case NOTIFY_CONNECT:
|
||||
return DP_ENUM_STR(NOTIFY_CONNECT);
|
||||
case NOTIFY_DISCONNECT:
|
||||
return DP_ENUM_STR(NOTIFY_DISCONNECT);
|
||||
case NOTIFY_CONNECT_IRQ_HPD:
|
||||
return DP_ENUM_STR(NOTIFY_CONNECT_IRQ_HPD);
|
||||
case NOTIFY_DISCONNECT_IRQ_HPD:
|
||||
return DP_ENUM_STR(NOTIFY_DISCONNECT_IRQ_HPD);
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void mdss_dp_phy_initialize(struct mdss_dp_drv_pdata *dp);
|
||||
|
||||
void mdss_dp_dpcd_cap_read(struct mdss_dp_drv_pdata *dp);
|
||||
|
|
|
@ -466,10 +466,8 @@ void dp_extract_edid_video_support(struct edp_edid *edid, char *buf)
|
|||
edid->video_intf = *bp & 0x0f;
|
||||
/* 6, 8, 10, 12, 14 and 16 bit per component */
|
||||
edid->color_depth = ((*bp & 0x70) >> 4); /* color bit depth */
|
||||
if (edid->color_depth) {
|
||||
edid->color_depth *= 2;
|
||||
edid->color_depth += 4;
|
||||
}
|
||||
/* decrement to match with the test_bit_depth enum definition */
|
||||
edid->color_depth--;
|
||||
pr_debug("Digital Video intf=%d color_depth=%d\n",
|
||||
edid->video_intf, edid->color_depth);
|
||||
} else {
|
||||
|
@ -1258,6 +1256,243 @@ end:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int dp_parse_test_timing_params1(struct mdss_dp_drv_pdata *ep,
|
||||
int const addr, int const len, u32 *val)
|
||||
{
|
||||
char *bp;
|
||||
struct edp_buf *rp;
|
||||
int rlen;
|
||||
|
||||
if (len < 2)
|
||||
return -EINVAL;
|
||||
|
||||
/* Read the requested video test pattern (Byte 0x221). */
|
||||
rlen = dp_aux_read_buf(ep, addr, len, 0);
|
||||
if (rlen < len) {
|
||||
pr_err("failed to read 0x%x\n", addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
rp = &ep->rxp;
|
||||
bp = rp->data;
|
||||
|
||||
*val = bp[1] | (bp[0] << 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dp_parse_test_timing_params2(struct mdss_dp_drv_pdata *ep,
|
||||
int const addr, int const len, u32 *val1, u32 *val2)
|
||||
{
|
||||
char *bp;
|
||||
struct edp_buf *rp;
|
||||
int rlen;
|
||||
|
||||
if (len < 2)
|
||||
return -EINVAL;
|
||||
|
||||
/* Read the requested video test pattern (Byte 0x221). */
|
||||
rlen = dp_aux_read_buf(ep, addr, len, 0);
|
||||
if (rlen < len) {
|
||||
pr_err("failed to read 0x%x\n", addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
rp = &ep->rxp;
|
||||
bp = rp->data;
|
||||
|
||||
*val1 = (bp[0] & BIT(7)) >> 7;
|
||||
*val2 = bp[1] | ((bp[0] & 0x7F) << 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dp_parse_test_timing_params3(struct mdss_dp_drv_pdata *ep,
|
||||
int const addr, u32 *val)
|
||||
{
|
||||
char *bp;
|
||||
struct edp_buf *rp;
|
||||
int rlen;
|
||||
|
||||
/* Read the requested video test pattern (Byte 0x221). */
|
||||
rlen = dp_aux_read_buf(ep, addr, 1, 0);
|
||||
if (rlen < 1) {
|
||||
pr_err("failed to read 0x%x\n", addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
rp = &ep->rxp;
|
||||
bp = rp->data;
|
||||
*val = bp[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_parse_video_pattern_params() - parses video pattern parameters from DPCD
|
||||
* @ep: Display Port Driver data
|
||||
*
|
||||
* Returns 0 if it successfully parses the video test pattern and the test
|
||||
* bit depth requested by the sink and, and if the values parsed are valid.
|
||||
*/
|
||||
static int dp_parse_video_pattern_params(struct mdss_dp_drv_pdata *ep)
|
||||
{
|
||||
int ret = 0;
|
||||
char *bp;
|
||||
char data;
|
||||
struct edp_buf *rp;
|
||||
int rlen;
|
||||
u32 dyn_range;
|
||||
int const test_parameter_len = 0x1;
|
||||
int const test_video_pattern_addr = 0x221;
|
||||
int const test_misc_addr = 0x232;
|
||||
|
||||
/* Read the requested video test pattern (Byte 0x221). */
|
||||
rlen = dp_aux_read_buf(ep, test_video_pattern_addr,
|
||||
test_parameter_len, 0);
|
||||
if (rlen < test_parameter_len) {
|
||||
pr_err("failed to read test video pattern\n");
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
rp = &ep->rxp;
|
||||
bp = rp->data;
|
||||
data = *bp++;
|
||||
|
||||
if (!mdss_dp_is_test_video_pattern_valid(data)) {
|
||||
pr_err("invalid test video pattern = 0x%x\n", data);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ep->test_data.test_video_pattern = data;
|
||||
pr_debug("test video pattern = 0x%x (%s)\n",
|
||||
ep->test_data.test_video_pattern,
|
||||
mdss_dp_test_video_pattern_to_string(
|
||||
ep->test_data.test_video_pattern));
|
||||
|
||||
/* Read the requested color bit depth and dynamic range (Byte 0x232) */
|
||||
rlen = dp_aux_read_buf(ep, test_misc_addr, test_parameter_len, 0);
|
||||
if (rlen < test_parameter_len) {
|
||||
pr_err("failed to read test bit depth\n");
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
rp = &ep->rxp;
|
||||
bp = rp->data;
|
||||
data = *bp++;
|
||||
|
||||
/* Dynamic Range */
|
||||
dyn_range = (data & BIT(3)) >> 3;
|
||||
if (!mdss_dp_is_dynamic_range_valid(dyn_range)) {
|
||||
pr_err("invalid test dynamic range = 0x%x", dyn_range);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
ep->test_data.test_dyn_range = dyn_range;
|
||||
pr_debug("test dynamic range = 0x%x (%s)\n",
|
||||
ep->test_data.test_dyn_range,
|
||||
mdss_dp_dynamic_range_to_string(ep->test_data.test_dyn_range));
|
||||
|
||||
/* Color bit depth */
|
||||
data &= (BIT(5) | BIT(6) | BIT(7));
|
||||
data >>= 5;
|
||||
if (!mdss_dp_is_test_bit_depth_valid(data)) {
|
||||
pr_err("invalid test bit depth = 0x%x\n", data);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ep->test_data.test_bit_depth = data;
|
||||
pr_debug("test bit depth = 0x%x (%s)\n",
|
||||
ep->test_data.test_bit_depth,
|
||||
mdss_dp_test_bit_depth_to_string(ep->test_data.test_bit_depth));
|
||||
|
||||
/* resolution timing params */
|
||||
ret = dp_parse_test_timing_params1(ep, 0x222, 2,
|
||||
&ep->test_data.test_h_total);
|
||||
if (ret) {
|
||||
pr_err("failed to parse test_h_total (0x222)\n");
|
||||
goto exit;
|
||||
}
|
||||
pr_debug("TEST_H_TOTAL = %d\n", ep->test_data.test_h_total);
|
||||
|
||||
ret = dp_parse_test_timing_params1(ep, 0x224, 2,
|
||||
&ep->test_data.test_v_total);
|
||||
if (ret) {
|
||||
pr_err("failed to parse test_v_total (0x224)\n");
|
||||
goto exit;
|
||||
}
|
||||
pr_debug("TEST_V_TOTAL = %d\n", ep->test_data.test_v_total);
|
||||
|
||||
ret = dp_parse_test_timing_params1(ep, 0x226, 2,
|
||||
&ep->test_data.test_h_start);
|
||||
if (ret) {
|
||||
pr_err("failed to parse test_h_start (0x226)\n");
|
||||
goto exit;
|
||||
}
|
||||
pr_debug("TEST_H_START = %d\n", ep->test_data.test_h_start);
|
||||
|
||||
ret = dp_parse_test_timing_params1(ep, 0x228, 2,
|
||||
&ep->test_data.test_v_start);
|
||||
if (ret) {
|
||||
pr_err("failed to parse test_v_start (0x228)\n");
|
||||
goto exit;
|
||||
}
|
||||
pr_debug("TEST_V_START = %d\n", ep->test_data.test_v_start);
|
||||
|
||||
ret = dp_parse_test_timing_params2(ep, 0x22A, 2,
|
||||
&ep->test_data.test_hsync_pol,
|
||||
&ep->test_data.test_hsync_width);
|
||||
if (ret) {
|
||||
pr_err("failed to parse (0x22A)\n");
|
||||
goto exit;
|
||||
}
|
||||
pr_debug("TEST_HSYNC_POL = %d\n", ep->test_data.test_hsync_pol);
|
||||
pr_debug("TEST_HSYNC_WIDTH = %d\n", ep->test_data.test_hsync_width);
|
||||
|
||||
ret = dp_parse_test_timing_params2(ep, 0x22C, 2,
|
||||
&ep->test_data.test_vsync_pol,
|
||||
&ep->test_data.test_vsync_width);
|
||||
if (ret) {
|
||||
pr_err("failed to parse (0x22C)\n");
|
||||
goto exit;
|
||||
}
|
||||
pr_debug("TEST_VSYNC_POL = %d\n", ep->test_data.test_vsync_pol);
|
||||
pr_debug("TEST_VSYNC_WIDTH = %d\n", ep->test_data.test_vsync_width);
|
||||
|
||||
ret = dp_parse_test_timing_params1(ep, 0x22E, 2,
|
||||
&ep->test_data.test_h_width);
|
||||
if (ret) {
|
||||
pr_err("failed to parse test_h_width (0x22E)\n");
|
||||
goto exit;
|
||||
}
|
||||
pr_debug("TEST_H_WIDTH = %d\n", ep->test_data.test_h_width);
|
||||
|
||||
ret = dp_parse_test_timing_params1(ep, 0x230, 2,
|
||||
&ep->test_data.test_v_height);
|
||||
if (ret) {
|
||||
pr_err("failed to parse test_v_height (0x230)\n");
|
||||
goto exit;
|
||||
}
|
||||
pr_debug("TEST_V_HEIGHT = %d\n", ep->test_data.test_v_height);
|
||||
|
||||
ret = dp_parse_test_timing_params3(ep, 0x233, &ep->test_data.test_rr_d);
|
||||
ep->test_data.test_rr_d &= BIT(0);
|
||||
if (ret) {
|
||||
pr_err("failed to parse test_rr_d (0x233)\n");
|
||||
goto exit;
|
||||
}
|
||||
pr_debug("TEST_REFRESH_DENOMINATOR = %d\n", ep->test_data.test_rr_d);
|
||||
|
||||
ret = dp_parse_test_timing_params3(ep, 0x234, &ep->test_data.test_rr_n);
|
||||
if (ret) {
|
||||
pr_err("failed to parse test_rr_n (0x234)\n");
|
||||
goto exit;
|
||||
}
|
||||
pr_debug("TEST_REFRESH_NUMERATOR = %d\n", ep->test_data.test_rr_n);
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* dp_is_test_supported() - checks if test requested by sink is supported
|
||||
|
@ -1268,6 +1503,7 @@ end:
|
|||
static bool dp_is_test_supported(u32 test_requested)
|
||||
{
|
||||
return (test_requested == TEST_LINK_TRAINING) ||
|
||||
(test_requested == TEST_VIDEO_PATTERN) ||
|
||||
(test_requested == TEST_EDID_READ) ||
|
||||
(test_requested == PHY_TEST_PATTERN);
|
||||
}
|
||||
|
@ -1289,6 +1525,7 @@ static void dp_sink_parse_test_request(struct mdss_dp_drv_pdata *ep)
|
|||
int const test_parameter_len = 0x1;
|
||||
int const device_service_irq_addr = 0x201;
|
||||
int const test_request_addr = 0x218;
|
||||
char buf[4];
|
||||
|
||||
/**
|
||||
* Read the device service IRQ vector (Byte 0x201) to determine
|
||||
|
@ -1341,12 +1578,19 @@ static void dp_sink_parse_test_request(struct mdss_dp_drv_pdata *ep)
|
|||
case TEST_LINK_TRAINING:
|
||||
ret = dp_parse_link_training_params(ep);
|
||||
break;
|
||||
case TEST_VIDEO_PATTERN:
|
||||
ret = dp_parse_video_pattern_params(ep);
|
||||
break;
|
||||
default:
|
||||
pr_debug("test 0x%x not supported\n",
|
||||
ep->test_data.test_requested);
|
||||
return;
|
||||
}
|
||||
|
||||
/* clear the test request IRQ */
|
||||
buf[0] = 1;
|
||||
dp_aux_write_buf(ep, test_request_addr, buf, 1, 0);
|
||||
|
||||
/**
|
||||
* Send a TEST_ACK if all test parameters are valid, otherwise send
|
||||
* a TEST_NACK.
|
||||
|
@ -1833,8 +2077,6 @@ int mdss_dp_link_train(struct mdss_dp_drv_pdata *dp)
|
|||
clear:
|
||||
dp_clear_training_pattern(dp);
|
||||
if (ret != -EINVAL) {
|
||||
mdss_dp_config_misc_settings(&dp->ctrl_io,
|
||||
&dp->panel_data.panel_info);
|
||||
mdss_dp_setup_tr_unit(&dp->ctrl_io, dp->link_rate,
|
||||
dp->lane_cnt, dp->vic,
|
||||
&dp->panel_data.panel_info);
|
||||
|
|
|
@ -767,28 +767,15 @@ void mdss_dp_sw_config_msa(struct dss_io_data *ctrl_io,
|
|||
writel_relaxed(nvid, ctrl_io->base + DP_SOFTWARE_NVID);
|
||||
}
|
||||
|
||||
void mdss_dp_config_misc_settings(struct dss_io_data *ctrl_io,
|
||||
struct mdss_panel_info *pinfo)
|
||||
void mdss_dp_config_misc(struct mdss_dp_drv_pdata *dp, u32 bd, u32 cc)
|
||||
{
|
||||
u32 bpp = pinfo->bpp;
|
||||
u32 misc_val = 0x0;
|
||||
|
||||
switch (bpp) {
|
||||
case 18:
|
||||
misc_val |= (0x0 << 5);
|
||||
break;
|
||||
case 30:
|
||||
misc_val |= (0x2 << 5);
|
||||
break;
|
||||
case 24:
|
||||
default:
|
||||
misc_val |= (0x1 << 5);
|
||||
}
|
||||
u32 misc_val = cc;
|
||||
|
||||
misc_val |= (bd << 5);
|
||||
misc_val |= BIT(0); /* Configure clock to synchronous mode */
|
||||
|
||||
pr_debug("Misc settings = 0x%x\n", misc_val);
|
||||
writel_relaxed(misc_val, ctrl_io->base + DP_MISC1_MISC0);
|
||||
writel_relaxed(misc_val, dp->ctrl_io.base + DP_MISC1_MISC0);
|
||||
}
|
||||
|
||||
void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate,
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#define DP_TEST_80BIT_CUSTOM_PATTERN_REG1 (0x000004C4)
|
||||
#define DP_TEST_80BIT_CUSTOM_PATTERN_REG2 (0x000004C8)
|
||||
|
||||
#define MMSS_DP_MISC1_MISC0 (0x0000042C)
|
||||
#define MMSS_DP_AUDIO_TIMING_GEN (0x00000480)
|
||||
#define MMSS_DP_AUDIO_TIMING_RBR_32 (0x00000484)
|
||||
#define MMSS_DP_AUDIO_TIMING_HBR_32 (0x00000488)
|
||||
|
@ -285,8 +286,7 @@ void mdss_dp_switch_usb3_phy_to_dp_mode(struct dss_io_data *tcsr_reg_io);
|
|||
void mdss_dp_assert_phy_reset(struct dss_io_data *ctrl_io, bool assert);
|
||||
void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate,
|
||||
u8 ln_cnt, u32 res, struct mdss_panel_info *pinfo);
|
||||
void mdss_dp_config_misc_settings(struct dss_io_data *ctrl_io,
|
||||
struct mdss_panel_info *pinfo);
|
||||
void mdss_dp_config_misc(struct mdss_dp_drv_pdata *dp, u32 bd, u32 cc);
|
||||
void mdss_dp_phy_aux_setup(struct dss_io_data *phy_io);
|
||||
void mdss_dp_hpd_configure(struct dss_io_data *ctrl_io, bool enable);
|
||||
void mdss_dp_aux_ctrl(struct dss_io_data *ctrl_io, bool enable);
|
||||
|
|
Loading…
Add table
Reference in a new issue