msm_fb: HDMI: Update HPD logic to address HDMI PLL related issues

In the current implementation, the regulators pertaining to the
HDMI core are turned off/on as part of the configuration of the
HDP circuitry. As a result, the regulator that powers the HDMI
PLL is turned off before the HDMI clocks on the PLL are disabled.
This might lead to the PLL not getting locked when it is re-enabled.

This change turns on and off the regulators and clocks in proper
sequence.

CRs-Fixed: 360135
CRs-Fixed: 358598
Change-Id: Ie3630b543e78e83dc565edc32239935135ca4ca5
Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
This commit is contained in:
Ajay Singh Parmar 2012-06-07 12:25:31 +05:30 committed by Stephen Boyd
parent 47f6294083
commit 43435f6fe9
10 changed files with 307 additions and 106 deletions

View file

@ -293,12 +293,16 @@ static struct resource hdmi_msm_resources[] = {
static int hdmi_enable_5v(int on); static int hdmi_enable_5v(int on);
static int hdmi_core_power(int on, int show); static int hdmi_core_power(int on, int show);
static int hdmi_cec_power(int on); static int hdmi_cec_power(int on);
static int hdmi_gpio_config(int on);
static int hdmi_panel_power(int on);
static struct msm_hdmi_platform_data hdmi_msm_data = { static struct msm_hdmi_platform_data hdmi_msm_data = {
.irq = HDMI_IRQ, .irq = HDMI_IRQ,
.enable_5v = hdmi_enable_5v, .enable_5v = hdmi_enable_5v,
.core_power = hdmi_core_power, .core_power = hdmi_core_power,
.cec_power = hdmi_cec_power, .cec_power = hdmi_cec_power,
.panel_power = hdmi_panel_power,
.gpio_config = hdmi_gpio_config,
}; };
static struct platform_device hdmi_msm_device = { static struct platform_device hdmi_msm_device = {
@ -716,8 +720,22 @@ static struct msm_bus_scale_pdata dtv_bus_scale_pdata = {
static struct lcdc_platform_data dtv_pdata = { static struct lcdc_platform_data dtv_pdata = {
.bus_scale_table = &dtv_bus_scale_pdata, .bus_scale_table = &dtv_bus_scale_pdata,
.lcdc_power_save = hdmi_panel_power,
}; };
static int hdmi_panel_power(int on)
{
int rc;
pr_debug("%s: HDMI Core: %s\n", __func__, (on ? "ON" : "OFF"));
rc = hdmi_core_power(on, 1);
if (rc)
rc = hdmi_cec_power(on);
pr_debug("%s: HDMI Core: %s Success\n", __func__, (on ? "ON" : "OFF"));
return rc;
}
static int hdmi_enable_5v(int on) static int hdmi_enable_5v(int on)
{ {
/* TBD: PM8921 regulator instead of 8901 */ /* TBD: PM8921 regulator instead of 8901 */
@ -765,7 +783,6 @@ static int hdmi_core_power(int on, int show)
static struct regulator *reg_8921_lvs7, *reg_8921_s4, *reg_ext_3p3v; static struct regulator *reg_8921_lvs7, *reg_8921_s4, *reg_ext_3p3v;
static int prev_on; static int prev_on;
int rc; int rc;
int pmic_gpio14 = PM8921_GPIO_PM_TO_SYS(14);
if (on == prev_on) if (on == prev_on)
return 0; return 0;
@ -822,20 +839,61 @@ static int hdmi_core_power(int on, int show)
rc = regulator_enable(reg_ext_3p3v); rc = regulator_enable(reg_ext_3p3v);
if (rc) { if (rc) {
pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc); pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc);
return -ENODEV; return rc;
} }
rc = regulator_enable(reg_8921_lvs7); rc = regulator_enable(reg_8921_lvs7);
if (rc) { if (rc) {
pr_err("'%s' regulator enable failed, rc=%d\n", pr_err("'%s' regulator enable failed, rc=%d\n",
"hdmi_vdda", rc); "hdmi_vdda", rc);
return rc; goto error1;
} }
rc = regulator_enable(reg_8921_s4); rc = regulator_enable(reg_8921_s4);
if (rc) { if (rc) {
pr_err("'%s' regulator enable failed, rc=%d\n", pr_err("'%s' regulator enable failed, rc=%d\n",
"hdmi_lvl_tsl", rc); "hdmi_lvl_tsl", rc);
return rc; goto error2;
} }
pr_debug("%s(on): success\n", __func__);
} else {
rc = regulator_disable(reg_ext_3p3v);
if (rc) {
pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
return -ENODEV;
}
rc = regulator_disable(reg_8921_lvs7);
if (rc) {
pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
return -ENODEV;
}
rc = regulator_disable(reg_8921_s4);
if (rc) {
pr_err("disable reg_8921_s4 failed, rc=%d\n", rc);
return -ENODEV;
}
pr_debug("%s(off): success\n", __func__);
}
prev_on = on;
return 0;
error2:
regulator_disable(reg_8921_lvs7);
error1:
regulator_disable(reg_ext_3p3v);
return rc;
}
static int hdmi_gpio_config(int on)
{
int rc = 0;
static int prev_on;
int pmic_gpio14 = PM8921_GPIO_PM_TO_SYS(14);
if (on == prev_on)
return 0;
if (on) {
rc = gpio_request(HDMI_DDC_CLK_GPIO, "HDMI_DDC_CLK"); rc = gpio_request(HDMI_DDC_CLK_GPIO, "HDMI_DDC_CLK");
if (rc) { if (rc) {
pr_err("'%s'(%d) gpio_request failed, rc=%d\n", pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
@ -873,27 +931,10 @@ static int hdmi_core_power(int on, int show)
gpio_set_value_cansleep(pmic_gpio14, 1); gpio_set_value_cansleep(pmic_gpio14, 1);
gpio_free(pmic_gpio14); gpio_free(pmic_gpio14);
} }
rc = regulator_disable(reg_ext_3p3v);
if (rc) {
pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
return -ENODEV;
}
rc = regulator_disable(reg_8921_lvs7);
if (rc) {
pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
return -ENODEV;
}
rc = regulator_disable(reg_8921_s4);
if (rc) {
pr_err("disable reg_8921_s4 failed, rc=%d\n", rc);
return -ENODEV;
}
pr_debug("%s(off): success\n", __func__); pr_debug("%s(off): success\n", __func__);
} }
prev_on = on; prev_on = on;
return 0; return 0;
error4: error4:
@ -903,8 +944,6 @@ error3:
error2: error2:
gpio_free(HDMI_DDC_CLK_GPIO); gpio_free(HDMI_DDC_CLK_GPIO);
error1: error1:
regulator_disable(reg_8921_lvs7);
regulator_disable(reg_8921_s4);
return rc; return rc;
} }

View file

@ -516,12 +516,16 @@ static struct resource hdmi_msm_resources[] = {
static int hdmi_enable_5v(int on); static int hdmi_enable_5v(int on);
static int hdmi_core_power(int on, int show); static int hdmi_core_power(int on, int show);
static int hdmi_cec_power(int on); static int hdmi_cec_power(int on);
static int hdmi_gpio_config(int on);
static int hdmi_panel_power(int on);
static struct msm_hdmi_platform_data hdmi_msm_data = { static struct msm_hdmi_platform_data hdmi_msm_data = {
.irq = HDMI_IRQ, .irq = HDMI_IRQ,
.enable_5v = hdmi_enable_5v, .enable_5v = hdmi_enable_5v,
.core_power = hdmi_core_power, .core_power = hdmi_core_power,
.cec_power = hdmi_cec_power, .cec_power = hdmi_cec_power,
.panel_power = hdmi_panel_power,
.gpio_config = hdmi_gpio_config,
}; };
static struct platform_device hdmi_msm_device = { static struct platform_device hdmi_msm_device = {
@ -594,7 +598,21 @@ static struct msm_bus_scale_pdata dtv_bus_scale_pdata = {
static struct lcdc_platform_data dtv_pdata = { static struct lcdc_platform_data dtv_pdata = {
.bus_scale_table = &dtv_bus_scale_pdata, .bus_scale_table = &dtv_bus_scale_pdata,
.lcdc_power_save = hdmi_panel_power,
}; };
static int hdmi_panel_power(int on)
{
int rc;
pr_debug("%s: HDMI Core: %s\n", __func__, (on ? "ON" : "OFF"));
rc = hdmi_core_power(on, 1);
if (rc)
rc = hdmi_cec_power(on);
pr_debug("%s: HDMI Core: %s Success\n", __func__, (on ? "ON" : "OFF"));
return rc;
}
#endif #endif
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
@ -674,30 +692,8 @@ static int hdmi_core_power(int on, int show)
"hdmi_avdd", rc); "hdmi_avdd", rc);
return rc; return rc;
} }
rc = gpio_request(100, "HDMI_DDC_CLK");
if (rc) {
pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
"HDMI_DDC_CLK", 100, rc);
goto error1;
}
rc = gpio_request(101, "HDMI_DDC_DATA");
if (rc) {
pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
"HDMI_DDC_DATA", 101, rc);
goto error2;
}
rc = gpio_request(102, "HDMI_HPD");
if (rc) {
pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
"HDMI_HPD", 102, rc);
goto error3;
}
pr_debug("%s(on): success\n", __func__); pr_debug("%s(on): success\n", __func__);
} else { } else {
gpio_free(100);
gpio_free(101);
gpio_free(102);
rc = regulator_disable(reg_8038_l23); rc = regulator_disable(reg_8038_l23);
if (rc) { if (rc) {
pr_err("disable reg_8038_l23 failed, rc=%d\n", rc); pr_err("disable reg_8038_l23 failed, rc=%d\n", rc);
@ -714,13 +710,50 @@ static int hdmi_core_power(int on, int show)
prev_on = on; prev_on = on;
return 0; return 0;
}
static int hdmi_gpio_config(int on)
{
int rc = 0;
static int prev_on;
if (on == prev_on)
return 0;
if (on) {
rc = gpio_request(100, "HDMI_DDC_CLK");
if (rc) {
pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
"HDMI_DDC_CLK", 100, rc);
return rc;
}
rc = gpio_request(101, "HDMI_DDC_DATA");
if (rc) {
pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
"HDMI_DDC_DATA", 101, rc);
goto error1;
}
rc = gpio_request(102, "HDMI_HPD");
if (rc) {
pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
"HDMI_HPD", 102, rc);
goto error2;
}
pr_debug("%s(on): success\n", __func__);
} else {
gpio_free(100);
gpio_free(101);
gpio_free(102);
pr_debug("%s(off): success\n", __func__);
}
prev_on = on;
return 0;
error3:
gpio_free(101);
error2: error2:
gpio_free(100); gpio_free(101);
error1: error1:
regulator_disable(reg_8038_l23); gpio_free(100);
return rc; return rc;
} }

