ASoC: madera: Read device tree configuration
authorCharles Keepax <ckeepax@opensource.cirrus.com>
Mon, 22 Jul 2019 13:52:09 +0000 (14:52 +0100)
committerMark Brown <broonie@kernel.org>
Mon, 22 Jul 2019 16:34:38 +0000 (17:34 +0100)
Read the configuration of the Madera ASoC driver from device tree.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20190722135209.30302-1-ckeepax@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/madera.c

index 1b1be19a2f991c2146f875752985295065faab74..5f1e32a5a8556e3b578c2918df33ac42dc3f3f82 100644 (file)
@@ -300,6 +300,100 @@ int madera_free_overheat(struct madera_priv *priv)
 }
 EXPORT_SYMBOL_GPL(madera_free_overheat);
 
+static int madera_get_variable_u32_array(struct device *dev,
+                                        const char *propname,
+                                        u32 *dest, int n_max,
+                                        int multiple)
+{
+       int n, ret;
+
+       n = device_property_count_u32(dev, propname);
+       if (n < 0) {
+               if (n == -EINVAL)
+                       return 0;       /* missing, ignore */
+
+               dev_warn(dev, "%s malformed (%d)\n", propname, n);
+
+               return n;
+       } else if ((n % multiple) != 0) {
+               dev_warn(dev, "%s not a multiple of %d entries\n",
+                        propname, multiple);
+
+               return -EINVAL;
+       }
+
+       if (n > n_max)
+               n = n_max;
+
+       ret = device_property_read_u32_array(dev, propname, dest, n);
+       if (ret < 0)
+               return ret;
+
+       return n;
+}
+
+static void madera_prop_get_inmode(struct madera_priv *priv)
+{
+       struct madera *madera = priv->madera;
+       struct madera_codec_pdata *pdata = &madera->pdata.codec;
+       u32 tmp[MADERA_MAX_INPUT * MADERA_MAX_MUXED_CHANNELS];
+       int n, i, in_idx, ch_idx;
+
+       BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode) != MADERA_MAX_INPUT);
+       BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode[0]) != MADERA_MAX_MUXED_CHANNELS);
+
+       n = madera_get_variable_u32_array(madera->dev, "cirrus,inmode",
+                                         tmp, ARRAY_SIZE(tmp),
+                                         MADERA_MAX_MUXED_CHANNELS);
+       if (n < 0)
+               return;
+
+       in_idx = 0;
+       ch_idx = 0;
+       for (i = 0; i < n; ++i) {
+               pdata->inmode[in_idx][ch_idx] = tmp[i];
+
+               if (++ch_idx == MADERA_MAX_MUXED_CHANNELS) {
+                       ch_idx = 0;
+                       ++in_idx;
+               }
+       }
+}
+
+static void madera_prop_get_pdata(struct madera_priv *priv)
+{
+       struct madera *madera = priv->madera;
+       struct madera_codec_pdata *pdata = &madera->pdata.codec;
+       u32 out_mono[ARRAY_SIZE(pdata->out_mono)];
+       int i, n;
+
+       madera_prop_get_inmode(priv);
+
+       n = madera_get_variable_u32_array(madera->dev, "cirrus,out-mono",
+                                         out_mono, ARRAY_SIZE(out_mono), 1);
+       if (n > 0)
+               for (i = 0; i < n; ++i)
+                       pdata->out_mono[i] = !!out_mono[i];
+
+       madera_get_variable_u32_array(madera->dev,
+                                     "cirrus,max-channels-clocked",
+                                     pdata->max_channels_clocked,
+                                     ARRAY_SIZE(pdata->max_channels_clocked),
+                                     1);
+
+       madera_get_variable_u32_array(madera->dev, "cirrus,pdm-fmt",
+                                     pdata->pdm_fmt,
+                                     ARRAY_SIZE(pdata->pdm_fmt), 1);
+
+       madera_get_variable_u32_array(madera->dev, "cirrus,pdm-mute",
+                                     pdata->pdm_mute,
+                                     ARRAY_SIZE(pdata->pdm_mute), 1);
+
+       madera_get_variable_u32_array(madera->dev, "cirrus,dmic-ref",
+                                     pdata->dmic_ref,
+                                     ARRAY_SIZE(pdata->dmic_ref), 1);
+}
+
 int madera_core_init(struct madera_priv *priv)
 {
        int i;
@@ -308,6 +402,9 @@ int madera_core_init(struct madera_priv *priv)
        BUILD_BUG_ON(!madera_mixer_texts[MADERA_NUM_MIXER_INPUTS - 1]);
        BUILD_BUG_ON(!madera_mixer_values[MADERA_NUM_MIXER_INPUTS - 1]);
 
+       if (!dev_get_platdata(priv->madera->dev))
+               madera_prop_get_pdata(priv);
+
        mutex_init(&priv->rate_lock);
 
        for (i = 0; i < MADERA_MAX_HP_OUTPUT; i++)