summaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/da7210.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/da7210.c')
-rw-r--r--sound/soc/codecs/da7210.c90
1 files changed, 86 insertions, 4 deletions
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index 3bd867de597b..35b881638658 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;
}
@@ -390,6 +438,7 @@ struct snd_soc_dai da7210_dai = {
.formats = DA7210_FORMATS,
},
.ops = &da7210_dai_ops,
+ .symmetric_rates = 1,
};
EXPORT_SYMBOL_GPL(da7210_dai);
@@ -444,7 +493,21 @@ 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 +545,28 @@ 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); /* unlock */
+ da7210_write(codec, DA7210_A_TEST_UNLOCK, 0xB4);
+ da7210_write(codec, DA7210_A_PLL1, 0x01);
+ da7210_write(codec, DA7210_A_CP_MODE, 0x7C);
+ da7210_write(codec, DA7210_A_HID_UNLOCK, 0x00); /* re-lock */
+ da7210_write(codec, DA7210_A_TEST_UNLOCK, 0x00);
/* Activate all enabled subsystem */
da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);