1. add lock in IRQ service and timer function
authorPeter Li <peter-li@ti.com>
Fri, 17 Mar 2017 23:55:50 +0000 (07:55 +0800)
committerPeter Li <peter-li@ti.com>
Fri, 17 Mar 2017 23:55:50 +0000 (07:55 +0800)
2. add compat ioctl to tiload driver
3. optimize the snapshot programming

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

index a22a8e0d9da9a968a76a04205039f038b9b0ac89..0650da94e46cb7a70f344532af0c5c2d9c79316d 100755 (executable)
 
 #define KCONTROL_CODEC
 
-static struct tas2557_register register_addr = { 0 };
-
-#define TAS2557_REG_IS_VALID(book, page, reg) \
-        ((book >= 0) && (book <= 255) &&\
-        (page >= 0) && (page <= 255) &&\
-        (reg >= 0) && (reg <= 127))
-
 static unsigned int tas2557_codec_read(struct snd_soc_codec *pCodec,
        unsigned int nRegister)
 {
@@ -64,13 +57,17 @@ static unsigned int tas2557_codec_read(struct snd_soc_codec *pCodec,
        int ret = 0;
        unsigned int Value = 0;
 
+       mutex_lock(&pTAS2557->codec_lock);
+
        ret = pTAS2557->read(pTAS2557, nRegister, &Value);
-       if (ret < 0) {
+       if (ret < 0)
                dev_err(pTAS2557->dev, "%s, %d, ERROR happen=%d\n", __func__,
                        __LINE__, ret);
-               return 0;
-       } else
-               return Value;
+       else
+               ret = Value;
+
+       mutex_unlock(&pTAS2557->codec_lock);
+       return ret;
 }
 
 static int tas2557_codec_write(struct snd_soc_codec *pCodec, unsigned int nRegister,
@@ -79,8 +76,11 @@ static int tas2557_codec_write(struct snd_soc_codec *pCodec, unsigned int nRegis
        struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
        int ret = 0;
 
+       mutex_lock(&pTAS2557->codec_lock);
+
        ret = pTAS2557->write(pTAS2557, nRegister, nValue);
-       
+
+       mutex_unlock(&pTAS2557->codec_lock);
        return ret;
 }
 
@@ -132,8 +132,12 @@ static int tas2557_mute(struct snd_soc_dai *dai, int mute)
        struct snd_soc_codec *codec = dai->codec;
        struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
 
+       mutex_lock(&pTAS2557->codec_lock);
+
        dev_dbg(pTAS2557->dev, "%s\n", __func__);
        tas2557_enable(pTAS2557, !mute);
+
+       mutex_unlock(&pTAS2557->codec_lock);
        return 0;
 }
 
@@ -154,10 +158,14 @@ static int tas2557_hw_params(struct snd_pcm_substream *pSubstream,
        struct snd_soc_codec *pCodec = pDAI->codec;
        struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
 
+       mutex_lock(&pTAS2557->codec_lock);
+
        dev_dbg(pTAS2557->dev, "%s\n", __func__);
 /* do bit rate setting during platform data */
 /* tas2557_set_bit_rate(pTAS2557, channel_both, snd_pcm_format_width(params_format(pParams))); */
        tas2557_set_sampling_rate(pTAS2557, params_rate(pParams));
+
+       mutex_unlock(&pTAS2557->codec_lock);
        return 0;
 }
 
@@ -202,105 +210,6 @@ static int tas2557_codec_remove(struct snd_soc_codec *pCodec)
        return 0;
 }
 
-static int tas2557_get_reg_addr(struct snd_kcontrol *pKcontrol,
-       struct snd_ctl_elem_value *pUcontrol)
-{
-#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);
-
-       pUcontrol->value.integer.value[0] = register_addr.book;
-       pUcontrol->value.integer.value[1] = register_addr.page;
-       pUcontrol->value.integer.value[2] = register_addr.reg;
-
-       dev_dbg(pTAS2557->dev, "%s: Get address [%d, %d, %d]\n", __func__,
-               register_addr.book, register_addr.page, register_addr.reg);
-
-       return 0;
-}
-
-static int tas2557_put_reg_addr(struct snd_kcontrol *pKcontrol,
-       struct snd_ctl_elem_value *pUcontrol)
-{
-#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);
-
-       register_addr.book = pUcontrol->value.integer.value[0];
-       register_addr.page = pUcontrol->value.integer.value[1];
-       register_addr.reg = pUcontrol->value.integer.value[2];
-
-       dev_dbg(pTAS2557->dev, "%s: Set address [%d, %d, %d]\n", __func__,
-               register_addr.book, register_addr.page, register_addr.reg);
-
-       return 0;
-}
-
-static int tas2557_get_reg_value(struct snd_kcontrol *pKcontrol,
-       struct snd_ctl_elem_value *pUcontrol)
-{
-#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);
-       unsigned int reg;
-       unsigned int nValue;
-
-       if (TAS2557_REG_IS_VALID(register_addr.book,
-                       register_addr.page, register_addr.reg)) {
-               reg = TAS2557_REG((unsigned int) register_addr.book,
-                       (unsigned int) register_addr.page,
-                       (unsigned int) register_addr.reg);
-               pTAS2557->read(pTAS2557, reg, &nValue);
-               pUcontrol->value.integer.value[0] = nValue;
-       } else {
-               dev_err(pTAS2557->dev, "%s: Invalid register address!\n", __func__);
-               pUcontrol->value.integer.value[0] = 0xFFFF;
-       }
-
-       dev_dbg(pTAS2557->dev, "%s: Read [%d, %d, %d] = %ld\n", __func__,
-               register_addr.book, register_addr.page, register_addr.reg,
-               pUcontrol->value.integer.value[0]);
-
-       return 0;
-}
-
-static int tas2557_put_reg_value(struct snd_kcontrol *pKcontrol,
-       struct snd_ctl_elem_value *pUcontrol)
-{
-#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);
-       unsigned int reg;
-
-       if (TAS2557_REG_IS_VALID(register_addr.book,
-                       register_addr.page, register_addr.reg)) {
-               reg = TAS2557_REG((unsigned int) register_addr.book,
-                       (unsigned int) register_addr.page,
-                       (unsigned int) register_addr.reg);
-               pTAS2557->write(pTAS2557, reg, pUcontrol->value.integer.value[0]);
-       } else {
-               dev_err(pTAS2557->dev, "%s: Invalid register address!\n", __func__);
-       }
-
-       dev_dbg(pTAS2557->dev, "%s: Write [%d, %d, %d] = %ld\n", __func__,
-               register_addr.book, register_addr.page, register_addr.reg,
-               pUcontrol->value.integer.value[0]);
-
-       return 0;
-}
-
 static int tas2557_power_ctrl_get(struct snd_kcontrol *pKcontrol,
        struct snd_ctl_elem_value *pValue)
 {
@@ -311,9 +220,13 @@ static int tas2557_power_ctrl_get(struct snd_kcontrol *pKcontrol,
 #endif
        struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
 
+       mutex_lock(&pTAS2557->codec_lock);
+
        pValue->value.integer.value[0] = pTAS2557->mbPowerUp;
        dev_dbg(pTAS2557->dev, "tas2557_power_ctrl_get = %d\n",
                pTAS2557->mbPowerUp);
+
+       mutex_unlock(&pTAS2557->codec_lock);
        return 0;
 }
 
@@ -329,9 +242,12 @@ static int tas2557_power_ctrl_put(struct snd_kcontrol *pKcontrol,
 
        int nPowerOn = pValue->value.integer.value[0];
 
-       dev_dbg(pTAS2557->dev, "tas2557_power_ctrl_put = %d\n", nPowerOn);
+       mutex_lock(&pTAS2557->codec_lock);
 
+       dev_dbg(pTAS2557->dev, "tas2557_power_ctrl_put = %d\n", nPowerOn);
        tas2557_enable(pTAS2557, (nPowerOn != 0));
+
+       mutex_unlock(&pTAS2557->codec_lock);
        return 0;
 }
 
@@ -346,10 +262,14 @@ static int tas2557_fs_get(struct snd_kcontrol *pKcontrol,
        struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
        int nFS = 48000;
 
+       mutex_lock(&pTAS2557->codec_lock);
+
        if (pTAS2557->mpFirmware->mnConfigurations)
                nFS = pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration].mnSamplingRate;
        pValue->value.integer.value[0] = nFS;
        dev_dbg(pTAS2557->dev, "tas2557_fs_get = %d\n", nFS);
+
+       mutex_unlock(&pTAS2557->codec_lock);
        return 0;
 }
 
