summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDimitris Papavasiliou <dpapavas@gmail.com>2019-01-26 08:17:01 -0500
committerMark Brown <broonie@kernel.org>2019-01-28 07:33:59 -0500
commitccc8d6c7b6d2f521a4b10c7f6d027f46c7a686bf (patch)
tree730975bd2d6b63f7c82ccd89af90b614eefb09bd
parent720734a0b66f9ca42ec6663a48702b16e49552ee (diff)
ASoC: pcm512x: Implement the set_bclk_ratio interface
Some boards, such as the HiFiBerry DAC+ Pro, use a pair of external oscillators, to generate 44.1 or 48kHz multiples and are forced to resort to hacks [1] in order to support 24-bit data without ending up with fractional dividers. This patch allows the machine driver to use 32-bit frames for 24-bit data to avoid such issues. Although the datasheet (p. 15) seems to suggest that only a handful of ratios are supported, it's not very explicit about it, so we allow the full range of values supported by the underlying register in the callback, to avoid needlessly rejecting potentially usable configurations. [1] http://mailman.alsa-project.org/pipermail/alsa-devel/2018-December/143442.html Signed-off-by: Dimitris Papavasiliou <dpapavas@gmail.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/codecs/pcm512x.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c
index 4cc24a5d5c31..ce8c5dbd2164 100644
--- a/sound/soc/codecs/pcm512x.c
+++ b/sound/soc/codecs/pcm512x.c
@@ -55,6 +55,7 @@ struct pcm512x_priv {
55 unsigned long overclock_dsp; 55 unsigned long overclock_dsp;
56 int mute; 56 int mute;
57 struct mutex mutex; 57 struct mutex mutex;
58 unsigned int bclk_ratio;
58}; 59};
59 60
60/* 61/*
@@ -915,10 +916,15 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
915 int fssp; 916 int fssp;
916 int gpio; 917 int gpio;
917 918
918 lrclk_div = snd_soc_params_to_frame_size(params); 919 if (pcm512x->bclk_ratio > 0) {
919 if (lrclk_div == 0) { 920 lrclk_div = pcm512x->bclk_ratio;
920 dev_err(dev, "No LRCLK?\n"); 921 } else {
921 return -EINVAL; 922 lrclk_div = snd_soc_params_to_frame_size(params);
923
924 if (lrclk_div == 0) {
925 dev_err(dev, "No LRCLK?\n");
926 return -EINVAL;
927 }
922 } 928 }
923 929
924 if (!pcm512x->pll_out) { 930 if (!pcm512x->pll_out) {
@@ -1383,6 +1389,19 @@ static int pcm512x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1383 return 0; 1389 return 0;
1384} 1390}
1385 1391
1392static int pcm512x_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
1393{
1394 struct snd_soc_component *component = dai->component;
1395 struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
1396
1397 if (ratio > 256)
1398 return -EINVAL;
1399
1400 pcm512x->bclk_ratio = ratio;
1401
1402 return 0;
1403}
1404
1386static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute) 1405static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute)
1387{ 1406{
1388 struct snd_soc_component *component = dai->component; 1407 struct snd_soc_component *component = dai->component;
@@ -1435,6 +1454,7 @@ static const struct snd_soc_dai_ops pcm512x_dai_ops = {
1435 .hw_params = pcm512x_hw_params, 1454 .hw_params = pcm512x_hw_params,
1436 .set_fmt = pcm512x_set_fmt, 1455 .set_fmt = pcm512x_set_fmt,
1437 .digital_mute = pcm512x_digital_mute, 1456 .digital_mute = pcm512x_digital_mute,
1457 .set_bclk_ratio = pcm512x_set_bclk_ratio,
1438}; 1458};
1439 1459
1440static struct snd_soc_dai_driver pcm512x_dai = { 1460static struct snd_soc_dai_driver pcm512x_dai = {