ASoC: Merge dropped fixes from v5.18
authorMark Brown <broonie@kernel.org>
Thu, 24 Nov 2022 13:19:02 +0000 (13:19 +0000)
committerMark Brown <broonie@kernel.org>
Thu, 24 Nov 2022 13:19:02 +0000 (13:19 +0000)
These fixes were queued for v5.18 but due to me changing my scripting
they never actually got merged - pulling them up now.

1  2 
sound/soc/codecs/tlv320adc3xxx.c
sound/soc/fsl/fsl_micfil.c
sound/soc/soc-ops.c

index a969547708d49676b876cba03f109e521965837d,104167c6fd93c792bae2017c35c8ee7ef6bc29e2..52bb55724724448015f494f02f15adb73cb1995c
@@@ -14,6 -14,7 +14,7 @@@
  
  #include <dt-bindings/sound/tlv320adc3xxx.h>
  #include <linux/clk.h>
+ #include <linux/gpio/consumer.h>
  #include <linux/module.h>
  #include <linux/moduleparam.h>
  #include <linux/io.h>
@@@ -1025,7 -1026,9 +1026,9 @@@ static const struct gpio_chip adc3xxx_g
  
  static void adc3xxx_free_gpio(struct adc3xxx *adc3xxx)
  {
+ #ifdef CONFIG_GPIOLIB
        gpiochip_remove(&adc3xxx->gpio_chip);
+ #endif
  }
  
  static void adc3xxx_init_gpio(struct adc3xxx *adc3xxx)