@@ -365,8 +285,12 @@ static int tas2557_fs_put(struct snd_kcontrol *pKcontrol,
        int ret = 0;
        int nFS = pValue->value.integer.value[0];
 
+       mutex_lock(&pTAS2557->codec_lock);
+
        dev_info(pTAS2557->dev, "tas2557_fs_put = %d\n", nFS);
        ret = tas2557_set_sampling_rate(pTAS2557, nFS);
+
+       mutex_unlock(&pTAS2557->codec_lock);
        return ret;
 }
 
@@ -380,9 +304,13 @@ static int tas2557_program_get(struct snd_kcontrol *pKcontrol,
 #endif
        struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
 
+       mutex_lock(&pTAS2557->codec_lock);
+
        pValue->value.integer.value[0] = pTAS2557->mnCurrentProgram;
        dev_dbg(pTAS2557->dev, "tas2557_program_get = %d\n",
                pTAS2557->mnCurrentProgram);
+
+       mutex_unlock(&pTAS2557->codec_lock);
        return 0;
 }
 
@@ -398,7 +326,11 @@ static int tas2557_program_put(struct snd_kcontrol *pKcontrol,
        unsigned int nProgram = pValue->value.integer.value[0];
        int ret = 0;
 
+       mutex_lock(&pTAS2557->codec_lock);
+
        ret = tas2557_set_program(pTAS2557, nProgram, -1);
+
+       mutex_unlock(&pTAS2557->codec_lock);
        return ret;
 }
 
@@ -412,9 +344,13 @@ static int tas2557_configuration_get(struct snd_kcontrol *pKcontrol,
 #endif
        struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
 
+       mutex_lock(&pTAS2557->codec_lock);
+
        pValue->value.integer.value[0] = pTAS2557->mnCurrentConfiguration;
        dev_dbg(pTAS2557->dev, "tas2557_configuration_get = %d\n",
                pTAS2557->mnCurrentConfiguration);
+
+       mutex_unlock(&pTAS2557->codec_lock);
        return 0;
 }
 
@@ -430,7 +366,12 @@ static int tas2557_configuration_put(struct snd_kcontrol *pKcontrol,
        unsigned int nConfiguration = pValue->value.integer.value[0];
        int ret = 0;
 
+       mutex_lock(&pTAS2557->codec_lock);
+
+       dev_info(pTAS2557->dev, "%s = %d\n", __func__, nConfiguration);
        ret = tas2557_set_config(pTAS2557, nConfiguration);
+
+       mutex_unlock(&pTAS2557->codec_lock);
        return ret;
 }
 
@@ -444,10 +385,14 @@ static int tas2557_calibration_get(struct snd_kcontrol *pKcontrol,
 #endif
        struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
 
+       mutex_lock(&pTAS2557->codec_lock);
+
        pValue->value.integer.value[0] = pTAS2557->mnCurrentCalibration;
        dev_info(pTAS2557->dev,
                "tas2557_calibration_get = %d\n",
                pTAS2557->mnCurrentCalibration);
+
+       mutex_unlock(&pTAS2557->codec_lock);
        return 0;
 }
 
@@ -463,8 +408,11 @@ static int tas2557_calibration_put(struct snd_kcontrol *pKcontrol,
        unsigned int nCalibration = pValue->value.integer.value[0];
        int ret = 0;
 
+       mutex_lock(&pTAS2557->codec_lock);
+
        ret = tas2557_set_calibration(pTAS2557, nCalibration);
-       
+
+       mutex_unlock(&pTAS2557->codec_lock);
        return ret;
 }
 
@@ -481,10 +429,6 @@ static DECLARE_TLV_DB_SCALE(dac_tlv, 0, 100, 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),
-       SOC_SINGLE_MULTI_EXT("Reg Addr", 0, 0, INT_MAX, 0, 3, tas2557_get_reg_addr,
-               tas2557_put_reg_addr),
-       SOC_SINGLE_EXT("Reg Value", SND_SOC_NOPM, 0, 0xFFFF, 0,
-               tas2557_get_reg_value, tas2557_put_reg_value),
        SOC_SINGLE_EXT("PowerCtrl", SND_SOC_NOPM, 0, 0x0001, 0,
                tas2557_power_ctrl_get, tas2557_power_ctrl_put),
        SOC_SINGLE_EXT("Program", SND_SOC_NOPM, 0, 0x00FF, 0, tas2557_program_get,
index 23817333cfb27eca3c6a8db781f8af9aa73555f6..d7d5bbbd8a9b8f37fd62f75a67f758ce09a63669 100755 (executable)
 #include "tas2557.h"
 #include "tas2557-core.h"
 
-#define PPC_DRIVER_VERSION 0x00000200
-#define TAS2557_CAL_NAME "/data/tas2557_cal.bin"
+#define PPC_DRIVER_VERSION                     0x00000200
+#define TAS2557_CAL_NAME    "/data/tas2557_cal.bin"
 
-static int tas2557_load_calibration(struct tas2557_priv *pTAS2557, char *pFileName);
-static int tas2557_load_data(struct tas2557_priv *pTAS2557, struct TData *pData, unsigned int nType);
+
+static int tas2557_load_calibration(struct tas2557_priv *pTAS2557,
+       char *pFileName);
+static int tas2557_load_data(struct tas2557_priv *pTAS2557, struct TData *pData,
+       unsigned int nType);
 static void tas2557_clear_firmware(struct TFirmware *pFirmware);
 static int tas2557_load_block(struct tas2557_priv *pTAS2557, struct TBlock *pBlock);
-static int tas2557_load_configuration(struct tas2557_priv *pTAS2557, unsigned int nConfiguration, bool bLoadSame);
+static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
+       unsigned int nConfiguration, bool bLoadSame);
 
 #define TAS2557_UDELAY 0xFFFFFFFE
 #define TAS2557_MDELAY 0xFFFFFFFD
