UPSTREAM: ASoC: da7219: Remove support for 32KHz PLL mode
[firefly-linux-kernel-4.4.55.git] / sound / soc / codecs / rt5625.c.enc
1 /*\r
2 RK1 SPKOUT Mux\r
3 RK11 HP Mixer\r
4 RK12 SPK Mixer\r
5 RK13 MoNo Mixer\r
6 RK2 SPKOUT Playback Switch\r
7 RK3 SPKOUT Playback Volume\r
8 RK4 PCM Playback Volume\r
9 RK5 Left HP Mixer\r
10 RK6 Right HP Mixer\r
11 RK7 HPLOUT Mux\r
12 RK71 HPL Mixer\r
13 RK8 HPROUT Mux\r
14 RK81 HPR Mixer\r
15 RK9 HPOUT Playback Switch\r
16 RKA HPOUT Playback Volume\r
17 RKB AUXOUT Mux\r
18 RKC AUXOUT Playback Switch\r
19 RKD AUXOUT Playback Volume\r
20 RKE Left Rec Mixer\r
21 RKF Right Rec Mixer\r
22 RKG DAC Mixer Playback Switch\r
23 RKH HIFI DAC Playback Switch\r
24 RKI Mic1 Playback Switch\r
25 RKJ Phone Playback Switch\r
26 RKK Mic1 Capture Switch\r
27 RKL Phone Capture Switch\r
28 RKM Voice DAC Playback Switch\r
29 */\r
30 \r
31 \r
32 #include <linux/module.h>\r
33 #include <linux/moduleparam.h>\r
34 #include <linux/kernel.h>\r
35 #include <linux/init.h>\r
36 #include <linux/delay.h>\r
37 #include <linux/pm.h>\r
38 #include <linux/i2c.h>\r
39 #include <linux/platform_device.h>\r
40 #include <linux/spi/spi.h>\r
41 #include <linux/jiffies.h>\r
42 #include <asm/delay.h>\r
43 #include <sound/core.h>\r
44 #include <sound/pcm.h>\r
45 #include <sound/pcm_params.h>\r
46 #include <sound/soc.h>\r
47 #include <sound/soc-dapm.h>\r
48 #include <sound/initval.h>\r
49 #include <sound/tlv.h>\r
50 #include <asm/div64.h>\r
51 \r
52 #include "rt5625.h"\r
53 \r
54 #if REALTEK_HWDEP\r
55 \r
56 #include <linux/ioctl.h>\r
57 #include <linux/types.h>\r
58 \r
59 #endif\r
60 \r
61 #if 0\r
62 #define DBG(x...) printk(KERN_INFO x)\r
63 #else\r
64 #define DBG(x...) do { } while (0)\r
65 #endif\r
66 \r
67 #define AUDIO_NAME "rt5625"\r
68 #define RT5625_VERSION "0.03 alsa 1.0.21"\r
69 #define ALSA_SOC_VERSION "1.0.21"\r
70 \r
71 #define RT5625_EQ_FUNC_ENA  0\r
72 \r
73 static void hp_depop_mode2(struct snd_soc_codec *codec);\r
74 static void hp_mute_unmute_depop(struct snd_soc_codec *codec,int mute); \r
75 \r
76 struct rt5625_priv {\r
77         unsigned int stereo_sysclk;\r
78         unsigned int voice_sysclk;\r
79 };\r
80 \r
81 struct rt5625_init_reg {\r
82         u8 reg_index;\r
83         u16 reg_value;  \r
84 };\r
85 \r
86 static struct rt5625_init_reg rt5625_init_list[] = {\r
87 \r
88         {RT5625_HP_OUT_VOL                      , 0x8888},      //default is -12db\r
89         {RT5625_SPK_OUT_VOL             , 0x8080},      //default is 0db\r
90         {RT5625_DAC_AND_MIC_CTRL        , 0xee03},      //DAC to hpmixer\r
91         {RT5625_OUTPUT_MIXER_CTRL       , 0x0748},      //all output from hpmixer\r
92         {RT5625_MIC_CTRL                        , 0x0500},      //mic boost 20db\r
93         {RT5625_ADC_REC_MIXER           , 0x3f3f},      //record source from mic1\r
94         {RT5625_GEN_CTRL_REG1           , 0x0c0a},      //speaker vdd ratio is 1\r
95         {RT5625_ADC_REC_GAIN            , 0xd5d5},      //gain 15db of ADC by default\r
96 \r
97 };\r
98 \r
99 #define RT5625_INIT_REG_NUM ARRAY_SIZE(rt5625_init_list)\r
100 \r
101 #if (RT5625_EQ_FUNC_ENA==1)\r
102 //*************************************************************************************************\r
103 //eq table\r
104 //*************************************************************************************************\r
105 enum\r
106 {\r
107         NORMAL=0,\r
108         CLUB,\r
109         DANCE,\r
110         LIVE,   \r
111         POP,\r
112         ROCK,\r
113         OPPO,\r
114         TREBLE,\r
115         BASS    \r
116 };\r
117 \r
118 typedef struct  _HW_EQ_PRESET\r
119 {\r
120         u16     HwEqType;\r
121         u16     EqValue[14];\r
122         u16  HwEQCtrl;\r
123 \r
124 }HW_EQ_PRESET;\r
125 \r
126 \r
127 HW_EQ_PRESET HwEq_Preset[]={\r
128 /*                      0x0             0x1             0x2       0x3   0x4             0x5             0x6             0x7     0x8             0x9             0xa     0xb             0xc             0x6e*/\r
129         {NORMAL,{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x0000},                   \r
130         {CLUB  ,{0x1C10,0x0000,0xC1CC,0x1E5D,0x0699,0xCD48,0x188D,0x0699,0xC3B6,0x1CD0,0x0699,0x0436,0x0000},0x800E},\r
131         {DANCE ,{0x1F2C,0x095B,0xC071,0x1F95,0x0616,0xC96E,0x1B11,0xFC91,0xDCF2,0x1194,0xFAF2,0x0436,0x0000},0x800F},\r
132         {LIVE  ,{0x1EB5,0xFCB6,0xC24A,0x1DF8,0x0E7C,0xC883,0x1C10,0x0699,0xDA41,0x1561,0x0295,0x0436,0x0000},0x800F},\r
133         {POP   ,{0x1EB5,0xFCB6,0xC1D4,0x1E5D,0x0E23,0xD92E,0x16E6,0xFCB6,0x0000,0x0969,0xF988,0x0436,0x0000},0x800F},\r
134         {ROCK  ,{0x1EB5,0xFCB6,0xC071,0x1F95,0x0424,0xC30A,0x1D27,0xF900,0x0C5D,0x0FC7,0x0E23,0x0436,0x0000},0x800F},\r
135         {OPPO  ,{0x0000,0x0000,0xCA4A,0x17F8,0x0FEC,0xCA4A,0x17F8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x800F},\r
136         {TREBLE,{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x188D,0x1699},0x8010},\r
137         {BASS  ,{0x1A43,0x0C00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x8001},\r
138         \r
139 };\r
140 \r
141 #endif\r
142 //*************************************************************************************************\r
143 //*************************************************************************************************\r
144 \r
145 /*\r
146  *      bit[0]  for linein playback switch\r
147  *      bit[1] phone\r
148  *      bit[2] mic1\r
149  *      bit[3] mic2\r
150  *      bit[4] vopcm\r
151  *      \r
152  */\r
153 #define HPL_MIXER 0x80\r
154 #define HPR_MIXER 0x82\r
155 static unsigned int reg80 = 0, reg82 = 0;\r
156 \r
157 /*\r
158  *      bit[0][1][2] use for aec control\r
159  *  bit[3] for none  \r
160  *      bit[4] for SPKL pga\r
161  *      bit[5] for SPKR pga\r
162  *      bit[6] for hpl pga\r
163  *      bit[7] for hpr pga\r
164  *  bit[8] for dump dsp\r
165  *  bit[12~15] for eq function\r
166  */\r
167  #define VIRTUAL_REG_FOR_MISC_FUNC 0x84\r
168 static unsigned int reg84 = 0;\r
169 \r
170 \r
171 static const u16 rt5625_reg[] = {\r
172         0x59b4, 0x8080, 0x8080, 0x8080,         /*reg00-reg06*/\r
173         0xc800, 0xe808, 0x1010, 0x0808,         /*reg08-reg0e*/\r
174         0xe0ef, 0xcbcb, 0x7f7f, 0x0000,         /*reg10-reg16*/\r
175         0xe010, 0x0000, 0x8008, 0x2007,         /*reg18-reg1e*/\r
176         0x0000, 0x0000, 0x00c0, 0xef00,         /*reg20-reg26*/\r
177         0x0000, 0x0000, 0x0000, 0x0000,         /*reg28-reg2e*/\r
178         0x0000, 0x0000, 0x0000, 0x0000,         /*reg30-reg36*/\r
179         0x0000, 0x0000, 0x0000, 0x0000,         /*reg38-reg3e*/\r
180         0x0c0a, 0x0000, 0x0000, 0x0000,         /*reg40-reg46*/\r
181         0x0029, 0x0000, 0xbe3e, 0x3e3e,         /*reg48-reg4e*/\r
182         0x0000, 0x0000, 0x803a, 0x0000,         /*reg50-reg56*/\r
183         0x0000, 0x0009, 0x0000, 0x3000,         /*reg58-reg5e*/\r
184         0x3075, 0x1010, 0x3110, 0x0000,         /*reg60-reg66*/\r
185         0x0553, 0x0000, 0x0000, 0x0000,         /*reg68-reg6e*/\r
186         0x0000, 0x0000, 0x0000, 0x0000,         /*reg70-reg76*/\r
187         0x0000, 0x0000, 0x0000, 0x0000,     /*reg78-reg7e*/\r
188 };\r
189 \r
190 \r
191 Voice_DSP_Reg VODSP_AEC_Init_Value[]=\r
192 {\r
193         {0x232C, 0x0025},\r
194         {0x230B, 0x0001},\r
195         {0x2308, 0x007F},\r
196         {0x23F8, 0x4003},\r
197         {0x2301, 0x0002},\r
198         {0x2328, 0x0001},\r
199         {0x2304, 0x00FA},\r
200         {0x2305, 0x0500},\r
201         {0x2306, 0x4000},\r
202         {0x230D, 0x0900},\r
203         {0x230E, 0x0280},\r
204         {0x2312, 0x00B1},\r
205         {0x2314, 0xC000},\r
206         {0x2316, 0x0041},\r
207         {0x2317, 0x2200},\r
208         {0x2318, 0x0C00},\r
209         {0x231D, 0x0050},\r
210         {0x231F, 0x4000},\r
211         {0x2330, 0x0008},\r
212         {0x2335, 0x000A},\r
213         {0x2336, 0x0004},\r
214         {0x2337, 0x5000},\r
215         {0x233A, 0x0300},\r
216         {0x233B, 0x0030},\r
217         {0x2341, 0x0008},\r
218         {0x2343, 0x0800},       \r
219         {0x2352, 0x7FFF},\r
220         {0x237F, 0x0400},\r
221         {0x23A7, 0x2800},\r
222         {0x22CE, 0x0400},\r
223         {0x22D3, 0x1500},\r
224         {0x22D4, 0x2800},\r
225         {0x22D5, 0x3000},\r
226         {0x2399, 0x2800},\r
227         {0x230C, 0x0000},       //to enable VODSP AEC function\r
228 };\r
229 \r
230 \r
231 #define SET_VODSP_REG_INIT_NUM  ARRAY_SIZE(VODSP_AEC_Init_Value)\r
232 static struct snd_soc_device *rt5625_socdev;\r
233 \r
234 static inline unsigned int rt5625_read_reg_cache(struct snd_soc_codec *codec, \r
235         unsigned int reg)\r
236 {\r
237         u16 *cache = codec->reg_cache;\r
238 \r
239         if (reg > 0x7e)\r
240                 return 0;\r
241         return cache[reg / 2];\r
242 }\r
243 \r
244 \r
245 static unsigned int rt5625_read_hw_reg(struct snd_soc_codec *codec, unsigned int reg) \r
246 {\r
247         u8 data[2] = {0};\r
248         unsigned int value = 0x0;\r
249         \r
250         data[0] = reg;\r
251         \r
252         i2c_master_reg8_recv(codec->control_data,reg,data,2,100 * 1000);        \r
253                       \r
254         value = (data[0]<<8) | data[1];\r
255 \r
256         DBG(KERN_INFO "rt5625_read ok, reg = %x, value = %x\n", reg, value);\r
257 \r
258         return value;   \r
259 }\r
260 \r
261 \r
262 static unsigned int rt5625_read(struct snd_soc_codec *codec, unsigned int reg)\r
263 {\r
264         if ((reg == 0x80)\r
265                 || (reg == 0x82)\r
266                 || (reg == 0x84))\r
267                 return (reg == 0x80) ? reg80 : ((reg == 0x82) ? reg82 : reg84);\r
268         \r
269                 return rt5625_read_hw_reg(codec, reg);\r
270 }\r
271 \r
272 \r
273 static inline void rt5625_write_reg_cache(struct snd_soc_codec *codec,\r
274         unsigned int reg, unsigned int value)\r
275 {\r
276         u16 *cache = codec->reg_cache;\r
277         if (reg > 0x7E)\r
278                 return;\r
279         cache[reg / 2] = value;\r
280 }\r
281 \r
282 static int rt5625_write(struct snd_soc_codec *codec, unsigned int reg,\r
283         unsigned int value)\r
284 {\r
285         u8 data[3];\r
286         unsigned int *regvalue = NULL;\r
287 \r
288         data[0] = reg;\r
289         data[1] = (value & 0xff00) >> 8;\r
290         data[2] = value & 0x00ff;\r
291         \r
292         if ((reg == 0x80)\r
293                 || (reg == 0x82)\r
294                 || (reg == 0x84))\r
295         {               \r
296                 regvalue = ((reg == 0x80) ? &reg80 : ((reg == 0x82) ? &reg82 : &reg84));\r
297                 *regvalue = value;\r
298                 DBG("rt5625_write ok, reg = %x, value = %x\n", reg, value);\r
299                 return 0;\r
300         }\r
301         rt5625_write_reg_cache(codec, reg, value);\r
302 \r
303         if (codec->hw_write(codec->control_data, data, 3) == 3)\r
304         {\r
305                 DBG("rt5625_write ok, reg = %x, value = %x\n", reg, value);\r
306                 return 0;\r
307         }\r
308         else \r
309         {\r
310                 printk("rt5625_write fail\n");\r
311                 return -EIO;\r
312         }\r
313 }\r
314 \r
315 int rt5625_write_mask(struct snd_soc_codec *codec, unsigned int reg,unsigned int value,unsigned int mask)\r
316 {\r
317         \r
318         unsigned char RetVal=0;\r
319         unsigned  int CodecData;\r
320 \r
321         DBG("rt5625_write_mask ok, reg = %x, value = %x ,mask= %x\n", reg, value,mask);\r
322 \r
323         if(!mask)\r
324                 return 0; \r
325 \r
326         if(mask!=0xffff)\r
327          {\r
328                 CodecData=rt5625_read(codec,reg);               \r
329                 CodecData&=~mask;\r
330                 CodecData|=(value&mask);\r
331                 RetVal=rt5625_write(codec,reg,CodecData);\r
332          }              \r
333         else\r
334         {\r
335                 RetVal=rt5625_write(codec,reg,value);\r
336         }\r
337 \r
338         return RetVal;\r
339 }\r
340 \r
341 \r
342 void rt5625_write_index(struct snd_soc_codec *codec, unsigned int reg,\r
343         unsigned int value)\r
344 {\r
345         \r
346         rt5625_write(codec,0x6a,reg);\r
347         rt5625_write(codec,0x6c,value); \r
348 }\r
349 \r
350 unsigned int rt5625_read_index(struct snd_soc_codec *codec, unsigned int reg)\r
351 {\r
352         unsigned int value = 0x0;\r
353         rt5625_write(codec,0x6a,reg);\r
354         value=rt5625_read(codec,0x6c);  \r
355         \r
356         return value;\r
357 }\r
358 \r
359 void rt5625_write_index_mask(struct snd_soc_codec *codec, unsigned int reg,unsigned int value,unsigned int mask)\r
360 {\r
361         \r
362 //      unsigned char RetVal=0;\r
363         unsigned  int CodecData;\r
364 \r
365         DBG("rt5625_write_index_mask ok, reg = %x, value = %x ,mask= %x\n", reg, value,mask);\r
366 \r
367         if(!mask)\r
368                 return; \r
369 \r
370         if(mask!=0xffff)\r
371          {\r
372                 CodecData=rt5625_read_index(codec,reg);         \r
373                 CodecData&=~mask;\r
374                 CodecData|=(value&mask);\r
375                 rt5625_write_index(codec,reg,CodecData);\r
376          }              \r
377         else\r
378         {\r
379                 rt5625_write_index(codec,reg,value);\r
380         }\r
381 }\r
382 \r
383 //#define rt5625_write_mask(c, reg, value, mask) snd_soc_update_bits(c, reg, mask, value)\r
384 \r
385 #define rt5625_reset(c) rt5625_write(c, RT5625_RESET, 0)\r
386 \r
387 /*read/write dsp reg*/\r
388 static int rt5625_wait_vodsp_i2c_done(struct snd_soc_codec *codec)\r
389 {\r
390         unsigned int checkcount = 0, vodsp_data;\r
391 \r
392         vodsp_data = rt5625_read(codec, RT5625_VODSP_REG_CMD);\r
393         while(vodsp_data & VODSP_BUSY)\r
394         {\r
395                 if(checkcount > 10)\r
396                         return -EBUSY;\r
397                 vodsp_data = rt5625_read(codec, RT5625_VODSP_REG_CMD);\r
398                 checkcount ++;          \r
399         }\r
400         return 0;\r
401 }\r
402 \r
403 static int rt5625_write_vodsp_reg(struct snd_soc_codec *codec, unsigned int vodspreg, unsigned int value)\r
404 {\r
405         int ret = 0;\r
406 \r
407         if(ret != rt5625_wait_vodsp_i2c_done(codec))\r
408                 return -EBUSY;\r
409 \r
410         rt5625_write(codec, RT5625_VODSP_REG_ADDR, vodspreg);\r
411         rt5625_write(codec, RT5625_VODSP_REG_DATA, value);\r
412         rt5625_write(codec, RT5625_VODSP_REG_CMD, VODSP_WRITE_ENABLE | VODSP_CMD_MW);\r
413         mdelay(10);\r
414         return ret;\r
415         \r
416 }\r
417 \r
418 static unsigned int rt5625_read_vodsp_reg(struct snd_soc_codec *codec, unsigned int vodspreg)\r
419 {\r
420         int ret = 0;\r
421         unsigned int nDataH, nDataL;\r
422         unsigned int value;\r
423 \r
424         if(ret != rt5625_wait_vodsp_i2c_done(codec))\r
425                 return -EBUSY;\r
426         \r
427         rt5625_write(codec, RT5625_VODSP_REG_ADDR, vodspreg);\r
428         rt5625_write(codec, RT5625_VODSP_REG_CMD, VODSP_READ_ENABLE | VODSP_CMD_MR);\r
429 \r
430         if (ret != rt5625_wait_vodsp_i2c_done(codec))\r
431                 return -EBUSY;\r
432         rt5625_write(codec, RT5625_VODSP_REG_ADDR, 0x26);\r
433         rt5625_write(codec, RT5625_VODSP_REG_CMD, VODSP_READ_ENABLE | VODSP_CMD_RR);\r
434 \r
435         if(ret != rt5625_wait_vodsp_i2c_done(codec))\r
436                 return -EBUSY;\r
437         nDataH = rt5625_read(codec, RT5625_VODSP_REG_DATA);\r
438         rt5625_write(codec, RT5625_VODSP_REG_ADDR, 0x25);\r
439         rt5625_write(codec, RT5625_VODSP_REG_CMD, VODSP_READ_ENABLE | VODSP_CMD_RR);\r
440 \r
441         if(ret != rt5625_wait_vodsp_i2c_done(codec))\r
442                 return -EBUSY;\r
443         nDataL = rt5625_read(codec, RT5625_VODSP_REG_DATA);\r
444         value = ((nDataH & 0xff) << 8) |(nDataL & 0xff);\r
445         DBG("%s vodspreg=0x%x, value=0x%x\n", __func__, vodspreg, value);\r
446         return value;\r
447 }\r
448 \r
449 static int rt5625_reg_init(struct snd_soc_codec *codec)\r
450 {\r
451         int i;\r
452 \r
453         for (i = 0; i < RT5625_INIT_REG_NUM; i++)\r
454                 rt5625_write(codec, rt5625_init_list[i].reg_index, rt5625_init_list[i].reg_value);\r
455 \r
456         return 0;\r
457 }\r
458 \r
459 //*************************************************************************************************\r
460 //*************************************************************************************************\r
461 #if (RT5625_EQ_FUNC_ENA==1)     \r
462 //eq function\r
463 static void rt5625_update_eqmode(struct snd_soc_codec *codec, int mode)\r
464 {\r
465         u16 HwEqIndex=0;\r
466 \r
467         if(mode==NORMAL)\r
468         {\r
469                 /*clear EQ parameter*/\r
470                 for(HwEqIndex=0;HwEqIndex<=0x0C;HwEqIndex++)\r
471                 {\r
472                         rt5625_write_index(codec, HwEqIndex, HwEq_Preset[mode].EqValue[HwEqIndex]);\r
473                 }\r
474                 \r
475                 rt5625_write_mask(codec, 0x6e,0x0,EN_HW_EQ_BLK | EN_HW_EQ_HPF | EN_HW_EQ_BP3 | EN_HW_EQ_BP2 | EN_HW_EQ_BP1 | EN_HW_EQ_LPF);             /*disable EQ block*/\r
476         }\r
477         else\r
478         {               \r
479                 /*Fill EQ parameter*/\r
480                 for(HwEqIndex=0;HwEqIndex<=0x0C;HwEqIndex++)\r
481                 {\r
482                         rt5625_write_index(codec, HwEqIndex, HwEq_Preset[mode].EqValue[HwEqIndex]); \r
483                 }               \r
484 \r
485                 //enable EQ block\r
486                 rt5625_write_mask(codec, 0x6e,HwEq_Preset[mode].HwEQCtrl,EN_HW_EQ_BLK | EN_HW_EQ_HPF | EN_HW_EQ_BP3 | EN_HW_EQ_BP2 | EN_HW_EQ_BP1 | EN_HW_EQ_LPF);              \r
487                 \r
488                 //update EQ parameter\r
489                 rt5625_write_mask(codec, 0x6e,0x0080,0x0080);\r
490         }\r
491 }\r
492 \r
493 \r
494 static int rt5625_eq_sel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)\r
495 {\r
496         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);\r
497         u16 Virtual_reg = rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC);\r
498         int rt5625_mode=((Virtual_reg)&0xf000)>>12;\r
499         \r
500         if ( rt5625_mode == ucontrol->value.integer.value[0])\r
501                 return 0;\r
502 \r
503         rt5625_update_eqmode(codec, ucontrol->value.enumerated.item[0]);\r
504 \r
505         Virtual_reg &= 0x0fff;\r
506         Virtual_reg |= (ucontrol->value.integer.value[0])<<12;\r
507         rt5625_write(codec, VIRTUAL_REG_FOR_MISC_FUNC, Virtual_reg);            \r
508         \r
509         return 0;\r
510 }\r
511 #endif\r
512 //*************************************************************************************************\r
513 //*************************************************************************************************\r
514 static const char *rt5625_aec_path_sel[] = {"aec func disable","aec func for pcm in/out",\r
515                                             "aec func for iis in/out","aec func for analog in/out"};            /*0*/                   \r
516 static const char *rt5625_spk_out_sel[] = {"Class AB", "Class D"};                                      /*1*/\r
517 static const char *rt5625_spk_l_source_sel[] = {"LPRN", "LPRP", "LPLN", "MM"};          /*2*/   \r
518 static const char *rt5625_spkmux_source_sel[] = {"VMID", "RK11", \r
519                                                         "RK12", "RK13"};                                                /*3*/\r
520 static const char *rt5625_hplmux_source_sel[] = {"VMID","RK71"};                                /*4*/\r
521 static const char *rt5625_hprmux_source_sel[] = {"VMID","RK81"};                                /*5*/\r
522 static const char *rt5625_auxmux_source_sel[] = {"VMID", "RK11", \r
523                                                         "RK12", "RK13"};                                                        /*6*/\r
524 static const char *rt5625_spkamp_ratio_sel[] = {"2.25 Vdd", "2.00 Vdd",\r
525                                         "1.75 Vdd", "1.50 Vdd", "1.25 Vdd", "1.00 Vdd"};                                /*7*/\r
526 static const char *rt5625_mic1_boost_sel[] = {"Bypass", "+20db", "+30db", "+40db"};     /*8*/\r
527 static const char *rt5625_mic2_boost_sel[] = {"Bypass", "+20db", "+30db", "+40db"};     /*9*/\r
528 static const char *rt5625_dmic_boost_sel[] = {"Bypass", "+6db", "+12db", "+18db", \r
529                                         "+24db", "+30db", "+36db", "+42db"};                                            /*10*/\r
530 static const char *rt5625_adcr_func_sel[] = {"Stereo ADC", "Voice ADC", \r
531                                         "VoDSP Interface", "PDM Slave Interface"};                                   /*11*/\r
532 #if (RT5625_EQ_FUNC_ENA==1)                                     \r
533 static const char *rt5625_eq_sel[] = {"NORMAL", "CLUB","DANCE", "LIVE","POP",                   /*12*/\r
534                                         "ROCK", "OPPO", "TREBLE", "BASS"};                                      \r
535 #endif\r
536 \r
537 static const struct soc_enum rt5625_enum[] = {\r
538 \r
539 SOC_ENUM_SINGLE(VIRTUAL_REG_FOR_MISC_FUNC, 0, 4, rt5625_aec_path_sel),          /*0*/\r
540 SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 13, 2, rt5625_spk_out_sel),           /*1*/\r
541 SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 14, 4, rt5625_spk_l_source_sel),      /*2*/\r
542 SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 10, 4, rt5625_spkmux_source_sel),/*3*/\r
543 SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 9, 2, rt5625_hplmux_source_sel),      /*4*/\r
544 SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 8, 2, rt5625_hprmux_source_sel),/*5*/\r
545 SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 6, 4, rt5625_auxmux_source_sel),/*6*/\r
546 SOC_ENUM_SINGLE(RT5625_GEN_CTRL_REG1, 1, 6, rt5625_spkamp_ratio_sel),           /*7*/\r
547 SOC_ENUM_SINGLE(RT5625_MIC_CTRL, 10, 4,  rt5625_mic1_boost_sel),                        /*8*/\r
548 SOC_ENUM_SINGLE(RT5625_MIC_CTRL, 8, 4, rt5625_mic2_boost_sel),                          /*9*/\r
549 SOC_ENUM_SINGLE(RT5625_DMIC_CTRL, 0, 8, rt5625_dmic_boost_sel),                         /*10*/\r
550 SOC_ENUM_SINGLE(RT5625_DAC_ADC_VODAC_FUN_SEL, 4, 4, rt5625_adcr_func_sel), /*11*/\r
551 #if (RT5625_EQ_FUNC_ENA==1)\r
552 SOC_ENUM_SINGLE(VIRTUAL_REG_FOR_MISC_FUNC, 12, 9, rt5625_eq_sel),    /*EQ mode select mode 12*/\r
553 #endif\r
554 };\r
555 \r
556 \r
557 \r
558 //*****************************************************************************\r
559 //function:Enable the Voice PCM interface Path\r
560 //*****************************************************************************\r
561 static int ConfigPcmVoicePath(struct snd_soc_codec *codec,unsigned int bEnableVoicePath,unsigned int mode)\r
562 {\r
563 \r
564         if(bEnableVoicePath)\r
565          {\r
566                         //Power on DAC reference\r
567                         rt5625_write_mask(codec,RT5625_PWR_MANAG_ADD1,PWR_DAC_REF|PWR_VOICE_DF2SE,PWR_DAC_REF|PWR_VOICE_DF2SE);\r
568                         //Power on Voice DAC/ADC \r
569                         rt5625_write_mask(codec,RT5625_PWR_MANAG_ADD2,PWR_VOICE_CLOCK,PWR_VOICE_CLOCK);\r
570                         //routing voice to HPMixer\r
571                         rt5625_write_mask(codec,RT5625_VOICE_DAC_OUT_VOL,0,M_V_DAC_TO_HP_MIXER);\r
572                                         \r
573                 switch(mode)            \r
574                 {\r
575                         case PCM_SLAVE_MODE_B:  //8kHz sampling rate,16 bits PCM mode and Slave mode,PCM mode is B,MCLK=24.576MHz from Oscillator.\r
576                                                                 //CSR PSKEY_PCM_CONFIG32 (HEX) = 0x08C00000,PSKEY_FORMAT=0x0060                         \r
577 \r
578                                 //Enable GPIO 1,3,4,5 to voice interface\r
579                                 //Set I2S to Slave mode\r
580                                 //Voice I2S SYSCLK Source select Main SYSCLK\r
581                                 //Set voice I2S VBCLK Polarity to Invert\r
582                                 //Set Data length to 16 bit\r
583                                 //set Data Fomrat to PCM mode B\r
584                                 //the register 0x36 value's should is 0xC083\r
585                                 rt5625_write(codec,RT5625_EXTEND_SDP_CTRL,0xC083);\r
586 \r
587                                 //Set LRCK voice select divide 32\r
588                                 //set voice blck select divide 6 and 8 \r
589                                 //voice filter clock divide 3 and 16\r
590                                 //the register 0x64 value's should is 0x5524\r
591                                 rt5625_write(codec,RT5625_VOICE_DAC_PCMCLK_CTRL1,0x5524);\r
592                 \r
593                                 break;\r
594 \r
595                         case PCM_SLAVE_MODE_A:  //8kHz sampling rate,16 bits PCM and Slave mode,PCM mode is A,MCLK=24.576MHz from Oscillator.\r
596                                                                 //CSR PSKEY_PCM_CONFIG32 (HEX) = 0x08C00004,PSKEY_FORMAT=0x0060                         \r
597 \r
598                                 //Enable GPIO 1,3,4,5 to voice interface\r
599                                 //Set I2S to Slave mode\r
600                                 //Voice I2S SYSCLK Source select Main SYSCLK\r
601                                 //Set voice i2s VBCLK Polarity to Invert\r
602                                 //Set Data length to 16 bit\r
603                                 //set Data Fomrat to PCM mode A\r
604                                 //the register 0x36 value's should is 0xC082\r
605                                 rt5625_write(codec,RT5625_EXTEND_SDP_CTRL,0xC082);\r
606 \r
607                                 //Set LRCK voice select divide 64\r
608                                 //set voice blck select divide 6 and 8 \r
609                                 //voice filter clock divide 3 and 16\r
610                                 //the register 0x64 value's should is 0x5524\r
611                                 rt5625_write(codec,RT5625_VOICE_DAC_PCMCLK_CTRL1,0x5524);\r
612                 \r
613                                 break;\r
614 \r
615                         case PCM_MASTER_MODE_B: //8kHz sampling rate,16 bits PCM and Master mode,PCM mode is B,Clock from PLL OUT\r
616                                                                 //CSR PSKEY_PCM_CONFIG32 (HEX) = 0x08000002,PSKEY_FORMAT=0x0060 \r
617 \r
618                                 //Enable GPIO 1,3,4,5 to voice interface\r
619                                 //Set I2S to master mode\r
620                                 //Set voice i2s VBCLK Polarity to Invert\r
621                                 //Set Data length to 16 bit\r
622                                 //set Data Fomrat to PCM mode B\r
623                                 //the register 0x36 value's should is 0x8083\r
624                                 rt5625_write(codec,RT5625_EXTEND_SDP_CTRL,0x8083);\r
625 \r
626                                 //Set LRCK voice select divide 64\r
627                                 //set voice blck select divide 6 and 8 \r
628                                 //voice filter clock divide 3 and 16\r
629                                 //the register 0x64 value's should is 0x5524\r
630                                 rt5625_write(codec,RT5625_VOICE_DAC_PCMCLK_CTRL1,0x5524);\r
631                 \r
632                                 break;\r
633 \r
634                         default:\r
635                                 //do nothing            \r
636                                 break;\r
637 \r
638                         }\r
639                 }\r
640                 else\r
641                 {       \r
642                         //Power down Voice Different to sing-end power\r
643                         rt5625_write_mask(codec,RT5625_PWR_MANAG_ADD1,0,PWR_VOICE_DF2SE);\r
644                         //Power down Voice DAC/ADC \r
645                         rt5625_write_mask(codec,RT5625_PWR_MANAG_ADD2,0,PWR_VOICE_CLOCK);\r
646                         //Disable Voice PCM interface   \r
647                         rt5625_write_mask(codec,RT5625_EXTEND_SDP_CTRL,0,EXT_I2S_FUNC_ENABLE);                  \r
648                 }\r
649         \r
650         return 0;\r
651 }\r
652 \r
653 static int init_vodsp_aec(struct snd_soc_codec *codec)\r
654 {\r
655         int i;\r
656         int ret = 0;\r
657 \r
658         /*disable LDO power*/\r
659         rt5625_write_mask(codec, RT5625_LDO_CTRL,0,LDO_ENABLE);\r
660         mdelay(20);     \r
661         rt5625_write_mask(codec, RT5625_VODSP_CTL,VODSP_NO_PD_MODE_ENA,VODSP_NO_PD_MODE_ENA);\r
662         /*enable LDO power and set output voltage to 1.2V*/\r
663         rt5625_write_mask(codec, RT5625_LDO_CTRL,LDO_ENABLE|LDO_OUT_VOL_CTRL_1_20V,LDO_ENABLE|LDO_OUT_VOL_CTRL_MASK);\r
664         mdelay(20);\r
665         /*enable power of VODSP I2C interface*/ \r
666         rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD3,PWR_VODSP_INTERFACE|PWR_I2C_FOR_VODSP,PWR_VODSP_INTERFACE|PWR_I2C_FOR_VODSP);\r
667         mdelay(1);\r
668         rt5625_write_mask(codec, RT5625_VODSP_CTL,0,VODSP_NO_RST_MODE_ENA);     /*Reset VODSP*/\r
669         mdelay(1);\r
670         rt5625_write_mask(codec, RT5625_VODSP_CTL,VODSP_NO_RST_MODE_ENA,VODSP_NO_RST_MODE_ENA); /*set VODSP to non-reset status*/               \r
671         mdelay(20);\r
672 \r
673         /*initize AEC paramter*/\r
674         for(i = 0; i < SET_VODSP_REG_INIT_NUM; i++)\r
675         {\r
676                 ret = rt5625_write_vodsp_reg(codec, VODSP_AEC_Init_Value[i].VoiceDSPIndex,VODSP_AEC_Init_Value[i].VoiceDSPValue);\r
677                 if(ret)\r
678                         return -EIO;\r
679         }               \r
680 \r
681         schedule_timeout_uninterruptible(msecs_to_jiffies(10)); \r
682 \r
683         return 0;\r
684 }\r
685 \r
686 //***********************************************************************************************\r
687 //function:Enable/Disable the vodsp interface Path\r
688 //For system clock only suport specific clock,realtek suggest customer to use 24.576Mhz or 22.5792Mhz\r
689 //clock fro MCLK(MCLK=48k*512 or 44.1k*512Mhz)\r
690 //***********************************************************************************************\r
691 static int set_vodsp_aec_path(struct snd_soc_codec *codec, unsigned int mode)\r
692 {\r
693 \r
694                 switch(mode)\r
695                 {\r
696 \r
697                         case PCM_IN_PCM_OUT:\r
698                                 //set PCM format\r
699                                 ConfigPcmVoicePath(codec,1,PCM_MASTER_MODE_B);\r
700                                 //set AEC path\r
701                                 rt5625_write_mask(codec, 0x26,0x0300,0x0300);\r
702                                 rt5625_write_mask(codec, RT5625_VODSP_PDM_CTL,VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_VOICE|VOICE_PCM_S_SEL_AEC_TXDP\r
703                                                                                                                          ,VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_MASK|VOICE_PCM_S_SEL_MASK);\r
704                                 rt5625_write_mask(codec, RT5625_DAC_ADC_VODAC_FUN_SEL,ADCR_FUNC_SEL_PDM|VODAC_SOUR_SEL_VODSP_TXDC\r
705                                                                                                                                         ,ADCR_FUNC_SEL_MASK|VODAC_SOUR_SEL_MASK);\r
706                                 rt5625_write_mask(codec, RT5625_VODSP_CTL,VODSP_LRCK_SEL_8K,VODSP_LRCK_SEL_MASK);                                               \r
707                                 rt5625_write_mask(codec, 0x26,0x0000,0x0300);\r
708                                 //set input&output path and power\r
709                                 rt5625_write_mask(codec, 0x3a,0x0c8f,0x0c8f);//power on related bit\r
710                                 rt5625_write_mask(codec, 0x3c,0xa4cb,0xa4cb);//power on related bit\r
711                                 rt5625_write_mask(codec, 0x3e,0x3302,0xf302);//power on related bit\r
712                                                 \r
713                                 rt5625_write(codec, 0x10, 0xee0f);//mute DAC to hpmixer\r
714                                 rt5625_write(codec, 0x0e, 0x8808);//set Mic1 to differential mode\r
715                                 rt5625_write(codec, 0x22, 0x0000);//Mic boost 0db\r
716                                 rt5625_write(codec, 0x12, 0xCBD3);//ADC_Mixer_R boost 10.5 db\r
717                                 rt5625_write(codec, 0x14, 0x7f3f);//Mic1->ADCMixer_R\r
718                                 rt5625_write(codec, 0x18, 0xa010);//VoDAC to speakerMixer,0db\r
719                                 rt5625_write(codec, 0x1c, 0x8808);//speaker source from speakermixer\r
720                                                         \r
721                                 rt5625_write_mask(codec, 0x02,0x0000,0x8080);   //unmute speaker \r
722 \r
723                                 break;\r
724                         \r
725                         \r
726                         case ANALOG_IN_ANALOG_OUT:      \r
727                                 rt5625_write_mask(codec, 0x26,0x0300,0x0300);\r
728                                 rt5625_write_mask(codec, RT5625_VODSP_PDM_CTL,VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_ADCL|VOICE_PCM_S_SEL_AEC_TXDP\r
729                                                                                                                          ,VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_MASK|VOICE_PCM_S_SEL_MASK);\r
730                                 rt5625_write_mask(codec, RT5625_DAC_ADC_VODAC_FUN_SEL,ADCR_FUNC_SEL_PDM|VODAC_SOUR_SEL_VODSP_TXDC|DAC_FUNC_SEL_VODSP_TXDP|ADCL_FUNC_SEL_VODSP\r
731                                                                                                                                         ,ADCR_FUNC_SEL_MASK|VODAC_SOUR_SEL_MASK|DAC_FUNC_SEL_MASK|ADCL_FUNC_SEL_MASK);\r
732                                 rt5625_write_mask(codec, RT5625_VODSP_CTL,VODSP_LRCK_SEL_16K,VODSP_LRCK_SEL_MASK);      \r
733                                 rt5625_write_mask(codec, 0x26,0x0000,0x0300);\r
734                                 //set input&output path and power\r
735                                 rt5625_write_mask(codec, 0x3a,0xcc8f,0xcc8f);//power on related bit\r
736                                 rt5625_write_mask(codec, 0x3c,0xa7cf,0xa7cf);//power on related bit\r
737                                 rt5625_write_mask(codec, 0x3e,0xf312,0xf312);//power on related bit\r
738                                 \r
739                                 rt5625_write(codec, 0x0e, 0x8808);//set Mic1 to differential mode\r
740                                 rt5625_write(codec, 0x08, 0xe800);//set phone in to differential mode\r
741                                 rt5625_write(codec, 0x22, 0x0000);//Mic boost 0db\r
742                                 rt5625_write(codec, 0x14, 0x773f);//Mic1->ADCMixer_R,phone in-->ADCMixer_L\r
743                                 rt5625_write(codec, 0x12, 0xCBD3);//ADC_Mixer_R boost 10.5 db\r
744                                 rt5625_write(codec, 0x1c, 0x88c8);//speaker from spkmixer,monoOut from monoMixer\r
745                                 rt5625_write(codec, 0x18, 0xA010);//unmute VoDAC to spkmixer\r
746                                 rt5625_write(codec, 0x10, 0xee0e);//unmute DAC to monoMixer     \r
747                                 rt5625_write(codec, 0x62, 0x2222);\r
748                                 rt5625_write(codec, 0x64, 0x3122);\r
749                                 rt5625_write_mask(codec, 0x02,0x0000,0x8080);   //unmute speaker \r
750                                 rt5625_write_mask(codec, 0x06,0x0000,0x8080);   //unmute auxout \r
751                                 break;\r
752 \r
753                         case DAC_IN_ADC_OUT:    \r
754                                 rt5625_write_mask(codec, 0x26,0x0300,0x0300);\r
755                                 rt5625_write_mask(codec,RT5625_DAC_ADC_VODAC_FUN_SEL,ADCR_FUNC_SEL_PDM|DAC_FUNC_SEL_VODSP_TXDC\r
756                                                                                                                                         ,ADCR_FUNC_SEL_MASK|DAC_FUNC_SEL_MASK);\r
757                                 rt5625_write_mask(codec,RT5625_VODSP_PDM_CTL,VODSP_SRC1_PWR|VODSP_SRC2_PWR|VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_SRC1|REC_S_SEL_SRC2,\r
758                                                                                                                          VODSP_SRC1_PWR|VODSP_SRC2_PWR|VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_MASK|REC_S_SEL_MASK);                                    \r
759                                 rt5625_write_mask(codec,RT5625_VODSP_CTL,VODSP_LRCK_SEL_16K,VODSP_LRCK_SEL_MASK);\r
760                                 rt5625_write_mask(codec, 0x26,0x0000,0x0300);\r
761                                 //set input&output path and power       \r
762                                 rt5625_write_mask(codec, 0x3a,0xcc0f,0xcc0f);//power on related bit\r
763                                 rt5625_write_mask(codec, 0x3c,0xa7cb,0xa7cb);//power on related bit\r
764                                 rt5625_write_mask(codec, 0x3e,0x3302,0x3302);//power on related bit\r
765                                 \r
766                                 rt5625_write(codec, 0x0e, 0x8808);//set Mic1 to differential mode\r
767                                 rt5625_write(codec, 0x22, 0x0000);//Mic boost 0db\r
768                                 rt5625_write(codec, 0x14, 0x7f3f);//Mic1->ADCMixer_R\r
769                                 rt5625_write(codec, 0x12, 0xCBD3);//ADC_Mixer_R boost 10.5 db\r
770                                 rt5625_write(codec, 0x1c, 0x8808);//speaker out from spkMixer\r
771                                 rt5625_write(codec, 0x10, 0xee0d);//unmute DAC to spkMixer      \r
772                                 rt5625_write(codec, 0x60, 0x3075);\r
773                                 rt5625_write(codec, 0x62, 0x1010);                                      \r
774                                 rt5625_write_mask(codec, 0x02,0x0000,0x8080);   //unmute speaker \r
775 \r
776                                 break;\r
777 \r
778                         case VODSP_AEC_DISABLE:\r
779                         default:\r
780                                 rt5625_write_mask(codec, 0x02,0x8080,0x8080);//mute speaker out\r
781                                 rt5625_write_mask(codec, 0x06,0x8080,0x8080);//mute auxout              \r
782                                 rt5625_write(codec, 0x22, 0x0500);//Mic boost 20db by default\r
783                                 rt5625_write(codec, 0x14, 0x3f3f);//record from Mic1 by default\r
784                                 rt5625_write(codec, 0x12, 0xD5D5);//ADC_Mixer_R boost 15 db by default\r
785                                 rt5625_write(codec, 0x1c, 0x0748);//all output from HPmixer by default\r
786                                 rt5625_write(codec, 0x10, 0xee03);//DAC to HPmixer by default\r
787                                 rt5625_write(codec, 0x18, 0xe010);//mute VoDAC to mixer by default\r
788                                 rt5625_write_mask(codec, 0x26,0x0300,0x0300);\r
789                                 /*set stereo DAC&Voice DAC&Stereo ADC function select to default*/ \r
790                                 rt5625_write(codec, RT5625_DAC_ADC_VODAC_FUN_SEL,0);            \r
791                                 /*set VODSP&PDM Control to default*/ \r
792                                 rt5625_write(codec, RT5625_VODSP_PDM_CTL,0);\r
793                                 rt5625_write_mask(codec, 0x26,0x0000,0x0300);           \r
794                                 rt5625_write_mask(codec, 0x3e,0x0000,0xf312);//power down related bit\r
795                                 rt5625_write_mask(codec, 0x3a,0x0000,0xcc8d);//power down related bit\r
796                                 rt5625_write_mask(codec, 0x3c,0x0000,0x07cf);//power down related bit\r
797                                 \r
798                         \r
799                                 break;\r
800                 }               \r
801 \r
802         return 0;\r
803 }\r
804 \r
805 static int enable_vodsp_aec(struct snd_soc_codec *codec, unsigned int VodspAEC_En, unsigned int AEC_mode)\r
806 {\r
807         int  ret = 0;\r
808 \r
809         \r
810         if (VodspAEC_En != 0)\r
811         {       \r
812 \r
813                 //enable power of VODSP I2C interface & VODSP interface\r
814                 rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD3,PWR_VODSP_INTERFACE|PWR_I2C_FOR_VODSP,PWR_VODSP_INTERFACE|PWR_I2C_FOR_VODSP);\r
815                 //enable power of VODSP I2S interface \r
816                 rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD1,PWR_I2S_INTERFACE,PWR_I2S_INTERFACE);    \r
817                 //select input/output of VODSP AEC\r
818                 set_vodsp_aec_path(codec, AEC_mode);            \r
819 \r
820         }\r
821         else\r
822         {\r
823                 //disable VODSP AEC path\r
824                 set_vodsp_aec_path(codec, VODSP_AEC_DISABLE);\r
825                 //set VODSP AEC to power down mode                      \r
826                 rt5625_write_mask(codec, RT5625_VODSP_CTL,0,VODSP_NO_PD_MODE_ENA);\r
827                 //disable power of VODSP I2C interface & VODSP interface\r
828                 rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD3,0,PWR_VODSP_INTERFACE|PWR_I2C_FOR_VODSP);                                \r
829         }\r
830 \r
831         return ret;\r
832 }\r
833 \r
834 static void rt5625_aec_config(struct snd_soc_codec *codec, unsigned int mode)\r
835 {\r
836         DBG("rt5625_aec_config %d\n",mode);\r
837 \r
838         if (mode == VODSP_AEC_DISABLE)\r
839         {\r
840                 enable_vodsp_aec(codec,0, mode);        \r
841                 /*disable LDO power*/\r
842                 rt5625_write_mask(codec, RT5625_LDO_CTRL,0,LDO_ENABLE);\r
843         }\r
844         else\r
845         {\r
846                 init_vodsp_aec(codec);\r
847         \r
848                 enable_vodsp_aec(codec,1, mode);                \r
849         }\r
850 }\r
851 //****************************************************************************************************************\r
852 //*\r
853 //*function:disable rt5625's function.\r
854 //*\r
855 //*\r
856 //****************************************************************************************************************\r
857 static int rt5625_func_aec_disable(struct snd_soc_codec *codec,int mode)\r
858 {\r
859 \r
860         switch(mode)\r
861         {\r
862                 case RT5625_AEC_PCM_IN_OUT:\r
863                 case RT5625_AEC_IIS_IN_OUT:\r
864                 case RT5625_AEC_ANALOG_IN_OUT:\r
865                         \r
866                         rt5625_aec_config(codec,VODSP_AEC_DISABLE);     //disable AEC function and path\r
867                         \r
868                 break;\r
869                 \r
870                 default:\r
871 \r
872                 break;\r
873         }\r
874 \r
875         return 0;\r
876 }\r
877 \r
878 \r
879 static int rt5625_get_dsp_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)\r
880 {\r
881         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);\r
882          /*cause we choose bit[0][1] to store the mode type*/\r
883         int mode = (rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC)) & 0x03;  \r
884 \r
885         ucontrol->value.integer.value[0] = mode;\r
886         return 0;\r
887 }\r
888 \r
889 \r
890 static int rt5625_set_dsp_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)\r
891 {\r
892         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);\r
893         u16 Virtual_reg = rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC);\r
894         int rt5625_mode=(Virtual_reg)&0x03;\r
895 \r
896         DBG("rt5625_mode=%d,value[0]=%ld,Virtual_reg=%x\n",rt5625_mode,ucontrol->value.integer.value[0],Virtual_reg);\r
897 \r
898         if ( rt5625_mode == ucontrol->value.integer.value[0])\r
899                 return 0;\r
900 \r
901         switch(ucontrol->value.integer.value[0])\r
902         {\r
903                 case RT5625_AEC_PCM_IN_OUT:\r
904 \r
905                         rt5625_aec_config(codec,PCM_IN_PCM_OUT);//enable AEC PCM in/out function and path\r
906 \r
907                 break;\r
908 \r
909                 case RT5625_AEC_IIS_IN_OUT:\r
910 \r
911                         rt5625_aec_config(codec,DAC_IN_ADC_OUT);//enable AEC IIS in/out function and path\r
912 \r
913                 break;\r
914 \r
915                 case RT5625_AEC_ANALOG_IN_OUT:\r
916                         \r
917                         rt5625_aec_config(codec,ANALOG_IN_ANALOG_OUT);//enable AEC analog in/out function and path\r
918                         \r
919                 break;\r
920 \r
921                 case RT5625_AEC_DISABLE:\r
922         \r
923                         rt5625_func_aec_disable(codec,rt5625_mode);             //disable previous select function.     \r
924         \r
925                 break;  \r
926 \r
927                 default:\r
928 \r
929                 break;\r
930         }\r
931 \r
932         Virtual_reg &= 0xfffc;\r
933         Virtual_reg |= (ucontrol->value.integer.value[0]);\r
934         rt5625_write(codec, VIRTUAL_REG_FOR_MISC_FUNC, Virtual_reg);\r
935 \r
936         DBG("2rt5625_mode=%d,value[0]=%ld,Virtual_reg=%x\n",rt5625_mode,ucontrol->value.integer.value[0],Virtual_reg);\r
937         return 0;\r
938 }\r
939 \r
940 static int rt5625_dump_dsp_reg(struct snd_soc_codec *codec)\r
941 {\r
942         int i;\r
943 \r
944         rt5625_write_mask(codec, RT5625_VODSP_CTL, VODSP_NO_PD_MODE_ENA,VODSP_NO_PD_MODE_ENA);\r
945         for (i = 0; i < SET_VODSP_REG_INIT_NUM; i++) {\r
946                 rt5625_read_vodsp_reg(codec, VODSP_AEC_Init_Value[i].VoiceDSPIndex);\r
947         }\r
948         return 0;\r
949 }\r
950 \r
951 \r
952 static int rt5625_dump_dsp_put(struct snd_kcontrol *kcontrol, \r
953                 struct snd_ctl_elem_value *ucontrol)\r
954 {\r
955         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);\r
956         int mode = rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC);\r
957 \r
958         mode &= ~(0x01 << 8);\r
959         mode |= (ucontrol->value.integer.value[0] << 8);\r
960         rt5625_write(codec, VIRTUAL_REG_FOR_MISC_FUNC, mode);\r
961         rt5625_dump_dsp_reg(codec);\r
962         \r
963         return 0;\r
964 }\r
965 \r
966 static const struct snd_kcontrol_new rt5625_snd_controls[] = {\r
967 SOC_ENUM_EXT("rt5625 aec mode sel", rt5625_enum[0], rt5625_get_dsp_mode, rt5625_set_dsp_mode),\r
968 SOC_ENUM("SPK Amp Type", rt5625_enum[1]),\r
969 SOC_ENUM("Left SPK Source", rt5625_enum[2]),\r
970 SOC_ENUM("SPK Amp Ratio", rt5625_enum[7]),\r
971 SOC_ENUM("Mic1 Boost", rt5625_enum[8]),\r
972 SOC_ENUM("Mic2 Boost", rt5625_enum[9]),\r
973 SOC_ENUM("Dmic Boost", rt5625_enum[10]),\r
974 SOC_ENUM("ADCR Func", rt5625_enum[11]),\r
975 SOC_DOUBLE("RK4", RT5625_STEREO_DAC_VOL, 8, 0, 63, 1),\r
976 SOC_DOUBLE("LineIn Playback Volume", RT5625_LINE_IN_VOL, 8, 0, 31, 1),\r
977 SOC_SINGLE("Phone Playback Volume", RT5625_PHONEIN_VOL, 8, 31, 1),\r
978 SOC_SINGLE("Mic1 Playback Volume", RT5625_MIC_VOL, 8, 31, 1),\r
979 SOC_SINGLE("Mic2 Playback Volume", RT5625_MIC_VOL, 0, 31, 1),\r
980 SOC_DOUBLE("PCM Capture Volume", RT5625_ADC_REC_GAIN, 8, 0, 31, 1),\r
981 SOC_DOUBLE("RK3", RT5625_SPK_OUT_VOL, 8, 0, 31, 1),\r
982 SOC_DOUBLE("RK2", RT5625_SPK_OUT_VOL, 15, 7, 1, 1),\r
983 SOC_DOUBLE("RKA", RT5625_HP_OUT_VOL, 8, 0, 31, 1),\r
984 SOC_DOUBLE("RK9", RT5625_HP_OUT_VOL, 15, 7, 1, 1),\r
985 SOC_DOUBLE("RKD", RT5625_AUX_OUT_VOL, 8, 0, 31, 1),\r
986 SOC_DOUBLE("RKC", RT5625_AUX_OUT_VOL, 15, 7, 1, 1),\r
987 SOC_DOUBLE("ADC Record Gain", RT5625_ADC_REC_GAIN, 8, 0, 31, 0),\r
988 SOC_SINGLE_EXT("VoDSP Dump", VIRTUAL_REG_FOR_MISC_FUNC, 8, 1, 0,\r
989                         snd_soc_get_volsw, rt5625_dump_dsp_put),\r
990 #if (RT5625_EQ_FUNC_ENA==1)                     \r
991 SOC_ENUM_EXT("EQ Mode", rt5625_enum[12], snd_soc_get_enum_double, rt5625_eq_sel_put),                           \r
992 #endif\r
993 };\r
994 \r
995 static int rt5625_add_controls(struct snd_soc_codec *codec)\r
996 {\r
997         int err, i;\r
998 \r
999         for (i = 0; i < ARRAY_SIZE(rt5625_snd_controls); i++){\r
1000                 err = snd_ctl_add(codec->card, \r
1001                                 snd_soc_cnew(&rt5625_snd_controls[i],\r
1002                                                 codec, NULL));\r
1003                 if (err < 0)\r
1004                         return err;\r
1005         }\r
1006         return 0;\r
1007 }\r
1008 \r
1009 static void hp_depop_mode2(struct snd_soc_codec *codec)\r
1010 {\r
1011         rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD1, PWR_SOFTGEN_EN, PWR_SOFTGEN_EN);\r
1012         rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD3, PWR_HP_R_OUT_VOL|PWR_HP_L_OUT_VOL,\r
1013                           PWR_HP_R_OUT_VOL|PWR_HP_L_OUT_VOL);\r
1014         rt5625_write(codec, RT5625_MISC_CTRL,HP_DEPOP_MODE2_EN);\r
1015 \r
1016         DBG("delay 500 msec\n");\r
1017 \r
1018         schedule_timeout_uninterruptible(msecs_to_jiffies(500));\r
1019                 \r
1020 \r
1021         rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD1, PWR_HP_OUT_AMP|PWR_HP_OUT_ENH_AMP,\r
1022                           PWR_HP_OUT_AMP|PWR_HP_OUT_ENH_AMP);\r
1023         //rt5625_write_mask(codec, RT5625_MISC_CTRL, 0, HP_DEPOP_MODE2_EN);\r
1024 \r
1025 }\r
1026 \r
1027 //enable depop function for mute/unmute\r
1028 static void hp_mute_unmute_depop(struct snd_soc_codec *codec,int mute)\r
1029 {\r
1030         if(mute)\r
1031         {\r
1032                 rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD1, PWR_SOFTGEN_EN, PWR_SOFTGEN_EN);\r
1033                 rt5625_write(codec, RT5625_MISC_CTRL,M_UM_DEPOP_EN|HP_R_M_UM_DEPOP_EN|HP_L_M_UM_DEPOP_EN);\r
1034                 //Mute headphone right/left channel\r
1035                 rt5625_write_mask(codec,RT5625_HP_OUT_VOL,RT_L_MUTE|RT_R_MUTE,RT_L_MUTE|RT_R_MUTE);     \r
1036                 mdelay(50);\r
1037         }\r
1038         else\r
1039         {\r
1040                 rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD1, PWR_SOFTGEN_EN, PWR_SOFTGEN_EN);\r
1041                 rt5625_write(codec, RT5625_MISC_CTRL, M_UM_DEPOP_EN|HP_R_M_UM_DEPOP_EN|HP_L_M_UM_DEPOP_EN);\r
1042                 //unMute headphone right/left channel\r
1043                 rt5625_write_mask(codec,RT5625_HP_OUT_VOL,0,RT_L_MUTE|RT_R_MUTE);       \r
1044                 mdelay(50);\r
1045         }\r
1046 \r
1047 }\r
1048 \r
1049 \r
1050 /*\r
1051  * _DAPM_ Controls\r
1052  */\r
1053  /*Left ADC Rec mixer*/\r
1054  /*Left ADC Rec mixer*/\r
1055 static const struct snd_kcontrol_new rt5625_left_adc_rec_mixer_controls[] = {\r
1056 SOC_DAPM_SINGLE("RKK", RT5625_ADC_REC_MIXER, 14, 1, 1),\r
1057 SOC_DAPM_SINGLE("Mic2 Capture Switch", RT5625_ADC_REC_MIXER, 13, 1, 1),\r
1058 SOC_DAPM_SINGLE("LineIn Capture Switch", RT5625_ADC_REC_MIXER, 12, 1, 1),\r
1059 SOC_DAPM_SINGLE("RKL", RT5625_ADC_REC_MIXER, 11, 1, 1),\r
1060 SOC_DAPM_SINGLE("HP Mixer Capture Switch", RT5625_ADC_REC_MIXER, 10, 1, 1),\r
1061 SOC_DAPM_SINGLE("SPK Mixer Capture Switch", RT5625_ADC_REC_MIXER, 9, 1, 1),\r
1062 SOC_DAPM_SINGLE("MoNo Mixer Capture Switch", RT5625_ADC_REC_MIXER, 8, 1, 1),\r
1063 \r
1064 };\r
1065 \r
1066 /*Left ADC Rec mixer*/\r
1067 static const struct snd_kcontrol_new rt5625_right_adc_rec_mixer_controls[] = {\r
1068 SOC_DAPM_SINGLE("RKK", RT5625_ADC_REC_MIXER, 6, 1, 1),\r
1069 SOC_DAPM_SINGLE("Mic2 Capture Switch", RT5625_ADC_REC_MIXER, 5, 1, 1),\r
1070 SOC_DAPM_SINGLE("LineIn Capture Switch", RT5625_ADC_REC_MIXER, 4, 1, 1),\r
1071 SOC_DAPM_SINGLE("RKL", RT5625_ADC_REC_MIXER, 3, 1, 1),\r
1072 SOC_DAPM_SINGLE("HP Mixer Capture Switch", RT5625_ADC_REC_MIXER, 2, 1, 1),\r
1073 SOC_DAPM_SINGLE("SPK Mixer Capture Switch", RT5625_ADC_REC_MIXER, 1, 1, 1),\r
1074 SOC_DAPM_SINGLE("MoNo Mixer Capture Switch", RT5625_ADC_REC_MIXER, 0, 1, 1),\r
1075 };\r
1076 \r
1077 /*Left hpmixer mixer*/\r
1078 static const struct snd_kcontrol_new rt5625_left_hp_mixer_controls[] = {\r
1079 SOC_DAPM_SINGLE("ADC Playback Switch", RT5625_ADC_REC_GAIN, 15, 1, 1),\r
1080 SOC_DAPM_SINGLE("LineIn Playback Switch", HPL_MIXER, 0, 1, 0),\r
1081 SOC_DAPM_SINGLE("RKJ", HPL_MIXER, 1, 1, 0),\r
1082 SOC_DAPM_SINGLE("RKI", HPL_MIXER, 2, 1, 0),\r
1083 SOC_DAPM_SINGLE("Mic2 Playback Switch", HPL_MIXER, 3, 1, 0),\r
1084 SOC_DAPM_SINGLE("RKM", HPL_MIXER, 4, 1, 0),\r
1085 SOC_DAPM_SINGLE("RKH", RT5625_DAC_AND_MIC_CTRL, 3, 1, 1),\r
1086 \r
1087 };\r
1088 \r
1089 /*Right hpmixer mixer*/\r
1090 static const struct snd_kcontrol_new rt5625_right_hp_mixer_controls[] = {\r
1091 SOC_DAPM_SINGLE("ADC Playback Switch", RT5625_ADC_REC_GAIN, 7, 1, 1),\r
1092 SOC_DAPM_SINGLE("LineIn Playback Switch", HPR_MIXER, 0, 1, 0),\r
1093 SOC_DAPM_SINGLE("RKJ", HPR_MIXER, 1, 1, 0),\r
1094 SOC_DAPM_SINGLE("RKI", HPR_MIXER, 2, 1, 0),\r
1095 SOC_DAPM_SINGLE("Mic2 Playback Switch", HPR_MIXER, 3, 1, 0),\r
1096 SOC_DAPM_SINGLE("RKM", HPR_MIXER, 4, 1, 0),\r
1097 SOC_DAPM_SINGLE("RKH", RT5625_DAC_AND_MIC_CTRL, 2, 1, 1),\r
1098 \r
1099 };\r
1100 \r
1101 /*mono mixer*/\r
1102 static const struct snd_kcontrol_new rt5625_mono_mixer_controls[] = {\r
1103 SOC_DAPM_SINGLE("ADCL Playback Switch", RT5625_ADC_REC_GAIN, 14, 1, 1),\r
1104 SOC_DAPM_SINGLE("ADCR Playback Switch", RT5625_ADC_REC_GAIN, 6, 1, 1),\r
1105 SOC_DAPM_SINGLE("Line Mixer Playback Switch", RT5625_LINE_IN_VOL, 13, 1, 1),\r
1106 SOC_DAPM_SINGLE("RKI", RT5625_DAC_AND_MIC_CTRL, 13, 1, 1),\r
1107 SOC_DAPM_SINGLE("Mic2 Playback Switch", RT5625_DAC_AND_MIC_CTRL, 9, 1, 1),\r
1108 SOC_DAPM_SINGLE("RKG", RT5625_DAC_AND_MIC_CTRL, 0, 1, 1),\r
1109 SOC_DAPM_SINGLE("RKM", RT5625_VOICE_DAC_OUT_VOL, 13, 1, 1),\r
1110 };\r
1111 \r
1112 /*speaker mixer*/\r
1113 static const struct snd_kcontrol_new rt5625_spk_mixer_controls[] = {\r
1114 SOC_DAPM_SINGLE("Line Mixer Playback Switch", RT5625_LINE_IN_VOL, 14, 1, 1),    \r
1115 SOC_DAPM_SINGLE("RKJ", RT5625_PHONEIN_VOL, 14, 1, 1),\r
1116 SOC_DAPM_SINGLE("RKI", RT5625_DAC_AND_MIC_CTRL, 14, 1, 1),\r
1117 SOC_DAPM_SINGLE("Mic2 Playback Switch", RT5625_DAC_AND_MIC_CTRL, 10, 1, 1),\r
1118 SOC_DAPM_SINGLE("RKG", RT5625_DAC_AND_MIC_CTRL, 1, 1, 1),\r
1119 SOC_DAPM_SINGLE("RKM", RT5625_VOICE_DAC_OUT_VOL, 14, 1, 1),\r
1120 };\r
1121 \r
1122 static int mixer_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event)\r
1123 {\r
1124         struct snd_soc_codec *codec = w->codec;\r
1125         unsigned int l, r;\r
1126 \r
1127         DBG("enter %s\n", __func__);\r
1128 \r
1129         l= rt5625_read(codec, HPL_MIXER);\r
1130         r = rt5625_read(codec, HPR_MIXER);\r
1131         \r
1132         if ((l & 0x1) || (r & 0x1))\r
1133                 rt5625_write_mask(codec, 0x0a, 0x0000, 0x8000);\r
1134         else\r
1135                 rt5625_write_mask(codec, 0x0a, 0x8000, 0x8000);\r
1136 \r
1137         if ((l & 0x2) || (r & 0x2))\r
1138                 rt5625_write_mask(codec, 0x08, 0x0000, 0x8000);\r
1139         else\r
1140                 rt5625_write_mask(codec, 0x08, 0x8000, 0x8000);\r
1141 \r
1142         if ((l & 0x4) || (r & 0x4))\r
1143                 rt5625_write_mask(codec, 0x10, 0x0000, 0x8000);\r
1144         else\r
1145                 rt5625_write_mask(codec, 0x10, 0x8000, 0x8000);\r
1146 \r
1147         if ((l & 0x8) || (r & 0x8))\r
1148                 rt5625_write_mask(codec, 0x10, 0x0000, 0x0800);\r
1149         else\r
1150                 rt5625_write_mask(codec, 0x10, 0x0800, 0x0800);\r
1151 \r
1152         if ((l & 0x10) || (r & 0x10))\r
1153                 rt5625_write_mask(codec, 0x18, 0x0000, 0x8000);\r
1154         else\r
1155                 rt5625_write_mask(codec, 0x18, 0x8000, 0x8000);\r
1156 \r
1157         return 0;\r
1158 }\r
1159 \r
1160 \r
1161 /*\r
1162  *      bit[0][1] use for aec control\r
1163  *      bit[2][3] for ADCR func\r
1164  *      bit[4] for SPKL pga\r
1165  *      bit[5] for SPKR pga\r
1166  *      bit[6] for hpl pga\r
1167  *      bit[7] for hpr pga\r
1168  */\r
1169 static int spk_pga_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event)\r
1170  {\r
1171         struct snd_soc_codec *codec = w->codec;\r
1172         int reg;\r
1173         \r
1174         DBG("enter %s\n", __func__);\r
1175         reg = rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC) & (0x3 << 4);\r
1176         if ((reg >> 4) != 0x3 && reg != 0)\r
1177                 return 0;\r
1178 \r
1179         switch (event)\r
1180         {\r
1181                 case SND_SOC_DAPM_POST_PMU:\r
1182                         DBG("after virtual spk power up!\n");\r
1183                         rt5625_write_mask(codec, 0x3e, 0x3000, 0x3000);\r
1184                         rt5625_write_mask(codec, 0x02, 0x0000, 0x8080);\r
1185                         rt5625_write_mask(codec, 0x3a, 0x0400, 0x0400);//power on spk amp\r
1186                         break;\r
1187                 case SND_SOC_DAPM_POST_PMD:\r
1188                         DBG("aftet virtual spk power down!\n");\r
1189                         rt5625_write_mask(codec, 0x3a, 0x0000, 0x0400);//power off spk amp\r
1190                         rt5625_write_mask(codec, 0x02, 0x8080, 0x8080);\r
1191                         rt5625_write_mask(codec, 0x3e, 0x0000, 0x3000);                 \r
1192                         break;\r
1193                 default:\r
1194                         return 0;\r
1195         }\r
1196         return 0;\r
1197 }\r
1198 \r
1199 \r
1200 \r
1201 \r
1202 static int hp_pga_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event)\r
1203 {\r
1204         struct snd_soc_codec *codec = w->codec;\r
1205         int reg;\r
1206 \r
1207         DBG("enter %s\n", __func__);\r
1208 \r
1209         reg = rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC) & (0x3 << 6);\r
1210         if ((reg >> 6) != 0x3 && reg != 0)\r
1211                 return 0;\r
1212         \r
1213         switch (event)\r
1214         {\r
1215                 case SND_SOC_DAPM_POST_PMD:\r
1216 \r
1217                         DBG("aftet virtual hp power down!\n");\r
1218 \r
1219                         hp_mute_unmute_depop(codec,1);//mute hp\r
1220                         rt5625_write_mask(codec, 0x3a, 0x0000, 0x0300);\r
1221                         rt5625_write_mask(codec, 0x3e, 0x0000, 0x0c00);                 \r
1222                         break;\r
1223 \r
1224                 case SND_SOC_DAPM_POST_PMU:     \r
1225 \r
1226                         DBG("after virtual hp power up!\n");\r
1227                         hp_depop_mode2(codec);\r
1228                         hp_mute_unmute_depop(codec,0);//unmute hp\r
1229                         break;\r
1230 \r
1231                 default:\r
1232                         return 0;\r
1233         }       \r
1234 \r
1235         return 0;\r
1236 }\r
1237 \r
1238 \r
1239 \r
1240 static int aux_pga_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event)\r
1241 {\r
1242         return 0;\r
1243 }\r
1244 \r
1245 /*SPKOUT Mux*/\r
1246 static const struct snd_kcontrol_new rt5625_spkout_mux_out_controls = \r
1247 SOC_DAPM_ENUM("Route", rt5625_enum[3]);\r
1248 \r
1249 /*HPLOUT MUX*/\r
1250 static const struct snd_kcontrol_new rt5625_hplout_mux_out_controls = \r
1251 SOC_DAPM_ENUM("Route", rt5625_enum[4]);\r
1252 \r
1253 /*HPROUT MUX*/\r
1254 static const struct snd_kcontrol_new rt5625_hprout_mux_out_controls = \r
1255 SOC_DAPM_ENUM("Route", rt5625_enum[5]);\r
1256 /*AUXOUT MUX*/\r
1257 static const struct snd_kcontrol_new rt5625_auxout_mux_out_controls = \r
1258 SOC_DAPM_ENUM("Route", rt5625_enum[6]);\r
1259 \r
1260 static const struct snd_soc_dapm_widget rt5625_dapm_widgets[] = {\r
1261 SND_SOC_DAPM_INPUT("Left LineIn"),\r
1262 SND_SOC_DAPM_INPUT("Right LineIn"),\r
1263 SND_SOC_DAPM_INPUT("Phone"),\r
1264 SND_SOC_DAPM_INPUT("Mic1"),\r
1265 SND_SOC_DAPM_INPUT("Mic2"),\r
1266 \r
1267 SND_SOC_DAPM_PGA("Mic1 Boost", RT5625_PWR_MANAG_ADD3, 1, 0, NULL, 0),\r
1268 SND_SOC_DAPM_PGA("Mic2 Boost", RT5625_PWR_MANAG_ADD3, 0, 0, NULL, 0),\r
1269 \r
1270 SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback DAC", RT5625_PWR_MANAG_ADD2, 9, 0),\r
1271 SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback DAC", RT5625_PWR_MANAG_ADD2, 8, 0),\r
1272 SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback DAC", RT5625_PWR_MANAG_ADD2, 10, 0),\r
1273 \r
1274 SND_SOC_DAPM_PGA("Left LineIn PGA", RT5625_PWR_MANAG_ADD3, 7, 0, NULL, 0),\r
1275 SND_SOC_DAPM_PGA("Right LineIn PGA", RT5625_PWR_MANAG_ADD3, 6, 0, NULL, 0),\r
1276 SND_SOC_DAPM_PGA("Phone PGA", RT5625_PWR_MANAG_ADD3, 5, 0, NULL, 0),\r
1277 SND_SOC_DAPM_PGA("Mic1 PGA", RT5625_PWR_MANAG_ADD3, 3, 0, NULL, 0),\r
1278 SND_SOC_DAPM_PGA("Mic2 PGA", RT5625_PWR_MANAG_ADD3, 2, 0, NULL, 0),\r
1279 SND_SOC_DAPM_PGA("VoDAC PGA", RT5625_PWR_MANAG_ADD1, 7, 0, NULL, 0),\r
1280 SND_SOC_DAPM_MIXER("RKE", RT5625_PWR_MANAG_ADD2, 1, 0,\r
1281         &rt5625_left_adc_rec_mixer_controls[0], ARRAY_SIZE(rt5625_left_adc_rec_mixer_controls)),\r
1282 SND_SOC_DAPM_MIXER("RKF", RT5625_PWR_MANAG_ADD2, 0, 0,\r
1283         &rt5625_right_adc_rec_mixer_controls[0], ARRAY_SIZE(rt5625_right_adc_rec_mixer_controls)),\r
1284 SND_SOC_DAPM_MIXER_E("RK5", RT5625_PWR_MANAG_ADD2, 5, 0,\r
1285         &rt5625_left_hp_mixer_controls[0], ARRAY_SIZE(rt5625_left_hp_mixer_controls),\r
1286         mixer_event, SND_SOC_DAPM_POST_REG),\r
1287 SND_SOC_DAPM_MIXER_E("RK6", RT5625_PWR_MANAG_ADD2, 4, 0,\r
1288         &rt5625_right_hp_mixer_controls[0], ARRAY_SIZE(rt5625_right_hp_mixer_controls),\r
1289         mixer_event, SND_SOC_DAPM_POST_REG),\r
1290 SND_SOC_DAPM_MIXER("RK13", RT5625_PWR_MANAG_ADD2, 2, 0, \r
1291         &rt5625_mono_mixer_controls[0], ARRAY_SIZE(rt5625_mono_mixer_controls)),\r
1292 SND_SOC_DAPM_MIXER("RK12", RT5625_PWR_MANAG_ADD2, 3, 0,\r
1293         &rt5625_spk_mixer_controls[0], ARRAY_SIZE(rt5625_spk_mixer_controls)),  \r
1294 SND_SOC_DAPM_MIXER("RK11", SND_SOC_NOPM, 0, 0, NULL, 0),\r
1295 SND_SOC_DAPM_MIXER("DAC Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),\r
1296 SND_SOC_DAPM_MIXER("Line Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),\r
1297 \r
1298 SND_SOC_DAPM_MUX("RK1", SND_SOC_NOPM, 0, 0, &rt5625_spkout_mux_out_controls),\r
1299 SND_SOC_DAPM_MUX("RK7", SND_SOC_NOPM, 0, 0, &rt5625_hplout_mux_out_controls),\r
1300 SND_SOC_DAPM_MUX("RK8", SND_SOC_NOPM, 0, 0, &rt5625_hprout_mux_out_controls),\r
1301 SND_SOC_DAPM_MUX("RKB", SND_SOC_NOPM, 0, 0, &rt5625_auxout_mux_out_controls),\r
1302 \r
1303 SND_SOC_DAPM_PGA_E("SPKL Out PGA", VIRTUAL_REG_FOR_MISC_FUNC, 4, 0, NULL, 0,\r
1304                                 spk_pga_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),\r
1305 SND_SOC_DAPM_PGA_E("SPKR Out PGA", VIRTUAL_REG_FOR_MISC_FUNC, 5, 0, NULL, 0,\r
1306                                 spk_pga_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),\r
1307 SND_SOC_DAPM_PGA_E("HPL Out PGA",VIRTUAL_REG_FOR_MISC_FUNC, 6, 0, NULL, 0, \r
1308                                 hp_pga_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),\r
1309 SND_SOC_DAPM_PGA_E("HPR Out PGA",VIRTUAL_REG_FOR_MISC_FUNC, 7, 0, NULL, 0, \r
1310                                 hp_pga_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),\r
1311 SND_SOC_DAPM_PGA_E("AUX Out PGA",RT5625_PWR_MANAG_ADD3, 14, 0, NULL, 0, \r
1312                                 aux_pga_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),\r
1313                                 \r
1314 SND_SOC_DAPM_ADC("Left ADC", "Left ADC HiFi Capture", RT5625_PWR_MANAG_ADD2, 7, 0),\r
1315 SND_SOC_DAPM_ADC("Right ADC", "Right ADC HiFi Capture", RT5625_PWR_MANAG_ADD2, 6, 0),\r
1316 SND_SOC_DAPM_OUTPUT("SPKL"),\r
1317 SND_SOC_DAPM_OUTPUT("SPKR"),\r
1318 SND_SOC_DAPM_OUTPUT("HPL"),\r
1319 SND_SOC_DAPM_OUTPUT("HPR"),\r
1320 SND_SOC_DAPM_OUTPUT("AUX"),\r
1321 SND_SOC_DAPM_MICBIAS("Mic1 Bias", RT5625_PWR_MANAG_ADD1, 3, 0),\r
1322 SND_SOC_DAPM_MICBIAS("Mic2 Bias", RT5625_PWR_MANAG_ADD1, 2, 0),\r
1323 };\r
1324 \r
1325 static const struct snd_soc_dapm_route audio_map[] = {\r
1326                 /*output*/\r
1327                 {"SPKL", NULL, "SPKL Out PGA"},\r
1328                 {"SPKR", NULL, "SPKR Out PGA"},\r
1329                 {"HPL", NULL, "HPL Out PGA"},\r
1330                 {"HPR", NULL, "HPR Out PGA"},\r
1331                 {"AUX", NULL, "AUX Out PGA"},\r
1332 \r
1333                 /*Input PGA*/\r
1334                 {"Left LineIn PGA", NULL, "Left LineIn"},\r
1335                 {"Right LineIn PGA", NULL, "Right LineIn"},\r
1336                 {"Phone PGA", NULL, "Phone"},\r
1337                 {"Mic1 Boost", NULL, "Mic1"},\r
1338                 {"Mic2 Boost", NULL, "Mic2"},\r
1339                 {"Mic1 PGA", NULL, "Mic1"},\r
1340                 {"Mic2 PGA", NULL, "Mic2"},\r
1341                 {"VoDAC PGA", NULL, "Voice DAC"},\r
1342                 \r
1343                 /*Left ADC mixer*/\r
1344                 {"RKE", "LineIn Capture Switch", "Left LineIn"},\r
1345                 {"RKE", "RKL", "Phone"},\r
1346                 {"RKE", "RKK", "Mic1 Boost"},\r
1347                 {"RKE", "Mic2 Capture Switch", "Mic2 Boost"},\r
1348                 {"RKE", "HP Mixer Capture Switch", "RK5"},\r
1349                 {"RKE", "SPK Mixer Capture Switch", "RK12"},\r
1350                 {"RKE", "MoNo Mixer Capture Switch", "RK13"},\r
1351 \r
1352                 /*Right ADC Mixer*/\r
1353                 {"RKF", "LineIn Capture Switch", "Right LineIn"},\r
1354                 {"RKF", "RKL", "Phone"},\r
1355                 {"RKF", "RKK", "Mic1 Boost"},\r
1356                 {"RKF", "Mic2 Capture Switch", "Mic2 Boost"},\r
1357                 {"RKF", "HP Mixer Capture Switch", "RK6"},\r
1358                 {"RKF", "SPK Mixer Capture Switch", "RK12"},\r
1359                 {"RKF", "MoNo Mixer Capture Switch", "RK13"},\r
1360                 \r
1361                 /*HPL mixer*/\r
1362                 {"RK5", "ADC Playback Switch", "RKE"},\r
1363                 {"RK5", "LineIn Playback Switch", "Left LineIn PGA"},\r
1364                 {"RK5", "RKJ", "Phone PGA"},\r
1365                 {"RK5", "RKI", "Mic1 PGA"},\r
1366                 {"RK5", "Mic2 Playback Switch", "Mic2 PGA"},\r
1367                 {"RK5", "RKH", "Left DAC"},\r
1368                 {"RK5", "RKM", "VoDAC PGA"},\r
1369 \r
1370                 /*DAC Mixer*/\r
1371                 {"DAC Mixer", NULL, "Left DAC"},\r
1372                 {"DAC Mixer", NULL, "Right DAC"},\r
1373 \r
1374                 /*line mixer*/\r
1375                 {"Line Mixer", NULL, "Left LineIn PGA"},\r
1376                 {"Line Mixer", NULL, "Right LineIn PGA"},\r
1377 \r
1378                 /*HPR mixer*/\r
1379                 {"RK6", "ADC Playback Switch", "RKF"},\r
1380                 {"RK6", "LineIn Playback Switch", "Right LineIn PGA"},\r
1381                 {"RK6", "RKH", "Right DAC"},\r
1382                 {"RK6", "RKJ", "Phone PGA"},\r
1383                 {"RK6", "RKI", "Mic1 PGA"},\r
1384                 {"RK6", "Mic2 Playback Switch", "Mic2 PGA"},\r
1385                 {"RK6", "RKM", "VoDAC PGA"},\r
1386 \r
1387                 /*spk mixer*/\r
1388                 {"RK12", "Line Mixer Playback Switch", "Line Mixer"},\r
1389                 {"RK12", "RKJ", "Phone PGA"},\r
1390                 {"RK12", "RKI", "Mic1 PGA"},\r
1391                 {"RK12", "Mic2 Playback Switch", "Mic2 PGA"},\r
1392                 {"RK12", "RKG", "DAC Mixer"},\r
1393                 {"RK12", "RKM", "VoDAC PGA"},\r
1394 \r
1395                 /*mono mixer*/\r
1396                 {"RK13", "Line Mixer Playback Switch", "Line Mixer"},\r
1397                 {"RK13", "ADCL Playback Switch","RKE"},\r
1398                 {"RK13", "ADCR Playback Switch","RKF"},\r
1399                 {"RK13", "RKI", "Mic1 PGA"},\r
1400                 {"RK13", "Mic2 Playback Switch", "Mic2 PGA"},\r
1401                 {"RK13", "RKG", "DAC Mixer"},\r
1402                 {"RK13", "RKM", "VoDAC PGA"},\r
1403                 \r
1404                 /*hp mixer*/\r
1405                 {"RK11", NULL, "RK5"},\r
1406                 {"RK11", NULL, "RK6"},\r
1407 \r
1408                 /*spkout mux*/\r
1409                 {"RK1", "RK11", "RK11"},\r
1410                 {"RK1", "RK12", "RK12"},\r
1411                 {"RK1", "RK13", "RK13"},\r
1412                 \r
1413                 /*hpl out mux*/\r
1414                 {"RK7", "RK71", "RK5"},\r
1415                 \r
1416                 /*hpr out mux*/\r
1417                 {"RK8", "RK81", "RK6"},\r
1418 \r
1419                 /*aux out mux*/\r
1420                 {"RKB", "RK11", "RK11"},\r
1421                 {"RKB", "RK12", "RK12"},\r
1422                 {"RKB", "RK13", "RK13"},\r
1423 \r
1424                 /*spkl out pga*/\r
1425                 {"SPKL Out PGA", NULL, "RK1"},\r
1426 \r
1427                 /*spkr out pga*/\r
1428                 {"SPKR Out PGA", NULL, "RK1"},\r
1429                 \r
1430                 /*hpl out pga*/\r
1431                 {"HPL Out PGA", NULL, "RK7"},\r
1432 \r
1433                 /*hpr out pga*/\r
1434                 {"HPR Out PGA", NULL, "RK8"},\r
1435 \r
1436                 /*aux out pga*/\r
1437                 {"AUX Out PGA", NULL, "RKB"}, \r
1438                 \r
1439                 /*left adc*/\r
1440                 {"Left ADC", NULL, "RKE"},\r
1441                 \r
1442                 /*right adc*/\r
1443                 {"Right ADC", NULL, "RKF"},\r
1444                 \r
1445 \r
1446 };\r
1447 \r
1448 \r
1449 static int rt5625_add_widgets(struct snd_soc_codec *codec)\r
1450 {\r
1451         snd_soc_dapm_new_controls(codec, rt5625_dapm_widgets, \r
1452                                 ARRAY_SIZE(rt5625_dapm_widgets));\r
1453         snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));\r
1454         snd_soc_dapm_new_widgets(codec);\r
1455 \r
1456         return 0;\r
1457 }\r
1458 \r
1459 struct _pll_div{\r
1460         u32 pll_in;\r
1461         u32 pll_out;\r
1462         u16 regvalue;\r
1463 };\r
1464 \r
1465 \r
1466 /**************************************************************\r
1467   *     watch out!\r
1468   *     our codec support you to select different source as pll input, but if you \r
1469   *     use both of the I2S audio interface and pcm interface instantially. \r
1470   *     The two DAI must have the same pll setting params, so you have to offer\r
1471   *     the same pll input, and set our codec's sysclk the same one, we suggest \r
1472   *     24576000.\r
1473   **************************************************************/\r
1474 static const struct _pll_div codec_master_pll1_div[] = {\r
1475                 \r
1476         {   2048000,  8192000,   0x0ea0},\r
1477         {   3686400,  8192000,   0x4e27},\r
1478         {  12000000,  8192000,   0x456b},\r
1479         {  13000000,  8192000,   0x495f},\r
1480         {  13100000,  8192000,   0x0320},\r
1481         {   2048000,  11289600,  0xf637},\r
1482         {   3686400,  11289600,  0x2f22},\r
1483         {  12000000,  11289600,  0x3e2f},\r
1484         {  13000000,  11289600,  0x4d5b},\r
1485         {  13100000,  11289600,  0x363b},\r
1486         {   2048000,  16384000,  0x1ea0},\r
1487         {   3686400,  16384000,  0x9e27},\r
1488         {  12000000,  16384000,  0x452b},\r
1489         {  13000000,  16384000,  0x542f},\r
1490         {  13100000,  16384000,  0x03a0},\r
1491         {   2048000,  16934400,  0xe625},\r
1492         {   3686400,  16934400,  0x9126},\r
1493         {  12000000,  16934400,  0x4d2c},\r
1494         {  13000000,  16934400,  0x742f},\r
1495         {  13100000,  16934400,  0x3c27},\r
1496         {   2048000,  22579200,  0x2aa0},\r
1497         {   3686400,  22579200,  0x2f20},\r
1498         {  12000000,  22579200,  0x7e2f},\r
1499         {  13000000,  22579200,  0x742f},\r
1500         {  13100000,  22579200,  0x3c27},\r
1501         {   2048000,  24576000,  0x2ea0},\r
1502         {   3686400,  24576000,  0xee27},\r
1503         {  11289600,  24576000,  0x950F},\r
1504         {  12000000,  24576000,  0x2915},\r
1505         {  12288000,  24576000,  0x0600},\r
1506         {  13000000,  24576000,  0x772e},\r
1507         {  13100000,  24576000,  0x0d20},\r
1508         {  26000000,  24576000,  0x2027},\r
1509         {  26000000,  22579200,  0x392f},\r
1510         {  24576000,  22579200,  0x0921},\r
1511         {  24576000,  24576000,  0x02a0},\r
1512 };\r
1513 \r
1514 static const struct _pll_div codec_bclk_pll1_div[] = {\r
1515 \r
1516         {   256000,   4096000,  0x3ea0},\r
1517         {   352800,   5644800,  0x3ea0},\r
1518         {   512000,   8192000,  0x3ea0},\r
1519         {   705600,  11289600,  0x3ea0},\r
1520         {  1024000,  16384000,  0x3ea0},        \r
1521         {  1411200,  22579200,  0x3ea0},\r
1522         {  1536000,  24576000,  0x3ea0},        \r
1523         {  2048000,  16384000,  0x1ea0},        \r
1524         {  2822400,  22579200,  0x1ea0},\r
1525         {  3072000,  24576000,  0x1ea0},\r
1526         {   705600,  11289600,  0x3ea0},\r
1527         {   705600,   8467200,  0x3ab0},\r
1528         {  2822400,  11289600,  0x1ee0},\r
1529         {  3072000,  12288000,  0x1ee0},                        \r
1530 };\r
1531 \r
1532 static const struct _pll_div codec_vbclk_pll1_div[] = {\r
1533 \r
1534         {   256000,   4096000,  0x3ea0},\r
1535         {   352800,   5644800,  0x3ea0},\r
1536         {   512000,   8192000,  0x3ea0},\r
1537         {   705600,  11289600,  0x3ea0},\r
1538         {  1024000,  16384000,  0x3ea0},        \r
1539         {  1411200,  22579200,  0x3ea0},\r
1540         {  1536000,  24576000,  0x3ea0},        \r
1541         {  2048000,  16384000,  0x1ea0},        \r
1542         {  2822400,  22579200,  0x1ea0},\r
1543         {  3072000,  24576000,  0x1ea0},\r
1544         {   705600,  11289600,  0x3ea0},\r
1545         {   705600,   8467200,  0x3ab0},\r
1546 };\r
1547 \r
1548 \r
1549 struct _coeff_div_stereo {\r
1550         unsigned int mclk;\r
1551         unsigned int rate;\r
1552         unsigned int reg60;\r
1553         unsigned int reg62;\r
1554 };\r
1555 \r
1556 struct _coeff_div_voice {\r
1557         unsigned int mclk;\r
1558         unsigned int rate;\r
1559         unsigned int reg64;\r
1560 };\r
1561 \r
1562 static const struct _coeff_div_stereo coeff_div_stereo[] = {\r
1563 \r
1564         /*bclk is config to 32fs, if codec is choose to be slave mode , input bclk should be 32*fs */\r
1565         {24576000,  48000,  0x3174,  0x1010},      \r
1566         {12288000,  48000,  0x1174,  0x0000},\r
1567         {18432000,  48000,  0x2174,  0x1111},\r
1568         {36864000,  48000,  0x2274,  0x2020},\r
1569         {49152000,  48000,  0xf074,  0x3030},\r
1570         {24576000,  48000,  0x3172,  0x1010},\r
1571         {24576000,   8000,  0xB274,  0x2424},\r
1572         {24576000,  16000,  0xB174,  0x2222},\r
1573         {24576000,  32000,  0xB074,  0x2121},\r
1574         {22579200,  11025,  0X3374,  0x1414},\r
1575         {22579200,  22050,  0X3274,  0x1212},\r
1576         {22579200,  44100,  0X3174,  0x1010},\r
1577         {0, 0, 0, 0},\r
1578 };\r
1579 \r
1580 static const struct _coeff_div_voice coeff_div_voice[] = {\r
1581 \r
1582         /*bclk is config to 32fs, if codec is choose to be slave mode , input bclk should be 32*fs */\r
1583         {24576000,  16000,  0x2622}, \r
1584         {24576000,   8000,  0x2824},\r
1585         {0, 0, 0},\r
1586 };\r
1587 \r
1588 static int get_coeff(unsigned int mclk, unsigned int rate, int mode)\r
1589 {\r
1590         int i;\r
1591 \r
1592         DBG("get_coeff mclk = %d, rate = %d, mode = %d\n", mclk, rate, mode);\r
1593 \r
1594         if (!mode) {\r
1595                 for (i = 0; i < ARRAY_SIZE(coeff_div_stereo); i++) {\r
1596                         if ((coeff_div_stereo[i].rate == rate) && (coeff_div_stereo[i].mclk == mclk))\r
1597                                 return i;\r
1598                 }\r
1599         } else {\r
1600                 for (i = 0; i< ARRAY_SIZE(coeff_div_voice); i++) {\r
1601                         if ((coeff_div_voice[i].rate == rate) && (coeff_div_voice[i].mclk == mclk))\r
1602                                 return i;\r
1603                 }\r
1604         }\r
1605 \r
1606         printk("can't find a matched mclk and rate in %s\n", \r
1607                (mode ? "coeff_div_voice[]" : "coeff_div_audio[]"));\r
1608 \r
1609         return -EINVAL;\r
1610 }\r
1611 \r
1612 \r
1613 static int rt5625_codec_set_dai_pll(struct snd_soc_dai *codec_dai, \r
1614                 int pll_id, unsigned int freq_in, unsigned int freq_out)\r
1615 {\r
1616         int i;\r
1617         int ret = -EINVAL;\r
1618         struct snd_soc_codec *codec = codec_dai->codec;\r
1619 \r
1620         DBG("enter %s pll_id = %d freq_in = %d freq_out = %d\n",\r
1621                __func__, pll_id, freq_in, freq_out);\r
1622 \r
1623         if (pll_id < RT5625_PLL1_FROM_MCLK || pll_id > RT5625_PLL1_FROM_VBCLK)\r
1624                 return -EINVAL;\r
1625 \r
1626         if (!freq_in || !freq_out)\r
1627                 return 0;\r
1628 \r
1629         if (RT5625_PLL1_FROM_MCLK == pll_id) {\r
1630 \r
1631                 for (i = 0; i < ARRAY_SIZE(codec_master_pll1_div); i ++)\r
1632                 {\r
1633                         if ((freq_in == codec_master_pll1_div[i].pll_in) && (freq_out == codec_master_pll1_div[i].pll_out))\r
1634                         {\r
1635                                 rt5625_write(codec, RT5625_GEN_CTRL_REG2, 0x0000);  /*PLL source from MCLK*/\r
1636                                 rt5625_write(codec, RT5625_PLL_CTRL, codec_master_pll1_div[i].regvalue);  /*set pll code*/\r
1637                                 rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD2, 0x8000, 0x8000);  /*enable pll1 power*/\r
1638                                 rt5625_write_mask(codec, RT5625_GEN_CTRL_REG1, 0x8000, 0x8000);\r
1639                                 ret = 0;\r
1640                         }\r
1641                 }\r
1642         } else if (RT5625_PLL1_FROM_BCLK == pll_id) {\r
1643 \r
1644                 for (i = 0; i < ARRAY_SIZE(codec_bclk_pll1_div); i ++)\r
1645                 {\r
1646                         if ((freq_in == codec_bclk_pll1_div[i].pll_in) && (freq_out == codec_bclk_pll1_div[i].pll_out))\r
1647                         {\r
1648                                 rt5625_write(codec, RT5625_GEN_CTRL_REG2, 0x2000);  /*PLL source from BCLK*/\r
1649                                 rt5625_write(codec, RT5625_PLL_CTRL, codec_bclk_pll1_div[i].regvalue);  /*set pll1 code*/\r
1650                                 rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD2, 0x8000, 0x8000);  /*enable pll1 power*/\r
1651                                 rt5625_write_mask(codec, RT5625_GEN_CTRL_REG1, 0x8000, 0x8000);\r
1652                                 ret = 0;\r
1653                         }\r
1654                 }\r
1655         } else if (RT5625_PLL1_FROM_VBCLK == pll_id) {\r
1656 \r
1657                 for (i = 0; i < ARRAY_SIZE(codec_vbclk_pll1_div); i ++)\r
1658                 {\r
1659                         if ((freq_in == codec_vbclk_pll1_div[i].pll_in) && (freq_out == codec_vbclk_pll1_div[i].pll_out))\r
1660                         {\r
1661                                 rt5625_write(codec, RT5625_GEN_CTRL_REG2, 0x3000);  /*PLL source from VBCLK*/\r
1662                                 rt5625_write(codec, RT5625_PLL_CTRL, codec_vbclk_pll1_div[i].regvalue);  /*set pll1 code*/\r
1663                                 rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD2, 0x8000, 0x8000);  /*enable pll1 power*/\r
1664                                 rt5625_write_mask(codec, RT5625_GEN_CTRL_REG1, 0x8000, 0x8000);\r
1665                                 ret = 0;\r
1666                         }\r
1667                 }\r
1668         }\r
1669         return 0;\r
1670 }\r
1671 \r
1672 \r
1673 static int rt5625_hifi_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai, \r
1674                 int clk_id, unsigned int freq, int dir)\r
1675 {\r
1676         struct snd_soc_codec *codec = codec_dai->codec;\r
1677         struct rt5625_priv * rt5625 = codec->private_data;\r
1678 \r
1679         DBG("sysclk freq %u for audio i2s\n", freq);\r
1680         \r
1681         if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {\r
1682                 rt5625->stereo_sysclk = freq;\r
1683                 return 0;\r
1684         }\r
1685         \r
1686         printk("unsupported sysclk freq %u for audio i2s\n", freq);\r
1687                rt5625->stereo_sysclk=24576000;\r
1688         \r
1689         return 0;\r
1690 }\r
1691 \r
1692 static int rt5625_voice_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai, \r
1693                 int clk_id, unsigned int freq, int dir)\r
1694 {\r
1695         struct snd_soc_codec *codec = codec_dai->codec;\r
1696         struct rt5625_priv * rt5625 = codec->private_data;\r
1697 \r
1698         DBG("sysclk freq %u for voice pcm\n", freq);\r
1699 \r
1700         if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {\r
1701                 rt5625->voice_sysclk = freq;\r
1702                 return 0;\r
1703         }                       \r
1704 \r
1705         printk("unsupported sysclk freq %u for voice pcm\n", freq);\r
1706                rt5625->voice_sysclk = 24576000;\r
1707         \r
1708         return 0;\r
1709 }\r
1710 \r
1711 \r
1712 static int rt5625_hifi_pcm_hw_params(struct snd_pcm_substream *substream, \r
1713                         struct snd_pcm_hw_params *params,\r
1714                         struct snd_soc_dai *dai)\r
1715 {\r
1716         struct snd_soc_pcm_runtime *rtd = substream->private_data;\r
1717         struct snd_soc_device *socdev = rtd->socdev;\r
1718         struct snd_soc_codec *codec = socdev->card->codec;\r
1719         struct rt5625_priv *rt5625 = codec->private_data;\r
1720 \r
1721         unsigned int iface = rt5625_read(codec, RT5625_MAIN_SDP_CTRL) & 0xfff3;\r
1722         int rate = params_rate(params);\r
1723         int coeff = get_coeff(rt5625->stereo_sysclk, rate, 0);\r
1724         \r
1725         DBG("enter %s rate = %d \n", __func__, rate);\r
1726 \r
1727         switch (params_format(params))\r
1728         {\r
1729                 case SNDRV_PCM_FORMAT_S16_LE:\r
1730                         break;\r
1731                 case SNDRV_PCM_FORMAT_S20_3LE:\r
1732                         iface |= 0x0004;\r
1733                 case SNDRV_PCM_FORMAT_S24_LE:\r
1734                         iface |= 0x0008;\r
1735                 case SNDRV_PCM_FORMAT_S8:\r
1736                         iface |= 0x000c;\r
1737         }\r
1738 \r
1739         rt5625_write(codec, RT5625_MAIN_SDP_CTRL, iface);\r
1740         rt5625_write_mask(codec, 0x3a, 0xc801, 0xc801);   /*power i2s and dac ref*/\r
1741         if (coeff >= 0) {\r
1742                 rt5625_write(codec, RT5625_STEREO_DAC_CLK_CTRL1, coeff_div_stereo[coeff].reg60);\r
1743                 rt5625_write(codec, RT5625_STEREO_DAC_CLK_CTRL2, coeff_div_stereo[coeff].reg62);\r
1744         }\r
1745         \r
1746         return 0;\r
1747 }\r
1748 \r
1749 static int rt5625_voice_pcm_hw_params(struct snd_pcm_substream *substream, \r
1750                         struct snd_pcm_hw_params *params,\r
1751                         struct snd_soc_dai *dai)\r
1752 {\r
1753         struct snd_soc_pcm_runtime *rtd = substream->private_data;\r
1754         struct snd_soc_device *socdev = rtd->socdev;\r
1755         struct snd_soc_codec *codec = socdev->card->codec;\r
1756         struct rt5625_priv *rt5625 = codec->private_data;\r
1757         struct snd_soc_dapm_widget *w;\r
1758         unsigned int iface = rt5625_read(codec, RT5625_EXTEND_SDP_CTRL) & 0xfff3;\r
1759         int rate = params_rate(params);\r
1760         int coeff = get_coeff(rt5625->voice_sysclk, rate, 1);\r
1761 \r
1762         DBG("enter %s rate = %d \n", __func__, rate);\r
1763 \r
1764         list_for_each_entry(w, &codec->dapm_widgets, list)\r
1765         {\r
1766                 if (!w->sname)\r
1767                         continue;\r
1768                 if (!strcmp(w->name, "Right ADC"))\r
1769                         strcpy(w->sname, "Right ADC Voice Capture");\r
1770         }\r
1771         \r
1772         switch (params_format(params))\r
1773         {\r
1774                 case SNDRV_PCM_FORMAT_S16_LE:\r
1775                         break;\r
1776                 case SNDRV_PCM_FORMAT_S20_3LE:\r
1777                         iface |= 0x0004;\r
1778                 case SNDRV_PCM_FORMAT_S24_LE:\r
1779                         iface |= 0x0008;\r
1780                 case SNDRV_PCM_FORMAT_S8:\r
1781                         iface |= 0x000c;\r
1782         }\r
1783         rt5625_write_mask(codec, 0x3a, 0x0801, 0x0801);   /*power i2s and dac ref*/\r
1784         rt5625_write(codec, RT5625_EXTEND_SDP_CTRL, iface);\r
1785         if (coeff >= 0)\r
1786                 rt5625_write(codec, RT5625_VOICE_DAC_PCMCLK_CTRL1, coeff_div_voice[coeff].reg64);\r
1787 \r
1788         return 0;\r
1789 }\r
1790 \r
1791 \r
1792 static int rt5625_hifi_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)\r
1793 {\r
1794 \r
1795         struct snd_soc_codec *codec = codec_dai->codec;\r
1796         u16 iface = 0;\r
1797 \r
1798         DBG("enter %s fmt = %d\n", __func__, fmt);\r
1799 \r
1800         /*set master/slave interface*/\r
1801         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK)\r
1802         {\r
1803                 case SND_SOC_DAIFMT_CBM_CFM:\r
1804                         iface = 0x0000;\r
1805                         break;\r
1806                 case SND_SOC_DAIFMT_CBS_CFS:\r
1807                         iface = 0x8000;\r
1808                         break;\r
1809                 default:\r
1810                         return -EINVAL;\r
1811         }\r
1812 \r
1813         /*interface format*/\r
1814         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK)\r
1815         {\r
1816                 case SND_SOC_DAIFMT_I2S:\r
1817                         iface |= 0x0000;\r
1818                         break;\r
1819                 case SND_SOC_DAIFMT_LEFT_J:\r
1820                         iface |= 0x0001;\r
1821                         break;\r
1822                 case SND_SOC_DAIFMT_DSP_A:\r
1823                         iface |= 0x0002;\r
1824                         break;\r
1825                 case SND_SOC_DAIFMT_DSP_B:\r
1826                         iface |= 0x0003;\r
1827                         break;\r
1828                 default:\r
1829                         return -EINVAL;                 \r
1830         }\r
1831 \r
1832         /*clock inversion*/\r
1833         switch (fmt & SND_SOC_DAIFMT_INV_MASK)\r
1834         {\r
1835                 case SND_SOC_DAIFMT_NB_NF:\r
1836                         iface |= 0x0000;\r
1837                         break;\r
1838                 case SND_SOC_DAIFMT_IB_NF:\r
1839                         iface |= 0x0080;\r
1840                         break;\r
1841                 default:\r
1842                         return -EINVAL;\r
1843         }\r
1844 \r
1845         rt5625_write(codec, RT5625_MAIN_SDP_CTRL, iface);\r
1846         return 0;\r
1847 }\r
1848 \r
1849 static int rt5625_voice_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)\r
1850 {\r
1851         struct snd_soc_codec *codec = codec_dai->codec;\r
1852         int iface;\r
1853 \r
1854         DBG("enter %s\n", __func__);\r
1855         /*set slave/master mode*/\r
1856         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK)\r
1857         {\r
1858                 case SND_SOC_DAIFMT_CBM_CFM:\r
1859                         iface = 0x0000;\r
1860                         break;\r
1861                 case SND_SOC_DAIFMT_CBS_CFS:\r
1862                         iface = 0x4000;\r
1863                         break;\r
1864                 default:\r
1865                         return -EINVAL;                 \r
1866         }\r
1867 \r
1868         switch(fmt & SND_SOC_DAIFMT_FORMAT_MASK)\r
1869         {\r
1870                 case SND_SOC_DAIFMT_I2S:\r
1871                         iface |= 0x0000;\r
1872                         break;\r
1873                 case SND_SOC_DAIFMT_LEFT_J:\r
1874                         iface |= 0x0001;\r
1875                         break;\r
1876                 case SND_SOC_DAIFMT_DSP_A:\r
1877                         iface |= 0x0002;\r
1878                         break;\r
1879                 case SND_SOC_DAIFMT_DSP_B:\r
1880                         iface |= 0x0003;\r
1881                         break;\r
1882                 default:\r
1883                         return -EINVAL;         \r
1884         }\r
1885 \r
1886         /*clock inversion*/\r
1887         switch (fmt & SND_SOC_DAIFMT_INV_MASK)\r
1888         {\r
1889                 case SND_SOC_DAIFMT_NB_NF:\r
1890                         iface |= 0x0000;\r
1891                         break;\r
1892                 case SND_SOC_DAIFMT_IB_NF:\r
1893                         iface |= 0x0080;\r
1894                         break;\r
1895                 default:\r
1896                         return -EINVAL;                 \r
1897         }\r
1898 \r
1899         iface |= 0x8000;      /*enable vopcm*/\r
1900         rt5625_write(codec, RT5625_EXTEND_SDP_CTRL, iface);     \r
1901         return 0;\r
1902 }\r
1903 \r
1904 \r
1905 static int rt5625_hifi_codec_mute(struct snd_soc_dai *dai, int mute)\r
1906 {\r
1907         struct snd_soc_codec *codec = dai->codec;\r
1908 \r
1909         if (mute) \r
1910                 rt5625_write_mask(codec, RT5625_STEREO_DAC_VOL, 0x8080, 0x8080);\r
1911         else\r
1912                 rt5625_write_mask(codec, RT5625_STEREO_DAC_VOL, 0x0000, 0x8080);\r
1913         return 0;\r
1914 }\r
1915 \r
1916 static int rt5625_voice_codec_mute(struct snd_soc_dai *dai, int mute)\r
1917 {\r
1918         struct snd_soc_codec *codec = dai->codec;\r
1919 \r
1920         if (mute)\r
1921                 rt5625_write_mask(codec, RT5625_VOICE_DAC_OUT_VOL, 0x1000, 0x1000);\r
1922         else \r
1923                 rt5625_write_mask(codec, RT5625_VOICE_DAC_OUT_VOL, 0x0000, 0x1000);\r
1924         return 0;\r
1925 }\r
1926 \r
1927 \r
1928 static int rt5625_set_bias_level(struct snd_soc_codec *codec, \r
1929                         enum snd_soc_bias_level level)\r
1930 {\r
1931         switch(level) {\r
1932         case SND_SOC_BIAS_ON:\r
1933                 break;\r
1934         case SND_SOC_BIAS_PREPARE:\r
1935                 rt5625_write(codec, 0x26, 0x0000);\r
1936                 rt5625_write_mask(codec, 0x3c, 0x2000, 0x2000);     \r
1937                 rt5625_write_mask(codec, 0x3a, 0x000e, 0x000e);         \r
1938                 break;\r
1939         case SND_SOC_BIAS_STANDBY:\r
1940                 break;\r
1941         case SND_SOC_BIAS_OFF:\r
1942                 rt5625_write_mask(codec, 0x04, 0x8080, 0x8080);        /*mute hp*/\r
1943                 rt5625_write_mask(codec, 0x02, 0x8080, 0x8080);        /*mute spk*/\r
1944                 rt5625_write(codec, 0x3e, 0x0000);                                      //power off all bit\r
1945                 rt5625_write(codec, 0x3a, 0x0000);                                      //power off all bit\r
1946                 rt5625_write(codec, 0x3c, 0x0000);                                      //power off all bit\r
1947                 \r
1948                 break;\r
1949         }\r
1950         codec->bias_level = level;\r
1951         return 0;\r
1952 }\r
1953 \r
1954 \r
1955 #define RT5625_STEREO_RATES     SNDRV_PCM_RATE_8000_48000\r
1956 \r
1957 #define RT5626_VOICE_RATES SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_8000\r
1958 \r
1959 #define RT5625_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\\r
1960                         SNDRV_PCM_FMTBIT_S20_3LE |\\r
1961                         SNDRV_PCM_FMTBIT_S24_LE |\\r
1962                         SNDRV_PCM_FMTBIT_S8)\r
1963 \r
1964 static struct snd_soc_dai_ops rt5625_dai_ops_hifi = {\r
1965 \r
1966         .hw_params      = rt5625_hifi_pcm_hw_params,\r
1967 //      .digital_mute   = rt5625_hifi_codec_mute,\r
1968         .set_fmt        = rt5625_hifi_codec_set_dai_fmt,\r
1969         .set_pll        = rt5625_codec_set_dai_pll,\r
1970         .set_sysclk     = rt5625_hifi_codec_set_dai_sysclk,\r
1971 \r
1972 };\r
1973 \r
1974 \r
1975 static struct snd_soc_dai_ops rt5625_dai_ops_voice = {\r
1976 \r
1977         .hw_params      = rt5625_voice_pcm_hw_params,\r
1978 //      .digital_mute   = rt5625_voice_codec_mute,\r
1979         .set_fmt        = rt5625_voice_codec_set_dai_fmt,\r
1980         .set_pll        = rt5625_codec_set_dai_pll,\r
1981         .set_sysclk     = rt5625_voice_codec_set_dai_sysclk,\r
1982 \r
1983 };\r
1984 \r
1985 \r
1986 \r
1987 struct snd_soc_dai rt5625_dai[] = {\r
1988         /*hifi codec dai*/\r
1989         {\r
1990                 .name = "RT5625 HiFi",\r
1991                 .id = 1,\r
1992                 .playback = {\r
1993                         .stream_name = "HiFi Playback",\r
1994                         .channels_min = 1,\r
1995                         .channels_max = 2,\r
1996                         .rates = RT5625_STEREO_RATES,\r
1997                         .formats = RT5625_FORMATS,\r
1998                 },\r
1999                 .capture = {\r
2000                         .stream_name = "HiFi Capture",\r
2001                         .channels_min = 1,\r
2002                         .channels_max = 2,\r
2003                         .rates = RT5625_STEREO_RATES,\r
2004                         .formats = RT5625_FORMATS,\r
2005                 },\r
2006                 \r
2007                 .ops = &rt5625_dai_ops_hifi,\r
2008         },\r
2009 \r
2010         /*voice codec dai*/\r
2011         {\r
2012                 .name = "RT5625 Voice",\r
2013                 .id = 2,\r
2014                 .playback = {\r
2015                         .stream_name = "Voice Playback",\r
2016                         .channels_min = 1,\r
2017                         .channels_max = 1,\r
2018                         .rates = RT5626_VOICE_RATES,\r
2019                         .formats = RT5625_FORMATS,\r
2020                 },\r
2021                 .capture = {\r
2022                         .stream_name = "Voice Capture",\r
2023                         .channels_min = 1,\r
2024                         .channels_max = 1,\r
2025                         .rates = RT5626_VOICE_RATES,\r
2026                         .formats = RT5625_FORMATS,\r
2027                 },\r
2028                 \r
2029                 .ops = &rt5625_dai_ops_voice,\r
2030 \r
2031         },\r
2032 };\r
2033 \r
2034 EXPORT_SYMBOL_GPL(rt5625_dai);\r
2035 \r
2036 \r
2037 static void rt5625_work(struct work_struct *work)\r
2038 {\r
2039         struct snd_soc_codec *codec =\r
2040                  container_of(work, struct snd_soc_codec, delayed_work.work);\r
2041         rt5625_set_bias_level(codec, codec->bias_level);\r
2042 }\r
2043 \r
2044 \r
2045 #if defined(CONFIG_SND_HWDEP)\r
2046 \r
2047 #if REALTEK_HWDEP\r
2048 \r
2049 #define RT_CE_CODEC_HWDEP_NAME "rt56xx hwdep "\r
2050 \r
2051 \r
2052 static int rt56xx_hwdep_open(struct snd_hwdep *hw, struct file *file)\r
2053 {\r
2054         DBG("enter %s\n", __func__);\r
2055         return 0;\r
2056 }\r
2057 \r
2058 static int rt56xx_hwdep_release(struct snd_hwdep *hw, struct file *file)\r
2059 {\r
2060         DBG("enter %s\n", __func__);\r
2061         return 0;\r
2062 }\r
2063 \r
2064 \r
2065 static int rt56xx_hwdep_ioctl_common(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg)\r
2066 {\r
2067         struct rt56xx_cmd rt56xx;\r
2068         struct rt56xx_cmd __user *_rt56xx = arg;\r
2069         struct rt56xx_reg_state *buf;\r
2070         struct rt56xx_reg_state *p;\r
2071         struct snd_soc_codec *codec = hw->private_data;\r
2072 \r
2073         if (copy_from_user(&rt56xx, _rt56xx, sizeof(rt56xx)))\r
2074                 return -EFAULT;\r
2075         buf = kmalloc(sizeof(*buf) * rt56xx.number, GFP_KERNEL);\r
2076         if (buf == NULL)\r
2077                 return -ENOMEM;\r
2078         if (copy_from_user(buf, rt56xx.buf, sizeof(*buf) * rt56xx.number)) {\r
2079                 goto err;\r
2080         }\r
2081         switch (cmd) {\r
2082                 case RT_READ_CODEC_REG_IOCTL:\r
2083                         for (p = buf; p < buf + rt56xx.number; p++)\r
2084                         {\r
2085                                 p->reg_value = codec->read(codec, p->reg_index);\r
2086                         }\r
2087                         if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * rt56xx.number))\r
2088                                 goto err;\r
2089                                 \r
2090                         break;\r
2091                 case RT_WRITE_CODEC_REG_IOCTL:\r
2092                         for (p = buf; p < buf + rt56xx.number; p++)\r
2093                                 codec->write(codec, p->reg_index, p->reg_value);\r
2094                         break;\r
2095         }\r
2096 \r
2097         kfree(buf);\r
2098         return 0;\r
2099 \r
2100 err:\r
2101         kfree(buf);\r
2102         return -EFAULT;\r
2103         \r
2104 }\r
2105 \r
2106 static int rt56xx_codec_dump_reg(struct snd_hwdep *hw, struct file *file, unsigned long arg)\r
2107 {\r
2108         struct rt56xx_cmd rt56xx;\r
2109         struct rt56xx_cmd __user *_rt56xx = arg;\r
2110         struct rt56xx_reg_state *buf;\r
2111         struct snd_soc_codec *codec = hw->private_data;\r
2112         int number = codec->reg_cache_size;\r
2113         int i;\r
2114 \r
2115         DBG("enter %s, number = %d\n", __func__, number);       \r
2116         if (copy_from_user(&rt56xx, _rt56xx, sizeof(rt56xx)))\r
2117                 return -EFAULT;\r
2118         \r
2119         buf = kmalloc(sizeof(*buf) * number, GFP_KERNEL);\r
2120         if (buf == NULL)\r
2121                 return -ENOMEM;\r
2122 \r
2123         for (i = 0; i < number; i++)\r
2124         {\r
2125                 buf[i].reg_index = i << 1;\r
2126                 buf[i].reg_value = codec->read(codec, buf[i].reg_index);\r
2127         }\r
2128         if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * i))\r
2129                 goto err;\r
2130         rt56xx.number = number;\r
2131         if (copy_to_user(_rt56xx, &rt56xx, sizeof(rt56xx)))\r
2132                 goto err;\r
2133         kfree(buf);\r
2134         return 0;\r
2135 err:\r
2136         kfree(buf);\r
2137         return -EFAULT;\r
2138         \r
2139 }\r
2140 \r
2141 static int rt56xx_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg)\r
2142 {\r
2143         if (cmd == RT_READ_ALL_CODEC_REG_IOCTL)\r
2144         {\r
2145                 return rt56xx_codec_dump_reg(hw, file, arg);\r
2146         }\r
2147         else\r
2148         {\r
2149                 return rt56xx_hwdep_ioctl_common(hw, file, cmd, arg);\r
2150         }\r
2151 }\r
2152 \r
2153 int realtek_ce_init_hwdep(struct snd_soc_codec *codec)\r
2154 {\r
2155         struct snd_hwdep *hw;\r
2156         struct snd_card *card = codec->card;\r
2157         int err;\r
2158 \r
2159         if ((err = snd_hwdep_new(card, RT_CE_CODEC_HWDEP_NAME, 0, &hw)) < 0)\r
2160                 return err;\r
2161         \r
2162         strcpy(hw->name, RT_CE_CODEC_HWDEP_NAME);\r
2163         hw->private_data = codec;\r
2164         hw->ops.open = rt56xx_hwdep_open;\r
2165         hw->ops.release = rt56xx_hwdep_release;\r
2166         hw->ops.ioctl = rt56xx_hwdep_ioctl;\r
2167         return 0;\r
2168 }\r
2169 \r
2170 #endif\r
2171 \r
2172 #endif\r
2173 \r
2174 static int rt5625_init(struct snd_soc_device *socdev)\r
2175 {\r
2176 \r
2177         struct snd_soc_codec *codec = socdev->card->codec;\r
2178         int ret = 0;\r
2179 \r
2180         codec->name = "RT5625";\r
2181         codec->owner = THIS_MODULE;\r
2182         codec->read = rt5625_read;\r
2183         codec->write = rt5625_write;\r
2184         codec->set_bias_level = rt5625_set_bias_level;\r
2185         codec->dai= rt5625_dai;\r
2186         codec->num_dai = 2;\r
2187         codec->reg_cache_step = 2;              \r
2188         codec->reg_cache_size = ARRAY_SIZE(rt5625_reg)*2;\r
2189         codec->reg_cache = kmemdup(rt5625_reg, sizeof(rt5625_reg), GFP_KERNEL);\r
2190         if (codec->reg_cache == NULL)\r
2191                 return -ENOMEM;\r
2192 \r
2193         rt5625_reset(codec);\r
2194 \r
2195         ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);\r
2196         if (ret < 0 )\r
2197         {\r
2198                 printk(KERN_ERR "rt5625:  failed to create pcms\n");\r
2199                 goto pcm_err;\r
2200         }\r
2201         \r
2202         rt5625_write(codec, RT5625_PD_CTRL_STAT, 0);\r
2203         rt5625_write(codec, RT5625_PWR_MANAG_ADD1, PWR_MAIN_BIAS);\r
2204         rt5625_write(codec, RT5625_PWR_MANAG_ADD2, PWR_MIXER_VREF);\r
2205         rt5625_reg_init(codec);\r
2206         rt5625_set_bias_level(codec, SND_SOC_BIAS_PREPARE);\r
2207         codec->bias_level = SND_SOC_BIAS_STANDBY;\r
2208         schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(80));\r
2209 \r
2210 #if (RT5625_EQ_FUNC_ENA==1)     \r
2211         rt5625_update_eqmode(codec,POP);\r
2212 #endif\r
2213         \r
2214         rt5625_add_controls(codec);\r
2215         rt5625_add_widgets(codec);\r
2216 \r
2217         #if defined(CONFIG_SND_HWDEP)\r
2218 \r
2219                 #if REALTEK_HWDEP\r
2220 \r
2221                  realtek_ce_init_hwdep(codec);\r
2222 \r
2223                 #endif\r
2224 \r
2225         #endif\r
2226 \r
2227         ret = snd_soc_init_card(socdev);\r
2228 \r
2229         if (ret < 0)\r
2230         {\r
2231                 printk(KERN_ERR "rt5625: failed to register card\n");\r
2232                 goto card_err;\r
2233         }\r
2234         DBG("rt5625: initial ok\n");\r
2235         return 0;\r
2236 \r
2237         card_err:\r
2238                 snd_soc_free_pcms(socdev);\r
2239                 snd_soc_dapm_free(socdev);\r
2240         \r
2241         pcm_err:\r
2242                 kfree(codec->reg_cache);\r
2243                 return ret;\r
2244         \r
2245         \r
2246 }\r
2247 \r
2248 \r
2249 static int rt5625_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)\r
2250 {\r
2251         struct snd_soc_device *socdev = rt5625_socdev;\r
2252         struct snd_soc_codec *codec = socdev->card->codec;\r
2253         int ret;\r
2254 \r
2255         i2c_set_clientdata(i2c, codec);\r
2256         codec->control_data = i2c;\r
2257 \r
2258         ret = rt5625_init(socdev);\r
2259         if (ret < 0)\r
2260                 pr_err("failed to initialise rt5625\n");\r
2261 \r
2262         return ret;\r
2263 }\r
2264 \r
2265 static int rt5625_i2c_remove(struct i2c_client *client)\r
2266 {\r
2267         struct snd_soc_codec *codec = i2c_get_clientdata(client);\r
2268         kfree(codec->reg_cache);\r
2269         return 0;\r
2270 }\r
2271 \r
2272 static const struct i2c_device_id rt5625_i2c_id[] = {\r
2273                 {"rt5625", 0},\r
2274                 {}\r
2275 };\r
2276 MODULE_DEVICE_TABLE(i2c, rt5625_i2c_id);\r
2277 static struct i2c_driver rt5625_i2c_driver = {\r
2278         .driver = {\r
2279                 .name = "RT5625 I2C Codec",\r
2280                 .owner = THIS_MODULE,\r
2281         },\r
2282         .probe =    rt5625_i2c_probe,\r
2283         .remove =   rt5625_i2c_remove,\r
2284         .id_table = rt5625_i2c_id,\r
2285 };\r
2286 \r
2287 \r
2288 static int rt5625_add_i2c_device(struct platform_device *pdev,\r
2289                                  const struct rt5625_setup_data *setup)\r
2290 {\r
2291 #if 0\r
2292         struct i2c_board_info info;\r
2293         struct i2c_adapter *adapter;\r
2294         struct i2c_client *client;\r
2295 #endif\r
2296         int ret;\r
2297 \r
2298         ret = i2c_add_driver(&rt5625_i2c_driver);\r
2299         if (ret != 0) {\r
2300                 dev_err(&pdev->dev, "can't add i2c driver\n");\r
2301                 return ret;\r
2302         }\r
2303 #if 0\r
2304         memset(&info, 0, sizeof(struct i2c_board_info));\r
2305         info.addr = setup->i2c_address;\r
2306         strlcpy(info.type, "rt5625", I2C_NAME_SIZE);\r
2307 \r
2308         adapter = i2c_get_adapter(setup->i2c_bus);\r
2309         if (!adapter) {\r
2310                 dev_err(&pdev->dev, "can't get i2c adapter %d\n",\r
2311                         setup->i2c_bus);\r
2312                 goto err_driver;\r
2313         }\r
2314 \r
2315         client = i2c_new_device(adapter, &info);\r
2316         i2c_put_adapter(adapter);\r
2317         if (!client) {\r
2318                 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",\r
2319                         (unsigned int)info.addr);\r
2320                 goto err_driver;\r
2321         }\r
2322 #endif\r
2323         return 0;\r
2324 #if 0\r
2325 err_driver:\r
2326         i2c_del_driver(&rt5625_i2c_driver);\r
2327         return -ENODEV;\r
2328 #endif\r
2329 }\r
2330 \r
2331 \r
2332 static int rt5625_probe(struct platform_device *pdev)\r
2333 {\r
2334         struct snd_soc_device *socdev = platform_get_drvdata(pdev);\r
2335         struct rt5625_setup_data *setup;\r
2336         struct snd_soc_codec *codec;\r
2337         struct rt5625_priv *rt5625;\r
2338         int ret;\r
2339 \r
2340         pr_info("RT5625 Audio Codec %s", RT5625_VERSION);\r
2341 \r
2342         if(socdev->codec_data)\r
2343         {\r
2344                 setup = socdev->codec_data;             \r
2345         }\r
2346 \r
2347         codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);\r
2348         if (codec == NULL)\r
2349                 return -ENOMEM;\r
2350 \r
2351         rt5625 = kzalloc(sizeof(struct rt5625_priv), GFP_KERNEL);\r
2352         if (rt5625 == NULL) {\r
2353                 kfree(codec);\r
2354                 return -ENOMEM;\r
2355         }\r
2356         codec->private_data = rt5625;\r
2357         socdev->card->codec = codec;\r
2358 \r
2359         mutex_init(&codec->mutex);\r
2360         INIT_LIST_HEAD(&codec->dapm_widgets);\r
2361         INIT_LIST_HEAD(&codec->dapm_paths);\r
2362         rt5625_socdev = socdev;\r
2363         INIT_DELAYED_WORK(&codec->delayed_work, rt5625_work);\r
2364 \r
2365         ret = -ENODEV;\r
2366 //      if (setup->i2c_address) \r
2367         {\r
2368                 codec->hw_write = (hw_write_t)i2c_master_send;\r
2369                 //codec->hw_read = (hw_read_t)i2c_master_recv;\r
2370                 ret = rt5625_add_i2c_device(pdev, setup);\r
2371         }\r
2372 \r
2373         if (ret != 0) {\r
2374                 kfree(codec->private_data);\r
2375                 kfree(codec);\r
2376                 socdev->card->codec = NULL;\r
2377         }\r
2378         return ret;\r
2379 }\r
2380 \r
2381 static int run_delayed_work(struct delayed_work *dwork)\r
2382 {\r
2383         int ret;\r
2384 \r
2385         /* cancel any work waiting to be queued. */\r
2386         ret = cancel_delayed_work(dwork);\r
2387 \r
2388         /* if there was any work waiting then we run it now and\r
2389          * wait for it's completion */\r
2390         if (ret) {\r
2391                 schedule_delayed_work(dwork, 0);\r
2392                 flush_scheduled_work();\r
2393         }\r
2394         return ret;\r
2395 }\r
2396 \r
2397 \r
2398 static int rt5625_remove(struct platform_device *pdev)\r
2399 {\r
2400         struct snd_soc_device *socdev = platform_get_drvdata(pdev);\r
2401         struct snd_soc_codec *codec = socdev->card->codec;\r
2402 \r
2403         if (codec->control_data)\r
2404                 rt5625_set_bias_level(codec, SND_SOC_BIAS_OFF);\r
2405         run_delayed_work(&codec->delayed_work);\r
2406         snd_soc_free_pcms(socdev);\r
2407         snd_soc_dapm_free(socdev);\r
2408         i2c_unregister_device(codec->control_data);\r
2409         i2c_del_driver(&rt5625_i2c_driver);\r
2410         kfree(codec->private_data);\r
2411         kfree(codec);\r
2412 \r
2413         return 0;\r
2414 }\r
2415 \r
2416 \r
2417 static int rt5625_suspend(struct platform_device *pdev, pm_message_t state)\r
2418 {\r
2419         struct snd_soc_device *socdev = platform_get_drvdata(pdev);\r
2420         struct snd_soc_codec *codec = socdev->card->codec;\r
2421 \r
2422         rt5625_set_bias_level(codec, SND_SOC_BIAS_OFF);\r
2423 \r
2424         return 0;\r
2425 }\r
2426 \r
2427 static int rt5625_resume(struct platform_device *pdev)\r
2428 {\r
2429         struct snd_soc_device *socdev = platform_get_drvdata(pdev);\r
2430         struct snd_soc_codec *codec = socdev->card->codec;\r
2431 \r
2432         \r
2433 //      int i;\r
2434 //      u8 data[3];\r
2435 //      u16 *cache = codec->reg_cache;\r
2436 \r
2437 #if 1\r
2438         rt5625_reset(codec);\r
2439         rt5625_write(codec, RT5625_PD_CTRL_STAT, 0);\r
2440         rt5625_write(codec, RT5625_PWR_MANAG_ADD1, PWR_MAIN_BIAS);\r
2441         rt5625_write(codec, RT5625_PWR_MANAG_ADD2, PWR_MIXER_VREF);\r
2442         rt5625_reg_init(codec);\r
2443 #else\r
2444         /* Sync reg_cache with the hardware */\r
2445         for (i = 0; i < ARRAY_SIZE(rt5625_reg); i++) {\r
2446                 if (i == RT5625_RESET)\r
2447                         continue;\r
2448                 data[0] = i << 1;\r
2449                 data[1] = (0xff00 & cache[i]) >> 8;\r
2450                 data[2] = 0x00ff & cache[i];\r
2451                 codec->hw_write(codec->control_data, data, 3);\r
2452         }\r
2453 \r
2454         rt5625_set_bias_level(codec, SND_SOC_BIAS_STANDBY);\r
2455 #endif\r
2456 \r
2457         /* charge rt5625 caps */\r
2458         if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {\r
2459                 rt5625_set_bias_level(codec, SND_SOC_BIAS_PREPARE);\r
2460                 codec->bias_level = SND_SOC_BIAS_ON;\r
2461                 schedule_delayed_work(&codec->delayed_work,\r
2462                                         msecs_to_jiffies(100));\r
2463         }\r
2464 \r
2465         return 0;\r
2466 }\r
2467 \r
2468 \r
2469 struct snd_soc_codec_device soc_codec_dev_rt5625 = {\r
2470         .probe =        rt5625_probe,\r
2471         .remove =       rt5625_remove,\r
2472         .suspend =      rt5625_suspend,\r
2473         .resume =       rt5625_resume,\r
2474 };\r
2475 \r
2476 EXPORT_SYMBOL_GPL(soc_codec_dev_rt5625);\r
2477 \r
2478 static int __init rt5625_modinit(void)\r
2479 {\r
2480         return snd_soc_register_dais(rt5625_dai, ARRAY_SIZE(rt5625_dai));\r
2481 }\r
2482 \r
2483 static void __exit rt5625_exit(void)\r
2484 {\r
2485         snd_soc_unregister_dais(rt5625_dai, ARRAY_SIZE(rt5625_dai));\r
2486 }\r
2487 \r
2488 module_init(rt5625_modinit);\r
2489 module_exit(rt5625_exit);\r
2490 MODULE_LICENSE("GPL");\r
2491 \r