@@@ -1152,20 -1155,20 +1155,20 @@@ static int adc3xxx_hw_params(struct snd
                return i;
  
        /* select data word length */
 -      switch (params_format(params)) {
 -      case SNDRV_PCM_FORMAT_S16_LE:
 +      switch (params_width(params)) {
 +      case 16:
                iface_len = ADC3XXX_IFACE_16BITS;
                width = 16;
                break;
 -      case SNDRV_PCM_FORMAT_S20_3LE:
 +      case 20:
                iface_len = ADC3XXX_IFACE_20BITS;
                width = 20;
                break;
 -      case SNDRV_PCM_FORMAT_S24_LE:
 +      case 24:
                iface_len = ADC3XXX_IFACE_24BITS;
                width = 24;
                break;
 -      case SNDRV_PCM_FORMAT_S32_LE:
 +      case 32:
                iface_len = ADC3XXX_IFACE_32BITS;
                width = 32;
                break;
@@@ -1252,7 -1255,8 +1255,7 @@@ static int adc3xxx_set_dai_fmt(struct s
        int master = 0;
        int ret;
  
 -      /* set master/slave audio interface */
 -      switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 +      switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
        case SND_SOC_DAIFMT_CBP_CFP:
                master = 1;
                clkdir = ADC3XXX_BCLK_MASTER | ADC3XXX_WCLK_MASTER;
@@@ -1334,21 -1338,13 +1337,21 @@@ static const struct snd_soc_component_d
        .num_dapm_widgets       = ARRAY_SIZE(adc3xxx_dapm_widgets),
        .dapm_routes            = adc3xxx_intercon,
        .num_dapm_routes        = ARRAY_SIZE(adc3xxx_intercon),
 +      .endianness             = 1,
  };
  
 -static int adc3xxx_i2c_probe(struct i2c_client *i2c,
 -                           const struct i2c_device_id *id)
 +static const struct i2c_device_id adc3xxx_i2c_id[] = {
 +      { "tlv320adc3001", ADC3001 },
 +      { "tlv320adc3101", ADC3101 },
 +      {}
 +};
 +MODULE_DEVICE_TABLE(i2c, adc3xxx_i2c_id);
 +
 +static int adc3xxx_i2c_probe(struct i2c_client *i2c)
  {
        struct device *dev = &i2c->dev;
        struct adc3xxx *adc3xxx = NULL;
 +      const struct i2c_device_id *id;
        int ret;
  
        adc3xxx = devm_kzalloc(dev, sizeof(struct adc3xxx), GFP_KERNEL);
  
        i2c_set_clientdata(i2c, adc3xxx);
  
 +      id = i2c_match_id(adc3xxx_i2c_id, i2c);
        adc3xxx->type = id->driver_data;
  
        /* Reset codec chip */
@@@ -1426,7 -1421,7 +1429,7 @@@ err_unprepare_mclk
        return ret;
  }
  
 -static int __exit adc3xxx_i2c_remove(struct i2c_client *client)
 +static void __exit adc3xxx_i2c_remove(struct i2c_client *client)
  {
        struct adc3xxx *adc3xxx = i2c_get_clientdata(client);
  
                clk_disable_unprepare(adc3xxx->mclk);
        adc3xxx_free_gpio(adc3xxx);
        snd_soc_unregister_component(&client->dev);
 -      return 0;
  }
  
  static const struct of_device_id tlv320adc3xxx_of_match[] = {
  };
  MODULE_DEVICE_TABLE(of, tlv320adc3xxx_of_match);
  
 -static const struct i2c_device_id adc3xxx_i2c_id[] = {
 -      { "tlv320adc3001", ADC3001 },
 -      { "tlv320adc3101", ADC3101 },
 -      {}
 -};
 -MODULE_DEVICE_TABLE(i2c, adc3xxx_i2c_id);
 -
  static struct i2c_driver adc3xxx_i2c_driver = {
        .driver = {
                   .name = "tlv320adc3xxx-codec",
                   .of_match_table = tlv320adc3xxx_of_match,
                  },
 -      .probe = adc3xxx_i2c_probe,
 -      .remove = adc3xxx_i2c_remove,
 +      .probe_new = adc3xxx_i2c_probe,
 +      .remove = __exit_p(adc3xxx_i2c_remove),
        .id_table = adc3xxx_i2c_id,
  };
  
index 79ef4e269bc95a3ef248f9da4af8503b9ef70dd6,d1cd104f858473b1621a42136e9f4456a3e8042c..4b86ef82fd930ae8f2a2d30d5f1a1e941fee8ed0
@@@ -1,7 -1,6 +1,7 @@@
  // SPDX-License-Identifier: GPL-2.0
  // Copyright 2018 NXP
  
 +#include <linux/bitfield.h>
  #include <linux/clk.h>
  #include <linux/device.h>
  #include <linux/interrupt.h>
@@@ -16,7 -15,6 +16,7 @@@
  #include <linux/regmap.h>
  #include <linux/sysfs.h>
  #include <linux/types.h>
 +#include <linux/dma/imx-dma.h>
  #include <sound/dmaengine_pcm.h>
  #include <sound/pcm.h>
  #include <sound/soc.h>
  #include <sound/core.h>
  
  #include "fsl_micfil.h"
 -#include "imx-pcm.h"
 +#include "fsl_utils.h"
  
 -#define FSL_MICFIL_RATES              SNDRV_PCM_RATE_8000_48000
 -#define FSL_MICFIL_FORMATS            (SNDRV_PCM_FMTBIT_S16_LE)
 +#define MICFIL_OSR_DEFAULT    16
 +
 +enum quality {
 +      QUALITY_HIGH,
 +      QUALITY_MEDIUM,
 +      QUALITY_LOW,
 +      QUALITY_VLOW0,
 +      QUALITY_VLOW1,
 +      QUALITY_VLOW2,
 +};
  
  struct fsl_micfil {
        struct platform_device *pdev;
        const struct fsl_micfil_soc_data *soc;
        struct clk *busclk;
        struct clk *mclk;
 +      struct clk *pll8k_clk;
 +      struct clk *pll11k_clk;
        struct snd_dmaengine_dai_dma_data dma_params_rx;
 +      struct sdma_peripheral_config sdmacfg;
        unsigned int dataline;
        char name[32];
        int irq[MICFIL_IRQ_LINES];
 -      unsigned int mclk_streams;
 -      int quality;    /*QUALITY 2-0 bits */
 -      bool slave_mode;
 -      int channel_gain[8];
 +      enum quality quality;
 +      int dc_remover;
  };
  
  struct fsl_micfil_soc_data {
@@@ -59,7 -48,6 +59,7 @@@
        unsigned int fifo_depth;
        unsigned int dataline;
        bool imx;
 +      u64  formats;
  };
  
  static struct fsl_micfil_soc_data fsl_micfil_imx8mm = {
        .fifos = 8,
        .fifo_depth = 8,
        .dataline =  0xf,
 +      .formats = SNDRV_PCM_FMTBIT_S16_LE,
 +};
 +
 +static struct fsl_micfil_soc_data fsl_micfil_imx8mp = {
 +      .imx = true,
 +      .fifos = 8,
 +      .fifo_depth = 32,
 +      .dataline =  0xf,
 +      .formats = SNDRV_PCM_FMTBIT_S32_LE,
  };
  
  static const struct of_device_id fsl_micfil_dt_ids[] = {
        { .compatible = "fsl,imx8mm-micfil", .data = &fsl_micfil_imx8mm },
 +      { .compatible = "fsl,imx8mp-micfil", .data = &fsl_micfil_imx8mp },
        {}
  };
  MODULE_DEVICE_TABLE(of, fsl_micfil_dt_ids);
  
 -/* Table 5. Quality Modes
 - * Medium     0 0 0
 - * High               0 0 1
 - * Very Low 2 1 0 0
 - * Very Low 1 1 0 1
 - * Very Low 0 1 1 0
 - * Low                1 1 1
 - */
  static const char * const micfil_quality_select_texts[] = {
 -      "Medium", "High",
 -      "N/A", "N/A",
 -      "VLow2", "VLow1",
 -      "VLow0", "Low",
 +      [QUALITY_HIGH] = "High",
 +      [QUALITY_MEDIUM] = "Medium",
 +      [QUALITY_LOW] = "Low",
 +      [QUALITY_VLOW0] = "VLow0",
 +      [QUALITY_VLOW1] = "Vlow1",
 +      [QUALITY_VLOW2] = "Vlow2",
  };
  
  static const struct soc_enum fsl_micfil_quality_enum =
 -      SOC_ENUM_SINGLE(REG_MICFIL_CTRL2,
 -                      MICFIL_CTRL2_QSEL_SHIFT,
 -                      ARRAY_SIZE(micfil_quality_select_texts),
 -                      micfil_quality_select_texts);
 +      SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_quality_select_texts),
 +                          micfil_quality_select_texts);
  
  static DECLARE_TLV_DB_SCALE(gain_tlv, 0, 100, 0);
  
 +static int micfil_set_quality(struct fsl_micfil *micfil)
 +{
 +      u32 qsel;
 +
 +      switch (micfil->quality) {
 +      case QUALITY_HIGH:
 +              qsel = MICFIL_QSEL_HIGH_QUALITY;
 +              break;
 +      case QUALITY_MEDIUM:
 +              qsel = MICFIL_QSEL_MEDIUM_QUALITY;
 +              break;
 +      case QUALITY_LOW:
 +              qsel = MICFIL_QSEL_LOW_QUALITY;
 +              break;
 +      case QUALITY_VLOW0:
 +              qsel = MICFIL_QSEL_VLOW0_QUALITY;
 +              break;
 +      case QUALITY_VLOW1:
 +              qsel = MICFIL_QSEL_VLOW1_QUALITY;
 +              break;
 +      case QUALITY_VLOW2:
 +              qsel = MICFIL_QSEL_VLOW2_QUALITY;
 +              break;
 +      }
 +
 +      return regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL2,
 +                                MICFIL_CTRL2_QSEL,
 +                                FIELD_PREP(MICFIL_CTRL2_QSEL, qsel));
 +}
 +
 +static int micfil_quality_get(struct snd_kcontrol *kcontrol,
 +                            struct snd_ctl_elem_value *ucontrol)
 +{
 +      struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
 +      struct fsl_micfil *micfil = snd_soc_component_get_drvdata(cmpnt);
 +
 +      ucontrol->value.integer.value[0] = micfil->quality;
 +
 +      return 0;
 +}
 +
 +static int micfil_quality_set(struct snd_kcontrol *kcontrol,
 +                            struct snd_ctl_elem_value *ucontrol)
 +{
 +      struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
 +      struct fsl_micfil *micfil = snd_soc_component_get_drvdata(cmpnt);
 +
 +      micfil->quality = ucontrol->value.integer.value[0];
 +
 +      return micfil_set_quality(micfil);
 +}
 +
  static const struct snd_kcontrol_new fsl_micfil_snd_controls[] = {
        SOC_SINGLE_SX_TLV("CH0 Volume", REG_MICFIL_OUT_CTRL,
                          MICFIL_OUTGAIN_CHX_SHIFT(0), 0xF, 0x7, gain_tlv),
                          MICFIL_OUTGAIN_CHX_SHIFT(7), 0xF, 0x7, gain_tlv),
        SOC_ENUM_EXT("MICFIL Quality Select",
                     fsl_micfil_quality_enum,
 -                   snd_soc_get_enum_double, snd_soc_put_enum_double),
 +                   micfil_quality_get, micfil_quality_set),
  };
  
 -static inline int get_pdm_clk(struct fsl_micfil *micfil,
 -                            unsigned int rate)
 -{
 -      u32 ctrl2_reg;
 -      int qsel, osr;
 -      int bclk;
 -
 -      regmap_read(micfil->regmap, REG_MICFIL_CTRL2, &ctrl2_reg);
 -      osr = 16 - ((ctrl2_reg & MICFIL_CTRL2_CICOSR_MASK)
 -                  >> MICFIL_CTRL2_CICOSR_SHIFT);
 -
 -      regmap_read(micfil->regmap, REG_MICFIL_CTRL2, &ctrl2_reg);
 -      qsel = ctrl2_reg & MICFIL_CTRL2_QSEL_MASK;
 -
 -      switch (qsel) {
 -      case MICFIL_HIGH_QUALITY:
 -              bclk = rate * 8 * osr / 2; /* kfactor = 0.5 */
 -              break;
 -      case MICFIL_MEDIUM_QUALITY:
 -      case MICFIL_VLOW0_QUALITY:
 -              bclk = rate * 4 * osr * 1; /* kfactor = 1 */
 -              break;
 -      case MICFIL_LOW_QUALITY:
 -      case MICFIL_VLOW1_QUALITY:
 -              bclk = rate * 2 * osr * 2; /* kfactor = 2 */
 -              break;
 -      case MICFIL_VLOW2_QUALITY:
 -              bclk = rate * osr * 4; /* kfactor = 4 */
 -              break;
 -      default:
 -              dev_err(&micfil->pdev->dev,
 -                      "Please make sure you select a valid quality.\n");
 -              bclk = -1;
 -              break;
 -      }
 -
 -      return bclk;
 -}
 -
 -static inline int get_clk_div(struct fsl_micfil *micfil,
 -                            unsigned int rate)
 -{
 -      u32 ctrl2_reg;
 -      long mclk_rate;
 -      int clk_div;
 -
 -      regmap_read(micfil->regmap, REG_MICFIL_CTRL2, &ctrl2_reg);
 -
 -      mclk_rate = clk_get_rate(micfil->mclk);
 -
 -      clk_div = mclk_rate / (get_pdm_clk(micfil, rate) * 2);
 -
 -      return clk_div;
 -}
 -
  /* The SRES is a self-negated bit which provides the CPU with the
   * capability to initialize the PDM Interface module through the
   * slave-bus interface. This bit always reads as zero, and this
@@@ -184,19 -173,64 +184,38 @@@ static int fsl_micfil_reset(struct devi
        struct fsl_micfil *micfil = dev_get_drvdata(dev);
        int ret;
  
 -      ret = regmap_update_bits(micfil->regmap,
 -                               REG_MICFIL_CTRL1,
 -                               MICFIL_CTRL1_MDIS_MASK,
 -                               0);
 -      if (ret) {
 -              dev_err(dev, "failed to clear MDIS bit %d\n", ret);
 +      ret = regmap_clear_bits(micfil->regmap, REG_MICFIL_CTRL1,
 +                              MICFIL_CTRL1_MDIS);
 +      if (ret)
                return ret;
 -      }
  
 -      ret = regmap_update_bits(micfil->regmap,
 -                               REG_MICFIL_CTRL1,
 -                               MICFIL_CTRL1_SRES_MASK,
 -                               MICFIL_CTRL1_SRES);
 -      if (ret) {
 -              dev_err(dev, "failed to reset MICFIL: %d\n", ret);
 +      ret = regmap_set_bits(micfil->regmap, REG_MICFIL_CTRL1,
 +                            MICFIL_CTRL1_SRES);
 +      if (ret)
                return ret;
 -      }
  
+       /*
+        * SRES is self-cleared bit, but REG_MICFIL_CTRL1 is defined
+        * as non-volatile register, so SRES still remain in regmap
+        * cache after set, that every update of REG_MICFIL_CTRL1,
+        * software reset happens. so clear it explicitly.
+        */
+       ret = regmap_clear_bits(micfil->regmap, REG_MICFIL_CTRL1,
+                               MICFIL_CTRL1_SRES);
+       if (ret)
+               return ret;
+       /*
+        * Set SRES should clear CHnF flags, But even add delay here
+        * the CHnF may not be cleared sometimes, so clear CHnF explicitly.
+        */
+       ret = regmap_write_bits(micfil->regmap, REG_MICFIL_STAT, 0xFF, 0xFF);
+       if (ret)
+               return ret;
        return 0;
  }
  
 -static int fsl_micfil_set_mclk_rate(struct fsl_micfil *micfil,
 -                                  unsigned int freq)
 -{
 -      struct device *dev = &micfil->pdev->dev;
 -      int ret;
 -
 -      clk_disable_unprepare(micfil->mclk);
 -
 -      ret = clk_set_rate(micfil->mclk, freq * 1024);
 -      if (ret)
 -              dev_warn(dev, "failed to set rate (%u): %d\n",
 -                       freq * 1024, ret);
 -
 -      clk_prepare_enable(micfil->mclk);
 -
 -      return ret;
 -}
 -
  static int fsl_micfil_startup(struct snd_pcm_substream *substream,
                              struct snd_soc_dai *dai)
  {
@@@ -234,32 -268,42 +253,32 @@@ static int fsl_micfil_trigger(struct sn
                 * 11 - reserved
                 */
                ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL1,
 -                                       MICFIL_CTRL1_DISEL_MASK,
 -                                       (1 << MICFIL_CTRL1_DISEL_SHIFT));
 -              if (ret) {
 -                      dev_err(dev, "failed to update DISEL bits\n");
 +                              MICFIL_CTRL1_DISEL,
 +                              FIELD_PREP(MICFIL_CTRL1_DISEL, MICFIL_CTRL1_DISEL_DMA));
 +              if (ret)
                        return ret;
 -              }
  
                /* Enable the module */
 -              ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL1,
 -                                       MICFIL_CTRL1_PDMIEN_MASK,
 -                                       MICFIL_CTRL1_PDMIEN);
 -              if (ret) {
 -                      dev_err(dev, "failed to enable the module\n");
 +              ret = regmap_set_bits(micfil->regmap, REG_MICFIL_CTRL1,
 +                                    MICFIL_CTRL1_PDMIEN);
 +              if (ret)
                        return ret;
 -              }
  
                break;
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                /* Disable the module */
 -              ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL1,
 -                                       MICFIL_CTRL1_PDMIEN_MASK,
 -                                       0);
 -              if (ret) {
 -                      dev_err(dev, "failed to enable the module\n");
 +              ret = regmap_clear_bits(micfil->regmap, REG_MICFIL_CTRL1,
 +                                      MICFIL_CTRL1_PDMIEN);
 +              if (ret)
                        return ret;
 -              }
  
                ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL1,
 -                                       MICFIL_CTRL1_DISEL_MASK,
 -                                       (0 << MICFIL_CTRL1_DISEL_SHIFT));
 -              if (ret) {
 -                      dev_err(dev, "failed to update DISEL bits\n");
 +                              MICFIL_CTRL1_DISEL,
 +                              FIELD_PREP(MICFIL_CTRL1_DISEL, MICFIL_CTRL1_DISEL_DISABLE));
 +              if (ret)
                        return ret;
 -              }
                break;
        default:
                return -EINVAL;
        return 0;
  }
  
 -static int fsl_set_clock_params(struct device *dev, unsigned int rate)
 +static int fsl_micfil_reparent_rootclk(struct fsl_micfil *micfil, unsigned int sample_rate)
  {
 -      struct fsl_micfil *micfil = dev_get_drvdata(dev);
 -      int clk_div;
 +      struct device *dev = &micfil->pdev->dev;
 +      u64 ratio = sample_rate;
 +      struct clk *clk;
        int ret;
  
 -      ret = fsl_micfil_set_mclk_rate(micfil, rate);
 -      if (ret < 0)
 -              dev_err(dev, "failed to set mclk[%lu] to rate %u\n",
 -                      clk_get_rate(micfil->mclk), rate);
 -
 -      /* set CICOSR */
 -      ret |= regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL2,
 -                               MICFIL_CTRL2_CICOSR_MASK,
 -                               MICFIL_CTRL2_OSR_DEFAULT);
 -      if (ret)
 -              dev_err(dev, "failed to set CICOSR in reg 0x%X\n",
 -                      REG_MICFIL_CTRL2);
 -
 -      /* set CLK_DIV */
 -      clk_div = get_clk_div(micfil, rate);
 -      if (clk_div < 0)
 -              ret = -EINVAL;
 +      /* Get root clock */
 +      clk = micfil->mclk;
  
 -      ret |= regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL2,
 -                               MICFIL_CTRL2_CLKDIV_MASK, clk_div);
 +      /* Disable clock first, for it was enabled by pm_runtime */
 +      clk_disable_unprepare(clk);
 +      fsl_asoc_reparent_pll_clocks(dev, clk, micfil->pll8k_clk,
 +                                   micfil->pll11k_clk, ratio);
 +      ret = clk_prepare_enable(clk);
        if (ret)
 -              dev_err(dev, "failed to set CLKDIV in reg 0x%X\n",
 -                      REG_MICFIL_CTRL2);
 +              return ret;
  
 -      return ret;
 +      return 0;
  }
  
  static int fsl_micfil_hw_params(struct snd_pcm_substream *substream,
        struct fsl_micfil *micfil = snd_soc_dai_get_drvdata(dai);
        unsigned int channels = params_channels(params);
        unsigned int rate = params_rate(params);
 -      struct device *dev = &micfil->pdev->dev;
 +      int clk_div = 8;
 +      int osr = MICFIL_OSR_DEFAULT;
        int ret;
  
        /* 1. Disable the module */
 -      ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL1,
 -                               MICFIL_CTRL1_PDMIEN_MASK, 0);
 -      if (ret) {
 -              dev_err(dev, "failed to disable the module\n");
 +      ret = regmap_clear_bits(micfil->regmap, REG_MICFIL_CTRL1,
 +                              MICFIL_CTRL1_PDMIEN);
 +      if (ret)
                return ret;
 -      }
  
        /* enable channels */
        ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL1,
                                 0xFF, ((1 << channels) - 1));
 -      if (ret) {
 -              dev_err(dev, "failed to enable channels %d, reg 0x%X\n", ret,
 -                      REG_MICFIL_CTRL1);
 +      if (ret)
                return ret;
 -      }
  
 -      ret = fsl_set_clock_params(dev, rate);
 -      if (ret < 0) {
 -              dev_err(dev, "Failed to set clock parameters [%d]\n", ret);
 +      ret = fsl_micfil_reparent_rootclk(micfil, rate);
 +      if (ret)
                return ret;
 -      }
  
 -      micfil->dma_params_rx.maxburst = channels * MICFIL_DMA_MAXBURST_RX;
 -
 -      return 0;
 -}
 -
 -static int fsl_micfil_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
 -                                   unsigned int freq, int dir)
 -{
 -      struct fsl_micfil *micfil = snd_soc_dai_get_drvdata(dai);
 -      struct device *dev = &micfil->pdev->dev;
 -
 -      int ret;
 +      ret = clk_set_rate(micfil->mclk, rate * clk_div * osr * 8);
 +      if (ret)
 +              return ret;
  
 -      if (!freq)
 -              return 0;
 +      ret = micfil_set_quality(micfil);
 +      if (ret)
 +              return ret;
  
 -      ret = fsl_micfil_set_mclk_rate(micfil, freq);
 -      if (ret < 0)
 -              dev_err(dev, "failed to set mclk[%lu] to rate %u\n",
 -                      clk_get_rate(micfil->mclk), freq);
 +      ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL2,
 +                               MICFIL_CTRL2_CLKDIV | MICFIL_CTRL2_CICOSR,
 +                               FIELD_PREP(MICFIL_CTRL2_CLKDIV, clk_div) |
 +                               FIELD_PREP(MICFIL_CTRL2_CICOSR, 16 - osr));
 +
 +      micfil->dma_params_rx.peripheral_config = &micfil->sdmacfg;
 +      micfil->dma_params_rx.peripheral_size = sizeof(micfil->sdmacfg);
 +      micfil->sdmacfg.n_fifos_src = channels;
 +      micfil->sdmacfg.sw_done = true;
 +      micfil->dma_params_rx.maxburst = channels * MICFIL_DMA_MAXBURST_RX;
  
 -      return ret;
 +      return 0;
  }
  
  static const struct snd_soc_dai_ops fsl_micfil_dai_ops = {
        .startup = fsl_micfil_startup,
        .trigger = fsl_micfil_trigger,
        .hw_params = fsl_micfil_hw_params,
 -      .set_sysclk = fsl_micfil_set_dai_sysclk,
  };
  
  static int fsl_micfil_dai_probe(struct snd_soc_dai *cpu_dai)
  {
        struct fsl_micfil *micfil = dev_get_drvdata(cpu_dai->dev);
        struct device *dev = cpu_dai->dev;
 -      unsigned int val;
 -      int ret;
 -      int i;
 +      unsigned int val = 0;
 +      int ret, i;
  
 -      /* set qsel to medium */
 -      ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL2,
 -                               MICFIL_CTRL2_QSEL_MASK, MICFIL_MEDIUM_QUALITY);
 +      micfil->quality = QUALITY_VLOW0;
 +
 +      /* set default gain to 2 */
 +      regmap_write(micfil->regmap, REG_MICFIL_OUT_CTRL, 0x22222222);
 +
 +      /* set DC Remover in bypass mode*/
 +      for (i = 0; i < MICFIL_OUTPUT_CHANNELS; i++)
 +              val |= MICFIL_DC_BYPASS << MICFIL_DC_CHX_SHIFT(i);
 +      ret = regmap_update_bits(micfil->regmap, REG_MICFIL_DC_CTRL,
 +                               MICFIL_DC_CTRL_CONFIG, val);
        if (ret) {
 -              dev_err(dev, "failed to set quality mode bits, reg 0x%X\n",
 -                      REG_MICFIL_CTRL2);
 +              dev_err(dev, "failed to set DC Remover mode bits\n");
                return ret;
        }
 -
 -      /* set default gain to max_gain */
 -      regmap_write(micfil->regmap, REG_MICFIL_OUT_CTRL, 0x77777777);
 -      for (i = 0; i < 8; i++)
 -              micfil->channel_gain[i] = 0xF;
 +      micfil->dc_remover = MICFIL_DC_BYPASS;
  
        snd_soc_dai_init_dma_data(cpu_dai, NULL,
                                  &micfil->dma_params_rx);
  
        /* FIFO Watermark Control - FIFOWMK*/
 -      val = MICFIL_FIFO_CTRL_FIFOWMK(micfil->soc->fifo_depth) - 1;
        ret = regmap_update_bits(micfil->regmap, REG_MICFIL_FIFO_CTRL,
 -                               MICFIL_FIFO_CTRL_FIFOWMK_MASK,
 -                               val);
 -      if (ret) {
 -              dev_err(dev, "failed to set FIFOWMK\n");
 +                      MICFIL_FIFO_CTRL_FIFOWMK,
 +                      FIELD_PREP(MICFIL_FIFO_CTRL_FIFOWMK, micfil->soc->fifo_depth - 1));
 +      if (ret)
                return ret;
 -      }
  
        return 0;
  }
