2 * cs42l52.c -- CS42L52 ALSA SoC audio driver
4 * Copyright 2007 CirrusLogic, Inc.
6 * Author: Bo Liu <Bo.Liu@cirrus.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * Nov 2007 Initial version.
13 * Oct 2008 Updated to 2.6.26
17 #include <linux/module.h>
18 #include <linux/moduleparam.h>
19 #include <linux/version.h>
20 #include <linux/kernel.h>
21 #include <linux/init.h>
22 #include <linux/delay.h>
24 #include <linux/i2c.h>
25 #include <linux/platform_device.h>
26 #include <linux/spi/spi.h>
27 #include <sound/core.h>
28 #include <sound/pcm.h>
29 #include <sound/pcm_params.h>
30 #include <sound/soc.h>
31 #include <sound/soc-dapm.h>
32 #include <sound/initval.h>
33 #include <sound/tlv.h>
35 #include <linux/types.h>
36 #include <linux/device.h>
39 //#include "cs42L52_control.h"
42 #define SOCDBG(fmt, arg...) printk(KERN_ERR "%s: %s() " fmt, SOC_CS42L52_NAME, __FUNCTION__, ##arg)
44 #define SOCDBG(fmt, arg...)
46 #define SOCINF(fmt, args...) printk(KERN_INFO "%s: " fmt, SOC_CS42L52_NAME, ##args)
47 #define SOCERR(fmt, args...) printk(KERN_ERR "%s: " fmt, SOC_CS42L52_NAME, ##args)
49 static void soc_cs42l52_work(struct work_struct *work);
50 static int soc_cs42l52_set_bias_level(struct snd_soc_codec *codec,
51 enum snd_soc_bias_level level);
52 static int soc_cs42l52_pcm_hw_params(struct snd_pcm_substream *substream,
53 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai);
54 static int soc_cs42l52_set_sysclk(struct snd_soc_dai *codec_dai,
55 int clk_id, u_int freq, int dir);
57 static int soc_cs42l52_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
60 static int soc_cs42l52_digital_mute(struct snd_soc_dai *dai, int mute);
61 static int soc_cs42l52_set_fmt(struct snd_soc_dai *codec_dai,
63 static unsigned int soc_cs42l52_read(struct snd_soc_codec *codec,
67 * snd_soc_get_volsw - single mixer get callback
68 * @kcontrol: mixer control
69 * @uinfo: control element information
71 * Callback to get the value of a single mixer control.
73 * Returns 0 for success.
75 int snd_soc_cs42l5x_get_volsw(struct snd_kcontrol *kcontrol,
76 struct snd_ctl_elem_value *ucontrol)
78 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
79 int reg = kcontrol->private_value & 0xff;
80 int shift = (kcontrol->private_value >> 8) & 0x0f;
81 int rshift = (kcontrol->private_value >> 12) & 0x0f;
82 int max = (kcontrol->private_value >> 16) & 0xff;
83 int mask = (1 << fls(max)) - 1;
84 int min = (kcontrol->private_value >> 24) & 0xff;
86 ucontrol->value.integer.value[0] =
87 ((snd_soc_read(codec, reg) >> shift) - min) & mask;
89 ucontrol->value.integer.value[1] =
90 ((snd_soc_read(codec, reg) >> rshift) - min) & mask;
96 * snd_soc_put_volsw - single mixer put callback
97 * @kcontrol: mixer control
98 * @uinfo: control element information
100 * Callback to set the value of a single mixer control.
102 * Returns 0 for success.
104 int snd_soc_cs42l5x_put_volsw(struct snd_kcontrol *kcontrol,
105 struct snd_ctl_elem_value *ucontrol)
107 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
108 int reg = kcontrol->private_value & 0xff;
109 int shift = (kcontrol->private_value >> 8) & 0x0f;
110 int rshift = (kcontrol->private_value >> 12) & 0x0f;
111 int max = (kcontrol->private_value >> 16) & 0xff;
112 int mask = (1 << fls(max)) - 1;
113 int min = (kcontrol->private_value >> 24) & 0xff;
114 unsigned short val, val2, val_mask;
116 val = ((ucontrol->value.integer.value[0] + min) & mask);
118 val_mask = mask << shift;
120 if (shift != rshift) {
121 val2 = ((ucontrol->value.integer.value[1] + min) & mask);
122 val_mask |= mask << rshift;
123 val |= val2 << rshift;
125 return snd_soc_update_bits(codec, reg, val_mask, val);
129 * snd_soc_info_volsw_2r - double mixer info callback
130 * @kcontrol: mixer control
131 * @uinfo: control element information
133 * Callback to provide information about a double mixer control that
134 * spans 2 codec registers.
136 * Returns 0 for success.
138 int snd_soc_cs42l5x_info_volsw_2r(struct snd_kcontrol *kcontrol,
139 struct snd_ctl_elem_info *uinfo)
141 int max = (kcontrol->private_value >> 8) & 0xff;
144 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
146 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
149 uinfo->value.integer.min = 0;
150 uinfo->value.integer.max = max;
155 * snd_soc_get_volsw_2r - double mixer get callback
156 * @kcontrol: mixer control
157 * @uinfo: control element information
159 * Callback to get the value of a double mixer control that spans 2 registers.
161 * Returns 0 for success.
163 int snd_soc_cs42l5x_get_volsw_2r(struct snd_kcontrol *kcontrol,
164 struct snd_ctl_elem_value *ucontrol)
166 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
167 int reg = kcontrol->private_value & 0xff;
168 int reg2 = (kcontrol->private_value >> 24) & 0xff;
169 int max = (kcontrol->private_value >> 8) & 0xff;
170 int min = (kcontrol->private_value >> 16) & 0xff;
171 int mask = (1<<fls(max))-1;
174 val = snd_soc_read(codec, reg);
175 val2 = snd_soc_read(codec, reg2);
176 ucontrol->value.integer.value[0] = (val - min) & mask;
177 ucontrol->value.integer.value[1] = (val2 - min) & mask;
179 SOCDBG("reg[%02x:%02x] = %02x:%02x ucontrol[%02x:%02x], min = %02x, max = %02x, mask %02x\n",
181 ucontrol->value.integer.value[0], ucontrol->value.integer.value[1],
188 * snd_soc_put_volsw_2r - double mixer set callback
189 * @kcontrol: mixer control
190 * @uinfo: control element information
192 * Callback to set the value of a double mixer control that spans 2 registers.
194 * Returns 0 for success.
196 int snd_soc_cs42l5x_put_volsw_2r(struct snd_kcontrol *kcontrol,
197 struct snd_ctl_elem_value *ucontrol)
199 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
200 int reg = kcontrol->private_value & 0xff;
201 int reg2 = (kcontrol->private_value >> 24) & 0xff;
202 int max = (kcontrol->private_value >> 8) & 0xff;
203 int min = (kcontrol->private_value >> 16) & 0xff;
204 int mask = (1 << fls(max)) - 1;
206 unsigned short val, val2;
208 val = (ucontrol->value.integer.value[0] + min) & mask;
209 val2 = (ucontrol->value.integer.value[1] + min) & mask;
211 if ((err = snd_soc_update_bits(codec, reg, mask, val)) < 0)
214 err = snd_soc_update_bits(codec, reg2, mask, val2);
216 SOCDBG("reg[%02x:%02x] = %02x:%02x, ucontrol[%02x:%02x], min = %02x, max = %02x, mask = %02x\n",
217 reg, reg2, val, val2,
218 ucontrol->value.integer.value[0], ucontrol->value.integer.value[1],
224 #define SOC_SINGLE_CS42L52(xname, reg, shift, max, min) \
225 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
226 .info = snd_soc_info_volsw, .get = snd_soc_cs42l5x_get_volsw,\
227 .put = snd_soc_cs42l5x_put_volsw, \
228 .private_value = SOC_SINGLE_VALUE(reg, shift, max, min) }
230 #define SOC_DOUBLE_CS42L52(xname, reg, shift_left, shift_right, max, min) \
231 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
232 .info = snd_soc_info_volsw, .get = snd_soc_cs42l5x_get_volsw, \
233 .put = snd_soc_cs42l5x_put_volsw, \
234 .private_value = (reg) | ((shift_left) << 8) | \
235 ((shift_right) << 12) | ((max) << 16) | ((min) << 24) }
237 /* No shifts required */
238 #define SOC_DOUBLE_R_CS42L52(xname, reg_left, reg_right, max, min) \
239 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
240 .info = snd_soc_cs42l5x_info_volsw_2r, \
241 .get = snd_soc_cs42l5x_get_volsw_2r, .put = snd_soc_cs42l5x_put_volsw_2r, \
242 .private_value = (reg_left) | ((max) << 8) | ((min) << 16) | \
243 ((reg_right) << 24) }
247 * CS42L52 register default value
250 static const u8 soc_cs42l52_reg_default[] = {
251 0x00, 0xE0, 0x01, 0x07, 0x05, /*4*/
252 0xa0, 0x00, 0x00, 0x81, /*8*/
253 0x81, 0xa5, 0x00, 0x00, /*12*/
254 0x60, 0x02, 0x00, 0x00, /*16*/
255 0x00, 0x00, 0x00, 0x00, /*20*/
256 0x00, 0x00, 0x00, 0x80, /*24*/
257 0x80, 0x00, 0x00, 0x00, /*28*/
258 0x00, 0x00, 0x88, 0x00, /*32*/
259 0x00, 0x00, 0x00, 0x00, /*36*/
260 0x00, 0x00, 0x00, 0x7f, /*40*/
261 0xc0, 0x00, 0x3f, 0x00, /*44*/
262 0x00, 0x00, 0x00, 0x00, /*48*/
263 0x00, 0x3b, 0x00, 0x5f, /*52*/
266 static inline int soc_cs42l52_read_reg_cache(struct snd_soc_codec *codec,
269 u8 *cache = codec->reg_cache;
271 return reg > SOC_CS42L52_REG_NUM ? -EINVAL : cache[reg];
274 static inline void soc_cs42l52_write_reg_cache(struct snd_soc_codec *codec,
275 u_int reg, u_int val)
277 u8 *cache = codec->reg_cache;
279 if(reg > SOC_CS42L52_REG_NUM)
281 cache[reg] = val & 0xff;
284 static int soc_cs42l52_write(struct snd_soc_codec *codec,
285 unsigned reg, u_int val)
290 struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*)codec->private_data;
292 datas[0] = reg & 0xff; /*reg addr*/
293 datas[1] = val & 0xff; /*reg val*/
295 if(info->flags & SOC_CS42L52_ALL_IN_ONE)
297 for(i = 0; i < codec->num_dai; i++)
299 if(codec->hw_write(codec->control_data, datas, 2) != 2)
308 if(info->flags & SOC_CS42L52_CHIP_SWICTH)
310 num = info->flags & SOC_CS42L52_CHIP_MASK;
313 if(codec->hw_write(codec->control_data, datas, 2) != 2)
317 printk(KERN_INFO"soc_cs42l52_write---reg=%d--val=%d\n",reg,val);
319 soc_cs42l52_write_reg_cache(codec, reg, val);
323 return codec->write(codec, reg, val);
327 static unsigned int soc_cs42l52_read(struct snd_soc_codec *codec,
335 struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*)codec->private_data;
336 #ifndef CONFIG_CS42L52_DEBUG
337 if(reg == CODEC_CS42L52_SPK_STATUS)
341 if(info->flags & SOC_CS42L52_ALL_IN_ONE)
344 for(i = 0; i < codec->num_dai; i++)
346 if(codec->hw_write(codec->control_data, &addr, 1) == 1)
348 // if(codec->hw_read(codec->control_data, &data, 1) == 1)
350 // ret |= data << (i * 8);
360 #ifndef CONFIG_CS42L52_DEBUG
365 u8 *cache = codec->reg_cache;
367 retval = reg > SOC_CS42L52_REG_NUM ? -EINVAL : cache[reg];
368 /* SOCDBG("%s (cache) 0x%x = %02x (%d)\n", reg, retval, retval); */
372 // SOCDBG("0x%x = %02x (%d)\n", reg, ret, ret);
375 return codec->read(codec, reg);
379 static const char *cs42l52_mic_bias[] = {"0.5VA", "0.6VA", "0.7VA", "0.8VA", "0.83VA", "0.91VA"};
380 static const char *cs42l52_hpf_freeze[] = {"Continuous DC Subtraction", "Frozen DC Subtraction"};
381 static const char *cs42l52_hpf_corner_freq[] = {"Normal", "119Hz", "236Hz", "464Hz"};
382 static const char *cs42l52_adc_sum[] = {"Normal", "Sum half", "Sub half", "Inverted"};
383 static const char *cs42l52_sig_polarity[] = {"Normal", "Inverted"};
384 static const char *cs42l52_spk_mono_channel[] = {"ChannelA", "ChannelB"};
385 static const char *cs42l52_beep_type[] = {"Off", "Single", "Multiple", "Continuous"};
386 static const char *cs42l52_treble_freq[] = {"5kHz", "7kHz", "10kHz", "15kHz"};
387 static const char *cs42l52_bass_freq[] = {"50Hz", "100Hz", "200Hz", "250Hz"};
388 static const char *cs42l52_target_sel[] = {"Apply Specific", "Apply All"};
389 static const char *cs42l52_noise_gate_delay[] = {"50ms", "100ms", "150ms", "200ms"};
390 static const char *cs42l52_adc_mux[] = {"AIN1", "AIN2", "AIN3", "AIN4", "PGA"};
391 static const char *cs42l52_mic_mux[] = {"MIC1", "MIC2"};
392 static const char *cs42l52_stereo_mux[] = {"Mono", "Stereo"};
393 static const char *cs42l52_off[] = {"On", "Off"};
394 static const char *cs42l52_hpmux[] = {"Off", "On"};
396 static const struct soc_enum soc_cs42l52_enum[] = {
397 SOC_ENUM_DOUBLE(CODEC_CS42L52_ANALOG_HPF_CTL, 4, 6, 2, cs42l52_hpf_freeze), /*0*/
398 SOC_ENUM_SINGLE(CODEC_CS42L52_ADC_HPF_FREQ, 0, 4, cs42l52_hpf_corner_freq),
399 SOC_ENUM_SINGLE(CODEC_CS42L52_ADC_MISC_CTL, 4, 4, cs42l52_adc_sum),
400 SOC_ENUM_DOUBLE(CODEC_CS42L52_ADC_MISC_CTL, 2, 3, 2, cs42l52_sig_polarity),
401 SOC_ENUM_DOUBLE(CODEC_CS42L52_PB_CTL1, 2, 3, 2, cs42l52_sig_polarity),
402 SOC_ENUM_SINGLE(CODEC_CS42L52_PB_CTL2, 2, 2, cs42l52_spk_mono_channel), /*5*/
403 SOC_ENUM_SINGLE(CODEC_CS42L52_BEEP_TONE_CTL, 6, 4, cs42l52_beep_type),
404 SOC_ENUM_SINGLE(CODEC_CS42L52_BEEP_TONE_CTL, 3, 4, cs42l52_treble_freq),
405 SOC_ENUM_SINGLE(CODEC_CS42L52_BEEP_TONE_CTL, 1, 4, cs42l52_bass_freq),
406 SOC_ENUM_SINGLE(CODEC_CS42L52_LIMITER_CTL2, 6, 2, cs42l52_target_sel),
407 SOC_ENUM_SINGLE(CODEC_CS42L52_NOISE_GATE_CTL, 7, 2, cs42l52_target_sel), /*10*/
408 SOC_ENUM_SINGLE(CODEC_CS42L52_NOISE_GATE_CTL, 0, 4, cs42l52_noise_gate_delay),
409 SOC_ENUM_SINGLE(CODEC_CS42L52_ADC_PGA_A, 5, 5, cs42l52_adc_mux),
410 SOC_ENUM_SINGLE(CODEC_CS42L52_ADC_PGA_B, 5, 5, cs42l52_adc_mux),
411 SOC_ENUM_SINGLE(CODEC_CS42L52_MICA_CTL, 6, 2, cs42l52_mic_mux),
412 SOC_ENUM_SINGLE(CODEC_CS42L52_MICB_CTL, 6, 2, cs42l52_mic_mux), /*15*/
413 SOC_ENUM_SINGLE(CODEC_CS42L52_MICA_CTL, 5, 2, cs42l52_stereo_mux),
414 SOC_ENUM_SINGLE(CODEC_CS42L52_MICB_CTL, 5, 2, cs42l52_stereo_mux),
415 SOC_ENUM_SINGLE(CODEC_CS42L52_IFACE_CTL2, 0, 6, cs42l52_mic_bias), /*18*/
416 SOC_ENUM_SINGLE(CODEC_CS42L52_PWCTL2, 0, 2, cs42l52_off),
417 SOC_ENUM_SINGLE(CODEC_CS42L52_MISC_CTL, 6, 2, cs42l52_hpmux),
418 SOC_ENUM_SINGLE(CODEC_CS42L52_MISC_CTL, 7, 2, cs42l52_hpmux),
421 static const struct snd_kcontrol_new soc_cs42l52_controls[] = {
423 SOC_ENUM("Mic VA Capture Switch", soc_cs42l52_enum[18]), /*0*/
424 SOC_DOUBLE("HPF Capture Switch", CODEC_CS42L52_ANALOG_HPF_CTL, 5, 7, 1, 0),
425 SOC_ENUM("HPF Freeze Capture Switch", soc_cs42l52_enum[0]),
427 SOC_DOUBLE("Analog SR Capture Switch", CODEC_CS42L52_ANALOG_HPF_CTL, 1, 3, 1, 1),
428 SOC_DOUBLE("Analog ZC Capture Switch", CODEC_CS42L52_ANALOG_HPF_CTL, 0, 2, 1, 1),
429 SOC_ENUM("HPF corner freq Capture Switch", soc_cs42l52_enum[1]), /*5*/
431 SOC_SINGLE("Ganged Ctl Capture Switch", CODEC_CS42L52_ADC_MISC_CTL, 7, 1, 1), /* should be enabled init */
432 SOC_ENUM("Mix/Swap Capture Switch",soc_cs42l52_enum[2]),
433 SOC_ENUM("Signal Polarity Capture Switch", soc_cs42l52_enum[3]),
435 SOC_SINGLE("HP Analog Gain Playback Volume", CODEC_CS42L52_PB_CTL1, 5, 7, 0),
436 SOC_SINGLE("Playback B=A Volume Playback Switch", CODEC_CS42L52_PB_CTL1, 4, 1, 0), /*10*/ /*should be enabled init*/
437 SOC_ENUM("PCM Signal Polarity Playback Switch",soc_cs42l52_enum[4]),
439 SOC_SINGLE("Digital De-Emphasis Playback Switch", CODEC_CS42L52_MISC_CTL, 2, 1, 0),
440 SOC_SINGLE("Digital SR Playback Switch", CODEC_CS42L52_MISC_CTL, 1, 1, 0),
441 SOC_SINGLE("Digital ZC Playback Switch", CODEC_CS42L52_MISC_CTL, 0, 1, 0),
443 SOC_SINGLE("Spk Volume Equal Playback Switch", CODEC_CS42L52_PB_CTL2, 3, 1, 0) , /*15*/ /*should be enabled init*/
444 SOC_SINGLE("Spk Mute 50/50 Playback Switch", CODEC_CS42L52_PB_CTL2, 0, 1, 0),
445 SOC_ENUM("Spk Swap Channel Playback Switch", soc_cs42l52_enum[5]),
446 SOC_SINGLE("Spk Full-Bridge Playback Switch", CODEC_CS42L52_PB_CTL2, 1, 1, 0),
447 SOC_DOUBLE_R("Mic Gain Capture Volume", CODEC_CS42L52_MICA_CTL, CODEC_CS42L52_MICB_CTL, 0, 31, 0),
449 SOC_DOUBLE_R("ALC SR Capture Switch", CODEC_CS42L52_PGAA_CTL, CODEC_CS42L52_PGAB_CTL, 7, 1, 1), /*20*/
450 SOC_DOUBLE_R("ALC ZC Capture Switch", CODEC_CS42L52_PGAA_CTL, CODEC_CS42L52_PGAB_CTL, 6, 1, 1),
451 SOC_DOUBLE_R_CS42L52("PGA Capture Volume", CODEC_CS42L52_PGAA_CTL, CODEC_CS42L52_PGAB_CTL, 0x30, 0x18),
453 SOC_DOUBLE_R_CS42L52("Passthru Playback Volume", CODEC_CS42L52_PASSTHRUA_VOL, CODEC_CS42L52_PASSTHRUB_VOL, 0x90, 0x88),
454 SOC_DOUBLE("Passthru Playback Switch", CODEC_CS42L52_MISC_CTL, 4, 5, 1, 1),
455 SOC_DOUBLE_R_CS42L52("ADC Capture Volume", CODEC_CS42L52_ADCA_VOL, CODEC_CS42L52_ADCB_VOL, 0x80, 0xA0),
456 SOC_DOUBLE("ADC Capture Switch", CODEC_CS42L52_ADC_MISC_CTL, 0, 1, 1, 1),
457 SOC_DOUBLE_R_CS42L52("ADC Mixer Capture Volume", CODEC_CS42L52_ADCA_MIXER_VOL, CODEC_CS42L52_ADCB_MIXER_VOL, 0x7f, 0x19),
458 SOC_DOUBLE_R("ADC Mixer Capture Switch", CODEC_CS42L52_ADCA_MIXER_VOL, CODEC_CS42L52_ADCB_MIXER_VOL, 7, 1, 1),
459 SOC_DOUBLE_R_CS42L52("PCM Mixer Playback Volume", CODEC_CS42L52_PCMA_MIXER_VOL, CODEC_CS42L52_PCMB_MIXER_VOL, 0x7f, 0x19),
460 SOC_DOUBLE_R("PCM Mixer Playback Switch", CODEC_CS42L52_PCMA_MIXER_VOL, CODEC_CS42L52_PCMB_MIXER_VOL, 7, 1, 1),
462 SOC_SINGLE("Beep Freq", CODEC_CS42L52_BEEP_FREQ, 4, 15, 0),
463 SOC_SINGLE("Beep OnTime", CODEC_CS42L52_BEEP_FREQ, 0, 15, 0), /*30*/
464 SOC_SINGLE_CS42L52("Beep Volume", CODEC_CS42L52_BEEP_VOL, 0, 0x1f, 0x07),
465 SOC_SINGLE("Beep OffTime", CODEC_CS42L52_BEEP_VOL, 5, 7, 0),
466 SOC_ENUM("Beep Type", soc_cs42l52_enum[6]),
467 SOC_SINGLE("Beep Mix Switch", CODEC_CS42L52_BEEP_TONE_CTL, 5, 1, 1),
469 SOC_ENUM("Treble Corner Freq Playback Switch", soc_cs42l52_enum[7]), /*35*/
470 SOC_ENUM("Bass Corner Freq Playback Switch",soc_cs42l52_enum[8]),
471 SOC_SINGLE("Tone Control Playback Switch", CODEC_CS42L52_BEEP_TONE_CTL, 0, 1, 0),
472 SOC_SINGLE("Treble Gain Playback Volume", CODEC_CS42L52_TONE_CTL, 4, 15, 1),
473 SOC_SINGLE("Bass Gain Playback Volume", CODEC_CS42L52_TONE_CTL, 0, 15, 1),
475 SOC_DOUBLE_R_CS42L52("Master Playback Volume", CODEC_CS42L52_MASTERA_VOL, CODEC_CS42L52_MASTERB_VOL,0xe4, 0x34), /*40*/
476 SOC_DOUBLE_R_CS42L52("HP Digital Playback Volume", CODEC_CS42L52_HPA_VOL, CODEC_CS42L52_HPB_VOL, 0xff, 0x1),
477 SOC_DOUBLE("HP Digital Playback Switch", CODEC_CS42L52_PB_CTL2, 6, 7, 1, 1),
478 SOC_DOUBLE_R_CS42L52("Speaker Playback Volume", CODEC_CS42L52_SPKA_VOL, CODEC_CS42L52_SPKB_VOL, 0xff, 0x1),
479 SOC_DOUBLE("Speaker Playback Switch", CODEC_CS42L52_PB_CTL2, 4, 5, 1, 1),
481 SOC_SINGLE("Limiter Max Threshold Playback Volume", CODEC_CS42L52_LIMITER_CTL1, 5, 7, 0),
482 SOC_SINGLE("Limiter Cushion Threshold Playback Volume", CODEC_CS42L52_LIMITER_CTL1, 2, 7, 0),
483 SOC_SINGLE("Limiter SR Playback Switch", CODEC_CS42L52_LIMITER_CTL1, 1, 1, 0), /*45*/
484 SOC_SINGLE("Limiter ZC Playback Switch", CODEC_CS42L52_LIMITER_CTL1, 0, 1, 0),
485 SOC_SINGLE("Limiter Playback Switch", CODEC_CS42L52_LIMITER_CTL2, 7, 1, 0),
486 SOC_ENUM("Limiter Attnenuate Playback Switch", soc_cs42l52_enum[9]),
487 SOC_SINGLE("Limiter Release Rate Playback Volume", CODEC_CS42L52_LIMITER_CTL2, 0, 63, 0),
488 SOC_SINGLE("Limiter Attack Rate Playback Volume", CODEC_CS42L52_LIMITER_AT_RATE, 0, 63, 0), /*50*/
490 SOC_DOUBLE("ALC Capture Switch",CODEC_CS42L52_ALC_CTL, 6, 7, 1, 0),
491 SOC_SINGLE("ALC Attack Rate Capture Volume", CODEC_CS42L52_ALC_CTL, 0, 63, 0),
492 SOC_SINGLE("ALC Release Rate Capture Volume", CODEC_CS42L52_ALC_RATE, 0, 63, 0),
493 SOC_SINGLE("ALC Max Threshold Capture Volume", CODEC_CS42L52_ALC_THRESHOLD, 5, 7, 0),
494 SOC_SINGLE("ALC Min Threshold Capture Volume", CODEC_CS42L52_ALC_THRESHOLD, 2, 7, 0), /*55*/
496 SOC_ENUM("Noise Gate Type Capture Switch", soc_cs42l52_enum[10]),
497 SOC_SINGLE("Noise Gate Capture Switch", CODEC_CS42L52_NOISE_GATE_CTL, 6, 1, 0),
498 SOC_SINGLE("Noise Gate Boost Capture Switch", CODEC_CS42L52_NOISE_GATE_CTL, 5, 1, 1),
499 SOC_SINGLE("Noise Gate Threshold Capture Volume", CODEC_CS42L52_NOISE_GATE_CTL, 2, 7, 0),
500 SOC_ENUM("Noise Gate Delay Time Capture Switch", soc_cs42l52_enum[11]), /*60*/
502 SOC_SINGLE("Batt Compensation Switch", CODEC_CS42L52_BATT_COMPEN, 7, 1, 0),
503 SOC_SINGLE("Batt VP Monitor Switch", CODEC_CS42L52_BATT_COMPEN, 6, 1, 0),
504 SOC_SINGLE("Batt VP ref", CODEC_CS42L52_BATT_COMPEN, 0, 0x0f, 0),
505 SOC_SINGLE("Playback Charge Pump Freq", CODEC_CS42L52_CHARGE_PUMP, 4, 15, 0), /*64*/
509 static int soc_cs42l52_add_controls(struct snd_soc_codec *codec)
513 for(i = 0; i < ARRAY_SIZE(soc_cs42l52_controls); i++)
515 ret = snd_ctl_add(codec->card,
516 snd_soc_cnew(&soc_cs42l52_controls[i], codec, NULL));
519 SOCDBG("add cs42l52 controls failed\n");
526 static const struct snd_kcontrol_new cs42l52_adca_mux =
527 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[12]);
529 static const struct snd_kcontrol_new cs42l52_adcb_mux =
530 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[13]);
532 static const struct snd_kcontrol_new cs42l52_mica_mux =
533 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[14]);
535 static const struct snd_kcontrol_new cs42l52_micb_mux =
536 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[15]);
538 static const struct snd_kcontrol_new cs42l52_mica_stereo_mux =
539 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[16]);
541 static const struct snd_kcontrol_new cs42l52_micb_stereo_mux =
542 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[17]);
544 static const struct snd_kcontrol_new cs42l52_passa_switch =
545 SOC_DAPM_SINGLE("Switch", CODEC_CS42L52_MISC_CTL, 6, 1, 0);
547 static const struct snd_kcontrol_new cs42l52_passb_switch =
548 SOC_DAPM_SINGLE("Switch", CODEC_CS42L52_MISC_CTL, 7, 1, 0);
550 static const struct snd_kcontrol_new cs42l52_micbias_switch =
551 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[19]);
553 static const struct snd_kcontrol_new cs42l52_hpa_mux =
554 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[20]);
556 static const struct snd_kcontrol_new cs42l52_hpb_mux =
557 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[21]);
559 static const struct snd_soc_dapm_widget soc_cs42l52_dapm_widgets[] = {
561 SND_SOC_DAPM_ADC("ADC Left", "Capture", CODEC_CS42L52_PWCTL1, 1, 1),
562 SND_SOC_DAPM_ADC("ADC Right", "Capture", CODEC_CS42L52_PWCTL1, 2, 1),
564 SND_SOC_DAPM_MUX("MICA Mux Capture Switch", SND_SOC_NOPM, 0, 0, &cs42l52_mica_mux),
565 SND_SOC_DAPM_MUX("MICB Mux Capture Switch", SND_SOC_NOPM, 0, 0, &cs42l52_micb_mux),
566 SND_SOC_DAPM_MUX("MICA Stereo Mux Capture Switch", SND_SOC_NOPM, 1, 0, &cs42l52_mica_stereo_mux),
567 SND_SOC_DAPM_MUX("MICB Stereo Mux Capture Switch", SND_SOC_NOPM, 2, 0, &cs42l52_micb_stereo_mux),
569 SND_SOC_DAPM_MUX("ADC Mux Left Capture Switch", SND_SOC_NOPM, 1, 1, &cs42l52_adca_mux),
570 SND_SOC_DAPM_MUX("ADC Mux Right Capture Switch", SND_SOC_NOPM, 2, 1, &cs42l52_adcb_mux),
573 SND_SOC_DAPM_PGA("AIN1A Switch", CODEC_CS42L52_ADC_PGA_A, 0, 0, NULL, 0),
574 SND_SOC_DAPM_PGA("AIN2A Switch", CODEC_CS42L52_ADC_PGA_A, 1, 0, NULL, 0),
575 SND_SOC_DAPM_PGA("AIN3A Switch", CODEC_CS42L52_ADC_PGA_A, 2, 0, NULL, 0),
576 SND_SOC_DAPM_PGA("AIN4A Switch", CODEC_CS42L52_ADC_PGA_A, 3, 0, NULL, 0),
577 SND_SOC_DAPM_PGA("MICA Switch" , CODEC_CS42L52_ADC_PGA_A, 4, 0, NULL, 0),
579 SND_SOC_DAPM_PGA("AIN1B Switch", CODEC_CS42L52_ADC_PGA_B, 0, 0, NULL, 0),
580 SND_SOC_DAPM_PGA("AIN2B Switch", CODEC_CS42L52_ADC_PGA_B, 1, 0, NULL, 0),
581 SND_SOC_DAPM_PGA("AIN3B Switch", CODEC_CS42L52_ADC_PGA_B, 2, 0, NULL, 0),
582 SND_SOC_DAPM_PGA("AIN4B Switch", CODEC_CS42L52_ADC_PGA_B, 3, 0, NULL, 0),
583 SND_SOC_DAPM_PGA("MICB Switch" , CODEC_CS42L52_ADC_PGA_B, 4, 0, NULL, 0),
586 SND_SOC_DAPM_PGA("PGA MICA", CODEC_CS42L52_PWCTL2, PWCTL2_PDN_MICA_SHIFT, 1, NULL, 0),
587 SND_SOC_DAPM_PGA("PGA MICB", CODEC_CS42L52_PWCTL2, PWCTL2_PDN_MICB_SHIFT, 1, NULL, 0),
589 /* MIC bias switch */
590 SND_SOC_DAPM_MUX("Mic Bias Capture Switch", SND_SOC_NOPM, 0, 0, &cs42l52_micbias_switch),
591 SND_SOC_DAPM_PGA("Mic-Bias", CODEC_CS42L52_PWCTL2, 0, 1, NULL, 0),
594 SND_SOC_DAPM_PGA("PGA Left", CODEC_CS42L52_PWCTL1, PWCTL1_PDN_PGAA_SHIFT, 1, NULL, 0),
595 SND_SOC_DAPM_PGA("PGA Right", CODEC_CS42L52_PWCTL1, PWCTL1_PDN_PGAB_SHIFT, 1, NULL, 0),
598 SND_SOC_DAPM_MUX("Passthrough Left Playback Switch", SND_SOC_NOPM, 0, 0, &cs42l52_hpa_mux),
599 SND_SOC_DAPM_MUX("Passthrough Right Playback Switch", SND_SOC_NOPM, 0, 0, &cs42l52_hpb_mux),
601 SND_SOC_DAPM_DAC("DAC Left", "Playback", SND_SOC_NOPM, 0, 0),
602 SND_SOC_DAPM_DAC("DAC Right", "Playback", SND_SOC_NOPM, 0, 0),
604 // SND_SOC_DAPM_PGA("HP Amp Left", CODEC_CS42L52_PWCTL3, 4, 1, NULL, 0),
605 // SND_SOC_DAPM_PGA("HP Amp Right", CODEC_CS42L52_PWCTL3, 6, 1, NULL, 0),
607 // SND_SOC_DAPM_PGA("SPK Pwr Left", CODEC_CS42L52_PWCTL3, 0, 1, NULL, 0),
608 // SND_SOC_DAPM_PGA("SPK Pwr Right", CODEC_CS42L52_PWCTL3, 2, 1, NULL, 0),
610 SND_SOC_DAPM_OUTPUT("HPA"),
611 SND_SOC_DAPM_OUTPUT("HPB"),
612 SND_SOC_DAPM_OUTPUT("SPKA"),
613 SND_SOC_DAPM_OUTPUT("SPKB"),
614 SND_SOC_DAPM_OUTPUT("MICBIAS"),
616 SND_SOC_DAPM_INPUT("INPUT1A"),
617 SND_SOC_DAPM_INPUT("INPUT2A"),
618 SND_SOC_DAPM_INPUT("INPUT3A"),
619 SND_SOC_DAPM_INPUT("INPUT4A"),
620 SND_SOC_DAPM_INPUT("INPUT1B"),
621 SND_SOC_DAPM_INPUT("INPUT2B"),
622 SND_SOC_DAPM_INPUT("INPUT3B"),
623 SND_SOC_DAPM_INPUT("INPUT4B"),
624 SND_SOC_DAPM_INPUT("MICA"),
625 SND_SOC_DAPM_INPUT("MICB"),
628 static const struct snd_soc_dapm_route soc_cs42l52_audio_map[] = {
630 /* adc select path */
631 {"ADC Mux Left Capture Switch", "AIN1", "INPUT1A"},
632 {"ADC Mux Right Capture Switch", "AIN1", "INPUT1B"},
633 {"ADC Mux Left Capture Switch", "AIN2", "INPUT2A"},
634 {"ADC Mux Right Capture Switch", "AIN2", "INPUT2B"},
635 {"ADC Mux Left Capture Switch", "AIN3", "INPUT3A"},
636 {"ADC Mux Right Capture Switch", "AIN3", "INPUT3B"},
637 {"ADC Mux Left Capture Switch", "AIN4", "INPUT4A"},
638 {"ADC Mux Right Capture Switch", "AIN4", "INPUT4B"},
640 /* left capture part */
641 {"AIN1A Switch", NULL, "INPUT1A"},
642 {"AIN2A Switch", NULL, "INPUT2A"},
643 {"AIN3A Switch", NULL, "INPUT3A"},
644 {"AIN4A Switch", NULL, "INPUT4A"},
645 {"MICA Switch", NULL, "MICA"},
646 {"PGA MICA", NULL, "MICA Switch"},
648 {"PGA Left", NULL, "AIN1A Switch"},
649 {"PGA Left", NULL, "AIN2A Switch"},
650 {"PGA Left", NULL, "AIN3A Switch"},
651 {"PGA Left", NULL, "AIN4A Switch"},
652 {"PGA Left", NULL, "PGA MICA"},
654 /* right capture part */
655 {"AIN1B Switch", NULL, "INPUT1B"},
656 {"AIN2B Switch", NULL, "INPUT2B"},
657 {"AIN3B Switch", NULL, "INPUT3B"},
658 {"AIN4B Switch", NULL, "INPUT4B"},
659 {"MICB Switch", NULL, "MICB"},
660 {"PGA MICB", NULL, "MICB Switch"},
662 {"PGA Right", NULL, "AIN1B Switch"},
663 {"PGA Right", NULL, "AIN2B Switch"},
664 {"PGA Right", NULL, "AIN3B Switch"},
665 {"PGA Right", NULL, "AIN4B Switch"},
666 {"PGA Right", NULL, "PGA MICB"},
668 {"ADC Mux Left Capture Switch", "PGA", "PGA Left"},
669 {"ADC Mux Right Capture Switch", "PGA", "PGA Right"},
670 {"ADC Left", NULL, "ADC Mux Left Capture Switch"},
671 {"ADC Right", NULL, "ADC Mux Right Capture Switch"},
674 {"Mic Bias Capture Switch", "On", "PGA MICA"},
675 {"Mic Bias Capture Switch", "On", "PGA MICB"},
676 {"Mic-Bias", NULL, "Mic Bias Capture Switch"},
677 {"Mic-Bias", NULL, "Mic Bias Capture Switch"},
678 {"ADC Mux Left Capture Switch", "PGA", "Mic-Bias"},
679 {"ADC Mux Right Capture Switch", "PGA", "Mic-Bias"},
680 {"Passthrough Left Playback Switch", "On", "Mic-Bias"},
681 {"Passthrough Right Playback Switch", "On", "Mic-Bias"},
684 {"Passthrough Left Playback Switch", "On", "PGA Left"},
685 {"Passthrough Right Playback Switch", "On", "PGA Right"},
686 {"Passthrough Left Playback Switch", "Off", "DAC Left"},
687 {"Passthrough Right Playback Switch", "Off", "DAC Right"},
691 {"HP Amp Left", NULL, "Passthrough Left Playback Switch"},
692 {"HP Amp Right", NULL, "Passthrough Right Playback Switch"},
693 {"HPA", NULL, "HP Amp Left"},
694 {"HPB", NULL, "HP Amp Right"},
698 {"SPK Pwr Left", NULL, "DAC Left"},
699 {"SPK Pwr Right", NULL, "DAC Right"},
700 {"SPKA", NULL, "SPK Pwr Left"},
701 {"SPKB", NULL, "SPK Pwr Right"},
704 // {NULL, NULL, NULL},
707 static int soc_cs42l52_add_widgets(struct snd_soc_codec *soc_codec)
709 snd_soc_dapm_new_controls(soc_codec, soc_cs42l52_dapm_widgets,
710 ARRAY_SIZE(soc_cs42l52_dapm_widgets));
712 snd_soc_dapm_add_routes(soc_codec, soc_cs42l52_audio_map,
713 ARRAY_SIZE(soc_cs42l52_audio_map));
715 snd_soc_dapm_new_widgets(soc_codec);
719 #define SOC_CS42L52_RATES ( SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \
720 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
721 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
722 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \
723 SNDRV_PCM_RATE_96000 ) /*refer to cs42l52 datasheet page35*/
725 #define SOC_CS42L52_FORMATS ( SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \
726 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_U18_3LE | \
727 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \
728 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE )
730 static struct snd_soc_dai_ops cs42l52_ops = {
731 .hw_params = soc_cs42l52_pcm_hw_params,
732 .set_sysclk = soc_cs42l52_set_sysclk,
733 .set_fmt = soc_cs42l52_set_fmt,
734 .digital_mute = soc_cs42l52_digital_mute,
735 .set_clkdiv = soc_cs42l52_set_dai_clkdiv,
739 struct snd_soc_dai soc_cs42l52_dai = {
740 .name = SOC_CS42L52_NAME,
742 .stream_name = "Playback",
744 .channels_max = SOC_CS42L52_DEFAULT_MAX_CHANS,
745 .rates = SOC_CS42L52_RATES,
746 .formats = SOC_CS42L52_FORMATS,
749 .stream_name = "Capture",
751 .channels_max = SOC_CS42L52_DEFAULT_MAX_CHANS,
752 .rates = SOC_CS42L52_RATES,
753 .formats = SOC_CS42L52_FORMATS,
758 .hw_params = soc_cs42l52_pcm_hw_params,
759 .set_sysclk = soc_cs42l52_set_sysclk,
760 .set_fmt = soc_cs42l52_set_fmt,
761 .digital_mute = soc_cs42l52_digital_mute,
766 EXPORT_SYMBOL_GPL(soc_cs42l52_dai);
768 /* #define CONFIG_MANUAL_CLK */
770 /* page 37 from cs42l52 datasheet */
771 static void soc_cs42l52_required_setup(struct snd_soc_codec *codec)
774 soc_cs42l52_write(codec, 0x00, 0x99);
775 soc_cs42l52_write(codec, 0x3e, 0xba);
776 soc_cs42l52_write(codec, 0x47, 0x80);
777 data = soc_cs42l52_read(codec, 0x32);
778 soc_cs42l52_write(codec, 0x32, data | 0x80);
779 soc_cs42l52_write(codec, 0x32, data & 0x7f);
780 soc_cs42l52_write(codec, 0x00, 0x00);
784 static struct snd_soc_codec *cs42l52_codec;
786 #if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
788 static int cs42l52_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
790 struct snd_soc_codec *soc_codec;
791 struct soc_codec_cs42l52 * info;
794 printk(KERN_INFO"cs42l52_i2c_probe\n");
796 soc_codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
797 if (soc_codec == NULL)
800 soc_codec->name = SOC_CS42L52_NAME;
801 soc_codec->owner = THIS_MODULE;
802 soc_codec->write = soc_cs42l52_write;
803 soc_codec->read = soc_cs42l52_read;
804 soc_codec->hw_write = (hw_write_t)i2c_master_send;
805 mutex_init(&soc_codec->mutex);
806 INIT_LIST_HEAD(&soc_codec->dapm_widgets);
807 INIT_LIST_HEAD(&soc_codec->dapm_paths);
809 soc_codec->set_bias_level = soc_cs42l52_set_bias_level;
810 soc_codec->dai = &soc_cs42l52_dai;
811 soc_codec->dai->playback.channels_max = 2;
812 soc_codec->dai->capture.channels_max = 2;
813 soc_codec->num_dai = 1;
814 soc_codec->control_data = i2c;
815 soc_codec->dev = &i2c->dev;
816 soc_codec->pcm_devs = 0; /*pcm device num index*/
817 soc_codec->pop_time = 2;
818 soc_codec->dai[0].codec = soc_codec;
820 soc_codec->reg_cache_size = sizeof(soc_cs42l52_reg_default);
822 soc_codec->reg_cache = kmemdup(soc_cs42l52_reg_default, sizeof(soc_cs42l52_reg_default), GFP_KERNEL);
824 info = (struct soc_codec_cs42l52 *)kmalloc(sizeof(struct soc_codec_cs42l52),GFP_KERNEL);
831 info->sysclk = SOC_CS42L52_DEFAULT_CLK;
832 info->format = SOC_CS42L52_DEFAULT_FORMAT;
834 soc_codec->private_data =(void*)info;
836 printk(KERN_INFO"soc_cs42l52_setup1\n");
837 if(!soc_codec->reg_cache)
839 SOCERR("%s: err out of memory\n", __FUNCTION__);
845 for(i = 0; i < soc_codec->num_dai; i++) //while(1) //
848 SOCINF("Cirrus CS42L52 codec , revision %d\n", ret & CHIP_REV_MASK);
849 /*set hp default volume*/
850 soc_cs42l52_write(soc_codec, CODEC_CS42L52_HPA_VOL, DEFAULT_HP_VOL);
851 soc_cs42l52_write(soc_codec, CODEC_CS42L52_HPB_VOL, DEFAULT_HP_VOL);
854 /*set spk default volume*/
855 soc_cs42l52_write(soc_codec, CODEC_CS42L52_SPKA_VOL, DEFAULT_SPK_VOL);
856 soc_cs42l52_write(soc_codec, CODEC_CS42L52_SPKB_VOL, DEFAULT_SPK_VOL);
859 /*set output default powerstate*/
860 soc_cs42l52_write(soc_codec, CODEC_CS42L52_PWCTL3, 5);
861 #ifdef CONFIG_MANUAL_CLK
862 soc_cs42l52_write(soc_codec, CODEC_CS42L52_CLK_CTL,
863 (soc_cs42l52_read(soc_codec, CODEC_CS42L52_CLK_CTL)
864 & ~CLK_CTL_AUTODECT_ENABLE));
866 soc_cs42l52_write(soc_codec, CODEC_CS42L52_CLK_CTL,
867 (soc_cs42l52_read(soc_codec, CODEC_CS42L52_CLK_CTL)
868 |CLK_CTL_AUTODECT_ENABLE));
871 /*default output stream configure*/
872 soc_cs42l52_write(soc_codec, CODEC_CS42L52_PB_CTL1,
873 (soc_cs42l52_read(soc_codec, CODEC_CS42L52_PB_CTL1)
874 | (PB_CTL1_HP_GAIN_07099 << PB_CTL1_HP_GAIN_SHIFT)));
876 soc_cs42l52_write(soc_codec, CODEC_CS42L52_MISC_CTL,
877 (soc_cs42l52_read(soc_codec, CODEC_CS42L52_MISC_CTL))
878 | (MISC_CTL_DEEMPH | MISC_CTL_DIGZC | MISC_CTL_DIGSFT));
880 /*default input stream configure*/
881 //soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADC_PGA_A, info->adc_sel1);
882 soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADC_PGA_A, 0<<6);
884 //soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADC_PGA_B, info->adc_sel2);
885 soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADC_PGA_B, 1<<7);
887 soc_cs42l52_write(soc_codec, CODEC_CS42L52_MICA_CTL,
888 (soc_cs42l52_read(soc_codec, CODEC_CS42L52_MICA_CTL)
889 | 0<<6));/*pre-amplifer 16db*/
890 soc_cs42l52_write(soc_codec, CODEC_CS42L52_MICB_CTL,
891 (soc_cs42l52_read(soc_codec, CODEC_CS42L52_MICB_CTL)
893 /*default input stream path configure*/
894 soc_cs42l52_write(soc_codec, CODEC_CS42L52_ANALOG_HPF_CTL,
895 (soc_cs42l52_read(soc_codec, CODEC_CS42L52_ANALOG_HPF_CTL)
896 | HPF_CTL_ANLGSFTB | HPF_CTL_ANLGSFTA));
897 soc_cs42l52_write(soc_codec, CODEC_CS42L52_PGAA_CTL, PGAX_CTL_VOL_6DB);
898 soc_cs42l52_write(soc_codec, CODEC_CS42L52_PGAB_CTL, PGAX_CTL_VOL_6DB); /*PGA volume*/
900 soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADCA_VOL, ADCX_VOL_12DB);
901 soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADCB_VOL, ADCX_VOL_12DB); /*ADC volume*/
903 soc_cs42l52_write(soc_codec, CODEC_CS42L52_ALC_CTL,
904 (ALC_CTL_ALCB_ENABLE | ALC_CTL_ALCA_ENABLE)); /*enable ALC*/
906 soc_cs42l52_write(soc_codec, CODEC_CS42L52_ALC_THRESHOLD,
907 ((ALC_RATE_0DB << ALC_MAX_RATE_SHIFT)
908 | (ALC_RATE_3DB << ALC_MIN_RATE_SHIFT)));/*ALC max and min threshold*/
911 soc_cs42l52_write(soc_codec, CODEC_CS42L52_NOISE_GATE_CTL,
912 (NG_ENABLE | (NG_MIN_70DB << NG_THRESHOLD_SHIFT)
913 | (NG_DELAY_100MS << NG_DELAY_SHIFT))); /*Noise Gate enable*/
915 soc_cs42l52_write(soc_codec, CODEC_CS42L52_BEEP_VOL, BEEP_VOL_12DB);
917 soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADCA_MIXER_VOL, 0x80 | ADC_MIXER_VOL_12DB);
918 soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADCB_MIXER_VOL, 0x80 | ADC_MIXER_VOL_12DB);
920 soc_cs42l52_dai.dev = &i2c->dev;
922 cs42l52_codec = soc_codec;
924 ret = snd_soc_register_codec(soc_codec);
926 dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
930 INIT_DELAYED_WORK(&soc_codec->delayed_work, soc_cs42l52_work);
932 ret = snd_soc_register_dai(&soc_cs42l52_dai);
934 dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret);
941 snd_soc_unregister_codec(soc_codec);
943 kfree(cs42l52_codec);
944 cs42l52_codec = NULL;
948 static int cs42l52_i2c_remove(struct i2c_client *client)
951 snd_soc_unregister_dai(&soc_cs42l52_dai);
952 snd_soc_unregister_codec(cs42l52_codec);
954 soc_cs42l52_set_bias_level(cs42l52_codec, SND_SOC_BIAS_OFF);
956 soc_cs42l52_dai.dev = NULL;
957 if(cs42l52_codec->reg_cache)
958 kfree(cs42l52_codec->reg_cache);
959 if(cs42l52_codec->private_data)
960 kfree(cs42l52_codec->private_data);
961 kfree(cs42l52_codec);
962 cs42l52_codec = NULL;
967 static const struct i2c_device_id cs42l52_i2c_id[] = {
971 MODULE_DEVICE_TABLE(i2c, cs42l52_i2c_id);
973 static struct i2c_driver cs42l52_i2c_drv = {
976 .owner = THIS_MODULE,
978 .probe = cs42l52_i2c_probe,
979 .remove = cs42l52_i2c_remove,
980 .id_table = cs42l52_i2c_id,
986 static int soc_cs42l52_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
989 struct snd_soc_codec *codec = codec_dai->codec;
992 printk("soc_cs42l52_set_dai_clkdiv\n");
997 static int soc_cs42l52_set_sysclk(struct snd_soc_dai *codec_dai,
998 int clk_id, u_int freq, int dir)
1001 struct snd_soc_codec *soc_codec = codec_dai->codec;
1002 struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*)soc_codec->private_data;
1004 if((freq >= SOC_CS42L52_MIN_CLK) && (freq <= SOC_CS42L52_MAX_CLK))
1006 info->sysclk = freq;
1007 SOCDBG("sysclk %d\n", info->sysclk);
1010 SOCDBG("invalid paramter\n");
1016 static int soc_cs42l52_set_fmt(struct snd_soc_dai *codec_dai,
1019 struct snd_soc_codec *soc_codec = codec_dai->codec;
1020 struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*)soc_codec->private_data;
1024 /* set master/slave audio interface */
1025 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1027 case SND_SOC_DAIFMT_CBM_CFM:
1028 SOCDBG("codec dai fmt master\n");
1029 iface = IFACE_CTL1_MASTER;
1031 case SND_SOC_DAIFMT_CBS_CFS:
1032 SOCDBG("codec dai fmt slave\n");
1035 SOCDBG("invaild formate\n");
1040 /* interface format */
1041 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1043 case SND_SOC_DAIFMT_I2S:
1044 SOCDBG("codec dai fmt i2s\n");
1045 iface |= (IFACE_CTL1_ADC_FMT_I2S | IFACE_CTL1_DAC_FMT_I2S);
1047 case SND_SOC_DAIFMT_RIGHT_J:
1048 SOCDBG("codec dai fmt right justified\n");
1049 iface |= IFACE_CTL1_DAC_FMT_RIGHT_J;
1050 SOCINF("warning only playback stream support this format\n");
1052 case SND_SOC_DAIFMT_LEFT_J:
1053 SOCDBG("codec dai fmt left justified\n");
1054 iface |= (IFACE_CTL1_ADC_FMT_LEFT_J | IFACE_CTL1_DAC_FMT_LEFT_J);
1056 case SND_SOC_DAIFMT_DSP_A:
1057 iface |= IFACE_CTL1_DSP_MODE_EN;
1059 case SND_SOC_DAIFMT_DSP_B:
1060 SOCINF("unsupported format\n");
1064 SOCINF("invaild format\n");
1069 /* clock inversion */
1070 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { /*tonyliu*/
1072 case SND_SOC_DAIFMT_NB_NF:
1073 SOCDBG("codec dai fmt normal sclk\n");
1075 case SND_SOC_DAIFMT_IB_IF:
1076 SOCDBG("codec dai fmt inversed sclk\n");
1077 iface |= IFACE_CTL1_INV_SCLK;
1079 case SND_SOC_DAIFMT_IB_NF:
1080 iface |= IFACE_CTL1_INV_SCLK;
1082 case SND_SOC_DAIFMT_NB_IF:
1085 SOCDBG("unsupported format\n");
1089 info->format = iface;
1095 static int soc_cs42l52_digital_mute(struct snd_soc_dai *dai, int mute)
1097 struct snd_soc_codec *soc_codec = dai->codec;
1098 u8 mute_val = soc_cs42l52_read(soc_codec, CODEC_CS42L52_PB_CTL1) & PB_CTL1_MUTE_MASK;
1102 printk(KERN_INFO"soc_cs42l52_digital_mute=1 %d\n",mute_val);
1104 soc_cs42l52_write(soc_codec, CODEC_CS42L52_PB_CTL1, mute_val | PB_CTL1_MSTB_MUTE | PB_CTL1_MSTA_MUTE);
1107 printk(KERN_INFO"soc_cs42l52_digital_mute=0 %d\n",mute_val);
1108 soc_cs42l52_write(soc_codec, CODEC_CS42L52_PB_CTL1, mute_val );
1114 struct soc_cs42l52_clk_para {
1124 static const struct soc_cs42l52_clk_para clk_map_table[] = {
1126 {12288000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
1127 {18432000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
1128 {12000000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},
1129 {24000000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},
1130 {27000000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 0}, /*4*/
1133 {11289600, 11025, CLK_CTL_S_QS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
1134 {16934400, 11025, CLK_CTL_S_QS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
1137 {12288000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
1138 {18432000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
1139 {12000000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},/*9*/
1140 {24000000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},
1141 {27000000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 1},
1144 {11289600, 22050, CLK_CTL_S_HS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
1145 {16934400, 22050, CLK_CTL_S_HS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
1148 {12288000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},/*14*/
1149 {18432000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
1150 {12000000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},
1151 {24000000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},
1152 {27000000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 0},
1155 {11289600, 44100, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},/*19*/
1156 {16934400, 44100, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
1159 {12288000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
1160 {18432000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
1161 {12000000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},
1162 {24000000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},/*24*/
1163 {27000000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 1},
1166 {11289600, 88200, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
1167 {16934400, 88200, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
1170 {12288000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
1171 {18432000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},/*29*/
1172 {12000000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},
1173 {24000000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},
1176 static int soc_cs42l52_get_clk(int mclk, int rate)
1180 u_int mclk1, mclk2 = 0;
1182 for(i = 0; i < ARRAY_SIZE(clk_map_table); i++)
1184 if(clk_map_table[i].rate == rate)
1186 mclk1 = clk_map_table[i].mclk;
1188 if(abs(mclk - mclk1) < abs(mclk - mclk2))
1197 return ret < ARRAY_SIZE(clk_map_table) ? ret : -EINVAL;
1200 static int soc_cs42l52_pcm_hw_params(struct snd_pcm_substream *substream,
1201 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
1204 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1205 struct snd_soc_device *soc_dev = rtd->socdev;
1206 struct snd_soc_codec *soc_codec = soc_dev->card->codec;
1207 struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*)soc_codec->private_data;
1209 info->format = SOC_CS42L52_DEFAULT_FORMAT;
1211 int index = soc_cs42l52_get_clk(info->sysclk, params_rate(params));
1215 info->sysclk = clk_map_table[index].mclk;
1216 clk |= (clk_map_table[index].speed << CLK_CTL_SPEED_SHIFT) |
1217 (clk_map_table[index].group << CLK_CTL_32K_SR_SHIFT) |
1218 (clk_map_table[index].videoclk << CLK_CTL_27M_MCLK_SHIFT) |
1219 (clk_map_table[index].ratio << CLK_CTL_RATIO_SHIFT) |
1220 clk_map_table[index].mclkdiv2;
1221 #ifdef CONFIG_MANUAL_CLK
1222 soc_cs42l52_write(soc_codec, CODEC_CS42L52_CLK_CTL, clk);
1224 soc_cs42l52_write(soc_codec, CODEC_CS42L52_CLK_CTL, 0xa0);
1226 soc_cs42l52_write(soc_codec, CODEC_CS42L52_IFACE_CTL1, info->format);
1230 SOCDBG("can't find out right mclk\n");
1237 int soc_cs42l52_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level)
1239 u8 pwctl1 = soc_cs42l52_read(codec, CODEC_CS42L52_PWCTL1) & 0x9f;
1240 u8 pwctl2 = soc_cs42l52_read(codec, CODEC_CS42L52_PWCTL2) & 0x07;
1243 case SND_SOC_BIAS_ON: /* full On */
1244 SOCDBG("full on\n");
1246 case SND_SOC_BIAS_PREPARE: /* partial On */
1247 SOCDBG("partial on\n");
1248 pwctl1 &= ~(PWCTL1_PDN_CHRG | PWCTL1_PDN_CODEC);
1249 soc_cs42l52_write(codec, CODEC_CS42L52_PWCTL1, pwctl1);
1251 case SND_SOC_BIAS_STANDBY: /* Off, with power */
1252 SOCDBG("off with power\n");
1253 pwctl1 &= ~(PWCTL1_PDN_CHRG | PWCTL1_PDN_CODEC);
1254 soc_cs42l52_write(codec, CODEC_CS42L52_PWCTL1, pwctl1);
1256 case SND_SOC_BIAS_OFF: /* Off, without power */
1257 SOCDBG("off without power\n");
1258 soc_cs42l52_write(codec, CODEC_CS42L52_PWCTL1, pwctl1 | 0x9f);
1259 soc_cs42l52_write(codec, CODEC_CS42L52_PWCTL2, pwctl2 | 0x07);
1262 codec->bias_level = level;
1266 static void soc_cs42l52_work(struct work_struct *work)
1268 struct snd_soc_codec *codec =
1269 container_of(work, struct snd_soc_codec, delayed_work.work);
1271 soc_cs42l52_set_bias_level(codec, codec->bias_level);
1274 static int soc_cs42l52_suspend(struct platform_device *pdev, pm_message_t state)
1276 struct snd_soc_device *soc_dev = (struct snd_soc_device*)platform_get_drvdata(pdev);
1277 struct snd_soc_codec *soc_codec = soc_dev->card->codec;
1279 soc_cs42l52_write(soc_codec, CODEC_CS42L52_PWCTL1, PWCTL1_PDN_CODEC);
1280 soc_cs42l52_set_bias_level(soc_codec, SND_SOC_BIAS_OFF);
1285 static int soc_cs42l52_resume(struct platform_device *pdev)
1287 struct snd_soc_device *soc_dev = (struct snd_soc_device*) platform_get_drvdata(pdev);
1288 struct snd_soc_codec *soc_codec = soc_dev->card->codec;
1289 struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*) soc_codec->private_data;
1292 u8 *reg_cache = (u8*) soc_codec->reg_cache;
1293 soc_codec->num_dai = 1;
1294 /* Sync reg_cache with the hardware */
1295 for(i = 0; i < soc_codec->num_dai; i++) {
1297 for(reg = 0; reg < ARRAY_SIZE(soc_cs42l52_reg_default); reg++) {
1299 data[1] = reg_cache[reg];
1300 if(soc_codec->hw_write(soc_codec->control_data, data, 2) != 2)
1305 soc_cs42l52_set_bias_level(soc_codec, SND_SOC_BIAS_STANDBY);
1307 /*charge cs42l52 codec*/
1308 if(soc_codec->suspend_bias_level == SND_SOC_BIAS_ON)
1310 soc_cs42l52_set_bias_level(soc_codec, SND_SOC_BIAS_PREPARE);
1311 soc_codec->bias_level = SND_SOC_BIAS_ON;
1312 schedule_delayed_work(&soc_codec->delayed_work, msecs_to_jiffies(1000));
1319 static int soc_cs42l52_probe(struct platform_device *pdev)
1321 struct snd_soc_device *soc_dev = platform_get_drvdata(pdev);
1322 struct snd_soc_codec *soc_codec;
1325 if (cs42l52_codec == NULL) {
1326 dev_err(&pdev->dev, "Codec device not registered\n");
1330 soc_dev->card->codec = cs42l52_codec;
1331 soc_codec = cs42l52_codec;
1333 ret = snd_soc_new_pcms(soc_dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1336 SOCERR("%s: add new pcms failed\n",__FUNCTION__);
1341 soc_cs42l52_add_controls(soc_codec);
1343 soc_cs42l52_add_widgets(soc_codec);
1345 ret = snd_soc_init_card(soc_dev);
1347 INIT_DELAYED_WORK(&soc_codec->delayed_work, soc_cs42l52_work);
1351 SOCERR("add snd card failed\n");
1358 snd_soc_free_pcms(soc_dev);
1359 snd_soc_dapm_free(soc_dev);
1365 static int soc_cs42l52_remove(struct platform_device *pdev)
1367 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1369 snd_soc_free_pcms(socdev);
1370 snd_soc_dapm_free(socdev);
1375 struct snd_soc_codec_device soc_codec_dev_cs42l52 = {
1376 .probe = soc_cs42l52_probe,
1377 .remove = soc_cs42l52_remove,
1378 .suspend = soc_cs42l52_suspend,
1379 .resume = soc_cs42l52_resume,
1382 EXPORT_SYMBOL_GPL(soc_codec_dev_cs42l52);
1384 static int __init cs42l52_modinit(void)
1386 printk(KERN_INFO"cs42l52_i2c_probe\n");
1387 return i2c_add_driver(&cs42l52_i2c_drv);
1389 module_init(cs42l52_modinit);
1391 static void __exit cs42l52_exit(void)
1393 printk(KERN_INFO"cs42l52_i2c_probe\n");
1394 i2c_del_driver(&cs42l52_i2c_drv);
1396 module_exit(cs42l52_exit);
1398 MODULE_DESCRIPTION("ALSA SoC CS42L52 Codec");
1399 MODULE_AUTHOR("Bo Liu, Bo.Liu@cirrus.com, www.cirrus.com");
1400 MODULE_LICENSE("GPL");