2014-09-28 03:11:37 +08:00
|
|
|
From 0b1d46fef20d096cc3991df89ec793a10df0eaf2 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Daniel Matuschek <info@crazy-audio.com>
|
|
|
|
Date: Wed, 15 Jan 2014 21:41:23 +0100
|
|
|
|
Subject: [PATCH 43/54] ASoC: wm8804: Implement MCLK configuration options, add
|
|
|
|
32bit support WM8804 can run with PLL frequencies of 256xfs and 128xfs for
|
|
|
|
most sample rates. At 192kHz only 128xfs is supported. The existing driver
|
|
|
|
selects 128xfs automatically for some lower samples rates. By using an
|
|
|
|
additional mclk_div divider, it is now possible to control the behaviour.
|
|
|
|
This allows using 256xfs PLL frequency on all sample rates up to 96kHz. It
|
|
|
|
should allow lower jitter and better signal quality. The behavior has to be
|
|
|
|
controlled by the sound card driver, because some sample frequency share the
|
|
|
|
same setting. e.g. 192kHz and 96kHz use 24.576MHz master clock. The only
|
|
|
|
difference is the MCLK divider.
|
|
|
|
|
|
|
|
This also added support for 32bit data.
|
|
|
|
|
|
|
|
Signed-off-by: Daniel Matuschek <daniel@matuschek.net>
|
|
|
|
---
|
|
|
|
sound/soc/codecs/wm8804.c | 19 +++++++++++++++----
|
|
|
|
sound/soc/codecs/wm8804.h | 4 ++++
|
|
|
|
2 files changed, 19 insertions(+), 4 deletions(-)
|
|
|
|
|
|
|
|
--- a/sound/soc/codecs/wm8804.c
|
|
|
|
+++ b/sound/soc/codecs/wm8804.c
|
|
|
|
@@ -63,6 +63,7 @@ struct wm8804_priv {
|
|
|
|
struct regmap *regmap;
|
|
|
|
struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES];
|
|
|
|
struct notifier_block disable_nb[WM8804_NUM_SUPPLIES];
|
|
|
|
+ int mclk_div;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int txsrc_get(struct snd_kcontrol *kcontrol,
|
2014-12-08 20:04:25 +08:00
|
|
|
@@ -277,6 +278,7 @@ static int wm8804_hw_params(struct snd_p
|
2014-09-28 03:11:37 +08:00
|
|
|
blen = 0x1;
|
|
|
|
break;
|
|
|
|
case SNDRV_PCM_FORMAT_S24_LE:
|
|
|
|
+ case SNDRV_PCM_FORMAT_S32_LE:
|
|
|
|
blen = 0x2;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
@@ -318,7 +320,7 @@ static struct {
|
|
|
|
|
|
|
|
#define FIXED_PLL_SIZE ((1ULL << 22) * 10)
|
|
|
|
static int pll_factors(struct pll_div *pll_div, unsigned int target,
|
|
|
|
- unsigned int source)
|
|
|
|
+ unsigned int source, unsigned int mclk_div)
|
|
|
|
{
|
|
|
|
u64 Kpart;
|
|
|
|
unsigned long int K, Ndiv, Nmod, tmp;
|
2014-12-08 20:04:25 +08:00
|
|
|
@@ -330,7 +332,8 @@ static int pll_factors(struct pll_div *p
|
2014-09-28 03:11:37 +08:00
|
|
|
*/
|
|
|
|
for (i = 0; i < ARRAY_SIZE(post_table); i++) {
|
|
|
|
tmp = target * post_table[i].div;
|
|
|
|
- if (tmp >= 90000000 && tmp <= 100000000) {
|
|
|
|
+ if ((tmp >= 90000000 && tmp <= 100000000) &&
|
|
|
|
+ (mclk_div == post_table[i].mclkdiv)) {
|
|
|
|
pll_div->freqmode = post_table[i].freqmode;
|
|
|
|
pll_div->mclkdiv = post_table[i].mclkdiv;
|
|
|
|
target *= post_table[i].div;
|
2014-12-08 20:04:25 +08:00
|
|
|
@@ -387,8 +390,11 @@ static int wm8804_set_pll(struct snd_soc
|
2014-09-28 03:11:37 +08:00
|
|
|
} else {
|
|
|
|
int ret;
|
|
|
|
struct pll_div pll_div;
|
|
|
|
+ struct wm8804_priv *wm8804;
|
|
|
|
|
|
|
|
- ret = pll_factors(&pll_div, freq_out, freq_in);
|
|
|
|
+ wm8804 = snd_soc_codec_get_drvdata(codec);
|
|
|
|
+
|
|
|
|
+ ret = pll_factors(&pll_div, freq_out, freq_in, wm8804->mclk_div);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
2014-12-08 20:04:25 +08:00
|
|
|
@@ -452,6 +458,7 @@ static int wm8804_set_clkdiv(struct snd_
|
2014-09-28 03:11:37 +08:00
|
|
|
int div_id, int div)
|
|
|
|
{
|
|
|
|
struct snd_soc_codec *codec;
|
|
|
|
+ struct wm8804_priv *wm8804;
|
|
|
|
|
|
|
|
codec = dai->codec;
|
|
|
|
switch (div_id) {
|
2014-12-08 20:04:25 +08:00
|
|
|
@@ -459,6 +466,10 @@ static int wm8804_set_clkdiv(struct snd_
|
2014-09-28 03:11:37 +08:00
|
|
|
snd_soc_update_bits(codec, WM8804_PLL5, 0x30,
|
|
|
|
(div & 0x3) << 4);
|
|
|
|
break;
|
|
|
|
+ case WM8804_MCLK_DIV:
|
|
|
|
+ wm8804 = snd_soc_codec_get_drvdata(codec);
|
|
|
|
+ wm8804->mclk_div = div;
|
|
|
|
+ break;
|
|
|
|
default:
|
|
|
|
dev_err(dai->dev, "Unknown clock divider: %d\n", div_id);
|
|
|
|
return -EINVAL;
|
2014-12-08 20:04:25 +08:00
|
|
|
@@ -641,7 +652,7 @@ static const struct snd_soc_dai_ops wm88
|
2014-09-28 03:11:37 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
#define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
|
|
|
|
- SNDRV_PCM_FMTBIT_S24_LE)
|
|
|
|
+ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
|
|
|
|
|
|
|
|
#define WM8804_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
|
|
|
|
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \
|
|
|
|
--- a/sound/soc/codecs/wm8804.h
|
|
|
|
+++ b/sound/soc/codecs/wm8804.h
|
|
|
|
@@ -57,5 +57,9 @@
|
|
|
|
#define WM8804_CLKOUT_SRC_OSCCLK 4
|
|
|
|
|
|
|
|
#define WM8804_CLKOUT_DIV 1
|
|
|
|
+#define WM8804_MCLK_DIV 2
|
|
|
|
+
|
|
|
|
+#define WM8804_MCLKDIV_256FS 0
|
|
|
|
+#define WM8804_MCLKDIV_128FS 1
|
|
|
|
|
|
|
|
#endif /* _WM8804_H */
|