diff --git a/tas2557-regmap.c b/tas2557-regmap.c
index 5453d0275e81bb54505ae75fed528a508afb237c..e9befd485964fb0b47855756b5d42166b4194595 100755 (executable)
--- a/tas2557-regmap.c
+++ b/tas2557-regmap.c
}
end:
+ if (nResult < 0)
+ pTAS2557->mnErrCode |= ERROR_DEVA_I2C_COMM;
+ else
+ pTAS2557->mnErrCode &= ~ERROR_DEVA_I2C_COMM;
return nResult;
}
if (nResult < 0) {
dev_err(pTAS2557->dev, "%s, %d, I2C error %d\n",
__func__, __LINE__, nResult);
+ pTAS2557->mnErrCode |= ERROR_DEVA_I2C_COMM;
goto end;
- }
+ } else
+ pTAS2557->mnErrCode &= ~ERROR_DEVA_I2C_COMM;
*pValue = Value;
}
TAS2557_PAGE_ID(nRegister));
if (nResult >= 0) {
nResult = regmap_write(pTAS2557->mpRegmap, TAS2557_PAGE_REG(nRegister), nValue);
- if (nResult < 0)
+ if (nResult < 0) {
dev_err(pTAS2557->dev, "%s, %d, I2C error %d\n",
__func__, __LINE__, nResult);
+ pTAS2557->mnErrCode |= ERROR_DEVA_I2C_COMM;
+ } else
+ pTAS2557->mnErrCode &= ~ERROR_DEVA_I2C_COMM;
}
end:
TAS2557_PAGE_ID(nRegister));
if (nResult >= 0) {
nResult = regmap_bulk_read(pTAS2557->mpRegmap, TAS2557_PAGE_REG(nRegister), pData, nLength);
- if (nResult < 0)
+ if (nResult < 0) {
dev_err(pTAS2557->dev, "%s, %d, I2C error %d\n",
__func__, __LINE__, nResult);
+ pTAS2557->mnErrCode |= ERROR_DEVA_I2C_COMM;
+ } else
+ pTAS2557->mnErrCode &= ~ERROR_DEVA_I2C_COMM;
}
end:
TAS2557_PAGE_ID(nRegister));
if (nResult >= 0) {
nResult = regmap_bulk_write(pTAS2557->mpRegmap, TAS2557_PAGE_REG(nRegister), pData, nLength);
- if (nResult < 0)
+ if (nResult < 0) {
dev_err(pTAS2557->dev, "%s, %d, I2C error %d\n",
__func__, __LINE__, nResult);
+ pTAS2557->mnErrCode |= ERROR_DEVA_I2C_COMM;
+ } else
+ pTAS2557->mnErrCode &= ~ERROR_DEVA_I2C_COMM;
}
end:
TAS2557_PAGE_ID(nRegister));
if (nResult >= 0) {
nResult = regmap_update_bits(pTAS2557->mpRegmap, TAS2557_PAGE_REG(nRegister), nMask, nValue);
- if (nResult < 0)
+ if (nResult < 0) {
dev_err(pTAS2557->dev, "%s, %d, I2C error %d\n",
__func__, __LINE__, nResult);
+ pTAS2557->mnErrCode |= ERROR_DEVA_I2C_COMM;
+ } else
+ pTAS2557->mnErrCode &= ~ERROR_DEVA_I2C_COMM;
}
end:
}
-void tas2557_enableIRQ(struct tas2557_priv *pTAS2557, bool enable)
+void tas2557_enableIRQ(struct tas2557_priv *pTAS2557, bool enable, bool startup_chk)
{
if (enable) {
if (!pTAS2557->mbIRQEnable) {
- if (pTAS2557->mnIRQ != 0)
+ if (gpio_is_valid(pTAS2557->mnGpioINT)) {
enable_irq(pTAS2557->mnIRQ);
- pTAS2557->mbIRQEnable = true;
+ if (startup_chk) {
+ /* check after 10 ms */
+ schedule_delayed_work(&pTAS2557->irq_work, msecs_to_jiffies(10));
+ }
+ pTAS2557->mbIRQEnable = true;
+ }
}
} else {
- if (pTAS2557->mbIRQEnable) {
- if (pTAS2557->mnIRQ != 0)
- disable_irq_nosync(pTAS2557->mnIRQ);
- pTAS2557->mbIRQEnable = false;
- }
+ if (gpio_is_valid(pTAS2557->mnGpioINT))
+ disable_irq_nosync(pTAS2557->mnIRQ);
+ pTAS2557->mbIRQEnable = false;
}
}
pTAS2557->mnCurrentBook = -1;
pTAS2557->mnCurrentPage = -1;
+ if (pTAS2557->mnErrCode)
+ dev_info(pTAS2557->dev, "before reset, ErrCode=0x%x\n", pTAS2557->mnErrCode);
+ pTAS2557->mnErrCode = 0;
}
static void irq_work_routine(struct work_struct *work)
{
int nResult = 0;
unsigned int nDevInt1Status = 0, nDevInt2Status = 0;
- unsigned int nDevPowerUpFlag = 0, nDevPowerStatus = 0;
+ unsigned int nDevPowerUpFlag = 0;
+ int nCounter = 2;
struct tas2557_priv *pTAS2557 =
container_of(work, struct tas2557_priv, irq_work.work);
mutex_lock(&pTAS2557->file_lock);
#endif
- if (!pTAS2557->mbPowerUp)
+ if(pTAS2557->mnErrCode & ERROR_FAILSAFE)
+ goto program;
+
+ if (pTAS2557->mbRuntimeSuspend) {
+ dev_info(pTAS2557->dev, "%s, Runtime Suspended\n", __func__);
+ goto end;
+ }
+
+ if (!pTAS2557->mbPowerUp) {
+ dev_info(pTAS2557->dev, "%s, device not powered\n", __func__);
goto end;
+ }
+ if ((!pTAS2557->mpFirmware->mnConfigurations)
+ || (!pTAS2557->mpFirmware->mnPrograms)) {
+ dev_info(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
+ goto end;
+ }
+ nResult = tas2557_dev_write(pTAS2557, TAS2557_GPIO4_PIN_REG, 0x00);
+ if (nResult < 0)
+ goto program;
nResult = tas2557_dev_read(pTAS2557, TAS2557_FLAGS_1, &nDevInt1Status);
if (nResult >= 0)
nResult = tas2557_dev_read(pTAS2557, TAS2557_FLAGS_2, &nDevInt2Status);
-
if (nResult < 0)
goto program;
- if (((nDevInt1Status & 0xdc) != 0) || ((nDevInt2Status & 0x0c) != 0)) {
+ if (((nDevInt1Status & 0xfc) != 0) || ((nDevInt2Status & 0x0c) != 0)) {
/* in case of INT_OC, INT_UV, INT_OT, INT_BO, INT_CL, INT_CLK1, INT_CLK2 */
dev_err(pTAS2557->dev, "critical error: 0x%x, 0x%x\n", nDevInt1Status, nDevInt2Status);
+ if (nDevInt1Status & 0x80) {
+ pTAS2557->mnErrCode |= ERROR_OVER_CURRENT;
+ dev_err(pTAS2557->dev, "DEVA SPK over current!\n");
+ } else
+ pTAS2557->mnErrCode &= ~ERROR_OVER_CURRENT;
+
+ if (nDevInt1Status & 0x40) {
+ pTAS2557->mnErrCode |= ERROR_UNDER_VOLTAGE;
+ dev_err(pTAS2557->dev, "DEVA SPK under voltage!\n");
+ } else
+ pTAS2557->mnErrCode &= ~ERROR_UNDER_VOLTAGE;
+
+ if (nDevInt1Status & 0x20) {
+ pTAS2557->mnErrCode |= ERROR_CLK_HALT;
+ dev_err(pTAS2557->dev, "DEVA clk halted!\n");
+ } else
+ pTAS2557->mnErrCode &= ~ERROR_CLK_HALT;
+
+ if (nDevInt1Status & 0x10) {
+ pTAS2557->mnErrCode |= ERROR_DIE_OVERTEMP;
+ dev_err(pTAS2557->dev, "DEVA die over temperature!\n");
+ } else
+ pTAS2557->mnErrCode &= ~ERROR_DIE_OVERTEMP;
+
+ if (nDevInt1Status & 0x08) {
+ pTAS2557->mnErrCode |= ERROR_BROWNOUT;
+ dev_err(pTAS2557->dev, "DEVA brownout!\n");
+ } else
+ pTAS2557->mnErrCode &= ~ERROR_BROWNOUT;
+
+ if (nDevInt1Status & 0x04) {
+ pTAS2557->mnErrCode |= ERROR_CLK_LOST;
+ dev_err(pTAS2557->dev, "DEVA clock lost!\n");
+ } else
+ pTAS2557->mnErrCode &= ~ERROR_CLK_LOST;
+
+ if (nDevInt2Status & 0x08) {
+ pTAS2557->mnErrCode |= ERROR_CLK_DET1;
+ dev_err(pTAS2557->dev, "DEVA clk detection 1!\n");
+ } else
+ pTAS2557->mnErrCode &= ~ERROR_CLK_DET1;
+
+ if (nDevInt2Status & 0x04) {
+ pTAS2557->mnErrCode |= ERROR_CLK_DET2;
+ dev_err(pTAS2557->dev, "DEVA clk detection 2!\n");
+ } else
+ pTAS2557->mnErrCode &= ~ERROR_CLK_DET2;
+
goto program;
} else {
- nResult = tas2557_dev_read(pTAS2557, TAS2557_POWER_UP_FLAG_REG, &nDevPowerUpFlag);
- if (nResult < 0)
- goto program;
- if ((nDevPowerUpFlag & 0x40) == 0) {
- /* Class-D doesn't power on */
- nResult = tas2557_dev_read(pTAS2557, TAS2557_POWER_CTRL2_REG, &nDevPowerStatus);
+ dev_dbg(pTAS2557->dev, "IRQ Status: 0x%x, 0x%x\n", nDevInt1Status, nDevInt2Status);
+ nCounter = 2;
+ while (nCounter > 0) {
+ nResult = tas2557_dev_read(pTAS2557, TAS2557_POWER_UP_FLAG_REG, &nDevPowerUpFlag);
if (nResult < 0)
goto program;
- if (nDevPowerStatus & 0x80)
- goto program; /* failed to power on the Class-D */
+ if ((nDevPowerUpFlag & 0xc0) == 0xc0)
+ break;
+ nCounter--;
+ if (nCounter > 0) {
+ /* in case check pow status just after power on TAS2557 */
+ dev_dbg(pTAS2557->dev, "PowSts: 0x%x, check again after 10ms\n",
+ nDevPowerUpFlag);
+ msleep(10);
+ }
}
+ if ((nDevPowerUpFlag & 0xc0) != 0xc0) {
+ dev_err(pTAS2557->dev, "%s, Critical ERROR B[%d]_P[%d]_R[%d]= 0x%x\n",
+ __func__,
+ TAS2557_BOOK_ID(TAS2557_POWER_UP_FLAG_REG),
+ TAS2557_PAGE_ID(TAS2557_POWER_UP_FLAG_REG),
+ TAS2557_PAGE_REG(TAS2557_POWER_UP_FLAG_REG),
+ nDevPowerUpFlag);
+ pTAS2557->mnErrCode |= ERROR_CLASSD_PWR;
+ goto program;
+ }
+ pTAS2557->mnErrCode &= ~ERROR_CLASSD_PWR;
- dev_dbg(pTAS2557->dev, "%s: INT1=0x%x, INT2=0x%x; PowerUpFlag=0x%x, PwrStatus=0x%x\n",
- __func__, nDevInt1Status, nDevInt2Status, nDevPowerUpFlag, nDevPowerStatus);
+ dev_dbg(pTAS2557->dev, "%s: INT1=0x%x, INT2=0x%x; PowerUpFlag=0x%x\n",
+ __func__, nDevInt1Status, nDevInt2Status, nDevPowerUpFlag);
goto end;
}
program:
/* hardware reset and reload */
+ nResult = -1;
tas2557_set_program(pTAS2557, pTAS2557->mnCurrentProgram, pTAS2557->mnCurrentConfiguration);
end:
-
+ if (nResult >= 0) {
+ tas2557_dev_write(pTAS2557, TAS2557_GPIO4_PIN_REG, 0x07);
+ tas2557_enableIRQ(pTAS2557, true, false);
+ }
#ifdef CONFIG_TAS2557_MISC
mutex_unlock(&pTAS2557->file_lock);
#endif
{
struct tas2557_priv *pTAS2557 = (struct tas2557_priv *)dev_id;
- tas2557_enableIRQ(pTAS2557, false);
+ tas2557_enableIRQ(pTAS2557, false, false);
/* get IRQ status after 100 ms */
schedule_delayed_work(&pTAS2557->irq_work, msecs_to_jiffies(100));
return IRQ_HANDLED;
{
struct tas2557_priv *pTAS2557 = container_of(timer, struct tas2557_priv, mtimer);
- if (pTAS2557->mbPowerUp)
+ if (pTAS2557->mbPowerUp) {
schedule_work(&pTAS2557->mtimerwork);
+ if (gpio_is_valid(pTAS2557->mnGpioINT)) {
+ tas2557_enableIRQ(pTAS2557, false, false);
+ schedule_delayed_work(&pTAS2557->irq_work, msecs_to_jiffies(1));
+ }
+ }
return HRTIMER_NORESTART;
}
mutex_lock(&pTAS2557->file_lock);
#endif
+ if (pTAS2557->mbRuntimeSuspend) {
+ dev_info(pTAS2557->dev, "%s, Runtime Suspended\n", __func__);
+ goto end;
+ }
+
if (!pTAS2557->mpFirmware->mnConfigurations) {
dev_info(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
goto end;
if (!(pTAS2557->mnDieTvReadCounter % LOW_TEMPERATURE_COUNTER)) {
nAvg /= LOW_TEMPERATURE_COUNTER;
dev_dbg(pTAS2557->dev, "check : avg=%d\n", nAvg);
- if ((nAvg & 0x80000000) != 0) {
- /* if Die temperature is below ZERO */
+ if (nAvg < -6) {
+ /* if Die temperature is below -6 degree C */
if (pTAS2557->mnDevCurrentGain != LOW_TEMPERATURE_GAIN) {
nResult = tas2557_set_DAC_gain(pTAS2557, LOW_TEMPERATURE_GAIN);
if (nResult < 0)
#endif
}
-#ifdef CONFIG_PM_SLEEP
-static int tas2557_suspend(struct device *dev)
+static int tas2557_runtime_suspend(struct tas2557_priv *pTAS2557)
{
- struct tas2557_priv *pTAS2557 = dev_get_drvdata(dev);
-
dev_dbg(pTAS2557->dev, "%s\n", __func__);
+
+ pTAS2557->mbRuntimeSuspend = true;
+
if (hrtimer_active(&pTAS2557->mtimer)) {
dev_dbg(pTAS2557->dev, "cancel die temp timer\n");
hrtimer_cancel(&pTAS2557->mtimer);
}
+ if (work_pending(&pTAS2557->mtimerwork)) {
+ dev_dbg(pTAS2557->dev, "cancel timer work\n");
+ cancel_work_sync(&pTAS2557->mtimerwork);
+ }
+ if (gpio_is_valid(pTAS2557->mnGpioINT)) {
+ if (delayed_work_pending(&pTAS2557->irq_work)) {
+ dev_dbg(pTAS2557->dev, "cancel IRQ work\n");
+ cancel_delayed_work_sync(&pTAS2557->irq_work);
+ }
+ }
return 0;
}
-static int tas2557_resume(struct device *dev)
+static int tas2557_runtime_resume(struct tas2557_priv *pTAS2557)
{
- struct tas2557_priv *pTAS2557 = dev_get_drvdata(dev);
struct TProgram *pProgram;
dev_dbg(pTAS2557->dev, "%s\n", __func__);
goto end;
}
- if (pTAS2557->mnCurrentProgram >= pTAS2557->mpCalFirmware->mnPrograms) {
+ if (pTAS2557->mnCurrentProgram >= pTAS2557->mpFirmware->mnPrograms) {
dev_err(pTAS2557->dev, "%s, firmware corrupted\n", __func__);
goto end;
}
}
}
+ pTAS2557->mbRuntimeSuspend = false;
end:
return 0;
}
-#endif
static bool tas2557_volatile(struct device *pDev, unsigned int nRegister)
{
pTAS2557->set_config = tas2557_set_config;
pTAS2557->set_calibration = tas2557_set_calibration;
pTAS2557->hw_reset = tas2557_hw_reset;
+ pTAS2557->runtime_suspend = tas2557_runtime_suspend;
+ pTAS2557->runtime_resume = tas2557_runtime_resume;
+ pTAS2557->mnRestart = 0;
+ pTAS2557->mnEdge = 4;
mutex_init(&pTAS2557->dev_lock);
dev_dbg(pTAS2557->dev, "irq = %d\n", pTAS2557->mnIRQ);
INIT_DELAYED_WORK(&pTAS2557->irq_work, irq_work_routine);
nResult = request_threaded_irq(pTAS2557->mnIRQ, tas2557_irq_handler,
- NULL, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ NULL, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
pClient->name, pTAS2557);
if (nResult < 0) {
dev_err(pTAS2557->dev,
MODULE_DEVICE_TABLE(of, tas2557_of_match);
#endif
-#ifdef CONFIG_PM_SLEEP
-static const struct dev_pm_ops tas2557_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(tas2557_suspend, tas2557_resume)
-};
-#endif
-
static struct i2c_driver tas2557_i2c_driver = {
.driver = {
.name = "tas2557",
.owner = THIS_MODULE,
-#ifdef CONFIG_PM_SLEEP
- .pm = &tas2557_pm_ops,
-#endif
#if defined(CONFIG_OF)
.of_match_table = of_match_ptr(tas2557_of_match),
#endif
MODULE_DESCRIPTION("TAS2557 I2C Smart Amplifier driver");
MODULE_LICENSE("GPL v2");
-#endif
\ No newline at end of file
+#endif