ASoC: TSCS42xx: Add CCF support to get sysclk
authorSteven Eckhoff <steven.eckhoff.opensource@gmail.com>
Wed, 4 Apr 2018 21:49:52 +0000 (16:49 -0500)
committerMark Brown <broonie@kernel.org>
Mon, 16 Apr 2018 10:53:47 +0000 (11:53 +0100)
The TSCS42xx relies on set_sysclk to get a unique clock id and rate,
which prevents it from being used with the simple-card.

Remove set_sysclk callback
Add CCF support to get clock id and rate
Add clocks and clock-names to device tree binding

Signed-off-by: Steven Eckhoff <steven.eckhoff.opensource@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Documentation/devicetree/bindings/sound/tscs42xx.txt
sound/soc/codecs/tscs42xx.c
sound/soc/codecs/tscs42xx.h

index 2ac2f099669761354469f9550700c00b61e7c91e..7eea32e9d07838aec8d7f30b4e88b39c69da24d3 100644 (file)
@@ -8,9 +8,15 @@ Required Properties:
        - reg :         <0x71> for analog mic
                        <0x69> for digital mic
 
+       - clock-names:  Must one of  the following "mclk1", "xtal", "mclk2"
+
+       - clocks:       phandle of the clock that provides the codec sysclk
+
 Example:
 
 wookie: codec@69 {
        compatible = "tempo,tscs42A2";
        reg = <0x69>;
+       clock-names = "xtal";
+       clocks = <&audio_xtal>;
 };
index bf207b0345f1a6c12554a4768e2560aa2a2cac30..d18ff17719cc617cd0084358dee0623b95223250 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
+#include <linux/clk.h>
 #include <sound/tlv.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
