2 * sound/soc/sprd/dai/vbc/vbc.c
4 * SPRD SoC CPU-DAI -- SpreadTrum SOC DAI with EQ&ALC and some loop.
6 * Copyright (C) 2012 SpreadTrum Ltd.
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.
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.
17 #define pr_fmt(fmt) "[audio: vbc ] " fmt
21 #include <asm/atomic.h>
22 #include <ubi_uboot.h>
25 #include "../sound_common.h"
27 #ifdef CONFIG_SPRD_AUDIO_DEBUG
28 #define vbc_dbg pr_info
33 #define FUN_REG(f) ((unsigned short)(-((f) + 1)))
35 #define DEFINE_SPINLOCK(...)
36 #define DEFINE_MUTEX(...)
38 #define VBC_DG_VAL_MAX (0x7F)
40 struct vbc_fw_header {
41 char magic[VBC_EQ_FIRMWARE_MAGIC_LEN];
46 struct vbc_eq_profile {
47 char magic[VBC_EQ_FIRMWARE_MAGIC_LEN];
48 char name[VBC_EQ_PROFILE_NAME_MAX];
50 u32 effect_paras[VBC_EFFECT_PARAS_LEN];
53 static const u32 vbc_eq_profile_default[VBC_EFFECT_PARAS_LEN] = {
54 /* TODO the default register value */
55 0x00000000, /* DAPATCHCTL */
56 0x00001818, /* DADGCTL */
57 0x0000007F, /* DAHPCTL */
58 0x00000000, /* DAALCCTL0 */
59 0x00000000, /* DAALCCTL1 */
60 0x00000000, /* DAALCCTL2 */
61 0x00000000, /* DAALCCTL3 */
62 0x00000000, /* DAALCCTL4 */
63 0x00000000, /* DAALCCTL5 */
64 0x00000000, /* DAALCCTL6 */
65 0x00000000, /* DAALCCTL7 */
66 0x00000000, /* DAALCCTL8 */
67 0x00000000, /* DAALCCTL9 */
68 0x00000000, /* DAALCCTL10 */
69 0x00000183, /* STCTL0 */
70 0x00000183, /* STCTL1 */
71 0x00000000, /* ADPATCHCTL */
72 0x00001818, /* ADDG01CTL */
73 0x00001818, /* ADDG23CTL */
74 0x00000000, /* ADHPCTL */
75 0x00000000, /* ADCSRCCTL */
76 0x00000000, /* DACSRCCTL */
77 0x00000000, /* MIXERCTL */
78 0x00000000, /* VBNGCVTHD */
79 0x00000000, /* VBNGCTTHD */
80 0x00000000, /* VBNGCTL */
81 0x00000000, /* HPCOEF0_H */
90 struct vbc_fw_header hdr;
91 struct vbc_eq_profile *data;
92 void (*vbc_eq_apply) (void *data);
95 typedef int (*vbc_dma_set) (int enable);
96 typedef int (*vbc_dg_set) (int enable, int dg);
97 DEFINE_MUTEX(vbc_mutex);
99 vbc_dma_set dma_set[2];
101 int (*arch_enable) (int chan);
102 int (*arch_disable) (int chan);
108 vbc_dg_set dg_set[2];
111 DEFINE_MUTEX(load_mutex);
112 static struct vbc_equ vbc_eq_setting = { 0 };
114 static void vbc_eq_try_apply(void);
115 static struct vbc_priv vbc[3];
117 DEFINE_SPINLOCK(vbc_lock);
118 /* local register setting */
119 static int vbc_reg_write(int reg, int val, int mask)
122 spin_lock(&vbc_lock);
123 tmp = __raw_readl(reg);
127 __raw_writel(tmp, reg);
128 spin_unlock(&vbc_lock);
132 static inline int vbc_reg_read(int reg)
135 tmp = __raw_readl(reg);
139 static int vbc_set_buffer_size(int ad_buffer_size, int da_buffer_size,
140 int ad23_buffer_size)
142 int val = vbc_reg_read(VBBUFFSIZE);
143 WARN_ON(ad_buffer_size > VBC_FIFO_FRAME_NUM);
144 WARN_ON(da_buffer_size > VBC_FIFO_FRAME_NUM);
145 WARN_ON(ad23_buffer_size > VBC_FIFO_FRAME_NUM);
146 if ((ad_buffer_size > 0)
147 && (ad_buffer_size <= VBC_FIFO_FRAME_NUM)) {
148 val &= ~(VBADBUFFERSIZE_MASK);
149 val |= (((ad_buffer_size - 1) << VBADBUFFERSIZE_SHIFT)
150 & VBADBUFFERSIZE_MASK);
152 if ((da_buffer_size > 0)
153 && (da_buffer_size <= VBC_FIFO_FRAME_NUM)) {
154 val &= ~(VBDABUFFERSIZE_MASK);
155 val |= (((da_buffer_size - 1) << VBDABUFFERSIZE_SHIFT)
156 & VBDABUFFERSIZE_MASK);
158 vbc_reg_write(VBBUFFSIZE, val,
159 (VBDABUFFERSIZE_MASK | VBADBUFFERSIZE_MASK));
160 if ((ad23_buffer_size > 0)
161 && (ad23_buffer_size <= VBC_FIFO_FRAME_NUM)) {
162 val &= ~(VBAD23BUFFERSIZE_MASK);
163 val |= (((ad23_buffer_size - 1) << VBAD23BUFFERSIZE_SHIFT)
164 & VBAD23BUFFERSIZE_MASK);
166 vbc_reg_write(VBBUFFAD23, val, VBAD23BUFFERSIZE_MASK);
170 static inline int vbc_sw_write_buffer(int enable)
172 /* Software access ping-pong buffer enable when VBENABE bit low */
173 vbc_reg_write(VBDABUFFDTA, ((enable ? 1 : 0) << RAMSW_EN),
178 static inline int vbc_da_enable(int enable, int chan)
180 vbc_reg_write(VBCHNEN, ((enable ? 1 : 0) << (VBDACHEN_SHIFT + chan)),
181 (1 << (VBDACHEN_SHIFT + chan)));
185 static inline int vbc_ad_enable(int enable, int chan)
187 vbc_reg_write(VBCHNEN, ((enable ? 1 : 0) << (VBADCHEN_SHIFT + chan)),
188 (1 << (VBADCHEN_SHIFT + chan)));
192 static inline int vbc_ad23_enable(int enable, int chan)
194 vbc_reg_write(VBCHNEN, ((enable ? 1 : 0) << (VBAD23CHEN_SHIFT + chan)),
195 (1 << (VBAD23CHEN_SHIFT + chan)));
199 static inline int vbc_enable_set(int enable)
201 vbc_reg_write(VBADBUFFDTA, (0 << VBIIS_LRCK), (1 << VBIIS_LRCK));
202 vbc_reg_write(VBDABUFFDTA, ((enable ? 1 : 0) << VBENABLE),
207 static inline int vbc_ad0_dma_set(int enable)
209 vbc_reg_write(VBDABUFFDTA, ((enable ? 1 : 0) << VBAD0DMA_EN),
214 static inline int vbc_ad1_dma_set(int enable)
216 vbc_reg_write(VBDABUFFDTA, ((enable ? 1 : 0) << VBAD1DMA_EN),
221 static inline int vbc_ad2_dma_set(int enable)
223 vbc_reg_write(VBADDMA, ((enable ? 1 : 0) << VBAD2DMA_EN),
228 static inline int vbc_ad3_dma_set(int enable)
230 vbc_reg_write(VBADDMA, ((enable ? 1 : 0) << VBAD3DMA_EN),
235 static inline int vbc_da0_dma_set(int enable)
237 vbc_reg_write(VBDABUFFDTA, ((enable ? 1 : 0) << VBDA0DMA_EN),
242 static inline int vbc_da1_dma_set(int enable)
244 vbc_reg_write(VBDABUFFDTA, ((enable ? 1 : 0) << VBDA1DMA_EN),
249 static void vbc_da_buffer_clear(int id)
252 vbc_reg_write(VBDABUFFDTA, ((id ? 1 : 0) << RAMSW_NUMB),
254 for (i = 0; i < VBC_FIFO_FRAME_NUM; i++) {
255 __raw_writel(0, VBDA0);
256 __raw_writel(0, VBDA1);
260 static void vbc_da_buffer_clear_all(void)
265 ret = arch_audio_vbc_enable();
267 pr_err("Failed to enable VBC\n");
269 save_enable |= (ret << 2);
270 for (i = 0; i < 2; i++) {
271 ret = vbc_da_enable(1, i);
273 pr_err("Failed to enable VBC DA%d\n", i);
275 save_enable |= (ret << i);
277 vbc_sw_write_buffer(true);
278 vbc_set_buffer_size(0, VBC_FIFO_FRAME_NUM, 0);
279 vbc_da_buffer_clear(1); /* clear data buffer 1 */
280 vbc_da_buffer_clear(0); /* clear data buffer 0 */
281 vbc_sw_write_buffer(false);
282 for (i = 0; i < 2; i++, save_enable >>= 1) {
283 if (save_enable & 0x1) {
288 if (save_enable & 0x1) {
289 arch_audio_vbc_disable();
293 static inline int vbc_str_2_index(int stream);
295 static int vbc_da_arch_enable(int chan)
298 ret = vbc_da_enable(1, chan);
300 pr_err("VBC da enable error:%i\n", ret);
303 arch_audio_vbc_enable();
304 vbc[vbc_str_2_index(SNDRV_PCM_STREAM_PLAYBACK)].is_active = 1;
309 static int vbc_da_arch_disable(int chan)
312 ret = vbc_da_enable(0, chan);
314 pr_err("VBC da disable error:%i\n", ret);
317 vbc[vbc_str_2_index(SNDRV_PCM_STREAM_PLAYBACK)].is_active = 0;
322 static int vbc_ad_arch_enable(int chan)
325 ret = vbc_ad_enable(1, chan);
327 pr_err("VBC ad enable error:%i\n", ret);
330 arch_audio_vbc_enable();
331 vbc[vbc_str_2_index(SNDRV_PCM_STREAM_CAPTURE)].is_active = 1;
336 static int vbc_ad_arch_disable(int chan)
339 ret = vbc_ad_enable(0, chan);
341 pr_err("VBC ad disable error:%i\n", ret);
344 vbc[vbc_str_2_index(SNDRV_PCM_STREAM_CAPTURE)].is_active = 0;
349 static int vbc_ad23_arch_enable(int chan)
352 ret = vbc_ad23_enable(1, chan);
354 pr_err("VBC ad enable error:%i\n", ret);
357 arch_audio_vbc_enable();
358 vbc[vbc_str_2_index(SNDRV_PCM_STREAM_CAPTURE) + 1].is_active =
364 static int vbc_ad23_arch_disable(int chan)
367 ret = vbc_ad23_enable(0, chan);
369 pr_err("VBC ad23 disable error:%i\n", ret);
372 vbc[vbc_str_2_index(SNDRV_PCM_STREAM_CAPTURE) + 1].is_active =
378 static inline int vbc_da0_dg_set(int enable, int dg)
381 vbc_reg_write(DADGCTL, 0x80 | (0xFF & dg), 0xFF);
383 vbc_reg_write(DADGCTL, 0, 0x80);
388 static inline int vbc_da1_dg_set(int enable, int dg)
391 vbc_reg_write(DADGCTL, (0x80 | (0xFF & dg)) << 8, 0xFF00);
393 vbc_reg_write(DADGCTL, 0, 0x8000);
398 static inline int vbc_ad0_dg_set(int enable, int dg)
401 vbc_reg_write(ADDG01CTL, 0x80 | (0xFF & dg), 0xFF);
403 vbc_reg_write(ADDG01CTL, 0, 0x80);
408 static inline int vbc_ad1_dg_set(int enable, int dg)
411 vbc_reg_write(ADDG01CTL, (0x80 | (0xFF & dg)) << 8, 0xFF00);
413 vbc_reg_write(ADDG01CTL, 0, 0x8000);
418 static inline int vbc_ad2_dg_set(int enable, int dg)
421 vbc_reg_write(ADDG23CTL, 0x80 | (0xFF & dg), 0xFF);
423 vbc_reg_write(ADDG23CTL, 0, 0x80);
428 static inline int vbc_ad3_dg_set(int enable, int dg)
431 vbc_reg_write(ADDG23CTL, (0x80 | (0xFF & dg)) << 8, 0xFF00);
433 vbc_reg_write(ADDG23CTL, 0, 0x8000);
438 static int vbc_try_dg_set(int vbc_idx, int id)
440 int dg = vbc[vbc_idx].dg_val[id];
441 if (vbc[vbc_idx].dg_switch[id]) {
442 vbc[vbc_idx].dg_set[id] (1, dg);
444 vbc[vbc_idx].dg_set[id] (0, dg);
449 int vbc_adc_sel_iis(int port)
451 vbc_reg_write(VBIISSEL, port << VBIISSEL_AD01_PORT_SHIFT,
452 VBIISSEL_AD01_PORT_MASK);
456 int vbc_adc23_sel_iis(int port)
458 vbc_reg_write(VBIISSEL, port << VBIISSEL_AD23_PORT_SHIFT,
459 VBIISSEL_AD23_PORT_MASK);
463 int vbc_dac0_fm_mixer(int mode)
465 vbc_reg_write(DAPATCHCTL, mode << VBDAPATH_DA0_ADDFM_SHIFT,
466 VBDAPATH_DA0_ADDFM_MASK);
470 int vbc_dac1_fm_mixer(int mode)
472 vbc_reg_write(DAPATCHCTL, mode << VBDAPATH_DA1_ADDFM_SHIFT,
473 VBDAPATH_DA1_ADDFM_MASK);
477 static int vbc_dac_src_enable(int enable)
481 (1 << VBDACSRC_F1F2F3_BP) | (1 << VBDACSRC_F1_SEL) | (1 <<
483 | (1 << VBDACSRC_F0_SEL) | (1 << VBDACSRC_EN);
486 vbc_reg_write(DACSRCCTL, (1 << VBDACSRC_CLR),
487 (1 << VBDACSRC_CLR));
488 for (i = 0; i < 10; i++) ;
489 vbc_reg_write(DACSRCCTL, 0, (1 << VBDACSRC_CLR));
492 vbc_reg_write(DACSRCCTL, 0x31, mask);
494 vbc_reg_write(DACSRCCTL, 0, 0x7F);
499 static int vbc_st0_enable(int enable)
501 vbc_reg_write(STCTL0, (enable ? (1 << 12) : 0), 1 << 12);
505 static int vbc_st1_enable(int enable)
507 vbc_reg_write(STCTL0, (enable ? (1 << 12) : 0), 1 << 12);
511 static void digtal_fm_input_enable(int enable)
513 /*we suppose that digital fm input from vbc ad01 */
515 vbc_adc_sel_iis(1); /*digital fm ==> vbc */
517 vbc_adc_sel_iis(0); /*codec ==> vbc */
521 vbc_st0_enable(enable);
522 vbc_st1_enable(enable);
525 vbc_dac_src_enable(enable); /*todo:maybe we need to reserve SRC value */
527 /*todo: set fm input pin */
530 static struct vbc_priv vbc[3] = {
532 .dma_set = {vbc_da0_dma_set, vbc_da1_dma_set},
533 .arch_enable = vbc_da_arch_enable,
534 .arch_disable = vbc_da_arch_disable,
537 .dg_val = {0x18, 0x18},
538 .dg_set = {vbc_da0_dg_set, vbc_da1_dg_set},
540 { /*Capture for ad01 */
541 .dma_set = {vbc_ad0_dma_set, vbc_ad1_dma_set},
542 .arch_enable = vbc_ad_arch_enable,
543 .arch_disable = vbc_ad_arch_disable,
546 .dg_val = {0x18, 0x18},
547 .dg_set = {vbc_ad0_dg_set, vbc_ad1_dg_set},
549 { /*Capture for ad23 */
550 .dma_set = {vbc_ad2_dma_set, vbc_ad3_dma_set},
551 .arch_enable = vbc_ad23_arch_enable,
552 .arch_disable = vbc_ad23_arch_disable,
555 .dg_val = {0x18, 0x18},
556 .dg_set = {vbc_ad2_dg_set, vbc_ad3_dg_set},
561 this index need use for the [struct vbc_priv] vbc[2] index
562 default MUST return 0.
564 static inline int vbc_str_2_index(int stream)
566 if (stream == SNDRV_PCM_STREAM_CAPTURE) {
573 static inline void vbc_reg_enable(void)
575 arch_audio_vbc_reg_enable();
578 int vbc_startup(int stream)
582 vbc_dbg("Entering %s\n", __func__);
583 vbc_idx = vbc_str_2_index(stream);
585 if (vbc[vbc_idx].is_open || vbc[vbc_idx].is_active) {
586 pr_err("vbc is actived:%d\n", stream);
589 mutex_lock(&vbc_mutex);
590 vbc[vbc_idx].is_open = 1;
591 mutex_unlock(&vbc_mutex);
595 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
596 vbc_da_buffer_clear_all();
597 vbc_set_buffer_size(0, VBC_FIFO_FRAME_NUM, 0);
599 } else if (vbc_idx == 1) {
600 vbc_set_buffer_size(VBC_FIFO_FRAME_NUM, 0, 0);
602 vbc_set_buffer_size(0, 0, VBC_FIFO_FRAME_NUM);
605 vbc_try_dg_set(vbc_idx, VBC_LEFT);
606 vbc_try_dg_set(vbc_idx, VBC_RIGHT);
608 vbc[vbc_idx].used_chan_count = 2;
610 WARN_ON(!vbc[vbc_idx].arch_enable);
611 WARN_ON(!vbc[vbc_idx].arch_disable);
612 WARN_ON(!vbc[vbc_idx].dma_set[0]);
613 WARN_ON(!vbc[vbc_idx].dma_set[1]);
615 vbc_dbg("Leaving %s\n", __func__);
619 static inline int vbc_can_close(void)
621 return !(vbc[vbc_str_2_index(SNDRV_PCM_STREAM_PLAYBACK)].is_open
622 || vbc[vbc_str_2_index(SNDRV_PCM_STREAM_CAPTURE)].is_open
624 vbc[(vbc_str_2_index(SNDRV_PCM_STREAM_CAPTURE) + 1)].is_open);
627 void vbc_shutdown(int stream)
632 vbc_dbg("Entering %s\n", __func__);
634 /* vbc da close MUST clear da buffer */
635 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
636 vbc_da_buffer_clear_all();
639 vbc_idx = vbc_str_2_index(stream);
641 for (i = 0; i < 2; i++) {
642 vbc[vbc_idx].arch_disable(i);
643 vbc[vbc_idx].dma_set[i] (0);
646 mutex_lock(&vbc_mutex);
647 vbc[vbc_idx].is_open = 0;
648 if (vbc_can_close()) {
650 arch_audio_vbc_reset();
651 arch_audio_vbc_disable();
652 arch_audio_vbc_reg_disable();
653 pr_info("close the VBC\n");
655 mutex_unlock(&vbc_mutex);
657 vbc_dbg("Leaving %s\n", __func__);
660 int vbc_trigger(int stream, int enable)
667 vbc_dbg("Entering %s\n", __func__);
670 vbc_idx = vbc_str_2_index(stream);
673 for (i = 0; i < vbc[vbc_idx].used_chan_count; i++) {
674 vbc[vbc_idx].arch_enable(i);
675 vbc[vbc_idx].dma_set[i] (1);
679 for (i = 0; i < vbc[vbc_idx].used_chan_count; i++) {
680 vbc[vbc_idx].arch_disable(i);
681 vbc[vbc_idx].dma_set[i] (0);
684 if (vbc_can_close()) {
686 arch_audio_vbc_disable();
691 vbc_dbg("Leaving %s\n", __func__);
696 static int vbc_eq_reg_offset(u32 reg)
699 if ((reg >= DAPATCHCTL) && (reg <= MIXERCTL)) {
700 i = (reg - DAPATCHCTL) >> 2;
701 } else if ((reg >= VBNGCVTHD) && (reg <= VBNGCTL)) {
702 i = ((reg - VBNGCVTHD) >> 2) + ((MIXERCTL - DAPATCHCTL) >> 2) +
704 } else if ((reg >= HPCOEF0_H) && (reg <= HPCOEF71_L)) {
705 i = ((reg - HPCOEF0_H) >> 2) + ((VBNGCTL - VBNGCVTHD) >> 2) +
706 ((MIXERCTL - DAPATCHCTL) >> 2) + 2;
708 BUG_ON(i >= VBC_EFFECT_PARAS_LEN);
712 static inline void vbc_eq_reg_set(u32 reg, void *data)
714 u32 *effect_paras = data;
715 vbc_dbg("reg(0x%x) = (0x%x)\n", reg,
716 effect_paras[vbc_eq_reg_offset(reg)]);
717 __raw_writel(effect_paras[vbc_eq_reg_offset(reg)], reg);
720 static inline void vbc_eq_reg_set_range(u32 reg_start, u32 reg_end, void *data)
723 for (reg_addr = reg_start; reg_addr <= reg_end; reg_addr += 4) {
724 vbc_eq_reg_set(reg_addr, data);
728 static void vbc_eq_reg_apply(void *data)
730 vbc_eq_reg_set_range(DAALCCTL0, DAALCCTL10, data);
731 vbc_eq_reg_set_range(HPCOEF0_H, HPCOEF71_L, data);
733 vbc_eq_reg_set(DAHPCTL, data);
734 vbc_eq_reg_set(DAPATCHCTL, data);
736 vbc_eq_reg_set(STCTL0, data);
737 vbc_eq_reg_set(STCTL1, data);
739 vbc_eq_reg_set(ADPATCHCTL, data);
740 vbc_eq_reg_set_range(ADHPCTL, VBNGCTL, data);
743 static void vbc_eq_profile_apply(void *data)
745 vbc_eq_reg_apply(data);
748 static void vbc_eq_profile_close(void)
750 vbc_eq_profile_apply(&vbc_eq_profile_default);
753 static void vbc_eq_try_apply(void)
756 vbc_dbg("Entering %s 0x%x\n", __func__,
757 (int)vbc_eq_setting.vbc_eq_apply);
758 if (vbc_eq_setting.vbc_eq_apply) {
759 mutex_lock(&load_mutex);
760 if (vbc_eq_setting.is_loaded) {
761 struct vbc_eq_profile *now =
762 &vbc_eq_setting.data[vbc_eq_setting.now_profile];
763 data = now->effect_paras;
764 pr_info("vbc eq apply '%s'\n", now->name);
765 vbc_eq_setting.vbc_eq_apply(data);
767 mutex_unlock(&load_mutex);
769 vbc_dbg("Leaving %s\n", __func__);
772 static int vbc_eq_profile_get(void)
774 return vbc_eq_setting.now_profile;
777 static int vbc_eq_profile_put(int select)
781 pr_info("vbc eq select %d max %d\n", select,
782 vbc_eq_setting.hdr.num_profile);
785 if (ret == vbc_eq_setting.now_profile) {
788 if (ret < vbc_eq_setting.hdr.num_profile) {
789 vbc_eq_setting.now_profile = ret;
794 vbc_dbg("Leaving %s\n", __func__);
798 static int vbc_switch_get(void)
801 ret = arch_audio_vbc_switch(AUDIO_NO_CHANGE);
804 AUDIO_TO_CP0_DSP_CTRL) ? 0 : ((ret ==
805 AUDIO_TO_CP1_DSP_CTRL) ? 1
811 static int vbc_switch_put(int is_arm)
814 pr_info("VBC switch to %s\n", is_arm ? "ARM" : "DSP");
817 ret = arch_audio_vbc_switch(ret == 0 ?
818 AUDIO_TO_CP0_DSP_CTRL : ((ret == 1) ?
819 AUDIO_TO_CP1_DSP_CTRL
821 AUDIO_TO_AP_ARM_CTRL));
823 vbc_dbg("Leaving %s\n", __func__);
827 static int vbc_eq_switch_get(void)
829 return vbc_eq_setting.is_active;
832 static int vbc_eq_switch_put(int is_active)
835 pr_info("VBC eq switch %s\n", is_active ? "ON" : "OFF");
838 if (ret == vbc_eq_setting.is_active) {
841 if ((ret == 0) || (ret == 1)) {
842 vbc_eq_setting.is_active = ret;
843 if (vbc_eq_setting.is_active) {
844 vbc_eq_setting.vbc_eq_apply = vbc_eq_profile_apply;
847 vbc_eq_setting.vbc_eq_apply = 0;
848 vbc_eq_profile_close();
852 vbc_dbg("Leaving %s\n", __func__);
856 static int vbc_dg_get(int stream, int id)
858 int vbc_idx = vbc_str_2_index(stream);
859 return vbc[vbc_idx].dg_val[id];
862 static int vbc_dg_put(int stream, int id, int dg)
865 int vbc_idx = vbc_str_2_index(stream);
867 pr_info("VBC %s%s DG set 0x%02x\n",
868 (vbc_idx == 2) ? "ADC23" : (vbc_idx == 1 ? "ADC" : "DAC"),
869 id == VBC_LEFT ? "L" : "R", dg);
872 if (ret == vbc[vbc_idx].dg_val[id]) {
875 if (ret <= VBC_DG_VAL_MAX) {
876 vbc[vbc_idx].dg_val[id] = ret;
879 vbc_try_dg_set(vbc_idx, id);
881 vbc_dbg("Leaving %s\n", __func__);
885 static int vbc_dg_switch_get(int stream, int id)
887 int vbc_idx = vbc_str_2_index(stream);
888 return vbc[vbc_idx].dg_switch[id];
891 static int vbc_dg_switch_put(int stream, int id, int enable)
894 int vbc_idx = vbc_str_2_index(stream);
896 pr_info("VBC %s%s DG switch %s\n",
897 (vbc_idx == 2) ? "ADC23" : (vbc_idx == 1 ? "ADC" : "DAC"),
898 id == VBC_LEFT ? "L" : "R",
899 enable ? "ON" : "OFF");
902 if (ret == vbc[vbc_idx].dg_switch[id]) {
906 vbc[vbc_idx].dg_switch[id] = ret;
908 vbc_try_dg_set(vbc_idx, id);
910 vbc_dbg("Leaving %s\n", __func__);
916 arch_audio_vbc_switch(AUDIO_TO_AP_ARM_CTRL);
924 MODULE_DESCRIPTION("SPRD ASoC VBC CUP-DAI driver");
925 MODULE_AUTHOR("Zhenfang Wang <zhenfang.wang@spreadtrum.com>");
926 MODULE_LICENSE("GPL");