@@ -124,7 +128,8 @@ static unsigned int p_tas2557_mute_DSP_down_data[] = {
        0xFFFFFFFF, 0xFFFFFFFF
 };
 
-static int tas2557_dev_load_data(struct tas2557_priv *pTAS2557, unsigned int *pData)
+static int tas2557_dev_load_data(struct tas2557_priv *pTAS2557,
+       unsigned int *pData)
 {
        int ret = 0;
        unsigned int n = 0;
@@ -246,24 +251,14 @@ int tas2557_get_die_temperature(struct tas2557_priv *pTAS2557, int *pTemperature
 int tas2557_load_platdata(struct tas2557_priv *pTAS2557)
 {
        int nResult = 0;
-       unsigned char nGain;
 
        if (gpio_is_valid(pTAS2557->mnGpioINT)) {
                nResult = tas2557_configIRQ(pTAS2557);
                if (nResult < 0)
                        goto end;
-               pTAS2557->enableIRQ(pTAS2557, false, true);
        }
 
        nResult = tas2557_set_bit_rate(pTAS2557, pTAS2557->mnI2SBits);
-       if (nResult < 0)
-               goto end;
-
-       nResult = tas2557_get_DAC_gain(pTAS2557, &nGain);
-       if (nResult >= 0) {
-               pTAS2557->mnDevGain = nGain;
-               pTAS2557->mnDevCurrentGain = nGain;
-       }
 
 end:
 
@@ -302,6 +297,117 @@ static void failsafe(struct tas2557_priv *pTAS2557)
                tas2557_clear_firmware(pTAS2557->mpFirmware);
 }
 
+
+/*
+* tas2557_load_coefficient
+*/
+static int tas2557_load_coefficient(struct tas2557_priv *pTAS2557,
+       int nPrevConfig, int nNewConfig, bool bPowerOn)
+{
+       int nResult = 0;
+       struct TPLL *pPLL;
+       bool bRestorePower = false;
+       struct TProgram *pProgram;
+       struct TConfiguration *pPrevConfiguration;
+       struct TConfiguration *pNewConfiguration;
+       struct TCalibration *pCalibration = NULL;
+
+       if (!pTAS2557->mpFirmware->mnConfigurations) {
+               dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
+               goto end;
+       }
+
+       if (nNewConfig >= pTAS2557->mpFirmware->mnConfigurations) {
+               dev_err(pTAS2557->dev, "%s, invalid configuration New=%d, total=%d\n",
+                       __func__, nNewConfig, pTAS2557->mpFirmware->mnConfigurations);
+               goto end;
+       }
+
+       if (nPrevConfig < 0)
+               pPrevConfiguration = NULL;
+       else
+               pPrevConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nPrevConfig]);
+
+       pNewConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nNewConfig]);
+
+       if (pPrevConfiguration) {
+               if (pPrevConfiguration->mnPLL == pNewConfiguration->mnPLL) {
+                       dev_dbg(pTAS2557->dev, "%s, PLL same\n", __func__);
+                       goto prog_coefficient;
+               }
+       }
+
+       pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
+       if (bPowerOn) {
+               dev_dbg(pTAS2557->dev, "%s, power down to load new PLL\n", __func__);
+               if (hrtimer_active(&pTAS2557->mtimer))
+                       hrtimer_cancel(&pTAS2557->mtimer);
+
+               if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)
+                       pTAS2557->enableIRQ(pTAS2557, false);
+
+               nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_mute_DSP_down_data);
+               if (nResult < 0)
+                       goto end;
+               bRestorePower = true;
+       }
+
+       /* load PLL */
+       pPLL = &(pTAS2557->mpFirmware->mpPLLs[pNewConfiguration->mnPLL]);
+       dev_dbg(pTAS2557->dev, "load PLL: %s block for Configuration %s\n",
+               pPLL->mpName, pNewConfiguration->mpName);
+       nResult = tas2557_load_block(pTAS2557, &(pPLL->mBlock));
+       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);
+       if (nResult < 0)
+               goto end;
+
+prog_coefficient:
+       dev_dbg(pTAS2557->dev, "load new configuration: %s, coeff block data\n",
+               pNewConfiguration->mpName);
+       nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
+               TAS2557_BLOCK_CFG_COEFF_DEV_A);
+       if (nResult < 0)
+               goto end;
+       pTAS2557->mnCurrentConfiguration = nNewConfig;
+       if (pTAS2557->mpCalFirmware->mnCalibrations) {
+               pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[pTAS2557->mnCurrentCalibration]);
+               dev_dbg(pTAS2557->dev, "load calibration\n");
+               nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData),
+                       TAS2557_BLOCK_CFG_COEFF_DEV_A);
+               if (nResult < 0)
+                       goto end;
+       }
+
+       if (bRestorePower) {
+               pTAS2557->clearIRQ(pTAS2557);
+               dev_dbg(pTAS2557->dev, "device powered up, load startup\n");
+               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");
+               nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
+               if (nResult < 0)
+                       goto end;
+               if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
+                       pTAS2557->enableIRQ(pTAS2557, true);
+                       if (!hrtimer_active(&pTAS2557->mtimer)) {
+                               pTAS2557->mnDieTvReadCounter = 0;
+                               hrtimer_start(&pTAS2557->mtimer,
+                                       ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
+                       }
+               }
+       }
+end:
+
+       return nResult;
+}
+
 int tas2557_enable(struct tas2557_priv *pTAS2557, bool bEnable)
 {
        int nResult = 0, nRetry = 10;
@@ -329,8 +435,19 @@ int tas2557_enable(struct tas2557_priv *pTAS2557, bool bEnable)
        pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
        if (bEnable) {
                if (!pTAS2557->mbPowerUp) {
+                       if (pTAS2557->mbLoadConfigurationPrePowerUp) {
+                               dev_dbg(pTAS2557->dev, "load coefficient before power\n");
+                               nResult = tas2557_load_coefficient(pTAS2557,
+                                       pTAS2557->mnCurrentConfiguration, pTAS2557->mnNewConfiguration, false);
+                               if (nResult < 0)
+                                       goto end;
+                               pTAS2557->mbLoadConfigurationPrePowerUp = false;
+                       }
+
                        if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
-pllcheck:              /* check PLL */
+                               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;
@@ -360,6 +477,7 @@ pllcheck:           /* check PLL */
                                }
                        }
 
+                       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);
@@ -369,30 +487,28 @@ pllcheck:         /* check PLL */
                        nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
                        if (nResult < 0)
                                goto end;
-                       pTAS2557->mbPowerUp = true;
 
                        if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
                                /* turn on IRQ */