@@ -40,6 +41,9 @@ struct tscs42xx {
        struct mutex pll_lock;
 
        struct regmap *regmap;
+
+       struct clk *sysclk;
+       int sysclk_src_id;
 };
 
 struct coeff_ram_ctl {
@@ -1251,13 +1255,46 @@ static int tscs42xx_set_dai_bclk_ratio(struct snd_soc_dai *codec_dai,
        return 0;
 }
 
-static int tscs42xx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
-       int clk_id, unsigned int freq, int dir)
+static const struct snd_soc_dai_ops tscs42xx_dai_ops = {
+       .hw_params      = tscs42xx_hw_params,
+       .mute_stream    = tscs42xx_mute_stream,
+       .set_fmt        = tscs42xx_set_dai_fmt,
+       .set_bclk_ratio = tscs42xx_set_dai_bclk_ratio,
+};
+
+static int part_is_valid(struct tscs42xx *tscs42xx)
 {
-       struct snd_soc_component *component = codec_dai->component;
+       int val;
        int ret;
+       unsigned int reg;
+
+       ret = regmap_read(tscs42xx->regmap, R_DEVIDH, &reg);
+       if (ret < 0)
+               return ret;
 
-       switch (clk_id) {
+       val = reg << 8;
+       ret = regmap_read(tscs42xx->regmap, R_DEVIDL, &reg);
+       if (ret < 0)
+               return ret;
+
+       val |= reg;
+
+       switch (val) {
+       case 0x4A74:
+       case 0x4A73:
+               return true;
+       default:
+               return false;
+       };
+}
+
+static int set_sysclk(struct snd_soc_component *component)
+{
+       struct tscs42xx *tscs42xx = snd_soc_component_get_drvdata(component);
+       unsigned long freq;
+       int ret;
+
+       switch (tscs42xx->sysclk_src_id) {
        case TSCS42XX_PLL_SRC_XTAL:
        case TSCS42XX_PLL_SRC_MCLK1:
                ret = snd_soc_component_write(component, R_PLLREFSEL,
@@ -1285,6 +1322,7 @@ static int tscs42xx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
                return -EINVAL;
        }
 
+       freq = clk_get_rate(tscs42xx->sysclk);
        ret = set_pll_ctl_from_input_freq(component, freq);
        if (ret < 0) {
                dev_err(component->dev,
@@ -1295,41 +1333,13 @@ static int tscs42xx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
        return 0;
 }
 
-static const struct snd_soc_dai_ops tscs42xx_dai_ops = {
-       .hw_params      = tscs42xx_hw_params,
-       .mute_stream    = tscs42xx_mute_stream,
-       .set_fmt        = tscs42xx_set_dai_fmt,
-       .set_bclk_ratio = tscs42xx_set_dai_bclk_ratio,
-       .set_sysclk     = tscs42xx_set_dai_sysclk,
-};
-
-static int part_is_valid(struct tscs42xx *tscs42xx)
+static int tscs42xx_probe(struct snd_soc_component *component)
 {
-       int val;
-       int ret;
-       unsigned int reg;
-
-       ret = regmap_read(tscs42xx->regmap, R_DEVIDH, &reg);
-       if (ret < 0)
-               return ret;
-
-       val = reg << 8;
-       ret = regmap_read(tscs42xx->regmap, R_DEVIDL, &reg);
-       if (ret < 0)
-               return ret;
-
-       val |= reg;
-
-       switch (val) {
-       case 0x4A74:
-       case 0x4A73:
-               return true;
-       default:
-               return false;
-       };
+       return set_sysclk(component);
 }
 
 static const struct snd_soc_component_driver soc_codec_dev_tscs42xx = {
+       .probe                  = tscs42xx_probe,
        .dapm_widgets           = tscs42xx_dapm_widgets,
        .num_dapm_widgets       = ARRAY_SIZE(tscs42xx_dapm_widgets),
        .dapm_routes            = tscs42xx_intercon,
@@ -1387,11 +1397,15 @@ static const struct reg_sequence tscs42xx_patch[] = {
        { R_AIC2, RV_AIC2_BLRCM_DAC_BCLK_LRCLK_SHARED },
 };
 
+static char const * const src_names[TSCS42XX_PLL_SRC_CNT] = {
+       "xtal", "mclk1", "mclk2"};
+
 static int tscs42xx_i2c_probe(struct i2c_client *i2c,
                const struct i2c_device_id *id)
 {
        struct tscs42xx *tscs42xx;
-       int ret = 0;
+       int src;
+       int ret;
 
        tscs42xx = devm_kzalloc(&i2c->dev, sizeof(*tscs42xx), GFP_KERNEL);
        if (!tscs42xx) {
@@ -1402,6 +1416,24 @@ static int tscs42xx_i2c_probe(struct i2c_client *i2c,
        }
        i2c_set_clientdata(i2c, tscs42xx);
 
+       for (src = TSCS42XX_PLL_SRC_XTAL; src < TSCS42XX_PLL_SRC_CNT; src++) {
+               tscs42xx->sysclk = devm_clk_get(&i2c->dev, src_names[src]);
+               if (!IS_ERR(tscs42xx->sysclk)) {
+                       break;
+               } else if (PTR_ERR(tscs42xx->sysclk) != -ENOENT) {
+                       ret = PTR_ERR(tscs42xx->sysclk);
+                       dev_err(&i2c->dev, "Failed to get sysclk (%d)\n", ret);
+                       return ret;
+               }
+       }
+       if (src == TSCS42XX_PLL_SRC_CNT) {
+               ret = -EINVAL;
+               dev_err(&i2c->dev, "Failed to get a valid clock name (%d)\n",
+                               ret);
+               return ret;
+       }
+       tscs42xx->sysclk_src_id = src;
+
        tscs42xx->regmap = devm_regmap_init_i2c(i2c, &tscs42xx_regmap);
        if (IS_ERR(tscs42xx->regmap)) {
                ret = PTR_ERR(tscs42xx->regmap);
index d4a30bcbf64ba7f7195563d9b2264df37fadd0e2..814c8f3c4a68c83b7e9e2c5dc129ca50b7d5dc1b 100644 (file)
@@ -7,10 +7,10 @@
 #define __WOOKIE_H__
 
 enum {
-       TSCS42XX_PLL_SRC_NONE,
        TSCS42XX_PLL_SRC_XTAL,
        TSCS42XX_PLL_SRC_MCLK1,
        TSCS42XX_PLL_SRC_MCLK2,
+       TSCS42XX_PLL_SRC_CNT,
 };
 
 #define R_HPVOLL        0x0