Merge "mdss: display-port: fix DP issue when framework reboots"

This commit is contained in:
Linux Build Service Account 2017-03-09 17:21:25 -08:00 committed by Gerrit - the friendly Code Review server
commit cbd89c14fa
7 changed files with 236 additions and 53 deletions

View file

@ -285,11 +285,6 @@ static bool msm_ext_disp_validate_connect(struct msm_ext_disp *ext_disp,
/* if already connected, block a new connection */ /* if already connected, block a new connection */
if (ext_disp->current_disp != type) if (ext_disp->current_disp != type)
return false; return false;
/* if same display connected, block same connection type */
if (ext_disp->flags & flags)
return false;
end: end:
ext_disp->flags |= flags; ext_disp->flags |= flags;
ext_disp->current_disp = type; ext_disp->current_disp = type;

View file

@ -54,6 +54,8 @@ struct mdss_dp_attention_node {
#define DEFAULT_VIDEO_RESOLUTION HDMI_VFRMT_640x480p60_4_3 #define DEFAULT_VIDEO_RESOLUTION HDMI_VFRMT_640x480p60_4_3
static int mdss_dp_host_init(struct mdss_panel_data *pdata);
static int mdss_dp_host_deinit(struct mdss_dp_drv_pdata *dp);
static int mdss_dp_off_irq(struct mdss_dp_drv_pdata *dp_drv); static int mdss_dp_off_irq(struct mdss_dp_drv_pdata *dp_drv);
static void mdss_dp_mainlink_push_idle(struct mdss_panel_data *pdata); static void mdss_dp_mainlink_push_idle(struct mdss_panel_data *pdata);
static inline void mdss_dp_link_maintenance(struct mdss_dp_drv_pdata *dp, static inline void mdss_dp_link_maintenance(struct mdss_dp_drv_pdata *dp,
@ -64,6 +66,8 @@ static int mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp,
enum notification_status status); enum notification_status status);
static int mdss_dp_process_phy_test_pattern_request( static int mdss_dp_process_phy_test_pattern_request(
struct mdss_dp_drv_pdata *dp); struct mdss_dp_drv_pdata *dp);
static int mdss_dp_send_audio_notification(
struct mdss_dp_drv_pdata *dp, int val);
static inline 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)
{ {
@ -474,6 +478,12 @@ static int mdss_dp_clk_ctrl(struct mdss_dp_drv_pdata *dp_drv,
else else
dp_drv->link_clks_on = enable; dp_drv->link_clks_on = enable;
pr_debug("%s clocks for %s\n",
enable ? "enable" : "disable",
__mdss_dp_pm_name(pm_type));
pr_debug("link_clks:%s core_clks:%s\n",
dp_drv->link_clks_on ? "on" : "off",
dp_drv->core_clks_on ? "on" : "off");
error: error:
return ret; return ret;
} }
@ -961,6 +971,14 @@ static int mdss_dp_wait4video_ready(struct mdss_dp_drv_pdata *dp_drv)
ret = -EINVAL; ret = -EINVAL;
} else { } else {
ret = 0; ret = 0;
/*
* The audio subsystem should only be notified once the DP
* controller is in SEND_VIDEO state. This will ensure that
* the DP audio engine is able to acknowledge the audio unmute
* request, which will result in the AFE port being configured
* correctly.
*/
mdss_dp_send_audio_notification(dp_drv, true);
} }
pr_debug("End--\n"); pr_debug("End--\n");
@ -1038,6 +1056,22 @@ static int dp_get_audio_edid_blk(struct platform_device *pdev,
return rc; return rc;
} /* dp_get_audio_edid_blk */ } /* dp_get_audio_edid_blk */
static void dp_audio_teardown_done(struct platform_device *pdev)
{
struct mdss_dp_drv_pdata *dp = platform_get_drvdata(pdev);
if (!dp) {
pr_err("invalid input\n");
return;
}
mdss_dp_audio_enable(&dp->ctrl_io, false);
/* Make sure the DP audio engine is disabled */
wmb();
pr_debug("audio engine disabled\n");
} /* dp_audio_teardown_done */
static int mdss_dp_init_ext_disp(struct mdss_dp_drv_pdata *dp) static int mdss_dp_init_ext_disp(struct mdss_dp_drv_pdata *dp)
{ {
int ret = 0; int ret = 0;
@ -1059,6 +1093,8 @@ static int mdss_dp_init_ext_disp(struct mdss_dp_drv_pdata *dp)
dp_get_audio_edid_blk; dp_get_audio_edid_blk;
dp->ext_audio_data.codec_ops.cable_status = dp->ext_audio_data.codec_ops.cable_status =
dp_get_cable_status; dp_get_cable_status;
dp->ext_audio_data.codec_ops.teardown_done =
dp_audio_teardown_done;
if (!dp->pdev->dev.of_node) { if (!dp->pdev->dev.of_node) {
pr_err("%s cannot find dp dev.of_node\n", __func__); pr_err("%s cannot find dp dev.of_node\n", __func__);
@ -1284,6 +1320,11 @@ static int mdss_dp_enable_mainlink_clocks(struct mdss_dp_drv_pdata *dp)
if (dp->pixel_clk_rcg && dp->pixel_parent) if (dp->pixel_clk_rcg && dp->pixel_parent)
clk_set_parent(dp->pixel_clk_rcg, dp->pixel_parent); clk_set_parent(dp->pixel_clk_rcg, dp->pixel_parent);
if (dp->link_clks_on) {
pr_debug("link clocks already on\n");
return ret;
}
mdss_dp_set_clock_rate(dp, "ctrl_link_clk", mdss_dp_set_clock_rate(dp, "ctrl_link_clk",
(dp->link_rate * DP_LINK_RATE_MULTIPLIER) / DP_KHZ_TO_HZ); (dp->link_rate * DP_LINK_RATE_MULTIPLIER) / DP_KHZ_TO_HZ);
@ -1308,6 +1349,11 @@ static int mdss_dp_enable_mainlink_clocks(struct mdss_dp_drv_pdata *dp)
*/ */
static void mdss_dp_disable_mainlink_clocks(struct mdss_dp_drv_pdata *dp_drv) static void mdss_dp_disable_mainlink_clocks(struct mdss_dp_drv_pdata *dp_drv)
{ {
if (!dp_drv->link_clks_on) {
pr_debug("link clocks already off\n");
return;
}
mdss_dp_clk_ctrl(dp_drv, DP_CTRL_PM, false); mdss_dp_clk_ctrl(dp_drv, DP_CTRL_PM, false);
} }
@ -1347,7 +1393,7 @@ static void mdss_dp_configure_source_params(struct mdss_dp_drv_pdata *dp,
static int mdss_dp_setup_main_link(struct mdss_dp_drv_pdata *dp, bool train) static int mdss_dp_setup_main_link(struct mdss_dp_drv_pdata *dp, bool train)
{ {
int ret = 0; int ret = 0;
int ready = 0; bool mainlink_ready = false;
pr_debug("enter\n"); pr_debug("enter\n");
mdss_dp_mainlink_ctrl(&dp->ctrl_io, true); mdss_dp_mainlink_ctrl(&dp->ctrl_io, true);
@ -1380,8 +1426,8 @@ send_video:
mdss_dp_state_ctrl(&dp->ctrl_io, ST_SEND_VIDEO); mdss_dp_state_ctrl(&dp->ctrl_io, ST_SEND_VIDEO);
mdss_dp_wait4video_ready(dp); mdss_dp_wait4video_ready(dp);
ready = mdss_dp_mainlink_ready(dp, BIT(0)); mainlink_ready = mdss_dp_mainlink_ready(dp);
pr_debug("main link %s\n", ready ? "READY" : "NOT READY"); pr_debug("mainlink %s\n", mainlink_ready ? "READY" : "NOT READY");
end: end:
return ret; return ret;
@ -1543,6 +1589,16 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
return 0; return 0;
} }
/*
* During device suspend, host_deinit() is called
* to release DP resources. PM_RESUME can be
* called for any module wake-up. To avoid multiple host
* init/deinit during unrelated resume/suspend events,
* add host initialization call before DP power-on.
*/
if (!dp_drv->dp_initialized)
mdss_dp_host_init(pdata);
return mdss_dp_on_hpd(dp_drv); return mdss_dp_on_hpd(dp_drv);
} }
@ -1590,25 +1646,7 @@ static int mdss_dp_off_hpd(struct mdss_dp_drv_pdata *dp_drv)
mdss_dp_audio_enable(&dp_drv->ctrl_io, false); mdss_dp_audio_enable(&dp_drv->ctrl_io, false);
mdss_dp_irq_disable(dp_drv); mdss_dp_host_deinit(dp_drv);
mdss_dp_config_gpios(dp_drv, false);
mdss_dp_pinctrl_set_state(dp_drv, false);
/*
* The global reset will need DP link ralated clocks to be
* running. Add the global reset just before disabling the
* link clocks and core clocks.
*/
mdss_dp_ctrl_reset(&dp_drv->ctrl_io);
/* Make sure DP is disabled before clk disable */
wmb();
mdss_dp_disable_mainlink_clocks(dp_drv);
mdss_dp_clk_ctrl(dp_drv, DP_CORE_PM, false);
mdss_dp_regulator_ctrl(dp_drv, false);
dp_drv->dp_initialized = false;
dp_drv->power_on = false; dp_drv->power_on = false;
dp_drv->sink_info_read = false; dp_drv->sink_info_read = false;
@ -1639,26 +1677,46 @@ int mdss_dp_off(struct mdss_panel_data *pdata)
return mdss_dp_off_hpd(dp); return mdss_dp_off_hpd(dp);
} }
static int mdss_dp_send_cable_notification( static int mdss_dp_send_audio_notification(
struct mdss_dp_drv_pdata *dp, int val) struct mdss_dp_drv_pdata *dp, int val)
{ {
int ret = 0; int ret = 0;
u32 flags = 0; u32 flags = 0;
if (!dp) { if (!dp) {
DEV_ERR("%s: invalid input\n", __func__); pr_err("invalid input\n");
ret = -EINVAL; ret = -EINVAL;
goto end; goto end;
} }
flags |= MSM_EXT_DISP_HPD_VIDEO;
if (!mdss_dp_is_dvi_mode(dp) || dp->audio_test_req) { if (!mdss_dp_is_dvi_mode(dp) || dp->audio_test_req) {
dp->audio_test_req = false; dp->audio_test_req = false;
flags |= MSM_EXT_DISP_HPD_AUDIO; flags |= MSM_EXT_DISP_HPD_AUDIO;
if (dp->ext_audio_data.intf_ops.hpd)
ret = dp->ext_audio_data.intf_ops.hpd(dp->ext_pdev,
dp->ext_audio_data.type, val, flags);
} }
end:
return ret;
}
static int mdss_dp_send_video_notification(
struct mdss_dp_drv_pdata *dp, int val)
{
int ret = 0;
u32 flags = 0;
if (!dp) {
pr_err("invalid input\n");
ret = -EINVAL;
goto end;
}
flags |= MSM_EXT_DISP_HPD_VIDEO;
if (dp->ext_audio_data.intf_ops.hpd) if (dp->ext_audio_data.intf_ops.hpd)
ret = dp->ext_audio_data.intf_ops.hpd(dp->ext_pdev, ret = dp->ext_audio_data.intf_ops.hpd(dp->ext_pdev,
dp->ext_audio_data.type, val, flags); dp->ext_audio_data.type, val, flags);
@ -1673,6 +1731,19 @@ static void mdss_dp_set_default_resolution(struct mdss_dp_drv_pdata *dp)
DEFAULT_VIDEO_RESOLUTION, true); DEFAULT_VIDEO_RESOLUTION, true);
} }
static void mdss_dp_set_default_link_parameters(struct mdss_dp_drv_pdata *dp)
{
const int default_max_link_rate = 0x6;
const int default_max_lane_count = 1;
dp->dpcd.max_lane_count = default_max_lane_count;
dp->dpcd.max_link_rate = default_max_link_rate;
pr_debug("max_link_rate = 0x%x, max_lane_count= 0x%x\n",
dp->dpcd.max_link_rate,
dp->dpcd.max_lane_count);
}
static int mdss_dp_edid_init(struct mdss_panel_data *pdata) static int mdss_dp_edid_init(struct mdss_panel_data *pdata)
{ {
struct mdss_dp_drv_pdata *dp_drv = NULL; struct mdss_dp_drv_pdata *dp_drv = NULL;
@ -1775,6 +1846,49 @@ vreg_error:
return ret; return ret;
} }
/**
* mdss_dp_host_deinit() - Uninitialize DP controller
* @dp: Display Port Driver data
*
* Perform required steps to uninitialize DP controller
* and its resources.
*/
static int mdss_dp_host_deinit(struct mdss_dp_drv_pdata *dp)
{
if (!dp) {
pr_err("Invalid input data\n");
return -EINVAL;
}
if (!dp->dp_initialized) {
pr_debug("%s: host deinit done already\n", __func__);
return 0;
}
mdss_dp_irq_disable(dp);
mdss_dp_config_gpios(dp, false);
mdss_dp_pinctrl_set_state(dp, false);
/*
* The global reset will need DP link ralated clocks to be
* running. Add the global reset just before disabling the
* link clocks and core clocks.
*/
mdss_dp_ctrl_reset(&dp->ctrl_io);
/* Make sure DP is disabled before clk disable */
wmb();
mdss_dp_disable_mainlink_clocks(dp);
mdss_dp_clk_ctrl(dp, DP_CORE_PM, false);
mdss_dp_regulator_ctrl(dp, false);
dp->dp_initialized = false;
pr_debug("Host deinitialized successfully\n");
return 0;
}
/** /**
* mdss_dp_notify_clients() - notifies DP clients of cable connection * mdss_dp_notify_clients() - notifies DP clients of cable connection
* @dp: Display Port Driver data * @dp: Display Port Driver data
@ -1804,7 +1918,7 @@ static int mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp,
goto invalid_request; goto invalid_request;
/* Follow the same programming as for NOTIFY_CONNECT */ /* Follow the same programming as for NOTIFY_CONNECT */
mdss_dp_host_init(&dp->panel_data); mdss_dp_host_init(&dp->panel_data);
mdss_dp_send_cable_notification(dp, true); mdss_dp_send_video_notification(dp, true);
break; break;
case NOTIFY_CONNECT: case NOTIFY_CONNECT:
if ((dp->hpd_notification_status == NOTIFY_CONNECT_IRQ_HPD) || if ((dp->hpd_notification_status == NOTIFY_CONNECT_IRQ_HPD) ||
@ -1812,16 +1926,18 @@ static int mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp,
NOTIFY_DISCONNECT_IRQ_HPD)) NOTIFY_DISCONNECT_IRQ_HPD))
goto invalid_request; goto invalid_request;
mdss_dp_host_init(&dp->panel_data); mdss_dp_host_init(&dp->panel_data);
mdss_dp_send_cable_notification(dp, true); mdss_dp_send_video_notification(dp, true);
break; break;
case NOTIFY_DISCONNECT: case NOTIFY_DISCONNECT:
mdss_dp_send_cable_notification(dp, false); mdss_dp_send_audio_notification(dp, false);
mdss_dp_send_video_notification(dp, false);
break; break;
case NOTIFY_DISCONNECT_IRQ_HPD: case NOTIFY_DISCONNECT_IRQ_HPD:
if (dp->hpd_notification_status == NOTIFY_DISCONNECT) if (dp->hpd_notification_status == NOTIFY_DISCONNECT)
goto invalid_request; goto invalid_request;
mdss_dp_send_cable_notification(dp, false); mdss_dp_send_audio_notification(dp, false);
mdss_dp_send_video_notification(dp, false);
if (!IS_ERR_VALUE(ret) && ret) { if (!IS_ERR_VALUE(ret) && ret) {
reinit_completion(&dp->irq_comp); reinit_completion(&dp->irq_comp);
ret = wait_for_completion_timeout(&dp->irq_comp, ret = wait_for_completion_timeout(&dp->irq_comp,
@ -1878,12 +1994,16 @@ static int mdss_dp_process_hpd_high(struct mdss_dp_drv_pdata *dp)
pr_debug("edid read error, setting default resolution\n"); pr_debug("edid read error, setting default resolution\n");
mdss_dp_set_default_resolution(dp); mdss_dp_set_default_resolution(dp);
mdss_dp_set_default_link_parameters(dp);
goto notify; goto notify;
} }
ret = hdmi_edid_parser(dp->panel_data.panel_info.edid_data); ret = hdmi_edid_parser(dp->panel_data.panel_info.edid_data);
if (ret) { if (ret) {
pr_err("edid parse failed\n"); pr_err("edid parse failed, setting default resolution\n");
mdss_dp_set_default_resolution(dp);
mdss_dp_set_default_link_parameters(dp);
goto notify; goto notify;
} }
@ -2307,7 +2427,7 @@ static ssize_t mdss_dp_wta_hpd(struct device *dev,
} else { } else {
dp_send_events(dp, EV_USBPD_DISCOVER_MODES); dp_send_events(dp, EV_USBPD_DISCOVER_MODES);
} }
} else if (!dp->hpd && dp->power_on) { } else if (!dp->hpd) {
mdss_dp_notify_clients(dp, NOTIFY_DISCONNECT); mdss_dp_notify_clients(dp, NOTIFY_DISCONNECT);
} }
end: end:
@ -2686,6 +2806,22 @@ static void mdss_dp_update_hdcp_info(struct mdss_dp_drv_pdata *dp)
} }
} }
/**
* mdss_dp_reset_panel_info() - reset the panel_info data
* @dp: Display Port Driver data
*
* This function will reset the panel resolution to
* HDMI_VFRMT_UNKNOWN if the sink device is not connected. This will help
* to reconfigure the panel resolution during cable connect event.
*/
static void mdss_dp_reset_panel_info(struct mdss_dp_drv_pdata *dp)
{
if (dp->suspend_vic != HDMI_VFRMT_UNKNOWN) {
dp->suspend_vic = HDMI_VFRMT_UNKNOWN;
dp_init_panel_info(dp, dp->suspend_vic);
}
}
static int mdss_dp_event_handler(struct mdss_panel_data *pdata, static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
int event, void *arg) int event, void *arg)
{ {
@ -2705,11 +2841,10 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
switch (event) { switch (event) {
case MDSS_EVENT_UNBLANK: case MDSS_EVENT_UNBLANK:
mdss_dp_ack_state(dp, true);
rc = mdss_dp_on(pdata); rc = mdss_dp_on(pdata);
break; break;
case MDSS_EVENT_PANEL_ON: case MDSS_EVENT_PANEL_ON:
mdss_dp_ack_state(dp, true);
mdss_dp_update_hdcp_info(dp); mdss_dp_update_hdcp_info(dp);
if (dp_is_hdcp_enabled(dp)) { if (dp_is_hdcp_enabled(dp)) {
@ -2754,6 +2889,31 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
case MDSS_EVENT_CHECK_PARAMS: case MDSS_EVENT_CHECK_PARAMS:
rc = mdss_dp_check_params(dp, arg); rc = mdss_dp_check_params(dp, arg);
break; break;
case MDSS_EVENT_SUSPEND:
/*
* Make sure DP host_deinit is called
* when DP host is initialized but not
* powered ON.
* For example, this scenerio happens
* when you connect DP sink while the
* device is in suspend state.
*/
if ((!dp->power_on) && (dp->dp_initialized))
rc = mdss_dp_host_deinit(dp);
/*
* For DP suspend/resume use case, CHECK_PARAMS is
* not called if the cable status is not changed.
* Store the sink resolution in suspend and configure
* the resolution during DP resume path.
*/
if (dp->power_on)
dp->suspend_vic = dp->vic;
break;
case MDSS_EVENT_RESUME:
if (dp->suspend_vic != HDMI_VFRMT_UNKNOWN)
dp_init_panel_info(dp, dp->suspend_vic);
break;
default: default:
pr_debug("unhandled event=%d\n", event); pr_debug("unhandled event=%d\n", event);
break; break;
@ -3109,6 +3269,27 @@ static void usbpd_disconnect_callback(struct usbpd_svid_handler *hdlr)
} else { } else {
mdss_dp_notify_clients(dp_drv, NOTIFY_DISCONNECT); mdss_dp_notify_clients(dp_drv, NOTIFY_DISCONNECT);
} }
/*
* If cable is disconnected during device suspend,
* reset the panel resolution to HDMI_VFRMT_UNKNOWN
* so that new resolution is configured during
* cable connect event
*/
if ((!dp_drv->power_on) && (!dp_drv->dp_initialized))
mdss_dp_reset_panel_info(dp_drv);
/*
* If a cable/dongle is connected to the TX device but
* no sink device is connected, we call host
* initialization where orientation settings are
* configured. When the cable/dongle is disconnect,
* call host de-initialization to make sure
* we re-configure the orientation settings during
* the next connect event.
*/
if ((!dp_drv->power_on) && (dp_drv->dp_initialized))
mdss_dp_host_deinit(dp_drv);
} }
static int mdss_dp_validate_callback(u8 cmd, static int mdss_dp_validate_callback(u8 cmd,
@ -3605,6 +3786,16 @@ static void mdss_dp_process_attention(struct mdss_dp_drv_pdata *dp_drv)
mdss_dp_notify_clients(dp_drv, NOTIFY_DISCONNECT); mdss_dp_notify_clients(dp_drv, NOTIFY_DISCONNECT);
pr_debug("Attention: Notified clients\n"); pr_debug("Attention: Notified clients\n");
/*
* When a DP adaptor is connected and if sink is
* disconnected during device suspend,
* reset the panel resolution to HDMI_VFRMT_UNKNOWN
* so that new resolution is configured during
* connect event.
*/
if ((!dp_drv->power_on) && (!dp_drv->dp_initialized))
mdss_dp_reset_panel_info(dp_drv);
/** /**
* Manually turn off the DP controller if we are in PHY * Manually turn off the DP controller if we are in PHY
* testing mode. * testing mode.
@ -3827,6 +4018,7 @@ static int mdss_dp_probe(struct platform_device *pdev)
dp_drv->hpd_irq_on = false; dp_drv->hpd_irq_on = false;
mdss_dp_reset_test_data(dp_drv); mdss_dp_reset_test_data(dp_drv);
init_completion(&dp_drv->irq_comp); init_completion(&dp_drv->irq_comp);
dp_drv->suspend_vic = HDMI_VFRMT_UNKNOWN;
pr_debug("done\n"); pr_debug("done\n");

View file

@ -450,6 +450,7 @@ struct mdss_dp_drv_pdata {
bool link_clks_on; bool link_clks_on;
bool power_on; bool power_on;
bool sink_info_read; bool sink_info_read;
u32 suspend_vic;
bool hpd; bool hpd;
bool psm_enabled; bool psm_enabled;
bool audio_test_req; bool audio_test_req;

View file

@ -2247,12 +2247,8 @@ static int dp_start_link_train_2(struct mdss_dp_drv_pdata *ep)
else else
pattern = 0x02; pattern = 0x02;
dp_write(ep->base + DP_STATE_CTRL, 0x0);
/* Make sure to clear the current pattern before starting a new one */
wmb();
dp_host_train_set(ep, pattern);
mdss_dp_aux_update_voltage_and_pre_emphasis_lvl(ep); mdss_dp_aux_update_voltage_and_pre_emphasis_lvl(ep);
dp_host_train_set(ep, pattern);
dp_train_pattern_set_write(ep, pattern | 0x20);/* train_2 */ dp_train_pattern_set_write(ep, pattern | 0x20);/* train_2 */
do { do {

View file

@ -177,23 +177,22 @@ void mdss_dp_mainlink_ctrl(struct dss_io_data *ctrl_io, bool enable)
writel_relaxed(mainlink_ctrl, ctrl_io->base + DP_MAINLINK_CTRL); writel_relaxed(mainlink_ctrl, ctrl_io->base + DP_MAINLINK_CTRL);
} }
int mdss_dp_mainlink_ready(struct mdss_dp_drv_pdata *dp, u32 which) bool mdss_dp_mainlink_ready(struct mdss_dp_drv_pdata *dp)
{ {
u32 data; u32 data;
int cnt = 10; int cnt = 10;
int const mainlink_ready_bit = BIT(0);
while (--cnt) { while (--cnt) {
/* DP_MAINLINK_READY */ /* DP_MAINLINK_READY */
data = readl_relaxed(dp->base + DP_MAINLINK_READY); data = readl_relaxed(dp->base + DP_MAINLINK_READY);
if (data & which) { if (data & mainlink_ready_bit)
pr_debug("which=%x ready\n", which); return true;
return 1;
}
udelay(1000); udelay(1000);
} }
pr_err("which=%x NOT ready\n", which); pr_err("mainlink not ready\n");
return 0; return false;
} }
/* DP Configuration controller*/ /* DP Configuration controller*/

View file

@ -291,7 +291,7 @@ 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); void mdss_dp_aux_ctrl(struct dss_io_data *ctrl_io, bool enable);
void mdss_dp_mainlink_ctrl(struct dss_io_data *ctrl_io, bool enable); void mdss_dp_mainlink_ctrl(struct dss_io_data *ctrl_io, bool enable);
void mdss_dp_ctrl_lane_mapping(struct dss_io_data *ctrl_io, char *l_map); void mdss_dp_ctrl_lane_mapping(struct dss_io_data *ctrl_io, char *l_map);
int mdss_dp_mainlink_ready(struct mdss_dp_drv_pdata *dp, u32 which); bool mdss_dp_mainlink_ready(struct mdss_dp_drv_pdata *dp);
void mdss_dp_timing_cfg(struct dss_io_data *ctrl_io, void mdss_dp_timing_cfg(struct dss_io_data *ctrl_io,
struct mdss_panel_info *pinfo); struct mdss_panel_info *pinfo);
void mdss_dp_configuration_ctrl(struct dss_io_data *ctrl_io, u32 data); void mdss_dp_configuration_ctrl(struct dss_io_data *ctrl_io, u32 data);

View file

@ -271,7 +271,7 @@ struct msm_hdmi_mode_timing_info {
720, 5, 5, 20, false, 74250, 60000, false, true, HDMI_RES_AR_16_9, 0} 720, 5, 5, 20, false, 74250, 60000, false, true, HDMI_RES_AR_16_9, 0}
#define HDMI_VFRMT_1920x1080i60_16_9_TIMING \ #define HDMI_VFRMT_1920x1080i60_16_9_TIMING \
{HDMI_VFRMT_1920x1080i60_16_9, 1920, 88, 44, 148, false, \ {HDMI_VFRMT_1920x1080i60_16_9, 1920, 88, 44, 148, false, \
540, 2, 5, 5, false, 74250, 60000, false, true, HDMI_RES_AR_16_9, 0} 540, 2, 5, 5, false, 74250, 60000, true, true, HDMI_RES_AR_16_9, 0}
#define HDMI_VFRMT_1440x480i60_4_3_TIMING \ #define HDMI_VFRMT_1440x480i60_4_3_TIMING \
{HDMI_VFRMT_1440x480i60_4_3, 1440, 38, 124, 114, true, \ {HDMI_VFRMT_1440x480i60_4_3, 1440, 38, 124, 114, true, \
240, 4, 3, 15, true, 27000, 60000, true, true, HDMI_RES_AR_4_3, 0} 240, 4, 3, 15, true, 27000, 60000, true, true, HDMI_RES_AR_4_3, 0}