1. IRQ use Level trigger
authorPeter Li <a0220410@ti.com>
Sun, 26 Mar 2017 08:24:36 +0000 (16:24 +0800)
committerPeter Li <a0220410@ti.com>
Sun, 26 Mar 2017 08:24:36 +0000 (16:24 +0800)
2. add clock error detection
3. prepare for PPC3 TAS2557 app driver version 0x300 update

tas2557-codec.c
tas2557-core.c
tas2557-core.h
tas2557-misc.c
tas2557-regmap.c
tas2557.h

index 0650da94e46cb7a70f344532af0c5c2d9c79316d..2bd6fb462d2075703ff628dbbc488fb06b40db73 100755 (executable)
@@ -426,6 +426,55 @@ static DECLARE_TLV_DB_SCALE(dac_tlv, 0, 100, 0);
 
        
 
+static const char * const chl_setup_text[] = {
+       "default",
+       "DevA-Mute",
+       "DevA-Left",
+       "DevA-Right",
+       "DevA-MonoMix"
+};
+static const struct soc_enum chl_setup_enum[] = {
+       SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(chl_setup_text), chl_setup_text),
+};
+
+static int tas2557_dsp_chl_setup_get(struct snd_kcontrol *pKcontrol,
+                       struct snd_ctl_elem_value *pValue)
+{
+#ifdef KCONTROL_CODEC
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
+#else
+       struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
+#endif
+       struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
+
+       mutex_lock(&pTAS2557->codec_lock);
+
+       pValue->value.integer.value[0] = pTAS2557->mnChannelState;
+
+       mutex_unlock(&pTAS2557->codec_lock);
+
+       return 0;
+}
+
+static int tas2557_dsp_chl_setup_put(struct snd_kcontrol *pKcontrol,
+                       struct snd_ctl_elem_value *pValue)
+{
+#ifdef KCONTROL_CODEC
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
+#else
+       struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
+#endif
+       struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
+       int channel_state = pValue->value.integer.value[0];
+
+       mutex_lock(&pTAS2557->codec_lock);
+
+       tas2557_SA_DevChnSetup(pTAS2557, channel_state);
+
+       mutex_unlock(&pTAS2557->codec_lock);
+       return 0;
+}
+
 static const struct snd_kcontrol_new tas2557_snd_controls[] = {
        SOC_SINGLE_TLV("DAC Playback Volume", TAS2557_SPK_CTRL_REG, 3, 0x0f, 0,
                dac_tlv),
@@ -439,6 +488,8 @@ static const struct snd_kcontrol_new tas2557_snd_controls[] = {
                tas2557_fs_get, tas2557_fs_put),
        SOC_SINGLE_EXT("Calibration", SND_SOC_NOPM, 0, 0x00FF, 0,
                tas2557_calibration_get, tas2557_calibration_put),
+       SOC_ENUM_EXT("DSPChl Setup", chl_setup_enum[0],
+               tas2557_dsp_chl_setup_get, tas2557_dsp_chl_setup_put),
 };
 
 static struct snd_soc_codec_driver soc_codec_driver_tas2557 = {
index d7d5bbbd8a9b8f37fd62f75a67f758ce09a63669..4bc1cfa19a9d4b5bb5175587be25f2c4354d291e 100755 (executable)
@@ -41,7 +41,9 @@
 #include "tas2557.h"
 #include "tas2557-core.h"
 
-#define PPC_DRIVER_VERSION                     0x00000200
+#define PPC_DRIVER_CRCCHK                      0x00000200
+#define PPC_DRIVER_CONFDEV                     0x00000300
+
 #define TAS2557_CAL_NAME    "/data/tas2557_cal.bin"
 
 
@@ -70,20 +72,20 @@ static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
 
 static unsigned int p_tas2557_default_data[] = {
        TAS2557_SAR_ADC2_REG, 0x05,     /* enable SAR ADC */
-/*TODO TAS2555_CLK_ERR_CTRL2, 0x39,    enable clock error detection on PLL */
-/*TODO TAS2555_CLK_ERR_CTRL3, 0x11,    enable clock error detection on PLL */
+       TAS2557_CLK_ERR_CTRL2, 0x21,    /*clk1:clock hysteresis, 0.34ms; clock halt, 22ms*/
+       TAS2557_CLK_ERR_CTRL3, 0x21,    /*clk2: rampDown 15dB/us, clock hysteresis, 10.66us; clock halt, 22ms */
        TAS2557_SAFE_GUARD_REG, TAS2557_SAFE_GUARD_PATTERN,     /* safe guard */
        0xFFFFFFFF, 0xFFFFFFFF
 };
 
 static unsigned int p_tas2557_irq_config[] = {
-/*     TAS2555_CLK_HALT_REG, 0x71,      TODO */
+       TAS2557_CLK_HALT_REG, 0x71,     /* enable clk halt detect2 interrupt */
        TAS2557_INT_GEN1_REG, 0x11,     /* enable spk OC and OV */
        TAS2557_INT_GEN2_REG, 0x11,     /* enable clk err1 and die OT */
        TAS2557_INT_GEN3_REG, 0x11,     /* enable clk err2 and brownout */
        TAS2557_INT_GEN4_REG, 0x01,     /* disable SAR, enable clk halt */
-       TAS2557_INT_MODE_REG, 0x80,     /* active high until INT_STICKY_1 and INT_STICKY_2 are read to be cleared. */
        TAS2557_GPIO4_PIN_REG, 0x07,    /* set GPIO4 as int1, default */
+       TAS2557_INT_MODE_REG, 0x80,     /* active high until INT_STICKY_1 and INT_STICKY_2 are read to be cleared. */
        0xFFFFFFFF, 0xFFFFFFFF
 };
 
@@ -91,12 +93,11 @@ static unsigned int p_tas2557_startup_data[] = {
        TAS2557_GPI_PIN_REG, 0x15,      /* enable DIN, MCLK, CCI */
        TAS2557_GPIO1_PIN_REG, 0x01,    /* enable BCLK */
        TAS2557_GPIO2_PIN_REG, 0x01,    /* enable WCLK */
-       TAS2557_CLK_ERR_CTRL, 0x00,      /* enable clock error detection */
        TAS2557_POWER_CTRL2_REG, 0xA0,   /* Class-D, Boost power up */
        TAS2557_POWER_CTRL2_REG, 0xA3,   /* Class-D, Boost, IV sense power up */
        TAS2557_POWER_CTRL1_REG, 0xF8,   /* PLL, DSP, clock dividers power up */
-       TAS2557_UDELAY, 2000,            /* delay */
-/*     TAS2557_CLK_ERR_CTRL, 0x03,      TODO  enable clock error detection */
+       TAS2557_UDELAY, 2000,           /* delay */
+       TAS2557_CLK_ERR_CTRL, 0x03,     /* enable clock error detection */
        0xFFFFFFFF, 0xFFFFFFFF
 };
 
@@ -121,13 +122,6 @@ static unsigned int p_tas2557_shutdown_data[] = {
        0xFFFFFFFF, 0xFFFFFFFF
 };
 
-static unsigned int p_tas2557_mute_DSP_down_data[] = {
-       TAS2557_MUTE_REG, 0x03,          /* mute */
-       TAS2557_POWER_CTRL1_REG, 0x60,   /* DSP power down */
-       TAS2557_UDELAY, 0xFF,            /* delay */
-       0xFFFFFFFF, 0xFFFFFFFF
-};
-
 static int tas2557_dev_load_data(struct tas2557_priv *pTAS2557,
        unsigned int *pData)
 {
@@ -156,6 +150,79 @@ int tas2557_configIRQ(struct tas2557_priv *pTAS2557)
        return tas2557_dev_load_data(pTAS2557, p_tas2557_irq_config);
 }
 
+/*
+* for PG2.1 Dual Mono
+*/
+int tas2557_SA_DevChnSetup(struct tas2557_priv *pTAS2557, unsigned int mode)
+{
+       int nResult = 0;
+       struct TProgram *pProgram;
+       unsigned char buf_mute[16] = {0};
+       unsigned char buf_DevA_Left[16] = {0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+       unsigned char buf_DevA_Right[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0, 0, 0, 0, 0, 0, 0};
+       unsigned char buf_DevA_MonoMix[16] = {0x20, 0, 0, 0, 0, 0, 0, 0, 0x20, 0, 0, 0, 0, 0, 0, 0};
+       unsigned char *pDevABuf;
+
+       dev_dbg(pTAS2557->dev, "%s, mode %d\n", __func__, mode);
+       if ((pTAS2557->mpFirmware->mnPrograms == 0)
+               || (pTAS2557->mpFirmware->mnConfigurations == 0)) {
+               dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
+               goto end;
+       }
+
+       pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
+       if (pProgram->mnAppMode != TAS2557_APP_TUNINGMODE) {
+               dev_err(pTAS2557->dev, "%s, not tuning mode\n", __func__);
+               goto end;
+       }
+
+       if (pTAS2557->mnPGID != TAS2557_PG_VERSION_2P1) {
+               dev_err(pTAS2557->dev, "%s, currently we only support PG2.1\n", __func__);
+               goto end;
+       }
+
+       if (pTAS2557->mbLoadConfigurationPrePowerUp) {
+               dev_dbg(pTAS2557->dev, "%s, setup channel after coeff update\n", __func__);
+               pTAS2557->mnChannelState = mode;
+               goto end;
+       }
+
+       switch (mode) {
+       case TAS2557_DEVA_CHL_DEFAULT:
+       pDevABuf = pTAS2557->mnDevAChlData;
+       break;
+
+       case TAS2557_DEVA_CHL_MUTE:
+       pDevABuf = buf_mute;
+       break;
+
+       case TAS2557_DEVA_CHL_LEFT:
+       pDevABuf = buf_DevA_Left;
+       break;
+
+       case TAS2557_DEVA_CHL_RIGHT:
+       pDevABuf = buf_DevA_Right;
+       break;
+
+       case TAS2557_DEVA_CHL_MONOMIX:
+       pDevABuf = buf_DevA_MonoMix;
+       break;
+       default:
+       break;
+       }
+
+       if (pDevABuf) {
+               nResult = pTAS2557->bulk_write(pTAS2557, TAS2557_SA_PG2P1_CHL_CTRL_REG, pDevABuf, 16);
+               if (nResult < 0)
+                       goto end;
+               pTAS2557->mnChannelState = mode;
+       }
+
+end:
+
+       return nResult;
+}
+
 int tas2557_set_bit_rate(struct tas2557_priv *pTAS2557, unsigned int nBitRate)
 {
        int ret = 0, n = -1;
@@ -287,6 +354,10 @@ end:
 static void failsafe(struct tas2557_priv *pTAS2557)
 {
        dev_err(pTAS2557->dev, "%s\n", __func__);
+       pTAS2557->mnErrCode |= ERROR_FAILSAFE;
+       if (hrtimer_active(&pTAS2557->mtimer))
+               hrtimer_cancel(&pTAS2557->mtimer);
+       pTAS2557->enableIRQ(pTAS2557, false);
        tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
        pTAS2557->mbPowerUp = false;
        pTAS2557->hw_reset(pTAS2557);
@@ -297,6 +368,15 @@ static void failsafe(struct tas2557_priv *pTAS2557)
                tas2557_clear_firmware(pTAS2557->mpFirmware);
 }
 
+int tas2557_checkPLL(struct tas2557_priv *pTAS2557)
+{
+       int nResult = 0;
+/*
+* TO DO
+*/
+
+       return nResult;
+}
 
 /*
 * tas2557_load_coefficient
@@ -329,7 +409,7 @@ static int tas2557_load_coefficient(struct tas2557_priv *pTAS2557,
                pPrevConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nPrevConfig]);
 
        pNewConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nNewConfig]);
-
+       pTAS2557->mnCurrentConfiguration = nNewConfig;
        if (pPrevConfiguration) {
                if (pPrevConfiguration->mnPLL == pNewConfiguration->mnPLL) {
                        dev_dbg(pTAS2557->dev, "%s, PLL same\n", __func__);
@@ -346,7 +426,7 @@ static int tas2557_load_coefficient(struct tas2557_priv *pTAS2557,
                if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)
                        pTAS2557->enableIRQ(pTAS2557, false);
 
-               nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_mute_DSP_down_data);
+               nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
                if (nResult < 0)
                        goto end;
                bRestorePower = true;
@@ -360,6 +440,7 @@ static int tas2557_load_coefficient(struct tas2557_priv *pTAS2557,
        if (nResult < 0)
                goto end;
        pTAS2557->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
+
        dev_dbg(pTAS2557->dev, "load configuration %s conefficient pre block\n",
                pNewConfiguration->mpName);
        nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData), TAS2557_BLOCK_CFG_PRE_DEV_A);
@@ -373,7 +454,17 @@ prog_coefficient:
                TAS2557_BLOCK_CFG_COEFF_DEV_A);
        if (nResult < 0)
                goto end;
-       pTAS2557->mnCurrentConfiguration = nNewConfig;
+       if (pTAS2557->mnChannelState == TAS2557_DEVA_CHL_DEFAULT) {
+               nResult = pTAS2557->bulk_read(pTAS2557,
+                       TAS2557_SA_PG2P1_CHL_CTRL_REG, pTAS2557->mnDevAChlData, 16);
+               if (nResult < 0)
+                       goto end;
+       } else {
+               nResult = tas2557_SA_DevChnSetup(pTAS2557, pTAS2557->mnChannelState);
+               if (nResult < 0)
+                       goto end;
+       }
+
        if (pTAS2557->mpCalFirmware->mnCalibrations) {
                pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[pTAS2557->mnCurrentCalibration]);
                dev_dbg(pTAS2557->dev, "load calibration\n");
@@ -389,6 +480,12 @@ prog_coefficient:
                nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
                if (nResult < 0)
                        goto end;
+               nResult = tas2557_checkPLL(pTAS2557);
+               if (nResult < 0) {
+                       nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
+                       pTAS2557->mbPowerUp = false;
+                       goto end;
+               }
                dev_dbg(pTAS2557->dev,
                        "device powered up, load unmute\n");
                nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
@@ -410,8 +507,7 @@ end:
 
 int tas2557_enable(struct tas2557_priv *pTAS2557, bool bEnable)
 {
-       int nResult = 0, nRetry = 10;
-       unsigned char nBuf[4];
+       int nResult = 0;
        unsigned int nValue;
        struct TProgram *pProgram;
 
@@ -444,45 +540,19 @@ int tas2557_enable(struct tas2557_priv *pTAS2557, bool bEnable)
                                pTAS2557->mbLoadConfigurationPrePowerUp = false;
                        }
 
-                       if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
-                               dev_dbg(pTAS2557->dev, "Tuning mode, check PLL\n");
-                               /* check PLL */
-pllcheck:
-                               nResult = pTAS2557->write(pTAS2557, TAS2557_POWER_CTRL1_REG, 0xf8);
-                               if (nResult < 0)
-                                       goto end;
-                               msleep(2);
-                               /* check TAS2557 */
-                               memset(nBuf, 0, 4);
-                               nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_XMEM_44_REG, nBuf, 4);
-                               if (nResult < 0)
-                                       goto end;
-                               nValue = ((unsigned int)nBuf[0] << 24) | ((unsigned int)nBuf[1] << 16) | ((unsigned int)nBuf[2] << 8) | nBuf[3];
-                               if (nValue == 0) {
-                                       nResult = pTAS2557->write(pTAS2557, TAS2557_POWER_CTRL1_REG, 0x60);
-                                       if (nResult < 0)
-                                               goto end;
-                                       msleep(2);
-                                       nResult = pTAS2557->write(pTAS2557, TAS2557_POWER_CTRL1_REG, 0x00);
-                                       if (nResult < 0)
-                                               goto end;
-                                       msleep(2);
-                                       nRetry--;
-                                       nResult = -EAGAIN;
-                                       if (nRetry == 0)
-                                               goto end;
-
-                                       dev_info(pTAS2557->dev, "PLL is absent, check again %d\n", nRetry);
-                                       goto pllcheck;
-                               }
-                       }
-
                        pTAS2557->clearIRQ(pTAS2557);
                        /* power on device */
                        dev_dbg(pTAS2557->dev, "Enable: load startup sequence\n");
                        nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
                        if (nResult < 0)
                                goto end;
+                       if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
+                               nResult = tas2557_checkPLL(pTAS2557);
+                               if (nResult < 0) {
+                                       nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
+                                       goto end;
+                               }
+                       }
                        dev_dbg(pTAS2557->dev, "Enable: load unmute sequence\n");
                        nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
                        if (nResult < 0)
