#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>
        struct mutex pll_lock;
 
        struct regmap *regmap;
+
+       struct clk *sysclk;
+       int sysclk_src_id;
 };
 
 struct coeff_ram_ctl {
        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, ®);
+       if (ret < 0)
+               return ret;
 
-       switch (clk_id) {
+       val = reg << 8;
+       ret = regmap_read(tscs42xx->regmap, R_DEVIDL, ®);
+       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,
                return -EINVAL;
        }
 
+       freq = clk_get_rate(tscs42xx->sysclk);
        ret = set_pll_ctl_from_input_freq(component, freq);
        if (ret < 0) {
                dev_err(component->dev,
        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, ®);
-       if (ret < 0)
-               return ret;
-
-       val = reg << 8;
-       ret = regmap_read(tscs42xx->regmap, R_DEVIDL, ®);
-       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,
        { 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) {
        }
        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);