@@@ -385,8 -452,8 +404,8 @@@ static struct snd_soc_dai_driver fsl_mi
                .stream_name = "CPU-Capture",
                .channels_min = 1,
                .channels_max = 8,
 -              .rates = FSL_MICFIL_RATES,
 -              .formats = FSL_MICFIL_FORMATS,
 +              .rates = SNDRV_PCM_RATE_8000_48000,
 +              .formats = SNDRV_PCM_FMTBIT_S16_LE,
        },
        .ops = &fsl_micfil_dai_ops,
  };
@@@ -395,7 -462,7 +414,7 @@@ static const struct snd_soc_component_d
        .name           = "fsl-micfil-dai",
        .controls       = fsl_micfil_snd_controls,
        .num_controls   = ARRAY_SIZE(fsl_micfil_snd_controls),
 -
 +      .legacy_dai_naming      = 1,
  };
  
  /* REGMAP */
@@@ -530,11 -597,11 +549,11 @@@ static irqreturn_t micfil_isr(int irq, 
        regmap_read(micfil->regmap, REG_MICFIL_CTRL1, &ctrl1_reg);
        regmap_read(micfil->regmap, REG_MICFIL_FIFO_STAT, &fifo_stat_reg);
  
 -      dma_enabled = MICFIL_DMA_ENABLED(ctrl1_reg);
 +      dma_enabled = FIELD_GET(MICFIL_CTRL1_DISEL, ctrl1_reg) == MICFIL_CTRL1_DISEL_DMA;
  
        /* Channel 0-7 Output Data Flags */
        for (i = 0; i < MICFIL_OUTPUT_CHANNELS; i++) {
 -              if (stat_reg & MICFIL_STAT_CHXF_MASK(i))
 +              if (stat_reg & MICFIL_STAT_CHXF(i))
                        dev_dbg(&pdev->dev,
                                "Data available in Data Channel %d\n", i);
                /* if DMA is not enabled, field must be written with 1
                if (!dma_enabled)
                        regmap_write_bits(micfil->regmap,
                                          REG_MICFIL_STAT,
 -                                        MICFIL_STAT_CHXF_MASK(i),
 +                                        MICFIL_STAT_CHXF(i),
                                          1);
        }
  
        for (i = 0; i < MICFIL_FIFO_NUM; i++) {
 -              if (fifo_stat_reg & MICFIL_FIFO_STAT_FIFOX_OVER_MASK(i))
 +              if (fifo_stat_reg & MICFIL_FIFO_STAT_FIFOX_OVER(i))
                        dev_dbg(&pdev->dev,
                                "FIFO Overflow Exception flag for channel %d\n",
                                i);
  
 -              if (fifo_stat_reg & MICFIL_FIFO_STAT_FIFOX_UNDER_MASK(i))
 +              if (fifo_stat_reg & MICFIL_FIFO_STAT_FIFOX_UNDER(i))
                        dev_dbg(&pdev->dev,
                                "FIFO Underflow Exception flag for channel %d\n",
                                i);
@@@ -570,16 -637,16 +589,16 @@@ static irqreturn_t micfil_err_isr(int i
  
        regmap_read(micfil->regmap, REG_MICFIL_STAT, &stat_reg);
  
 -      if (stat_reg & MICFIL_STAT_BSY_FIL_MASK)
 +      if (stat_reg & MICFIL_STAT_BSY_FIL)
                dev_dbg(&pdev->dev, "isr: Decimation Filter is running\n");
  
 -      if (stat_reg & MICFIL_STAT_FIR_RDY_MASK)
 +      if (stat_reg & MICFIL_STAT_FIR_RDY)
                dev_dbg(&pdev->dev, "isr: FIR Filter Data ready\n");
  
 -      if (stat_reg & MICFIL_STAT_LOWFREQF_MASK) {
 +      if (stat_reg & MICFIL_STAT_LOWFREQF) {
                dev_dbg(&pdev->dev, "isr: ipg_clk_app is too low\n");
                regmap_write_bits(micfil->regmap, REG_MICFIL_STAT,
 -                                MICFIL_STAT_LOWFREQF_MASK, 1);
 +                                MICFIL_STAT_LOWFREQF, 1);
        }
  
        return IRQ_HANDLED;
@@@ -592,6 -659,7 +611,6 @@@ static int fsl_micfil_probe(struct plat
        struct resource *res;
        void __iomem *regs;
        int ret, i;
 -      unsigned long irqflag = 0;
  
        micfil = devm_kzalloc(&pdev->dev, sizeof(*micfil), GFP_KERNEL);
        if (!micfil)
                return PTR_ERR(micfil->busclk);
        }
  
 +      fsl_asoc_get_pll_clocks(&pdev->dev, &micfil->pll8k_clk,
 +                              &micfil->pll11k_clk);
 +
        /* init regmap */
        regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
        if (IS_ERR(regs))
        /* get IRQs */
        for (i = 0; i < MICFIL_IRQ_LINES; i++) {
                micfil->irq[i] = platform_get_irq(pdev, i);
 -              dev_err(&pdev->dev, "GET IRQ: %d\n", micfil->irq[i]);
                if (micfil->irq[i] < 0)
                        return micfil->irq[i];
        }
  
 -      if (of_property_read_bool(np, "fsl,shared-interrupt"))
 -              irqflag = IRQF_SHARED;
 -
        /* Digital Microphone interface interrupt */
        ret = devm_request_irq(&pdev->dev, micfil->irq[0],
 -                             micfil_isr, irqflag,
 +                             micfil_isr, IRQF_SHARED,
                               micfil->name, micfil);
        if (ret) {
                dev_err(&pdev->dev, "failed to claim mic interface irq %u\n",
  
        /* Digital Microphone interface error interrupt */
        ret = devm_request_irq(&pdev->dev, micfil->irq[1],
 -                             micfil_err_isr, irqflag,
 +                             micfil_err_isr, IRQF_SHARED,
                               micfil->name, micfil);
        if (ret) {
                dev_err(&pdev->dev, "failed to claim mic interface error irq %u\n",
        micfil->dma_params_rx.addr = res->start + REG_MICFIL_DATACH0;
        micfil->dma_params_rx.maxburst = MICFIL_DMA_MAXBURST_RX;
  
 -
        platform_set_drvdata(pdev, micfil);
  
        pm_runtime_enable(&pdev->dev);
                return ret;
        }
  
 +      fsl_micfil_dai.capture.formats = micfil->soc->formats;
 +
        ret = devm_snd_soc_register_component(&pdev->dev, &fsl_micfil_component,
                                              &fsl_micfil_dai, 1);
        if (ret) {
diff --combined sound/soc/soc-ops.c
index bd88de056358355d5ac70e86778fa2df547de84b,7cac26a64e0cb49b729ed798e06b05a52c03596b..1970bda074d8ac9fa44049d5c83fa98f8940eb00
@@@ -14,6 -14,7 +14,6 @@@
  #include <linux/module.h>
  #include <linux/moduleparam.h>
  #include <linux/init.h>
 -#include <linux/delay.h>
  #include <linux/pm.h>
  #include <linux/bitops.h>
  #include <linux/ctype.h>
@@@ -176,28 -177,20 +176,28 @@@ int snd_soc_info_volsw(struct snd_kcont
  {
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
 -      int platform_max;
 -
 -      if (!mc->platform_max)
 -              mc->platform_max = mc->max;
 -      platform_max = mc->platform_max;
 -
 -      if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume"))
 -              uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 -      else
 +      const char *vol_string = NULL;
 +      int max;
 +
 +      max = uinfo->value.integer.max = mc->max - mc->min;
 +      if (mc->platform_max && mc->platform_max < max)
 +              max = mc->platform_max;
 +
 +      if (max == 1) {
 +              /* Even two value controls ending in Volume should always be integer */
 +              vol_string = strstr(kcontrol->id.name, " Volume");
 +              if (vol_string && !strcmp(vol_string, " Volume"))
 +                      uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 +              else
 +                      uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 +      } else {
                uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 +      }
  
        uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
        uinfo->value.integer.min = 0;
 -      uinfo->value.integer.max = platform_max - mc->min;
 +      uinfo->value.integer.max = max;
 +
        return 0;
  }
  EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
   * Callback to provide information about a single mixer control, or a double
   * mixer control that spans 2 registers of the SX TLV type. SX TLV controls
   * have a range that represents both positive and negative values either side
 - * of zero but without a sign bit.
 + * of zero but without a sign bit. min is the minimum register value, max is
 + * the number of steps.
   *
   * Returns 0 for success.
   */
@@@ -220,21 -212,12 +220,21 @@@ int snd_soc_info_volsw_sx(struct snd_kc
  {
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
 +      int max;
  
 -      snd_soc_info_volsw(kcontrol, uinfo);
 -      /* Max represents the number of levels in an SX control not the
 -       * maximum value, so add the minimum value back on
 -       */
 -      uinfo->value.integer.max += mc->min;
 +      if (mc->platform_max)
 +              max = mc->platform_max;
 +      else
 +              max = mc->max;
 +
 +      if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
 +              uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 +      else
 +              uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 +
 +      uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
 +      uinfo->value.integer.min = 0;
 +      uinfo->value.integer.max = max;
  
        return 0;
  }
@@@ -452,7 -435,7 +452,7 @@@ int snd_soc_put_volsw_sx(struct snd_kco
        val = ucontrol->value.integer.value[0];
        if (mc->platform_max && val > mc->platform_max)
                return -EINVAL;
-       if (val > max - min)
+       if (val > max)
                return -EINVAL;
        val_mask = mask << shift;
        val = (val + min) & mask;
  
                val_mask = mask << rshift;
                val2 = (ucontrol->value.integer.value[1] + min) & mask;
+               if (mc->platform_max && val2 > mc->platform_max)
+                       return -EINVAL;
+               if (val2 > max)
+                       return -EINVAL;
                val2 = val2 << rshift;
  
                err = snd_soc_component_update_bits(component, reg2, val_mask,
@@@ -543,7 -532,7 +549,7 @@@ int snd_soc_put_volsw_range(struct snd_
                return -EINVAL;
        if (mc->platform_max && tmp > mc->platform_max)
                return -EINVAL;
 -      if (tmp > mc->max - mc->min + 1)
 +      if (tmp > mc->max - mc->min)
                return -EINVAL;
  
        if (invert)
                        return -EINVAL;
                if (mc->platform_max && tmp > mc->platform_max)
                        return -EINVAL;
 -              if (tmp > mc->max - mc->min + 1)
 +              if (tmp > mc->max - mc->min)
                        return -EINVAL;
  
                if (invert)