-                               nResult = pTAS2557->enableIRQ(pTAS2557, true, true);
-                               if (nResult < 0)
-                                       goto end;
-                               hrtimer_start(&pTAS2557->mtimer,
-                                       ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
+                               pTAS2557->enableIRQ(pTAS2557, true);
+                               if (!hrtimer_active(&pTAS2557->mtimer)) {
+                                       pTAS2557->mnDieTvReadCounter = 0;
+                                       hrtimer_start(&pTAS2557->mtimer,
+                                               ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
+                               }
                        }
+                       pTAS2557->mbPowerUp = true;
                }
        } else {
                if (pTAS2557->mbPowerUp) {
-                       if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
-                               if (hrtimer_active(&pTAS2557->mtimer))
-                                       hrtimer_cancel(&pTAS2557->mtimer);
+                       if (hrtimer_active(&pTAS2557->mtimer))
+                               hrtimer_cancel(&pTAS2557->mtimer);
 
-                               dev_dbg(pTAS2557->dev, "Enable: load shutdown sequence\n");
+                       dev_dbg(pTAS2557->dev, "Enable: load shutdown sequence\n");
+                       if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
                                /* turn off IRQ */
-                               nResult = pTAS2557->enableIRQ(pTAS2557, false, true);
-                               if (nResult < 0)
-                                       goto end;
+                               pTAS2557->enableIRQ(pTAS2557, false);
                        }
-
                        nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
                        if (nResult < 0)
                                goto end;
@@ -1228,11 +1344,8 @@ static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
        unsigned int nConfiguration, bool bLoadSame)
 {
        int nResult = 0;
-       struct TProgram *pCurrentProgram = NULL;
        struct TConfiguration *pCurrentConfiguration = NULL;
        struct TConfiguration *pNewConfiguration = NULL;
-       struct TCalibration *pCalibration = NULL;
-       struct TPLL *pNewPLL = NULL;
 
        dev_dbg(pTAS2557->dev, "tas2557_load_configuration: %d\n", nConfiguration);
 
@@ -1275,110 +1388,15 @@ static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
                goto end;
        }
 
-       pCurrentProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
-       pNewPLL = &(pTAS2557->mpFirmware->mpPLLs[pNewConfiguration->mnPLL]);
-
-       if (pTAS2557->mpCalFirmware->mnCalibrations)
-               pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[pTAS2557->mnCurrentCalibration]);
-
        if (pTAS2557->mbPowerUp) {
-               if (pNewConfiguration->mnPLL != pCurrentConfiguration->mnPLL) {
-                       if (hrtimer_active(&pTAS2557->mtimer))
-                               hrtimer_cancel(&pTAS2557->mtimer);
-                       nResult = pTAS2557->enableIRQ(pTAS2557, false, true);
-                       if (nResult < 0)
-                               goto end;
-                       dev_dbg(pTAS2557->dev,
-                               "TAS2557 is powered up, power down DSP before loading new configuration\n");
-                       nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
-                       if (nResult < 0)
-                               goto end;
-                       dev_dbg(pTAS2557->dev, "TAS2557: load new PLL: %s, block data\n", pNewPLL->mpName);
-                       nResult = tas2557_load_block(pTAS2557, &(pNewPLL->mBlock));
-                       if (nResult < 0)
-                               goto end;
-                       pTAS2557->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
-                       dev_dbg(pTAS2557->dev, "load new configuration: %s, pre block data\n",
-                               pNewConfiguration->mpName);
-                       nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
-                               TAS2557_BLOCK_CFG_PRE_DEV_A);
-                       if (nResult < 0)
-                               goto end;
-                       dev_dbg(pTAS2557->dev, "TAS2557: load new configuration: %s, coeff block data\n",
-                               pNewConfiguration->mpName);
-                       nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
-                               TAS2557_BLOCK_CFG_COEFF_DEV_A);
-                       if (nResult < 0)
-                               goto end;
-                       if ((pTAS2557->mpCalFirmware->mnCalibrations)
-                               && (pCurrentProgram->mnAppMode == TAS2557_APP_TUNINGMODE)) {
-                               dev_dbg(pTAS2557->dev, "Enable: load calibration\n");
-                               nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData),
-                                       TAS2557_BLOCK_CFG_COEFF_DEV_A);
-                               if (nResult < 0)
-                                       goto end;
-                       }
-                       dev_dbg(pTAS2557->dev, "TAS2557: power up TAS2557\n");
-                       nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
-                       if (nResult < 0)
-                               goto end;
-                       dev_dbg(pTAS2557->dev, "TAS2557: unmute TAS2557\n");
-                       nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
-                       if (nResult < 0)
-                               goto end;
-
-                       if (pCurrentProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
-                               nResult = pTAS2557->enableIRQ(pTAS2557, true, false);
-                               hrtimer_start(&pTAS2557->mtimer,
-                                       ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
-                       }
-               } else {
-                       dev_dbg(pTAS2557->dev,
-                               "TAS2557 is powered up, no change in PLL: load new configuration: %s, coeff block data\n",
-                               pNewConfiguration->mpName);
-                       nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
-                               TAS2557_BLOCK_CFG_COEFF_DEV_A);
-                       if (nResult < 0)
-                               goto end;
-                       if ((pTAS2557->mpCalFirmware->mnCalibrations)
-                               && (pCurrentProgram->mnAppMode == TAS2557_APP_TUNINGMODE)) {
-                               dev_dbg(pTAS2557->dev, "Enable: load calibration\n");
-                               nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData), TAS2557_BLOCK_CFG_COEFF_DEV_A);
-                               if (nResult < 0)
-                                       goto end;
-                       }
-               }
-               pTAS2557->mbLoadConfigurationPostPowerUp = false;
+               nResult = tas2557_load_coefficient(pTAS2557, pTAS2557->mnCurrentConfiguration, nConfiguration, true);
+               pTAS2557->mbLoadConfigurationPrePowerUp = false;
        } else {
                dev_dbg(pTAS2557->dev,
-                       "TAS2557 was powered down\n");
-               if (pNewConfiguration->mnPLL != pCurrentConfiguration->mnPLL) {
-                       dev_dbg(pTAS2557->dev, "TAS2557: load new PLL: %s, block data\n",
-                               pNewPLL->mpName);
-                       nResult = tas2557_load_block(pTAS2557, &(pNewPLL->mBlock));
-                       if (nResult < 0)
-                               goto end;
-                       pTAS2557->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
-                       dev_dbg(pTAS2557->dev, "load new configuration: %s, pre block data\n", pNewConfiguration->mpName);
-                       nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData), TAS2557_BLOCK_CFG_PRE_DEV_A);
-                       if (nResult < 0)
-                               goto end;
-               }
-               dev_dbg(pTAS2557->dev, "TAS2557: load new configuration: %s, coeff block data\n", pNewConfiguration->mpName);
-               nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData), TAS2557_BLOCK_CFG_COEFF_DEV_A);
-               if (nResult < 0)
-                       goto end;
-
-               if ((pTAS2557->mpCalFirmware->mnCalibrations)
-                       && (pCurrentProgram->mnAppMode == TAS2557_APP_TUNINGMODE)) {
-                       dev_dbg(pTAS2557->dev, "Enable: load calibration\n");
-                       nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData), TAS2557_BLOCK_CFG_COEFF_DEV_A);
-                       if (nResult < 0)
-                               goto end;
-               }
-               pTAS2557->mbLoadConfigurationPostPowerUp = true;
+                       "TAS2557 was powered down, will load coefficient when power up\n");
+               pTAS2557->mbLoadConfigurationPrePowerUp = true;
+               pTAS2557->mnNewConfiguration = nConfiguration;
        }
