]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - tas2770sw-android/tas2770sw-android.git/blobdiff - tas2770-regmap.c
Add IRQ enable
[tas2770sw-android/tas2770sw-android.git] / tas2770-regmap.c
index bee81288d6bb0564fca5f308b2a37a85835c23e2..c98cdc7e794bcd579f17df70c2857fe4d6d8f3f2 100644 (file)
@@ -129,9 +129,6 @@ void tas2770_enableIRQ(struct tas2770_priv *pTAS2770, bool enable)
                schedule_delayed_work(&pTAS2770->irq_work, msecs_to_jiffies(10));
                pTAS2770->mbIRQEnable = true;
        } else {
-               if (!pTAS2770->mbIRQEnable)
-                       return;
-
                if (gpio_is_valid(pTAS2770->mnIRQGPIO))
                        disable_irq_nosync(pTAS2770->mnIRQ);
                pTAS2770->mbIRQEnable = false;
@@ -142,7 +139,11 @@ static void irq_work_routine(struct work_struct *work)
 {
        struct tas2770_priv *pTAS2770 =
                container_of(work, struct tas2770_priv, irq_work.work);
+       unsigned int nDevInt1Status = 0, nDevInt2Status = 0;
+       int nCounter = 2;
+       int nResult = 0;
 
+       dev_info(pTAS2770->dev, "%s\n", __func__);
 #ifdef CONFIG_TAS2770_CODEC
        mutex_lock(&pTAS2770->codec_lock);
 #endif
@@ -152,11 +153,109 @@ static void irq_work_routine(struct work_struct *work)
                goto end;
        }
 
-       if (!pTAS2770->mbPowerUp) {
+       if (pTAS2770->mnPowerState == TAS2770_POWER_SHUTDOWN) {
                dev_info(pTAS2770->dev, "%s, device not powered\n", __func__);
                goto end;
        }
 
+       nResult = regmap_write(pTAS2770->regmap, TAS2770_InterruptMaskReg0,
+                               TAS2770_InterruptMaskReg0_Disable);
+       nResult = regmap_write(pTAS2770->regmap, TAS2770_InterruptMaskReg1,
+                               TAS2770_InterruptMaskReg1_Disable);
+
+       if (nResult < 0)
+               goto reload;
+
+       nResult = regmap_read(pTAS2770->regmap, TAS2770_LatchedInterruptReg0, &nDevInt1Status);
+       if (nResult >= 0)
+               nResult = regmap_read(pTAS2770->regmap, TAS2770_LatchedInterruptReg1, &nDevInt2Status);
+       else
+               goto reload;
+
+       dev_info(pTAS2770->dev, "IRQ status : 0x%x, 0x%x\n",
+                       nDevInt1Status, nDevInt2Status);
+
+       if (((nDevInt1Status & 0x3) != 0) || ((nDevInt2Status & 0x0f) != 0)) {
+               /* in case of INT_OC, INT_OT, INT_OVLT, INT_UVLT, INT_BO */
+
+               if (nDevInt1Status & TAS2770_LatchedInterruptReg0_OCEFlagSticky_Interrupt) {
+                       pTAS2770->mnErrCode |= ERROR_OVER_CURRENT;
+                       dev_err(pTAS2770->dev, "SPK over current!\n");
+               } else
+                       pTAS2770->mnErrCode &= ~ERROR_OVER_CURRENT;
+
+               if (nDevInt1Status & TAS2770_LatchedInterruptReg0_OTEFlagSticky_Interrupt) {
+                       pTAS2770->mnErrCode |= ERROR_DIE_OVERTEMP;
+                       dev_err(pTAS2770->dev, "die over temperature!\n");
+               } else
+                       pTAS2770->mnErrCode &= ~ERROR_DIE_OVERTEMP;
+
+               if (nDevInt2Status & TAS2770_LatchedInterruptReg1_VBATOVLOSticky_Interrupt) {
+                       pTAS2770->mnErrCode |= ERROR_OVER_VOLTAGE;
+                       dev_err(pTAS2770->dev, "SPK over voltage!\n");
+               } else
+                       pTAS2770->mnErrCode &= ~ERROR_UNDER_VOLTAGE;
+
+               if (nDevInt2Status & TAS2770_LatchedInterruptReg1_VBATUVLOSticky_Interrupt) {
+                       pTAS2770->mnErrCode |= ERROR_UNDER_VOLTAGE;
+                       dev_err(pTAS2770->dev, "SPK under voltage!\n");
+               } else
+                       pTAS2770->mnErrCode &= ~ERROR_UNDER_VOLTAGE;
+
+               if (nDevInt2Status & TAS2770_LatchedInterruptReg1_BrownOutFlagSticky_Interrupt) {
+                       pTAS2770->mnErrCode |= ERROR_BROWNOUT;
+                       dev_err(pTAS2770->dev, "brownout!\n");
+               } else
+                       pTAS2770->mnErrCode &= ~ERROR_BROWNOUT;
+
+               goto reload;
+       } else {
+               nCounter = 2;
+
+               while (nCounter > 0) {
+                       nResult = regmap_read(pTAS2770->regmap, TAS2770_PowerControl, &nDevInt1Status);
+                       if (nResult < 0)
+                               goto reload;
+
+                       if ((nDevInt1Status & TAS2770_PowerControl_OperationalMode10_Mask)
+                               != TAS2770_PowerControl_OperationalMode10_Shutdown)
+                               break;
+
+                       nCounter--;
+                       if (nCounter > 0) {
+                               /* in case check pow status just after power on TAS2770 */
+                               dev_dbg(pTAS2770->dev, "PowSts B: 0x%x, check again after 10ms\n",
+                                       nDevInt1Status);
+                               msleep(10);
+                       }
+               }
+
+               if ((nDevInt1Status & TAS2770_PowerControl_OperationalMode10_Mask)
+                       == TAS2770_PowerControl_OperationalMode10_Shutdown) {
+                       dev_err(pTAS2770->dev, "%s, Critical ERROR REG[0x%x] = 0x%x\n",
+                               __func__,
+                               TAS2770_PowerControl,
+                               nDevInt1Status);
+                       pTAS2770->mnErrCode |= ERROR_CLASSD_PWR;
+                       goto reload;
+               }
+               pTAS2770->mnErrCode &= ~ERROR_CLASSD_PWR;
+       }
+
+       nResult = regmap_write(pTAS2770->regmap, TAS2770_InterruptMaskReg0, 0xfc);
+       if (nResult < 0)
+               goto reload;
+
+       nResult = regmap_write(pTAS2770->regmap, TAS2770_InterruptMaskReg1, 0xb1);
+       if (nResult < 0)
+               goto reload;
+
+       goto end;
+
+reload:
+       /* hardware reset and reload */
+       tas2770_LoadConfig(pTAS2770);
+
 end:
 #ifdef CONFIG_TAS2770_CODEC
        mutex_unlock(&pTAS2770->codec_lock);
@@ -168,7 +267,7 @@ static enum hrtimer_restart timer_func(struct hrtimer *timer)
        struct tas2770_priv *pTAS2770 = container_of(timer,
                struct tas2770_priv, mtimer);
 
-       if (pTAS2770->mbPowerUp) {
+       if (pTAS2770->mnPowerState != TAS2770_POWER_SHUTDOWN) {
                if (!delayed_work_pending(&pTAS2770->irq_work))
                        schedule_delayed_work(&pTAS2770->irq_work,
                                msecs_to_jiffies(20));
@@ -215,13 +314,12 @@ static int tas2770_runtime_resume(struct tas2770_priv *pTAS2770)
 {
        dev_dbg(pTAS2770->dev, "%s\n", __func__);
 
-       if (pTAS2770->mbPowerUp) {
+       if (pTAS2770->mnPowerState != TAS2770_POWER_SHUTDOWN) {
                if (!hrtimer_active(&pTAS2770->mtimer)) {
                        hrtimer_start(&pTAS2770->mtimer,
                                ns_to_ktime((u64)CHECK_PERIOD * NSEC_PER_MSEC),
                                HRTIMER_MODE_REL);
                }
-
        }
 
        pTAS2770->mbRuntimeSuspend = false;
@@ -260,6 +358,42 @@ static int tas2770_parse_dt(struct device *dev, struct tas2770_priv *pTAS2770)
                dev_dbg(pTAS2770->dev, "ti,irq-gpio=%d", pTAS2770->mnIRQGPIO);
        }
 
+       of_property_read_u32(np, "ti,left-slot", &pTAS2770->mnLeftSlot);
+       if (rc) {
+               dev_err(pTAS2770->dev, "Looking up %s property in node %s failed %d\n",
+                       "ti,left-slot", np->full_name, rc);
+       } else {
+               dev_dbg(pTAS2770->dev, "ti,left-slot=%d",
+                       pTAS2770->mnLeftSlot);
+       }
+
+       of_property_read_u32(np, "ti,right-slot", &pTAS2770->mnRightSlot);
+       if (rc) {
+               dev_err(pTAS2770->dev, "Looking up %s property in node %s failed %d\n",
+                       "ti,right-slot", np->full_name, rc);
+       } else {
+               dev_dbg(pTAS2770->dev, "ti,right-slot=%d",
+                       pTAS2770->mnRightSlot);
+       }
+
+       of_property_read_u32(np, "ti,imon-slot-no", &pTAS2770->mnImon_slot_no);
+       if (rc) {
+               dev_err(pTAS2770->dev, "Looking up %s property in node %s failed %d\n",
+                       "ti,imon-slot-no", np->full_name, rc);
+       } else {
+               dev_dbg(pTAS2770->dev, "ti,imon-slot-no=%d",
+                       pTAS2770->mnImon_slot_no);
+       }
+
+       of_property_read_u32(np, "ti,vmon-slot-no", &pTAS2770->mnVmon_slot_no);
+       if (rc) {
+               dev_err(pTAS2770->dev, "Looking up %s property in node %s failed %d\n",
+                       "ti,vmon-slot-no", np->full_name, rc);
+       } else {
+               dev_dbg(pTAS2770->dev, "ti,vmon-slot-no=%d",
+                       pTAS2770->mnVmon_slot_no);
+       }
+
        return ret;
 }
 
@@ -275,12 +409,14 @@ static int tas2770_i2c_probe(struct i2c_client *client,
                sizeof(struct tas2770_priv), GFP_KERNEL);
        if (pTAS2770 == NULL) {
                nResult = -ENOMEM;
+               dev_info(&client->dev, "Failed to allocate i2c device\n");
                goto end;
        }
 
        pTAS2770->dev = &client->dev;
        i2c_set_clientdata(client, pTAS2770);
        dev_set_drvdata(&client->dev, pTAS2770);
+       pTAS2770->mnPowerState = TAS2770_POWER_SHUTDOWN;
 
        pTAS2770->regmap = devm_regmap_init_i2c(client, &tas2770_i2c_regmap);
        if (IS_ERR(pTAS2770->regmap)) {
@@ -312,10 +448,11 @@ static int tas2770_i2c_probe(struct i2c_client *client,
                }
                gpio_direction_input(pTAS2770->mnIRQGPIO);
                pTAS2770->mnIRQ = gpio_to_irq(pTAS2770->mnIRQGPIO);
-               dev_dbg(pTAS2770->dev, "irq = %d\n", pTAS2770->mnIRQ);
+               dev_info(pTAS2770->dev, "irq = %d\n", pTAS2770->mnIRQ);
+               INIT_DELAYED_WORK(&pTAS2770->irq_work, irq_work_routine);
                nResult = request_threaded_irq(pTAS2770->mnIRQ,
                                        tas2770_irq_handler, NULL,
-                                       IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+                                       IRQF_TRIGGER_LOW | IRQF_ONESHOT,
                                        client->name, pTAS2770);
                if (nResult < 0) {
                        dev_err(pTAS2770->dev,
@@ -323,13 +460,19 @@ static int tas2770_i2c_probe(struct i2c_client *client,
                        goto free_gpio;
                }
                disable_irq_nosync(pTAS2770->mnIRQ);
-               INIT_DELAYED_WORK(&pTAS2770->irq_work, irq_work_routine);
        }
 
        pTAS2770->hw_reset = tas2770_hw_reset;
        pTAS2770->enableIRQ = tas2770_enableIRQ;
        pTAS2770->runtime_suspend = tas2770_runtime_suspend;
        pTAS2770->runtime_resume = tas2770_runtime_resume;
+       pTAS2770->mnCh_size = 0;
+       pTAS2770->mnSlot_width = 0;
+
+       tas2770_hw_reset(pTAS2770);
+       regmap_write(pTAS2770->regmap, TAS2770_SoftwareReset,
+                       TAS2770_SoftwareReset_SoftwareReset_Reset);
+
        mutex_init(&pTAS2770->dev_lock);
        if (nResult < 0)
                goto destroy_mutex;