[alsa-devel] [RFC PATCH] ASoC: pcm512x: enable set_sysclk callback
Pierre-Louis Bossart
pierre-louis.bossart at linux.intel.com
Fri Jun 1 23:26:43 CEST 2018
For codec master mode, the current pcm512x code relies on the clock API.
Simple boards such as Hifiberry DAC+ PRO rely on 2 local oscillators
to generate 44.1 or 48kHz multiples, with the clock selection being
handled by the machine driver toggling GPIOS.
The RaspberryPi kernel exposes a "hifiberry,dacpro-clk" clock driver
which does nothing but tell the codec driver what rate is set by the
machine driver [1][2]
This patch suggests an alternate fallback solution to let the codec
driver know what the sysclk is based on the existing .set_sysclk
callback.
[1] https://github.com/raspberrypi/linux/blob/rpi-4.14.y/sound/soc/bcm/hifiberry_dacplus.c
[2] https://github.com/raspberrypi/linux/blob/rpi-4.14.y/drivers/clk/clk-hifiberry-dacpro.c
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>
---
sound/soc/codecs/pcm512x.c | 33 +++++++++++++++++++++++++++++----
1 file changed, 29 insertions(+), 4 deletions(-)
diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c
index f0f2d4fd3769..8d6c173c1e25 100644
--- a/sound/soc/codecs/pcm512x.c
+++ b/sound/soc/codecs/pcm512x.c
@@ -40,6 +40,7 @@ static const char * const pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = {
struct pcm512x_priv {
struct regmap *regmap;
struct clk *sclk;
+ int sysclk;
struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES];
struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES];
int fmt;
@@ -519,6 +520,29 @@ static int pcm512x_hw_rule_rate(struct snd_pcm_hw_params *params,
ARRAY_SIZE(ranges), ranges, 0);
}
+static int sclk_get_rate(struct pcm512x_priv *pcm512x)
+{
+ if (!IS_ERR(pcm512x->sclk))
+ return clk_get_rate(pcm512x->sclk);
+ else
+ return pcm512x->sysclk;
+}
+
+static int pcm512x_set_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_component *component = dai->component;
+ struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
+
+ switch (freq) {
+ case 22579200:
+ case 24576000:
+ pcm512x->sysclk = freq;
+ return 0;
+ }
+ return -EINVAL;
+}
+
static int pcm512x_dai_startup_master(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@@ -528,7 +552,7 @@ static int pcm512x_dai_startup_master(struct snd_pcm_substream *substream,
struct snd_pcm_hw_constraint_ratnums *constraints_no_pll;
struct snd_ratnum *rats_no_pll;
- if (IS_ERR(pcm512x->sclk)) {
+ if (IS_ERR(pcm512x->sclk) && !pcm512x->sysclk) {
dev_err(dev, "Need SCLK for master mode: %ld\n",
PTR_ERR(pcm512x->sclk));
return PTR_ERR(pcm512x->sclk);
@@ -551,7 +575,7 @@ static int pcm512x_dai_startup_master(struct snd_pcm_substream *substream,
if (!rats_no_pll)
return -ENOMEM;
constraints_no_pll->rats = rats_no_pll;
- rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
+ rats_no_pll->num = sclk_get_rate(pcm512x) / 64;
rats_no_pll->den_min = 1;
rats_no_pll->den_max = 128;
rats_no_pll->den_step = 1;
@@ -858,7 +882,7 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
}
if (!pcm512x->pll_out) {
- sck_rate = clk_get_rate(pcm512x->sclk);
+ sck_rate = sclk_get_rate(pcm512x);
bclk_div = params->rate_den * 64 / lrclk_div;
bclk_rate = DIV_ROUND_CLOSEST(sck_rate, bclk_div);
@@ -875,7 +899,7 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
}
bclk_rate = ret;
- pllin_rate = clk_get_rate(pcm512x->sclk);
+ pllin_rate = sclk_get_rate(pcm512x);
sck_rate = pcm512x_find_sck(dai, bclk_rate);
if (!sck_rate)
@@ -1323,6 +1347,7 @@ static const struct snd_soc_dai_ops pcm512x_dai_ops = {
.startup = pcm512x_dai_startup,
.hw_params = pcm512x_hw_params,
.set_fmt = pcm512x_set_fmt,
+ .set_sysclk = pcm512x_set_sysclk,
};
static struct snd_soc_dai_driver pcm512x_dai = {
--
2.14.1
More information about the Alsa-devel
mailing list