-       pTAS2557->mnCurrentConfiguration = nConfiguration;
 
 end:
 
@@ -1585,11 +1603,10 @@ end:
 
 int tas2557_set_program(struct tas2557_priv *pTAS2557, unsigned int nProgram, int nConfig)
 {
-       struct TPLL *pPLL;
-       struct TConfiguration *pConfiguration;
        struct TProgram *pProgram;
        unsigned int nConfiguration = 0;
        unsigned int nSampleRate = 0;
+       unsigned char nGain;
        bool bFound = false;
        int nResult = 0;
 
@@ -1632,21 +1649,32 @@ int tas2557_set_program(struct tas2557_priv *pTAS2557, unsigned int nProgram, in
                        nResult = 0;
                        goto end;
                }
-       } else
+       } else {
+               if (pTAS2557->mpFirmware->mpConfigurations[nConfig].mnProgram != nProgram) {
+                       dev_err(pTAS2557->dev, "%s, configuration program doesn't match\n", __func__);
+                       nResult = 0;
+                       goto end;
+               }
                nConfiguration = nConfig;
+       }
 
-       pTAS2557->mnCurrentProgram = nProgram;
+       pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
        if (pTAS2557->mbPowerUp) {
+               dev_info(pTAS2557->dev,
+                       "device powered up, power down to load program %d (%s)\n",
+                       nProgram, pProgram->mpName);
                if (hrtimer_active(&pTAS2557->mtimer))
                        hrtimer_cancel(&pTAS2557->mtimer);
-               nResult = pTAS2557->enableIRQ(pTAS2557, false, true);
-               if (nResult < 0)
-                       goto end;
+
+               if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)
+                       pTAS2557->enableIRQ(pTAS2557, false);
+
                nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_mute_DSP_down_data);
                if (nResult < 0)
                        goto end;
        }
 
+       pTAS2557->hw_reset(pTAS2557);
        nResult = pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
        if (nResult < 0)
                goto end;
@@ -1654,32 +1682,25 @@ int tas2557_set_program(struct tas2557_priv *pTAS2557, unsigned int nProgram, in
        nResult = tas2557_load_default(pTAS2557);
        if (nResult < 0)
                goto end;
-       dev_info(pTAS2557->dev, "load program %d\n", nProgram);
-       pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
-       nResult = tas2557_load_data(pTAS2557, &(pProgram->mData), TAS2557_BLOCK_PGM_ALL);
-       if (nResult < 0)
-               goto end;
+
+       dev_info(pTAS2557->dev, "load program %d (%s)\n", nProgram, pProgram->mpName);
        nResult = tas2557_load_data(pTAS2557, &(pProgram->mData), TAS2557_BLOCK_PGM_DEV_A);
        if (nResult < 0)
                goto end;
-       pTAS2557->mnCurrentConfiguration = nConfiguration;
-       pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
-       pPLL = &(pTAS2557->mpFirmware->mpPLLs[pConfiguration->mnPLL]);
-       dev_dbg(pTAS2557->dev, "TAS2557 load PLL: %s block for Configuration %s\n", pPLL->mpName, pConfiguration->mpName);
-       nResult = tas2557_load_block(pTAS2557, &(pPLL->mBlock));
-       if (nResult < 0)
-               goto end;
-       pTAS2557->mnCurrentSampleRate = pConfiguration->mnSamplingRate;
-       dev_dbg(pTAS2557->dev, "load configuration %s conefficient pre block\n", pConfiguration->mpName);
-       nResult = tas2557_load_data(pTAS2557, &(pConfiguration->mData), TAS2557_BLOCK_CFG_PRE_DEV_A);
+       pTAS2557->mnCurrentProgram = nProgram;
+
+       nResult = tas2557_get_DAC_gain(pTAS2557, &nGain);
        if (nResult < 0)
                goto end;
+       pTAS2557->mnDevGain = nGain;
+       pTAS2557->mnDevCurrentGain = nGain;
 
-       nResult = tas2557_load_configuration(pTAS2557, nConfiguration, true);
+       nResult = tas2557_load_coefficient(pTAS2557, -1, nConfiguration, false);
        if (nResult < 0)
                goto end;
 
        if (pTAS2557->mbPowerUp) {
+               pTAS2557->clearIRQ(pTAS2557);
                dev_dbg(pTAS2557->dev, "device powered up, load startup\n");
                nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
                if (nResult < 0)
@@ -1689,10 +1710,14 @@ int tas2557_set_program(struct tas2557_priv *pTAS2557, unsigned int nProgram, in
                nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
                if (nResult < 0)
                        goto end;
+
                if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
-                       nResult = pTAS2557->enableIRQ(pTAS2557, true, false);
-                       hrtimer_start(&pTAS2557->mtimer, 
-                               ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
+                       pTAS2557->enableIRQ(pTAS2557, true);
+                       if (!hrtimer_active(&pTAS2557->mtimer)) {
+                               pTAS2557->mnDieTvReadCounter = 0;
+                               hrtimer_start(&pTAS2557->mtimer,
+                                       ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
+                       }
                }
        }
 
@@ -1767,6 +1792,17 @@ int tas2557_parse_dt(struct device *dev, struct tas2557_priv *pTAS2557)
        } else
                        dev_dbg(pTAS2557->dev, "ti,cdc-reset-gpio=%d\n", pTAS2557->mnResetGPIO);
 
+       if (ret >= 0) {
+               pTAS2557->mnGpioINT = of_get_named_gpio(np, "ti,irq-gpio", 0);
+               if (pTAS2557->mnGpioINT < 0) {
+                       dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
+                               "ti,irq-gpio", np->full_name,
+                               pTAS2557->mnGpioINT);
+                       ret = -EINVAL;
+               } else
+                       dev_dbg(pTAS2557->dev, "ti,irq-gpio=%d\n", pTAS2557->mnGpioINT);
+       }
+
        if (ret >= 0) {
                rc = of_property_read_u32(np, "ti,i2s-bits", &value);
                if (rc) {
@@ -1779,16 +1815,6 @@ int tas2557_parse_dt(struct device *dev, struct tas2557_priv *pTAS2557)
                }
        }
 
-       if (ret >= 0) {
-               pTAS2557->mnGpioINT = of_get_named_gpio(np, "ti,irq-gpio", 0);
-               if (pTAS2557->mnGpioINT < 0) {
-                       dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
-                               "ti,irq-gpio", np->full_name,
-                               pTAS2557->mnGpioINT);
-                       ret = -EINVAL;
-               } else
-                       dev_dbg(pTAS2557->dev, "ti,irq-gpio=%d\n", pTAS2557->mnGpioINT);
-       }
        return ret;
 }
 
