This driver USE PLL for 11025/22050/44100/88200 rate. To enable switching to bypass mode, PLL is always turned on. Special thanks to Phil
Signed-off-by: Phil Edworthy Phil.Edworthy@renesas.com Signed-off-by: Kuninori Morimoto morimoto.kuninori@renesas.com --- sound/soc/codecs/da7210.c | 87 ++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 83 insertions(+), 4 deletions(-)
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index 3bd867d..4083c7e 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -55,8 +55,14 @@ #define DA7210_DAI_SRC_SEL 0x25 #define DA7210_DAI_CFG1 0x26 #define DA7210_DAI_CFG3 0x28 +#define DA7210_PLL_DIV1 0x29 +#define DA7210_PLL_DIV2 0x2A #define DA7210_PLL_DIV3 0x2B #define DA7210_PLL 0x2C +#define DA7210_A_HID_UNLOCK 0x8A +#define DA7210_A_TEST_UNLOCK 0x8B +#define DA7210_A_PLL1 0x90 +#define DA7210_A_CP_MODE 0xA7
/* STARTUP1 bit fields */ #define DA7210_SC_MST_EN (1 << 0) @@ -124,13 +130,17 @@ /* PLL bit fields */ #define DA7210_PLL_FS_MASK (0xF << 0) #define DA7210_PLL_FS_8000 (0x1 << 0) +#define DA7210_PLL_FS_11025 (0x2 << 0) #define DA7210_PLL_FS_12000 (0x3 << 0) #define DA7210_PLL_FS_16000 (0x5 << 0) +#define DA7210_PLL_FS_22050 (0x6 << 0) #define DA7210_PLL_FS_24000 (0x7 << 0) #define DA7210_PLL_FS_32000 (0x9 << 0) +#define DA7210_PLL_FS_44100 (0xA << 0) #define DA7210_PLL_FS_48000 (0xB << 0) +#define DA7210_PLL_FS_88200 (0xE << 0) #define DA7210_PLL_FS_96000 (0xF << 0) - +#define DA7210_PLL_EN (0x1 << 7)
#define DA7210_VERSION "0.0.1"
@@ -249,7 +259,7 @@ static int da7210_hw_params(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = socdev->card->codec; u32 dai_cfg1; u32 hpf_reg, hpf_mask, hpf_value; - u32 fs; + u32 fs, bypass;
/* set DAI source to Left and Right ADC */ da7210_write(codec, DA7210_DAI_SRC_SEL, @@ -281,38 +291,76 @@ static int da7210_hw_params(struct snd_pcm_substream *substream, fs = DA7210_PLL_FS_8000; hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN; hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN; + bypass = DA7210_PLL_BYP; + break; + case 11025: + fs = DA7210_PLL_FS_11025; + hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN; + hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN; + bypass = 0; break; case 12000: fs = DA7210_PLL_FS_12000; hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN; hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN; + bypass = DA7210_PLL_BYP; break; case 16000: fs = DA7210_PLL_FS_16000; hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN; hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN; + bypass = DA7210_PLL_BYP; + break; + case 22050: + fs = DA7210_PLL_FS_22050; + hpf_mask = DA7210_VOICE_EN; + hpf_value = 0; + bypass = 0; break; case 32000: fs = DA7210_PLL_FS_32000; hpf_mask = DA7210_VOICE_EN; hpf_value = 0; + bypass = DA7210_PLL_BYP; + break; + case 44100: + fs = DA7210_PLL_FS_44100; + hpf_mask = DA7210_VOICE_EN; + hpf_value = 0; + bypass = 0; break; case 48000: fs = DA7210_PLL_FS_48000; hpf_mask = DA7210_VOICE_EN; hpf_value = 0; + bypass = DA7210_PLL_BYP; + break; + case 88200: + fs = DA7210_PLL_FS_88200; + hpf_mask = DA7210_VOICE_EN; + hpf_value = 0; + bypass = 0; break; case 96000: fs = DA7210_PLL_FS_96000; hpf_mask = DA7210_VOICE_EN; hpf_value = 0; + bypass = DA7210_PLL_BYP; break; default: return -EINVAL; }
+ /* Disable active mode */ + snd_soc_update_bits(codec, DA7210_STARTUP1, DA7210_SC_MST_EN, 0); + snd_soc_update_bits(codec, hpf_reg, hpf_mask, hpf_value); snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_FS_MASK, fs); + snd_soc_update_bits(codec, DA7210_PLL_DIV3, DA7210_PLL_BYP, bypass); + + /* Enable active mode */ + snd_soc_update_bits(codec, DA7210_STARTUP1, + DA7210_SC_MST_EN, DA7210_SC_MST_EN);
return 0; } @@ -444,9 +492,23 @@ static int da7210_init(struct da7210_priv *da7210) /* FIXME * * This driver use fixed value here + * And below settings expects MCLK = 12.288MHz + * + * When you select different MCLK, please check... + * DA7210_PLL_DIV1 val + * DA7210_PLL_DIV2 val + * DA7210_PLL_DIV3 val + * DA7210_PLL_DIV3 :: DA7210_MCLK_RANGExxx */
/* + * make sure that DA7210 use bypass mode before start up + */ + da7210_write(codec, DA7210_STARTUP1, 0); + da7210_write(codec, DA7210_PLL_DIV3, + DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP); + + /* * ADC settings */
@@ -482,9 +544,26 @@ static int da7210_init(struct da7210_priv *da7210) /* Diable PLL and bypass it */ da7210_write(codec, DA7210_PLL, DA7210_PLL_FS_48000);
- /* Bypass PLL and set MCLK freq rang to 10-20MHz */ - da7210_write(codec, DA7210_PLL_DIV3, + /* + * If 48kHz sound came, it use bypass mode, + * and when it is 44.1kHz, it use PLL. + * + * This time, this driver sets PLL always ON + * and controls bypass/PLL mode by switching + * DA7210_PLL_DIV3 :: DA7210_PLL_BYP bit. + * see da7210_hw_params + */ + da7210_write(codec, DA7210_PLL_DIV1, 0xE5); /* MCLK = 12.288MHz */ + da7210_write(codec, DA7210_PLL_DIV2, 0x99); + da7210_write(codec, DA7210_PLL_DIV3, 0x0A | DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP); + snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN); + + /* As suggested by Dialog */ + da7210_write(codec, DA7210_A_HID_UNLOCK, 0x8B); + da7210_write(codec, DA7210_A_TEST_UNLOCK, 0xB4); + da7210_write(codec, DA7210_A_PLL1, 0x01); + da7210_write(codec, DA7210_A_CP_MODE, 0x7C);
/* Activate all enabled subsystem */ da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);