summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUjwal Patel <ujwalp@codeaurora.org>2013-03-14 17:05:40 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:15:24 -0700
commit8ee7156cf1dd855aa8dd759bf3ec5220c81fd3cf (patch)
tree7e0065f434ffe5229a2ce3cb4a7ab37f11a6c6a4
parent7b8cbc68c0d70dd60cf74e199d5e203a3d997e2e (diff)
msm: mdss: enable support for hdmi as primary
When HDMI is configured as primary display, enable hpd circuit as soon as frame buffer is registered. Change-Id: I4bcc796ea6310416077b09858a272b2622c62709 Signed-off-by: Ujwal Patel <ujwalp@codeaurora.org>
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c56
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.h3
2 files changed, 51 insertions, 8 deletions
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
index caa24f6ef470..300671711982 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -449,6 +449,18 @@ static inline u32 hdmi_tx_is_dvi_mode(struct hdmi_tx_ctrl *hdmi_ctrl)
hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) ? 0 : 1;
} /* hdmi_tx_is_dvi_mode */
+static inline void hdmi_tx_send_cable_notification(
+ struct hdmi_tx_ctrl *hdmi_ctrl, int val)
+{
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+
+ if (!hdmi_ctrl->pdata.primary && (hdmi_ctrl->sdev.state != val))
+ switch_set_state(&hdmi_ctrl->sdev, val);
+} /* hdmi_tx_send_cable_notification */
+
static inline void hdmi_tx_set_audio_switch_node(struct hdmi_tx_ctrl *hdmi_ctrl,
int val, bool force)
{
@@ -695,11 +707,11 @@ static void hdmi_tx_hpd_int_work(struct work_struct *work)
if (hdmi_ctrl->hpd_state) {
hdmi_tx_read_sink_info(hdmi_ctrl);
- switch_set_state(&hdmi_ctrl->sdev, 1);
+ hdmi_tx_send_cable_notification(hdmi_ctrl, 1);
DEV_INFO("%s: sense cable CONNECTED: state switch to %d\n",
__func__, hdmi_ctrl->sdev.state);
} else {
- switch_set_state(&hdmi_ctrl->sdev, 0);
+ hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
DEV_INFO("%s: sense cable DISCONNECTED: state switch to %d\n",
__func__, hdmi_ctrl->sdev.state);
}
@@ -2097,6 +2109,7 @@ static int hdmi_tx_power_off(struct mdss_panel_data *panel_data)
static int hdmi_tx_power_on(struct mdss_panel_data *panel_data)
{
+ u32 timeout;
int rc = 0;
struct dss_io_data *io = NULL;
struct hdmi_tx_ctrl *hdmi_ctrl =
@@ -2121,6 +2134,16 @@ static int hdmi_tx_power_on(struct mdss_panel_data *panel_data)
/* If a power down is already underway, wait for it to finish */
flush_work(&hdmi_ctrl->power_off_work);
+ if (hdmi_ctrl->pdata.primary) {
+ timeout = wait_for_completion_interruptible_timeout(
+ &hdmi_ctrl->hpd_done, HZ);
+ if (!timeout) {
+ DEV_ERR("%s: cable connection hasn't happened yet\n",
+ __func__);
+ return -ETIMEDOUT;
+ }
+ }
+
rc = hdmi_tx_set_video_fmt(hdmi_ctrl, &panel_data->panel_info);
if (rc) {
DEV_ERR("%s: cannot set video_fmt.rc=%d\n", __func__, rc);
@@ -2265,7 +2288,7 @@ static int hdmi_tx_sysfs_enable_hpd(struct hdmi_tx_ctrl *hdmi_ctrl, int on)
} else {
hdmi_ctrl->hpd_off_pending = true;
- switch_set_state(&hdmi_ctrl->sdev, 0);
+ hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
DEV_DBG("%s: Hdmi state switch to %d\n", __func__,
hdmi_ctrl->sdev.state);
}
@@ -2441,6 +2464,20 @@ static int hdmi_tx_panel_event_handler(struct mdss_panel_data *panel_data,
hdmi_tx_sysfs_remove(hdmi_ctrl);
return rc;
}
+
+ if (hdmi_ctrl->pdata.primary) {
+ INIT_COMPLETION(hdmi_ctrl->hpd_done);
+ rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, true);
+ if (rc) {
+ DEV_ERR("%s: hpd_enable failed. rc=%d\n",
+ __func__, rc);
+ hdmi_tx_sysfs_remove(hdmi_ctrl);
+ return rc;
+ } else {
+ hdmi_ctrl->hpd_feature_on = true;
+ }
+ }
+
break;
case MDSS_EVENT_CHECK_PARAMS:
@@ -2487,7 +2524,7 @@ static int hdmi_tx_panel_event_handler(struct mdss_panel_data *panel_data,
if (!timeout & !hdmi_ctrl->hpd_state) {
DEV_INFO("%s: cable removed during suspend\n",
__func__);
- switch_set_state(&hdmi_ctrl->sdev, 0);
+ hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
rc = -EPERM;
} else {
DEV_DBG("%s: cable present after resume\n",
@@ -3116,6 +3153,13 @@ static int hdmi_tx_get_dt_data(struct platform_device *pdev,
}
}
+ if (of_find_property(pdev->dev.of_node, "qcom,primary_panel", NULL)) {
+ u32 tmp;
+ of_property_read_u32(pdev->dev.of_node, "qcom,primary_panel",
+ &tmp);
+ pdata->primary = tmp ? true : false;
+ }
+
return rc;
error:
@@ -3175,7 +3219,7 @@ static int hdmi_tx_probe(struct platform_device *pdev)
if (rc) {
DEV_ERR("%s: Failed to add child devices. rc=%d\n",
__func__, rc);
- goto failed_init_features;
+ goto failed_reg_panel;
} else {
DEV_DBG("%s: Add child devices.\n", __func__);
}
@@ -3187,8 +3231,6 @@ static int hdmi_tx_probe(struct platform_device *pdev)
return rc;
-failed_init_features:
- hdmi_tx_sysfs_remove(hdmi_ctrl);
failed_reg_panel:
hdmi_tx_dev_deinit(hdmi_ctrl);
failed_dev_init:
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.h b/drivers/video/fbdev/msm/mdss_hdmi_tx.h
index 06ae42766593..8d9a477a979a 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.h
@@ -30,8 +30,9 @@ enum hdmi_tx_power_module_type {
HDMI_TX_MAX_PM
};
+/* Data filled from device tree */
struct hdmi_tx_platform_data {
- /* Data filled from device tree nodes */
+ bool primary;
struct dss_io_data io[HDMI_TX_MAX_IO];
struct dss_module_power power_data[HDMI_TX_MAX_PM];
};