View file

@ -717,12 +717,16 @@ static struct resource hdmi_msm_resources[] = {
static int hdmi_enable_5v(int on); static int hdmi_enable_5v(int on);
static int hdmi_core_power(int on, int show); static int hdmi_core_power(int on, int show);
static int hdmi_cec_power(int on); static int hdmi_cec_power(int on);
static int hdmi_gpio_config(int on);
static int hdmi_panel_power(int on);
static struct msm_hdmi_platform_data hdmi_msm_data = { static struct msm_hdmi_platform_data hdmi_msm_data = {
.irq = HDMI_IRQ, .irq = HDMI_IRQ,
.enable_5v = hdmi_enable_5v, .enable_5v = hdmi_enable_5v,
.core_power = hdmi_core_power, .core_power = hdmi_core_power,
.cec_power = hdmi_cec_power, .cec_power = hdmi_cec_power,
.panel_power = hdmi_panel_power,
.gpio_config = hdmi_gpio_config,
}; };
static struct platform_device hdmi_msm_device = { static struct platform_device hdmi_msm_device = {
@ -784,7 +788,21 @@ static struct msm_bus_scale_pdata dtv_bus_scale_pdata = {
static struct lcdc_platform_data dtv_pdata = { static struct lcdc_platform_data dtv_pdata = {
.bus_scale_table = &dtv_bus_scale_pdata, .bus_scale_table = &dtv_bus_scale_pdata,
.lcdc_power_save = hdmi_panel_power,
}; };
static int hdmi_panel_power(int on)
{
int rc;
pr_debug("%s: HDMI Core: %s\n", __func__, (on ? "ON" : "OFF"));
rc = hdmi_core_power(on, 1);
if (rc)
rc = hdmi_cec_power(on);
pr_debug("%s: HDMI Core: %s Success\n", __func__, (on ? "ON" : "OFF"));
return rc;
}
#endif #endif
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
@ -885,30 +903,8 @@ static int hdmi_core_power(int on, int show)
"hdmi_vcc", rc); "hdmi_vcc", rc);
return rc; return rc;
} }
rc = gpio_request(100, "HDMI_DDC_CLK");
if (rc) {
pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
"HDMI_DDC_CLK", 100, rc);
goto error1;
}
rc = gpio_request(101, "HDMI_DDC_DATA");
if (rc) {
pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
"HDMI_DDC_DATA", 101, rc);
goto error2;
}
rc = gpio_request(102, "HDMI_HPD");
if (rc) {
pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
"HDMI_HPD", 102, rc);
goto error3;
}
pr_debug("%s(on): success\n", __func__); pr_debug("%s(on): success\n", __func__);
} else { } else {
gpio_free(100);
gpio_free(101);
gpio_free(102);
rc = regulator_disable(reg_8921_l23); rc = regulator_disable(reg_8921_l23);
if (rc) { if (rc) {
pr_err("disable reg_8921_l23 failed, rc=%d\n", rc); pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
@ -930,14 +926,50 @@ static int hdmi_core_power(int on, int show)
prev_on = on; prev_on = on;
return 0; return 0;
}
static int hdmi_gpio_config(int on)
{
int rc = 0;
static int prev_on;
if (on == prev_on)
return 0;
if (on) {
rc = gpio_request(100, "HDMI_DDC_CLK");
if (rc) {
pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
"HDMI_DDC_CLK", 100, rc);
return rc;
}
rc = gpio_request(101, "HDMI_DDC_DATA");
if (rc) {
pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
"HDMI_DDC_DATA", 101, rc);
goto error1;
}
rc = gpio_request(102, "HDMI_HPD");
if (rc) {
pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
"HDMI_HPD", 102, rc);
goto error2;
}
pr_debug("%s(on): success\n", __func__);
} else {
gpio_free(100);
gpio_free(101);
gpio_free(102);
pr_debug("%s(off): success\n", __func__);
}
prev_on = on;
return 0;
error3:
gpio_free(101);
error2: error2:
gpio_free(100); gpio_free(101);
error1: error1:
regulator_disable(reg_8921_l23); gpio_free(100);
regulator_disable(reg_8921_s4);
return rc; return rc;
} }

