tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / sound / soc / sprd / dai / vbc / r1p0 / vbc-codec.c
1 /*
2  * sound/soc/sprd/dai/vbc/r1p0/vbc-codec.c
3  *
4  * SPRD SoC VBC Codec -- SpreadTrum SOC VBC Codec function.
5  *
6  * Copyright (C) 2013 SpreadTrum Ltd.
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  */
17 #include <linux/module.h>
18 #include <linux/moduleparam.h>
19 #include <linux/init.h>
20 #include <linux/kernel.h>
21 #include <linux/string.h>
22 #include <linux/sysfs.h>
23 #include <linux/stat.h>
24 #include <linux/device.h>
25 #include <linux/platform_device.h>
26 #include <linux/slab.h>
27 #include <linux/firmware.h>
28 #include <linux/workqueue.h>
29 #include <linux/io.h>
30 #include <sound/core.h>
31 #include <sound/soc.h>
32 #include <sound/soc-dapm.h>
33 #include <sound/pcm_params.h>
34 #include <sound/tlv.h>
35
36 #include "sprd-asoc-common.h"
37 #include "vbc-codec.h"
38
39 #define FUN_REG(f) ((unsigned short)(-((f) + 1)))
40 #define SOC_REG(r) ((unsigned short)(r))
41
42 struct vbc_fw_header {
43         char magic[VBC_EQ_FIRMWARE_MAGIC_LEN];
44         u32 profile_version;
45         u32 num_profile;
46 };
47
48 struct vbc_eq_profile {
49         char magic[VBC_EQ_FIRMWARE_MAGIC_LEN];
50         char name[VBC_EQ_PROFILE_NAME_MAX];
51         /* TODO */
52         u32 effect_paras[VBC_EFFECT_PARAS_LEN];
53 };
54
55 static const u32 vbc_eq_profile_default[VBC_EFFECT_PARAS_LEN] = {
56 /* TODO the default register value */
57         0x00000000,             /*  DAPATCHCTL      */
58         0x00001818,             /*  DADGCTL         */
59         0x0000007F,             /*  DAHPCTL         */
60         0x00000000,             /*  DAALCCTL0       */
61         0x00000000,             /*  DAALCCTL1       */
62         0x00000000,             /*  DAALCCTL2       */
63         0x00000000,             /*  DAALCCTL3       */
64         0x00000000,             /*  DAALCCTL4       */
65         0x00000000,             /*  DAALCCTL5       */
66         0x00000000,             /*  DAALCCTL6       */
67         0x00000000,             /*  DAALCCTL7       */
68         0x00000000,             /*  DAALCCTL8       */
69         0x00000000,             /*  DAALCCTL9       */
70         0x00000000,             /*  DAALCCTL10      */
71         0x00000183,             /*  STCTL0          */
72         0x00000183,             /*  STCTL1          */
73         0x00000000,             /*  ADPATCHCTL      */
74         0x00001818,             /*  ADDGCTL         */
75         0x00000000,             /*  HPCOEF0         */
76 };
77
78 struct vbc_equ {
79         struct device *dev;
80         struct snd_soc_codec *codec;
81         int is_active;
82         int is_loading;
83         int valid;
84         int now_profile;
85         struct vbc_fw_header hdr;
86         struct vbc_eq_profile *data;
87         void (*vbc_eq_apply) (struct snd_soc_codec * codec, void *data,
88                               int vbc_idx);
89 };
90
91 static void vbc_eq_try_apply(struct snd_soc_codec *codec, int vbc_idx);
92
93 #define VBC_DG_VAL_MAX (0x7F)
94
95 typedef int (*vbc_dg_set) (int enable, int dg);
96 struct vbc_dg {
97         int dg_switch[2];
98         int dg_val[2];
99         vbc_dg_set dg_set[2];
100 };
101
102 struct st_hpf_dg {
103         int hpf_switch[2];
104         int dg_val[2];
105         int hpf_val[2];
106 };
107
108 /*vbc mux setting*/
109 enum {
110         SPRD_VBC_MUX_START = 0,
111         SPRD_VBC_AD0_INMUX,
112         SPRD_VBC_AD1_INMUX,
113         SPRD_VBC_AD_IISMUX,
114         SPRD_VBC_MUX_MAX
115 };
116
117 #define IS_SPRD_VBC_MUX_RANG(reg) ((reg) >= SPRD_VBC_MUX_START && (reg) < (SPRD_VBC_MUX_MAX))
118 #define SPRD_VBC_MUX_IDX(reg) (reg - SPRD_VBC_MUX_START)
119
120 static const char *vbc_mux_debug_str[SPRD_VBC_MUX_MAX] = {
121         "ad0 inmux",
122         "ad1 inmux",
123         "ad iis mux",
124 };
125
126 typedef int (*sprd_vbc_mux_set) (int sel);
127 struct sprd_vbc_mux_op {
128         int val;
129         sprd_vbc_mux_set set;
130 };
131
132 enum {
133         VBC_LOOP_SWITCH_START = SPRD_VBC_MUX_MAX,
134         VBC_AD_LOOP_SWITCH = VBC_LOOP_SWITCH_START,
135         VBC_LOOP_SWITCH_MAX
136 };
137
138 #define IS_SPRD_VBC_SWITCH_RANG(reg) ((reg) >= VBC_LOOP_SWITCH_START && (reg) < (VBC_LOOP_SWITCH_MAX))
139 #define SPRD_VBC_SWITCH_IDX(reg) (reg - VBC_LOOP_SWITCH_START)
140
141 struct vbc_codec_priv {
142         struct snd_soc_codec *codec;
143         struct vbc_equ vbc_eq_setting;
144         struct mutex load_mutex;
145         int vbc_control;
146         int vbc_loop_switch[SPRD_VBC_SWITCH_IDX(VBC_LOOP_SWITCH_MAX)];
147         struct vbc_dg dg[VBC_IDX_MAX];
148         int vbc_da_iis_port;
149         int adc_dgmux_val[ADC_DGMUX_MAX];
150         struct st_hpf_dg st_dg;
151         struct sprd_vbc_mux_op sprd_vbc_mux[SPRD_VBC_MUX_MAX];
152 };
153
154 static int vbc_ad0_inmux_set(int val)
155 {
156         vbc_reg_update(ADPATCHCTL, val << VBADPATH_AD0_INMUX_SHIFT,
157                        VBADPATH_AD0_INMUX_MASK);
158         return 0;
159 }
160
161 static int vbc_ad1_inmux_set(int val)
162 {
163         vbc_reg_update(ADPATCHCTL, val << VBADPATH_AD1_INMUX_SHIFT,
164                        VBADPATH_AD1_INMUX_MASK);
165         return 0;
166 }
167
168 static int vbc_ad0_dgmux_set(int val)
169 {
170         vbc_reg_update(ADPATCHCTL, val << VBADPATH_AD0_DGMUX_SHIFT,
171                        VBADPATH_AD0_DGMUX_MASK);
172         return 0;
173 }
174
175 static int vbc_ad1_dgmux_set(int val)
176 {
177         vbc_reg_update(ADPATCHCTL, val << VBADPATH_AD1_DGMUX_SHIFT,
178                        VBADPATH_AD1_DGMUX_MASK);
179         return 0;
180 }
181
182 static int vbc_ad_iismux_set(int port)
183 {
184         vbc_reg_update(VBIISSEL, port << VBIISSEL_AD_PORT_SHIFT,
185                        VBIISSEL_AD_PORT_MASK);
186         return 0;
187 }
188
189 static int vbc_da_iismux_set(int port)
190 {
191         vbc_reg_update(VBIISSEL, port << VBIISSEL_DA_PORT_SHIFT,
192                        VBIISSEL_DA_PORT_MASK);
193         return 0;
194 }
195
196 static int vbc_try_ad_iismux_set(int port);
197
198 static sprd_vbc_mux_set vbc_mux_cfg[SPRD_VBC_MUX_MAX] = {
199         vbc_ad0_inmux_set,
200         vbc_ad1_inmux_set,
201         vbc_try_ad_iismux_set,
202 };
203
204 static inline int vbc_da0_dg_set(int enable, int dg)
205 {
206         if (enable) {
207                 vbc_reg_update(DADGCTL, 0x80 | (0xFF & dg), 0xFF);
208         } else {
209                 vbc_reg_update(DADGCTL, 0, 0x80);
210         }
211         return 0;
212 }
213
214 static inline int vbc_da1_dg_set(int enable, int dg)
215 {
216         if (enable) {
217                 vbc_reg_update(DADGCTL, (0x80 | (0xFF & dg)) << 8, 0xFF00);
218         } else {
219                 vbc_reg_update(DADGCTL, 0, 0x8000);
220         }
221         return 0;
222 }
223
224 static inline int vbc_ad0_dg_set(int enable, int dg)
225 {
226         if (enable) {
227                 vbc_reg_update(ADDGCTL, 0x80 | (0xFF & dg), 0xFF);
228         } else {
229                 vbc_reg_update(ADDGCTL, 0, 0x80);
230         }
231         return 0;
232 }
233
234 static inline int vbc_ad1_dg_set(int enable, int dg)
235 {
236         if (enable) {
237                 vbc_reg_update(ADDGCTL, (0x80 | (0xFF & dg)) << 8, 0xFF00);
238         } else {
239                 vbc_reg_update(ADDGCTL, 0, 0x8000);
240         }
241         return 0;
242 }
243
244 static inline int vbc_st0_dg_set(int dg)
245 {
246         vbc_reg_update(STCTL0, (0x7F & dg) << 4, 0x7F0);
247         return 0;
248 }
249
250 static inline int vbc_st1_dg_set(int dg)
251 {
252         vbc_reg_update(STCTL1, (0x7F & dg) << 4, 0x7F0);
253         return 0;
254 }
255
256 static inline int vbc_st0_hpf_set(int enable, int hpf_val)
257 {
258         if (enable) {
259                 vbc_reg_update(STCTL0, BIT(VBST_HPF_0), BIT(VBST_HPF_0));
260                 vbc_reg_update(STCTL0, 0xF & hpf_val, 0xF);
261         } else {
262                 vbc_reg_update(STCTL0, 0, BIT(VBST_HPF_0));
263                 vbc_reg_update(STCTL0, 3, 0xF);
264         }
265         return 0;
266 }
267
268 static inline int vbc_st1_hpf_set(int enable, int hpf_val)
269 {
270         if (enable) {
271                 vbc_reg_update(STCTL1, BIT(VBST_HPF_1), BIT(VBST_HPF_1));
272                 vbc_reg_update(STCTL1, 0xF & hpf_val, 0xF);
273         } else {
274                 vbc_reg_update(STCTL1, 0, BIT(VBST_HPF_1));
275                 vbc_reg_update(STCTL1, 3, 0xF);
276         }
277         return 0;
278 }
279
280 static int vbc_try_dg_set(struct vbc_codec_priv *vbc_codec, int vbc_idx, int id)
281 {
282         struct vbc_dg *p_dg = &vbc_codec->dg[vbc_idx];
283         int dg = p_dg->dg_val[id];
284         if (p_dg->dg_switch[id]) {
285                 p_dg->dg_set[id] (1, dg);
286         } else {
287                 p_dg->dg_set[id] (0, dg);
288         }
289         return 0;
290 }
291
292 static int vbc_try_st_dg_set(struct vbc_codec_priv *vbc_codec, int id)
293 {
294         struct st_hpf_dg *p_st_dg = &vbc_codec->st_dg;
295         if (id == VBC_LEFT) {
296                 vbc_st0_dg_set(p_st_dg->dg_val[id]);
297         } else {
298                 vbc_st1_dg_set(p_st_dg->dg_val[id]);
299         }
300         return 0;
301 }
302
303 static int vbc_try_st_hpf_set(struct vbc_codec_priv *vbc_codec, int id)
304 {
305         struct st_hpf_dg *p_st_dg = &vbc_codec->st_dg;
306         if (id == VBC_LEFT) {
307                 vbc_st0_hpf_set(p_st_dg->hpf_switch[id], p_st_dg->hpf_val[id]);
308         } else {
309                 vbc_st1_hpf_set(p_st_dg->hpf_switch[id], p_st_dg->hpf_val[id]);
310         }
311         return 0;
312 }
313
314 static int vbc_try_da_iismux_set(int port)
315 {
316         return vbc_da_iismux_set(port ? (port + 1) : 0);
317 }
318
319 static int vbc_try_ad_iismux_set(int port)
320 {
321         return vbc_ad_iismux_set(port);
322 }
323
324 static int vbc_try_ad_dgmux_set(struct vbc_codec_priv *vbc_codec, int id)
325 {
326         switch (id) {
327         case ADC0_DGMUX:
328                 vbc_ad0_dgmux_set(vbc_codec->adc_dgmux_val[ADC0_DGMUX]);
329                 break;
330         case ADC1_DGMUX:
331                 vbc_ad1_dgmux_set(vbc_codec->adc_dgmux_val[ADC1_DGMUX]);
332                 break;
333         default:
334                 break;
335         }
336         return 0;
337 }
338
339 #ifdef CONFIG_SND_SOC_SPRD_AUDIO_DEBUG
340 static const char *get_event_name(int event)
341 {
342         const char *ev_name;
343         switch (event) {
344         case SND_SOC_DAPM_PRE_PMU:
345                 ev_name = "PRE_PMU";
346                 break;
347         case SND_SOC_DAPM_POST_PMU:
348                 ev_name = "POST_PMU";
349                 break;
350         case SND_SOC_DAPM_PRE_PMD:
351                 ev_name = "PRE_PMD";
352                 break;
353         case SND_SOC_DAPM_POST_PMD:
354                 ev_name = "POST_PMD";
355                 break;
356         default:
357                 BUG();
358                 return 0;
359         }
360         return ev_name;
361 }
362 #endif
363
364 static const char *ad0_inmux_txt[] = {
365         "IIS0AD0", "IIS1AD0", "NOINPUT",
366 };
367
368 static const char *ad1_inmux_txt[] = {
369         "IIS1AD1", "IIS0AD1", "NOINPUT",
370 };
371
372 static const char *ad_iis_txt[] = {
373         "AUDIIS0", "DIGFM",
374 };
375
376 #define SPRD_VBC_ENUM(xreg, xmax, xtexts)\
377                   SOC_ENUM_SINGLE(FUN_REG(xreg), 0, xmax, xtexts)
378
379 static const struct soc_enum vbc_mux_sel_enum[SPRD_VBC_MUX_MAX] = {
380         /*AD INMUX */
381         SPRD_VBC_ENUM(SPRD_VBC_AD0_INMUX, 4, ad0_inmux_txt),
382         SPRD_VBC_ENUM(SPRD_VBC_AD1_INMUX, 4, ad1_inmux_txt),
383         /*IIS INMUX */
384         SPRD_VBC_ENUM(SPRD_VBC_AD_IISMUX, 4, ad_iis_txt),
385 };
386
387 static int vbc_chan_event(struct snd_soc_dapm_widget *w,
388                           struct snd_kcontrol *kcontrol, int event)
389 {
390         int vbc_idx = FUN_REG(w->reg);
391         int chan = w->shift;
392         int ret = 0;
393
394         sp_asoc_pr_dbg("%s(%s%d) Event is %s\n", __func__,
395                        vbc_get_name(vbc_idx), chan, get_event_name(event));
396
397         switch (event) {
398         case SND_SOC_DAPM_PRE_PMU:
399                 vbc_chan_enable(1, vbc_idx, chan);
400                 break;
401         case SND_SOC_DAPM_POST_PMD:
402                 vbc_chan_enable(0, vbc_idx, chan);
403                 break;
404         default:
405                 BUG();
406                 ret = -EINVAL;
407                 break;
408         }
409
410         return ret;
411 }
412
413 static int vbc_power_event(struct snd_soc_dapm_widget *w,
414                            struct snd_kcontrol *kcontrol, int event)
415 {
416         int ret = 0;
417
418         sp_asoc_pr_dbg("%s Event is %s\n", __func__, get_event_name(event));
419
420         switch (event) {
421         case SND_SOC_DAPM_PRE_PMU:
422                 vbc_power(1);
423                 break;
424         case SND_SOC_DAPM_POST_PMD:
425                 vbc_power(0);
426                 break;
427         default:
428                 BUG();
429                 ret = -EINVAL;
430                 break;
431         }
432
433         return ret;
434 }
435
436 static int dfm_event(struct snd_soc_dapm_widget *w,
437                      struct snd_kcontrol *kcontrol, int event)
438 {
439         struct snd_soc_codec *codec = w->codec;
440         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
441         struct vbc_equ *p_eq_setting = &vbc_codec->vbc_eq_setting;
442         int ret = 0;
443
444         sp_asoc_pr_dbg("%s Event is %s\n", __func__, get_event_name(event));
445         switch (event) {
446         case SND_SOC_DAPM_POST_PMU:
447                 fm_set_vbc_buffer_size();       /*No use in FM function, just for debug VBC */
448                 vbc_try_st_dg_set(vbc_codec, VBC_LEFT);
449                 vbc_try_st_dg_set(vbc_codec, VBC_RIGHT);
450                 if (!p_eq_setting->codec)
451                         p_eq_setting->codec = codec;
452                 /*eq setting */
453                 if (p_eq_setting->is_active && p_eq_setting->data)
454                         vbc_eq_try_apply(codec, VBC_PLAYBACK);
455                 vbc_enable(1);
456                 break;
457         case SND_SOC_DAPM_PRE_PMD:
458                 vbc_enable(0);
459                 break;
460         default:
461                 BUG();
462                 ret = -EINVAL;
463         }
464
465         return ret;
466 }
467
468 static int aud_event(struct snd_soc_dapm_widget *w,
469                      struct snd_kcontrol *kcontrol, int event)
470 {
471         struct snd_soc_codec *codec = w->codec;
472         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
473         unsigned int vbc_idx = FUN_REG(w->reg);
474         struct vbc_equ *p_eq_setting = &vbc_codec->vbc_eq_setting;
475         int ret = 0;
476
477         sp_asoc_pr_dbg("%s Event is %s\n Chan is %s", __func__,
478                        get_event_name(event), vbc_get_name(vbc_idx));
479
480         switch (event) {
481         case SND_SOC_DAPM_PRE_PMU:
482                 /*eq setting */
483                 if (!p_eq_setting->codec)
484                         p_eq_setting->codec = codec;
485                 if (p_eq_setting->is_active && p_eq_setting->data)
486                         vbc_eq_try_apply(codec, vbc_idx);
487                 break;
488         case SND_SOC_DAPM_PRE_PMD:
489                 break;
490         default:
491                 BUG();
492                 ret = -EINVAL;
493         }
494
495         return ret;
496 }
497
498 static int mux_event(struct snd_soc_dapm_widget *w,
499                      struct snd_kcontrol *kcontrol, int event)
500 {
501         struct snd_soc_codec *codec = w->codec;
502         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
503         unsigned int id = SPRD_VBC_MUX_IDX(FUN_REG(w->reg));
504         struct sprd_vbc_mux_op *mux = &(vbc_codec->sprd_vbc_mux[id]);
505         int ret = 0;
506
507         sp_asoc_pr_dbg("%s Set %s(%d) Event is %s\n", __func__,
508                        vbc_mux_debug_str[id], mux->val, get_event_name(event));
509
510         switch (event) {
511         case SND_SOC_DAPM_PRE_PMU:
512                 mux->set = vbc_mux_cfg[id];
513                 ret = mux->set(mux->val);
514                 break;
515         case SND_SOC_DAPM_PRE_PMD:
516                 mux->set = 0;
517                 ret = vbc_mux_cfg[id] (0);
518                 break;
519         default:
520                 BUG();
521                 ret = -EINVAL;
522         }
523
524         return ret;
525 }
526
527 static int sprd_vbc_mux_get(struct snd_kcontrol *kcontrol,
528                             struct snd_ctl_elem_value *ucontrol)
529 {
530         struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
531         struct snd_soc_dapm_widget *widget = wlist->widgets[0];
532         struct snd_soc_codec *codec = widget->codec;
533         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
534         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
535         unsigned int reg = SPRD_VBC_MUX_IDX(FUN_REG(e->reg));
536         struct sprd_vbc_mux_op *mux = &(vbc_codec->sprd_vbc_mux[reg]);
537
538         ucontrol->value.enumerated.item[0] = mux->val;
539
540         return 0;
541 }
542
543 static int sprd_vbc_mux_put(struct snd_kcontrol *kcontrol,
544                             struct snd_ctl_elem_value *ucontrol)
545 {
546         struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
547         struct snd_soc_dapm_widget *widget = wlist->widgets[0];
548         struct snd_soc_codec *codec = widget->codec;
549         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
550         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
551         unsigned int reg = SPRD_VBC_MUX_IDX(FUN_REG(e->reg));
552         unsigned int max = e->max;
553         unsigned int mask = (1 << fls(max)) - 1;
554         struct sprd_vbc_mux_op *mux = &(vbc_codec->sprd_vbc_mux[reg]);
555         int ret = 0;
556
557         if (mux->val == ucontrol->value.enumerated.item[0])
558                 return 0;
559
560         sp_asoc_pr_info("Set MUX[%s] to %d\n", vbc_mux_debug_str[reg],
561                         ucontrol->value.enumerated.item[0]);
562
563         if (ucontrol->value.enumerated.item[0] > e->max - 1)
564                 return -EINVAL;
565
566         /*notice the sequence */
567         ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
568
569         /*update reg: must be set after snd_soc_dapm_put_enum_double->change = snd_soc_test_bits(widget->codec, e->reg, mask, val); */
570         mux->val = (ucontrol->value.enumerated.item[0] & mask);
571         if (mux->set) {
572                 ret = mux->set(mux->val);
573         }
574
575         return ret;
576 }
577
578 #define SPRD_VBC_MUX(xname, xenum) \
579          SOC_DAPM_ENUM_EXT(xname, xenum, sprd_vbc_mux_get, sprd_vbc_mux_put)
580
581 static const struct snd_kcontrol_new vbc_mux[SPRD_VBC_MUX_MAX] = {
582         SPRD_VBC_MUX("AD0 INMUX", vbc_mux_sel_enum[SPRD_VBC_AD0_INMUX]),
583         SPRD_VBC_MUX("AD1 INMUX", vbc_mux_sel_enum[SPRD_VBC_AD1_INMUX]),
584         SPRD_VBC_MUX("AD IISMUX", vbc_mux_sel_enum[SPRD_VBC_AD_IISMUX]),
585 };
586
587 #define VBC_DAPM_MUX_E(wname, wreg) \
588         SND_SOC_DAPM_MUX_E(wname, FUN_REG(wreg), 0, 0, &vbc_mux[wreg], mux_event, \
589                                                         SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD)
590
591 static int vbc_loop_switch_get(struct snd_kcontrol *kcontrol,
592                                struct snd_ctl_elem_value *ucontrol)
593 {
594         struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
595         struct snd_soc_dapm_widget *widget = wlist->widgets[0];
596         struct snd_soc_codec *codec = widget->codec;
597         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
598         struct soc_mixer_control *mc =
599             (struct soc_mixer_control *)kcontrol->private_value;
600         int id = SPRD_VBC_SWITCH_IDX(FUN_REG(mc->reg));
601         ucontrol->value.integer.value[0] = vbc_codec->vbc_loop_switch[id];
602         return 0;
603 }
604
605 static int vbc_loop_switch_put(struct snd_kcontrol *kcontrol,
606                                struct snd_ctl_elem_value *ucontrol)
607 {
608         int ret = 0;
609         struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
610         struct snd_soc_dapm_widget *widget = wlist->widgets[0];
611         struct snd_soc_codec *codec = widget->codec;
612         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
613         struct soc_mixer_control *mc =
614             (struct soc_mixer_control *)kcontrol->private_value;
615         int id = SPRD_VBC_SWITCH_IDX(FUN_REG(mc->reg));
616
617         ret = ucontrol->value.integer.value[0];
618         if (ret == vbc_codec->vbc_loop_switch[id]) {
619                 return ret;
620         }
621
622         sp_asoc_pr_info("VBC AD LOOP Switch Set %x\n",
623                         (int)ucontrol->value.integer.value[0]);
624
625         snd_soc_dapm_put_volsw(kcontrol, ucontrol);
626
627         vbc_codec->vbc_loop_switch[id] = ret;
628
629         return ret;
630 }
631
632 static const struct snd_kcontrol_new vbc_loop_control[] = {
633         SOC_SINGLE_EXT("Switch",
634                        FUN_REG(VBC_AD_LOOP_SWITCH),
635                        0, 1, 0,
636                        vbc_loop_switch_get,
637                        vbc_loop_switch_put),
638 };
639
640 static const struct snd_soc_dapm_widget vbc_codec_dapm_widgets[] = {
641         /*power */
642         SND_SOC_DAPM_SUPPLY("VBC Power", SND_SOC_NOPM, 0, 0,
643                             vbc_power_event,
644                             SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
645
646         /*ADC inmux */
647         VBC_DAPM_MUX_E("AD0 INMUX", SPRD_VBC_AD0_INMUX),
648         VBC_DAPM_MUX_E("AD1 INMUX", SPRD_VBC_AD1_INMUX),
649
650         /*IIS MUX */
651         VBC_DAPM_MUX_E("AD IISMUX", SPRD_VBC_AD_IISMUX),
652
653         /*ST Switch */
654         SND_SOC_DAPM_PGA_S("ST0 Switch", 4, SOC_REG(STCTL0), VBST_EN_0, 0, NULL,
655                            0),
656         SND_SOC_DAPM_PGA_S("ST1 Switch", 4, SOC_REG(STCTL1), VBST_EN_1, 0, NULL,
657                            0),
658
659         /*FM Mixer */
660         SND_SOC_DAPM_PGA_S("DA0 FM Mixer", 4, SOC_REG(DAPATCHCTL),
661                            VBDAPATH_DA0_ADDFM_SHIFT, 0, NULL, 0),
662         SND_SOC_DAPM_PGA_S("DA1 FM Mixer", 4, SOC_REG(DAPATCHCTL),
663                            VBDAPATH_DA1_ADDFM_SHIFT, 0, NULL, 0),
664
665         SND_SOC_DAPM_LINE("DFM", dfm_event),
666
667         /*VBC Chan Switch */
668         SND_SOC_DAPM_PGA_S("DA0 Switch", 5, FUN_REG(VBC_PLAYBACK), VBC_LEFT, 0,
669                            vbc_chan_event,
670                            SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
671
672         SND_SOC_DAPM_PGA_S("DA1 Switch", 5, FUN_REG(VBC_PLAYBACK), VBC_RIGHT, 0,
673                            vbc_chan_event,
674                            SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
675
676         SND_SOC_DAPM_PGA_S("AD0 Switch", 5, FUN_REG(VBC_CAPTRUE), VBC_LEFT, 0,
677                            vbc_chan_event,
678                            SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
679
680         SND_SOC_DAPM_PGA_S("AD1 Switch", 5, FUN_REG(VBC_CAPTRUE), VBC_RIGHT, 0,
681                            vbc_chan_event,
682                            SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
683
684         /*AUD loop var vbc switch */
685         SND_SOC_DAPM_PGA_S("Aud input", 4, FUN_REG(VBC_CAPTRUE), 0, 0,
686                            aud_event,
687                            SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
688         SND_SOC_DAPM_SWITCH("Aud Loop in VBC", SND_SOC_NOPM, 0, 0,
689                             &vbc_loop_control[SPRD_VBC_SWITCH_IDX
690                                               (VBC_AD_LOOP_SWITCH)]),
691 };
692
693 /* sprd_vbc supported interconnection*/
694 static const struct snd_soc_dapm_route vbc_codec_intercon[] = {
695         /************************power********************************/
696         /* digital fm playback need to open DA Clk and DA power */
697         {"DFM", NULL, "VBC Power"},
698
699         /********************** capture in  path in vbc ********************/
700         /* AD input route */
701         {"Aud Loop in VBC", "Switch", "Aud input"},
702
703         /* AD */
704         {"AD IISMUX", "DIGFM", "Dig FM Jack"},
705         {"AD IISMUX", "AUDIIS0", "Aud Loop in VBC"},
706
707         {"AD0 INMUX", "IIS0AD0", "AD IISMUX"},
708         {"AD0 INMUX", "IIS1AD0", "AD IISMUX"},
709         {"AD1 INMUX", "IIS1AD1", "AD IISMUX"},
710         {"AD1 INMUX", "IIS0AD1", "AD IISMUX"},
711
712         {"AD0 Switch", NULL, "AD0 INMUX"},
713         {"AD1 Switch", NULL, "AD1 INMUX"},
714
715         /********************** fm playback route ********************/
716         /*ST route */
717         {"ST0 INMUX", NULL, "AD0 Switch"},
718         {"ST1 INMUX", NULL, "AD1 Switch"},
719
720         {"ST0 Switch", NULL, "ST0 INMUX"},
721         {"ST1 Switch", NULL, "ST1 INMUX"},
722         {"DA0 Switch", NULL, "ST0 Switch"},
723         {"DA1 Switch", NULL, "ST1 Switch"},
724         {"DA0 FM Mixer", NULL, "DA0 Switch"},
725         {"DA1 FM Mixer", NULL, "DA1 Switch"},
726         {"DFM", NULL, "DA0 FM Mixer"},
727         {"DFM", NULL, "DA1 FM Mixer"},
728 };
729
730 int vbc_codec_startup(int vbc_idx, struct snd_soc_dai *dai)
731 {
732         struct vbc_codec_priv *vbc_codec = dev_get_drvdata(dai->dev);
733         struct vbc_equ *p_eq_setting = &vbc_codec->vbc_eq_setting;
734         sp_asoc_pr_dbg("%s %s\n", __func__, vbc_get_name(vbc_idx));
735
736         switch (vbc_idx) {
737         case VBC_PLAYBACK:
738                 vbc_try_da_iismux_set(vbc_codec->vbc_da_iis_port);
739                 break;
740         case VBC_CAPTRUE:
741                 vbc_try_ad_iismux_set(vbc_codec->sprd_vbc_mux
742                                       [SPRD_VBC_AD_IISMUX].val);
743                 vbc_try_ad_dgmux_set(vbc_codec, 0);
744                 vbc_try_ad_dgmux_set(vbc_codec, 1);
745                 break;
746         }
747
748         if (p_eq_setting->is_active && p_eq_setting->data)
749                 vbc_eq_try_apply(vbc_codec->codec, vbc_idx);
750
751         vbc_try_dg_set(vbc_codec, vbc_idx, VBC_LEFT);
752         vbc_try_dg_set(vbc_codec, vbc_idx, VBC_RIGHT);
753
754         return 0;
755 }
756
757 /*
758  * proc interface
759  */
760
761 #ifdef CONFIG_PROC_FS
762 static void vbc_proc_read(struct snd_info_entry *entry,
763                           struct snd_info_buffer *buffer)
764 {
765         int reg;
766
767         snd_iprintf(buffer, "vbc register dump\n");
768         for (reg = ARM_VB_BASE + 0x10; reg < ARM_VB_END; reg += 0x10) {
769                 snd_iprintf(buffer, "0x%04x | 0x%04x 0x%04x 0x%04x 0x%04x\n",
770                             (reg - ARM_VB_BASE)
771                             , vbc_reg_read(reg + 0x00)
772                             , vbc_reg_read(reg + 0x04)
773                             , vbc_reg_read(reg + 0x08)
774                             , vbc_reg_read(reg + 0x0C)
775                     );
776         }
777 }
778
779 static void vbc_proc_init(struct snd_soc_codec *codec)
780 {
781         struct snd_info_entry *entry;
782
783         if (!snd_card_proc_new(codec->card->snd_card, "vbc", &entry))
784                 snd_info_set_text_ops(entry, NULL, vbc_proc_read);
785 }
786 #else /* !CONFIG_PROC_FS */
787 static inline void vbc_proc_init(struct snd_soc_codec *codec)
788 {
789 }
790 #endif
791
792 static int vbc_eq_reg_offset(u32 reg)
793 {
794         int i = 0;
795         if ((reg >= DAPATCHCTL) && (reg <= ADDGCTL)) {
796                 i = (reg - DAPATCHCTL) >> 2;
797         } else if ((reg >= HPCOEF0) && (reg <= HPCOEF42)) {
798                 i = ((reg - HPCOEF0) >> 2) + ((ADDGCTL - DAPATCHCTL) >> 2) + 1;
799         }
800         BUG_ON(i >= VBC_EFFECT_PARAS_LEN);
801         return i;
802 }
803
804 static inline void vbc_eq_reg_set(u32 reg, void *data)
805 {
806         u32 *effect_paras = (u32 *) data;
807         vbc_reg_write(reg, effect_paras[vbc_eq_reg_offset(reg)]);
808 }
809
810 static inline void vbc_eq_reg_set_range(u32 reg_start, u32 reg_end, void *data)
811 {
812         u32 reg_addr;
813         for (reg_addr = reg_start; reg_addr <= reg_end; reg_addr += 4) {
814                 vbc_eq_reg_set(reg_addr, data);
815         }
816 }
817
818 static void vbc_eq_reg_apply(struct snd_soc_codec *codec, void *data,
819                              int vbc_idx)
820 {
821         if (vbc_idx == VBC_PLAYBACK) {
822                 vbc_eq_reg_set_range(DAALCCTL0, DAALCCTL10, data);
823                 vbc_eq_reg_set_range(HPCOEF0, HPCOEF42, data);
824
825                 vbc_eq_reg_set(DAHPCTL, data);
826                 /*FM function maybe use this regs,and EQ setting don't use them */
827                 /*vbc_da_eq_reg_set(DAPATCHCTL, data); */
828
829                 /*vbc_da_eq_reg_set(STCTL0, data); */
830                 /*vbc_da_eq_reg_set(STCTL1, data); */
831
832         } else {
833                 vbc_eq_reg_set(ADPATCHCTL, data);
834         }
835 }
836
837 static void vbc_eq_profile_apply(struct snd_soc_codec *codec, void *data,
838                                  int vbc_idx)
839 {
840         if (codec) {
841                 vbc_eq_reg_apply(codec, data, vbc_idx);
842         }
843 }
844
845 static void vbc_eq_profile_close(struct snd_soc_codec *codec, int vbc_idx)
846 {
847         vbc_eq_profile_apply(codec, &vbc_eq_profile_default, vbc_idx);
848 }
849
850 static void vbc_eq_try_apply(struct snd_soc_codec *codec, int vbc_idx)
851 {
852         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
853         struct vbc_equ *p_eq_setting = &vbc_codec->vbc_eq_setting;
854         u32 *data;
855
856         sp_asoc_pr_dbg("%s 0x%x\n", __func__, (int)p_eq_setting->vbc_eq_apply);
857         if (p_eq_setting->vbc_eq_apply) {
858                 struct vbc_eq_profile *now;
859                 mutex_lock(&vbc_codec->load_mutex);
860                 now = &p_eq_setting->data[p_eq_setting->now_profile];
861                 data = now->effect_paras;
862                 sp_asoc_pr_info("VBC %s EQ Apply '%s'\n",
863                                 vbc_get_name(vbc_idx), now->name);
864                 p_eq_setting->vbc_eq_apply(codec, data, vbc_idx);
865                 mutex_unlock(&vbc_codec->load_mutex);
866         }
867 }
868
869 static int vbc_eq_profile_get(struct snd_kcontrol *kcontrol,
870                               struct snd_ctl_elem_value *ucontrol)
871 {
872         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
873         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
874         struct vbc_equ *p_eq_setting = &vbc_codec->vbc_eq_setting;
875         ucontrol->value.integer.value[0] = p_eq_setting->now_profile;
876         return 0;
877 }
878
879 static int vbc_eq_profile_put(struct snd_kcontrol *kcontrol,
880                               struct snd_ctl_elem_value *ucontrol)
881 {
882         int ret = 0;
883         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
884         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
885         struct vbc_equ *p_eq_setting = &vbc_codec->vbc_eq_setting;
886         struct soc_mixer_control *mc =
887             (struct soc_mixer_control *)kcontrol->private_value;
888         int vbc_idx = FUN_REG(mc->reg);
889         int profile_max;
890
891         profile_max = p_eq_setting->hdr.num_profile;
892
893         ret = ucontrol->value.integer.value[0];
894         if (ret == p_eq_setting->now_profile) {
895                 return ret;
896         }
897
898         sp_asoc_pr_info("VBC %s EQ Select %ld max %d\n",
899                         vbc_get_name(vbc_idx),
900                         ucontrol->value.integer.value[0], profile_max);
901
902         if (ret < profile_max) {
903                 p_eq_setting->now_profile = ret;
904         }
905
906         if (p_eq_setting->is_active && p_eq_setting->data)
907                 vbc_eq_try_apply(codec, vbc_idx);
908
909         return ret;
910 }
911
912 static int vbc_eq_loading(struct snd_soc_codec *codec)
913 {
914         int ret;
915         const u8 *fw_data;
916         const struct firmware *fw;
917         int i;
918         int offset = 0;
919         int len = 0;
920         int old_num_profile;
921         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
922         struct vbc_equ *p_eq_setting = &vbc_codec->vbc_eq_setting;
923
924         sp_asoc_pr_dbg("%s\n", __func__);
925         mutex_lock(&vbc_codec->load_mutex);
926         p_eq_setting->is_loading = 1;
927
928         /* request firmware for VBC EQ */
929         ret = request_firmware(&fw, "vbc_eq", p_eq_setting->dev);
930         if (ret != 0) {
931                 pr_err("ERR:Failed to load firmware: %d\n", ret);
932                 goto req_fw_err;
933         }
934         fw_data = fw->data;
935         old_num_profile = p_eq_setting->hdr.num_profile;
936
937         memcpy(&p_eq_setting->hdr, fw_data, sizeof(p_eq_setting->hdr));
938
939         if (strncmp
940             (p_eq_setting->hdr.magic, VBC_EQ_FIRMWARE_MAGIC_ID,
941              VBC_EQ_FIRMWARE_MAGIC_LEN)) {
942                 pr_err("ERR:Firmware magic error!\n");
943                 ret = -EINVAL;
944                 goto eq_out;
945         }
946
947         if (p_eq_setting->hdr.profile_version != VBC_EQ_PROFILE_VERSION) {
948                 pr_err("ERR:Firmware support version is 0x%x!\n",
949                        VBC_EQ_PROFILE_VERSION);
950                 ret = -EINVAL;
951                 goto eq_out;
952         }
953
954         if (p_eq_setting->hdr.num_profile > VBC_EQ_PROFILE_CNT_MAX) {
955                 pr_err
956                     ("ERR:Firmware profile to large at %d, max count is %d!\n",
957                      p_eq_setting->hdr.num_profile, VBC_EQ_PROFILE_CNT_MAX);
958                 ret = -EINVAL;
959                 goto eq_out;
960         }
961
962         if (old_num_profile != p_eq_setting->hdr.num_profile) {
963                 vbc_safe_kfree(&p_eq_setting->data);
964         }
965
966         len = p_eq_setting->hdr.num_profile * sizeof(struct vbc_eq_profile);
967         if (p_eq_setting->data == NULL) {
968                 p_eq_setting->data = kzalloc(len, GFP_KERNEL);
969                 if (p_eq_setting->data == NULL) {
970                         ret = -ENOMEM;
971                         goto eq_out;
972                 }
973         }
974         offset = sizeof(struct vbc_fw_header);
975         memcpy(p_eq_setting->data, fw_data + offset, len);
976
977         for (i = 0; i < p_eq_setting->hdr.num_profile; i++) {
978                 const char *magic = (char *)p_eq_setting->data[i].magic;
979                 if (strncmp
980                     (magic, VBC_EQ_FIRMWARE_MAGIC_ID,
981                      VBC_EQ_FIRMWARE_MAGIC_LEN)) {
982                         pr_err
983                             ("ERR:Firmware profile[%d] magic error!magic: %s \n",
984                              i, magic);
985                         ret = -EINVAL;
986                         goto eq_out;
987                 }
988         }
989
990         ret = 0;
991         goto eq_out;
992
993 eq_out:
994         release_firmware(fw);
995 req_fw_err:
996         p_eq_setting->is_loading = 0;
997         mutex_unlock(&vbc_codec->load_mutex);
998         if (ret >= 0) {
999                 if (p_eq_setting->is_active && p_eq_setting->data)
1000                         vbc_eq_try_apply(codec, 0);
1001         }
1002         sp_asoc_pr_dbg("return %i\n", ret);
1003         return ret;
1004 }
1005
1006 static int vbc_switch_get(struct snd_kcontrol *kcontrol,
1007                           struct snd_ctl_elem_value *ucontrol)
1008 {
1009         int ret;
1010         ret = arch_audio_vbc_switch(AUDIO_NO_CHANGE);
1011         if (ret >= 0)
1012                 ucontrol->value.integer.value[0] =
1013                     (ret == AUDIO_TO_DSP_CTRL ? 0 : 1);
1014         return ret;
1015 }
1016
1017 static int vbc_switch_reg_val[];
1018 static int vbc_switch_put(struct snd_kcontrol *kcontrol,
1019                           struct snd_ctl_elem_value *ucontrol)
1020 {
1021         int ret;
1022         struct soc_enum *texts = (struct soc_enum *)kcontrol->private_value;
1023
1024         sp_asoc_pr_info("VBC Switch to %s\n",
1025                         texts->texts[ucontrol->value.integer.value[0]]);
1026
1027         ret = ucontrol->value.integer.value[0];
1028         ret = arch_audio_vbc_switch(ret == 0 ?
1029                                     AUDIO_TO_DSP_CTRL : AUDIO_TO_ARM_CTRL);
1030
1031         return ret;
1032 }
1033
1034 static int vbc_eq_switch_get(struct snd_kcontrol *kcontrol,
1035                              struct snd_ctl_elem_value *ucontrol)
1036 {
1037         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1038         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1039         struct vbc_equ *p_eq_setting = &vbc_codec->vbc_eq_setting;
1040         ucontrol->value.integer.value[0] = p_eq_setting->is_active;
1041         return 0;
1042 }
1043
1044 static int vbc_eq_switch_put(struct snd_kcontrol *kcontrol,
1045                              struct snd_ctl_elem_value *ucontrol)
1046 {
1047         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1048         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1049         struct vbc_equ *p_eq_setting = &vbc_codec->vbc_eq_setting;
1050         struct soc_mixer_control *mc =
1051             (struct soc_mixer_control *)kcontrol->private_value;
1052         int id = FUN_REG(mc->reg);
1053         int ret;
1054
1055         ret = ucontrol->value.integer.value[0];
1056         if (ret == p_eq_setting->is_active) {
1057                 return ret;
1058         }
1059
1060         sp_asoc_pr_info("VBC EQ Switch %s\n",
1061                         STR_ON_OFF(ucontrol->value.integer.value[0]));
1062
1063         if ((ret == 0) || (ret == 1)) {
1064                 p_eq_setting->is_active = ret;
1065                 if (p_eq_setting->is_active && p_eq_setting->data) {
1066                         p_eq_setting->vbc_eq_apply = vbc_eq_profile_apply;
1067                         vbc_eq_try_apply(codec, id);
1068                 } else {
1069                         p_eq_setting->vbc_eq_apply = 0;
1070                         vbc_eq_profile_close(codec, id);
1071                 }
1072         }
1073
1074         return ret;
1075 }
1076
1077 static int vbc_eq_load_get(struct snd_kcontrol *kcontrol,
1078                            struct snd_ctl_elem_value *ucontrol)
1079 {
1080         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1081         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1082         struct vbc_equ *p_eq_setting = &vbc_codec->vbc_eq_setting;
1083         ucontrol->value.integer.value[0] = p_eq_setting->is_loading;
1084         return 0;
1085 }
1086
1087 static int vbc_eq_load_put(struct snd_kcontrol *kcontrol,
1088                            struct snd_ctl_elem_value *ucontrol)
1089 {
1090         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1091         int ret;
1092         struct soc_enum *texts = (struct soc_enum *)kcontrol->private_value;
1093
1094         sp_asoc_pr_info("VBC EQ %s\n",
1095                         texts->texts[ucontrol->value.integer.value[0]]);
1096
1097         ret = ucontrol->value.integer.value[0];
1098         if (ret == 1) {
1099                 ret = vbc_eq_loading(codec);
1100         }
1101
1102         return ret;
1103 }
1104
1105 static int vbc_dg_get(struct snd_kcontrol *kcontrol,
1106                       struct snd_ctl_elem_value *ucontrol)
1107 {
1108         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1109         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1110         struct soc_mixer_control *mc =
1111             (struct soc_mixer_control *)kcontrol->private_value;
1112         int id = FUN_REG(mc->reg);
1113         int vbc_idx = mc->shift;
1114
1115         ucontrol->value.integer.value[0] = vbc_codec->dg[vbc_idx].dg_val[id];
1116         return 0;
1117 }
1118
1119 static int vbc_dg_put(struct snd_kcontrol *kcontrol,
1120                       struct snd_ctl_elem_value *ucontrol)
1121 {
1122         int ret = 0;
1123         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1124         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1125         struct soc_mixer_control *mc =
1126             (struct soc_mixer_control *)kcontrol->private_value;
1127         int id = FUN_REG(mc->reg);
1128         int vbc_idx = mc->shift;
1129
1130         ret = ucontrol->value.integer.value[0];
1131         if (ret == vbc_codec->dg[vbc_idx].dg_val[id]) {
1132                 return ret;
1133         }
1134
1135         sp_asoc_pr_info("VBC %s%d DG set 0x%02x\n",
1136                         vbc_get_name(vbc_idx), id,
1137                         (int)ucontrol->value.integer.value[0]);
1138
1139         if (ret <= VBC_DG_VAL_MAX) {
1140                 vbc_codec->dg[vbc_idx].dg_val[id] = ret;
1141         }
1142
1143         vbc_try_dg_set(vbc_codec, vbc_idx, id);
1144
1145         return ret;
1146 }
1147
1148 static int vbc_st_dg_get(struct snd_kcontrol *kcontrol,
1149                          struct snd_ctl_elem_value *ucontrol)
1150 {
1151         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1152         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1153         struct soc_mixer_control *mc =
1154             (struct soc_mixer_control *)kcontrol->private_value;
1155         int id = FUN_REG(mc->reg);
1156
1157         ucontrol->value.integer.value[0] = vbc_codec->st_dg.dg_val[id];
1158         return 0;
1159 }
1160
1161 static int vbc_st_dg_put(struct snd_kcontrol *kcontrol,
1162                          struct snd_ctl_elem_value *ucontrol)
1163 {
1164         int ret = 0;
1165         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1166         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1167         struct soc_mixer_control *mc =
1168             (struct soc_mixer_control *)kcontrol->private_value;
1169         int id = FUN_REG(mc->reg);
1170
1171         ret = ucontrol->value.integer.value[0];
1172         if (ret == vbc_codec->st_dg.dg_val[id]) {
1173                 return ret;
1174         }
1175
1176         sp_asoc_pr_info("VBC ST%d DG set 0x%02x\n", id,
1177                         (int)ucontrol->value.integer.value[0]);
1178
1179         if (ret <= VBC_DG_VAL_MAX) {
1180                 vbc_codec->st_dg.dg_val[id] = ret;
1181         }
1182
1183         vbc_try_st_dg_set(vbc_codec, id);
1184
1185         return ret;
1186 }
1187
1188 static int vbc_dg_switch_get(struct snd_kcontrol *kcontrol,
1189                              struct snd_ctl_elem_value *ucontrol)
1190 {
1191         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1192         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1193         struct soc_mixer_control *mc =
1194             (struct soc_mixer_control *)kcontrol->private_value;
1195         int id = FUN_REG(mc->reg);
1196         int vbc_idx = mc->shift;
1197
1198         ucontrol->value.integer.value[0] = vbc_codec->dg[vbc_idx].dg_switch[id];
1199         return 0;
1200 }
1201
1202 static int vbc_dg_switch_put(struct snd_kcontrol *kcontrol,
1203                              struct snd_ctl_elem_value *ucontrol)
1204 {
1205         int ret = 0;
1206         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1207         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1208         struct soc_mixer_control *mc =
1209             (struct soc_mixer_control *)kcontrol->private_value;
1210         int id = FUN_REG(mc->reg);
1211         int vbc_idx = mc->shift;
1212
1213         ret = ucontrol->value.integer.value[0];
1214         if (ret == vbc_codec->dg[vbc_idx].dg_switch[id]) {
1215                 return ret;
1216         }
1217
1218         sp_asoc_pr_info("VBC %s%d DG Switch %s\n",
1219                         vbc_get_name(vbc_idx), id,
1220                         STR_ON_OFF(ucontrol->value.integer.value[0]));
1221
1222         vbc_codec->dg[vbc_idx].dg_switch[id] = ret;
1223
1224         vbc_try_dg_set(vbc_codec, vbc_idx, id);
1225
1226         return ret;
1227 }
1228
1229 static int vbc_st_hpf_switch_get(struct snd_kcontrol *kcontrol,
1230                                  struct snd_ctl_elem_value *ucontrol)
1231 {
1232         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1233         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1234         struct soc_mixer_control *mc =
1235             (struct soc_mixer_control *)kcontrol->private_value;
1236         int id = FUN_REG(mc->reg);
1237
1238         ucontrol->value.integer.value[0] = vbc_codec->st_dg.hpf_switch[id];
1239         return 0;
1240 }
1241
1242 static int vbc_st_hpf_switch_put(struct snd_kcontrol *kcontrol,
1243                                  struct snd_ctl_elem_value *ucontrol)
1244 {
1245         int ret = 0;
1246         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1247         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1248         struct soc_mixer_control *mc =
1249             (struct soc_mixer_control *)kcontrol->private_value;
1250         int id = FUN_REG(mc->reg);
1251
1252         ret = ucontrol->value.integer.value[0];
1253         if (ret == vbc_codec->st_dg.hpf_switch[id]) {
1254                 return ret;
1255         }
1256
1257         sp_asoc_pr_info("VBC ST%d HPF Switch %s\n", id,
1258                         STR_ON_OFF(ucontrol->value.integer.value[0]));
1259
1260         vbc_codec->st_dg.hpf_switch[id] = ret;
1261
1262         vbc_try_st_hpf_set(vbc_codec, id);
1263
1264         return ret;
1265 }
1266
1267 static int vbc_st_hpf_get(struct snd_kcontrol *kcontrol,
1268                           struct snd_ctl_elem_value *ucontrol)
1269 {
1270         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1271         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1272         struct soc_mixer_control *mc =
1273             (struct soc_mixer_control *)kcontrol->private_value;
1274         int id = FUN_REG(mc->reg);
1275
1276         ucontrol->value.integer.value[0] = vbc_codec->st_dg.hpf_val[id];
1277         return 0;
1278 }
1279
1280 static int vbc_st_hpf_put(struct snd_kcontrol *kcontrol,
1281                           struct snd_ctl_elem_value *ucontrol)
1282 {
1283         int ret = 0;
1284         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1285         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1286         struct soc_mixer_control *mc =
1287             (struct soc_mixer_control *)kcontrol->private_value;
1288         int id = FUN_REG(mc->reg);
1289
1290         ret = ucontrol->value.integer.value[0];
1291         if (ret == vbc_codec->st_dg.hpf_val[id]) {
1292                 return ret;
1293         }
1294
1295         sp_asoc_pr_info("VBC ST%d HPF set 0x%02x\n", id,
1296                         (int)ucontrol->value.integer.value[0]);
1297
1298         if (ret <= VBC_DG_VAL_MAX) {
1299                 vbc_codec->st_dg.hpf_val[id] = ret;
1300         }
1301
1302         vbc_try_st_hpf_set(vbc_codec, id);
1303
1304         return ret;
1305 }
1306
1307 static int adc_dgmux_get(struct snd_kcontrol *kcontrol,
1308                          struct snd_ctl_elem_value *ucontrol)
1309 {
1310         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1311         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1312         struct soc_mixer_control *mc =
1313             (struct soc_mixer_control *)kcontrol->private_value;
1314         int id = FUN_REG(mc->reg);
1315
1316         ucontrol->value.integer.value[0] = vbc_codec->adc_dgmux_val[id];
1317         return 0;
1318 }
1319
1320 static int adc_dgmux_put(struct snd_kcontrol *kcontrol,
1321                          struct snd_ctl_elem_value *ucontrol)
1322 {
1323         int ret = 0;
1324         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1325         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1326         struct soc_mixer_control *mc =
1327             (struct soc_mixer_control *)kcontrol->private_value;
1328         int id = FUN_REG(mc->reg);
1329
1330         ret = ucontrol->value.integer.value[0];
1331         if (ret == vbc_codec->adc_dgmux_val[id]) {
1332                 return ret;
1333         }
1334
1335         sp_asoc_pr_info("VBC AD%d DG mux : %ld\n", id,
1336                         ucontrol->value.integer.value[0]);
1337
1338         vbc_codec->adc_dgmux_val[id] = ret;
1339         vbc_try_ad_dgmux_set(vbc_codec, id);
1340
1341         return ret;
1342 }
1343
1344 static int dac_iismux_get(struct snd_kcontrol *kcontrol,
1345                           struct snd_ctl_elem_value *ucontrol)
1346 {
1347         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1348         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1349         ucontrol->value.integer.value[0] = vbc_codec->vbc_da_iis_port;
1350         return 0;
1351 }
1352
1353 static int dac_iismux_put(struct snd_kcontrol *kcontrol,
1354                           struct snd_ctl_elem_value *ucontrol)
1355 {
1356         struct soc_enum *texts = (struct soc_enum *)kcontrol->private_value;
1357         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1358         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1359
1360         if (vbc_codec->vbc_da_iis_port == ucontrol->value.integer.value[0])
1361                 return 0;
1362
1363         sp_asoc_pr_info("VBC DA output to %s\n",
1364                         texts->texts[ucontrol->value.integer.value[0]]);
1365
1366         vbc_codec->vbc_da_iis_port = ucontrol->value.integer.value[0];
1367
1368         vbc_try_da_iismux_set(vbc_codec->vbc_da_iis_port);
1369
1370         return 1;
1371 }
1372
1373 static const char *switch_function[] = { "dsp", "arm" };
1374 static const char *eq_load_function[] = { "idle", "loading" };
1375 static const char *da_iis_mux_function[] =
1376     { "sprd-codec", "ext-codec-4", "ext-codec-6" };
1377 static const char *fm_sample_rate_function[] = { "32000", "48000" };
1378
1379 static const struct soc_enum vbc_enum[] = {
1380         SOC_ENUM_SINGLE_EXT(2, switch_function),
1381         SOC_ENUM_SINGLE_EXT(2, eq_load_function),
1382         SOC_ENUM_SINGLE_EXT(3, da_iis_mux_function),
1383         SOC_ENUM_SINGLE_EXT(2, fm_sample_rate_function),
1384 };
1385
1386 static const struct snd_kcontrol_new vbc_codec_snd_controls[] = {
1387         SOC_ENUM_EXT("VBC Switch", vbc_enum[0], vbc_switch_get,
1388                      vbc_switch_put),
1389         SOC_SINGLE_EXT("VBC EQ Switch", FUN_REG(VBC_PLAYBACK), 0, 1, 0,
1390                        vbc_eq_switch_get,
1391                        vbc_eq_switch_put),
1392         SOC_ENUM_EXT("VBC EQ Update", vbc_enum[1], vbc_eq_load_get,
1393                      vbc_eq_load_put),
1394
1395         SOC_SINGLE_EXT("VBC DACL DG Set", FUN_REG(VBC_LEFT),
1396                        VBC_PLAYBACK, VBC_DG_VAL_MAX, 0, vbc_dg_get,
1397                        vbc_dg_put),
1398         SOC_SINGLE_EXT("VBC DACR DG Set", FUN_REG(VBC_RIGHT),
1399                        VBC_PLAYBACK, VBC_DG_VAL_MAX, 0, vbc_dg_get,
1400                        vbc_dg_put),
1401         SOC_SINGLE_EXT("VBC ADCL DG Set", FUN_REG(VBC_LEFT),
1402                        VBC_CAPTRUE, VBC_DG_VAL_MAX, 0, vbc_dg_get,
1403                        vbc_dg_put),
1404         SOC_SINGLE_EXT("VBC ADCR DG Set", FUN_REG(VBC_RIGHT),
1405                        VBC_CAPTRUE, VBC_DG_VAL_MAX, 0, vbc_dg_get,
1406                        vbc_dg_put),
1407         SOC_SINGLE_EXT("VBC STL DG Set", FUN_REG(VBC_LEFT),
1408                        0, VBC_DG_VAL_MAX, 0, vbc_st_dg_get, vbc_st_dg_put),
1409         SOC_SINGLE_EXT("VBC STR DG Set", FUN_REG(VBC_RIGHT),
1410                        0, VBC_DG_VAL_MAX, 0, vbc_st_dg_get, vbc_st_dg_put),
1411
1412         SOC_SINGLE_EXT("VBC DACL DG Switch", FUN_REG(VBC_LEFT),
1413                        VBC_PLAYBACK, 1, 0, vbc_dg_switch_get,
1414                        vbc_dg_switch_put),
1415         SOC_SINGLE_EXT("VBC DACR DG Switch", FUN_REG(VBC_RIGHT),
1416                        VBC_PLAYBACK, 1, 0, vbc_dg_switch_get,
1417                        vbc_dg_switch_put),
1418         SOC_SINGLE_EXT("VBC ADCL DG Switch", FUN_REG(VBC_LEFT),
1419                        VBC_CAPTRUE, 1, 0, vbc_dg_switch_get,
1420                        vbc_dg_switch_put),
1421         SOC_SINGLE_EXT("VBC ADCR DG Switch", FUN_REG(VBC_RIGHT),
1422                        VBC_CAPTRUE, 1, 0, vbc_dg_switch_get,
1423                        vbc_dg_switch_put),
1424         SOC_SINGLE_EXT("VBC STL HPF Switch", FUN_REG(VBC_LEFT),
1425                        0, 1, 0, vbc_st_hpf_switch_get, vbc_st_hpf_switch_put),
1426         SOC_SINGLE_EXT("VBC STR HPF Switch", FUN_REG(VBC_RIGHT),
1427                        0, 1, 0, vbc_st_hpf_switch_get, vbc_st_hpf_switch_put),
1428         SOC_SINGLE_EXT("VBC STL HPF Set", FUN_REG(VBC_LEFT),
1429                        0, VBC_DG_VAL_MAX, 0, vbc_st_hpf_get, vbc_st_hpf_put),
1430         SOC_SINGLE_EXT("VBC STR HPF Set", FUN_REG(VBC_RIGHT),
1431                        0, VBC_DG_VAL_MAX, 0, vbc_st_hpf_get, vbc_st_hpf_put),
1432
1433         SOC_SINGLE_EXT("VBC AD0 DG Mux", FUN_REG(ADC0_DGMUX), 0, 1, 0,
1434                        adc_dgmux_get, adc_dgmux_put),
1435         SOC_SINGLE_EXT("VBC AD1 DG Mux", FUN_REG(ADC1_DGMUX), 0, 1, 0,
1436                        adc_dgmux_get, adc_dgmux_put),
1437         SOC_ENUM_EXT("VBC DA IIS Mux", vbc_enum[2], dac_iismux_get,
1438                      dac_iismux_put),
1439         SOC_SINGLE_EXT("VBC DA EQ Profile Select", FUN_REG(VBC_PLAYBACK), 0,
1440                        VBC_EQ_PROFILE_CNT_MAX, 0,
1441                        vbc_eq_profile_get, vbc_eq_profile_put),
1442
1443 };
1444
1445 static unsigned int vbc_codec_read(struct snd_soc_codec *codec,
1446                                    unsigned int reg)
1447 {
1448         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1449         /* Because snd_soc_update_bits reg is 16 bits short type,
1450            so muse do following convert
1451          */
1452         if (IS_SPRD_VBC_RANG(reg | SPRD_VBC_BASE_HI)) {
1453                 reg |= SPRD_VBC_BASE_HI;
1454                 return vbc_reg_read(reg);
1455         } else if (IS_SPRD_VBC_MUX_RANG(FUN_REG(reg))) {
1456                 int id = SPRD_VBC_MUX_IDX(FUN_REG(reg));
1457                 struct sprd_vbc_mux_op *mux = &(vbc_codec->sprd_vbc_mux[id]);
1458                 return mux->val;
1459         } else if (IS_SPRD_VBC_SWITCH_RANG(FUN_REG(reg))) {
1460                 int id = SPRD_VBC_SWITCH_IDX(FUN_REG(reg));
1461                 return vbc_codec->vbc_loop_switch[id];
1462         }
1463
1464         sp_asoc_pr_dbg("The Register is NOT VBC Codec's reg = 0x%x\n", reg);
1465         return 0;
1466 }
1467
1468 static int vbc_codec_write(struct snd_soc_codec *codec, unsigned int reg,
1469                            unsigned int val)
1470 {
1471         if (IS_SPRD_VBC_RANG(reg | SPRD_VBC_BASE_HI)) {
1472                 reg |= SPRD_VBC_BASE_HI;
1473                 return vbc_reg_write(reg, val);
1474         }
1475         sp_asoc_pr_dbg("The Register is NOT VBC Codec's reg = 0x%x\n", reg);
1476         return 0;
1477 }
1478
1479 static int vbc_codec_soc_probe(struct snd_soc_codec *codec)
1480 {
1481         struct vbc_codec_priv *vbc_codec = snd_soc_codec_get_drvdata(codec);
1482         struct vbc_equ *p_eq_setting = &vbc_codec->vbc_eq_setting;
1483         int ret = 0;
1484
1485         sp_asoc_pr_dbg("%s\n", __func__);
1486
1487         codec->dapm.idle_bias_off = 1;
1488
1489         vbc_codec->codec = codec;
1490         p_eq_setting->codec = codec;
1491
1492         vbc_proc_init(codec);
1493
1494         return ret;
1495 }
1496
1497 /* power down chip */
1498 static int vbc_codec_soc_remove(struct snd_soc_codec *codec)
1499 {
1500         return 0;
1501 }
1502
1503 static struct snd_soc_codec_driver soc_codec_dev_vbc_codec = {
1504         .probe = vbc_codec_soc_probe,
1505         .remove = vbc_codec_soc_remove,
1506         .read = vbc_codec_read,
1507         .write = vbc_codec_write,
1508         .reg_word_size = sizeof(u16),
1509         .reg_cache_step = 2,
1510         .dapm_widgets = vbc_codec_dapm_widgets,
1511         .num_dapm_widgets = ARRAY_SIZE(vbc_codec_dapm_widgets),
1512         .dapm_routes = vbc_codec_intercon,
1513         .num_dapm_routes = ARRAY_SIZE(vbc_codec_intercon),
1514         .controls = vbc_codec_snd_controls,
1515         .num_controls = ARRAY_SIZE(vbc_codec_snd_controls),
1516 };
1517
1518 static int sprd_vbc_codec_probe(struct platform_device *pdev)
1519 {
1520         struct vbc_codec_priv *vbc_codec;
1521         int ret;
1522
1523         sp_asoc_pr_dbg("%s\n", __func__);
1524
1525         vbc_codec = devm_kzalloc(&pdev->dev, sizeof(struct vbc_codec_priv),
1526                                  GFP_KERNEL);
1527         if (vbc_codec == NULL)
1528                 return -ENOMEM;
1529
1530         platform_set_drvdata(pdev, vbc_codec);
1531
1532         ret = snd_soc_register_codec(&pdev->dev,
1533                                      &soc_codec_dev_vbc_codec, NULL, 0);
1534         if (ret != 0) {
1535                 pr_err("ERR:Failed to register VBC-CODEC: %d\n", ret);
1536         }
1537
1538         /* AP refer to array vbc_switch_reg_val */
1539         vbc_codec->vbc_control = 2;
1540         vbc_codec->vbc_eq_setting.dev = &pdev->dev;
1541         vbc_codec->st_dg.dg_val[0] = 0x18;
1542         vbc_codec->st_dg.dg_val[1] = 0x18;
1543         vbc_codec->st_dg.hpf_val[0] = 0x3;
1544         vbc_codec->st_dg.hpf_val[1] = 0x3;
1545         vbc_codec->dg[0].dg_val[0] = 0x18;
1546         vbc_codec->dg[0].dg_val[1] = 0x18;
1547         vbc_codec->dg[1].dg_val[0] = 0x18;
1548         vbc_codec->dg[1].dg_val[1] = 0x18;
1549         vbc_codec->dg[0].dg_set[0] = vbc_da0_dg_set;
1550         vbc_codec->dg[0].dg_set[1] = vbc_da1_dg_set;
1551         vbc_codec->dg[1].dg_set[0] = vbc_ad0_dg_set;
1552         vbc_codec->dg[1].dg_set[1] = vbc_ad1_dg_set;
1553         mutex_init(&vbc_codec->load_mutex);
1554
1555         return ret;
1556 }
1557
1558 static int sprd_vbc_codec_remove(struct platform_device *pdev)
1559 {
1560         struct vbc_codec_priv *vbc_codec = platform_get_drvdata(pdev);
1561         vbc_codec->vbc_eq_setting.dev = 0;
1562
1563         snd_soc_unregister_codec(&pdev->dev);
1564         return 0;
1565 }
1566
1567 MODULE_DESCRIPTION("SPRD ASoC VBC Codec Driver");
1568 MODULE_AUTHOR("Zhenfang Wang <zhenfang.wang@spreadtrum.com>");
1569 MODULE_AUTHOR("Ken.Kuang <ken.kuang@spreadtrum.com>");
1570 MODULE_LICENSE("GPL");
1571 MODULE_ALIAS("codec:VBC Codec");