diff options
author | Timur Tabi <timur@freescale.com> | 2007-12-18 09:42:53 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-01-31 11:29:42 -0500 |
commit | 8432395fd9124aa9408f61c94aa743878b4ddaf9 (patch) | |
tree | 9718763653e59c6b1bd86d8a62d927627009e748 /sound/soc | |
parent | b7d2a8035a382ad268aba8c0612797b4f2625f61 (diff) |
[ALSA] cs4270: wrong sample rate when CONFIG_SND_SOC_CS4270_VD33_ERRATA is set
When CONFIG_SND_SOC_CS4270_VD33_ERRATA is set, there was a mismatch between
the mclk_ratios[] and cs4270_mode_ratios[] arrays. The two arrays have been
merged and code has been shuffled. One side effect is that the
cs4270_set_dai_sysclk() and cs4270_set_dai_fmt() functions are available only
if I2C has been enabled.
Signed-off-by: Timur Tabi <timur@freescale.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/codecs/cs4270.c | 261 |
1 files changed, 128 insertions, 133 deletions
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index dab22cc97ead..968eda37754c 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -48,12 +48,130 @@ struct cs4270_private { | |||
48 | unsigned int mode; /* The mode (I2S or left-justified) */ | 48 | unsigned int mode; /* The mode (I2S or left-justified) */ |
49 | }; | 49 | }; |
50 | 50 | ||
51 | /* The number of MCLK/LRCK ratios supported by the CS4270 */ | 51 | /* |
52 | #define NUM_MCLK_RATIOS 9 | 52 | * The codec isn't really big-endian or little-endian, since the I2S |
53 | * interface requires data to be sent serially with the MSbit first. | ||
54 | * However, to support BE and LE I2S devices, we specify both here. That | ||
55 | * way, ALSA will always match the bit patterns. | ||
56 | */ | ||
57 | #define CS4270_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ | ||
58 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ | ||
59 | SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ | ||
60 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ | ||
61 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \ | ||
62 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) | ||
63 | |||
64 | #ifdef USE_I2C | ||
65 | |||
66 | /* CS4270 registers addresses */ | ||
67 | #define CS4270_CHIPID 0x01 /* Chip ID */ | ||
68 | #define CS4270_PWRCTL 0x02 /* Power Control */ | ||
69 | #define CS4270_MODE 0x03 /* Mode Control */ | ||
70 | #define CS4270_FORMAT 0x04 /* Serial Format, ADC/DAC Control */ | ||
71 | #define CS4270_TRANS 0x05 /* Transition Control */ | ||
72 | #define CS4270_MUTE 0x06 /* Mute Control */ | ||
73 | #define CS4270_VOLA 0x07 /* DAC Channel A Volume Control */ | ||
74 | #define CS4270_VOLB 0x08 /* DAC Channel B Volume Control */ | ||
75 | |||
76 | #define CS4270_FIRSTREG 0x01 | ||
77 | #define CS4270_LASTREG 0x08 | ||
78 | #define CS4270_NUMREGS (CS4270_LASTREG - CS4270_FIRSTREG + 1) | ||
53 | 79 | ||
54 | /* The actual MCLK/LRCK ratios, in increasing numerical order */ | 80 | /* Bit masks for the CS4270 registers */ |
55 | static unsigned int mclk_ratios[NUM_MCLK_RATIOS] = | 81 | #define CS4270_CHIPID_ID 0xF0 |
56 | {64, 96, 128, 192, 256, 384, 512, 768, 1024}; | 82 | #define CS4270_CHIPID_REV 0x0F |
83 | #define CS4270_PWRCTL_FREEZE 0x80 | ||
84 | #define CS4270_PWRCTL_PDN_ADC 0x20 | ||
85 | #define CS4270_PWRCTL_PDN_DAC 0x02 | ||
86 | #define CS4270_PWRCTL_PDN 0x01 | ||
87 | #define CS4270_MODE_SPEED_MASK 0x30 | ||
88 | #define CS4270_MODE_1X 0x00 | ||
89 | #define CS4270_MODE_2X 0x10 | ||
90 | #define CS4270_MODE_4X 0x20 | ||
91 | #define CS4270_MODE_SLAVE 0x30 | ||
92 | #define CS4270_MODE_DIV_MASK 0x0E | ||
93 | #define CS4270_MODE_DIV1 0x00 | ||
94 | #define CS4270_MODE_DIV15 0x02 | ||
95 | #define CS4270_MODE_DIV2 0x04 | ||
96 | #define CS4270_MODE_DIV3 0x06 | ||
97 | #define CS4270_MODE_DIV4 0x08 | ||
98 | #define CS4270_MODE_POPGUARD 0x01 | ||
99 | #define CS4270_FORMAT_FREEZE_A 0x80 | ||
100 | #define CS4270_FORMAT_FREEZE_B 0x40 | ||
101 | #define CS4270_FORMAT_LOOPBACK 0x20 | ||
102 | #define CS4270_FORMAT_DAC_MASK 0x18 | ||
103 | #define CS4270_FORMAT_DAC_LJ 0x00 | ||
104 | #define CS4270_FORMAT_DAC_I2S 0x08 | ||
105 | #define CS4270_FORMAT_DAC_RJ16 0x18 | ||
106 | #define CS4270_FORMAT_DAC_RJ24 0x10 | ||
107 | #define CS4270_FORMAT_ADC_MASK 0x01 | ||
108 | #define CS4270_FORMAT_ADC_LJ 0x00 | ||
109 | #define CS4270_FORMAT_ADC_I2S 0x01 | ||
110 | #define CS4270_TRANS_ONE_VOL 0x80 | ||
111 | #define CS4270_TRANS_SOFT 0x40 | ||
112 | #define CS4270_TRANS_ZERO 0x20 | ||
113 | #define CS4270_TRANS_INV_ADC_A 0x08 | ||
114 | #define CS4270_TRANS_INV_ADC_B 0x10 | ||
115 | #define CS4270_TRANS_INV_DAC_A 0x02 | ||
116 | #define CS4270_TRANS_INV_DAC_B 0x04 | ||
117 | #define CS4270_TRANS_DEEMPH 0x01 | ||
118 | #define CS4270_MUTE_AUTO 0x20 | ||
119 | #define CS4270_MUTE_ADC_A 0x08 | ||
120 | #define CS4270_MUTE_ADC_B 0x10 | ||
121 | #define CS4270_MUTE_POLARITY 0x04 | ||
122 | #define CS4270_MUTE_DAC_A 0x01 | ||
123 | #define CS4270_MUTE_DAC_B 0x02 | ||
124 | |||
125 | /* | ||
126 | * Clock Ratio Selection for Master Mode with I2C enabled | ||
127 | * | ||
128 | * The data for this chart is taken from Table 5 of the CS4270 reference | ||
129 | * manual. | ||
130 | * | ||
131 | * This table is used to determine how to program the Mode Control register. | ||
132 | * It is also used by cs4270_set_dai_sysclk() to tell ALSA which sampling | ||
133 | * rates the CS4270 currently supports. | ||
134 | * | ||
135 | * Each element in this array corresponds to the ratios in mclk_ratios[]. | ||
136 | * These two arrays need to be in sync. | ||
137 | * | ||
138 | * 'speed_mode' is the corresponding bit pattern to be written to the | ||
139 | * MODE bits of the Mode Control Register | ||
140 | * | ||
141 | * 'mclk' is the corresponding bit pattern to be wirten to the MCLK bits of | ||
142 | * the Mode Control Register. | ||
143 | * | ||
144 | * In situations where a single ratio is represented by multiple speed | ||
145 | * modes, we favor the slowest speed. E.g, for a ratio of 128, we pick | ||
146 | * double-speed instead of quad-speed. However, the CS4270 errata states | ||
147 | * that Divide-By-1.5 can cause failures, so we avoid that mode where | ||
148 | * possible. | ||
149 | * | ||
150 | * ERRATA: There is an errata for the CS4270 where divide-by-1.5 does not | ||
151 | * work if VD = 3.3V. If this effects you, select the | ||
152 | * CONFIG_SND_SOC_CS4270_VD33_ERRATA Kconfig option, and the driver will | ||
153 | * never select any sample rates that require divide-by-1.5. | ||
154 | */ | ||
155 | static struct { | ||
156 | unsigned int ratio; | ||
157 | u8 speed_mode; | ||
158 | u8 mclk; | ||
159 | } cs4270_mode_ratios[] = { | ||
160 | {64, CS4270_MODE_4X, CS4270_MODE_DIV1}, | ||
161 | #ifndef CONFIG_SND_SOC_CS4270_VD33_ERRATA | ||
162 | {96, CS4270_MODE_4X, CS4270_MODE_DIV15}, | ||
163 | #endif | ||
164 | {128, CS4270_MODE_2X, CS4270_MODE_DIV1}, | ||
165 | {192, CS4270_MODE_4X, CS4270_MODE_DIV3}, | ||
166 | {256, CS4270_MODE_1X, CS4270_MODE_DIV1}, | ||
167 | {384, CS4270_MODE_2X, CS4270_MODE_DIV3}, | ||
168 | {512, CS4270_MODE_1X, CS4270_MODE_DIV2}, | ||
169 | {768, CS4270_MODE_1X, CS4270_MODE_DIV3}, | ||
170 | {1024, CS4270_MODE_1X, CS4270_MODE_DIV4} | ||
171 | }; | ||
172 | |||
173 | /* The number of MCLK/LRCK ratios supported by the CS4270 */ | ||
174 | #define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios) | ||
57 | 175 | ||
58 | /* | 176 | /* |
59 | * Determine the CS4270 samples rates. | 177 | * Determine the CS4270 samples rates. |
@@ -97,7 +215,7 @@ static int cs4270_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai, | |||
97 | cs4270->mclk = freq; | 215 | cs4270->mclk = freq; |
98 | 216 | ||
99 | for (i = 0; i < NUM_MCLK_RATIOS; i++) { | 217 | for (i = 0; i < NUM_MCLK_RATIOS; i++) { |
100 | unsigned int rate = freq / mclk_ratios[i]; | 218 | unsigned int rate = freq / cs4270_mode_ratios[i].ratio; |
101 | rates |= snd_pcm_rate_to_rate_bit(rate); | 219 | rates |= snd_pcm_rate_to_rate_bit(rate); |
102 | if (rate < rate_min) | 220 | if (rate < rate_min) |
103 | rate_min = rate; | 221 | rate_min = rate; |
@@ -155,80 +273,6 @@ static int cs4270_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, | |||
155 | } | 273 | } |
156 | 274 | ||
157 | /* | 275 | /* |
158 | * The codec isn't really big-endian or little-endian, since the I2S | ||
159 | * interface requires data to be sent serially with the MSbit first. | ||
160 | * However, to support BE and LE I2S devices, we specify both here. That | ||
161 | * way, ALSA will always match the bit patterns. | ||
162 | */ | ||
163 | #define CS4270_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ | ||
164 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ | ||
165 | SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ | ||
166 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ | ||
167 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \ | ||
168 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) | ||
169 | |||
170 | #ifdef USE_I2C | ||
171 | |||
172 | /* CS4270 registers addresses */ | ||
173 | #define CS4270_CHIPID 0x01 /* Chip ID */ | ||
174 | #define CS4270_PWRCTL 0x02 /* Power Control */ | ||
175 | #define CS4270_MODE 0x03 /* Mode Control */ | ||
176 | #define CS4270_FORMAT 0x04 /* Serial Format, ADC/DAC Control */ | ||
177 | #define CS4270_TRANS 0x05 /* Transition Control */ | ||
178 | #define CS4270_MUTE 0x06 /* Mute Control */ | ||
179 | #define CS4270_VOLA 0x07 /* DAC Channel A Volume Control */ | ||
180 | #define CS4270_VOLB 0x08 /* DAC Channel B Volume Control */ | ||
181 | |||
182 | #define CS4270_FIRSTREG 0x01 | ||
183 | #define CS4270_LASTREG 0x08 | ||
184 | #define CS4270_NUMREGS (CS4270_LASTREG - CS4270_FIRSTREG + 1) | ||
185 | |||
186 | /* Bit masks for the CS4270 registers */ | ||
187 | #define CS4270_CHIPID_ID 0xF0 | ||
188 | #define CS4270_CHIPID_REV 0x0F | ||
189 | #define CS4270_PWRCTL_FREEZE 0x80 | ||
190 | #define CS4270_PWRCTL_PDN_ADC 0x20 | ||
191 | #define CS4270_PWRCTL_PDN_DAC 0x02 | ||
192 | #define CS4270_PWRCTL_PDN 0x01 | ||
193 | #define CS4270_MODE_SPEED_MASK 0x30 | ||
194 | #define CS4270_MODE_1X 0x00 | ||
195 | #define CS4270_MODE_2X 0x10 | ||
196 | #define CS4270_MODE_4X 0x20 | ||
197 | #define CS4270_MODE_SLAVE 0x30 | ||
198 | #define CS4270_MODE_DIV_MASK 0x0E | ||
199 | #define CS4270_MODE_DIV1 0x00 | ||
200 | #define CS4270_MODE_DIV15 0x02 | ||
201 | #define CS4270_MODE_DIV2 0x04 | ||
202 | #define CS4270_MODE_DIV3 0x06 | ||
203 | #define CS4270_MODE_DIV4 0x08 | ||
204 | #define CS4270_MODE_POPGUARD 0x01 | ||
205 | #define CS4270_FORMAT_FREEZE_A 0x80 | ||
206 | #define CS4270_FORMAT_FREEZE_B 0x40 | ||
207 | #define CS4270_FORMAT_LOOPBACK 0x20 | ||
208 | #define CS4270_FORMAT_DAC_MASK 0x18 | ||
209 | #define CS4270_FORMAT_DAC_LJ 0x00 | ||
210 | #define CS4270_FORMAT_DAC_I2S 0x08 | ||
211 | #define CS4270_FORMAT_DAC_RJ16 0x18 | ||
212 | #define CS4270_FORMAT_DAC_RJ24 0x10 | ||
213 | #define CS4270_FORMAT_ADC_MASK 0x01 | ||
214 | #define CS4270_FORMAT_ADC_LJ 0x00 | ||
215 | #define CS4270_FORMAT_ADC_I2S 0x01 | ||
216 | #define CS4270_TRANS_ONE_VOL 0x80 | ||
217 | #define CS4270_TRANS_SOFT 0x40 | ||
218 | #define CS4270_TRANS_ZERO 0x20 | ||
219 | #define CS4270_TRANS_INV_ADC_A 0x08 | ||
220 | #define CS4270_TRANS_INV_ADC_B 0x10 | ||
221 | #define CS4270_TRANS_INV_DAC_A 0x02 | ||
222 | #define CS4270_TRANS_INV_DAC_B 0x04 | ||
223 | #define CS4270_TRANS_DEEMPH 0x01 | ||
224 | #define CS4270_MUTE_AUTO 0x20 | ||
225 | #define CS4270_MUTE_ADC_A 0x08 | ||
226 | #define CS4270_MUTE_ADC_B 0x10 | ||
227 | #define CS4270_MUTE_POLARITY 0x04 | ||
228 | #define CS4270_MUTE_DAC_A 0x01 | ||
229 | #define CS4270_MUTE_DAC_B 0x02 | ||
230 | |||
231 | /* | ||
232 | * A list of addresses on which this CS4270 could use. I2C addresses are | 276 | * A list of addresses on which this CS4270 could use. I2C addresses are |
233 | * 7 bits. For the CS4270, the upper four bits are always 1001, and the | 277 | * 7 bits. For the CS4270, the upper four bits are always 1001, and the |
234 | * lower three bits are determined via the AD2, AD1, and AD0 pins | 278 | * lower three bits are determined via the AD2, AD1, and AD0 pins |
@@ -315,53 +359,6 @@ static int cs4270_i2c_write(struct snd_soc_codec *codec, unsigned int reg, | |||
315 | } | 359 | } |
316 | 360 | ||
317 | /* | 361 | /* |
318 | * Clock Ratio Selection for Master Mode with I2C enabled | ||
319 | * | ||
320 | * The data for this chart is taken from Table 5 of the CS4270 reference | ||
321 | * manual. | ||
322 | * | ||
323 | * This table is used to determine how to program the Mode Control register. | ||
324 | * It is also used by cs4270_set_dai_sysclk() to tell ALSA which sampling | ||
325 | * rates the CS4270 currently supports. | ||
326 | * | ||
327 | * Each element in this array corresponds to the ratios in mclk_ratios[]. | ||
328 | * These two arrays need to be in sync. | ||
329 | * | ||
330 | * 'speed_mode' is the corresponding bit pattern to be written to the | ||
331 | * MODE bits of the Mode Control Register | ||
332 | * | ||
333 | * 'mclk' is the corresponding bit pattern to be wirten to the MCLK bits of | ||
334 | * the Mode Control Register. | ||
335 | * | ||
336 | * In situations where a single ratio is represented by multiple speed | ||
337 | * modes, we favor the slowest speed. E.g, for a ratio of 128, we pick | ||
338 | * double-speed instead of quad-speed. However, the CS4270 errata states | ||
339 | * that Divide-By-1.5 can cause failures, so we avoid that mode where | ||
340 | * possible. | ||
341 | * | ||
342 | * ERRATA: There is an errata for the CS4270 where divide-by-1.5 does not | ||
343 | * work if VD = 3.3V. If this effects you, select the | ||
344 | * CONFIG_SND_SOC_CS4270_VD33_ERRATA Kconfig option, and the driver will | ||
345 | * never select any sample rates that require divide-by-1.5. | ||
346 | */ | ||
347 | static struct { | ||
348 | u8 speed_mode; | ||
349 | u8 mclk; | ||
350 | } cs4270_mode_ratios[NUM_MCLK_RATIOS] = { | ||
351 | {CS4270_MODE_4X, CS4270_MODE_DIV1}, /* 64 */ | ||
352 | #ifndef CONFIG_SND_SOC_CS4270_VD33_ERRATA | ||
353 | {CS4270_MODE_4X, CS4270_MODE_DIV15}, /* 96 */ | ||
354 | #endif | ||
355 | {CS4270_MODE_2X, CS4270_MODE_DIV1}, /* 128 */ | ||
356 | {CS4270_MODE_4X, CS4270_MODE_DIV3}, /* 192 */ | ||
357 | {CS4270_MODE_1X, CS4270_MODE_DIV1}, /* 256 */ | ||
358 | {CS4270_MODE_2X, CS4270_MODE_DIV3}, /* 384 */ | ||
359 | {CS4270_MODE_1X, CS4270_MODE_DIV2}, /* 512 */ | ||
360 | {CS4270_MODE_1X, CS4270_MODE_DIV3}, /* 768 */ | ||
361 | {CS4270_MODE_1X, CS4270_MODE_DIV4} /* 1024 */ | ||
362 | }; | ||
363 | |||
364 | /* | ||
365 | * Program the CS4270 with the given hardware parameters. | 362 | * Program the CS4270 with the given hardware parameters. |
366 | * | 363 | * |
367 | * The .dai_ops functions are used to provide board-specific data, like | 364 | * The .dai_ops functions are used to provide board-specific data, like |
@@ -388,7 +385,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, | |||
388 | ratio = cs4270->mclk / rate; /* MCLK/LRCK ratio */ | 385 | ratio = cs4270->mclk / rate; /* MCLK/LRCK ratio */ |
389 | 386 | ||
390 | for (i = 0; i < NUM_MCLK_RATIOS; i++) { | 387 | for (i = 0; i < NUM_MCLK_RATIOS; i++) { |
391 | if (mclk_ratios[i] == ratio) | 388 | if (cs4270_mode_ratios[i].ratio == ratio) |
392 | break; | 389 | break; |
393 | } | 390 | } |
394 | 391 | ||
@@ -669,7 +666,7 @@ error: | |||
669 | return ret; | 666 | return ret; |
670 | } | 667 | } |
671 | 668 | ||
672 | #endif | 669 | #endif /* USE_I2C*/ |
673 | 670 | ||
674 | struct snd_soc_codec_dai cs4270_dai = { | 671 | struct snd_soc_codec_dai cs4270_dai = { |
675 | .name = "CS4270", | 672 | .name = "CS4270", |
@@ -687,10 +684,6 @@ struct snd_soc_codec_dai cs4270_dai = { | |||
687 | .rates = 0, | 684 | .rates = 0, |
688 | .formats = CS4270_FORMATS, | 685 | .formats = CS4270_FORMATS, |
689 | }, | 686 | }, |
690 | .dai_ops = { | ||
691 | .set_sysclk = cs4270_set_dai_sysclk, | ||
692 | .set_fmt = cs4270_set_dai_fmt, | ||
693 | } | ||
694 | }; | 687 | }; |
695 | EXPORT_SYMBOL_GPL(cs4270_dai); | 688 | EXPORT_SYMBOL_GPL(cs4270_dai); |
696 | 689 | ||
@@ -752,6 +745,8 @@ static int cs4270_probe(struct platform_device *pdev) | |||
752 | if (codec->control_data) { | 745 | if (codec->control_data) { |
753 | /* Initialize codec ops */ | 746 | /* Initialize codec ops */ |
754 | cs4270_dai.ops.hw_params = cs4270_hw_params; | 747 | cs4270_dai.ops.hw_params = cs4270_hw_params; |
748 | cs4270_dai.dai_ops.set_sysclk = cs4270_set_dai_sysclk; | ||
749 | cs4270_dai.dai_ops.set_fmt = cs4270_set_dai_fmt; | ||
755 | #ifdef CONFIG_SND_SOC_CS4270_HWMUTE | 750 | #ifdef CONFIG_SND_SOC_CS4270_HWMUTE |
756 | cs4270_dai.dai_ops.digital_mute = cs4270_mute; | 751 | cs4270_dai.dai_ops.digital_mute = cs4270_mute; |
757 | #endif | 752 | #endif |