platform: msm_shared: check for hdmi cable status
Provide and API to check for HDMI cable status. Other modules may
use this API to make decisions based on cable connection status.
Change-Id: I8c32c25c2863f33828da4d14d0ca613f844918ae
diff --git a/platform/msm_shared/mdss_hdmi.c b/platform/msm_shared/mdss_hdmi.c
index 3214a87..0741308 100644
--- a/platform/msm_shared/mdss_hdmi.c
+++ b/platform/msm_shared/mdss_hdmi.c
@@ -41,6 +41,9 @@
static struct msm_fb_panel_data panel;
extern int msm_display_init(struct msm_fb_panel_data *pdata);
+static bool hdmi_power_enabled;
+static bool hdmi_panel_clock_enabled;
+static bool hdmi_pll_clock_enabled;
/* Supported HDMI Audio channels */
#define MSM_HDMI_AUDIO_CHANNEL_2 1
@@ -568,29 +571,51 @@
static uint32_t mdss_hdmi_panel_clock(uint8_t enable, struct msm_panel_info *pinfo)
{
- return target_hdmi_panel_clock(enable, pinfo);
+ int ret = NO_ERROR;
+ if (hdmi_panel_clock_enabled)
+ return ret;
+
+ ret = target_hdmi_panel_clock(enable, pinfo);
+
+ hdmi_panel_clock_enabled = enable;
+
+ return ret;
}
static uint32_t mdss_hdmi_pll_clock(uint8_t enable, struct msm_panel_info *pinfo)
{
- return target_hdmi_pll_clock(enable, pinfo);
+ int ret = NO_ERROR;
+
+ if (hdmi_pll_clock_enabled)
+ return ret;
+
+ ret = target_hdmi_pll_clock(enable, pinfo);
+
+ hdmi_pll_clock_enabled = enable;
+
+ return ret;
}
static int mdss_hdmi_enable_power(uint8_t enable, struct msm_panel_info *pinfo)
{
- int ret = NO_ERROR;
+ int ret = NO_ERROR;
+
+ if (hdmi_power_enabled)
+ return ret;
ret = target_hdmi_regulator_ctrl(enable);
if (ret) {
dprintf(CRITICAL, "hdmi regulator control enable failed\n");
goto bail_regulator_fail;
- }
+ }
ret = target_hdmi_gpio_ctrl(enable);
if (ret) {
dprintf(CRITICAL, "hdmi gpio control enable failed\n");
goto bail_gpio_fail;
- }
+ }
+
+ hdmi_power_enabled = enable;
dprintf(SPEW, "HDMI Panel power %s done\n", enable ? "on" : "off");
@@ -813,6 +838,44 @@
pinfo->lcdc.dual_pipe = 0;
}
+static uint8_t mdss_hdmi_cable_status(void)
+{
+ uint32_t reg_val;
+ uint8_t cable_status;
+
+ mdss_hdmi_set_mode(true);
+
+ /* Enable USEC REF timer */
+ writel(0x0001001B, HDMI_USEC_REFTIMER);
+
+ /* set timeout to 4.1ms (max) for hardware debounce */
+ reg_val = readl(HDMI_HPD_CTRL) | 0x1FFF;
+
+ /* enable HPD circuit */
+ writel(reg_val | BIT(28), HDMI_HPD_CTRL);
+
+ writel(BIT(2) | BIT(1), HDMI_HPD_INT_CTRL);
+
+ /* Toggle HPD circuit to trigger HPD sense */
+ reg_val = readl(HDMI_HPD_CTRL) | 0x1FFF;
+ writel(reg_val & ~BIT(28), HDMI_HPD_CTRL);
+ writel(reg_val & BIT(28), HDMI_HPD_CTRL);
+
+ mdelay(20);
+
+ cable_status = (readl(HDMI_HPD_INT_STATUS) & BIT(1)) >> 1;
+
+ dprintf(INFO, "hdmi cable %s\n",
+ cable_status ? "connected" : "not connected");
+
+ writel(BIT(0), HDMI_HPD_INT_CTRL);
+ writel(reg_val & ~BIT(28), HDMI_HPD_CTRL);
+
+ mdss_hdmi_set_mode(false);
+
+ return cable_status;
+}
+
static int mdss_hdmi_update_panel_info(void)
{
mdss_hdmi_set_mode(true);