@@ -521,11 +591,8 @@ pllcheck:
 
 end:
        if (nResult < 0) {
-               if (nRetry == 0)
-                       dev_err(pTAS2557->dev, "PLL is absent and enable timeout\n");
-               else
-                       dev_err(pTAS2557->dev, "enable failure %d\n", nResult);
-               failsafe(pTAS2557);
+               if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
+                       failsafe(pTAS2557);
        }
 
        return nResult;
@@ -533,9 +600,9 @@ end:
 
 int tas2557_set_sampling_rate(struct tas2557_priv *pTAS2557, unsigned int nSamplingRate)
 {
+       int nResult = 0;
        struct TConfiguration *pConfiguration;
        unsigned int nConfiguration;
-       int nResult = 0;
 
        dev_dbg(pTAS2557->dev, "tas2557_setup_clocks: nSamplingRate = %d [Hz]\n",
                nSamplingRate);
@@ -645,7 +712,8 @@ static int fw_parse_header(struct tas2557_priv *pTAS2557,
        pFirmware->mnDeviceFamily = fw_convert_number(pData);
        pData += 4;
        if (pFirmware->mnDeviceFamily != 0) {
-               dev_err(pTAS2557->dev, "deviceFamily %d, not TAS device", pFirmware->mnDeviceFamily);
+               dev_err(pTAS2557->dev,
+                       "deviceFamily %d, not TAS device", pFirmware->mnDeviceFamily);
                return -EINVAL;
        }
 
@@ -653,7 +721,8 @@ static int fw_parse_header(struct tas2557_priv *pTAS2557,
        pData += 4;
 
        if (pFirmware->mnDevice != 2) {
-               dev_err(pTAS2557->dev, "device %d, not TAS2557", pFirmware->mnDevice);
+               dev_err(pTAS2557->dev,
+                       "device %d, not TAS2557 Dual Mono", pFirmware->mnDevice);
                return -EINVAL;
        }
 
@@ -670,7 +739,7 @@ static int fw_parse_block_data(struct tas2557_priv *pTAS2557, struct TFirmware *
        pBlock->mnType = fw_convert_number(pData);
        pData += 4;
 
-       if (pFirmware->mnDriverVersion >= PPC_DRIVER_VERSION) {
+       if (pFirmware->mnDriverVersion >= PPC_DRIVER_CRCCHK) {
                pBlock->mbPChkSumPresent = pData[0];
                pData++;
 
@@ -693,7 +762,6 @@ static int fw_parse_block_data(struct tas2557_priv *pTAS2557, struct TFirmware *
        n = pBlock->mnCommands * 4;
        pBlock->mpData = kmemdup(pData, n, GFP_KERNEL);
        pData += n;
-
        return pData - pDataStart;
 }
 
@@ -716,12 +784,12 @@ static int fw_parse_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmw
 
        pImageData->mpBlocks =
                kmalloc(sizeof(struct TBlock) * pImageData->mnBlocks, GFP_KERNEL);
+
        for (nBlock = 0; nBlock < pImageData->mnBlocks; nBlock++) {
                n = fw_parse_block_data(pTAS2557, pFirmware,
                        &(pImageData->mpBlocks[nBlock]), pData);
                pData += n;
        }
-
        return pData - pDataStart;
 }
 
@@ -815,7 +883,8 @@ static int fw_parse_configuration_data(struct tas2557_priv *pTAS2557,
        pFirmware->mpConfigurations =
                kmalloc(sizeof(struct TConfiguration) * pFirmware->mnConfigurations,
                GFP_KERNEL);
-       for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations; nConfiguration++) {
+       for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations;
+               nConfiguration++) {
                pConfiguration = &(pFirmware->mpConfigurations[nConfiguration]);
                memcpy(pConfiguration->mpName, pData, 64);
                pData += 64;
@@ -824,6 +893,11 @@ static int fw_parse_configuration_data(struct tas2557_priv *pTAS2557,
                pConfiguration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
                pData += n + 1;
 
+               if (pFirmware->mnDriverVersion >= PPC_DRIVER_CONFDEV) {
+                       pConfiguration->mnDevices = (pData[0] << 8) + pData[1];
+                       pData += 2;
+               }
+
                pConfiguration->mnProgram = pData[0];
                pData++;
 
@@ -858,7 +932,9 @@ int fw_parse_calibration_data(struct tas2557_priv *pTAS2557,
 
        pFirmware->mpCalibrations =
                kmalloc(sizeof(struct TCalibration) * pFirmware->mnCalibrations, GFP_KERNEL);
-       for (nCalibration = 0; nCalibration < pFirmware->mnCalibrations; nCalibration++) {
+       for (nCalibration = 0;
+               nCalibration < pFirmware->mnCalibrations;
+               nCalibration++) {
                pCalibration = &(pFirmware->mpCalibrations[nCalibration]);
                memcpy(pCalibration->mpName, pData, 64);
                pData += 64;
@@ -1286,10 +1362,12 @@ start:
                        dev_err(pTAS2557->dev, "Block PChkSum Error: FW = 0x%x, Reg = 0x%x\n",
                                pBlock->mnPChkSum, (nValue1&0xff));
                        nResult = -EAGAIN;
+                               pTAS2557->mnErrCode |= ERROR_PRAM_CRCCHK;
                        goto check;
                }
 
                nResult = 0;
+               pTAS2557->mnErrCode &= ~ERROR_PRAM_CRCCHK;
                dev_dbg(pTAS2557->dev, "Block[0x%x] PChkSum match\n", pBlock->mnType);
        }
 
@@ -1298,8 +1376,10 @@ start:
                        dev_err(pTAS2557->dev, "Block YChkSum Error: FW = 0x%x, YCRC = 0x%x\n",
                                pBlock->mnYChkSum, nCRCChkSum);
                        nResult = -EAGAIN;
+                       pTAS2557->mnErrCode |= ERROR_YRAM_CRCCHK;
                        goto check;
                }
+               pTAS2557->mnErrCode &= ~ERROR_YRAM_CRCCHK;
                nResult = 0;
                dev_dbg(pTAS2557->dev, "Block[0x%x] YChkSum match\n", pBlock->mnType);
        }
@@ -1347,7 +1427,7 @@ static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
        struct TConfiguration *pCurrentConfiguration = NULL;
        struct TConfiguration *pNewConfiguration = NULL;
 
-       dev_dbg(pTAS2557->dev, "tas2557_load_configuration: %d\n", nConfiguration);
+       dev_dbg(pTAS2557->dev, "%s: %d\n", __func__, nConfiguration);
 
        if ((!pTAS2557->mpFirmware->mpPrograms) ||
                (!pTAS2557->mpFirmware->mpConfigurations)) {
@@ -1400,8 +1480,10 @@ static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
 
 end:
 
-       if (nResult < 0)
-               failsafe(pTAS2557);
+       if (nResult < 0) {
+               if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
+                       failsafe(pTAS2557);
+       }
 
        return nResult;
 }
@@ -1553,6 +1635,14 @@ void tas2557_fw_ready(const struct firmware *pFW, void *pContext)
        unsigned int nProgram = 0;
        unsigned int nSampleRate = 0;
 
+#ifdef CONFIG_TAS2557_CODEC
+       mutex_lock(&pTAS2557->codec_lock);
+#endif
+
+#ifdef CONFIG_TAS2557_MISC
+       mutex_lock(&pTAS2557->file_lock);
+#endif
+
        dev_info(pTAS2557->dev, "%s:\n", __func__);
 
        if (unlikely(!pFW) || unlikely(!pFW->data)) {
@@ -1594,14 +1684,21 @@ void tas2557_fw_ready(const struct firmware *pFW, void *pContext)
        }
 
        pTAS2557->mnCurrentSampleRate = nSampleRate;
-
        nResult = tas2557_set_program(pTAS2557, nProgram, -1);
 
 end:
-       return;
+
+#ifdef CONFIG_TAS2557_CODEC
+       mutex_unlock(&pTAS2557->codec_lock);
+#endif
+
+#ifdef CONFIG_TAS2557_MISC
+       mutex_unlock(&pTAS2557->file_lock);
+#endif
 }
 
-int tas2557_set_program(struct tas2557_priv *pTAS2557, unsigned int nProgram, int nConfig)
+int tas2557_set_program(struct tas2557_priv *pTAS2557,
+       unsigned int nProgram, int nConfig)
 {
        struct TProgram *pProgram;
        unsigned int nConfiguration = 0;
@@ -1669,7 +1766,7 @@ int tas2557_set_program(struct tas2557_priv *pTAS2557, unsigned int nProgram, in
                if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)
                        pTAS2557->enableIRQ(pTAS2557, false);
 
-               nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_mute_DSP_down_data);
+               nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
                if (nResult < 0)
                        goto end;
        }
@@ -1705,8 +1802,15 @@ int tas2557_set_program(struct tas2557_priv *pTAS2557, unsigned int nProgram, in
                nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
                if (nResult < 0)
                        goto end;
-               dev_dbg(pTAS2557->dev,
-                       "device powered up, load unmute\n");
+               if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
+                       nResult = tas2557_checkPLL(pTAS2557);
+                       if (nResult < 0) {
+                               nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
+                               pTAS2557->mbPowerUp = false;
+                               goto end;
+                       }
+               }
+               dev_dbg(pTAS2557->dev, "device powered up, load unmute\n");
                nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
                if (nResult < 0)
                        goto end;
@@ -1723,9 +1827,10 @@ int tas2557_set_program(struct tas2557_priv *pTAS2557, unsigned int nProgram, in
 
 end:
 
-       if (nResult < 0)
-               failsafe(pTAS2557);
-
+       if (nResult < 0) {
+               if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
+                       failsafe(pTAS2557);
+       }
        return nResult;
 }
 
@@ -1743,10 +1848,12 @@ int tas2557_set_calibration(struct tas2557_priv *pTAS2557, int nCalibration)
        }
 
        if (nCalibration == 0x00FF) {
-               dev_info(pTAS2557->dev, "load new calibration file %s\n", TAS2557_CAL_NAME);
                nResult = tas2557_load_calibration(pTAS2557, TAS2557_CAL_NAME);
-               if (nResult < 0)
+               if (nResult < 0) {
+                       dev_info(pTAS2557->dev, "load new calibration file %s fail %d\n",
+                               TAS2557_CAL_NAME, nResult);
                        goto end;
+               }
                nCalibration = 0;
        }
 
@@ -1762,7 +1869,7 @@ int tas2557_set_calibration(struct tas2557_priv *pTAS2557, int nCalibration)
        pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
 
        if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
-               dev_dbg(pTAS2557->dev, "Enable: load calibration\n");
+               dev_dbg(pTAS2557->dev, "%s, load calibration\n", __func__);
                nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData), TAS2557_BLOCK_CFG_COEFF_DEV_A);
                if (nResult < 0)
                        goto end;
index 53914f1db82e9c2d8b0dfd02d3df78f56fd1bb52..7170428bc864c10aa5c934dcdd2e0af18835c514 100755 (executable)
@@ -59,6 +59,7 @@ struct TYCRC {
 };
 
 int tas2557_enable(struct tas2557_priv *pTAS2557, bool bEnable);
+int tas2557_SA_DevChnSetup(struct tas2557_priv *pTAS2557, unsigned int mode);
 int tas2557_get_die_temperature(struct tas2557_priv *pTAS2557, int *pTemperature);
 int tas2557_set_sampling_rate(struct tas2557_priv *pTAS2557, unsigned int nSamplingRate);
 int tas2557_set_bit_rate(struct tas2557_priv *pTAS2557, unsigned int nBitRate);
index db4bb3d2ba4bcd9e66b2b69de92843457c87f6d2..f53425b0272f736838a7f2afd28d5f5fcf827a34 100755 (executable)
@@ -120,63 +120,70 @@ static ssize_t tas2557_file_read(struct file *file, char *buf, size_t count, lof
        break;
 
        case TIAUDIO_CMD_PROGRAM: {
-               if (g_logEnable)
-                       dev_info(pTAS2557->dev, "TIAUDIO_CMD_PROGRAM: count = %d\n", (int)count);
-
-               if (count == PROGRAM_BUF_SIZE) {
-                       p_kBuf = kzalloc(count, GFP_KERNEL);
-                       if (p_kBuf != NULL) {
-                               struct TProgram *pProgram =
-                                       &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
-                               p_kBuf[0] = pTAS2557->mpFirmware->mnPrograms;
-                               p_kBuf[1] = pTAS2557->mnCurrentProgram;
-                               p_kBuf[2] = pProgram->mnAppMode;
-                               p_kBuf[3] = (pProgram->mnBoost&0xff00)>>8;
-                               p_kBuf[4] = (pProgram->mnBoost&0x00ff);
-                               memcpy(&p_kBuf[5], pProgram->mpName, FW_NAME_SIZE);
-                               strlcpy(&p_kBuf[5+FW_NAME_SIZE], pProgram->mpDescription, strlen(pProgram->mpDescription) + 1);
-                               ret = copy_to_user(buf, p_kBuf, count);
-                               if (ret != 0) {
-                                       /* Failed to copy all the data, exit */
-                                       dev_err(pTAS2557->dev, "copy to user fail %d\n", ret);
-                               }
-                               kfree(p_kBuf);
+               if ((pTAS2557->mpFirmware->mnConfigurations > 0)
+                       && (pTAS2557->mpFirmware->mnPrograms > 0)) {
+                       if (g_logEnable)
+                               dev_info(pTAS2557->dev, "TIAUDIO_CMD_PROGRAM: count = %d\n", (int)count);
+
+                       if (count == PROGRAM_BUF_SIZE) {
+                               p_kBuf = kzalloc(count, GFP_KERNEL);
+                               if (p_kBuf != NULL) {
+                                       struct TProgram *pProgram =
+                                               &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
+                                       p_kBuf[0] = pTAS2557->mpFirmware->mnPrograms;
+                                       p_kBuf[1] = pTAS2557->mnCurrentProgram;
+                                       p_kBuf[2] = pProgram->mnAppMode;
+                                       p_kBuf[3] = (pProgram->mnBoost&0xff00)>>8;
+                                       p_kBuf[4] = (pProgram->mnBoost&0x00ff);
+                                       memcpy(&p_kBuf[5], pProgram->mpName, FW_NAME_SIZE);
+                                       strlcpy(&p_kBuf[5+FW_NAME_SIZE], pProgram->mpDescription, strlen(pProgram->mpDescription) + 1);
+                                       ret = copy_to_user(buf, p_kBuf, count);
+                                       if (ret != 0) {
+                                               /* Failed to copy all the data, exit */
+                                               dev_err(pTAS2557->dev, "copy to user fail %d\n", ret);
+                                       }
+                                       kfree(p_kBuf);
+                               } else
+                                       dev_err(pTAS2557->dev, "read no mem\n");
                        } else
-                               dev_err(pTAS2557->dev, "read no mem\n");
+                               dev_err(pTAS2557->dev, "read buffer not sufficient\n");
                } else
-                       dev_err(pTAS2557->dev, "read buffer not sufficient\n");
+                       dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
        }
        break;
 
        case TIAUDIO_CMD_CONFIGURATION: {
-               if (g_logEnable)
-                       dev_info(pTAS2557->dev, "TIAUDIO_CMD_CONFIGURATION: count = %d\n", (int)count);
-               if (count == CONFIGURATION_BUF_SIZE) {
-                       p_kBuf = kzalloc(count, GFP_KERNEL);
-                       if (p_kBuf != NULL) {
-                               struct TConfiguration *pConfiguration =
-                                       &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
-
-                               p_kBuf[0] = pTAS2557->mpFirmware->mnConfigurations;
-                               p_kBuf[1] = pTAS2557->mnCurrentConfiguration;
-                               memcpy(&p_kBuf[2], pConfiguration->mpName, FW_NAME_SIZE);
-                               p_kBuf[2+FW_NAME_SIZE] = pConfiguration->mnProgram;
-                               p_kBuf[3+FW_NAME_SIZE] = pConfiguration->mnPLL;
-                               p_kBuf[4+FW_NAME_SIZE] = (pConfiguration->mnSamplingRate&0x000000ff);
-                               p_kBuf[5+FW_NAME_SIZE] = ((pConfiguration->mnSamplingRate&0x0000ff00)>>8);
-                               p_kBuf[6+FW_NAME_SIZE] = ((pConfiguration->mnSamplingRate&0x00ff0000)>>16);
-                               p_kBuf[7+FW_NAME_SIZE] = ((pConfiguration->mnSamplingRate&0xff000000)>>24);
-                               strlcpy(&p_kBuf[8+FW_NAME_SIZE], pConfiguration->mpDescription, strlen(pConfiguration->mpDescription)+1);
-                               ret = copy_to_user(buf, p_kBuf, count);
-                               if (ret != 0) {
-                                       /* Failed to copy all the data, exit */
-                                       dev_err(pTAS2557->dev, "copy to user fail %d\n", ret);
-                               }
-                               kfree(p_kBuf);
+               if ((pTAS2557->mpFirmware->mnConfigurations > 0)
+               && (pTAS2557->mpFirmware->mnPrograms > 0)) {
+                       if (g_logEnable)
+                               dev_info(pTAS2557->dev, "TIAUDIO_CMD_CONFIGURATION: count = %d\n", (int)count);
+                       if (count == CONFIGURATION_BUF_SIZE) {
+                               p_kBuf = kzalloc(count, GFP_KERNEL);
+                               if (p_kBuf != NULL) {
+                                       struct TConfiguration *pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
+
+                                       p_kBuf[0] = pTAS2557->mpFirmware->mnConfigurations;
+                                       p_kBuf[1] = pTAS2557->mnCurrentConfiguration;
+                                       memcpy(&p_kBuf[2], pConfiguration->mpName, FW_NAME_SIZE);
+                                       p_kBuf[2+FW_NAME_SIZE] = pConfiguration->mnProgram;
+                                       p_kBuf[3+FW_NAME_SIZE] = pConfiguration->mnPLL;
+                                       p_kBuf[4+FW_NAME_SIZE] = (pConfiguration->mnSamplingRate&0x000000ff);
+                                       p_kBuf[5+FW_NAME_SIZE] = ((pConfiguration->mnSamplingRate&0x0000ff00)>>8);
+                                       p_kBuf[6+FW_NAME_SIZE] = ((pConfiguration->mnSamplingRate&0x00ff0000)>>16);
+                                       p_kBuf[7+FW_NAME_SIZE] = ((pConfiguration->mnSamplingRate&0xff000000)>>24);
+                                       strlcpy(&p_kBuf[8+FW_NAME_SIZE], pConfiguration->mpDescription, strlen(pConfiguration->mpDescription)+1);
+                                       ret = copy_to_user(buf, p_kBuf, count);
+                                       if (ret != 0) {
+                                               /* Failed to copy all the data, exit */
+                                               dev_err(pTAS2557->dev, "copy to user fail %d\n", ret);
+                                       }
+                                       kfree(p_kBuf);
+                               } else
+                                       dev_err(pTAS2557->dev, "read no mem\n");
                        } else
-                               dev_err(pTAS2557->dev, "read no mem\n");
+                               dev_err(pTAS2557->dev, "read buffer not sufficient\n");
                } else
-                       dev_err(pTAS2557->dev, "read buffer not sufficient\n");
+                       dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
        }
        break;
 
@@ -352,21 +359,33 @@ static ssize_t tas2557_file_write(struct file *file, const char *buf, size_t cou
        break;
 
        case TIAUDIO_CMD_PROGRAM:
+       {
                if (count == 2) {
-                       if (g_logEnable)
-                               dev_info(pTAS2557->dev, "TIAUDIO_CMD_PROGRAM, set to %d\n", p_kBuf[1]);
-                       tas2557_set_program(pTAS2557, p_kBuf[1], -1);
-                       pTAS2557->mnDBGCmd = 0;
+                       if ((pTAS2557->mpFirmware->mnConfigurations > 0)
+                               && (pTAS2557->mpFirmware->mnPrograms > 0)) {
+                               if (g_logEnable)
+                                       dev_info(pTAS2557->dev, "TIAUDIO_CMD_PROGRAM, set to %d\n", p_kBuf[1]);
+                               tas2557_set_program(pTAS2557, p_kBuf[1], -1);
+                               pTAS2557->mnDBGCmd = 0;
+                       } else
+                               dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
                }
+       }
        break;
 
        case TIAUDIO_CMD_CONFIGURATION:
+       {
                if (count == 2) {
-                       if (g_logEnable)
-                               dev_info(pTAS2557->dev, "TIAUDIO_CMD_CONFIGURATION, set to %d\n", p_kBuf[1]);
-                       tas2557_set_config(pTAS2557, p_kBuf[1]);
-                       pTAS2557->mnDBGCmd = 0;
+                       if ((pTAS2557->mpFirmware->mnConfigurations > 0)
+                       && (pTAS2557->mpFirmware->mnPrograms > 0)) {
+                               if (g_logEnable)
+                                       dev_info(pTAS2557->dev, "TIAUDIO_CMD_CONFIGURATION, set to %d\n", p_kBuf[1]);
+                               tas2557_set_config(pTAS2557, p_kBuf[1]);
+                               pTAS2557->mnDBGCmd = 0;
+                       } else
+                               dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
                }
+       }
        break;
 
        case TIAUDIO_CMD_FW_TIMESTAMP:
@@ -374,12 +393,17 @@ static ssize_t tas2557_file_write(struct file *file, const char *buf, size_t cou
        break;
 
        case TIAUDIO_CMD_CALIBRATION:
+       {
                if (count == 2) {
-                       if (g_logEnable)
-                               dev_info(pTAS2557->dev, "TIAUDIO_CMD_CALIBRATION, set to %d\n", p_kBuf[1]);
-                       tas2557_set_calibration(pTAS2557, p_kBuf[1]);
-                       pTAS2557->mnDBGCmd = 0;
+                       if ((pTAS2557->mpFirmware->mnConfigurations > 0)
+                       && (pTAS2557->mpFirmware->mnPrograms > 0)) {
+                               if (g_logEnable)
+                                       dev_info(pTAS2557->dev, "TIAUDIO_CMD_CALIBRATION, set to %d\n", p_kBuf[1]);
+                               tas2557_set_calibration(pTAS2557, p_kBuf[1]);
+                               pTAS2557->mnDBGCmd = 0;
+                       }
                }
+       }
        break;
 
        case TIAUDIO_CMD_SAMPLERATE:
@@ -483,19 +507,25 @@ static long tas2557_file_unlocked_ioctl(struct file *file, unsigned int cmd, uns
 
        case SMARTPA_SPK_SWITCH_PROGRAM:
        {
-               tas2557_set_program(pTAS2557, arg, -1);
+               if ((pTAS2557->mpFirmware->mnConfigurations > 0)
+                       && (pTAS2557->mpFirmware->mnPrograms > 0))
+                       tas2557_set_program(pTAS2557, arg, -1);
        }
        break;
 
        case SMARTPA_SPK_SWITCH_CONFIGURATION:
        {
-               tas2557_set_config(pTAS2557, arg);
+               if ((pTAS2557->mpFirmware->mnConfigurations > 0)
+                       && (pTAS2557->mpFirmware->mnPrograms > 0))
+                       tas2557_set_config(pTAS2557, arg);
        }
        break;
 
        case SMARTPA_SPK_SWITCH_CALIBRATION:
        {
-               tas2557_set_calibration(pTAS2557, arg);
+               if ((pTAS2557->mpFirmware->mnConfigurations > 0)
+                       && (pTAS2557->mpFirmware->mnPrograms > 0))
+                       tas2557_set_calibration(pTAS2557, arg);
        }
        break;
 
index 5453d0275e81bb54505ae75fed528a508afb237c..9f20c167526c0221a16bc3464884b50b480bb6af 100755 (executable)
@@ -103,6 +103,10 @@ static int tas2557_change_book_page(
        }
 
 end:
+       if (nResult < 0)
+               pTAS2557->mnErrCode |= ERROR_DEVA_I2C_COMM;
+       else
+               pTAS2557->mnErrCode &= ~ERROR_DEVA_I2C_COMM;
 
        return nResult;
 }
@@ -136,8 +140,10 @@ static int tas2557_dev_read(
                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;
        }
 
@@ -182,9 +188,12 @@ static int tas2557_dev_write(
                                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:
@@ -220,9 +229,12 @@ static int tas2557_dev_bulk_read(
                                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:
@@ -258,9 +270,12 @@ static int tas2557_dev_bulk_write(
                                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:
@@ -296,9 +311,12 @@ static int tas2557_dev_update_bits(
                                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:
@@ -346,6 +364,9 @@ static void tas2557_hw_reset(struct tas2557_priv *pTAS2557)
 
        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)
@@ -367,6 +388,12 @@ static void irq_work_routine(struct work_struct *work)
        if (!pTAS2557->mbPowerUp)
                goto end;
 
+       if ((!pTAS2557->mpFirmware->mnConfigurations)
+               || (!pTAS2557->mpFirmware->mnPrograms)) {
+               dev_info(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
+               goto end;
+       }
+
        nResult = tas2557_dev_read(pTAS2557, TAS2557_FLAGS_1, &nDevInt1Status);
        if (nResult >= 0)
                nResult = tas2557_dev_read(pTAS2557, TAS2557_FLAGS_2, &nDevInt2Status);
@@ -374,9 +401,57 @@ static void irq_work_routine(struct work_struct *work)
        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);
@@ -388,9 +463,12 @@ static void irq_work_routine(struct work_struct *work)
                        if (nResult < 0)
                                goto program;
                        if (nDevPowerStatus & 0x80)
+                                       pTAS2557->mnErrCode |= ERROR_CLASSD_PWR;
                                goto program; /* failed to power on the Class-D */
                }
 
+               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);
                goto end;
@@ -416,8 +494,8 @@ static irqreturn_t tas2557_irq_handler(int irq, void *dev_id)
        struct tas2557_priv *pTAS2557 = (struct tas2557_priv *)dev_id;
 
        tas2557_enableIRQ(pTAS2557, false);
-       /* get IRQ status after 100 ms */
-       schedule_delayed_work(&pTAS2557->irq_work, msecs_to_jiffies(100));
+       /* get IRQ status after 50 ms */
+       schedule_delayed_work(&pTAS2557->irq_work, msecs_to_jiffies(50));
        return IRQ_HANDLED;
 }
 
@@ -666,7 +744,7 @@ static int tas2557_i2c_probe(struct i2c_client *pClient,
                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,
index 228b881ab02f38dd8b4317bfb567251b62d1a6d8..f230a216959cfb4b1526be3142d3a905e61daafa 100755 (executable)
--- a/tas2557.h
+++ b/tas2557.h
@@ -80,6 +80,8 @@
 #define TAS2557_SAFE_GUARD_REG                 TAS2557_REG(0, 0, 37)
 #define TAS2557_ASI_CTL1_REG                   TAS2557_REG(0, 0, 42)
 #define TAS2557_CLK_ERR_CTRL                   TAS2557_REG(0, 0, 44)
+#define TAS2557_CLK_ERR_CTRL2                  TAS2557_REG(0, 0, 45)   /* B0_P0_R0x2d*/
+#define TAS2557_CLK_ERR_CTRL3                  TAS2557_REG(0, 0, 46)   /* B0_P0_R0x2e*/
 #define TAS2557_DBOOST_CFG_REG                 TAS2557_REG(0, 0, 52)
 #define TAS2557_POWER_UP_FLAG_REG              TAS2557_REG(0, 0, 100)
 #define TAS2557_FLAGS_1                                TAS2557_REG(0, 0, 104)  /* B0_P0_R0x68*/
 #define TAS2557_ASI1_WDIV_CLK_RATIO_REG                TAS2557_REG(0, 1, 15)
 #define TAS2557_ASI1_DAC_CLKOUT_REG            TAS2557_REG(0, 1, 16)
 #define TAS2557_ASI1_ADC_CLKOUT_REG            TAS2557_REG(0, 1, 17)
-
 #define TAS2557_ASI2_DAC_FORMAT_REG            TAS2557_REG(0, 1, 21)
 #define TAS2557_ASI2_ADC_FORMAT_REG            TAS2557_REG(0, 1, 22)
 #define TAS2557_ASI2_OFFSET1_REG               TAS2557_REG(0, 1, 23)
 #define TAS2557_ASI2_WDIV_CLK_RATIO_REG                TAS2557_REG(0, 1, 35)
 #define TAS2557_ASI2_DAC_CLKOUT_REG            TAS2557_REG(0, 1, 36)
 #define TAS2557_ASI2_ADC_CLKOUT_REG            TAS2557_REG(0, 1, 37)
-
 #define TAS2557_GPIO1_PIN_REG                  TAS2557_REG(0, 1, 61)   /*B0_P1_R0x3d */
 #define TAS2557_GPIO2_PIN_REG                  TAS2557_REG(0, 1, 62)   /*B0_P1_R0x3e */
 #define TAS2557_GPIO3_PIN_REG                  TAS2557_REG(0, 1, 63)   /*B0_P1_R0x3f */
 #define TAS2557_GPIO8_PIN_REG                  TAS2557_REG(0, 1, 68)
 #define TAS2557_GPIO9_PIN_REG                  TAS2557_REG(0, 1, 69)
 #define TAS2557_GPIO10_PIN_REG                 TAS2557_REG(0, 1, 70)
-
 #define TAS2557_GPI_PIN_REG                            TAS2557_REG(0, 1, 77)   /*B0_P1_R0x4d */
 #define TAS2557_GPIO_HIZ_CTRL1_REG             TAS2557_REG(0, 1, 79)
 #define TAS2557_GPIO_HIZ_CTRL2_REG             TAS2557_REG(0, 1, 80)
 #define TAS2557_GPIO_HIZ_CTRL3_REG             TAS2557_REG(0, 1, 81)
 #define TAS2557_GPIO_HIZ_CTRL4_REG             TAS2557_REG(0, 1, 82)
 #define TAS2557_GPIO_HIZ_CTRL5_REG             TAS2557_REG(0, 1, 83)
-
 #define TAS2557_BIT_BANG_CTRL_REG              TAS2557_REG(0, 1, 87)
 #define TAS2557_BIT_BANG_OUT1_REG              TAS2557_REG(0, 1, 88)
 #define TAS2557_BIT_BANG_OUT2_REG              TAS2557_REG(0, 1, 89)
 #define TAS2557_BIT_BANG_IN1_REG               TAS2557_REG(0, 1, 90)
 #define TAS2557_BIT_BANG_IN2_REG               TAS2557_REG(0, 1, 91)
 #define TAS2557_BIT_BANG_IN3_REG               TAS2557_REG(0, 1, 92)
-
 #define TAS2557_PDM_IN_CLK_REG                 TAS2557_REG(0, 1, 94)
 #define TAS2557_PDM_IN_PIN_REG                 TAS2557_REG(0, 1, 95)
-
 #define TAS2557_ASIM_IFACE1_REG                        TAS2557_REG(0, 1, 98)
 #define TAS2557_ASIM_FORMAT_REG                        TAS2557_REG(0, 1, 99)
 #define TAS2557_ASIM_IFACE3_REG                        TAS2557_REG(0, 1, 100)
 #define TAS2557_ASIM_IFACE6_REG                        TAS2557_REG(0, 1, 103)
 #define TAS2557_ASIM_IFACE7_REG                        TAS2557_REG(0, 1, 104)
 #define TAS2557_ASIM_IFACE8_REG                        TAS2557_REG(0, 1, 105)
-#define TAS2557_ASIM_IFACE9_REG                        TAS2557_REG(0, 1, 106)
-
+#define TAS2557_CLK_HALT_REG                   TAS2557_REG(0, 1, 106)  /* B0_P1_R0x6a */
 #define TAS2557_INT_GEN1_REG                   TAS2557_REG(0, 1, 108)  /* B0_P1_R0x6c */
-#define TAS2557_INT_GEN2_REG                   TAS2557_REG(0, 1, 109)
+#define TAS2557_INT_GEN2_REG                   TAS2557_REG(0, 1, 109)  /* B0_P1_R0x6d */
 #define TAS2557_INT_GEN3_REG                   TAS2557_REG(0, 1, 110)  /* B0_P1_R0x6e */
 #define TAS2557_INT_GEN4_REG                   TAS2557_REG(0, 1, 111)  /* B0_P1_R0x6f */
 #define TAS2557_INT_MODE_REG                   TAS2557_REG(0, 1, 114)  /* B0_P1_R0x72 */
-
 #define TAS2557_MAIN_CLKIN_REG                 TAS2557_REG(0, 1, 115)
 #define TAS2557_PLL_CLKIN_REG                  TAS2557_REG(0, 1, 116)
 #define TAS2557_CLKOUT_MUX_REG                 TAS2557_REG(0, 1, 117)
 #define TAS2557_CLKOUT_CDIV_REG                        TAS2557_REG(0, 1, 118)
-
 #define TAS2557_HACK_GP01_REG                  TAS2557_REG(0, 1, 122)
 
 #define TAS2557_HACK01_REG                     TAS2557_REG(0, 2, 10)
 
 #define TAS2557_SA_PG1P0_CHL_CTRL_REG  TAS2557_REG(0, 58, 120) /* B0_P0x3a_R0x78 */
 
-
 #define TAS2557_TEST_MODE_REG                  TAS2557_REG(0, 253, 13)
 #define TAS2557_BROADCAST_REG                  TAS2557_REG(0, 253, 54)
 #define TAS2557_CRYPTIC_REG                    TAS2557_REG(0, 253, 71)
 #define TAS2557_RAMP_CLK_DIV_MSB_REG           TAS2557_REG(100, 0, 43)
 #define TAS2557_RAMP_CLK_DIV_LSB_REG           TAS2557_REG(100, 0, 44)
 
-#define TAS2557_XMEM_44_REG                            TAS2557_REG(130, 2, 64) /* B0x82_P0x02_R0x40 */
 #define TAS2557_DIE_TEMP_REG                   TAS2557_REG(130, 2, 124)        /* B0x82_P0x02_R0x7C */
 
 /* Bits */
 #define TAS2557_FW_NAME     "tas2557_uCDSP.bin"
 #define TAS2557_PG1P0_FW_NAME     "tas2557_pg1p0_uCDSP.bin"
 
-#define TAS2557_APP_ROM1MODE   0
-#define TAS2557_APP_ROM2MODE   1
-#define TAS2557_APP_TUNINGMODE 2
+#define        TAS2557_APP_ROM1MODE    0
+#define        TAS2557_APP_ROM2MODE    1
+#define        TAS2557_APP_TUNINGMODE  2
+#define        TAS2557_APP_ROM1_96KHZ  3
+#define        TAS2557_APP_ROM2_96KHZ  4
+#define        TAS2557_APP_RAMMODE             5
+
+#define        TAS2557_BOOST_OFF               0
+#define        TAS2557_BOOST_DEVA              1
+#define        TAS2557_BOOST_DEVB              2
+#define        TAS2557_BOOST_BOTH              3
+
+#define        TAS2557_DEVA_CHL_DEFAULT        0       /* DevA default */
+#define        TAS2557_DEVA_CHL_MUTE           1       /* DevA mute */
+#define        TAS2557_DEVA_CHL_LEFT           2       /* DevA left channel */
+#define        TAS2557_DEVA_CHL_RIGHT          3       /* DevA right channel */
+#define        TAS2557_DEVA_CHL_MONOMIX        4       /* DevA (L+R)/2 */
+
+#define        ERROR_NONE                      0x00000000
+#define        ERROR_PLL_ABSENT        0x00000001
+#define        ERROR_DEVA_I2C_COMM     0x00000002
+#define        ERROR_PRAM_CRCCHK       0x00000008
+#define        ERROR_YRAM_CRCCHK       0x00000010
+#define        ERROR_CLK_DET2          0x00000020
+#define        ERROR_CLK_DET1          0x00000040
+#define        ERROR_CLK_LOST          0x00000080
+#define        ERROR_BROWNOUT          0x00000100
+#define        ERROR_DIE_OVERTEMP      0x00000200
+#define        ERROR_CLK_HALT          0x00000400
+#define        ERROR_UNDER_VOLTAGE     0x00000800
+#define        ERROR_OVER_CURRENT      0x00001000
+#define        ERROR_CLASSD_PWR        0x00002000
+#define        ERROR_FAILSAFE          0x40000000
 
 struct TBlock {
        unsigned int mnType;
@@ -334,6 +355,7 @@ struct TPLL {
 struct TConfiguration {
        char mpName[64];
        char *mpDescription;
+       unsigned int mnDevices;
        unsigned int mnProgram;
        unsigned int mnPLL;
        unsigned int mnSamplingRate;
@@ -430,6 +452,9 @@ struct tas2557_priv {
        bool mbIRQEnable;
        unsigned char mnI2SBits;
 
+       unsigned int mnChannelState;
+       unsigned char mnDevAChlData[16];
+
        /* for low temperature check */
        unsigned int mnDevGain;
        unsigned int mnDevCurrentGain;
@@ -437,6 +462,7 @@ struct tas2557_priv {
        struct hrtimer mtimer;
        struct work_struct mtimerwork;
 
+       unsigned int mnErrCode;
 #ifdef CONFIG_TAS2557_CODEC
        struct mutex codec_lock;
 #endif