index 9af4ca4e6420c0d2d88b4be807ffb60cb0855a17..5453d0275e81bb54505ae75fed528a508afb237c 100755 (executable)
@@ -55,6 +55,7 @@
 #endif
 
 #define LOW_TEMPERATURE_GAIN 6
+#define LOW_TEMPERATURE_COUNTER 12
 
 static int tas2557_change_book_page(
        struct tas2557_priv *pTAS2557,
@@ -305,18 +306,21 @@ end:
        return nResult;
 }
 
-int tas2557_enableIRQ(struct tas2557_priv *pTAS2557, bool enable, bool clear)
+void tas2557_clearIRQ(struct tas2557_priv *pTAS2557)
 {
        unsigned int nValue;
        int nResult = 0;
 
-       if (enable) {
-               if (clear) {
-                       nResult = pTAS2557->read(pTAS2557, TAS2557_FLAGS_1, &nValue);
-                       if (nResult >= 0)
-                               nResult = pTAS2557->read(pTAS2557, TAS2557_FLAGS_2, &nValue);
-               }
+       nResult = pTAS2557->read(pTAS2557, TAS2557_FLAGS_1, &nValue);
+       if (nResult >= 0)
+               pTAS2557->read(pTAS2557, TAS2557_FLAGS_2, &nValue);
+
+}
+
 
+void tas2557_enableIRQ(struct tas2557_priv *pTAS2557, bool enable)
+{
+       if (enable) {
                if (!pTAS2557->mbIRQEnable) {
                        if (pTAS2557->mnIRQ != 0)
                                enable_irq(pTAS2557->mnIRQ);
@@ -328,28 +332,18 @@ int tas2557_enableIRQ(struct tas2557_priv *pTAS2557, bool enable, bool clear)
                                disable_irq_nosync(pTAS2557->mnIRQ);
                        pTAS2557->mbIRQEnable = false;
                }
-
-               if (clear) {
-                       nResult = pTAS2557->read(pTAS2557, TAS2557_FLAGS_1, &nValue);
-                       if (nResult >= 0)
-                               nResult = pTAS2557->read(pTAS2557, TAS2557_FLAGS_2, &nValue);
-               }
        }
-
-       return nResult;
 }
 
 static void tas2557_hw_reset(struct tas2557_priv *pTAS2557)
 {
-#ifdef ENABLE_GPIO_RESET
        if (gpio_is_valid(pTAS2557->mnResetGPIO)) {
-               devm_gpio_request_one(pTAS2557->dev, pTAS2557->mnResetGPIO,
-                       GPIOF_OUT_INIT_LOW, "TAS2557_RST");
-               msleep(10);
-               gpio_set_value_cansleep(pTAS2557->mnResetGPIO, 1);
-               udelay(1000);
+               gpio_direction_output(pTAS2557->mnResetGPIO, 0);
+               msleep(5);
+               gpio_direction_output(pTAS2557->mnResetGPIO, 1);
+               msleep(2);
        }
-#endif
+
        pTAS2557->mnCurrentBook = -1;
        pTAS2557->mnCurrentPage = -1;
 }
@@ -362,8 +356,16 @@ static void irq_work_routine(struct work_struct *work)
        struct tas2557_priv *pTAS2557 =
                container_of(work, struct tas2557_priv, irq_work.work);
 
+#ifdef CONFIG_TAS2557_CODEC
+       mutex_lock(&pTAS2557->codec_lock);
+#endif
+
+#ifdef CONFIG_TAS2557_MISC
+       mutex_lock(&pTAS2557->file_lock);
+#endif
+
        if (!pTAS2557->mbPowerUp)
-               return;
+               goto end;
 
        nResult = tas2557_dev_read(pTAS2557, TAS2557_FLAGS_1, &nDevInt1Status);
        if (nResult >= 0)
@@ -391,20 +393,29 @@ static void irq_work_routine(struct work_struct *work)
 
                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;
        }
-       return;
 
 program:
        /* hardware reset and reload */
-       tas2557_hw_reset(pTAS2557);
        tas2557_set_program(pTAS2557, pTAS2557->mnCurrentProgram, pTAS2557->mnCurrentConfiguration);
