Merge remote-tracking branches 'asoc/topic/ak4613', 'asoc/topic/ak4642', 'asoc/topic...
authorMark Brown <broonie@kernel.org>
Mon, 3 Jul 2017 15:51:31 +0000 (16:51 +0100)
committerMark Brown <broonie@kernel.org>
Mon, 3 Jul 2017 15:51:31 +0000 (16:51 +0100)
1  2  3  4  5  6 
sound/soc/codecs/ak4613.c
sound/soc/codecs/cs35l35.c

index 987918628d5b58f721771706f78655529ade1f71,a4520a1f849d93950322727045e0876380286cd0,b2dfddead22774cc85a9b4612b8edbfd3ceffa5c,b2dfddead22774cc85a9b4612b8edbfd3ceffa5c,b2dfddead22774cc85a9b4612b8edbfd3ceffa5c,b2dfddead22774cc85a9b4612b8edbfd3ceffa5c..690edebf029eb53c213ace00c88e39b14c6b3d75
@@@@@@@ -94,6 -94,8 -94,6 -94,6 -94,6 -94,6 +94,8 @@@@@@@ struct ak4613_interface 
      struct ak4613_priv {
        struct mutex lock;
        const struct ak4613_interface *iface;
+ ++++  struct snd_pcm_hw_constraint_list constraint;
+ ++++  unsigned int sysclk;
      
        unsigned int fmt;
        u8 oc;
@@@@@@@ -139,9 -141,7 -139,9 -139,9 -139,9 -139,9 +141,7 @@@@@@@ static const struct reg_default ak4613_
      #define AUDIO_IFACE(b, fmt) { b, SND_SOC_DAIFMT_##fmt }
      static const struct ak4613_interface ak4613_iface[] = {
        /* capture */                           /* playback */
- ----  [0] = { AUDIO_IFACE(24, LEFT_J),        AUDIO_IFACE(16, RIGHT_J) },
- ----  [1] = { AUDIO_IFACE(24, LEFT_J),        AUDIO_IFACE(20, RIGHT_J) },
- ----  [2] = { AUDIO_IFACE(24, LEFT_J),        AUDIO_IFACE(24, RIGHT_J) },
+ ++++  /* [0] - [2] are not supported */
        [3] = { AUDIO_IFACE(24, LEFT_J),        AUDIO_IFACE(24, LEFT_J) },
        [4] = { AUDIO_IFACE(24, I2S),           AUDIO_IFACE(24, I2S) },
      };
@@@@@@@ -254,6 -254,74 -254,6 -254,6 -254,6 -254,6 +254,74 @@@@@@@ static void ak4613_dai_shutdown(struct 
        mutex_unlock(&priv->lock);
      }
      
+ ++++static void ak4613_hw_constraints(struct ak4613_priv *priv,
+ ++++                            struct snd_pcm_runtime *runtime)
+ ++++{
+ ++++  static const unsigned int ak4613_rates[] = {
+ ++++           32000,
+ ++++           44100,
+ ++++           48000,
+ ++++           64000,
+ ++++           88200,
+ ++++           96000,
+ ++++          176400,
+ ++++          192000,
+ ++++  };
+ ++++  struct snd_pcm_hw_constraint_list *constraint = &priv->constraint;
+ ++++  unsigned int fs;
+ ++++  int i;
+ ++++
+ ++++  constraint->list        = ak4613_rates;
+ ++++  constraint->mask        = 0;
+ ++++  constraint->count       = 0;
+ ++++
+ ++++  /*
+ ++++   * Slave Mode
+ ++++   *      Normal: [32kHz, 48kHz] : 256fs,384fs or 512fs
+ ++++   *      Double: [64kHz, 96kHz] : 256fs
+ ++++   *      Quad  : [128kHz,192kHz]: 128fs
+ ++++   *
+ ++++   * Master mode
+ ++++   *      Normal: [32kHz, 48kHz] : 256fs or 512fs
+ ++++   *      Double: [64kHz, 96kHz] : 256fs
+ ++++   *      Quad  : [128kHz,192kHz]: 128fs
+ ++++  */
+ ++++  for (i = 0; i < ARRAY_SIZE(ak4613_rates); i++) {
+ ++++          /* minimum fs on each range */
+ ++++          fs = (ak4613_rates[i] <= 96000) ? 256 : 128;
+ ++++
+ ++++          if (priv->sysclk >= ak4613_rates[i] * fs)
+ ++++                  constraint->count = i + 1;
+ ++++  }
+ ++++
+ ++++  snd_pcm_hw_constraint_list(runtime, 0,
+ ++++                          SNDRV_PCM_HW_PARAM_RATE, constraint);
+ ++++}
+ ++++
+ ++++static int ak4613_dai_startup(struct snd_pcm_substream *substream,
+ ++++                        struct snd_soc_dai *dai)
+ ++++{
+ ++++  struct snd_soc_codec *codec = dai->codec;
+ ++++  struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec);
+ ++++
+ ++++  priv->cnt++;
+ ++++
+ ++++  ak4613_hw_constraints(priv, substream->runtime);
+ ++++
+ ++++  return 0;
+ ++++}
+ ++++
+ ++++static int ak4613_dai_set_sysclk(struct snd_soc_dai *codec_dai,
+ ++++                           int clk_id, unsigned int freq, int dir)
+ ++++{
+ ++++  struct snd_soc_codec *codec = codec_dai->codec;
+ ++++  struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec);
+ ++++
+ ++++  priv->sysclk = freq;
+ ++++
+ ++++  return 0;
+ ++++}
+ ++++
      static int ak4613_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
      {
        struct snd_soc_codec *codec = dai->codec;
        fmt &= SND_SOC_DAIFMT_FORMAT_MASK;
      
        switch (fmt) {
- ----  case SND_SOC_DAIFMT_RIGHT_J:
        case SND_SOC_DAIFMT_LEFT_J:
        case SND_SOC_DAIFMT_I2S:
                priv->fmt = fmt;
- ----
                break;
        default:
                return -EINVAL;
@@@@@@@ -286,13 -352,8 -286,13 -286,13 -286,13 -286,13 +352,8 @@@@@@@ static bool ak4613_dai_fmt_matching(con
        if (fmts->fmt != fmt)
                return false;
      
- ----  if (fmt == SND_SOC_DAIFMT_RIGHT_J) {
- ----          if (fmts->width != width)
- ----                  return false;
- ----  } else {
- ----          if (fmts->width < width)
- ----                  return false;
- ----  }
+ ++++  if (fmts->width != width)
+ ++++          return false;
      
        return true;
      }
@@@@@@@ -319,6 -380,7 -319,6 -319,6 -319,6 -319,6 +380,7 @@@@@@@ static int ak4613_dai_hw_params(struct 
        case 48000:
                ctrl2 = DFS_NORMAL_SPEED;
                break;
+ ++++  case 64000:
        case 88200:
        case 96000:
                ctrl2 = DFS_DOUBLE_SPEED;
                if (ak4613_dai_fmt_matching(priv->iface, is_play, fmt, width))
                        iface = priv->iface;
        } else {
 -----          for (i = ARRAY_SIZE(ak4613_iface); i >= 0; i--) {
 +++++          for (i = ARRAY_SIZE(ak4613_iface) - 1; i >= 0; i--) {
                        if (!ak4613_dai_fmt_matching(ak4613_iface + i,
                                                     is_play,
                                                     fmt, width))
        if ((priv->iface == NULL) ||
            (priv->iface == iface)) {
                priv->iface = iface;
- ----          priv->cnt++;
                ret = 0;
        }
        mutex_unlock(&priv->lock);
@@@@@@@ -407,7 -468,9 -407,7 -407,7 -407,7 -407,7 +468,9 @@@@@@@ static int ak4613_set_bias_level(struc
      }
      
      static const struct snd_soc_dai_ops ak4613_dai_ops = {
+ ++++  .startup        = ak4613_dai_startup,
        .shutdown       = ak4613_dai_shutdown,
+ ++++  .set_sysclk     = ak4613_dai_set_sysclk,
        .set_fmt        = ak4613_dai_set_fmt,
        .hw_params      = ak4613_dai_hw_params,
      };
                                 SNDRV_PCM_RATE_96000  |\
                                 SNDRV_PCM_RATE_176400 |\
                                 SNDRV_PCM_RATE_192000)
- ----#define AK4613_PCM_FMTBIT (SNDRV_PCM_FMTBIT_S16_LE |\
- ----                           SNDRV_PCM_FMTBIT_S24_LE)
+ ++++#define AK4613_PCM_FMTBIT (SNDRV_PCM_FMTBIT_S24_LE)
      
      static struct snd_soc_dai_driver ak4613_dai = {
        .name = "ak4613-hifi",
@@@@@@@ -527,6 -589,7 -527,6 -527,6 -527,6 -527,6 +589,7 @@@@@@@ static int ak4613_i2c_probe(struct i2c_
      
        priv->iface             = NULL;
        priv->cnt               = 0;
+ ++++  priv->sysclk            = 0;
      
        mutex_init(&priv->lock);
      
index 5ff12e4116e56ae164c972015f358db1b88202c8,f8aef5869b03afad906a0159f5836655f7495c51,f8aef5869b03afad906a0159f5836655f7495c51,f8aef5869b03afad906a0159f5836655f7495c51,f8aef5869b03afad906a0159f5836655f7495c51,375be49b7fd0b2f528b1a6a8b67a3c2e6beea774..f1ee184ecab2994424cdca4a6d9a1bbfd526bd5f
@@@@@@@ -162,14 -162,6 -162,6 -162,6 -162,6 -162,6 +162,14 @@@@@@@ static bool cs35l35_precious_register(s
        }
      }
      
 +++++static void cs35l35_reset(struct cs35l35_private *cs35l35)
 +++++{
 +++++  gpiod_set_value_cansleep(cs35l35->reset_gpio, 0);
 +++++  usleep_range(2000, 2100);
 +++++  gpiod_set_value_cansleep(cs35l35->reset_gpio, 1);
 +++++  usleep_range(1000, 1100);
 +++++}
 +++++
      static int cs35l35_wait_for_pdn(struct cs35l35_private *cs35l35)
      {
        int ret;
@@@@@@@ -764,6 -756,6 -756,6 -756,6 -756,6 -756,76 +764,76 @@@@@@@ static int cs35l35_codec_set_sysclk(str
        return ret;
      }
      
+++++ static int cs35l35_boost_inductor(struct cs35l35_private *cs35l35,
+++++                             int inductor)
+++++ {
+++++   struct regmap *regmap = cs35l35->regmap;
+++++   unsigned int bst_ipk = 0;
+++++ 
+++++   /*
+++++    * Digital Boost Converter Configuration for feedback,
+++++    * ramping, switching frequency, and estimation block seeding.
+++++    */
+++++ 
+++++   regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
+++++                      CS35L35_BST_CONV_SWFREQ_MASK, 0x00);
+++++ 
+++++   regmap_read(regmap, CS35L35_BST_PEAK_I, &bst_ipk);
+++++   bst_ipk &= CS35L35_BST_IPK_MASK;
+++++ 
+++++   switch (inductor) {
+++++   case 1000: /* 1 uH */
+++++           regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x24);
+++++           regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x24);
+++++           regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
+++++                              CS35L35_BST_CONV_LBST_MASK, 0x00);
+++++ 
+++++           if (bst_ipk < 0x04)
+++++                   regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);
+++++           else
+++++                   regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x4E);
+++++           break;
+++++   case 1200: /* 1.2 uH */
+++++           regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x20);
+++++           regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x20);
+++++           regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
+++++                              CS35L35_BST_CONV_LBST_MASK, 0x01);
+++++ 
+++++           if (bst_ipk < 0x04)
+++++                   regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);
+++++           else
+++++                   regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x47);
+++++           break;
+++++   case 1500: /* 1.5uH */
+++++           regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x20);
+++++           regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x20);
+++++           regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
+++++                              CS35L35_BST_CONV_LBST_MASK, 0x02);
+++++ 
+++++           if (bst_ipk < 0x04)
+++++                   regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);
+++++           else
+++++                   regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x3C);
+++++           break;
+++++   case 2200: /* 2.2uH */
+++++           regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x19);
+++++           regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x25);
+++++           regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
+++++                              CS35L35_BST_CONV_LBST_MASK, 0x03);
+++++ 
+++++           if (bst_ipk < 0x04)
+++++                   regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);
+++++           else
+++++                   regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x23);
+++++           break;
+++++   default:
+++++           dev_err(cs35l35->dev, "Invalid Inductor Value %d uH\n",
+++++                   inductor);
+++++           return -EINVAL;
+++++   }
+++++   return 0;
+++++ }
+++++ 
      static int cs35l35_codec_probe(struct snd_soc_codec *codec)
      {
        struct cs35l35_private *cs35l35 = snd_soc_codec_get_drvdata(codec);
                                cs35l35->pdata.bst_ipk <<
                                CS35L35_BST_IPK_SHIFT);
      
