[alsa-devel] [PATCH 2/2] ASoC: da7210: Add 11025/22050/44100/88200 rate support
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);
On Tue, Mar 02, 2010 at 05:13:50PM +0900, Kuninori Morimoto wrote:
- /* 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);
This will take effect for both playback and capture - what happens if one mode wants bypass and another doesn't? Does the device actually support asymmetric sample rates?
- /* 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);
I suspect you want to disable the HID and test keys when you're done fiddling with the configuration here...
Dear Mark
Thank you for checking patch
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);
This will take effect for both playback and capture - what happens if one mode wants bypass and another doesn't? Does the device actually support asymmetric sample rates?
This chip doesn't support asymmetric sample rates. Is there a method of prohibiting it on ALSA ? Or should I add any lock ?
- /* 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);
I suspect you want to disable the HID and test keys when you're done fiddling with the configuration here...
Ohh sorry. This XXX_UNLOCK doesn't mean "disable".. In default, we can not change value on some register because it is locked. So, this driver unlock it here.
Should I add some comment ?
Best regards -- Kuninori Morimoto
On Wed, Mar 10, 2010 at 11:45:52AM +0900, Kuninori Morimoto wrote:
This chip doesn't support asymmetric sample rates. Is there a method of prohibiting it on ALSA ? Or should I add any lock ?
Set symmetric_rates in the DAI.
- /* 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);
I suspect you want to disable the HID and test keys when you're done fiddling with the configuration here...
Ohh sorry. This XXX_UNLOCK doesn't mean "disable".. In default, we can not change value on some register because it is locked. So, this driver unlock it here.
Should I add some comment ?
No, what I'm saying is that since the registers are supposed to be locked in normal operation you should reset the lock registers so that unintended register writes don't occur in normal operation. The locks will cover more than you're updating here.
participants (2)
-
Kuninori Morimoto
-
Mark Brown