Merge remote-tracking branches 'asoc/topic/mtk', 'asoc/topic/nau8540', 'asoc/topic...
authorMark Brown <broonie@kernel.org>
Fri, 12 Jan 2018 12:29:18 +0000 (12:29 +0000)
committerMark Brown <broonie@kernel.org>
Fri, 12 Jan 2018 12:29:18 +0000 (12:29 +0000)
1  2  3  4  5  6 
sound/soc/codecs/nau8825.c

index e853a6dfd33b0ee7b8bf700dffea8b1e477f2d09,714ce17da717c0edbc8817aa482dc1f2ec6fbcbe,714ce17da717c0edbc8817aa482dc1f2ec6fbcbe,714ce17da717c0edbc8817aa482dc1f2ec6fbcbe,2aea642b4a5d60fb1922fe62319d9ec9c5efb78c,714ce17da717c0edbc8817aa482dc1f2ec6fbcbe..a1b697b6fb6483a357f68efa5818725a2a6e62e8
@@@@@@@ -194,10 -194,10 -194,10 -194,10 -194,10 -194,10 +194,10 @@@@@@@ static const struct reg_default nau8825
      
      /* register backup table when cross talk detection */
      static struct reg_default nau8825_xtalk_baktab[] = {
---- -  { NAU8825_REG_ADC_DGAIN_CTRL, 0 },
++++ +  { NAU8825_REG_ADC_DGAIN_CTRL, 0x00cf },
        { NAU8825_REG_HSVOL_CTRL, 0 },
---- -  { NAU8825_REG_DACL_CTRL, 0 },
---- -  { NAU8825_REG_DACR_CTRL, 0 },
++++ +  { NAU8825_REG_DACL_CTRL, 0x00cf },
++++ +  { NAU8825_REG_DACR_CTRL, 0x02cf },
      };
      
      static const unsigned short logtable[256] = {
       * tasks are allowed to acquire the semaphore, calling this function will
       * put the task to sleep. If the semaphore is not released within the
       * specified number of jiffies, this function returns.
---- - * Acquires the semaphore without jiffies. If no more tasks are allowed
---- - * to acquire the semaphore, calling this function will put the task to
---- - * sleep until the semaphore is released.
       * If the semaphore is not released within the specified number of jiffies,
---- - * this function returns -ETIME.
---- - * If the sleep is interrupted by a signal, this function will return -EINTR.
---- - * It returns 0 if the semaphore was acquired successfully.
++++ + * this function returns -ETIME. If the sleep is interrupted by a signal,
++++ + * this function will return -EINTR. It returns 0 if the semaphore was
++++ + * acquired successfully.
++++ + *
++++ + * Acquires the semaphore without jiffies. Try to acquire the semaphore
++++ + * atomically. Returns 0 if the semaphore has been acquired successfully
++++ + * or 1 if it it cannot be acquired.
       */
      static int nau8825_sema_acquire(struct nau8825 *nau8825, long timeout)
      {
                if (ret < 0)
                        dev_warn(nau8825->dev, "Acquire semaphore timeout\n");
        } else {
---- -          ret = down_interruptible(&nau8825->xtalk_sem);
---- -          if (ret < 0)
++++ +          ret = down_trylock(&nau8825->xtalk_sem);
++++ +          if (ret)
                        dev_warn(nau8825->dev, "Acquire semaphore fail\n");
        }
      
@@@@@@@ -454,22 -454,22 -454,22 -454,22 -455,32 -454,22 +455,32 @@@@@@@ static void nau8825_xtalk_backup(struc
      {
        int i;
      
++++ +  if (nau8825->xtalk_baktab_initialized)
++++ +          return;
++++ +
        /* Backup some register values to backup table */
        for (i = 0; i < ARRAY_SIZE(nau8825_xtalk_baktab); i++)
                regmap_read(nau8825->regmap, nau8825_xtalk_baktab[i].reg,
                                &nau8825_xtalk_baktab[i].def);
++++ +
++++ +  nau8825->xtalk_baktab_initialized = true;
      }
      
---- -static void nau8825_xtalk_restore(struct nau8825 *nau8825)
++++ +static void nau8825_xtalk_restore(struct nau8825 *nau8825, bool cause_cancel)
      {
        int i, volume;
      
++++ +  if (!nau8825->xtalk_baktab_initialized)
++++ +          return;
++++ +
        /* Restore register values from backup table; When the driver restores
---- -   * the headphone volumem, it needs recover to original level gradually
---- -   * with 3dB per step for less pop noise.
++++ +   * the headphone volume in XTALK_DONE state, it needs recover to
++++ +   * original level gradually with 3dB per step for less pop noise.
++++ +   * Otherwise, the restore should do ASAP.
         */
        for (i = 0; i < ARRAY_SIZE(nau8825_xtalk_baktab); i++) {
---- -          if (nau8825_xtalk_baktab[i].reg == NAU8825_REG_HSVOL_CTRL) {
++++ +          if (!cause_cancel && nau8825_xtalk_baktab[i].reg ==
++++ +                  NAU8825_REG_HSVOL_CTRL) {
                        /* Ramping up the volume change to reduce pop noise */
                        volume = nau8825_xtalk_baktab[i].def &
                                NAU8825_HPR_VOL_MASK;
                regmap_write(nau8825->regmap, nau8825_xtalk_baktab[i].reg,
                                nau8825_xtalk_baktab[i].def);
        }
++++ +
++++ +  nau8825->xtalk_baktab_initialized = false;
      }
      
      static void nau8825_xtalk_prepare_dac(struct nau8825 *nau8825)
@@@@@@@ -644,7 -644,7 -644,7 -644,7 -657,7 -644,7 +657,7 @@@@@@@ static void nau8825_xtalk_clean_adc(str
                NAU8825_POWERUP_ADCL | NAU8825_ADC_VREFSEL_MASK, 0);
      }
      
---- -static void nau8825_xtalk_clean(struct nau8825 *nau8825)
++++ +static void nau8825_xtalk_clean(struct nau8825 *nau8825, bool cause_cancel)
      {
        /* Enable internal VCO needed for interruptions */
        nau8825_configure_sysclk(nau8825, NAU8825_CLK_INTERNAL, 0);
                NAU8825_I2S_MS_MASK | NAU8825_I2S_LRC_DIV_MASK |
                NAU8825_I2S_BLK_DIV_MASK, NAU8825_I2S_MS_SLAVE);
        /* Restore value of specific register for cross talk */
---- -  nau8825_xtalk_restore(nau8825);
++++ +  nau8825_xtalk_restore(nau8825, cause_cancel);
      }
      
      static void nau8825_xtalk_imm_start(struct nau8825 *nau8825, int vol)
@@@@@@@ -779,7 -779,7 -779,7 -779,7 -792,7 -779,7 +792,7 @@@@@@@ static void nau8825_xtalk_measure(struc
                dev_dbg(nau8825->dev, "cross talk sidetone: %x\n", sidetone);
                regmap_write(nau8825->regmap, NAU8825_REG_DAC_DGAIN_CTRL,
                                        (sidetone << 8) | sidetone);
---- -          nau8825_xtalk_clean(nau8825);
++++ +          nau8825_xtalk_clean(nau8825, false);
                nau8825->xtalk_state = NAU8825_XTALK_DONE;
                break;
        default:
@@@@@@@ -815,13 -815,13 -815,13 -815,13 -828,14 -815,13 +828,14 @@@@@@@ static void nau8825_xtalk_work(struct w
      
      static void nau8825_xtalk_cancel(struct nau8825 *nau8825)
      {
---- -  /* If the xtalk_protect is true, that means the process is still
---- -   * on going. The driver forces to cancel the cross talk task and
++++ +  /* If the crosstalk is eanbled and the process is on going,
++++ +   * the driver forces to cancel the crosstalk task and
         * restores the configuration to original status.
         */
---- -  if (nau8825->xtalk_protect) {
++++ +  if (nau8825->xtalk_enable && nau8825->xtalk_state !=
++++ +          NAU8825_XTALK_DONE) {
                cancel_work_sync(&nau8825->xtalk_work);
---- -          nau8825_xtalk_clean(nau8825);
++++ +          nau8825_xtalk_clean(nau8825, true);
        }
        /* Reset parameters for cross talk suppression function */
        nau8825_sema_reset(nau8825);
@@@@@@@ -905,7 -905,6 -905,6 -905,6 -919,6 -905,6 +919,7 @@@@@@@ static int nau8825_adc_event(struct snd
      
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
 +++++          msleep(125);
                regmap_update_bits(nau8825->regmap, NAU8825_REG_ENA_CTRL,
                        NAU8825_ENABLE_ADC, NAU8825_ENABLE_ADC);
                break;
@@@@@@@ -1246,8 -1245,8 -1245,8 -1245,8 -1259,10 -1245,8 +1260,10 @@@@@@@ static int nau8825_hw_params(struct snd
                regmap_read(nau8825->regmap, NAU8825_REG_DAC_CTRL1, &osr);
                osr &= NAU8825_DAC_OVERSAMPLE_MASK;
                if (nau8825_clock_check(nau8825, substream->stream,
---- -                  params_rate(params), osr))
++++ +                  params_rate(params), osr)) {
++++ +                  nau8825_sema_release(nau8825);
                        return -EINVAL;
++++ +          }
                regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER,
                        NAU8825_CLK_DAC_SRC_MASK,
                        osr_dac_sel[osr].clk_src << NAU8825_CLK_DAC_SRC_SFT);
                regmap_read(nau8825->regmap, NAU8825_REG_ADC_RATE, &osr);
                osr &= NAU8825_ADC_SYNC_DOWN_MASK;
                if (nau8825_clock_check(nau8825, substream->stream,
---- -                  params_rate(params), osr))
++++ +                  params_rate(params), osr)) {
++++ +                  nau8825_sema_release(nau8825);
                        return -EINVAL;
++++ +          }
                regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER,
                        NAU8825_CLK_ADC_SRC_MASK,
                        osr_adc_sel[osr].clk_src << NAU8825_CLK_ADC_SRC_SFT);
                        bclk_div = 1;
                else if (bclk_fs <= 128)
                        bclk_div = 0;
---- -          else
++++ +          else {
++++ +                  nau8825_sema_release(nau8825);
                        return -EINVAL;
++++ +          }
                regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2,
                        NAU8825_I2S_LRC_DIV_MASK | NAU8825_I2S_BLK_DIV_MASK,
                        ((bclk_div + 1) << NAU8825_I2S_LRC_DIV_SFT) | bclk_div);
                val_len |= NAU8825_I2S_DL_32;
                break;
        default:
++++ +          nau8825_sema_release(nau8825);
                return -EINVAL;
        }
      