+
+end:
+
+#ifdef CONFIG_TAS2557_MISC
+       mutex_unlock(&pTAS2557->file_lock);
+#endif
+
+#ifdef CONFIG_TAS2557_CODEC
+       mutex_unlock(&pTAS2557->codec_lock);
+#endif
 }
 
 static irqreturn_t tas2557_irq_handler(int irq, void *dev_id)
 {
        struct tas2557_priv *pTAS2557 = (struct tas2557_priv *)dev_id;
 
-       tas2557_enableIRQ(pTAS2557, false, false);
+       tas2557_enableIRQ(pTAS2557, false);
        /* get IRQ status after 100 ms */
        schedule_delayed_work(&pTAS2557->irq_work, msecs_to_jiffies(100));
        return IRQ_HANDLED;
@@ -422,32 +433,62 @@ static enum hrtimer_restart temperature_timer_func(struct hrtimer *timer)
 static void timer_work_routine(struct work_struct *work)
 {
        struct tas2557_priv *pTAS2557 = container_of(work, struct tas2557_priv, mtimerwork);
-       int nResult, nTemp;
+       int nResult, nTemp, nActTemp;
+       struct TProgram *pProgram;
+       static int nAvg;
 
-       if (!pTAS2557->mbPowerUp)
+#ifdef CONFIG_TAS2557_CODEC
+       mutex_lock(&pTAS2557->codec_lock);
+#endif
+
+#ifdef CONFIG_TAS2557_MISC
+       mutex_lock(&pTAS2557->file_lock);
+#endif
+
+       if (!pTAS2557->mpFirmware->mnConfigurations) {
+               dev_info(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
                goto end;
+       }
+
+       pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
+       if (!pTAS2557->mbPowerUp
+               || (pProgram->mnAppMode != TAS2557_APP_TUNINGMODE)) {
+               dev_info(pTAS2557->dev, "%s, pass, Pow=%d, program=%s\n",
+                       __func__, pTAS2557->mbPowerUp, pProgram->mpName);
+               goto end;
+       }
 
        nResult = tas2557_get_die_temperature(pTAS2557, &nTemp);
        if (nResult >= 0) {
-               dev_dbg(pTAS2557->dev, "Die=0x%x, degree=%d\n", nTemp, (nTemp>>23));
-               if ((nTemp & 0x80000000) != 0) {
-                       /* if Die temperature is below ZERO */
-                       if (pTAS2557->mnDevCurrentGain != LOW_TEMPERATURE_GAIN) {
-                               nResult = tas2557_set_DAC_gain(pTAS2557, LOW_TEMPERATURE_GAIN);
-                               if (nResult < 0)
-                                       goto end;
-                               pTAS2557->mnDevCurrentGain = LOW_TEMPERATURE_GAIN;
-                               dev_dbg(pTAS2557->dev, "LOW Temp: set gain to %d\n", LOW_TEMPERATURE_GAIN);
-                       }
-               } else {
-                       /* if Die temperature is above ZERO */
-                       if (pTAS2557->mnDevCurrentGain != pTAS2557->mnDevGain) {
-                               nResult = tas2557_set_DAC_gain(pTAS2557, pTAS2557->mnDevGain);
-                               if (nResult < 0)
-                                       goto end;
-                               pTAS2557->mnDevCurrentGain = pTAS2557->mnDevGain;
-                               dev_dbg(pTAS2557->dev, "LOW Temp: set gain to original\n");
+               nActTemp = (int)(nTemp >> 23);
+               dev_dbg(pTAS2557->dev, "Die=0x%x, degree=%d\n", nTemp, nActTemp);
+               if (!pTAS2557->mnDieTvReadCounter)
+                       nAvg = 0;
+               pTAS2557->mnDieTvReadCounter++;
+               nAvg += nActTemp;
+               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 (pTAS2557->mnDevCurrentGain != LOW_TEMPERATURE_GAIN) {
+                                       nResult = tas2557_set_DAC_gain(pTAS2557, LOW_TEMPERATURE_GAIN);
+                                       if (nResult < 0)
+                                               goto end;
+                                       pTAS2557->mnDevCurrentGain = LOW_TEMPERATURE_GAIN;
+                                       dev_dbg(pTAS2557->dev, "LOW Temp: set gain to %d\n", LOW_TEMPERATURE_GAIN);
+                               }
+                       } else if (nAvg > 5) {
+                               /* if Die temperature is above 5 degree C */
+                               if (pTAS2557->mnDevCurrentGain != pTAS2557->mnDevGain) {
+                                       nResult = tas2557_set_DAC_gain(pTAS2557, pTAS2557->mnDevGain);
+                                       if (nResult < 0)
+                                               goto end;
+                                       pTAS2557->mnDevCurrentGain = pTAS2557->mnDevGain;
+                                       dev_dbg(pTAS2557->dev, "LOW Temp: set gain to original\n");
+                               }
                        }
+                       nAvg = 0;
                }
 
                if (pTAS2557->mbPowerUp)
@@ -456,7 +497,14 @@ static void timer_work_routine(struct work_struct *work)
        }
 
 end:
-       return;
+
+#ifdef CONFIG_TAS2557_MISC
+       mutex_unlock(&pTAS2557->file_lock);
+#endif
+
+#ifdef CONFIG_TAS2557_CODEC
+       mutex_unlock(&pTAS2557->codec_lock);
+#endif
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -493,6 +541,7 @@ static int tas2557_resume(struct device *dev)
        if (pTAS2557->mbPowerUp && (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)) {
                if (!hrtimer_active(&pTAS2557->mtimer)) {
                        dev_dbg(pTAS2557->dev, "%s, start Die Temp check timer\n", __func__);
+                       pTAS2557->mnDieTvReadCounter = 0;
                        hrtimer_start(&pTAS2557->mtimer,
                                ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
                }
@@ -500,7 +549,7 @@ static int tas2557_resume(struct device *dev)
 
 end:
 
-       return 0; 
+       return 0;
 }
 #endif
 
@@ -558,7 +607,15 @@ static int tas2557_i2c_probe(struct i2c_client *pClient,
        if (pClient->dev.of_node)
                tas2557_parse_dt(&pClient->dev, pTAS2557);
 
-       tas2557_hw_reset(pTAS2557);
+       if (gpio_is_valid(pTAS2557->mnResetGPIO)) {
+               nResult = gpio_request(pTAS2557->mnResetGPIO, "TAS2557-RESET");
+               if (nResult < 0) {
+                       dev_err(pTAS2557->dev, "%s: GPIO %d request error\n",
+                               __func__, pTAS2557->mnResetGPIO);
+                       goto err;
+               }
+               tas2557_hw_reset(pTAS2557);
+       }
 
        pTAS2557->read = tas2557_dev_read;
        pTAS2557->write = tas2557_dev_write;
@@ -566,6 +623,7 @@ static int tas2557_i2c_probe(struct i2c_client *pClient,
        pTAS2557->bulk_write = tas2557_dev_bulk_write;
        pTAS2557->update_bits = tas2557_dev_update_bits;
        pTAS2557->enableIRQ = tas2557_enableIRQ;
+       pTAS2557->clearIRQ = tas2557_clearIRQ;
        pTAS2557->set_config = tas2557_set_config;
        pTAS2557->set_calibration = tas2557_set_calibration;
        pTAS2557->hw_reset = tas2557_hw_reset;
@@ -631,6 +689,7 @@ static int tas2557_i2c_probe(struct i2c_client *pClient,
        }
 
 #ifdef CONFIG_TAS2557_CODEC
+       mutex_init(&pTAS2557->codec_lock);
        tas2557_register_codec(pTAS2557);
 #endif
 
@@ -648,7 +707,7 @@ static int tas2557_i2c_probe(struct i2c_client *pClient,
        INIT_WORK(&pTAS2557->mtimerwork, timer_work_routine);
 
        nResult = request_firmware_nowait(THIS_MODULE, 1, pFWName,
-                               pTAS2557->dev, GFP_KERNEL, pTAS2557, tas2557_fw_ready);
+               pTAS2557->dev, GFP_KERNEL, pTAS2557, tas2557_fw_ready);
 
 err:
 
@@ -663,6 +722,7 @@ static int tas2557_i2c_remove(struct i2c_client *pClient)
 
 #ifdef CONFIG_TAS2557_CODEC
        tas2557_deregister_codec(pTAS2557);
+       mutex_destroy(&pTAS2557->codec_lock);
 #endif
 
 #ifdef CONFIG_TAS2557_MISC
@@ -717,4 +777,5 @@ module_i2c_driver(tas2557_i2c_driver);
 MODULE_AUTHOR("Texas Instruments Inc.");
 MODULE_DESCRIPTION("TAS2557 I2C Smart Amplifier driver");
 MODULE_LICENSE("GPL v2");
+
 #endif
\ No newline at end of file
index 31490c96e46925e169fbc42ecaed05b4a31c2e93..228b881ab02f38dd8b4317bfb567251b62d1a6d8 100755 (executable)
--- a/tas2557.h
+++ b/tas2557.h
@@ -386,6 +386,7 @@ struct tas2557_priv {
        struct TFirmware *mpCalFirmware;
        unsigned int mnCurrentProgram;
        unsigned int mnCurrentSampleRate;
+       unsigned int mnNewConfiguration;
        unsigned int mnCurrentConfiguration;
        unsigned int mnCurrentCalibration;
        unsigned char mnCurrentBook;
@@ -393,7 +394,7 @@ struct tas2557_priv {
        int mnDevChl;
        bool mbTILoadActive;
        bool mbPowerUp;
-       bool mbLoadConfigurationPostPowerUp;
+       bool mbLoadConfigurationPrePowerUp;
        bool mbLoadCalibrationPostPowerUp;
        unsigned int mnPowerCtrl;
        bool mbCalibrationLoaded;
@@ -419,7 +420,8 @@ struct tas2557_priv {
                int config);
        int (*set_calibration)(struct tas2557_priv *pTAS2557,
                int calibration);
-       int (*enableIRQ)(struct tas2557_priv *pTAS2557, bool enable, bool clear);
+       void (*clearIRQ)(struct tas2557_priv *pTAS2557);
+       void (*enableIRQ)(struct tas2557_priv *pTAS2557, bool enable);
        void (*hw_reset)(struct tas2557_priv *pTAS2557);
 
        int mnGpioINT;
@@ -431,9 +433,14 @@ struct tas2557_priv {
        /* for low temperature check */
        unsigned int mnDevGain;
        unsigned int mnDevCurrentGain;
+       unsigned int mnDieTvReadCounter;
        struct hrtimer mtimer;
        struct work_struct mtimerwork;
 
+#ifdef CONFIG_TAS2557_CODEC
+       struct mutex codec_lock;
+#endif
+
 #ifdef CONFIG_TAS2557_MISC
        int mnDBGCmd;
        int mnCurrentReg;
index add7b414be9a8a060fa747b5906242304fc4cfa5..1719bc4ce70615c3903e64c7b36d1be359b26ccc 100755 (executable)
--- a/tiload.c
+++ b/tiload.c
@@ -282,6 +282,72 @@ static long tiload_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        return num;
 }
 
+#ifdef CONFIG_COMPAT
+static long tiload_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       struct tas2557_priv *pTAS2557 = (struct tas2557_priv *)filp->private_data;
+       long nResult = 0;
+
+       switch (cmd) {
+       case TILOAD_COMPAT_IOMAGICNUM_GET:
+               dev_info(pTAS2557->dev, "%s, TILOAD_COMPAT_IOMAGICNUM_GET=0x%x\n",
+                       __func__, cmd);
+               nResult = tiload_ioctl(filp, TILOAD_IOMAGICNUM_GET,
+                       (unsigned long) compat_ptr(arg));
+               break;
+
+       case TILOAD_COMPAT_IOMAGICNUM_SET:
+               dev_info(pTAS2557->dev, "%s, TILOAD_COMPAT_IOMAGICNUM_SET=0x%x\n",
+                       __func__, cmd);
+               nResult = tiload_ioctl(filp, TILOAD_IOMAGICNUM_SET,
+                       (unsigned long) compat_ptr(arg));
+               break;
+
+       case TILOAD_COMPAT_BPR_READ:
+               dev_info(pTAS2557->dev, "%s, TILOAD_COMPAT_BPR_READ=0x%x\n",
+                       __func__, cmd);
+               nResult = tiload_ioctl(filp, TILOAD_BPR_READ,
+                       (unsigned long) compat_ptr(arg));
+               break;
+
+       case TILOAD_COMPAT_BPR_WRITE:
+               dev_info(pTAS2557->dev, "%s, TILOAD_COMPAT_BPR_WRITE=0x%x\n",
+                       __func__, cmd);
+               nResult = tiload_ioctl(filp, TILOAD_BPR_WRITE,
+                       (unsigned long) compat_ptr(arg));
+               break;
+
+       case TILOAD_COMPAT_IOCTL_SET_CHL:
+               dev_info(pTAS2557->dev, "%s, TILOAD_COMPAT_IOCTL_SET_CHL=0x%x\n",
+                       __func__, cmd);
+               nResult = tiload_ioctl(filp, TILOAD_IOCTL_SET_CHL,
+                       (unsigned long) compat_ptr(arg));
+               break;
+
+       case TILOAD_COMPAT_IOCTL_SET_CONFIG:
+               dev_info(pTAS2557->dev, "%s, TILOAD_COMPAT_IOCTL_SET_CONFIG=0x%x\n",
+                       __func__, cmd);
+               nResult = tiload_ioctl(filp, TILOAD_IOCTL_SET_CONFIG,
+                       (unsigned long) compat_ptr(arg));
+               break;
+
+       case TILOAD_COMPAT_IOCTL_SET_CALIBRATION:
+               dev_info(pTAS2557->dev, "%s, TILOAD_COMPAT_IOCTL_SET_CALIBRATION=0x%x\n",
+                       __func__, cmd);
+               nResult = tiload_ioctl(filp, TILOAD_IOCTL_SET_CALIBRATION,
+                       (unsigned long) compat_ptr(arg));
+               break;
+
+       default:
+               dev_err(pTAS2557->dev, "%s, unsupport compat ioctl=0x%x\n",
+                       __func__, cmd);
+               break;
+       }
+
+       return nResult;
+}
+#endif
+
 /*********** File operations structure for tiload *************/
 static const struct file_operations tiload_fops = {
        .owner = THIS_MODULE,
@@ -290,6 +356,9 @@ static const struct file_operations tiload_fops = {
        .read = tiload_read,
        .write = tiload_write,
        .unlocked_ioctl = tiload_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = tiload_compat_ioctl,
+#endif
 };
 
 /*----------------------------------------------------------------------------
index 8f2960b784423a97efef1b7687cdacaf1390da5d..7468acfa396481981d3544f97f90568dd0830953 100755 (executable)
--- a/tiload.h
+++ b/tiload.h
 #ifndef _TILOAD_H
 #define _TILOAD_H
 
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+#endif
+
 #include "tas2557.h"
 
 #define BPR_REG(book, page, reg)               (((book * 256 * 128) + \
@@ -46,6 +50,16 @@ struct BPR {
 #define TILOAD_IOCTL_SET_CONFIG                        _IOW(TILOAD_IOC_MAGIC, 6, int)
 #define TILOAD_IOCTL_SET_CALIBRATION   _IOW(TILOAD_IOC_MAGIC, 7, int)
 
+#ifdef CONFIG_COMPAT
+#define TILOAD_COMPAT_IOMAGICNUM_GET           _IOR(TILOAD_IOC_MAGIC, 1, compat_int_t)
+#define TILOAD_COMPAT_IOMAGICNUM_SET           _IOW(TILOAD_IOC_MAGIC, 2, compat_int_t)
+#define TILOAD_COMPAT_BPR_READ                         _IOR(TILOAD_IOC_MAGIC, 3, struct BPR)
+#define TILOAD_COMPAT_BPR_WRITE                                _IOW(TILOAD_IOC_MAGIC, 4, struct BPR)
+#define TILOAD_COMPAT_IOCTL_SET_CHL                    _IOW(TILOAD_IOC_MAGIC, 5, compat_int_t)
+#define TILOAD_COMPAT_IOCTL_SET_CONFIG         _IOW(TILOAD_IOC_MAGIC, 6, compat_int_t)
+#define TILOAD_COMPAT_IOCTL_SET_CALIBRATION    _IOW(TILOAD_IOC_MAGIC, 7, compat_int_t)
+#endif
+
 int tiload_driver_init(struct tas2557_priv *pTAS2557);
 
 #endif