aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/cs4270.c
diff options
context:
space:
mode:
authorTimur Tabi <timur@freescale.com>2007-12-18 09:42:53 -0500
committerJaroslav Kysela <perex@perex.cz>2008-01-31 11:29:42 -0500
commit8432395fd9124aa9408f61c94aa743878b4ddaf9 (patch)
tree9718763653e59c6b1bd86d8a62d927627009e748 /sound/soc/codecs/cs4270.c
parentb7d2a8035a382ad268aba8c0612797b4f2625f61 (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/codecs/cs4270.c')
-rw-r--r--sound/soc/codecs/cs4270.c261
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 */
55static 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 */
155static 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 */
347static 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
674struct snd_soc_codec_dai cs4270_dai = { 671struct 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};
695EXPORT_SYMBOL_GPL(cs4270_dai); 688EXPORT_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