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)
Documentation/devicetree/bindings/sound/cs35l35.txt
include/sound/cs35l35.h
sound/soc/atmel/atmel-pcm.h
sound/soc/codecs/ak4613.c
sound/soc/codecs/ak4642.c
sound/soc/codecs/cs35l34.c
sound/soc/codecs/cs35l35.c
sound/soc/codecs/cs35l35.h

index 016b768bc722b6ca3e16600eb08ddb5a8b711a6d..77ee75c39233f0fcd058f36e568b20d1e8051918 100644 (file)
@@ -16,6 +16,9 @@ Required properties:
     (See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
     for further information relating to interrupt properties)
 
+ - cirrus,boost-ind-nanohenry: Inductor value for boost converter. The value is
+    in nH and they can be values of 1000nH, 1200nH, 1500nH, and 2200nH.
+
 Optional properties:
   - reset-gpios : gpio used to reset the amplifier
 
index 29da899e17e4def3dfe72e1b67eabba795f2fa8c..d69cd7847afde25a6a76d74cbe0e683536384a98 100644 (file)
@@ -99,6 +99,8 @@ struct cs35l35_platform_data {
        bool shared_bst;
        /* Specifies this amp is using an external boost supply */
        bool ext_bst;
+       /* Inductor Value */
+       int boost_ind;
        /* ClassH Algorithm */
        struct classh_cfg classh_algo;
        /* Monitor Config */
index 6eaf081cad5083222e03bf54935ded0130bfec08..4b27aed40a512ac9e1b86ee22e572564b70d3520 100644 (file)
@@ -83,8 +83,7 @@ struct atmel_pcm_dma_params {
 #define ssc_readx(base, reg)            (__raw_readl((base) + (reg)))
 #define ssc_writex(base, reg, value)    __raw_writel((value), (base) + (reg))
 
-#if defined(CONFIG_SND_ATMEL_SOC_PDC) || \
-       defined(CONFIG_SND_ATMEL_SOC_PDC_MODULE)
+#if IS_ENABLED(CONFIG_SND_ATMEL_SOC_PDC)
 int atmel_pcm_pdc_platform_register(struct device *dev);
 void atmel_pcm_pdc_platform_unregister(struct device *dev);
 #else
@@ -97,8 +96,7 @@ static inline void atmel_pcm_pdc_platform_unregister(struct device *dev)
 }
 #endif
 
-#if defined(CONFIG_SND_ATMEL_SOC_DMA) || \
-       defined(CONFIG_SND_ATMEL_SOC_DMA_MODULE)
+#if IS_ENABLED(CONFIG_SND_ATMEL_SOC_DMA)
 int atmel_pcm_dma_platform_register(struct device *dev);
 void atmel_pcm_dma_platform_unregister(struct device *dev);
 #else
index 987918628d5b58f721771706f78655529ade1f71..690edebf029eb53c213ace00c88e39b14c6b3d75 100644 (file)
@@ -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 @@ static const struct reg_default ak4613_reg[] = {
 #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 @@ static void ak4613_dai_shutdown(struct snd_pcm_substream *substream,
        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;
@@ -262,11 +330,9 @@ static int ak4613_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
        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 @@ static bool ak4613_dai_fmt_matching(const struct ak4613_interface *iface,
        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 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream,
        case 48000:
                ctrl2 = DFS_NORMAL_SPEED;
                break;
+       case 64000:
        case 88200:
        case 96000:
                ctrl2 = DFS_DOUBLE_SPEED;
@@ -358,7 +420,6 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream,
        if ((priv->iface == NULL) ||
            (priv->iface == iface)) {
                priv->iface = iface;
-               priv->cnt++;
                ret = 0;
        }
        mutex_unlock(&priv->lock);
@@ -407,7 +468,9 @@ static int ak4613_set_bias_level(struct snd_soc_codec *codec,
 }
 
 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,
 };
@@ -420,8 +483,7 @@ static const struct snd_soc_dai_ops ak4613_dai_ops = {
                                 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 @@ static int ak4613_i2c_probe(struct i2c_client *i2c,
 
        priv->iface             = NULL;
        priv->cnt               = 0;
+       priv->sysclk            = 0;
 
        mutex_init(&priv->lock);
 
index 23ab9646c3514c1c21adbd0166e93eb4eab4b360..66de8a2013a6b1e5b2c54f9512a18e324ed3b81f 100644 (file)
@@ -433,7 +433,7 @@ static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 static int ak4642_set_mcko(struct snd_soc_codec *codec,
                           u32 frequency)
 {
-       u32 fs_list[] = {
+       static const u32 fs_list[] = {
                [0] = 8000,
                [1] = 12000,
                [2] = 16000,
@@ -447,7 +447,7 @@ static int ak4642_set_mcko(struct snd_soc_codec *codec,
                [14] = 29400,
                [15] = 44100,
        };
-       u32 ps_list[] = {
+       static const u32 ps_list[] = {
                [0] = 256,
                [1] = 128,
                [2] = 64,
index 7c5d1510cf2cb293638ce3f7ef360cd5f7789b1c..0a747c66cc6ccc593036775f51ae4eaa050cc850 100644 (file)
@@ -567,12 +567,12 @@ static int cs35l34_pcm_hw_params(struct snd_pcm_substream *substream,
        return ret;
 }
 
-static unsigned int cs35l34_src_rates[] = {
+static const unsigned int cs35l34_src_rates[] = {
        8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
 };
 
 
-static struct snd_pcm_hw_constraint_list cs35l34_constraints = {
+static const struct snd_pcm_hw_constraint_list cs35l34_constraints = {
        .count  = ARRAY_SIZE(cs35l34_src_rates),
        .list   = cs35l34_src_rates,
 };
index 5ff12e4116e56ae164c972015f358db1b88202c8..f1ee184ecab2994424cdca4a6d9a1bbfd526bd5f 100644 (file)
@@ -764,6 +764,76 @@ static int cs35l35_codec_set_sysclk(struct snd_soc_codec *codec,
        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);
@@ -783,6 +853,10 @@ static int cs35l35_codec_probe(struct snd_soc_codec *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 +1277,15 @@ static int cs35l35_handle_of_data(struct i2c_client *i2c_client,
                        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)
index 5a6e43a87c4ddc3e1a6d527c0242cf69af6e87a8..621bfef70d03668883f281d86cce73389120e810 100644 (file)
 #define CS35L35_SP_I2S_DRV_MASK                0x03
 #define CS35L35_SP_I2S_DRV_SHIFT       0
 
+/* Boost Converter Config */
+#define CS35L35_BST_CONV_COEFF_MASK    0xFF
+#define CS35L35_BST_CONV_SLOPE_MASK    0xFF
+#define CS35L35_BST_CONV_LBST_MASK     0x03
+#define CS35L35_BST_CONV_SWFREQ_MASK   0xF0
+
 /* Class H Algorithm Control */
 #define CS35L35_CH_STEREO_MASK         0x40
 #define CS35L35_CH_STEREO_SHIFT                6