View file

@ -3083,13 +3083,17 @@ static struct resource hdmi_msm_resources[] = {
static int hdmi_enable_5v(int on); static int hdmi_enable_5v(int on);
static int hdmi_core_power(int on, int show); static int hdmi_core_power(int on, int show);
static int hdmi_gpio_config(int on);
static int hdmi_cec_power(int on); static int hdmi_cec_power(int on);
static int hdmi_panel_power(int on);
static struct msm_hdmi_platform_data hdmi_msm_data = { static struct msm_hdmi_platform_data hdmi_msm_data = {
.irq = HDMI_IRQ, .irq = HDMI_IRQ,
.enable_5v = hdmi_enable_5v, .enable_5v = hdmi_enable_5v,
.core_power = hdmi_core_power, .core_power = hdmi_core_power,
.cec_power = hdmi_cec_power, .cec_power = hdmi_cec_power,
.panel_power = hdmi_panel_power,
.gpio_config = hdmi_gpio_config,
}; };
static struct platform_device hdmi_msm_device = { static struct platform_device hdmi_msm_device = {
@ -9006,6 +9010,29 @@ static int hdmi_core_power(int on, int show)
"8058_l16", rc); "8058_l16", rc);
return rc; return rc;
} }
pr_debug("%s(on): success\n", __func__);
} else {
rc = regulator_disable(reg_8058_l16);
if (rc)
pr_warning("'%s' regulator disable failed, rc=%d\n",
"8058_l16", rc);
pr_debug("%s(off): success\n", __func__);
}
prev_on = on;
return 0;
}
static int hdmi_gpio_config(int on)
{
int rc = 0;
static int prev_on;
if (on == prev_on)
return 0;
if (on) {
rc = gpio_request(170, "HDMI_DDC_CLK"); rc = gpio_request(170, "HDMI_DDC_CLK");
if (rc) { if (rc) {
pr_err("'%s'(%d) gpio_request failed, rc=%d\n", pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
@ -9024,20 +9051,15 @@ static int hdmi_core_power(int on, int show)
"HDMI_HPD", 172, rc); "HDMI_HPD", 172, rc);
goto error3; goto error3;
} }
pr_info("%s(on): success\n", __func__); pr_debug("%s(on): success\n", __func__);
} else { } else {
gpio_free(170); gpio_free(170);
gpio_free(171); gpio_free(171);
gpio_free(172); gpio_free(172);
rc = regulator_disable(reg_8058_l16); pr_debug("%s(off): success\n", __func__);
if (rc)
pr_warning("'%s' regulator disable failed, rc=%d\n",
"8058_l16", rc);
pr_info("%s(off): success\n", __func__);
} }
prev_on = on; prev_on = on;
return 0; return 0;
error3: error3:
@ -9045,7 +9067,6 @@ error3:
error2: error2:
gpio_free(170); gpio_free(170);
error1: error1:
regulator_disable(reg_8058_l16);
return rc; return rc;
} }
@ -9094,6 +9115,18 @@ error:
return rc; return rc;
} }
static int hdmi_panel_power(int on)
{
int rc;
pr_debug("%s: HDMI Core: %s\n", __func__, (on ? "ON" : "OFF"));
rc = hdmi_core_power(on, 1);
if (rc)
rc = hdmi_cec_power(on);
pr_debug("%s: HDMI Core: %s Success\n", __func__, (on ? "ON" : "OFF"));
return rc;
}
#undef _GET_REGULATOR #undef _GET_REGULATOR
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */ #endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
@ -9516,6 +9549,7 @@ static struct msm_bus_scale_pdata dtv_bus_scale_pdata = {
static struct lcdc_platform_data dtv_pdata = { static struct lcdc_platform_data dtv_pdata = {
.bus_scale_table = &dtv_bus_scale_pdata, .bus_scale_table = &dtv_bus_scale_pdata,
.lcdc_power_save = hdmi_panel_power,
}; };
static struct msm_bus_paths dtv_hdmi_prim_bus_scale_usecases[] = { static struct msm_bus_paths dtv_hdmi_prim_bus_scale_usecases[] = {

View file

@ -97,6 +97,7 @@ int hdmi_pll_enable(void)
{ {
unsigned int val; unsigned int val;
u32 ahb_en_reg, ahb_enabled; u32 ahb_en_reg, ahb_enabled;
unsigned int timeout_count;
ahb_en_reg = readl_relaxed(AHB_EN_REG); ahb_en_reg = readl_relaxed(AHB_EN_REG);
ahb_enabled = ahb_en_reg & BIT(4); ahb_enabled = ahb_en_reg & BIT(4);
@ -110,6 +111,12 @@ int hdmi_pll_enable(void)
writel_relaxed(0x8D, HDMI_PHY_PLL_LOCKDET_CFG2); writel_relaxed(0x8D, HDMI_PHY_PLL_LOCKDET_CFG2);
writel_relaxed(0x10, HDMI_PHY_PLL_LOCKDET_CFG0); writel_relaxed(0x10, HDMI_PHY_PLL_LOCKDET_CFG0);
writel_relaxed(0x1A, HDMI_PHY_PLL_LOCKDET_CFG1); writel_relaxed(0x1A, HDMI_PHY_PLL_LOCKDET_CFG1);
/* Wait for a short time before de-asserting
* to allow the hardware to complete its job.
* This much of delay should be fine for hardware
* to assert and de-assert.
*/
udelay(10);
/* De-assert PLL S/W reset */ /* De-assert PLL S/W reset */
writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2); writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
@ -118,6 +125,11 @@ int hdmi_pll_enable(void)
/* Assert PHY S/W reset */ /* Assert PHY S/W reset */
writel_relaxed(val, HDMI_PHY_REG_12); writel_relaxed(val, HDMI_PHY_REG_12);
val &= ~BIT(5); val &= ~BIT(5);
/* Wait for a short time before de-asserting
to allow the hardware to complete its job.
This much of delay should be fine for hardware
to assert and de-assert. */
udelay(10);
/* De-assert PHY S/W reset */ /* De-assert PHY S/W reset */
writel_relaxed(val, HDMI_PHY_REG_12); writel_relaxed(val, HDMI_PHY_REG_12);
writel_relaxed(0x3f, HDMI_PHY_REG_2); writel_relaxed(0x3f, HDMI_PHY_REG_2);
@ -135,8 +147,32 @@ int hdmi_pll_enable(void)
writel_relaxed(val, HDMI_PHY_PLL_PWRDN_B); writel_relaxed(val, HDMI_PHY_PLL_PWRDN_B);
writel_relaxed(0x80, HDMI_PHY_REG_2); writel_relaxed(0x80, HDMI_PHY_REG_2);
while (!(readl_relaxed(HDMI_PHY_PLL_STATUS0) & BIT(0))) timeout_count = 1000;
cpu_relax(); while (!(readl_relaxed(HDMI_PHY_PLL_STATUS0) & BIT(0)) &&
timeout_count) {
if (--timeout_count == 0) {
/*
* PLL has still not locked.
* Do a software reset and try again
* Assert PLL S/W reset first
*/
writel_relaxed(0x8D, HDMI_PHY_PLL_LOCKDET_CFG2);
/* Wait for a short time before de-asserting
* to allow the hardware to complete its job.
* This much of delay should be fine for hardware
* to assert and de-assert.
*/
udelay(10);
writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
timeout_count = 1000;
pr_err("%s: PLL not locked after %d iterations\n",
__func__, timeout_count);
pr_err("%s: Asserting PLL S/W reset & trying again\n",
__func__);
}
}
if (!ahb_enabled) if (!ahb_enabled)
writel_relaxed(ahb_en_reg & ~BIT(4), AHB_EN_REG); writel_relaxed(ahb_en_reg & ~BIT(4), AHB_EN_REG);

View file

@ -485,6 +485,8 @@ struct msm_hdmi_platform_data {
int (*enable_5v)(int on); int (*enable_5v)(int on);
int (*core_power)(int on, int show); int (*core_power)(int on, int show);
int (*cec_power)(int on); int (*cec_power)(int on);
int (*panel_power)(int on);
int (*gpio_config)(int on);
int (*init_irq)(void); int (*init_irq)(void);
bool (*check_hdcp_hw_support)(void); bool (*check_hdcp_hw_support)(void);
}; };

View file

@ -1312,7 +1312,8 @@ void hdmi_msm_set_mode(boolean power_on)
/* HDMI_CTRL */ /* HDMI_CTRL */
HDMI_OUTP(0x0000, reg_val); HDMI_OUTP(0x0000, reg_val);
DEV_DBG("HDMI Core: %s\n", power_on ? "Enable" : "Disable"); DEV_DBG("HDMI Core: %s, HDMI_CTRL=0x%08x\n",
power_on ? "Enable" : "Disable", reg_val);
} }
static void msm_hdmi_init_ddc(void) static void msm_hdmi_init_ddc(void)
@ -4231,22 +4232,24 @@ static void hdmi_msm_hpd_read_work(struct work_struct *work)
static void hdmi_msm_hpd_off(void) static void hdmi_msm_hpd_off(void)
{ {
int rc = 0;
if (!hdmi_msm_state->hpd_initialized) { if (!hdmi_msm_state->hpd_initialized) {
DEV_DBG("%s: HPD is already OFF, returning\n", __func__); DEV_DBG("%s: HPD is already OFF, returning\n", __func__);
return; return;
} }
DEV_DBG("%s: (timer, clk, 5V, core, IRQ off)\n", __func__); DEV_DBG("%s: (timer, 5V, IRQ off)\n", __func__);
del_timer(&hdmi_msm_state->hpd_state_timer); del_timer(&hdmi_msm_state->hpd_state_timer);
disable_irq(hdmi_msm_state->irq); disable_irq(hdmi_msm_state->irq);
hdmi_msm_set_mode(FALSE); hdmi_msm_set_mode(FALSE);
hdmi_msm_state->hpd_initialized = FALSE;
hdmi_msm_powerdown_phy();
hdmi_msm_state->pd->cec_power(0);
hdmi_msm_state->pd->enable_5v(0); hdmi_msm_state->pd->enable_5v(0);
hdmi_msm_state->pd->core_power(0, 1);
hdmi_msm_clk(0); hdmi_msm_clk(0);
rc = hdmi_msm_state->pd->gpio_config(0);
if (rc != 0)
DEV_INFO("%s: Failed to disable GPIOs. Error=%d\n",
__func__, rc);
hdmi_msm_state->hpd_initialized = FALSE; hdmi_msm_state->hpd_initialized = FALSE;
} }
@ -4262,16 +4265,33 @@ static int hdmi_msm_hpd_on(bool trigger_handler)
{ {
static int phy_reset_done; static int phy_reset_done;
uint32 hpd_ctrl; uint32 hpd_ctrl;
int rc = 0;
if (hdmi_msm_state->hpd_initialized) { if (hdmi_msm_state->hpd_initialized) {
DEV_DBG("%s: HPD is already ON, returning\n", __func__); DEV_DBG("%s: HPD is already ON\n", __func__);
return 0; return 0;
} }
hdmi_msm_clk(1); rc = hdmi_msm_state->pd->gpio_config(1);
hdmi_msm_state->pd->core_power(1, 1); if (rc) {
hdmi_msm_state->pd->enable_5v(1); DEV_ERR("%s: Failed to enable GPIOs. Error=%d\n",
hdmi_msm_state->pd->cec_power(1); __func__, rc);
goto error1;
}
rc = hdmi_msm_clk(1);
if (rc) {
DEV_ERR("%s: Failed to enable clocks. Error=%d\n",
__func__, rc);
goto error2;
}
rc = hdmi_msm_state->pd->enable_5v(1);
if (rc) {
DEV_ERR("%s: Failed to enable 5V regulator. Error=%d\n",
__func__, rc);
goto error3;
}
hdmi_msm_dump_regs("HDMI-INIT: "); hdmi_msm_dump_regs("HDMI-INIT: ");
hdmi_msm_set_mode(FALSE); hdmi_msm_set_mode(FALSE);
@ -4279,6 +4299,7 @@ static int hdmi_msm_hpd_on(bool trigger_handler)
hdmi_phy_reset(); hdmi_phy_reset();
phy_reset_done = 1; phy_reset_done = 1;
} }
hdmi_msm_set_mode(TRUE);
/* HDMI_USEC_REFTIMER[0x0208] */ /* HDMI_USEC_REFTIMER[0x0208] */
HDMI_OUTP(0x0208, 0x0001001B); HDMI_OUTP(0x0208, 0x0001001B);
@ -4312,9 +4333,14 @@ static int hdmi_msm_hpd_on(bool trigger_handler)
hdmi_msm_state->hpd_initialized = TRUE; hdmi_msm_state->hpd_initialized = TRUE;
hdmi_msm_set_mode(TRUE);
return 0; return 0;
error3:
hdmi_msm_clk(0);
error2:
hdmi_msm_state->pd->gpio_config(0);
error1:
return rc;
} }
static int hdmi_msm_power_ctrl(boolean enable) static int hdmi_msm_power_ctrl(boolean enable)

