Merge "msm8974: mhl_sii8334: disable intrs in low-pwr"
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index fe10189..287f2cd 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -391,6 +391,10 @@
return rc;
}
+ if (hdmi_ctrl->mhl_max_pclk && hpd &&
+ (!hdmi_ctrl->mhl_hpd_on || hdmi_ctrl->hpd_feature_on))
+ return 0;
+
if (0 == hpd && hdmi_ctrl->hpd_feature_on) {
rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, false);
} else if (1 == hpd && !hdmi_ctrl->hpd_feature_on) {
@@ -2508,6 +2512,9 @@
return -EINVAL;
}
+ /* mhl status should override */
+ hdmi_ctrl->mhl_hpd_on = on;
+
if (!on && hdmi_ctrl->hpd_feature_on) {
rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, false);
} else if (on && !hdmi_ctrl->hpd_feature_on) {
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index ce3c00c..d4f8e67 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -62,6 +62,7 @@
u32 hpd_initialized;
u8 timing_gen_on;
u32 mhl_max_pclk;
+ u8 mhl_hpd_on;
struct completion hpd_done;
struct work_struct hpd_int_work;
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index a1053fb..9cae431 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -361,7 +361,7 @@
pr_debug("%s:%u\n", __func__, __LINE__);
INIT_COMPLETION(mhl_ctrl->rgnd_done);
timeout = wait_for_completion_interruptible_timeout
- (&mhl_ctrl->rgnd_done, HZ/2);
+ (&mhl_ctrl->rgnd_done, HZ);
if (!timeout) {
/* most likely nothing plugged in USB */
/* USB HOST connected or already in USB mode */
@@ -377,6 +377,12 @@
{
int rc;
struct mhl_tx_ctrl *mhl_ctrl = data;
+ struct i2c_client *client = mhl_ctrl->i2c_handle;
+ unsigned long flags;
+
+ enable_irq(client->irq);
+ /* wait for i2c interrupt line to be activated */
+ msleep(300);
if (id) {
/* When MHL cable is disconnected we get a sii8334
@@ -396,11 +402,16 @@
mhl_ctrl->notify_usb_online = usb_notify_cb;
if (!mhl_ctrl->disc_enabled) {
+ spin_lock_irqsave(&mhl_ctrl->lock, flags);
+ mhl_ctrl->tx_powered_off = false;
+ spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
mhl_sii_reset_pin(mhl_ctrl, 0);
msleep(50);
mhl_sii_reset_pin(mhl_ctrl, 1);
- /* TX PR-guide requires a 100 ms wait here */
- msleep(100);
+ /* chipset PR recommends waiting for at least 100 ms
+ * the chipset needs longer to come out of D3 state.
+ */
+ msleep(300);
mhl_init_reg_settings(mhl_ctrl, true);
rc = mhl_sii_wait_for_rgnd(mhl_ctrl);
} else {
@@ -690,8 +701,8 @@
MHL_SII_PAGE3_WR(0x3C, 0x80);
- if (mhl_ctrl->cur_state != POWER_STATE_D3)
- MHL_SII_REG_NAME_MOD(REG_INT_CTRL, BIT6 | BIT5 | BIT4, BIT4);
+ MHL_SII_REG_NAME_MOD(REG_INT_CTRL,
+ (BIT6 | BIT5 | BIT4), (BIT6 | BIT4));
/* Enable Auto Soft RESET */
MHL_SII_REG_NAME_WR(REG_SRST, 0x084);
@@ -858,11 +869,6 @@
static void mhl_msm_disconnection(struct mhl_tx_ctrl *mhl_ctrl)
{
struct i2c_client *client = mhl_ctrl->i2c_handle;
- unsigned long flags;
-
- spin_lock_irqsave(&mhl_ctrl->lock, flags);
- mhl_ctrl->dwnstream_hpd &= ~BIT6;
- spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
/* disabling Tx termination */
MHL_SII_REG_NAME_WR(REG_MHLTX_CTL1, 0xD0);
@@ -870,7 +876,7 @@
mhl_msc_clear(mhl_ctrl);
}
-static int mhl_msm_read_rgnd_int(struct mhl_tx_ctrl *mhl_ctrl)
+static int mhl_msm_read_rgnd_int(struct mhl_tx_ctrl *mhl_ctrl)
{
uint8_t rgnd_imp;
struct i2c_client *client = mhl_ctrl->i2c_handle;
@@ -967,12 +973,12 @@
if ((0x00 == status) &&\
(mhl_ctrl->cur_state == POWER_STATE_D3)) {
- pr_err("%s: invalid intr\n", __func__);
+ pr_warn("%s: invalid intr\n", __func__);
return 0;
}
if (0xFF == status) {
- pr_debug("%s: invalid intr 0xff\n", __func__);
+ pr_warn("%s: invalid intr 0xff\n", __func__);
MHL_SII_REG_NAME_WR(REG_INTR4, status);
return 0;
}
@@ -999,13 +1005,14 @@
power_supply_changed(&mhl_ctrl->mhl_psy);
if (mhl_ctrl->notify_usb_online)
mhl_ctrl->notify_usb_online(0);
- return -EACCES;
+ return 0;
}
if (status & BIT5) {
/* clr intr - reg int4 */
pr_debug("%s: mhl discon: int4 st=%02X\n", __func__,
(int)status);
+ mhl_ctrl->mhl_det_discon = true;
reg = MHL_SII_REG_NAME_RD(REG_INTR4);
MHL_SII_REG_NAME_WR(REG_INTR4, reg);
@@ -1013,7 +1020,7 @@
power_supply_changed(&mhl_ctrl->mhl_psy);
if (mhl_ctrl->notify_usb_online)
mhl_ctrl->notify_usb_online(0);
- return -EACCES;
+ return 0;
}
if ((mhl_ctrl->cur_state != POWER_STATE_D0_NO_MHL) &&\
@@ -1054,6 +1061,32 @@
MHL_SII_REG_NAME_WR(REG_INTR5, intr_5_stat);
}
+static void mhl_tx_down(struct mhl_tx_ctrl *mhl_ctrl)
+{
+ struct i2c_client *client = mhl_ctrl->i2c_handle;
+ unsigned long flags;
+ uint8_t reg;
+
+ switch_mode(mhl_ctrl, POWER_STATE_D3, true);
+
+ reg = MHL_SII_REG_NAME_RD(REG_INTR1);
+ MHL_SII_REG_NAME_WR(REG_INTR1, reg);
+
+ reg = MHL_SII_REG_NAME_RD(REG_INTR4);
+ MHL_SII_REG_NAME_WR(REG_INTR4, reg);
+
+ /* disable INTR1 and INTR4 */
+ MHL_SII_REG_NAME_MOD(REG_INTR1_MASK, BIT6, 0x0);
+ MHL_SII_REG_NAME_MOD(REG_INTR4_MASK,
+ (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6), 0x0);
+
+ MHL_SII_PAGE1_MOD(0x003D, BIT0, 0x00);
+ spin_lock_irqsave(&mhl_ctrl->lock, flags);
+ mhl_ctrl->tx_powered_off = true;
+ spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
+ pr_debug("%s: disabled\n", __func__);
+ disable_irq_nosync(client->irq);
+}
static void mhl_hpd_stat_isr(struct mhl_tx_ctrl *mhl_ctrl)
{
@@ -1085,20 +1118,24 @@
spin_lock_irqsave(&mhl_ctrl->lock, flags);
t = mhl_ctrl->dwnstream_hpd;
+ pr_debug("%s: %u: dwnstrm_hpd=0x%02x\n",
+ __func__, __LINE__, mhl_ctrl->dwnstream_hpd);
spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
if (BIT6 & (cbus_stat ^ t)) {
u8 status = cbus_stat & BIT6;
mhl_drive_hpd(mhl_ctrl, status ? HPD_UP : HPD_DOWN);
- if (!status) {
- MHL_SII_PAGE1_MOD(0x003D, BIT0, 0x00);
- spin_lock_irqsave(&mhl_ctrl->lock, flags);
- mhl_ctrl->tx_powered_off = true;
- spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
+ if (!status && mhl_ctrl->mhl_det_discon) {
+ pr_debug("%s:%u: power_down\n",
+ __func__, __LINE__);
+ mhl_tx_down(mhl_ctrl);
}
spin_lock_irqsave(&mhl_ctrl->lock, flags);
mhl_ctrl->dwnstream_hpd = cbus_stat;
+ pr_debug("%s: %u: dwnstrm_hpd=0x%02x\n",
+ __func__, __LINE__, mhl_ctrl->dwnstream_hpd);
spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
+ mhl_ctrl->mhl_det_discon = false;
}
}
}
@@ -1252,6 +1289,7 @@
uint8_t cmd_data = 0x0;
int msc_msg_recved = 0;
int rc = -1;
+ unsigned long flags;
struct i2c_client *client = mhl_ctrl->i2c_handle;
regval = MHL_SII_REG_NAME_RD(REG_CBUS_INTR_STATUS);
@@ -1292,6 +1330,14 @@
intr = MHL_SII_REG_NAME_RD(REG_CBUS_SET_INT_0);
MHL_SII_REG_NAME_WR(REG_CBUS_SET_INT_0, intr);
mhl_msc_recv_set_int(mhl_ctrl, 0, intr);
+ if (intr & MHL_INT_DCAP_CHG) {
+ /* No need to go to low power mode */
+ spin_lock_irqsave(&mhl_ctrl->lock, flags);
+ mhl_ctrl->dwnstream_hpd = 0x00;
+ pr_debug("%s: %u: dwnstrm_hpd=0x%02x\n",
+ __func__, __LINE__, mhl_ctrl->dwnstream_hpd);
+ spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
+ }
pr_debug("%s: MHL_INT_0 = %02x\n", __func__, intr);
intr = MHL_SII_REG_NAME_RD(REG_CBUS_SET_INT_1);
@@ -1337,8 +1383,18 @@
{
int rc;
struct mhl_tx_ctrl *mhl_ctrl = (struct mhl_tx_ctrl *)data;
+ unsigned long flags;
+
pr_debug("%s: Getting Interrupts\n", __func__);
+ spin_lock_irqsave(&mhl_ctrl->lock, flags);
+ if (mhl_ctrl->tx_powered_off) {
+ pr_warn("%s: powered off\n", __func__);
+ spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
+ return IRQ_HANDLED;
+ }
+ spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
+
/*
* Check RGND, MHL_EST, CBUS_LOCKOUT, SCDT
* interrupts. In D3, we get only RGND
@@ -1398,6 +1454,8 @@
*/
mhl_init_reg_settings(mhl_ctrl, true);
switch_mode(mhl_ctrl, POWER_STATE_D3, true);
+ pr_debug("%s:%u: power_down\n", __func__, __LINE__);
+ mhl_tx_down(mhl_ctrl);
return 0;
}
diff --git a/include/linux/mhl_8334.h b/include/linux/mhl_8334.h
index f04bf80..7297ff3 100644
--- a/include/linux/mhl_8334.h
+++ b/include/linux/mhl_8334.h
@@ -162,6 +162,7 @@
spinlock_t lock;
bool tx_powered_off;
uint8_t dwnstream_hpd;
+ bool mhl_det_discon;
};
int mhl_i2c_reg_read(struct i2c_client *client,