]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - tas2770sw-android/tas2770sw-android.git/blobdiff - tas2770-regmap.c
Support bitwidth change in IV data
[tas2770sw-android/tas2770sw-android.git] / tas2770-regmap.c
index 402d97320e2a5e09e98818143b26b0fdab7b61d4..e2b65b94bddbf97440a2d6d652fbbbe78442d99d 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_dbg(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;
@@ -351,7 +449,7 @@ static int tas2770_i2c_probe(struct i2c_client *client,
                dev_dbg(pTAS2770->dev, "irq = %d\n", pTAS2770->mnIRQ);
                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,