Merge tag 'v4.4-rc2'
[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 static void call_delay_work(struct work_struct *work)
186 {
187                 struct snd_soc_codec *codec = rk2928_data.codec;
188         if(codec == NULL)
189                 return;
190          printk("%s speaker is disabled\n", __FUNCTION__);
191          rk2928_write_incall(NULL, CODEC_REG_DAC_MUTE, v_MUTE_DAC(0));
192          rk2928_write_incall(codec, CODEC_REG_POWER, 0x0c);
193          rk2928_write_incall(codec, CODEC_REG_ADC_SOURCE, 0x03);
194          rk2928_write_incall(codec, CODEC_REG_ADC_PGA_GAIN, 0x33);//spk 0x33        
195          rk2928_data.call_enable = 1;
196         mutex_unlock(&rk2928_data.mutex_lock);
197
198 }
199 #ifdef CONFIG_MODEM_SOUND
200 void call_set_spk(int on)
201 {
202         struct snd_soc_codec *codec = rk2928_data.codec;
203         if(codec == NULL)
204                 return; 
205         mutex_lock(&rk2928_data.mutex_lock);
206         switch(on)
207         {
208         case 0:
209                 printk("%s speaker is enabled\n", __FUNCTION__);
210                 rk2928_data.call_enable = 0;
211         //      rk2928_write(NULL, CODEC_REG_DAC_MUTE, v_MUTE_DAC(0));
212                 rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x00);
213                 printk("rk2928 codec stop phone need depop\n");
214                 rk2928_data.stop_phone_depop = true;    
215                 break;
216         case 1:
217                 rk2928_write_incall(NULL, CODEC_REG_DAC_MUTE, v_MUTE_DAC(1));
218                 schedule_delayed_work(&rk2928_data.h_delayed_work, msecs_to_jiffies(1000));
219                 return;
220         case 2:
221                 printk("%s speaker is disabled\n", __FUNCTION__);
222                 rk2928_write(NULL, CODEC_REG_DAC_MUTE, v_MUTE_DAC(0));
223                 rk2928_write(codec, CODEC_REG_POWER, 0x0c);
224                 rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x03);
225                 rk2928_write(codec, CODEC_REG_ADC_PGA_GAIN, 0x11);//headset
226                 rk2928_data.call_enable = 1;    
227                 break;
228         case 3:
229                 printk("%s speaker is disabled\n", __FUNCTION__);
230                 rk2928_write(NULL, CODEC_REG_DAC_MUTE, v_MUTE_DAC(0));
231                 rk2928_write(codec, CODEC_REG_POWER, 0x0c);
232                 rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x03);
233                 rk2928_write(codec, CODEC_REG_ADC_PGA_GAIN, 0x33);//spk 0x33            
234                 rk2928_data.call_enable = 1;
235                 break;
236         }
237         mutex_unlock(&rk2928_data.mutex_lock);
238         return;
239 }
240 #endif
241 #ifdef CONFIG_RK_HEADSET_DET
242 //for headset
243 void rk2928_codec_set_spk(bool on)
244 {
245         struct snd_soc_codec *codec = rk2928_data.codec;
246         if(codec == NULL)
247                 return;
248         if(on)
249                 rk2928_data.headset_status = HP_IN;
250         else
251                 rk2928_data.headset_status = HP_OUT;
252         if(rk2928_data.call_enable)
253                 return;
254         printk("%s: headset %s %s PA bias_level=%d\n",__FUNCTION__,on?"in":"out",on?"disable":"enable",codec->dapm.bias_level);
255         if(on) {
256                 if(rk2928_data.spkctl != INVALID_GPIO)
257                 {
258                         gpio_direction_output(rk2928_data.spkctl, GPIO_LOW);
259                 }
260         }
261         else {
262                 if(codec->dapm.bias_level == SND_SOC_BIAS_STANDBY 
263                 || codec->dapm.bias_level == SND_SOC_BIAS_OFF){
264                         return;
265                 }               
266                 if(rk2928_data.spkctl != INVALID_GPIO)
267                 {
268                         gpio_direction_output(rk2928_data.spkctl, GPIO_HIGH);
269                 }
270         }
271 }
272 #endif
273
274 static int rk2928_audio_hw_params(struct snd_pcm_substream *substream,
275                                     struct snd_pcm_hw_params *params,
276                                     struct snd_soc_dai *dai)
277 {
278 //      struct snd_soc_pcm_runtime *rtd = substream->private_data;
279 //      struct snd_soc_codec *codec = rtd->codec;
280 //      struct rk2928_codec_data *priv = snd_soc_codec_get_drvdata(codec);
281         
282         DBG("%s", __FUNCTION__);
283
284         return 0;
285 }
286
287 static int rk2928_audio_trigger(struct snd_pcm_substream *substream, int cmd,
288                                 struct snd_soc_dai *dai)
289 {
290         struct snd_soc_pcm_runtime *rtd = substream->private_data;
291         struct snd_soc_codec *codec = rtd->codec;
292         struct rk2928_codec_data *priv = snd_soc_codec_get_drvdata(codec);
293         int err = 0;
294         int data, pd_adc;
295         DBG("%s cmd 0x%x", __FUNCTION__, cmd);
296
297         switch (cmd) {
298                 case SNDRV_PCM_TRIGGER_START:
299                 case SNDRV_PCM_TRIGGER_RESUME:
300                 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
301                         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
302 //                              rk2928_write(codec, CODEC_REG_DAC_GAIN, v_GAIN_DAC(DAC_GAIN_3DB_P));
303                                 if(!rk2928_data.hdmi_enable) {
304                                         data = rk2928_read(codec, CODEC_REG_POWER);
305                                         if(soc_is_rk2928g()){
306                                                 if( (data & m_PD_ADC) == 0) {
307                                                         data &= ~m_PD_ADC;
308                                                         data |= v_PD_ADC(1);
309                                                         pd_adc = 1;
310                                                 }
311                                                 else
312                                                         pd_adc = 0;
313                                         }
314                                         else{
315                                                 if( (data & m_PD_ADC_R) == 0) {
316                                                         data &= ~m_PD_ADC_R;
317                                                         data |= v_PD_ADC_R(1);
318                                                         pd_adc = 1;
319                                                 }
320                                                 else
321                                                         pd_adc = 0;
322                                         }
323                                         if(pd_adc == 1) {
324                                                 DBG("%s reg 0x%02x value 0x%02x", __FUNCTION__, CODEC_REG_POWER, data);
325                                                 writel(data, rk2928_data.regbase + CODEC_REG_POWER*4);
326                                                 udelay(100);                                            
327                                         }
328
329                                         rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x03);
330                                         udelay(100);
331                                         rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x00);
332                                         
333                                         udelay(100);
334                                         rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x03);
335                                         udelay(100);
336                                         rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x00);
337                                         
338                                         udelay(100);
339                                         rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x03);
340                                         udelay(100);
341                                         rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x00);
342
343                                         if(pd_adc == 1) {
344                                                 udelay(100);
345                                                 data = rk2928_read(codec, CODEC_REG_POWER);
346                                                 if( soc_is_rk2928g() ) {
347                                                         data &= ~m_PD_ADC;
348                                                         data |= v_PD_ADC(0);
349                                                 }
350                                                 else {
351                                                         data &= ~m_PD_ADC_R;
352                                                         data |= v_PD_ADC_R(0);
353                                                 }
354                                                 DBG("%s reg 0x%02x value 0x%02x", __FUNCTION__, CODEC_REG_POWER, data);
355                                                 writel(data, rk2928_data.regbase + CODEC_REG_POWER*4);
356                                         }
357                                         
358                                         rk2928_write(codec, CODEC_REG_DAC_MUTE, v_MUTE_DAC(0));
359                                         if(rk2928_data.spkctl != INVALID_GPIO && rk2928_data.headset_status == HP_OUT && rk2928_data.stop_phone_depop ) {
360                                                 mdelay(100);
361                                                 gpio_direction_output(rk2928_data.spkctl, GPIO_HIGH);
362                                                 rk2928_data.stop_phone_depop = false;
363                                         }
364                                 }
365                                 rk2928_data.mute = 0;
366                         //      if(rk2928_data.spkctl != INVALID_GPIO && rk2928_data.headset_status == HP_OUT) {
367                         //              gpio_direction_output(rk2928_data.spkctl, GPIO_HIGH);
368                         //      }
369                         }
370                         else {
371                                 rk2928_write(codec, CODEC_REG_ADC_PGA_GAIN, 0xFF);
372                                 rk2928_write(codec, 0x08, 0xff);
373                                 rk2928_write(codec, 0x09, 0x07);
374                         }
375                         break;
376                 case SNDRV_PCM_TRIGGER_STOP:
377                 case SNDRV_PCM_TRIGGER_SUSPEND:
378                 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
379 #ifdef CONFIG_MODEM_SOUND       
380         if(rk2928_data.call_enable)
381                 return err;
382 #endif          
383                         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
384                                 //if(rk2928_data.spkctl != INVALID_GPIO) {
385                                         //gpio_direction_output(rk2928_data.spkctl, GPIO_LOW);
386                                 //}
387                                 rk2928_write(codec, CODEC_REG_DAC_MUTE, v_MUTE_DAC(1));
388                                 rk2928_data.mute = 1;
389                         }
390                         break;
391                 default:
392                         err = -EINVAL;
393         }
394         return err;
395 }
396
397 static int rk2928_audio_startup(struct snd_pcm_substream *substream,
398                                   struct snd_soc_dai *dai)
399 {
400 //      struct snd_soc_pcm_runtime *rtd = substream->private_data;
401 //      struct snd_soc_codec *codec = rtd->codec;
402         DBG("%s", __FUNCTION__);
403         return 0;
404 }
405
406 static int rk2928_set_bias_level(struct snd_soc_codec *codec,
407                               enum snd_soc_bias_level level)
408 {
409         DBG("%s level %d\n", __FUNCTION__, level);
410         
411         if(codec == NULL)
412                 return -1;
413                 
414         switch(level)
415         {
416                 case SND_SOC_BIAS_ON:
417                         break;
418                 case SND_SOC_BIAS_PREPARE:
419                         rk2928_write_mask(codec, CODEC_REG_POWER, m_PD_MIC_BIAS | m_PD_CODEC, v_PD_MIC_BIAS(0) | v_PD_CODEC(0));
420                         break;
421                 case SND_SOC_BIAS_STANDBY:
422                 case SND_SOC_BIAS_OFF:
423                         printk("rk2928 codec standby\n");
424 #ifdef CONFIG_MODEM_SOUND       
425         if(rk2928_data.call_enable)
426                 break;
427 #endif                          
428                 //      if(rk2928_data.spkctl != INVALID_GPIO) {
429                 //              gpio_direction_output(rk2928_data.spkctl, GPIO_LOW);
430                 //      }
431                         rk2928_write(codec, CODEC_REG_POWER, v_PWR_OFF);
432                         break;
433                 default:
434                         return -1;
435         }
436         codec->dapm.bias_level = level;
437         return 0;
438 }
439
440 static void rk2929_codec_reset(void)
441 {
442         // Reset Codec
443         cru_set_soft_reset(SOFT_RST_ACODEC, true);
444         udelay(1000);
445         cru_set_soft_reset(SOFT_RST_ACODEC, false);
446 }
447
448 static int rk2928_probe(struct snd_soc_codec *codec)
449 {
450         struct platform_device *pdev = to_platform_device(codec->dev);
451         struct snd_soc_dapm_context *dapm = &codec->dapm;
452         struct resource *res, *mem;
453         struct rk2928_codec_pdata *pdata;
454         int ret;
455         
456         DBG("%s", __FUNCTION__);
457         
458         snd_soc_codec_set_drvdata(codec, &rk2928_data);
459
460         rk2928_data.dev = &pdev->dev;
461         rk2928_data.pdata = pdev->dev.platform_data;    
462         pdata = rk2928_data.pdata;
463         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
464         if (!res) {
465                 dev_err(&pdev->dev, "Unable to get register resource\n");
466                 ret = -ENXIO;
467                 goto err0;
468         }
469         rk2928_data.regbase_phy = res->start;
470         rk2928_data.regsize_phy = (res->end - res->start) + 1;
471         mem = request_mem_region(res->start, (res->end - res->start) + 1, pdev->name);
472         if (!mem)
473         {
474         dev_err(&pdev->dev, "failed to request mem region for rk2928 codec\n");
475         ret = -ENOENT;
476         goto err0;
477         }
478         
479         rk2928_data.regbase = (int)ioremap(res->start, (res->end - res->start) + 1);
480         if (!rk2928_data.regbase) {
481                 dev_err(&pdev->dev, "cannot ioremap acodec registers\n");
482                 ret = -ENXIO;
483                 goto err1;
484         }
485         
486         rk2928_data.pclk = clk_get(NULL,"pclk_acodec");
487         if(IS_ERR(rk2928_data.pclk))
488         {
489                 dev_err(rk2928_data.dev, "Unable to get acodec hclk\n");
490                 ret = -ENXIO;
491                 goto err1;
492         }
493         clk_enable(rk2928_data.pclk);
494
495         res = platform_get_resource(pdev, IORESOURCE_IO, 0);
496         if(!res) {
497                 rk2928_data.spkctl = INVALID_GPIO;
498         }
499         else {
500                 rk2928_data.spkctl = res->start;
501         }
502
503         if(rk2928_data.spkctl != INVALID_GPIO) {
504                 ret = gpio_request(rk2928_data.spkctl, NULL);
505                 if (ret != 0) {
506                         gpio_free(rk2928_data.spkctl);
507                 }
508                 else
509                         gpio_direction_output(rk2928_data.spkctl, GPIO_LOW);
510         }
511 //------------------------------------------------------------------
512         if (pdata->hpctl) {
513                 ret = pdata->hpctl_io_init();
514                 if (ret) 
515                         goto err1;
516                 rk2928_data.hp_ctl = pdata->hpctl;
517                 gpio_direction_output(rk2928_data.hp_ctl, GPIO_LOW);
518         }
519         //Reset Codec
520         rk2929_codec_reset();
521
522         // Select SDI input from internal audio codec
523         writel(0x04000400, RK2928_GRF_BASE + GRF_SOC_CON0);
524         
525         // Mute and Power off codec
526         rk2928_write(codec, CODEC_REG_DAC_MUTE, v_MUTE_DAC(1));
527         rk2928_set_bias_level(codec, SND_SOC_BIAS_OFF);
528         if(soc_is_rk2928g()){   
529             snd_soc_dapm_new_controls(dapm, rk2928_dapm_widgets,
530                 ARRAY_SIZE(rk2928_dapm_widgets));
531             snd_soc_dapm_add_routes(dapm, rk2928_audio_map, ARRAY_SIZE(rk2928_audio_map));
532         }else{
533             snd_soc_dapm_new_controls(dapm, rk2926_dapm_widgets,
534                 ARRAY_SIZE(rk2926_dapm_widgets));
535             snd_soc_dapm_add_routes(dapm, rk2926_audio_map, ARRAY_SIZE(rk2926_audio_map));
536         }
537
538         INIT_DELAYED_WORK(&rk2928_data.h_delayed_work, call_delay_work);
539         mutex_init(&rk2928_data.mutex_lock);
540         rk2928_data.call_enable = 0;
541         rk2928_data.headset_status = HP_OUT;
542         rk2928_data.codec=codec;
543         rk2928_data.stop_phone_depop=false;
544         return 0;
545         
546 err1:
547         release_mem_region(res->start,(res->end - res->start) + 1);
548 //      clk_disable(rk2928_data.hclk);
549 err0:
550         DBG("%s failed", __FUNCTION__);
551         return ret;
552 }
553
554 static int rk2928_remove(struct snd_soc_codec *codec)
555 {
556         return 0;
557 }
558
559 static int rk2928_suspend(struct snd_soc_codec *codec)
560 {
561         DBG("%s", __FUNCTION__);
562         rk2928_set_bias_level(codec, SND_SOC_BIAS_OFF);
563         clk_disable(rk2928_data.pclk);
564         return 0;
565 }
566
567 static int rk2928_resume(struct snd_soc_codec *codec)
568 {
569         DBG("%s", __FUNCTION__);
570         clk_enable(rk2928_data.pclk);
571         rk2928_write(codec, CODEC_REG_POWER, v_PD_ADC(1) | v_PD_DAC(1) | v_PD_MIC_BIAS(0));
572         return 0;
573 }
574
575 static struct snd_soc_codec_driver rk2928_audio_codec_drv = {
576         .probe = rk2928_probe,
577         .remove = rk2928_remove,
578         .suspend = rk2928_suspend,
579         .resume = rk2928_resume,
580         .read = rk2928_read,
581         .write = rk2928_write,
582         .set_bias_level = rk2928_set_bias_level,
583 };
584
585 static struct snd_soc_dai_ops rk2928_audio_codec_ops = {
586         .hw_params = rk2928_audio_hw_params,
587         .trigger = rk2928_audio_trigger,
588         .startup = rk2928_audio_startup,
589 };
590
591 static struct snd_soc_dai_driver rk2928_codec_dai = {
592         .name = "rk2928-codec",
593         .playback = {
594                 .stream_name = "HIFI Playback",
595                 .channels_min = 1,
596                 .channels_max = 2,
597                 .rates = SNDRV_PCM_RATE_8000_48000,
598                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | 
599                         SNDRV_PCM_FMTBIT_S24_LE,
600         },
601         .capture = {
602                 .stream_name = "HIFI Capture",
603                 .channels_min = 1,
604                 .channels_max = 2,
605                 .rates = SNDRV_PCM_RATE_8000_48000,
606                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE,
607         },
608         .ops = &rk2928_audio_codec_ops,
609 };
610
611 static int rk2928_codec_probe(struct platform_device *pdev)
612 {
613         int r;
614         
615         DBG("%s", __FUNCTION__);
616         
617         /* Register ASoC codec DAI */
618         r = snd_soc_register_codec(&pdev->dev, &rk2928_audio_codec_drv,
619                                         &rk2928_codec_dai, 1);
620         if (r) {
621                 dev_err(&pdev->dev, "can't register ASoC rk2928 audio codec\n");
622                 return r;
623         }
624         
625         DBG("%s success", __FUNCTION__);
626         return 0;
627         
628 }
629
630 static int __devexit rk2928_codec_remove(struct platform_device *pdev)
631 {
632         snd_soc_unregister_codec(&pdev->dev);
633         return 0;
634 }
635
636 static void rk2928_codec_shutdown(struct platform_device *pdev)
637 {
638         printk("%s .....\n", __FUNCTION__);
639         if(rk2928_data.spkctl != INVALID_GPIO)
640                 gpio_direction_output(rk2928_data.spkctl, GPIO_LOW);
641         if(rk2928_data.hp_ctl != 0 ) 
642                 gpio_direction_output(rk2928_data.hp_ctl, GPIO_LOW);    
643 }
644 static struct platform_driver rk2928_codec_driver = {
645         .probe          = rk2928_codec_probe,
646         .remove         = __devexit_p(rk2928_codec_remove),
647         .driver         = {
648                 .name   = "rk2928-codec",
649                 .owner  = THIS_MODULE,
650         },
651         .shutdown = rk2928_codec_shutdown,
652 };
653
654 static int __init rk2928_codec_init(void)
655 {
656         return platform_driver_register(&rk2928_codec_driver);
657 }
658 module_init(rk2928_codec_init);
659
660 static void __exit rk2928_codec_exit(void)
661 {
662         #ifdef CODEC_I2C_MODE
663         i2c_del_driver(&rk2928_codec_driver);
664         #else
665         platform_driver_unregister(&rk2928_codec_driver);
666         #endif
667 }
668 module_exit(rk2928_codec_exit);
669
670 MODULE_DESCRIPTION("ASoC RK2928 codec driver");
671 MODULE_LICENSE("GPL");