2 * rt5621.c -- RT5621 ALSA SoC audio codec driver
4 * Copyright 2011 Realtek Semiconductor Corp.
5 * Author: Johnny Hsu <johnnyhsu@realtek.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/module.h>
13 #include <linux/moduleparam.h>
14 #include <linux/init.h>
15 #include <linux/delay.h>
17 #include <linux/i2c.h>
18 #include <linux/platform_device.h>
19 #include <linux/spi/spi.h>
20 #include <sound/core.h>
21 #include <sound/pcm.h>
22 #include <sound/pcm_params.h>
23 #include <sound/soc.h>
24 #include <sound/soc-dapm.h>
25 #include <sound/initval.h>
26 #include <sound/tlv.h>
31 #include <linux/ioctl.h>
32 #include <linux/types.h>
36 #define DBG(x...) printk(x)
41 #define RT5621_VERSION "0.01 alsa 1.0.24"
43 static int caps_charge = 500;
44 module_param(caps_charge, int, 0);
45 MODULE_PARM_DESC(caps_charge, "RT5621 cap charge time (msecs)");
47 struct snd_soc_codec *rt5621_codec;
49 static void rt5621_work(struct work_struct *work);
51 static struct workqueue_struct *rt5621_workq;
52 static DECLARE_DELAYED_WORK(delayed_work, rt5621_work);
54 #define ENABLE_EQ_HREQ 1
75 typedef struct _HW_EQ_PRESET
83 HW_EQ_PRESET HwEq_Preset[]={
84 /* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x 0x9 0xa 0x 0xc 0x62*/
85 {NORMAL,{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x0000},
86 {CLUB ,{0x1C10,0x0000,0xC1CC,0x1E5D,0x0699,0xCD48,0x188D,0x0699,0xC3B6,0x1CD0,0x0699,0x0436,0x0000},0x800E},
87 {DANCE ,{0x1F2C,0x095B,0xC071,0x1F95,0x0616,0xC96E,0x1B11,0xFC91,0xDCF2,0x1194,0xFAF2,0x0436,0x0000},0x800F},
88 {LIVE ,{0x1EB5,0xFCB6,0xC24A,0x1DF8,0x0E7C,0xC883,0x1C10,0x0699,0xDA41,0x1561,0x0295,0x0436,0x0000},0x800F},
89 {POP ,{0x1E98,0xFCB6,0xC340,0x1D60,0x095B,0xC6AC,0x1BBC,0x0556,0x0689,0x0F33,0x0000,0xEDD1,0xF805},0x801F},
90 {ROCK ,{0x1EB5,0xFCB6,0xC071,0x1F95,0x0424,0xC30A,0x1D27,0xF900,0x0C5D,0x0FC7,0x0E23,0x0436,0x0000},0x800F},
91 {OPPO ,{0x0000,0x0000,0xCA4A,0x17F8,0x0FEC,0xCA4A,0x17F8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x800F},
92 {TREBLE,{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x188D,0x1699},0x8010},
93 {BASS ,{0x1A43,0x0C00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x8001},
94 {EQTEST,{0x1F8C,0x1830,0xC118,0x1EEF,0xFD77,0xD8CB,0x1BBC,0x0556,0x0689,0x0F33,0x0000,0xF17F,0x0FEC},0x8003},
97 static const u16 rt5621_reg[RT5621_VENDOR_ID2 + 1] = {
98 [RT5621_RESET] = 0x59b4,
99 [RT5621_SPK_OUT_VOL] = 0x8080,
100 [RT5621_HP_OUT_VOL] = 0x8080,
101 [RT5621_MONO_AUX_OUT_VOL] = 0x8080,
102 [RT5621_AUXIN_VOL] = 0xe808,
103 [RT5621_LINE_IN_VOL] = 0xe808,
104 [RT5621_STEREO_DAC_VOL] = 0xe808,
105 [RT5621_MIC_VOL] = 0x0808,
106 [RT5621_MIC_ROUTING_CTRL] = 0xe0e0,
107 [RT5621_ADC_REC_GAIN] = 0xf58b,
108 [RT5621_ADC_REC_MIXER] = 0x7f7f,
109 [RT5621_SOFT_VOL_CTRL_TIME] = 0x000a,
110 [RT5621_OUTPUT_MIXER_CTRL] = 0xc000,
111 [RT5621_AUDIO_INTERFACE] = 0x8000,
112 [RT5621_STEREO_AD_DA_CLK_CTRL] = 0x166d,
113 [RT5621_ADD_CTRL_REG] = 0x5300,
114 [RT5621_GPIO_PIN_CONFIG] = 0x1c0e,
115 [RT5621_GPIO_PIN_POLARITY] = 0x1c0e,
116 [RT5621_GPIO_PIN_STATUS] = 0x0002,
117 [RT5621_OVER_TEMP_CURR_STATUS] = 0x003c,
118 [RT5621_PSEDUEO_SPATIAL_CTRL] = 0x0497,
119 [RT5621_AVC_CTRL] = 0x000b,
120 [RT5621_VENDOR_ID1] = 0x10ec,
121 [RT5621_VENDOR_ID2] = 0x2003,
124 #define rt5621_write_mask(c, reg, value, mask) snd_soc_update_bits(c, reg, mask, value)
126 #define rt5621_write_index_reg(c, addr, data) \
128 snd_soc_write(c, 0x6a, addr); \
129 snd_soc_write(c, 0x6c, data); \
132 static int rt5621_reset(struct snd_soc_codec *codec)
134 return snd_soc_write(codec, RT5621_RESET, 0);
137 static int rt5621_volatile_register(
138 struct snd_soc_codec *codec, unsigned int reg)
142 case RT5621_HID_CTRL_DATA:
143 case RT5621_GPIO_PIN_STATUS:
144 case RT5621_OVER_TEMP_CURR_STATUS:
151 static int rt5621_readable_register(
152 struct snd_soc_codec *codec, unsigned int reg)
156 case RT5621_SPK_OUT_VOL:
157 case RT5621_HP_OUT_VOL:
158 case RT5621_MONO_AUX_OUT_VOL:
159 case RT5621_AUXIN_VOL:
160 case RT5621_LINE_IN_VOL:
161 case RT5621_STEREO_DAC_VOL:
163 case RT5621_MIC_ROUTING_CTRL:
164 case RT5621_ADC_REC_GAIN:
165 case RT5621_ADC_REC_MIXER:
166 case RT5621_SOFT_VOL_CTRL_TIME:
167 case RT5621_OUTPUT_MIXER_CTRL:
168 case RT5621_MIC_CTRL:
169 case RT5621_AUDIO_INTERFACE:
170 case RT5621_STEREO_AD_DA_CLK_CTRL:
171 case RT5621_COMPANDING_CTRL:
172 case RT5621_PWR_MANAG_ADD1:
173 case RT5621_PWR_MANAG_ADD2:
174 case RT5621_PWR_MANAG_ADD3:
175 case RT5621_ADD_CTRL_REG:
176 case RT5621_GLOBAL_CLK_CTRL_REG:
177 case RT5621_PLL_CTRL:
178 case RT5621_GPIO_OUTPUT_PIN_CTRL:
179 case RT5621_GPIO_PIN_CONFIG:
180 case RT5621_GPIO_PIN_POLARITY:
181 case RT5621_GPIO_PIN_STICKY:
182 case RT5621_GPIO_PIN_WAKEUP:
183 case RT5621_GPIO_PIN_STATUS:
184 case RT5621_GPIO_PIN_SHARING:
185 case RT5621_OVER_TEMP_CURR_STATUS:
186 case RT5621_JACK_DET_CTRL:
187 case RT5621_MISC_CTRL:
188 case RT5621_PSEDUEO_SPATIAL_CTRL:
190 case RT5621_EQ_MODE_ENABLE:
191 case RT5621_AVC_CTRL:
192 case RT5621_HID_CTRL_INDEX:
193 case RT5621_HID_CTRL_DATA:
194 case RT5621_VENDOR_ID1:
195 case RT5621_VENDOR_ID2:
203 //static const char *rt5621_spkl_pga[] = {"Vmid","HPL mixer","SPK mixer","Mono Mixer"};
204 static const char *rt5621_spkn_source_sel[] = {"RN", "RP", "LN"};
205 static const char *rt5621_spk_pga[] = {"Vmid","HP mixer","SPK mixer","Mono Mixer"};
206 static const char *rt5621_hpl_pga[] = {"Vmid","HPL mixer"};
207 static const char *rt5621_hpr_pga[] = {"Vmid","HPR mixer"};
208 static const char *rt5621_mono_pga[] = {"Vmid","HP mixer","SPK mixer","Mono Mixer"};
209 static const char *rt5621_amp_type_sel[] = {"Class AB","Class D"};
210 static const char *rt5621_mic_boost_sel[] = {"Bypass","20db","30db","40db"};
212 static const struct soc_enum rt5621_enum[] = {
213 SOC_ENUM_SINGLE(RT5621_OUTPUT_MIXER_CTRL, 14, 3, rt5621_spkn_source_sel), /* spkn source from hp mixer */
214 SOC_ENUM_SINGLE(RT5621_OUTPUT_MIXER_CTRL, 10, 4, rt5621_spk_pga), /* spk input sel 1 */
215 SOC_ENUM_SINGLE(RT5621_OUTPUT_MIXER_CTRL, 9, 2, rt5621_hpl_pga), /* hp left input sel 2 */
216 SOC_ENUM_SINGLE(RT5621_OUTPUT_MIXER_CTRL, 8, 2, rt5621_hpr_pga), /* hp right input sel 3 */
217 SOC_ENUM_SINGLE(RT5621_OUTPUT_MIXER_CTRL, 6, 4, rt5621_mono_pga), /* mono input sel 4 */
218 SOC_ENUM_SINGLE(RT5621_MIC_CTRL, 10,4, rt5621_mic_boost_sel), /*Mic1 boost sel 5 */
219 SOC_ENUM_SINGLE(RT5621_MIC_CTRL, 8,4,rt5621_mic_boost_sel), /*Mic2 boost sel 6 */
220 SOC_ENUM_SINGLE(RT5621_OUTPUT_MIXER_CTRL,13,2,rt5621_amp_type_sel), /*Speaker AMP sel 7 */
223 static int rt5621_amp_sel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
225 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
226 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
228 unsigned short mask, bitmask;
230 for (bitmask = 1; bitmask < e->max; bitmask <<= 1);
232 if (ucontrol->value.enumerated.item[0] > e->max - 1)
234 val = ucontrol->value.enumerated.item[0] << e->shift_l;
235 mask = (bitmask - 1) << e->shift_l;
236 if (e->shift_l != e->shift_r) {
237 if (ucontrol->value.enumerated.item[1] > e->max - 1)
239 val |= ucontrol->value.enumerated.item[1] << e->shift_r;
240 mask |= (bitmask - 1) << e->shift_r;
243 snd_soc_update_bits(codec, e->reg, mask, val);
248 snd_soc_update_bits(codec, 0x3c, 0x0000, 0x4000); /*power off classd*/
249 snd_soc_update_bits(codec, 0x3c, 0x8000, 0x8000); /*power on classab*/
251 snd_soc_update_bits(codec, 0x3c, 0x0000, 0x8000); /*power off classab*/
252 snd_soc_update_bits(codec, 0x3c, 0x4000, 0x4000); /*power on classd*/
258 //*****************************************************************************
260 //function:Change audio codec power status
262 //*****************************************************************************
263 static int rt5621_ChangeCodecPowerStatus(struct snd_soc_codec *codec,int power_state)
265 unsigned short int PowerDownState=0;
267 switch(power_state) {
268 case POWER_STATE_D0: //FULL ON-----power on all power
270 snd_soc_write(codec,RT5621_PWR_MANAG_ADD1,~PowerDownState);
271 snd_soc_write(codec,RT5621_PWR_MANAG_ADD2,~PowerDownState);
272 snd_soc_write(codec,RT5621_PWR_MANAG_ADD3,~PowerDownState);
274 case POWER_STATE_D1: //LOW ON-----
275 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD2 ,PWR_VREF |
276 PWR_DAC_REF_CIR | PWR_L_DAC_CLK | PWR_R_DAC_CLK |
277 PWR_L_HP_MIXER | PWR_R_HP_MIXER | PWR_L_ADC_CLK_GAIN |
278 PWR_R_ADC_CLK_GAIN | PWR_L_ADC_REC_MIXER | PWR_R_ADC_REC_MIXER |
279 PWR_CLASS_AB, PWR_VREF | PWR_DAC_REF_CIR | PWR_L_DAC_CLK |
280 PWR_R_DAC_CLK | PWR_L_HP_MIXER | PWR_R_HP_MIXER |
281 PWR_L_ADC_CLK_GAIN | PWR_R_ADC_CLK_GAIN |
282 PWR_L_ADC_REC_MIXER | PWR_R_ADC_REC_MIXER | PWR_CLASS_AB);
284 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD3 ,PWR_MAIN_BIAS |
285 PWR_HP_R_OUT_VOL | PWR_HP_L_OUT_VOL | PWR_SPK_OUT |
286 PWR_MIC1_FUN_CTRL | PWR_MIC1_BOOST_MIXER, PWR_MAIN_BIAS |
287 PWR_HP_R_OUT_VOL | PWR_HP_L_OUT_VOL | PWR_SPK_OUT |
288 PWR_MIC1_FUN_CTRL | PWR_MIC1_BOOST_MIXER);
290 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD1 ,PWR_MAIN_I2S_EN |
291 PWR_HP_OUT_ENH_AMP | PWR_HP_OUT_AMP | PWR_MIC1_BIAS_EN,
292 PWR_MAIN_I2S_EN | PWR_HP_OUT_ENH_AMP | PWR_HP_OUT_AMP |
296 case POWER_STATE_D1_PLAYBACK: //Low on of Playback
297 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD2, PWR_VREF | PWR_DAC_REF_CIR |
298 PWR_L_DAC_CLK | PWR_R_DAC_CLK | PWR_L_HP_MIXER | PWR_R_HP_MIXER |
299 PWR_CLASS_AB | PWR_CLASS_D, PWR_VREF | PWR_DAC_REF_CIR |
300 PWR_L_DAC_CLK | PWR_R_DAC_CLK | PWR_L_HP_MIXER | PWR_R_HP_MIXER |
301 PWR_CLASS_AB | PWR_CLASS_D);
303 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD3, PWR_MAIN_BIAS |
304 PWR_HP_R_OUT_VOL | PWR_HP_L_OUT_VOL | PWR_SPK_OUT,
305 PWR_MAIN_BIAS | PWR_HP_R_OUT_VOL | PWR_HP_L_OUT_VOL | PWR_SPK_OUT);
307 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD1, PWR_MAIN_I2S_EN |
308 PWR_HP_OUT_ENH_AMP | PWR_HP_OUT_AMP, PWR_MAIN_I2S_EN |
309 PWR_HP_OUT_ENH_AMP | PWR_HP_OUT_AMP);
312 case POWER_STATE_D1_RECORD: //Low on of Record
313 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD1, PWR_MAIN_I2S_EN |
314 PWR_MIC1_BIAS_EN, PWR_MAIN_I2S_EN | PWR_MIC1_BIAS_EN);
315 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD2, PWR_VREF |
316 PWR_L_ADC_CLK_GAIN | PWR_R_ADC_CLK_GAIN | PWR_L_ADC_REC_MIXER |
317 PWR_R_ADC_REC_MIXER, PWR_VREF | PWR_L_ADC_CLK_GAIN |
318 PWR_R_ADC_CLK_GAIN | PWR_L_ADC_REC_MIXER | PWR_R_ADC_REC_MIXER);
319 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD3, PWR_MAIN_BIAS |
320 PWR_MIC2_BOOST_MIXER | PWR_MIC1_BOOST_MIXER, PWR_MAIN_BIAS |
321 PWR_MIC2_BOOST_MIXER | PWR_MIC1_BOOST_MIXER);
324 case POWER_STATE_D2: //STANDBY----
325 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD1, 0, PWR_MAIN_I2S_EN |
326 PWR_HP_OUT_ENH_AMP | PWR_HP_OUT_AMP | PWR_MIC1_BIAS_EN);
327 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD3, 0, PWR_HP_R_OUT_VOL |
328 PWR_HP_L_OUT_VOL | PWR_SPK_OUT | PWR_MIC1_FUN_CTRL |
329 PWR_MIC1_BOOST_MIXER);
330 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD2, 0, PWR_DAC_REF_CIR |
331 PWR_L_DAC_CLK | PWR_R_DAC_CLK | PWR_L_HP_MIXER | PWR_R_HP_MIXER|
332 PWR_L_ADC_CLK_GAIN | PWR_R_ADC_CLK_GAIN | PWR_L_ADC_REC_MIXER |
333 PWR_R_ADC_REC_MIXER | PWR_CLASS_AB | PWR_CLASS_D);
336 case POWER_STATE_D2_PLAYBACK: //STANDBY of playback
337 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD3, 0, /*PWR_HP_R_OUT_VOL |
338 PWR_HP_L_OUT_VOL |*/ PWR_SPK_OUT);
339 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD1, 0, PWR_HP_OUT_ENH_AMP |
341 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD2, 0, PWR_DAC_REF_CIR |
342 PWR_L_DAC_CLK | PWR_R_DAC_CLK | PWR_L_HP_MIXER | PWR_R_HP_MIXER |
343 PWR_CLASS_AB | PWR_CLASS_D);
346 case POWER_STATE_D2_RECORD: //STANDBY of record
347 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD1, 0, PWR_MIC1_BIAS_EN);
348 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD2, 0, PWR_L_ADC_CLK_GAIN |
349 PWR_R_ADC_CLK_GAIN | PWR_L_ADC_REC_MIXER | PWR_R_ADC_REC_MIXER);
350 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD3, 0, PWR_MIC2_BOOST_MIXER |
351 PWR_MIC1_BOOST_MIXER);
354 case POWER_STATE_D3: //SLEEP
355 case POWER_STATE_D4: //OFF----power off all power
356 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD1, 0, PWR_HP_OUT_ENH_AMP |
358 snd_soc_write(codec, RT5621_PWR_MANAG_ADD3, 0);
359 snd_soc_write(codec, RT5621_PWR_MANAG_ADD1, 0);
360 snd_soc_write(codec, RT5621_PWR_MANAG_ADD2, 0);
371 //*****************************************************************************
373 //function AudioOutEnable:Mute/Unmute audio out channel
374 //WavOutPath:output channel
375 //Mute :Mute/Unmute output channel
377 //*****************************************************************************
378 static int rt5621_AudioOutEnable(struct snd_soc_codec *codec,
379 unsigned short int WavOutPath, int Mute)
385 case RT_WAVOUT_ALL_ON:
386 RetVal = rt5621_write_mask(codec, RT5621_SPK_OUT_VOL, RT_L_MUTE | RT_R_MUTE,
387 RT_L_MUTE | RT_R_MUTE); //Mute Speaker right/left channel
388 RetVal = rt5621_write_mask(codec, RT5621_HP_OUT_VOL, RT_L_MUTE | RT_R_MUTE,
389 RT_L_MUTE | RT_R_MUTE); //Mute headphone right/left channel
390 RetVal = rt5621_write_mask(codec, RT5621_MONO_AUX_OUT_VOL, RT_L_MUTE |
391 RT_R_MUTE, RT_L_MUTE | RT_R_MUTE); //Mute Aux/Mono right/left channel
392 RetVal = rt5621_write_mask(codec, RT5621_STEREO_DAC_VOL, RT_M_HP_MIXER |
393 RT_M_SPK_MIXER | RT_M_MONO_MIXER, RT_M_HP_MIXER |
394 RT_M_SPK_MIXER | RT_M_MONO_MIXER); //Mute DAC to HP,Speaker,Mono Mixer
398 RetVal = rt5621_write_mask(codec, RT5621_HP_OUT_VOL, RT_L_MUTE | RT_R_MUTE,
399 RT_L_MUTE | RT_R_MUTE); //Mute headphone right/left channel
403 RetVal = rt5621_write_mask(codec, RT5621_SPK_OUT_VOL, RT_L_MUTE | RT_R_MUTE,
404 RT_L_MUTE | RT_R_MUTE); //Mute Speaker right/left channel
407 case RT_WAVOUT_AUXOUT:
408 RetVal = rt5621_write_mask(codec, RT5621_MONO_AUX_OUT_VOL, RT_L_MUTE |
409 RT_R_MUTE, RT_L_MUTE | RT_R_MUTE); //Mute AuxOut right/left channel
414 RetVal = rt5621_write_mask(codec, RT5621_MONO_AUX_OUT_VOL, RT_L_MUTE,
415 RT_L_MUTE); //Mute MonoOut channel
419 RetVal = rt5621_write_mask(codec, RT5621_STEREO_DAC_VOL, RT_M_HP_MIXER |
420 RT_M_SPK_MIXER | RT_M_MONO_MIXER, RT_M_HP_MIXER | RT_M_SPK_MIXER |
421 RT_M_MONO_MIXER); //Mute DAC to HP,Speaker,Mono Mixer
429 case RT_WAVOUT_ALL_ON:
430 RetVal = rt5621_write_mask(codec, RT5621_SPK_OUT_VOL, 0, RT_L_MUTE |
431 RT_R_MUTE); //Mute Speaker right/left channel
432 RetVal = rt5621_write_mask(codec, RT5621_HP_OUT_VOL, 0, RT_L_MUTE |
433 RT_R_MUTE); //Mute headphone right/left channel
434 RetVal = rt5621_write_mask(codec, RT5621_MONO_AUX_OUT_VOL, 0, RT_L_MUTE |
435 RT_R_MUTE); //Mute Aux/Mono right/left channel
436 RetVal = rt5621_write_mask(codec, RT5621_STEREO_DAC_VOL, 0, RT_M_HP_MIXER |
437 RT_M_SPK_MIXER | RT_M_MONO_MIXER); //Mute DAC to HP,Speaker,Mono Mixer
440 RetVal = rt5621_write_mask(codec, RT5621_HP_OUT_VOL, 0, RT_L_MUTE |
441 RT_R_MUTE); //UnMute headphone right/left channel
445 RetVal = rt5621_write_mask(codec, RT5621_SPK_OUT_VOL, 0, RT_L_MUTE |
446 RT_R_MUTE); //unMute Speaker right/left channel
448 case RT_WAVOUT_AUXOUT:
449 RetVal = rt5621_write_mask(codec, RT5621_MONO_AUX_OUT_VOL, 0, RT_L_MUTE |
450 RT_R_MUTE); //unMute AuxOut right/left channel
454 RetVal = rt5621_write_mask(codec, RT5621_MONO_AUX_OUT_VOL, 0,
455 RT_L_MUTE); //unMute MonoOut channel
459 RetVal = rt5621_write_mask(codec, RT5621_STEREO_DAC_VOL, 0, RT_M_HP_MIXER |
460 RT_M_SPK_MIXER | RT_M_MONO_MIXER); //unMute DAC to HP,Speaker,Mono Mixer
472 //*****************************************************************************
474 //function:Enable/Disable ADC input source control
476 //*****************************************************************************
477 static int Enable_ADC_Input_Source(struct snd_soc_codec *codec,unsigned short int ADC_Input_Sour,int Enable)
483 bRetVal=rt5621_write_mask(codec,RT5621_ADC_REC_MIXER,0,ADC_Input_Sour);
486 bRetVal=rt5621_write_mask(codec,RT5621_ADC_REC_MIXER,ADC_Input_Sour,ADC_Input_Sour);
492 static void rt5621_update_eqmode(struct snd_soc_codec *codec, int mode)
496 if (mode == NORMAL) {
497 /*clear EQ parameter*/
498 for (HwEqIndex=0; HwEqIndex<=0x0C; HwEqIndex++) {
500 rt5621_write_index_reg(codec, HwEqIndex, HwEq_Preset[mode].EqValue[HwEqIndex])
503 snd_soc_write(codec, 0x62, 0x0); /*disable EQ block*/
505 snd_soc_write(codec, 0x62, HwEq_Preset[mode].HwEQCtrl);
507 /*Fill EQ parameter*/
508 for (HwEqIndex=0; HwEqIndex<=0x0C; HwEqIndex++) {
510 rt5621_write_index_reg(codec, HwEqIndex, HwEq_Preset[mode].EqValue[HwEqIndex])
512 //update EQ parameter
513 snd_soc_write(codec, 0x66, 0x1f);
514 schedule_timeout_uninterruptible(msecs_to_jiffies(1));
515 snd_soc_write(codec, 0x66, 0x0);
519 static const struct snd_kcontrol_new rt5621_snd_controls[] = {
520 SOC_DOUBLE("Speaker Playback Volume", RT5621_SPK_OUT_VOL, 8, 0, 31, 1),
521 SOC_DOUBLE("Speaker Playback Switch", RT5621_SPK_OUT_VOL, 15, 7, 1, 1),
522 SOC_DOUBLE("Headphone Playback Volume", RT5621_HP_OUT_VOL, 8, 0, 31, 1),
523 SOC_DOUBLE("Headphone Playback Switch", RT5621_HP_OUT_VOL,15, 7, 1, 1),
524 SOC_DOUBLE("AUX Playback Volume", RT5621_MONO_AUX_OUT_VOL, 8, 0, 31, 1),
525 SOC_DOUBLE("AUX Playback Switch", RT5621_MONO_AUX_OUT_VOL, 15, 7, 1, 1),
526 SOC_DOUBLE("PCM Playback Volume", RT5621_STEREO_DAC_VOL, 8, 0, 31, 1),
527 SOC_DOUBLE("Line In Volume", RT5621_LINE_IN_VOL, 8, 0, 31, 1),
528 SOC_SINGLE("Mic 1 Volume", RT5621_MIC_VOL, 8, 31, 1),
529 SOC_SINGLE("Mic 2 Volume", RT5621_MIC_VOL, 0, 31, 1),
530 SOC_ENUM("Mic 1 Boost", rt5621_enum[5]),
531 SOC_ENUM("Mic 2 Boost", rt5621_enum[6]),
532 SOC_ENUM_EXT("Speaker Amp Type", rt5621_enum[7], snd_soc_get_enum_double, rt5621_amp_sel_put),
533 SOC_DOUBLE("AUX In Volume", RT5621_AUXIN_VOL, 8, 0, 31, 1),
534 SOC_DOUBLE("Capture Volume", RT5621_ADC_REC_GAIN, 7, 0, 31, 0),
537 void hp_depop_mode2(struct snd_soc_codec *codec)
539 snd_soc_update_bits(codec, 0x3e, 0x8000, 0x8000);
540 snd_soc_update_bits(codec, 0x04, 0x8080, 0x8080);
541 snd_soc_update_bits(codec, 0x3a, 0x0100, 0x0100);
542 snd_soc_update_bits(codec, 0x3c, 0x2000, 0x2000);
543 snd_soc_update_bits(codec, 0x3e, 0x0600, 0x0600);
544 snd_soc_update_bits(codec, 0x5e, 0x0200, 0x0200);
545 schedule_timeout_uninterruptible(msecs_to_jiffies(300));
548 void aux_depop_mode2(struct snd_soc_codec *codec)
550 snd_soc_update_bits(codec, 0x3e, 0x8000, 0x8000);
551 snd_soc_update_bits(codec, 0x06, 0x8080, 0x8080);
552 snd_soc_update_bits(codec, 0x3a, 0x0100, 0x0100);
553 snd_soc_update_bits(codec, 0x3c, 0x2000, 0x2000);
554 snd_soc_update_bits(codec, 0x3e, 0x6000, 0x6000);
555 snd_soc_update_bits(codec, 0x5e, 0x0020, 0x0200);
556 schedule_timeout_uninterruptible(msecs_to_jiffies(300));
557 snd_soc_update_bits(codec, 0x3a, 0x0002, 0x0002);
558 snd_soc_update_bits(codec, 0x3a, 0x0001, 0x0001);
561 static int rt5621_pcm_hw_prepare(struct snd_pcm_substream *substream,
562 struct snd_soc_dai *codec_dai)
565 struct snd_soc_codec *codec = codec_dai->codec;
566 int stream = substream->stream;
570 case SNDRV_PCM_STREAM_PLAYBACK:
572 rt5621_ChangeCodecPowerStatus(codec,POWER_STATE_D1_PLAYBACK); //power on dac to hp and speaker out
574 rt5621_AudioOutEnable(codec,RT_WAVOUT_SPK,0); //unmute speaker out
576 rt5621_AudioOutEnable(codec,RT_WAVOUT_HP,0); //unmute hp
578 rt5621_AudioOutEnable(codec,RT_WAVOUT_AUXOUT,0); //unmute auxout out
581 case SNDRV_PCM_STREAM_CAPTURE:
583 rt5621_ChangeCodecPowerStatus(codec,POWER_STATE_D1_RECORD); //power on input to adc
585 Enable_ADC_Input_Source(codec,RT_WAVIN_L_MIC1|RT_WAVIN_R_MIC1,1); //enable record source from mic1
600 static const struct _pll_div codec_pll_div[] = {
602 { 2048000, 8192000, 0x0ea0},
603 { 3686400, 8192000, 0x4e27},
604 { 12000000, 8192000, 0x456b},
605 { 13000000, 8192000, 0x495f},
606 { 13100000, 8192000, 0x0320},
607 { 2048000, 11289600, 0xf637},
608 { 3686400, 11289600, 0x2f22},
609 { 12000000, 11289600, 0x3e2f},
610 { 13000000, 11289600, 0x4d5b},
611 { 13100000, 11289600, 0x363b},
612 { 2048000, 16384000, 0x1ea0},
613 { 3686400, 16384000, 0x9e27},
614 { 12000000, 16384000, 0x452b},
615 { 13000000, 16384000, 0x542f},
616 { 13100000, 16384000, 0x03a0},
617 { 2048000, 16934400, 0xe625},
618 { 3686400, 16934400, 0x9126},
619 { 12000000, 16934400, 0x4d2c},
620 { 13000000, 16934400, 0x742f},
621 { 13100000, 16934400, 0x3c27},
622 { 2048000, 22579200, 0x2aa0},
623 { 3686400, 22579200, 0x2f20},
624 { 12000000, 22579200, 0x7e2f},
625 { 13000000, 22579200, 0x742f},
626 { 13100000, 22579200, 0x3c27},
627 { 2048000, 24576000, 0x2ea0},
628 { 3686400, 24576000, 0xee27},
629 { 12000000, 24576000, 0x2915},
630 { 13000000, 24576000, 0x772e},
631 { 13100000, 24576000, 0x0d20},
634 static const struct _pll_div codec_bclk_pll_div[] = {
636 { 1536000, 24576000, 0x3ea0},
637 { 3072000, 24576000, 0x1ea0},
638 { 512000, 24576000, 0x8e90},
639 { 256000, 24576000, 0xbe80},
640 { 2822400, 11289600, 0x1ee0},
641 { 3072000, 12288000, 0x1ee0},
645 static int rt5621_set_dai_pll(struct snd_soc_dai *dai,
646 int pll_id,int source, unsigned int freq_in, unsigned int freq_out)
650 struct snd_soc_codec *codec = dai->codec;
652 if (pll_id < RT5621_PLL_FR_MCLK || pll_id > RT5621_PLL_FR_BCLK)
655 //rt5621_write_mask(codec,RT5621_PWR_MANAG_ADD2, 0x0000,0x1000); //disable PLL power
657 if (!freq_in || !freq_out) {
662 if (RT5621_PLL_FR_MCLK == pll_id) {
663 for (i = 0; i < ARRAY_SIZE(codec_pll_div); i++) {
665 if (codec_pll_div[i].pll_in == freq_in && codec_pll_div[i].pll_out == freq_out)
667 snd_soc_update_bits(codec, RT5621_GLOBAL_CLK_CTRL_REG, 0x0000, 0x4000);
668 snd_soc_write(codec,RT5621_PLL_CTRL,codec_pll_div[i].regvalue);//set PLL parameter
669 snd_soc_update_bits(codec,RT5621_PWR_MANAG_ADD2, 0x1000,0x1000); //enable PLL power
674 else if (RT5621_PLL_FR_BCLK == pll_id)
676 for (i = 0; i < ARRAY_SIZE(codec_bclk_pll_div); i++)
678 if ((freq_in == codec_bclk_pll_div[i].pll_in) && (freq_out == codec_bclk_pll_div[i].pll_out))
680 snd_soc_update_bits(codec, RT5621_GLOBAL_CLK_CTRL_REG, 0x4000, 0x4000);
681 snd_soc_write(codec,RT5621_PLL_CTRL,codec_bclk_pll_div[i].regvalue);//set PLL parameter
682 snd_soc_update_bits(codec,RT5621_PWR_MANAG_ADD2, 0x1000,0x1000); //enable PLL power
688 snd_soc_update_bits(codec,RT5621_GLOBAL_CLK_CTRL_REG,0x8000,0x8000);//Codec sys-clock from PLL
700 /* codec hifi mclk (after PLL) clock divider coefficients */
701 static const struct _coeff_div coeff_div[] = {
703 { 8192000, 8000, 256*4, 0x2a2d},
704 {12288000, 8000, 384*4, 0x2c2f},
707 {11289600, 11025, 256*4, 0x2a2d},
708 {16934400, 11025, 384*4, 0x2c2f},
711 {12288000, 16000, 384*2, 0x1c2f},
712 {16384000, 16000, 256*4, 0x2a2d},
713 {24576000, 16000, 384*4, 0x2c2f},
716 {11289600, 22050, 256*2, 0x1a2d},
717 {16934400, 22050, 384*2, 0x1c2f},
720 {12288000, 32000, 384 , 0x0c2f},
721 {16384000, 32000, 256*2, 0x1a2d},
722 {24576000, 32000, 384*2, 0x1c2f},
725 {11289600, 44100, 256*1, 0x0a2d},
726 {22579200, 44100, 256*2, 0x1a2d},
727 {45158400, 44100, 256*4, 0x2a2d},
730 {12288000, 48000, 256*1, 0x0a2d},
731 {24576000, 48000, 256*2, 0x1a2d},
732 {49152000, 48000, 256*4, 0x2a2d},
734 //MCLK is 24.576Mhz(for 8k,16k,32k)
735 {24576000, 8000, 384*8, 0x3c6b},
736 {24576000, 16000, 384*4, 0x2c6b},
737 {24576000, 32000, 384*2, 0x1c6b},
739 //MCLK is 22.5792mHz(for 11k,22k)
740 {22579200, 11025, 256*8, 0x3a2d},
741 {22579200, 22050, 256*4, 0x2a2d},
746 static int get_coeff(int mclk, int rate)
750 DBG("get_coeff mclk=%d,rate=%d\n",mclk,rate);
752 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
753 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
761 * Clock after PLL and dividers
763 /*in this driver, you have to set sysclk to be 24576000,
764 * but you don't need to give a clk to be 24576000, our
765 * internal pll will generate this clock! so it won't make
768 static int rt5621_set_dai_sysclk(struct snd_soc_dai *dai,
769 int clk_id, unsigned int freq, int dir)
771 struct snd_soc_codec *codec = dai->codec;
772 struct rt5621_priv *rt5621 = snd_soc_codec_get_drvdata(codec);
774 if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
775 rt5621->sysclk = freq;
779 printk("unsupported sysclk freq %u for audio i2s\n", freq);
785 static int rt5621_set_dai_fmt(struct snd_soc_dai *dai,
788 struct snd_soc_codec *codec = dai->codec;
791 /* set master/slave audio interface */
792 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
793 case SND_SOC_DAIFMT_CBM_CFM:
796 case SND_SOC_DAIFMT_CBS_CFS:
803 /* interface format */
804 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
805 case SND_SOC_DAIFMT_I2S:
808 case SND_SOC_DAIFMT_RIGHT_J:
811 case SND_SOC_DAIFMT_LEFT_J:
814 case SND_SOC_DAIFMT_DSP_A:
817 case SND_SOC_DAIFMT_DSP_B:
824 /* clock inversion */
825 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
826 case SND_SOC_DAIFMT_NB_NF:
829 case SND_SOC_DAIFMT_IB_NF:
836 snd_soc_write(codec,RT5621_AUDIO_INTERFACE,iface);
841 static int rt5621_pcm_hw_params(struct snd_pcm_substream *substream,
842 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
844 struct snd_soc_codec *codec = dai->codec;
845 struct rt5621_priv *rt5621 = snd_soc_codec_get_drvdata(codec);
846 u16 iface = snd_soc_read(codec,RT5621_AUDIO_INTERFACE)&0xfff3;
847 int coeff = get_coeff(rt5621->sysclk, params_rate(params));
849 DBG("rt5621_pcm_hw_params\n");
851 coeff = get_coeff(24576000, params_rate(params)); /*if not set sysclk, default to be 24.576MHz*/
854 switch (params_format(params)) {
855 case SNDRV_PCM_FORMAT_S16_LE:
858 case SNDRV_PCM_FORMAT_S20_3LE:
861 case SNDRV_PCM_FORMAT_S24_LE:
864 case SNDRV_PCM_FORMAT_S32_LE:
869 /* set iface & srate */
870 snd_soc_write(codec, RT5621_AUDIO_INTERFACE, iface);
873 snd_soc_write(codec, RT5621_STEREO_AD_DA_CLK_CTRL, coeff_div[coeff].regvalue);
876 printk(KERN_ERR "cant find matched sysclk and rate config\n");
883 static int rt5621_set_bias_level(struct snd_soc_codec *codec,
884 enum snd_soc_bias_level level)
887 case SND_SOC_BIAS_ON:
888 snd_soc_update_bits(codec, RT5621_SPK_OUT_VOL, RT_L_MUTE | RT_R_MUTE, 0);
889 snd_soc_update_bits(codec, RT5621_HP_OUT_VOL, RT_L_MUTE | RT_R_MUTE, 0);
892 case SND_SOC_BIAS_PREPARE:
895 case SND_SOC_BIAS_STANDBY:
896 snd_soc_update_bits(codec, RT5621_SPK_OUT_VOL, RT_L_MUTE | RT_R_MUTE, RT_L_MUTE | RT_R_MUTE);
897 snd_soc_update_bits(codec, RT5621_HP_OUT_VOL, RT_L_MUTE | RT_R_MUTE, RT_L_MUTE | RT_R_MUTE);
898 if (SND_SOC_BIAS_OFF == codec->dapm.bias_level) {
899 snd_soc_write(codec, RT5621_PWR_MANAG_ADD3, 0x8000);//enable Main bias
900 snd_soc_write(codec, RT5621_PWR_MANAG_ADD2, 0x2000);//enable Vref
901 codec->cache_only = false;
902 snd_soc_cache_sync(codec);
906 case SND_SOC_BIAS_OFF:
907 snd_soc_update_bits(codec, RT5621_SPK_OUT_VOL, RT_L_MUTE | RT_R_MUTE, RT_L_MUTE | RT_R_MUTE);
908 snd_soc_update_bits(codec, RT5621_HP_OUT_VOL, RT_L_MUTE | RT_R_MUTE, RT_L_MUTE | RT_R_MUTE);
909 snd_soc_write(codec, RT5621_PWR_MANAG_ADD3, 0x0000);
910 snd_soc_write(codec, RT5621_PWR_MANAG_ADD2, 0x0000);
911 snd_soc_write(codec, RT5621_PWR_MANAG_ADD1, 0x0000);
917 codec->dapm.bias_level = level;
924 struct rt5621_init_reg{
930 static struct rt5621_init_reg init_data[] = {
931 {RT5621_AUDIO_INTERFACE, 0x8000}, //set I2S codec to slave mode
932 {RT5621_STEREO_DAC_VOL, 0x0505}, //default stereo DAC volume to 0db
933 {RT5621_OUTPUT_MIXER_CTRL, 0x2b40}, //default output mixer control
934 {RT5621_ADC_REC_MIXER, 0x3f3f}, //set record source is Mic1 by default
935 {RT5621_MIC_CTRL, 0x0a00}, //set Mic1,Mic2 boost 20db
936 {RT5621_SPK_OUT_VOL, 0x8080}, //default speaker volume to 0db
937 {RT5621_HP_OUT_VOL, 0x8080}, //default HP volume to -12db
938 {RT5621_ADD_CTRL_REG, 0x4b00}, //Class AB/D speaker ratio is 1.25VDD
939 {RT5621_STEREO_AD_DA_CLK_CTRL, 0x066d}, //set Dac filter to 256fs
940 {RT5621_ADC_REC_GAIN, 0xfa95}, //set ADC boost to 15db
941 {RT5621_HID_CTRL_INDEX, 0x46}, //Class D setting
942 {RT5621_MIC_VOL, 0x1f08},
943 {RT5621_HID_CTRL_DATA, 0xFFFF}, //power on Class D Internal register
944 {RT5621_JACK_DET_CTRL, 0x4810}, //power on Class D Internal register
946 #define RT5621_INIT_REG_NUM ARRAY_SIZE(init_data)
948 static int rt5621_reg_init(struct snd_soc_codec *codec)
952 for (i = 0; i < RT5621_INIT_REG_NUM; i++)
953 snd_soc_write(codec, init_data[i].reg_index, init_data[i].reg_value);
958 void codec_set_spk(bool on)
960 struct snd_soc_codec *codec = rt5621_codec;
962 DBG("%s: %d\n", __func__, on);
968 DBG("snd_soc_dapm_enable_pin\n");
969 snd_soc_dapm_enable_pin(&codec->dapm, "Headphone Jack");
970 snd_soc_dapm_enable_pin(&codec->dapm, "Ext Spk");
974 DBG("snd_soc_dapm_disable_pin\n");
975 snd_soc_dapm_disable_pin(&codec->dapm, "Headphone Jack");
976 snd_soc_dapm_disable_pin(&codec->dapm, "Ext Spk");
979 snd_soc_dapm_sync(&codec->dapm);
984 static void rt5621_work(struct work_struct *work)
986 struct snd_soc_codec *codec = rt5621_codec;
988 rt5621_set_bias_level(codec, codec->dapm.bias_level);
991 static int rt5621_probe(struct snd_soc_codec *codec)
995 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
997 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1000 codec->cache_bypass = 1;
1002 rt5621_reset(codec);
1003 snd_soc_write(codec, RT5621_PWR_MANAG_ADD3, 0x8000);//enable Main bias
1004 snd_soc_write(codec, RT5621_PWR_MANAG_ADD2, 0x2000);//enable Vref
1005 hp_depop_mode2(codec);
1006 rt5621_reg_init(codec);
1010 rt5621_write_index_reg(codec, 0x11,0x1);
1011 rt5621_write_index_reg(codec, 0x12,0x1);
1012 rt5621_update_eqmode(codec, HFREQ);
1015 rt5621_workq = create_freezable_workqueue("rt5621");
1016 if (rt5621_workq == NULL) {
1017 printk("wm8900_probe::create_freezeable_workqueue ERROR !");
1022 rt5621_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
1023 codec->dapm.bias_level = SND_SOC_BIAS_STANDBY;
1025 queue_delayed_work(rt5621_workq, &delayed_work,
1026 msecs_to_jiffies(caps_charge));
1028 codec->dapm.bias_level = SND_SOC_BIAS_STANDBY;
1030 rt5621_codec = codec;
1035 static int rt5621_remove(struct snd_soc_codec *codec)
1037 rt5621_set_bias_level(codec, SND_SOC_BIAS_OFF);
1039 cancel_delayed_work_sync(&delayed_work);
1044 static int rt5621_suspend(struct snd_soc_codec *codec, pm_message_t state)
1046 rt5621_set_bias_level(codec, SND_SOC_BIAS_OFF);
1050 static int rt5621_resume(struct snd_soc_codec *codec)
1053 rt5621_reset(codec);
1054 snd_soc_write(codec, RT5621_PWR_MANAG_ADD3, 0x8000);//enable Main bias
1055 snd_soc_write(codec, RT5621_PWR_MANAG_ADD2, 0x2000);//enable Vref
1057 hp_depop_mode2(codec);
1059 rt5621_reg_init(codec);
1063 rt5621_write_index_reg(codec, 0x11,0x1);
1064 rt5621_write_index_reg(codec, 0x12,0x1);
1065 rt5621_update_eqmode(codec, HFREQ);
1068 rt5621_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1069 if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) {
1070 rt5621_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
1071 codec->dapm.bias_level = SND_SOC_BIAS_ON;
1072 queue_delayed_work(rt5621_workq, &delayed_work,
1073 msecs_to_jiffies(caps_charge));
1078 #define rt5621_suspend NULL
1079 #define rt5621_resume NULL
1082 static void rt5621_shutdown(struct snd_pcm_substream *substream,
1083 struct snd_soc_dai *codec_dai)
1085 struct snd_soc_codec *codec = codec_dai->codec;
1086 int stream = substream->stream;
1090 case SNDRV_PCM_STREAM_PLAYBACK:
1092 rt5621_AudioOutEnable(codec,RT_WAVOUT_SPK,1); //mute speaker out
1094 rt5621_AudioOutEnable(codec,RT_WAVOUT_HP,1); //mute hp out
1096 rt5621_AudioOutEnable(codec,RT_WAVOUT_AUXOUT,1); //mute auxout
1098 rt5621_ChangeCodecPowerStatus(codec,POWER_STATE_D2_PLAYBACK); //power off dac to hp and speaker out and auxout
1103 case SNDRV_PCM_STREAM_CAPTURE:
1105 Enable_ADC_Input_Source(codec,RT_WAVIN_L_MIC1|RT_WAVIN_R_MIC1,0); //disable record source from mic1
1107 rt5621_ChangeCodecPowerStatus(codec,POWER_STATE_D2_RECORD);
1114 //#define RT5621_HIFI_RATES SNDRV_PCM_RATE_8000_48000
1115 #define RT5621_HIFI_RATES (SNDRV_PCM_RATE_44100) // zyy 20110704, playback and record use same sample rate
1117 #define RT5621_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
1118 SNDRV_PCM_FMTBIT_S24_LE)
1120 struct snd_soc_dai_ops rt5621_hifi_ops = {
1121 .hw_params = rt5621_pcm_hw_params,
1122 .set_fmt = rt5621_set_dai_fmt,
1123 .set_sysclk = rt5621_set_dai_sysclk,
1124 .set_pll = rt5621_set_dai_pll,
1125 .prepare = rt5621_pcm_hw_prepare,
1126 .shutdown = rt5621_shutdown,
1129 struct snd_soc_dai_driver rt5621_dai = {
1130 .name = "RT5621 HiFi",
1132 .stream_name = "HiFi Playback",
1135 .rates = RT5621_HIFI_RATES,
1136 .formats = RT5621_FORMATS,
1139 .stream_name = "HiFi Capture",
1142 .rates = RT5621_HIFI_RATES,
1143 .formats = RT5621_FORMATS,
1145 .ops = &rt5621_hifi_ops,
1148 static struct snd_soc_codec_driver soc_codec_dev_rt5621 = {
1149 .probe = rt5621_probe,
1150 .remove = rt5621_remove,
1151 .suspend = rt5621_suspend,
1152 .resume = rt5621_resume,
1153 .set_bias_level = rt5621_set_bias_level,
1154 .reg_cache_size = RT5621_VENDOR_ID2 + 1,
1155 .reg_word_size = sizeof(u16),
1156 .reg_cache_default = rt5621_reg,
1157 .volatile_register = rt5621_volatile_register,
1158 .readable_register = rt5621_readable_register,
1159 .reg_cache_step = 1,
1160 .controls = rt5621_snd_controls,
1161 .num_controls = ARRAY_SIZE(rt5621_snd_controls),
1164 static const struct i2c_device_id rt5621_i2c_id[] = {
1168 MODULE_DEVICE_TABLE(i2c, rt5621_i2c_id);
1170 static int rt5621_i2c_probe(struct i2c_client *i2c,
1171 const struct i2c_device_id *id)
1173 struct rt5621_priv *rt5621;
1176 rt5621 = kzalloc(sizeof(struct rt5621_priv), GFP_KERNEL);
1180 i2c_set_clientdata(i2c, rt5621);
1182 ret = snd_soc_register_codec(&i2c->dev,
1183 &soc_codec_dev_rt5621, &rt5621_dai, 1);
1190 static __devexit int rt5621_i2c_remove(struct i2c_client *i2c)
1192 snd_soc_unregister_codec(&i2c->dev);
1193 kfree(i2c_get_clientdata(i2c));
1197 struct i2c_driver rt5621_i2c_driver = {
1200 .owner = THIS_MODULE,
1202 .probe = rt5621_i2c_probe,
1203 .remove = __devexit_p(rt5621_i2c_remove),
1204 .id_table = rt5621_i2c_id,
1207 static int __init rt5621_modinit(void)
1209 return i2c_add_driver(&rt5621_i2c_driver);
1211 module_init(rt5621_modinit);
1213 static void __exit rt5621_modexit(void)
1215 i2c_del_driver(&rt5621_i2c_driver);
1217 module_exit(rt5621_modexit);
1219 MODULE_DESCRIPTION("ASoC RT5621 driver");
1220 MODULE_AUTHOR("Johnny Hsu <johnnyhsu@realtek.com>");
1221 MODULE_LICENSE("GPL");