rk2928 add phonepad support
[firefly-linux-kernel-4.4.55.git] / sound / soc / codecs / rk2928_codec.c
1 /*
2  * rk2928_codec.c ALSA SoC RK2928 codec driver
3  *
4  * Copyright 2012 Rockchip
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * version 2 as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18  * 02110-1301 USA
19  *
20  */
21
22 #include <linux/module.h>
23 #include <linux/moduleparam.h>
24 #include <linux/init.h>
25 #include <linux/delay.h>
26 #include <linux/pm.h>
27 #include <linux/gpio.h>
28 #include <linux/platform_device.h>
29 #include <linux/slab.h>
30 #include <linux/workqueue.h>
31 #include <asm/io.h>
32 #include <asm/delay.h>
33 #include <linux/wakelock.h>
34 #include <sound/core.h>
35 #include <sound/pcm.h>
36 #include <sound/pcm_params.h>
37 #include <sound/soc.h>
38 #include <sound/initval.h>
39 #include <sound/tlv.h>
40 #include <mach/cru.h>
41 #include <mach/iomux.h>
42 #include <mach/cpu.h>
43 #include <linux/clk.h>
44 #include "rk2928_codec.h"
45 #define HP_OUT 0
46 #define HP_IN  1
47
48 static struct rk2928_codec_data {
49         struct device   *dev;
50         struct snd_soc_codec *codec;
51         int                     regbase;
52         int                             regbase_phy;
53         int                             regsize_phy;
54         struct clk              *pclk;
55         int                             mute;
56         int                             hdmi_enable;
57         int                             spkctl;
58         int                             hp_ctl;
59         int             call_enable;
60         int             headset_status; 
61         struct rk2928_codec_pdata *pdata;
62         bool                    stop_phone_depop;
63         struct delayed_work h_delayed_work;     
64         struct mutex mutex_lock;
65 } rk2928_data;
66
67 static int DAC_event(struct snd_soc_dapm_widget *w,
68                           struct snd_kcontrol *kcontrol, int event)
69 {
70         struct snd_soc_codec *codec = w->codec;
71         struct rk2928_codec_data *priv = snd_soc_codec_get_drvdata(codec);
72         
73         DBG("%s::%d event = %d\n",__FUNCTION__,__LINE__,event);
74
75         switch (event) {
76         case SND_SOC_DAPM_PRE_PMD:
77 #ifdef CONFIG_MODEM_SOUND       
78         if(rk2928_data.call_enable)
79                 return 0;
80 #endif                  
81                 //before widget power down
82                 if(rk2928_data.spkctl != INVALID_GPIO) {
83                         gpio_direction_output(rk2928_data.spkctl, GPIO_LOW);
84                 }       
85                 if(rk2928_data.hp_ctl != 0 && rk2928_data.headset_status == HP_IN) {
86                 //      gpio_direction_output(rk2928_data.hp_ctl, GPIO_LOW);
87                 }                       
88                 break;
89         case SND_SOC_DAPM_POST_PMU:     
90                 //after widget power up 
91                 if(rk2928_data.spkctl != INVALID_GPIO && rk2928_data.headset_status == HP_OUT) {
92                         gpio_direction_output(rk2928_data.spkctl, GPIO_HIGH);
93                         msleep(200);
94                 }
95                 if(rk2928_data.hp_ctl != 0 ) {//&& rk2928_data.headset_status == HP_IN
96                         gpio_direction_output(rk2928_data.hp_ctl, GPIO_HIGH);
97                 }
98                 break;
99         }
100
101         return 0;
102 }
103
104 static const struct snd_soc_dapm_widget rk2928_dapm_widgets[] = {
105         SND_SOC_DAPM_DAC_E("DACL", "HIFI Playback", CODEC_REG_POWER, 5, 1,DAC_event, SND_SOC_DAPM_PRE_PMD|SND_SOC_DAPM_POST_PMU),
106         SND_SOC_DAPM_DAC_E("DACR", "HIFI Playback", CODEC_REG_POWER, 4, 1,DAC_event, SND_SOC_DAPM_PRE_PMD|SND_SOC_DAPM_POST_PMU),
107         SND_SOC_DAPM_PGA("DACL Amp", CODEC_REG_DAC_GAIN, 2, 0, NULL, 0),
108         SND_SOC_DAPM_PGA("DACR Amp", CODEC_REG_DAC_GAIN, 0, 0, NULL, 0),
109         SND_SOC_DAPM_OUTPUT("SPKL"),
110         SND_SOC_DAPM_OUTPUT("SPKR"),
111         SND_SOC_DAPM_ADC("ADCL", "HIFI Capture", CODEC_REG_POWER, 3, 1),
112         SND_SOC_DAPM_INPUT("MICL"),
113         SND_SOC_DAPM_ADC("ADCR", "HIFI Capture", CODEC_REG_POWER, 2, 1),
114         SND_SOC_DAPM_INPUT("MICR"),
115 };
116
117 static const struct snd_soc_dapm_route rk2928_audio_map[] = {
118         {"SPKL", "DACL Amp", "DACL"},
119         {"SPKR", "DACR Amp", "DACR"},
120         {"ADCL", NULL, "MICL"},
121         {"ADCR", NULL, "MICR"},
122 };
123
124 static const struct snd_soc_dapm_widget rk2926_dapm_widgets[] = {
125         SND_SOC_DAPM_DAC("DACL", "HIFI Playback", CODEC_REG_POWER, 5, 1),
126         SND_SOC_DAPM_DAC("DACR", "HIFI Playback", CODEC_REG_POWER, 4, 1),
127         SND_SOC_DAPM_PGA("DACL Amp", CODEC_REG_DAC_GAIN, 2, 0, NULL, 0),
128         SND_SOC_DAPM_PGA("DACR Amp", CODEC_REG_DAC_GAIN, 0, 0, NULL, 0),
129         SND_SOC_DAPM_OUTPUT("SPKL"),
130         SND_SOC_DAPM_OUTPUT("SPKR"),
131         SND_SOC_DAPM_ADC("ADCR", "HIFI Capture", CODEC_REG_POWER, 2, 1),
132         SND_SOC_DAPM_INPUT("MICR"),
133 };
134
135 static const struct snd_soc_dapm_route rk2926_audio_map[] = {
136         {"SPKL", "DACL Amp", "DACL"},
137         {"SPKR", "DACR Amp", "DACR"},
138         {"ADCR", NULL, "MICR"},
139 };
140
141 static unsigned int rk2928_read(struct snd_soc_codec *codec, unsigned int reg)
142 {       
143         return readl(rk2928_data.regbase + reg*4);
144 }
145
146 static int rk2928_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value)
147 {       
148 #ifdef CONFIG_MODEM_SOUND       
149         if(rk2928_data.call_enable)
150                 return 0;
151 #endif          
152         DBG("%s reg 0x%02x value 0x%02x", __FUNCTION__, reg, value);
153        if(reg == 0xc)
154                value &= ~0x31;  
155         writel(value, rk2928_data.regbase + reg*4);
156         if( (reg == CODEC_REG_POWER) && ( (value & m_PD_DAC) == 0)) {
157                 msleep(100);
158         }
159         return 0;
160 }
161 static int rk2928_write_incall(struct snd_soc_codec *codec, unsigned int reg, unsigned int value)
162 {
163         DBG("%s reg 0x%02x value 0x%02x", __FUNCTION__, reg, value);
164        if(reg == 0xc)
165                value &= ~0x31;
166         writel(value, rk2928_data.regbase + reg*4);
167         if( (reg == CODEC_REG_POWER) && ( (value & m_PD_DAC) == 0)) {
168                 msleep(100);
169         }
170         return 0;
171 }
172
173 static int rk2928_write_mask(struct snd_soc_codec *codec, unsigned int reg, 
174                                         unsigned int mask, unsigned int value)
175 {
176         unsigned int regvalue = rk2928_read(codec, reg);
177         
178         DBG("%s reg 0x%02x mask 0x%02x value 0x%02x", __FUNCTION__, reg, mask, value);
179         
180         regvalue &= ~mask;
181         regvalue |= mask & value;
182         return rk2928_write(codec, reg, regvalue);
183 }
184
185 void codec_set_spk(bool on)
186 {
187         if(on == 0) {
188                 DBG("%s speaker is disabled\n", __FUNCTION__);
189                 rk2928_data.hdmi_enable = 1;
190                 if(rk2928_data.mute == 0) {
191                         rk2928_write(NULL, CODEC_REG_DAC_MUTE, v_MUTE_DAC(1));
192                         if(rk2928_data.spkctl != INVALID_GPIO) {
193                                 gpio_direction_output(rk2928_data.spkctl, GPIO_LOW);
194                         }
195                 }
196         }
197         else {
198                 DBG("%s speaker is enabled\n", __FUNCTION__);
199                 rk2928_data.hdmi_enable = 0;
200                 if(rk2928_data.mute == 0) {
201                         rk2928_write(NULL, CODEC_REG_DAC_MUTE, v_MUTE_DAC(0));
202                         if((rk2928_data.spkctl != INVALID_GPIO) && (rk2928_data.headset_status == HP_OUT)) {
203                                 gpio_direction_output(rk2928_data.spkctl, GPIO_HIGH);
204                         }
205                 }
206         }
207 }
208
209 static void call_delay_work(struct work_struct *work)
210 {
211                 struct snd_soc_codec *codec = rk2928_data.codec;
212         if(codec == NULL)
213                 return;
214          printk("%s speaker is disabled\n", __FUNCTION__);
215          rk2928_write_incall(NULL, CODEC_REG_DAC_MUTE, v_MUTE_DAC(0));
216          rk2928_write_incall(codec, CODEC_REG_POWER, 0x0c);
217          rk2928_write_incall(codec, CODEC_REG_ADC_SOURCE, 0x03);
218          rk2928_write_incall(codec, CODEC_REG_ADC_PGA_GAIN, 0x33);//spk 0x33        
219          rk2928_data.call_enable = 1;
220         mutex_unlock(&rk2928_data.mutex_lock);
221
222 }
223 #ifdef CONFIG_MODEM_SOUND
224 void call_set_spk(int on)
225 {
226         struct snd_soc_codec *codec = rk2928_data.codec;
227         if(codec == NULL)
228                 return; 
229         mutex_lock(&rk2928_data.mutex_lock);
230         switch(on)
231         {
232         case 0:
233                 printk("%s speaker is enabled\n", __FUNCTION__);
234                 rk2928_data.call_enable = 0;
235         //      rk2928_write(NULL, CODEC_REG_DAC_MUTE, v_MUTE_DAC(0));
236                 rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x00);
237                 printk("rk2928 codec stop phone need depop\n");
238                 rk2928_data.stop_phone_depop = true;    
239                 break;
240         case 1:
241                 rk2928_write_incall(NULL, CODEC_REG_DAC_MUTE, v_MUTE_DAC(1));
242                 schedule_delayed_work(&rk2928_data.h_delayed_work, msecs_to_jiffies(1000));
243                 return;
244         case 2:
245                 printk("%s speaker is disabled\n", __FUNCTION__);
246                 rk2928_write(NULL, CODEC_REG_DAC_MUTE, v_MUTE_DAC(0));
247                 rk2928_write(codec, CODEC_REG_POWER, 0x0c);
248                 rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x03);
249                 rk2928_write(codec, CODEC_REG_ADC_PGA_GAIN, 0x11);//headset
250                 rk2928_data.call_enable = 1;    
251                 break;
252         case 3:
253                 printk("%s speaker is disabled\n", __FUNCTION__);
254                 rk2928_write(NULL, CODEC_REG_DAC_MUTE, v_MUTE_DAC(0));
255                 rk2928_write(codec, CODEC_REG_POWER, 0x0c);
256                 rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x03);
257                 rk2928_write(codec, CODEC_REG_ADC_PGA_GAIN, 0x33);//spk 0x33            
258                 rk2928_data.call_enable = 1;
259                 break;
260         }
261         mutex_unlock(&rk2928_data.mutex_lock);
262         return;
263 }
264 #endif
265 #ifdef CONFIG_RK_HEADSET_DET
266 //for headset
267 void rk2928_codec_set_spk(bool on)
268 {
269         struct snd_soc_codec *codec = rk2928_data.codec;
270         if(codec == NULL)
271                 return;
272         if(on)
273                 rk2928_data.headset_status = HP_IN;
274         else
275                 rk2928_data.headset_status = HP_OUT;
276         if(rk2928_data.call_enable)
277                 return;
278         printk("%s: headset %s %s PA bias_level=%d\n",__FUNCTION__,on?"in":"out",on?"disable":"enable",codec->dapm.bias_level);
279         if(on) {
280                 if(rk2928_data.spkctl != INVALID_GPIO)
281                 {
282                         gpio_direction_output(rk2928_data.spkctl, GPIO_LOW);
283                 }
284         }
285         else {
286                 if(codec->dapm.bias_level == SND_SOC_BIAS_STANDBY 
287                 || codec->dapm.bias_level == SND_SOC_BIAS_OFF){
288                         return;
289                 }               
290                 if(rk2928_data.spkctl != INVALID_GPIO)
291                 {
292                         gpio_direction_output(rk2928_data.spkctl, GPIO_HIGH);
293                 }
294         }
295 }
296 #endif
297
298 static int rk2928_audio_hw_params(struct snd_pcm_substream *substream,
299                                     struct snd_pcm_hw_params *params,
300                                     struct snd_soc_dai *dai)
301 {
302 //      struct snd_soc_pcm_runtime *rtd = substream->private_data;
303 //      struct snd_soc_codec *codec = rtd->codec;
304 //      struct rk2928_codec_data *priv = snd_soc_codec_get_drvdata(codec);
305         
306         DBG("%s", __FUNCTION__);
307
308         return 0;
309 }
310
311 static int rk2928_audio_trigger(struct snd_pcm_substream *substream, int cmd,
312                                 struct snd_soc_dai *dai)
313 {
314         struct snd_soc_pcm_runtime *rtd = substream->private_data;
315         struct snd_soc_codec *codec = rtd->codec;
316         struct rk2928_codec_data *priv = snd_soc_codec_get_drvdata(codec);
317         int err = 0;
318         int data, pd_adc;
319         DBG("%s cmd 0x%x", __FUNCTION__, cmd);
320
321         switch (cmd) {
322                 case SNDRV_PCM_TRIGGER_START:
323                 case SNDRV_PCM_TRIGGER_RESUME:
324                 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
325                         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
326 //                              rk2928_write(codec, CODEC_REG_DAC_GAIN, v_GAIN_DAC(DAC_GAIN_3DB_P));
327                                 if(!rk2928_data.hdmi_enable) {
328                                         data = rk2928_read(codec, CODEC_REG_POWER);
329                                         if(soc_is_rk2928g()){
330                                                 if( (data & m_PD_ADC) == 0) {
331                                                         data &= ~m_PD_ADC;
332                                                         data |= v_PD_ADC(1);
333                                                         pd_adc = 1;
334                                                 }
335                                                 else
336                                                         pd_adc = 0;
337                                         }
338                                         else{
339                                                 if( (data & m_PD_ADC_R) == 0) {
340                                                         data &= ~m_PD_ADC_R;
341                                                         data |= v_PD_ADC_R(1);
342                                                         pd_adc = 1;
343                                                 }
344                                                 else
345                                                         pd_adc = 0;
346                                         }
347                                         if(pd_adc == 1) {
348                                                 DBG("%s reg 0x%02x value 0x%02x", __FUNCTION__, CODEC_REG_POWER, data);
349                                                 writel(data, rk2928_data.regbase + CODEC_REG_POWER*4);
350                                                 udelay(100);                                            
351                                         }
352
353                                         rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x03);
354                                         udelay(100);
355                                         rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x00);
356                                         
357                                         udelay(100);
358                                         rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x03);
359                                         udelay(100);
360                                         rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x00);
361                                         
362                                         udelay(100);
363                                         rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x03);
364                                         udelay(100);
365                                         rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x00);
366
367                                         if(pd_adc == 1) {
368                                                 udelay(100);
369                                                 data = rk2928_read(codec, CODEC_REG_POWER);
370                                                 if( soc_is_rk2928g() ) {
371                                                         data &= ~m_PD_ADC;
372                                                         data |= v_PD_ADC(0);
373                                                 }
374                                                 else {
375                                                         data &= ~m_PD_ADC_R;
376                                                         data |= v_PD_ADC_R(0);
377                                                 }
378                                                 DBG("%s reg 0x%02x value 0x%02x", __FUNCTION__, CODEC_REG_POWER, data);
379                                                 writel(data, rk2928_data.regbase + CODEC_REG_POWER*4);
380                                         }
381                                         
382                                         rk2928_write(codec, CODEC_REG_DAC_MUTE, v_MUTE_DAC(0));
383                                         if(rk2928_data.spkctl != INVALID_GPIO && rk2928_data.headset_status == HP_OUT && rk2928_data.stop_phone_depop ) {
384                                                 mdelay(100);
385                                                 gpio_direction_output(rk2928_data.spkctl, GPIO_HIGH);
386                                                 rk2928_data.stop_phone_depop = false;
387                                         }
388                                 }
389                                 rk2928_data.mute = 0;
390                         //      if(rk2928_data.spkctl != INVALID_GPIO && rk2928_data.headset_status == HP_OUT) {
391                         //              gpio_direction_output(rk2928_data.spkctl, GPIO_HIGH);
392                         //      }
393                         }
394                         else {
395                                 rk2928_write(codec, CODEC_REG_ADC_PGA_GAIN, 0xFF);
396                                 rk2928_write(codec, 0x08, 0xff);
397                                 rk2928_write(codec, 0x09, 0x07);
398                         }
399                         break;
400                 case SNDRV_PCM_TRIGGER_STOP:
401                 case SNDRV_PCM_TRIGGER_SUSPEND:
402                 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
403 #ifdef CONFIG_MODEM_SOUND       
404         if(rk2928_data.call_enable)
405                 return err;
406 #endif          
407                         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
408                                 //if(rk2928_data.spkctl != INVALID_GPIO) {
409                                         //gpio_direction_output(rk2928_data.spkctl, GPIO_LOW);
410                                 //}
411                                 rk2928_write(codec, CODEC_REG_DAC_MUTE, v_MUTE_DAC(1));
412                                 rk2928_data.mute = 1;
413                         }
414                         break;
415                 default:
416                         err = -EINVAL;
417         }
418         return err;
419 }
420
421 static int rk2928_audio_startup(struct snd_pcm_substream *substream,
422                                   struct snd_soc_dai *dai)
423 {
424 //      struct snd_soc_pcm_runtime *rtd = substream->private_data;
425 //      struct snd_soc_codec *codec = rtd->codec;
426         DBG("%s", __FUNCTION__);
427         return 0;
428 }
429
430 static int rk2928_set_bias_level(struct snd_soc_codec *codec,
431                               enum snd_soc_bias_level level)
432 {
433         DBG("%s level %d\n", __FUNCTION__, level);
434         
435         if(codec == NULL)
436                 return -1;
437                 
438         switch(level)
439         {
440                 case SND_SOC_BIAS_ON:
441                         break;
442                 case SND_SOC_BIAS_PREPARE:
443                         rk2928_write_mask(codec, CODEC_REG_POWER, m_PD_MIC_BIAS | m_PD_CODEC, v_PD_MIC_BIAS(0) | v_PD_CODEC(0));
444                         break;
445                 case SND_SOC_BIAS_STANDBY:
446                 case SND_SOC_BIAS_OFF:
447                         printk("rk2928 codec standby\n");
448 #ifdef CONFIG_MODEM_SOUND       
449         if(rk2928_data.call_enable)
450                 break;
451 #endif                          
452                 //      if(rk2928_data.spkctl != INVALID_GPIO) {
453                 //              gpio_direction_output(rk2928_data.spkctl, GPIO_LOW);
454                 //      }
455                         rk2928_write(codec, CODEC_REG_POWER, v_PWR_OFF);
456                         break;
457                 default:
458                         return -1;
459         }
460         codec->dapm.bias_level = level;
461         return 0;
462 }
463
464 static void rk2929_codec_reset(void)
465 {
466         // Reset Codec
467         cru_set_soft_reset(SOFT_RST_ACODEC, true);
468         udelay(1000);
469         cru_set_soft_reset(SOFT_RST_ACODEC, false);
470 }
471
472 static int rk2928_probe(struct snd_soc_codec *codec)
473 {
474         struct platform_device *pdev = to_platform_device(codec->dev);
475         struct snd_soc_dapm_context *dapm = &codec->dapm;
476         struct resource *res, *mem;
477         struct rk2928_codec_pdata *pdata;
478         int ret;
479         
480         DBG("%s", __FUNCTION__);
481         
482         snd_soc_codec_set_drvdata(codec, &rk2928_data);
483
484         rk2928_data.dev = &pdev->dev;
485         rk2928_data.pdata = pdev->dev.platform_data;    
486         pdata = rk2928_data.pdata;
487         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
488         if (!res) {
489                 dev_err(&pdev->dev, "Unable to get register resource\n");
490                 ret = -ENXIO;
491                 goto err0;
492         }
493         rk2928_data.regbase_phy = res->start;
494         rk2928_data.regsize_phy = (res->end - res->start) + 1;
495         mem = request_mem_region(res->start, (res->end - res->start) + 1, pdev->name);
496         if (!mem)
497         {
498         dev_err(&pdev->dev, "failed to request mem region for rk2928 codec\n");
499         ret = -ENOENT;
500         goto err0;
501         }
502         
503         rk2928_data.regbase = (int)ioremap(res->start, (res->end - res->start) + 1);
504         if (!rk2928_data.regbase) {
505                 dev_err(&pdev->dev, "cannot ioremap acodec registers\n");
506                 ret = -ENXIO;
507                 goto err1;
508         }
509         
510         rk2928_data.pclk = clk_get(NULL,"pclk_acodec");
511         if(IS_ERR(rk2928_data.pclk))
512         {
513                 dev_err(rk2928_data.dev, "Unable to get acodec hclk\n");
514                 ret = -ENXIO;
515                 goto err1;
516         }
517         clk_enable(rk2928_data.pclk);
518
519         res = platform_get_resource(pdev, IORESOURCE_IO, 0);
520         if(!res) {
521                 rk2928_data.spkctl = INVALID_GPIO;
522         }
523         else {
524                 rk2928_data.spkctl = res->start;
525         }
526
527         if(rk2928_data.spkctl != INVALID_GPIO) {
528                 ret = gpio_request(rk2928_data.spkctl, NULL);
529                 if (ret != 0) {
530                         gpio_free(rk2928_data.spkctl);
531                 }
532                 else
533                         gpio_direction_output(rk2928_data.spkctl, GPIO_LOW);
534         }
535 //------------------------------------------------------------------
536         if (pdata->hpctl) {
537                 ret = pdata->hpctl_io_init();
538                 if (ret) 
539                         goto err1;
540                 rk2928_data.hp_ctl = pdata->hpctl;
541                 gpio_direction_output(rk2928_data.hp_ctl, GPIO_LOW);
542         }
543         //Reset Codec
544         rk2929_codec_reset();
545
546         // Select SDI input from internal audio codec
547         writel(0x04000400, RK2928_GRF_BASE + GRF_SOC_CON0);
548         
549         // Mute and Power off codec
550         rk2928_write(codec, CODEC_REG_DAC_MUTE, v_MUTE_DAC(1));
551         rk2928_set_bias_level(codec, SND_SOC_BIAS_OFF);
552         if(soc_is_rk2928g()){   
553             snd_soc_dapm_new_controls(dapm, rk2928_dapm_widgets,
554                 ARRAY_SIZE(rk2928_dapm_widgets));
555             snd_soc_dapm_add_routes(dapm, rk2928_audio_map, ARRAY_SIZE(rk2928_audio_map));
556         }else{
557             snd_soc_dapm_new_controls(dapm, rk2926_dapm_widgets,
558                 ARRAY_SIZE(rk2926_dapm_widgets));
559             snd_soc_dapm_add_routes(dapm, rk2926_audio_map, ARRAY_SIZE(rk2926_audio_map));
560         }
561
562         INIT_DELAYED_WORK(&rk2928_data.h_delayed_work, call_delay_work);
563         mutex_init(&rk2928_data.mutex_lock);
564         rk2928_data.call_enable = 0;
565         rk2928_data.headset_status = HP_OUT;
566         rk2928_data.codec=codec;
567         rk2928_data.stop_phone_depop=false;
568         return 0;
569         
570 err1:
571         release_mem_region(res->start,(res->end - res->start) + 1);
572 //      clk_disable(rk2928_data.hclk);
573 err0:
574         DBG("%s failed", __FUNCTION__);
575         return ret;
576 }
577
578 static int rk2928_remove(struct snd_soc_codec *codec)
579 {
580         return 0;
581 }
582
583 static int rk2928_suspend(struct snd_soc_codec *codec, pm_message_t state)
584 {
585         DBG("%s", __FUNCTION__);
586         rk2928_set_bias_level(codec, SND_SOC_BIAS_OFF);
587         clk_disable(rk2928_data.pclk);
588         return 0;
589 }
590
591 static int rk2928_resume(struct snd_soc_codec *codec)
592 {
593         DBG("%s", __FUNCTION__);
594         clk_enable(rk2928_data.pclk);
595         rk2928_write(codec, CODEC_REG_POWER, v_PD_ADC(1) | v_PD_DAC(1) | v_PD_MIC_BIAS(0));
596         return 0;
597 }
598
599 static struct snd_soc_codec_driver rk2928_audio_codec_drv = {
600         .probe = rk2928_probe,
601         .remove = rk2928_remove,
602         .suspend = rk2928_suspend,
603         .resume = rk2928_resume,
604         .read = rk2928_read,
605         .write = rk2928_write,
606         .set_bias_level = rk2928_set_bias_level,
607 };
608
609 static struct snd_soc_dai_ops rk2928_audio_codec_ops = {
610         .hw_params = rk2928_audio_hw_params,
611         .trigger = rk2928_audio_trigger,
612         .startup = rk2928_audio_startup,
613 };
614
615 static struct snd_soc_dai_driver rk2928_codec_dai = {
616         .name = "rk2928-codec",
617         .playback = {
618                 .stream_name = "HIFI Playback",
619                 .channels_min = 1,
620                 .channels_max = 2,
621                 .rates = SNDRV_PCM_RATE_8000_48000,
622                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | 
623                         SNDRV_PCM_FMTBIT_S24_LE,
624         },
625         .capture = {
626                 .stream_name = "HIFI Capture",
627                 .channels_min = 1,
628                 .channels_max = 2,
629                 .rates = SNDRV_PCM_RATE_8000_48000,
630                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE,
631         },
632         .ops = &rk2928_audio_codec_ops,
633 };
634
635 static __devinit int rk2928_codec_probe(struct platform_device *pdev)
636 {
637         int r;
638         
639         DBG("%s", __FUNCTION__);
640         
641         /* Register ASoC codec DAI */
642         r = snd_soc_register_codec(&pdev->dev, &rk2928_audio_codec_drv,
643                                         &rk2928_codec_dai, 1);
644         if (r) {
645                 dev_err(&pdev->dev, "can't register ASoC rk2928 audio codec\n");
646                 return r;
647         }
648         
649         DBG("%s success", __FUNCTION__);
650         return 0;
651         
652 }
653
654 static int __devexit rk2928_codec_remove(struct platform_device *pdev)
655 {
656         snd_soc_unregister_codec(&pdev->dev);
657         return 0;
658 }
659
660 static void rk2928_codec_shutdown(struct platform_device *pdev)
661 {
662         printk("%s .....\n", __FUNCTION__);
663         if(rk2928_data.spkctl != INVALID_GPIO)
664                 gpio_direction_output(rk2928_data.spkctl, GPIO_LOW);
665         if(rk2928_data.hp_ctl != 0 ) 
666                 gpio_direction_output(rk2928_data.hp_ctl, GPIO_LOW);    
667 }
668 static struct platform_driver rk2928_codec_driver = {
669         .probe          = rk2928_codec_probe,
670         .remove         = __devexit_p(rk2928_codec_remove),
671         .driver         = {
672                 .name   = "rk2928-codec",
673                 .owner  = THIS_MODULE,
674         },
675         .shutdown = rk2928_codec_shutdown,
676 };
677
678 static int __init rk2928_codec_init(void)
679 {
680         return platform_driver_register(&rk2928_codec_driver);
681 }
682 module_init(rk2928_codec_init);
683
684 static void __exit rk2928_codec_exit(void)
685 {
686         #ifdef CODEC_I2C_MODE
687         i2c_del_driver(&rk2928_codec_driver);
688         #else
689         platform_driver_unregister(&rk2928_codec_driver);
690         #endif
691 }
692 module_exit(rk2928_codec_exit);
693
694 MODULE_DESCRIPTION("ASoC RK2928 codec driver");
695 MODULE_LICENSE("GPL");