@@@@@@@ -1312,8 -1311,8 -1311,8 -1311,8 -1332,6 -1311,8 +1333,6 @@@@@@@ static int nau8825_set_dai_fmt(struct s
        struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec);
        unsigned int ctrl1_val = 0, ctrl2_val = 0;
      
---- -  nau8825_sema_acquire(nau8825, 3 * HZ);
---- -
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBM_CFM:
                ctrl2_val |= NAU8825_I2S_MS_MASTER;
                return -EINVAL;
        }
      
++++ +  nau8825_sema_acquire(nau8825, 3 * HZ);
++++ +
        regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL1,
                NAU8825_I2S_DL_MASK | NAU8825_I2S_DF_MASK |
                NAU8825_I2S_BP_MASK | NAU8825_I2S_PCMB_MASK,
@@@@@@@ -1687,7 -1686,7 -1686,7 -1686,7 -1707,7 -1686,7 +1708,7 @@@@@@@ static irqreturn_t nau8825_interrupt(in
        } else if (active_irq & NAU8825_HEADSET_COMPLETION_IRQ) {
                if (nau8825_is_jack_inserted(regmap)) {
                        event |= nau8825_jack_insert(nau8825);
---- -                  if (!nau8825->xtalk_bypass && !nau8825->high_imped) {
++++ +                  if (nau8825->xtalk_enable && !nau8825->high_imped) {
                                /* Apply the cross talk suppression in the
                                 * headset without high impedance.
                                 */
                                        int ret;
                                        nau8825->xtalk_protect = true;
                                        ret = nau8825_sema_acquire(nau8825, 0);
---- -                                  if (ret < 0)
++++ +                                  if (ret)
                                                nau8825->xtalk_protect = false;
                                }
                                /* Startup cross talk detection process */
---- -                          nau8825->xtalk_state = NAU8825_XTALK_PREPARE;
---- -                          schedule_work(&nau8825->xtalk_work);
++++ +                          if (nau8825->xtalk_protect) {
++++ +                                  nau8825->xtalk_state =
++++ +                                          NAU8825_XTALK_PREPARE;
++++ +                                  schedule_work(&nau8825->xtalk_work);
++++ +                          }
                        } else {
                                /* The cross talk suppression shouldn't apply
                                 * in the headset with high impedance. Thus,
                        nau8825->xtalk_event_mask = event_mask;
                }
        } else if (active_irq & NAU8825_IMPEDANCE_MEAS_IRQ) {
---- -          schedule_work(&nau8825->xtalk_work);
++++ +          /* crosstalk detection enable and process on going */
++++ +          if (nau8825->xtalk_enable && nau8825->xtalk_protect)
++++ +                  schedule_work(&nau8825->xtalk_work);
                clear_irq = NAU8825_IMPEDANCE_MEAS_IRQ;
        } else if ((active_irq & NAU8825_JACK_INSERTION_IRQ_MASK) ==
                NAU8825_JACK_INSERTION_DETECTED) {
@@@@@@@ -2382,7 -2381,7 -2381,7 -2381,7 -2407,7 -2381,7 +2408,7 @@@@@@@ static int __maybe_unused nau8825_resum
        regcache_sync(nau8825->regmap);
        nau8825->xtalk_protect = true;
        ret = nau8825_sema_acquire(nau8825, 0);
---- -  if (ret < 0)
++++ +  if (ret)
                nau8825->xtalk_protect = false;
        enable_irq(nau8825->irq);
      
@@@@@@@ -2441,8 -2440,8 -2440,8 -2440,8 -2466,8 -2440,8 +2467,8 @@@@@@@ static void nau8825_print_device_proper
                        nau8825->jack_insert_debounce);
        dev_dbg(dev, "jack-eject-debounce:  %d\n",
                        nau8825->jack_eject_debounce);
---- -  dev_dbg(dev, "crosstalk-bypass:     %d\n",
---- -                  nau8825->xtalk_bypass);
++++ +  dev_dbg(dev, "crosstalk-enable:     %d\n",
++++ +                  nau8825->xtalk_enable);
      }
      
      static int nau8825_read_device_properties(struct device *dev,
                &nau8825->jack_eject_debounce);
        if (ret)
                nau8825->jack_eject_debounce = 0;
---- -  nau8825->xtalk_bypass = device_property_read_bool(dev,
---- -          "nuvoton,crosstalk-bypass");
++++ +  nau8825->xtalk_enable = device_property_read_bool(dev,
++++ +          "nuvoton,crosstalk-enable");
      
        nau8825->mclk = devm_clk_get(dev, "mclk");
        if (PTR_ERR(nau8825->mclk) == -EPROBE_DEFER) {
@@@@@@@ -2569,6 -2568,6 -2568,6 -2568,6 -2594,7 -2568,6 +2595,7 @@@@@@@ static int nau8825_i2c_probe(struct i2c
         */
        nau8825->xtalk_state = NAU8825_XTALK_DONE;
        nau8825->xtalk_protect = false;
++++ +  nau8825->xtalk_baktab_initialized = false;
        sema_init(&nau8825->xtalk_sem, 1);
        INIT_WORK(&nau8825->xtalk_work, nau8825_xtalk_work);