View file

@ -137,6 +137,12 @@ static int dtv_on(struct platform_device *pdev)
clk_prepare_enable(ebi1_clk); clk_prepare_enable(ebi1_clk);
} }
#endif #endif
if (dtv_pdata && dtv_pdata->lcdc_power_save)
dtv_pdata->lcdc_power_save(1);
if (dtv_pdata && dtv_pdata->lcdc_gpio_config)
ret = dtv_pdata->lcdc_gpio_config(1);
mfd = platform_get_drvdata(pdev); mfd = platform_get_drvdata(pdev);
ret = clk_set_rate(tv_src_clk, mfd->fbi->var.pixclock); ret = clk_set_rate(tv_src_clk, mfd->fbi->var.pixclock);
@ -158,11 +164,6 @@ static int dtv_on(struct platform_device *pdev)
if (mdp_tv_clk) if (mdp_tv_clk)
clk_prepare_enable(mdp_tv_clk); clk_prepare_enable(mdp_tv_clk);
if (dtv_pdata && dtv_pdata->lcdc_power_save)
dtv_pdata->lcdc_power_save(1);
if (dtv_pdata && dtv_pdata->lcdc_gpio_config)
ret = dtv_pdata->lcdc_gpio_config(1);
ret = panel_next_on(pdev); ret = panel_next_on(pdev);
return ret; return ret;
} }

View file

@ -747,7 +747,6 @@ void hdmi_phy_reset(void)
void hdmi_msm_reset_core(void) void hdmi_msm_reset_core(void)
{ {
hdmi_msm_set_mode(FALSE);
hdmi_msm_clk(0); hdmi_msm_clk(0);
udelay(5); udelay(5);
hdmi_msm_clk(1); hdmi_msm_clk(1);

View file

@ -548,7 +548,6 @@ void hdmi_phy_reset(void)
void hdmi_msm_reset_core(void) void hdmi_msm_reset_core(void)
{ {
hdmi_msm_set_mode(FALSE);
hdmi_msm_clk(0); hdmi_msm_clk(0);
udelay(5); udelay(5);
hdmi_msm_clk(1); hdmi_msm_clk(1);