1
0
Fork 0

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: Steven Eckhoff <steven.eckhoff.opensource@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
hifive-unleashed-5.1
Steven Eckhoff 2018-04-04 16:49:52 -05:00 committed by Mark Brown
parent 7ab5ba47e8
commit aa0f18d762
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
3 changed files with 85 additions and 47 deletions

View 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>;
};

View 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,56 +1255,11 @@ 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)
{
struct snd_soc_component *component = codec_dai->component;
int ret;
switch (clk_id) {
case TSCS42XX_PLL_SRC_XTAL:
case TSCS42XX_PLL_SRC_MCLK1:
ret = snd_soc_component_write(component, R_PLLREFSEL,
RV_PLLREFSEL_PLL1_REF_SEL_XTAL_MCLK1 |
RV_PLLREFSEL_PLL2_REF_SEL_XTAL_MCLK1);
if (ret < 0) {
dev_err(component->dev,
"Failed to set pll reference input (%d)\n",
ret);
return ret;
}
break;
case TSCS42XX_PLL_SRC_MCLK2:
ret = snd_soc_component_write(component, R_PLLREFSEL,
RV_PLLREFSEL_PLL1_REF_SEL_MCLK2 |
RV_PLLREFSEL_PLL2_REF_SEL_MCLK2);
if (ret < 0) {
dev_err(component->dev,
"Failed to set PLL reference (%d)\n", ret);
return ret;
}
break;
default:
dev_err(component->dev, "pll src is unsupported\n");
return -EINVAL;
}
ret = set_pll_ctl_from_input_freq(component, freq);
if (ret < 0) {
dev_err(component->dev,
"Failed to setup PLL input freq (%d)\n", ret);
return ret;
}
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)
@ -1329,7 +1288,58 @@ static int part_is_valid(struct tscs42xx *tscs42xx)
};
}
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,
RV_PLLREFSEL_PLL1_REF_SEL_XTAL_MCLK1 |
RV_PLLREFSEL_PLL2_REF_SEL_XTAL_MCLK1);
if (ret < 0) {
dev_err(component->dev,
"Failed to set pll reference input (%d)\n",
ret);
return ret;
}
break;
case TSCS42XX_PLL_SRC_MCLK2:
ret = snd_soc_component_write(component, R_PLLREFSEL,
RV_PLLREFSEL_PLL1_REF_SEL_MCLK2 |
RV_PLLREFSEL_PLL2_REF_SEL_MCLK2);
if (ret < 0) {
dev_err(component->dev,
"Failed to set PLL reference (%d)\n", ret);
return ret;
}
break;
default:
dev_err(component->dev, "pll src is unsupported\n");
return -EINVAL;
}
freq = clk_get_rate(tscs42xx->sysclk);
ret = set_pll_ctl_from_input_freq(component, freq);
if (ret < 0) {
dev_err(component->dev,
"Failed to setup PLL input freq (%d)\n", ret);
return ret;
}
return 0;
}
static int tscs42xx_probe(struct snd_soc_component *component)
{
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);

View 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