Commit aa0f18d7 authored by Steven Eckhoff's avatar Steven Eckhoff Committed by Mark Brown

ASoC: TSCS42xx: Add CCF support to get sysclk

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: default avatarSteven Eckhoff <steven.eckhoff.opensource@gmail.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 7ab5ba47
...@@ -8,9 +8,15 @@ Required Properties: ...@@ -8,9 +8,15 @@ Required Properties:
- reg : <0x71> for analog mic - reg : <0x71> for analog mic
<0x69> for digital 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: Example:
wookie: codec@69 { wookie: codec@69 {
compatible = "tempo,tscs42A2"; compatible = "tempo,tscs42A2";
reg = <0x69>; reg = <0x69>;
clock-names = "xtal";
clocks = <&audio_xtal>;
}; };
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/clk.h>
#include <sound/tlv.h> #include <sound/tlv.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/soc.h> #include <sound/soc.h>
...@@ -40,6 +41,9 @@ struct tscs42xx { ...@@ -40,6 +41,9 @@ struct tscs42xx {
struct mutex pll_lock; struct mutex pll_lock;
struct regmap *regmap; struct regmap *regmap;
struct clk *sysclk;
int sysclk_src_id;
}; };
struct coeff_ram_ctl { struct coeff_ram_ctl {
...@@ -1251,13 +1255,46 @@ static int tscs42xx_set_dai_bclk_ratio(struct snd_soc_dai *codec_dai, ...@@ -1251,13 +1255,46 @@ static int tscs42xx_set_dai_bclk_ratio(struct snd_soc_dai *codec_dai,
return 0; return 0;
} }
static int tscs42xx_set_dai_sysclk(struct snd_soc_dai *codec_dai, static const struct snd_soc_dai_ops tscs42xx_dai_ops = {
int clk_id, unsigned int freq, int dir) .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; 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_XTAL:
case TSCS42XX_PLL_SRC_MCLK1: case TSCS42XX_PLL_SRC_MCLK1:
ret = snd_soc_component_write(component, R_PLLREFSEL, ret = snd_soc_component_write(component, R_PLLREFSEL,
...@@ -1285,6 +1322,7 @@ static int tscs42xx_set_dai_sysclk(struct snd_soc_dai *codec_dai, ...@@ -1285,6 +1322,7 @@ static int tscs42xx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
return -EINVAL; return -EINVAL;
} }
freq = clk_get_rate(tscs42xx->sysclk);
ret = set_pll_ctl_from_input_freq(component, freq); ret = set_pll_ctl_from_input_freq(component, freq);
if (ret < 0) { if (ret < 0) {
dev_err(component->dev, dev_err(component->dev,
...@@ -1295,41 +1333,13 @@ static int tscs42xx_set_dai_sysclk(struct snd_soc_dai *codec_dai, ...@@ -1295,41 +1333,13 @@ static int tscs42xx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
return 0; return 0;
} }
static const struct snd_soc_dai_ops tscs42xx_dai_ops = { static int tscs42xx_probe(struct snd_soc_component *component)
.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)
{ {
int val; return set_sysclk(component);
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;
};
} }
static const struct snd_soc_component_driver soc_codec_dev_tscs42xx = { static const struct snd_soc_component_driver soc_codec_dev_tscs42xx = {
.probe = tscs42xx_probe,
.dapm_widgets = tscs42xx_dapm_widgets, .dapm_widgets = tscs42xx_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(tscs42xx_dapm_widgets), .num_dapm_widgets = ARRAY_SIZE(tscs42xx_dapm_widgets),
.dapm_routes = tscs42xx_intercon, .dapm_routes = tscs42xx_intercon,
...@@ -1387,11 +1397,15 @@ static const struct reg_sequence tscs42xx_patch[] = { ...@@ -1387,11 +1397,15 @@ static const struct reg_sequence tscs42xx_patch[] = {
{ R_AIC2, RV_AIC2_BLRCM_DAC_BCLK_LRCLK_SHARED }, { 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, static int tscs42xx_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct tscs42xx *tscs42xx; struct tscs42xx *tscs42xx;
int ret = 0; int src;
int ret;
tscs42xx = devm_kzalloc(&i2c->dev, sizeof(*tscs42xx), GFP_KERNEL); tscs42xx = devm_kzalloc(&i2c->dev, sizeof(*tscs42xx), GFP_KERNEL);
if (!tscs42xx) { if (!tscs42xx) {
...@@ -1402,6 +1416,24 @@ static int tscs42xx_i2c_probe(struct i2c_client *i2c, ...@@ -1402,6 +1416,24 @@ static int tscs42xx_i2c_probe(struct i2c_client *i2c,
} }
i2c_set_clientdata(i2c, 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); tscs42xx->regmap = devm_regmap_init_i2c(i2c, &tscs42xx_regmap);
if (IS_ERR(tscs42xx->regmap)) { if (IS_ERR(tscs42xx->regmap)) {
ret = PTR_ERR(tscs42xx->regmap); ret = PTR_ERR(tscs42xx->regmap);
......
...@@ -7,10 +7,10 @@ ...@@ -7,10 +7,10 @@
#define __WOOKIE_H__ #define __WOOKIE_H__
enum { enum {
TSCS42XX_PLL_SRC_NONE,
TSCS42XX_PLL_SRC_XTAL, TSCS42XX_PLL_SRC_XTAL,
TSCS42XX_PLL_SRC_MCLK1, TSCS42XX_PLL_SRC_MCLK1,
TSCS42XX_PLL_SRC_MCLK2, TSCS42XX_PLL_SRC_MCLK2,
TSCS42XX_PLL_SRC_CNT,
}; };
#define R_HPVOLL 0x0 #define R_HPVOLL 0x0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment