diff --git a/tas2770-regmap.c b/tas2770-regmap.c
index 7f9354e6f1f98c89f61f6d5d86c5569280774410..c98cdc7e794bcd579f17df70c2857fe4d6d8f3f2 100644 (file)
--- a/tas2770-regmap.c
+++ b/tas2770-regmap.c
/*
- * ALSA SoC Texas Instruments TAS2770 High Performance 4W Smart Amplifier
+ * ALSA SoC Texas Instruments TAS2770 20-W Digital Input Mono Class-D
+ * Audio Amplifier with Speaker I/V Sense
*
* Copyright (C) 2016 Texas Instruments, Inc.
*
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;
{
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
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);
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));
{
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;
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;
}
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)) {
}
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,
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;