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 <linux/of_gpio.h>
21 #include <sound/core.h>
22 #include <sound/pcm.h>
23 #include <sound/pcm_params.h>
24 #include <sound/soc.h>
25 #include <sound/soc-dapm.h>
26 #include <sound/initval.h>
27 #include <sound/tlv.h>
29 //#include <mach/gpio.h>
34 #include <linux/ioctl.h>
35 #include <linux/types.h>
39 #define DBG(x...) printk(x)
46 #define INVALID_GPIO -1
48 #define RT5621_VERSION "0.01 alsa 1.0.24"
50 int rt5621_spk_ctl_gpio = INVALID_GPIO;
51 static int caps_charge = 500;
52 module_param(caps_charge, int, 0);
53 MODULE_PARM_DESC(caps_charge, "RT5621 cap charge time (msecs)");
55 struct snd_soc_codec *rt5621_codec;
57 static void rt5621_work(struct work_struct *work);
59 static struct workqueue_struct *rt5621_workq;
60 static DECLARE_DELAYED_WORK(delayed_work, rt5621_work);
62 #define ENABLE_EQ_HREQ 1
83 typedef struct _HW_EQ_PRESET
91 HW_EQ_PRESET HwEq_Preset[]={
92 /* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x 0x9 0xa 0x 0xc 0x62*/
93 {NORMAL,{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x0000},
94 {CLUB ,{0x1C10,0x0000,0xC1CC,0x1E5D,0x0699,0xCD48,0x188D,0x0699,0xC3B6,0x1CD0,0x0699,0x0436,0x0000},0x800E},
95 {DANCE ,{0x1F2C,0x095B,0xC071,0x1F95,0x0616,0xC96E,0x1B11,0xFC91,0xDCF2,0x1194,0xFAF2,0x0436,0x0000},0x800F},
96 {LIVE ,{0x1EB5,0xFCB6,0xC24A,0x1DF8,0x0E7C,0xC883,0x1C10,0x0699,0xDA41,0x1561,0x0295,0x0436,0x0000},0x800F},
97 {POP ,{0x1E98,0xFCB6,0xC340,0x1D60,0x095B,0xC6AC,0x1BBC,0x0556,0x0689,0x0F33,0x0000,0xEDD1,0xF805},0x801F},
98 {ROCK ,{0x1EB5,0xFCB6,0xC071,0x1F95,0x0424,0xC30A,0x1D27,0xF900,0x0C5D,0x0FC7,0x0E23,0x0436,0x0000},0x800F},
99 {OPPO ,{0x0000,0x0000,0xCA4A,0x17F8,0x0FEC,0xCA4A,0x17F8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x800F},
100 {TREBLE,{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x188D,0x1699},0x8010},
101 {BASS ,{0x1A43,0x0C00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x8001},
102 {EQTEST,{0x1F8C,0x1830,0xC118,0x1EEF,0xFD77,0xD8CB,0x1BBC,0x0556,0x0689,0x0F33,0x0000,0xF17F,0x0FEC},0x8003},
105 static const u16 rt5621_reg[RT5621_VENDOR_ID2 + 1] = {
106 [RT5621_RESET] = 0x59b4,
107 [RT5621_SPK_OUT_VOL] = 0x8080,
108 [RT5621_HP_OUT_VOL] = 0x8080,
109 [RT5621_MONO_AUX_OUT_VOL] = 0x8080,
110 [RT5621_AUXIN_VOL] = 0xe808,
111 [RT5621_LINE_IN_VOL] = 0xe808,
112 [RT5621_STEREO_DAC_VOL] = 0xe808,
113 [RT5621_MIC_VOL] = 0x0808,
114 [RT5621_MIC_ROUTING_CTRL] = 0xe0e0,
115 [RT5621_ADC_REC_GAIN] = 0xf58b,
116 [RT5621_ADC_REC_MIXER] = 0x7f7f,
117 [RT5621_SOFT_VOL_CTRL_TIME] = 0x000a,
118 [RT5621_OUTPUT_MIXER_CTRL] = 0xc000,
119 [RT5621_AUDIO_INTERFACE] = 0x8000,
120 [RT5621_STEREO_AD_DA_CLK_CTRL] = 0x166d,
121 [RT5621_ADD_CTRL_REG] = 0x5300,
122 [RT5621_GPIO_PIN_CONFIG] = 0x1c0e,
123 [RT5621_GPIO_PIN_POLARITY] = 0x1c0e,
124 [RT5621_GPIO_PIN_STATUS] = 0x0002,
125 [RT5621_OVER_TEMP_CURR_STATUS] = 0x003c,
126 [RT5621_PSEDUEO_SPATIAL_CTRL] = 0x0497,
127 [RT5621_AVC_CTRL] = 0x000b,
128 [RT5621_VENDOR_ID1] = 0x10ec,
129 [RT5621_VENDOR_ID2] = 0x2003,
132 #define rt5621_write_mask(c, reg, value, mask) snd_soc_update_bits(c, reg, mask, value)
134 #define rt5621_write_index_reg(c, addr, data) \
136 snd_soc_write(c, 0x6a, addr); \
137 snd_soc_write(c, 0x6c, data); \
140 static int rt5621_reset(struct snd_soc_codec *codec)
142 return snd_soc_write(codec, RT5621_RESET, 0);
145 static int rt5621_volatile_register(
146 struct snd_soc_codec *codec, unsigned int reg)
150 case RT5621_HID_CTRL_DATA:
151 case RT5621_GPIO_PIN_STATUS:
152 case RT5621_OVER_TEMP_CURR_STATUS:
159 static int rt5621_readable_register(
160 struct snd_soc_codec *codec, unsigned int reg)
164 case RT5621_SPK_OUT_VOL:
165 case RT5621_HP_OUT_VOL:
166 case RT5621_MONO_AUX_OUT_VOL:
167 case RT5621_AUXIN_VOL:
168 case RT5621_LINE_IN_VOL:
169 case RT5621_STEREO_DAC_VOL:
171 case RT5621_MIC_ROUTING_CTRL:
172 case RT5621_ADC_REC_GAIN:
173 case RT5621_ADC_REC_MIXER:
174 case RT5621_SOFT_VOL_CTRL_TIME:
175 case RT5621_OUTPUT_MIXER_CTRL:
176 case RT5621_MIC_CTRL:
177 case RT5621_AUDIO_INTERFACE:
178 case RT5621_STEREO_AD_DA_CLK_CTRL:
179 case RT5621_COMPANDING_CTRL:
180 case RT5621_PWR_MANAG_ADD1:
181 case RT5621_PWR_MANAG_ADD2:
182 case RT5621_PWR_MANAG_ADD3:
183 case RT5621_ADD_CTRL_REG:
184 case RT5621_GLOBAL_CLK_CTRL_REG:
185 case RT5621_PLL_CTRL:
186 case RT5621_GPIO_OUTPUT_PIN_CTRL:
187 case RT5621_GPIO_PIN_CONFIG:
188 case RT5621_GPIO_PIN_POLARITY:
189 case RT5621_GPIO_PIN_STICKY:
190 case RT5621_GPIO_PIN_WAKEUP:
191 case RT5621_GPIO_PIN_STATUS:
192 case RT5621_GPIO_PIN_SHARING:
193 case RT5621_OVER_TEMP_CURR_STATUS:
194 case RT5621_JACK_DET_CTRL:
195 case RT5621_MISC_CTRL:
196 case RT5621_PSEDUEO_SPATIAL_CTRL:
198 case RT5621_EQ_MODE_ENABLE:
199 case RT5621_AVC_CTRL:
200 case RT5621_HID_CTRL_INDEX:
201 case RT5621_HID_CTRL_DATA:
202 case RT5621_VENDOR_ID1:
203 case RT5621_VENDOR_ID2:
211 //static const char *rt5621_spkl_pga[] = {"Vmid","HPL mixer","SPK mixer","Mono Mixer"};
212 static const char *rt5621_spkn_source_sel[] = {"RN", "RP", "LN"};
213 static const char *rt5621_spk_pga[] = {"Vmid","HP mixer","SPK mixer","Mono Mixer"};
214 static const char *rt5621_hpl_pga[] = {"Vmid","HPL mixer"};
215 static const char *rt5621_hpr_pga[] = {"Vmid","HPR mixer"};
216 static const char *rt5621_mono_pga[] = {"Vmid","HP mixer","SPK mixer","Mono Mixer"};
217 static const char *rt5621_amp_type_sel[] = {"Class AB","Class D"};
218 static const char *rt5621_mic_boost_sel[] = {"Bypass","20db","30db","40db"};
220 static const struct soc_enum rt5621_enum[] = {
221 SOC_ENUM_SINGLE(RT5621_OUTPUT_MIXER_CTRL, 14, 3, rt5621_spkn_source_sel), /* spkn source from hp mixer */
222 SOC_ENUM_SINGLE(RT5621_OUTPUT_MIXER_CTRL, 10, 4, rt5621_spk_pga), /* spk input sel 1 */
223 SOC_ENUM_SINGLE(RT5621_OUTPUT_MIXER_CTRL, 9, 2, rt5621_hpl_pga), /* hp left input sel 2 */
224 SOC_ENUM_SINGLE(RT5621_OUTPUT_MIXER_CTRL, 8, 2, rt5621_hpr_pga), /* hp right input sel 3 */
225 SOC_ENUM_SINGLE(RT5621_OUTPUT_MIXER_CTRL, 6, 4, rt5621_mono_pga), /* mono input sel 4 */
226 SOC_ENUM_SINGLE(RT5621_MIC_CTRL, 10,4, rt5621_mic_boost_sel), /*Mic1 boost sel 5 */
227 SOC_ENUM_SINGLE(RT5621_MIC_CTRL, 8,4,rt5621_mic_boost_sel), /*Mic2 boost sel 6 */
228 SOC_ENUM_SINGLE(RT5621_OUTPUT_MIXER_CTRL,13,2,rt5621_amp_type_sel), /*Speaker AMP sel 7 */
231 static int rt5621_amp_sel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
233 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
234 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
236 unsigned short mask, bitmask;
238 for (bitmask = 1; bitmask < e->max; bitmask <<= 1);
240 if (ucontrol->value.enumerated.item[0] > e->max - 1)
242 val = ucontrol->value.enumerated.item[0] << e->shift_l;
243 mask = (bitmask - 1) << e->shift_l;
244 if (e->shift_l != e->shift_r) {
245 if (ucontrol->value.enumerated.item[1] > e->max - 1)
247 val |= ucontrol->value.enumerated.item[1] << e->shift_r;
248 mask |= (bitmask - 1) << e->shift_r;
251 snd_soc_update_bits(codec, e->reg, mask, val);
256 snd_soc_update_bits(codec, 0x3c, 0x0000, 0x4000); /*power off classd*/
257 snd_soc_update_bits(codec, 0x3c, 0x8000, 0x8000); /*power on classab*/
259 snd_soc_update_bits(codec, 0x3c, 0x0000, 0x8000); /*power off classab*/
260 snd_soc_update_bits(codec, 0x3c, 0x4000, 0x4000); /*power on classd*/
266 //*****************************************************************************
268 //function:Change audio codec power status
270 //*****************************************************************************
271 static int rt5621_ChangeCodecPowerStatus(struct snd_soc_codec *codec,int power_state)
273 unsigned short int PowerDownState=0;
275 switch(power_state) {
276 case POWER_STATE_D0: //FULL ON-----power on all power
278 snd_soc_write(codec,RT5621_PWR_MANAG_ADD1,~PowerDownState);
279 snd_soc_write(codec,RT5621_PWR_MANAG_ADD2,~PowerDownState);
280 snd_soc_write(codec,RT5621_PWR_MANAG_ADD3,~PowerDownState);
282 case POWER_STATE_D1: //LOW ON-----
283 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD2 ,PWR_VREF |
284 PWR_DAC_REF_CIR | PWR_L_DAC_CLK | PWR_R_DAC_CLK |
285 PWR_L_HP_MIXER | PWR_R_HP_MIXER | PWR_L_ADC_CLK_GAIN |
286 PWR_R_ADC_CLK_GAIN | PWR_L_ADC_REC_MIXER | PWR_R_ADC_REC_MIXER |
287 PWR_CLASS_AB, PWR_VREF | PWR_DAC_REF_CIR | PWR_L_DAC_CLK |
288 PWR_R_DAC_CLK | PWR_L_HP_MIXER | PWR_R_HP_MIXER |
289 PWR_L_ADC_CLK_GAIN | PWR_R_ADC_CLK_GAIN |
290 PWR_L_ADC_REC_MIXER | PWR_R_ADC_REC_MIXER | PWR_CLASS_AB);
292 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD3 ,PWR_MAIN_BIAS |
293 PWR_HP_R_OUT_VOL | PWR_HP_L_OUT_VOL | PWR_SPK_OUT |
294 PWR_MIC1_FUN_CTRL | PWR_MIC1_BOOST_MIXER, PWR_MAIN_BIAS |
295 PWR_HP_R_OUT_VOL | PWR_HP_L_OUT_VOL | PWR_SPK_OUT |
296 PWR_MIC1_FUN_CTRL | PWR_MIC1_BOOST_MIXER);
298 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD1 ,PWR_MAIN_I2S_EN |
299 PWR_HP_OUT_ENH_AMP | PWR_HP_OUT_AMP | PWR_MIC1_BIAS_EN,
300 PWR_MAIN_I2S_EN | PWR_HP_OUT_ENH_AMP | PWR_HP_OUT_AMP |
304 case POWER_STATE_D1_PLAYBACK: //Low on of Playback
305 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD2, PWR_VREF | PWR_DAC_REF_CIR |
306 PWR_L_DAC_CLK | PWR_R_DAC_CLK | PWR_L_HP_MIXER | PWR_R_HP_MIXER |
307 PWR_CLASS_AB | PWR_CLASS_D|PWR_SPK_MIXER, PWR_VREF | PWR_DAC_REF_CIR |
308 PWR_L_DAC_CLK | PWR_R_DAC_CLK | PWR_L_HP_MIXER | PWR_R_HP_MIXER |
309 PWR_CLASS_AB | PWR_CLASS_D|PWR_SPK_MIXER);
311 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD3, PWR_MAIN_BIAS |
312 PWR_HP_R_OUT_VOL | PWR_HP_L_OUT_VOL | PWR_SPK_OUT,
313 PWR_MAIN_BIAS | PWR_HP_R_OUT_VOL | PWR_HP_L_OUT_VOL | PWR_SPK_OUT);
315 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD1, PWR_MAIN_I2S_EN |
316 PWR_HP_OUT_ENH_AMP | PWR_HP_OUT_AMP, PWR_MAIN_I2S_EN |
317 PWR_HP_OUT_ENH_AMP | PWR_HP_OUT_AMP);
320 case POWER_STATE_D1_RECORD: //Low on of Record
321 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD1, PWR_MAIN_I2S_EN |
322 PWR_MIC1_BIAS_EN, PWR_MAIN_I2S_EN | PWR_MIC1_BIAS_EN);
323 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD2, PWR_VREF |
324 PWR_L_ADC_CLK_GAIN | PWR_R_ADC_CLK_GAIN | PWR_L_ADC_REC_MIXER |
325 PWR_R_ADC_REC_MIXER, PWR_VREF | PWR_L_ADC_CLK_GAIN |
326 PWR_R_ADC_CLK_GAIN | PWR_L_ADC_REC_MIXER | PWR_R_ADC_REC_MIXER);
327 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD3, PWR_MAIN_BIAS |
328 PWR_MIC2_BOOST_MIXER | PWR_MIC1_BOOST_MIXER, PWR_MAIN_BIAS |
329 PWR_MIC2_BOOST_MIXER | PWR_MIC1_BOOST_MIXER);
332 case POWER_STATE_D2: //STANDBY----
333 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD1, 0, PWR_MAIN_I2S_EN |
334 PWR_HP_OUT_ENH_AMP | PWR_HP_OUT_AMP | PWR_MIC1_BIAS_EN);
335 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD3, 0, PWR_HP_R_OUT_VOL |
336 PWR_HP_L_OUT_VOL | PWR_SPK_OUT | PWR_MIC1_FUN_CTRL |
337 PWR_MIC1_BOOST_MIXER);
338 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD2, 0, PWR_DAC_REF_CIR |
339 PWR_L_DAC_CLK | PWR_R_DAC_CLK | PWR_L_HP_MIXER | PWR_R_HP_MIXER|
340 PWR_L_ADC_CLK_GAIN | PWR_R_ADC_CLK_GAIN | PWR_L_ADC_REC_MIXER |
341 PWR_R_ADC_REC_MIXER | PWR_CLASS_AB | PWR_CLASS_D);
344 case POWER_STATE_D2_PLAYBACK: //STANDBY of playback
345 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD3, 0, /*PWR_HP_R_OUT_VOL |
346 PWR_HP_L_OUT_VOL |*/ PWR_SPK_OUT);
347 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD1, 0, PWR_HP_OUT_ENH_AMP |
349 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD2, 0, PWR_DAC_REF_CIR |
350 PWR_L_DAC_CLK | PWR_R_DAC_CLK | PWR_L_HP_MIXER | PWR_R_HP_MIXER |
351 PWR_CLASS_AB | PWR_CLASS_D);
354 case POWER_STATE_D2_RECORD: //STANDBY of record
355 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD1, 0, PWR_MIC1_BIAS_EN);
356 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD2, 0, PWR_L_ADC_CLK_GAIN |
357 PWR_R_ADC_CLK_GAIN | PWR_L_ADC_REC_MIXER | PWR_R_ADC_REC_MIXER);
358 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD3, 0, PWR_MIC2_BOOST_MIXER |
359 PWR_MIC1_BOOST_MIXER);
362 case POWER_STATE_D3: //SLEEP
363 case POWER_STATE_D4: //OFF----power off all power
364 rt5621_write_mask(codec, RT5621_PWR_MANAG_ADD1, 0, PWR_HP_OUT_ENH_AMP |
366 snd_soc_write(codec, RT5621_PWR_MANAG_ADD3, 0);
367 snd_soc_write(codec, RT5621_PWR_MANAG_ADD1, 0);
368 snd_soc_write(codec, RT5621_PWR_MANAG_ADD2, 0);
379 //*****************************************************************************
381 //function AudioOutEnable:Mute/Unmute audio out channel
382 //WavOutPath:output channel
383 //Mute :Mute/Unmute output channel
385 //*****************************************************************************
386 static int rt5621_AudioOutEnable(struct snd_soc_codec *codec,
387 unsigned short int WavOutPath, int Mute)
393 case RT_WAVOUT_ALL_ON:
394 RetVal = rt5621_write_mask(codec, RT5621_SPK_OUT_VOL, RT_L_MUTE | RT_R_MUTE,
395 RT_L_MUTE | RT_R_MUTE); //Mute Speaker right/left channel
396 RetVal = rt5621_write_mask(codec, RT5621_HP_OUT_VOL, RT_L_MUTE | RT_R_MUTE,
397 RT_L_MUTE | RT_R_MUTE); //Mute headphone right/left channel
398 RetVal = rt5621_write_mask(codec, RT5621_MONO_AUX_OUT_VOL, RT_L_MUTE |
399 RT_R_MUTE, RT_L_MUTE | RT_R_MUTE); //Mute Aux/Mono right/left channel
400 RetVal = rt5621_write_mask(codec, RT5621_STEREO_DAC_VOL, RT_M_HP_MIXER |
401 RT_M_SPK_MIXER | RT_M_MONO_MIXER, RT_M_HP_MIXER |
402 RT_M_SPK_MIXER | RT_M_MONO_MIXER); //Mute DAC to HP,Speaker,Mono Mixer
406 RetVal = rt5621_write_mask(codec, RT5621_HP_OUT_VOL, RT_L_MUTE | RT_R_MUTE,
407 RT_L_MUTE | RT_R_MUTE); //Mute headphone right/left channel
411 RetVal = rt5621_write_mask(codec, RT5621_SPK_OUT_VOL, RT_L_MUTE | RT_R_MUTE,
412 RT_L_MUTE | RT_R_MUTE); //Mute Speaker right/left channel
415 case RT_WAVOUT_AUXOUT:
416 RetVal = rt5621_write_mask(codec, RT5621_MONO_AUX_OUT_VOL, RT_L_MUTE |
417 RT_R_MUTE, RT_L_MUTE | RT_R_MUTE); //Mute AuxOut right/left channel
422 RetVal = rt5621_write_mask(codec, RT5621_MONO_AUX_OUT_VOL, RT_L_MUTE,
423 RT_L_MUTE); //Mute MonoOut channel
427 RetVal = rt5621_write_mask(codec, RT5621_STEREO_DAC_VOL, RT_M_HP_MIXER |
428 RT_M_SPK_MIXER | RT_M_MONO_MIXER, RT_M_HP_MIXER | RT_M_SPK_MIXER |
429 RT_M_MONO_MIXER); //Mute DAC to HP,Speaker,Mono Mixer
437 case RT_WAVOUT_ALL_ON:
438 RetVal = rt5621_write_mask(codec, RT5621_SPK_OUT_VOL, 0, RT_L_MUTE |
439 RT_R_MUTE); //Mute Speaker right/left channel
440 RetVal = rt5621_write_mask(codec, RT5621_HP_OUT_VOL, 0, RT_L_MUTE |
441 RT_R_MUTE); //Mute headphone right/left channel
442 RetVal = rt5621_write_mask(codec, RT5621_MONO_AUX_OUT_VOL, 0, RT_L_MUTE |
443 RT_R_MUTE); //Mute Aux/Mono right/left channel
444 RetVal = rt5621_write_mask(codec, RT5621_STEREO_DAC_VOL, 0, RT_M_HP_MIXER |
445 RT_M_SPK_MIXER | RT_M_MONO_MIXER); //Mute DAC to HP,Speaker,Mono Mixer
448 RetVal = rt5621_write_mask(codec, RT5621_HP_OUT_VOL, 0, RT_L_MUTE |
449 RT_R_MUTE); //UnMute headphone right/left channel
453 RetVal = rt5621_write_mask(codec, RT5621_SPK_OUT_VOL, 0, RT_L_MUTE |
454 RT_R_MUTE); //unMute Speaker right/left channel
456 case RT_WAVOUT_AUXOUT:
457 RetVal = rt5621_write_mask(codec, RT5621_MONO_AUX_OUT_VOL, 0, RT_L_MUTE |
458 RT_R_MUTE); //unMute AuxOut right/left channel
462 RetVal = rt5621_write_mask(codec, RT5621_MONO_AUX_OUT_VOL, 0,
463 RT_L_MUTE); //unMute MonoOut channel
467 RetVal = rt5621_write_mask(codec, RT5621_STEREO_DAC_VOL, 0, RT_M_HP_MIXER |
468 RT_M_SPK_MIXER | RT_M_MONO_MIXER); //unMute DAC to HP,Speaker,Mono Mixer
480 //*****************************************************************************
482 //function:Enable/Disable ADC input source control
484 //*****************************************************************************
485 static int Enable_ADC_Input_Source(struct snd_soc_codec *codec,unsigned short int ADC_Input_Sour,int Enable)
491 bRetVal=rt5621_write_mask(codec,RT5621_ADC_REC_MIXER,0,ADC_Input_Sour);
494 bRetVal=rt5621_write_mask(codec,RT5621_ADC_REC_MIXER,ADC_Input_Sour,ADC_Input_Sour);
500 static void rt5621_update_eqmode(struct snd_soc_codec *codec, int mode)
504 if (mode == NORMAL) {
505 /*clear EQ parameter*/
506 for (HwEqIndex=0; HwEqIndex<=0x0C; HwEqIndex++) {
508 rt5621_write_index_reg(codec, HwEqIndex, HwEq_Preset[mode].EqValue[HwEqIndex])
511 snd_soc_write(codec, 0x62, 0x0); /*disable EQ block*/
513 snd_soc_write(codec, 0x62, HwEq_Preset[mode].HwEQCtrl);
515 /*Fill EQ parameter*/
516 for (HwEqIndex=0; HwEqIndex<=0x0C; HwEqIndex++) {
518 rt5621_write_index_reg(codec, HwEqIndex, HwEq_Preset[mode].EqValue[HwEqIndex])
520 //update EQ parameter
521 snd_soc_write(codec, 0x66, 0x1f);
522 schedule_timeout_uninterruptible(msecs_to_jiffies(1));
523 snd_soc_write(codec, 0x66, 0x0);
527 static const struct snd_kcontrol_new rt5621_snd_controls[] = {
528 SOC_DOUBLE("Speaker Playback Volume", RT5621_SPK_OUT_VOL, 8, 0, 31, 1),
529 SOC_DOUBLE("Speaker Playback Switch", RT5621_SPK_OUT_VOL, 15, 7, 1, 1),
530 SOC_DOUBLE("Headphone Playback Volume", RT5621_HP_OUT_VOL, 8, 0, 31, 1),
531 SOC_DOUBLE("Headphone Playback Switch", RT5621_HP_OUT_VOL,15, 7, 1, 1),
532 SOC_DOUBLE("AUX Playback Volume", RT5621_MONO_AUX_OUT_VOL, 8, 0, 31, 1),
533 SOC_DOUBLE("AUX Playback Switch", RT5621_MONO_AUX_OUT_VOL, 15, 7, 1, 1),
534 SOC_DOUBLE("PCM Playback Volume", RT5621_STEREO_DAC_VOL, 8, 0, 31, 1),
535 SOC_DOUBLE("Line In Volume", RT5621_LINE_IN_VOL, 8, 0, 31, 1),
536 SOC_SINGLE("Mic 1 Volume", RT5621_MIC_VOL, 8, 31, 1),
537 SOC_SINGLE("Mic 2 Volume", RT5621_MIC_VOL, 0, 31, 1),
538 SOC_ENUM("Mic 1 Boost", rt5621_enum[5]),
539 SOC_ENUM("Mic 2 Boost", rt5621_enum[6]),
540 SOC_ENUM_EXT("Speaker Amp Type", rt5621_enum[7], snd_soc_get_enum_double, rt5621_amp_sel_put),
541 SOC_DOUBLE("AUX In Volume", RT5621_AUXIN_VOL, 8, 0, 31, 1),
542 SOC_DOUBLE("Capture Volume", RT5621_ADC_REC_GAIN, 7, 0, 31, 0),
545 void hp_depop_mode2(struct snd_soc_codec *codec)
547 snd_soc_update_bits(codec, 0x3e, 0x8000, 0x8000);
548 snd_soc_update_bits(codec, 0x04, 0x8080, 0x8080);
549 snd_soc_update_bits(codec, 0x3a, 0x0100, 0x0100);
550 snd_soc_update_bits(codec, 0x3c, 0x2000, 0x2000);
551 snd_soc_update_bits(codec, 0x3e, 0x0600, 0x0600);
552 snd_soc_update_bits(codec, 0x5e, 0x0200, 0x0200);
553 schedule_timeout_uninterruptible(msecs_to_jiffies(300));
556 void aux_depop_mode2(struct snd_soc_codec *codec)
558 snd_soc_update_bits(codec, 0x3e, 0x8000, 0x8000);
559 snd_soc_update_bits(codec, 0x06, 0x8080, 0x8080);
560 snd_soc_update_bits(codec, 0x3a, 0x0100, 0x0100);
561 snd_soc_update_bits(codec, 0x3c, 0x2000, 0x2000);
562 snd_soc_update_bits(codec, 0x3e, 0x6000, 0x6000);
563 snd_soc_update_bits(codec, 0x5e, 0x0020, 0x0200);
564 schedule_timeout_uninterruptible(msecs_to_jiffies(300));
565 snd_soc_update_bits(codec, 0x3a, 0x0002, 0x0002);
566 snd_soc_update_bits(codec, 0x3a, 0x0001, 0x0001);
569 static int rt5621_pcm_hw_prepare(struct snd_pcm_substream *substream,
570 struct snd_soc_dai *codec_dai)
573 struct snd_soc_codec *codec = codec_dai->codec;
574 int stream = substream->stream;
578 case SNDRV_PCM_STREAM_PLAYBACK:
580 rt5621_ChangeCodecPowerStatus(codec,POWER_STATE_D1_PLAYBACK); //power on dac to hp and speaker out
582 rt5621_AudioOutEnable(codec,RT_WAVOUT_SPK,0); //unmute speaker out
584 rt5621_AudioOutEnable(codec,RT_WAVOUT_HP,0); //unmute hp
586 rt5621_AudioOutEnable(codec,RT_WAVOUT_AUXOUT,0); //unmute auxout out
589 case SNDRV_PCM_STREAM_CAPTURE:
591 rt5621_ChangeCodecPowerStatus(codec,POWER_STATE_D1_RECORD); //power on input to adc
593 Enable_ADC_Input_Source(codec,RT_WAVIN_L_MIC1|RT_WAVIN_R_MIC1,1); //enable record source from mic1
608 static const struct _pll_div codec_pll_div[] = {
610 { 2048000, 8192000, 0x0ea0},
611 { 3686400, 8192000, 0x4e27},
612 { 12000000, 8192000, 0x456b},
613 { 13000000, 8192000, 0x495f},
614 { 13100000, 8192000, 0x0320},
615 { 2048000, 11289600, 0xf637},
616 { 3686400, 11289600, 0x2f22},
617 { 12000000, 11289600, 0x3e2f},
618 { 13000000, 11289600, 0x4d5b},
619 { 13100000, 11289600, 0x363b},
620 { 2048000, 16384000, 0x1ea0},
621 { 3686400, 16384000, 0x9e27},
622 { 12000000, 16384000, 0x452b},
623 { 13000000, 16384000, 0x542f},
624 { 13100000, 16384000, 0x03a0},
625 { 2048000, 16934400, 0xe625},
626 { 3686400, 16934400, 0x9126},
627 { 12000000, 16934400, 0x4d2c},
628 { 13000000, 16934400, 0x742f},
629 { 13100000, 16934400, 0x3c27},
630 { 2048000, 22579200, 0x2aa0},
631 { 3686400, 22579200, 0x2f20},
632 { 12000000, 22579200, 0x7e2f},
633 { 13000000, 22579200, 0x742f},
634 { 13100000, 22579200, 0x3c27},
635 { 2048000, 24576000, 0x2ea0},
636 { 3686400, 24576000, 0xee27},
637 { 12000000, 24576000, 0x2915},
638 { 13000000, 24576000, 0x772e},
639 { 13100000, 24576000, 0x0d20},
642 static const struct _pll_div codec_bclk_pll_div[] = {
644 { 1536000, 24576000, 0x3ea0},
645 { 3072000, 24576000, 0x1ea0},
646 { 512000, 24576000, 0x8e90},
647 { 256000, 24576000, 0xbe80},
648 { 2822400, 11289600, 0x1ee0},
649 { 3072000, 12288000, 0x1ee0},
653 static int rt5621_set_dai_pll(struct snd_soc_dai *dai,
654 int pll_id,int source, unsigned int freq_in, unsigned int freq_out)
658 struct snd_soc_codec *codec = dai->codec;
660 if (pll_id < RT5621_PLL_FR_MCLK || pll_id > RT5621_PLL_FR_BCLK)
663 //rt5621_write_mask(codec,RT5621_PWR_MANAG_ADD2, 0x0000,0x1000); //disable PLL power
665 if (!freq_in || !freq_out) {
670 if (RT5621_PLL_FR_MCLK == pll_id) {
671 for (i = 0; i < ARRAY_SIZE(codec_pll_div); i++) {
673 if (codec_pll_div[i].pll_in == freq_in && codec_pll_div[i].pll_out == freq_out)
675 snd_soc_update_bits(codec, RT5621_GLOBAL_CLK_CTRL_REG, 0x0000, 0x4000);
676 snd_soc_write(codec,RT5621_PLL_CTRL,codec_pll_div[i].regvalue);//set PLL parameter
677 snd_soc_update_bits(codec,RT5621_PWR_MANAG_ADD2, 0x1000,0x1000); //enable PLL power
682 else if (RT5621_PLL_FR_BCLK == pll_id)
684 for (i = 0; i < ARRAY_SIZE(codec_bclk_pll_div); i++)
686 if ((freq_in == codec_bclk_pll_div[i].pll_in) && (freq_out == codec_bclk_pll_div[i].pll_out))
688 snd_soc_update_bits(codec, RT5621_GLOBAL_CLK_CTRL_REG, 0x4000, 0x4000);
689 snd_soc_write(codec,RT5621_PLL_CTRL,codec_bclk_pll_div[i].regvalue);//set PLL parameter
690 snd_soc_update_bits(codec,RT5621_PWR_MANAG_ADD2, 0x1000,0x1000); //enable PLL power
696 snd_soc_update_bits(codec,RT5621_GLOBAL_CLK_CTRL_REG,0x8000,0x8000);//Codec sys-clock from PLL
708 /* codec hifi mclk (after PLL) clock divider coefficients */
709 static const struct _coeff_div coeff_div[] = {
711 { 8192000, 8000, 256*4, 0x2a2d},
712 {12288000, 8000, 384*4, 0x2c2f},
715 {11289600, 11025, 256*4, 0x2a2d},
716 {16934400, 11025, 384*4, 0x2c2f},
719 {12288000, 16000, 384*2, 0x1c2f},
720 {16384000, 16000, 256*4, 0x2a2d},
721 {24576000, 16000, 384*4, 0x2c2f},
724 {11289600, 22050, 256*2, 0x1a2d},
725 {16934400, 22050, 384*2, 0x1c2f},
728 {12288000, 32000, 384 , 0x0c2f},
729 {16384000, 32000, 256*2, 0x1a2d},
730 {24576000, 32000, 384*2, 0x1c2f},
733 {11289600, 44100, 256*1, 0x0a2d},
734 {22579200, 44100, 256*2, 0x1a2d},
735 {45158400, 44100, 256*4, 0x2a2d},
738 {12288000, 48000, 256*1, 0x0a2d},
739 {24576000, 48000, 256*2, 0x1a2d},
740 {49152000, 48000, 256*4, 0x2a2d},
742 //MCLK is 24.576Mhz(for 8k,16k,32k)
743 {24576000, 8000, 384*8, 0x3c6b},
744 {24576000, 16000, 384*4, 0x2c6b},
745 {24576000, 32000, 384*2, 0x1c6b},
747 //MCLK is 22.5792mHz(for 11k,22k)
748 {22579200, 11025, 256*8, 0x3a2d},
749 {22579200, 22050, 256*4, 0x2a2d},
754 static int get_coeff(int mclk, int rate)
758 DBG("get_coeff mclk=%d,rate=%d\n",mclk,rate);
760 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
761 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
769 * Clock after PLL and dividers
771 /*in this driver, you have to set sysclk to be 24576000,
772 * but you don't need to give a clk to be 24576000, our
773 * internal pll will generate this clock! so it won't make
776 static int rt5621_set_dai_sysclk(struct snd_soc_dai *dai,
777 int clk_id, unsigned int freq, int dir)
779 struct snd_soc_codec *codec = dai->codec;
780 struct rt5621_priv *rt5621 = snd_soc_codec_get_drvdata(codec);
782 if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
783 rt5621->sysclk = freq;
787 printk("unsupported sysclk freq %u for audio i2s\n", freq);
793 static int rt5621_set_dai_fmt(struct snd_soc_dai *dai,
796 struct snd_soc_codec *codec = dai->codec;
799 /* set master/slave audio interface */
800 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
801 case SND_SOC_DAIFMT_CBM_CFM:
804 case SND_SOC_DAIFMT_CBS_CFS:
811 /* interface format */
812 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
813 case SND_SOC_DAIFMT_I2S:
816 case SND_SOC_DAIFMT_RIGHT_J:
819 case SND_SOC_DAIFMT_LEFT_J:
822 case SND_SOC_DAIFMT_DSP_A:
825 case SND_SOC_DAIFMT_DSP_B:
832 /* clock inversion */
833 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
834 case SND_SOC_DAIFMT_NB_NF:
837 case SND_SOC_DAIFMT_IB_NF:
844 snd_soc_write(codec,RT5621_AUDIO_INTERFACE,iface);
849 static int rt5621_pcm_hw_params(struct snd_pcm_substream *substream,
850 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
852 struct snd_soc_codec *codec = dai->codec;
853 struct rt5621_priv *rt5621 = snd_soc_codec_get_drvdata(codec);
854 u16 iface = snd_soc_read(codec,RT5621_AUDIO_INTERFACE)&0xfff3;
855 int coeff = get_coeff(rt5621->sysclk, params_rate(params));
857 DBG("rt5621_pcm_hw_params\n");
859 coeff = get_coeff(24576000, params_rate(params)); /*if not set sysclk, default to be 24.576MHz*/
862 switch (params_format(params)) {
863 case SNDRV_PCM_FORMAT_S16_LE:
866 case SNDRV_PCM_FORMAT_S20_3LE:
869 case SNDRV_PCM_FORMAT_S24_LE:
872 case SNDRV_PCM_FORMAT_S32_LE:
877 /* set iface & srate */
878 snd_soc_write(codec, RT5621_AUDIO_INTERFACE, iface);
881 snd_soc_write(codec, RT5621_STEREO_AD_DA_CLK_CTRL, coeff_div[coeff].regvalue);
884 printk(KERN_ERR "cant find matched sysclk and rate config\n");
891 static int rt5621_set_bias_level(struct snd_soc_codec *codec,
892 enum snd_soc_bias_level level)
895 case SND_SOC_BIAS_ON:
896 snd_soc_update_bits(codec, RT5621_SPK_OUT_VOL, RT_L_MUTE | RT_R_MUTE, 0);
897 snd_soc_update_bits(codec, RT5621_HP_OUT_VOL, RT_L_MUTE | RT_R_MUTE, 0);
900 case SND_SOC_BIAS_PREPARE:
903 case SND_SOC_BIAS_STANDBY:
904 snd_soc_update_bits(codec, RT5621_SPK_OUT_VOL, RT_L_MUTE | RT_R_MUTE, RT_L_MUTE | RT_R_MUTE);
905 snd_soc_update_bits(codec, RT5621_HP_OUT_VOL, RT_L_MUTE | RT_R_MUTE, RT_L_MUTE | RT_R_MUTE);
906 if (SND_SOC_BIAS_OFF == codec->dapm.bias_level) {
907 snd_soc_write(codec, RT5621_PWR_MANAG_ADD3, 0x8000);//enable Main bias
908 snd_soc_write(codec, RT5621_PWR_MANAG_ADD2, 0x2000);//enable Vref
909 codec->cache_only = false;
910 snd_soc_cache_sync(codec);
914 case SND_SOC_BIAS_OFF:
915 snd_soc_update_bits(codec, RT5621_SPK_OUT_VOL, RT_L_MUTE | RT_R_MUTE, RT_L_MUTE | RT_R_MUTE);
916 snd_soc_update_bits(codec, RT5621_HP_OUT_VOL, RT_L_MUTE | RT_R_MUTE, RT_L_MUTE | RT_R_MUTE);
917 snd_soc_write(codec, RT5621_PWR_MANAG_ADD3, 0x0000);
918 snd_soc_write(codec, RT5621_PWR_MANAG_ADD2, 0x0000);
919 snd_soc_write(codec, RT5621_PWR_MANAG_ADD1, 0x0000);
925 codec->dapm.bias_level = level;
932 struct rt5621_init_reg{
938 static struct rt5621_init_reg init_data[] = {
939 {RT5621_AUDIO_INTERFACE, 0x8000}, //set I2S codec to slave mode
940 {RT5621_STEREO_DAC_VOL, 0x0808}, //default stereo DAC volume to 0db
941 {RT5621_OUTPUT_MIXER_CTRL, 0x2b40}, //default output mixer control
942 {RT5621_ADC_REC_MIXER, 0x3f3f}, //set record source is Mic1 by default
943 {RT5621_MIC_CTRL, 0x0a00}, //set Mic1,Mic2 boost 20db
944 {RT5621_SPK_OUT_VOL, 0x8080}, //default speaker volume to 0db
945 {RT5621_HP_OUT_VOL, 0x8080}, //default HP volume to -12db
946 {RT5621_ADD_CTRL_REG, 0x4b00}, //Class AB/D speaker ratio is 1.25VDD
947 {RT5621_STEREO_AD_DA_CLK_CTRL, 0x066d}, //set Dac filter to 256fs
948 {RT5621_ADC_REC_GAIN, 0xfa95}, //set ADC boost to 15db
949 {RT5621_HID_CTRL_INDEX, 0x46}, //Class D setting
950 {RT5621_MIC_VOL, 0x0808},
951 {RT5621_MIC_ROUTING_CTRL, 0xf0e0},
952 {RT5621_HID_CTRL_DATA, 0xFFFF}, //power on Class D Internal register
953 {RT5621_JACK_DET_CTRL, 0x4810}, //power on Class D Internal register
955 #define RT5621_INIT_REG_NUM ARRAY_SIZE(init_data)
957 static int rt5621_reg_init(struct snd_soc_codec *codec)
961 for (i = 0; i < RT5621_INIT_REG_NUM; i++)
962 snd_soc_write(codec, init_data[i].reg_index, init_data[i].reg_value);
967 static void rt5621_work(struct work_struct *work)
969 struct snd_soc_codec *codec = rt5621_codec;
971 rt5621_set_bias_level(codec, codec->dapm.bias_level);
974 static int rt5621_probe(struct snd_soc_codec *codec)
978 printk("##################### %s ######################\n", __FUNCTION__);
980 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
982 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
985 codec->cache_bypass = 1;
988 snd_soc_write(codec, RT5621_PWR_MANAG_ADD3, 0x8000);//enable Main bias
989 snd_soc_write(codec, RT5621_PWR_MANAG_ADD2, 0x2000);//enable Vref
990 hp_depop_mode2(codec);
991 rt5621_reg_init(codec);
995 rt5621_write_index_reg(codec, 0x11,0x1);
996 rt5621_write_index_reg(codec, 0x12,0x1);
997 rt5621_update_eqmode(codec, HFREQ);
1000 rt5621_workq = create_freezable_workqueue("rt5621");
1001 if (rt5621_workq == NULL) {
1002 printk("wm8900_probe::create_freezeable_workqueue ERROR !");
1007 rt5621_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
1008 codec->dapm.bias_level = SND_SOC_BIAS_STANDBY;
1010 queue_delayed_work(rt5621_workq, &delayed_work,
1011 msecs_to_jiffies(caps_charge));
1013 codec->dapm.bias_level = SND_SOC_BIAS_STANDBY;
1015 rt5621_codec = codec;
1020 static int rt5621_remove(struct snd_soc_codec *codec)
1022 rt5621_set_bias_level(codec, SND_SOC_BIAS_OFF);
1024 cancel_delayed_work_sync(&delayed_work);
1029 static int rt5621_suspend(struct snd_soc_codec *codec)
1031 rt5621_set_bias_level(codec, SND_SOC_BIAS_OFF);
1035 static int rt5621_resume(struct snd_soc_codec *codec)
1038 rt5621_reset(codec);
1039 snd_soc_write(codec, RT5621_PWR_MANAG_ADD3, 0x8000);//enable Main bias
1040 snd_soc_write(codec, RT5621_PWR_MANAG_ADD2, 0x2000);//enable Vref
1042 hp_depop_mode2(codec);
1044 rt5621_reg_init(codec);
1048 rt5621_write_index_reg(codec, 0x11,0x1);
1049 rt5621_write_index_reg(codec, 0x12,0x1);
1050 rt5621_update_eqmode(codec, HFREQ);
1053 rt5621_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1054 if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) {
1055 rt5621_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
1056 codec->dapm.bias_level = SND_SOC_BIAS_ON;
1057 queue_delayed_work(rt5621_workq, &delayed_work,
1058 msecs_to_jiffies(caps_charge));
1063 #define rt5621_suspend NULL
1064 #define rt5621_resume NULL
1067 static void rt5621_shutdown(struct snd_pcm_substream *substream,
1068 struct snd_soc_dai *codec_dai)
1070 struct snd_soc_codec *codec = codec_dai->codec;
1071 int stream = substream->stream;
1075 case SNDRV_PCM_STREAM_PLAYBACK:
1077 rt5621_AudioOutEnable(codec,RT_WAVOUT_SPK,1); //mute speaker out
1079 rt5621_AudioOutEnable(codec,RT_WAVOUT_HP,1); //mute hp out
1081 rt5621_AudioOutEnable(codec,RT_WAVOUT_AUXOUT,1); //mute auxout
1083 rt5621_ChangeCodecPowerStatus(codec,POWER_STATE_D2_PLAYBACK); //power off dac to hp and speaker out and auxout
1088 case SNDRV_PCM_STREAM_CAPTURE:
1090 Enable_ADC_Input_Source(codec,RT_WAVIN_L_MIC1|RT_WAVIN_R_MIC1,0); //disable record source from mic1
1092 rt5621_ChangeCodecPowerStatus(codec,POWER_STATE_D2_RECORD);
1099 //#define RT5621_HIFI_RATES SNDRV_PCM_RATE_8000_48000
1100 #define RT5621_HIFI_RATES (SNDRV_PCM_RATE_44100) // zyy 20110704, playback and record use same sample rate
1102 #define RT5621_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
1103 SNDRV_PCM_FMTBIT_S24_LE)
1105 struct snd_soc_dai_ops rt5621_hifi_ops = {
1106 .hw_params = rt5621_pcm_hw_params,
1107 .set_fmt = rt5621_set_dai_fmt,
1108 .set_sysclk = rt5621_set_dai_sysclk,
1109 .set_pll = rt5621_set_dai_pll,
1110 .prepare = rt5621_pcm_hw_prepare,
1111 .shutdown = rt5621_shutdown,
1114 struct snd_soc_dai_driver rt5621_dai = {
1115 .name = "RT5621 HiFi",
1117 .stream_name = "HiFi Playback",
1120 .rates = RT5621_HIFI_RATES,
1121 .formats = RT5621_FORMATS,
1124 .stream_name = "HiFi Capture",
1127 .rates = RT5621_HIFI_RATES,
1128 .formats = RT5621_FORMATS,
1130 .ops = &rt5621_hifi_ops,
1133 static struct snd_soc_codec_driver soc_codec_dev_rt5621 = {
1134 .probe = rt5621_probe,
1135 .remove = rt5621_remove,
1136 .suspend = rt5621_suspend,
1137 .resume = rt5621_resume,
1138 .set_bias_level = rt5621_set_bias_level,
1139 .reg_cache_size = RT5621_VENDOR_ID2 + 1,
1140 .reg_word_size = sizeof(u16),
1141 .reg_cache_default = rt5621_reg,
1142 .volatile_register = rt5621_volatile_register,
1143 .readable_register = rt5621_readable_register,
1144 .reg_cache_step = 1,
1145 .controls = rt5621_snd_controls,
1146 .num_controls = ARRAY_SIZE(rt5621_snd_controls),
1149 static const struct i2c_device_id rt5621_i2c_id[] = {
1153 MODULE_DEVICE_TABLE(i2c, rt5621_i2c_id);
1158 compatible = "rt5621";
1160 spk-ctl-gpio = <&gpio6 GPIO_B6 GPIO_ACTIVE_HIGH>;
1163 static int rt5621_i2c_probe(struct i2c_client *i2c,
1164 const struct i2c_device_id *id)
1166 struct rt5621_priv *rt5621;
1169 printk("##################### %s ######################\n", __FUNCTION__);
1172 rt5621_spk_ctl_gpio= of_get_named_gpio_flags(i2c->dev.of_node, "spk-ctl-gpio", 0, NULL);
1173 if (rt5621_spk_ctl_gpio < 0) {
1174 DBG("%s() Can not read property spk-ctl-gpio\n", __FUNCTION__);
1175 rt5621_spk_ctl_gpio = INVALID_GPIO;
1177 #endif //#ifdef CONFIG_OF
1179 ret = gpio_request(rt5621_spk_ctl_gpio, "spk_con");
1181 printk("gpio request spk_con error!\n");
1184 printk("########################### set spk_con HIGH ##################################\n");
1185 gpio_direction_output(rt5621_spk_ctl_gpio, GPIO_HIGH);
1186 gpio_set_value(rt5621_spk_ctl_gpio, GPIO_HIGH);
1189 rt5621 = kzalloc(sizeof(struct rt5621_priv), GFP_KERNEL);
1193 i2c_set_clientdata(i2c, rt5621);
1195 ret = snd_soc_register_codec(&i2c->dev,
1196 &soc_codec_dev_rt5621, &rt5621_dai, 1);
1203 static int rt5621_i2c_remove(struct i2c_client *i2c)
1205 snd_soc_unregister_codec(&i2c->dev);
1206 kfree(i2c_get_clientdata(i2c));
1210 struct i2c_driver rt5621_i2c_driver = {
1213 .owner = THIS_MODULE,
1215 .probe = rt5621_i2c_probe,
1216 .remove = rt5621_i2c_remove,
1217 .id_table = rt5621_i2c_id,
1220 static int __init rt5621_modinit(void)
1222 return i2c_add_driver(&rt5621_i2c_driver);
1224 module_init(rt5621_modinit);
1226 static void __exit rt5621_modexit(void)
1228 i2c_del_driver(&rt5621_i2c_driver);
1230 module_exit(rt5621_modexit);
1232 MODULE_DESCRIPTION("ASoC RT5621 driver");
1233 MODULE_AUTHOR("Johnny Hsu <johnnyhsu@realtek.com>");
1234 MODULE_LICENSE("GPL");