+++++   ret = cs35l35_boost_inductor(cs35l35, cs35l35->pdata.boost_ind);
+++++   if (ret)
+++++           return ret;
+++++ 
        if (cs35l35->pdata.gain_zc)
                regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL,
                                CS35L35_AMP_GAIN_ZC_MASK,
@@@@@@@ -1203,7 -1195,7 -1195,7 -1195,7 -1195,7 -1269,15 +1277,15 @@@@@@@ static int cs35l35_handle_of_data(struc
                        return -EINVAL;
                }
      
-----           pdata->bst_ipk = (val32 - 1680) / 110;
+++++           pdata->bst_ipk = ((val32 - 1680) / 110) | CS35L35_VALID_PDATA;
+++++   }
+++++ 
+++++   ret = of_property_read_u32(np, "cirrus,boost-ind-nanohenry", &val32);
+++++   if (ret >= 0) {
+++++           pdata->boost_ind = val32;
+++++   } else {
+++++           dev_err(&i2c_client->dev, "Inductor not specified.\n");
+++++           return -EINVAL;
        }
      
        if (of_property_read_u32(np, "cirrus,sp-drv-strength", &val32) >= 0)
@@@@@@@ -1462,7 -1454,7 -1454,7 -1454,7 -1454,7 -1536,7 +1544,7 @@@@@@@ static int cs35l35_i2c_probe(struct i2c
                }
        }
      
 -----  gpiod_set_value_cansleep(cs35l35->reset_gpio, 1);
 +++++  cs35l35_reset(cs35l35);
      
        init_completion(&cs35l35->pdn_done);