1 /******************************************************************************
2 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************/
18
19 /********************************************************************************************************
20 * @file audio.c
21 *
22 * @brief This is the source file for B91
23 *
24 * @author Driver Group
25 *
26 *******************************************************************************************************/
27 #include "audio.h"
28 #include "clock.h"
29 #include "pwm.h"
30 #include "stimer.h"
31
32
33 unsigned char audio_rx_dma_chn;
34 unsigned char audio_tx_dma_chn;
35
36 dma_chain_config_t g_audio_tx_dma_list_cfg;
37 dma_chain_config_t g_audio_rx_dma_list_cfg;
38
39 aduio_i2s_codec_config_t audio_i2s_codec_config=
40 {
41 .audio_in_mode =BIT_16_MONO,
42 .audio_out_mode =BIT_16_MONO_FIFO0,
43 .i2s_data_select =I2S_BIT_16_DATA,
44 .codec_data_select =CODEC_BIT_16_DATA,
45 .i2s_codec_m_s_mode =I2S_M_CODEC_S,
46 .in_digital_gain =CODEC_IN_D_GAIN_0_DB,
47 .in_analog_gain =CODEC_IN_A_GAIN_0_DB,
48 .out_digital_gain =CODEC_OUT_D_GAIN_0_DB,
49 .out_analog_gain =CODEC_OUT_A_GAIN_0_DB,
50 .mic_input_mode_select =DIFF_ENDED_INPUT,//0 single-ended input, 1 differential input
51 .dac_output_chn_select =DAC_OUTPUT_L_R_CHN,//0 right and left channel both active ,1 only left channel active
52 .adc_wnf_mode_select =CODEC_ADC_WNF_INACTIVE,
53 };
54
55
56 aduio_i2s_invert_config_t audio_i2s_invert_config={
57 .i2s_lr_clk_invert_select=I2S_LR_CLK_INVERT_DIS,
58 .i2s_data_invert_select=I2S_DATA_INVERT_DIS,
59 };
60
61
62 dma_config_t audio_dma_rx_config=
63 {
64 .dst_req_sel= 0,
65 .src_req_sel=DMA_REQ_AUDIO0_RX,//rx req
66 .dst_addr_ctrl=DMA_ADDR_INCREMENT,
67 .src_addr_ctrl=DMA_ADDR_FIX,
68 .dstmode=DMA_NORMAL_MODE,
69 .srcmode=DMA_HANDSHAKE_MODE,
70 .dstwidth=DMA_CTR_WORD_WIDTH,//must word
71 .srcwidth=DMA_CTR_WORD_WIDTH,//must word
72 .src_burst_size=0,//must 0
73 .read_num_en=0,
74 .priority=0,
75 .write_num_en=0,
76 .auto_en=0,//must 0
77 };
78
79 dma_config_t audio_dma_tx_config=
80 {
81 .dst_req_sel= DMA_REQ_AUDIO0_TX,//tx req
82 .src_req_sel=0,
83 .dst_addr_ctrl=DMA_ADDR_FIX,
84 .src_addr_ctrl=DMA_ADDR_INCREMENT,//increment
85 .dstmode=DMA_HANDSHAKE_MODE,//handshake
86 .srcmode=DMA_NORMAL_MODE,
87 .dstwidth=DMA_CTR_WORD_WIDTH,//must word
88 .srcwidth=DMA_CTR_WORD_WIDTH,//must word
89 .src_burst_size=0,//must 0
90 .read_num_en=0,
91 .priority=0,
92 .write_num_en=0,
93 .auto_en=0,//must 0
94 };
95
96
97
98 /**
99 * @brief This function serves to invert data between R channel and L channel.
100 * @param[in] en - I2S_DATA_INVERT_DIS: L channel ( left channel data left); I2S_DATA_INVERT_EN(right channel data left)
101 * @attention must be set before audio_init().
102 * @return none
103 */
audio_set_mono_chn(audio_data_invert_e en)104 void audio_set_mono_chn(audio_data_invert_e en)
105 {
106 audio_i2s_invert_config.i2s_data_invert_select=en;
107 }
108
109 /**
110 * @brief This function serves to invert LR-clk.
111 * @param[in] en -lr_clk phase control(in RJ,LJ or i2s modes),in i2s mode(opposite phasing in RJ,LJ mode), 0=right channel data when lr_clk high ,1=right channel data when lr_clk low.
112 * in DSP mode(in DSP mode only), DSP mode A/B select,0=DSP mode A ,1=DSP mode B
113 * @attention If the left and right channels are both active,there will be a phase difference(about 1 sample) between the left and right channels,invert lr_clk can eliminate the phase difference,but data output channel will invert.
114 * @attention must be set before audio_init().
115 * @return none
116 */
audio_invert_i2s_lr_clk(audio_i2s_lr_clk_invert_e en)117 void audio_invert_i2s_lr_clk(audio_i2s_lr_clk_invert_e en)
118 {
119 audio_i2s_invert_config.i2s_lr_clk_invert_select=en;
120 }
121
122 /**
123 * @brief This function serves to set mic input mode.
124 * @param[in] input_mode - 0 single-ended input, 1 differential input.
125 * @attention must be set before audio_init().
126 * @return none
127 */
audio_set_codec_mic_input_mode(audio_input_mode_select_e input_mode)128 void audio_set_codec_mic_input_mode (audio_input_mode_select_e input_mode)
129 {
130 audio_i2s_codec_config.mic_input_mode_select=input_mode;
131 }
132
133 /**
134 * @brief This function serves to set in path digital and analog gain .
135 * @param[in] d_gain - digital gain value
136 * @param[in] a_gain - analog gain value
137 * @attention must be set before audio_init().
138 * @return none
139 */
audio_set_codec_in_path_a_d_gain(codec_in_path_digital_gain_e d_gain,codec_in_path_analog_gain_e a_gain)140 void audio_set_codec_in_path_a_d_gain (codec_in_path_digital_gain_e d_gain,codec_in_path_analog_gain_e a_gain )
141 {
142 audio_i2s_codec_config.in_digital_gain=d_gain;
143 audio_i2s_codec_config.in_analog_gain=a_gain;
144 }
145
146
147 /**
148 * @brief This function serves to set out path digital and analog gain .
149 * @param[in] d_gain - digital gain value
150 * @param[in] a_gain - analog gain value
151 * @attention must be set before audio_init().
152 * @return none
153 */
audio_set_codec_out_path_a_d_gain(codec_out_path_digital_gain_e d_gain,codec_out_path_analog_gain_e a_gain)154 void audio_set_codec_out_path_a_d_gain (codec_out_path_digital_gain_e d_gain,codec_out_path_analog_gain_e a_gain)
155 {
156 audio_i2s_codec_config.out_digital_gain=d_gain;
157 audio_i2s_codec_config.out_analog_gain=a_gain;
158 }
159
160
161 /**
162 * @brief This function serves to choose which is master to provide clock.
163 * @param[in] m_s - I2S_S_CODEC_M: i2s as slave ,codec as master; I2S_M_CODEC_S: i2s as master, codec as slave.
164 * @attention must be set before audio_init().
165 * @return none
166 */
audio_set_i2s_codec_m_s(i2s_codec_m_s_mode_e m_s)167 void audio_set_i2s_codec_m_s (i2s_codec_m_s_mode_e m_s)
168 {
169 audio_i2s_codec_config.i2s_codec_m_s_mode=m_s;
170 }
171
172 /**
173 * @brief This function serves to set wind noise filter(WNF),it is a programmable high pass filter feature enabling to reduce wind noise.
174 * @param[in] mode - the wind noise filter mode,the wind noise filter is a 1st order filter.
175 * Mode1 -3dB 59Hz
176 * Wind Noise Filter corner frequency Mode2 -3dB 117Hz
177 Mode3 -3dB 235Hz
178 * @attention must be set before audio_init().
179 * @return none
180 */
audio_set_codec_wnf(adc_wnf_mode_sel_e mode)181 void audio_set_codec_wnf(adc_wnf_mode_sel_e mode)
182 {
183 audio_i2s_codec_config.adc_wnf_mode_select = mode;
184 }
185
186 /**
187 * @brief This function serves to set dac output channel.
188 * @param[in] chn-DAC_OUTPUT_L_R_CHN - right and left channel both active ; DAC_OUTPUT_L_CHN, only left channel active.
189 * @return none
190 * @attention must be set before audio_init().
191 */
audio_set_output_chn(audio_output_chn_e chn)192 void audio_set_output_chn(audio_output_chn_e chn)
193 {
194 audio_i2s_codec_config.dac_output_chn_select = chn;
195 }
196
197 /**
198 * @brief This function serves to choose which is master to provide clock.
199 * @param[in] chn_wl: select word length and audio channel number
200 * @return none
201 */
aduio_set_chn_wl(audio_channel_wl_mode_e chn_wl)202 void aduio_set_chn_wl(audio_channel_wl_mode_e chn_wl)
203 {
204 switch (chn_wl)
205 {
206 case MONO_BIT_16:
207 audio_i2s_codec_config.audio_in_mode=BIT_16_MONO;
208 audio_i2s_codec_config.audio_out_mode=BIT_16_MONO_FIFO0;
209 audio_i2s_codec_config.i2s_data_select=I2S_BIT_16_DATA;
210 audio_i2s_codec_config.codec_data_select=CODEC_BIT_16_DATA;
211 break;
212
213 case MONO_BIT_20:
214 audio_i2s_codec_config.audio_in_mode=BIT_20_OR_24_MONO;
215 audio_i2s_codec_config.audio_out_mode=BIT_20_OR_24_MONO_FIFO0;
216 audio_i2s_codec_config.i2s_data_select=I2S_BIT_20_DATA;
217 audio_i2s_codec_config.codec_data_select=CODEC_BIT_20_DATA;
218 break;
219
220 case MONO_BIT_24:
221 audio_i2s_codec_config.audio_in_mode=BIT_20_OR_24_MONO;
222 audio_i2s_codec_config.audio_out_mode=BIT_20_OR_24_MONO_FIFO0;
223 audio_i2s_codec_config.i2s_data_select=I2S_BIT_24_DATA;
224 audio_i2s_codec_config.codec_data_select=CODEC_BIT_24_DATA;
225 break;
226
227 case STEREO_BIT_16:
228 audio_i2s_codec_config.audio_in_mode=BIT_16_STEREO;
229 audio_i2s_codec_config.audio_out_mode=BIT_16_STEREO_FIFO0;
230 audio_i2s_codec_config.i2s_data_select=I2S_BIT_16_DATA;
231 audio_i2s_codec_config.codec_data_select=CODEC_BIT_16_DATA;
232 break;
233
234 case STEREO_BIT_20:
235 audio_i2s_codec_config.audio_in_mode=BIT_20_OR_24_STEREO;
236 audio_i2s_codec_config.audio_out_mode=BIT_20_OR_24_STEREO_FIFO0;
237 audio_i2s_codec_config.i2s_data_select=I2S_BIT_20_DATA;
238 audio_i2s_codec_config.codec_data_select=CODEC_BIT_20_DATA;
239 break;
240
241 case STEREO_BIT_24:
242 audio_i2s_codec_config.audio_in_mode=BIT_20_OR_24_STEREO;
243 audio_i2s_codec_config.audio_out_mode=BIT_20_OR_24_STEREO_FIFO0;
244 audio_i2s_codec_config.i2s_data_select=I2S_BIT_24_DATA;
245 audio_i2s_codec_config.codec_data_select=CODEC_BIT_24_DATA;
246 break;
247 }
248
249 }
250
251
252 /**
253 * @brief This function selects pin for i2s.
254 * @param[in] pin - the selected pin.
255 * @return none
256 */
audio_i2s_set_pin_mux(i2s_pin_e pin)257 void audio_i2s_set_pin_mux(i2s_pin_e pin)
258 {
259
260 unsigned char val=0;
261 unsigned char start_bit = (BIT_LOW_BIT(pin & 0xff) %4 )<<1;
262 unsigned char mask =(unsigned char) ~BIT_RNG(start_bit , start_bit+1);
263 if(pin==I2S_BCK_PC3)
264 {
265 val = 0;//function 0
266 }
267 else if((pin==I2S_ADC_LR_PC4)||(pin==I2S_ADC_DAT_PC5)||(pin==I2S_DAC_LR_PC6)||(pin==I2S_DAC_DAT_PC7))
268 {
269 val = 1<<(start_bit);//function 1
270 }
271 reg_gpio_func_mux(pin)=(reg_gpio_func_mux(pin)& mask)|val;
272 gpio_function_dis(pin);
273
274 }
275
276 /**
277 * @brief This function configures i2s pin.
278 * @param[in] none
279 * @return none
280 */
audio_i2s_set_pin(void)281 void audio_i2s_set_pin(void)
282 {
283 audio_i2s_set_pin_mux(I2S_BCK_PC3);
284 audio_i2s_set_pin_mux(I2S_ADC_LR_PC4);
285 audio_i2s_set_pin_mux(I2S_ADC_DAT_PC5);
286 audio_i2s_set_pin_mux(I2S_DAC_LR_PC6);
287 audio_i2s_set_pin_mux(I2S_DAC_DAT_PC7);
288 }
289
290 /**
291 * @brief This function serves to set codec supply voltage
292 * @param[in] volt - the voltage of codec supply.A1 2.8V default,A0 1.8V default.
293 * @return none
294 *
295 */
audio_set_codec_supply(codec_volt_supply_e volt)296 void audio_set_codec_supply (codec_volt_supply_e volt)
297 {
298
299 if(0xff==g_chip_version )//A0 1.8v default ( BIT(7) - 1: 2.8v 0: 1.8v )
300 {
301 if(CODEC_2P8V==volt)
302 {
303 /*
304 * VDD_1V8 configured as 2.8V,dcdc_trim_flash_out need trim down (ana_0c<2:0>100 --> 000).Only effect in DCDC mode.
305 * theory(max) 2.84V 2.60V
306 * actual(max) about 3.02V 2.74V
307 */
308 analog_write_reg8(0x0c, analog_read_reg8(0x0c) & 0xf8);
309 analog_write_reg8(0x02,analog_read_reg8(0x02)|BIT(7));
310 }
311
312 else if(CODEC_1P8V==volt)
313 {
314 //VDD_1V8 configured as 1.8V,VDD_1V8 need set default. theory 1.8V, actual about 2.04V
315 analog_write_reg8(0x0c, (analog_read_reg8(0x0c) & 0xf8) | 0x04);
316 analog_write_reg8(0x02,analog_read_reg8(0x02)&(~BIT(7)));
317 }
318
319 }
320
321 else //A1 2.8v default ( BIT(7) - 1: 1.8v 0: 2.8v )
322 {
323 if(CODEC_1P8V==volt)
324 {
325 //VDD_1V8 configured as 1.8V,VDD_1V8 need set default.
326 analog_write_reg8(0x0c, (analog_read_reg8(0x0c) & 0xf8) | 0x04);
327 analog_write_reg8(0x02,analog_read_reg8(0x02)|BIT(7));
328 }
329
330 else if(CODEC_2P8V==volt)
331 {
332 //VDD_1V8 configured as 2.8V,VDD_1V8 need trim down (ana_0c<2:0>100 --> 000).Only effect in DCDC mode.
333 analog_write_reg8(0x0c, analog_read_reg8(0x0c) & 0xf8);
334 analog_write_reg8(0x02,analog_read_reg8(0x02)&(~BIT(7)));
335 }
336 }
337 }
338
339 /**
340 * @brief This function configures dmic pin.
341 * @param[in] pin_gp - the group of dmic pin
342 * @return none
343 */
audio_set_dmic_pin(dmic_pin_group_e pin_gp)344 void audio_set_dmic_pin(dmic_pin_group_e pin_gp)
345 {
346 if(pin_gp == DMIC_GROUPB_B2_DAT_B3_B4_CLK)
347 {
348 reg_gpio_pad_mul_sel=BIT(2);
349 reg_gpio_pb_fuc_h=reg_gpio_pb_fuc_h&(~BIT_RNG(0,1));
350 reg_gpio_pb_fuc_l=(reg_gpio_pb_fuc_l&(~BIT_RNG(4,7)));
351 gpio_function_dis(GPIO_PB2|GPIO_PB3|GPIO_PB4);
352 }
353 else if(pin_gp == DMIC_GROUPC_C1_DAT_C2_C3_CLK)
354 {
355 reg_gpio_pad_mul_sel=BIT(0);
356 reg_gpio_pc_fuc_l=(reg_gpio_pc_fuc_l&(~BIT_RNG(2,7)))|((2<<2)|(2<<4)|(2<<6));
357 gpio_function_dis(GPIO_PC1|GPIO_PC2|GPIO_PC3);
358
359 }
360 else if(pin_gp == DMIC_GROUPD_D4_DAT_D5_D6_CLK)//can not use in A0
361 {
362 reg_gpio_pd_fuc_h=(reg_gpio_pd_fuc_h&(~BIT_RNG(0,5)))|((1<<0)|(1<<2)|(1<<4));
363 gpio_function_dis(GPIO_PD4|GPIO_PD5|GPIO_PD6);
364 }
365 else if(pin_gp == DMIC_B2_DAT_B3_CLK)
366 {
367 reg_gpio_pad_mul_sel=BIT(2);
368 reg_gpio_pb_fuc_l=(reg_gpio_pb_fuc_l&(~BIT_RNG(4,7)));
369 gpio_function_dis(GPIO_PB2|GPIO_PB3);
370 }
371 else if(pin_gp == DMIC_C1_DAT_C2_CLK)
372 {
373 reg_gpio_pad_mul_sel=BIT(0);
374 reg_gpio_pc_fuc_l=(reg_gpio_pc_fuc_l&(~BIT_RNG(2,5)))|((2<<2)|(2<<4));
375 gpio_function_dis(GPIO_PC1|GPIO_PC2);
376 }
377 else if(pin_gp == DMIC_D4_DAT_D5_CLK)//can not use in A0
378 {
379 reg_gpio_pd_fuc_h=(reg_gpio_pd_fuc_h&(~BIT_RNG(0,3)))|((1<<0)|(1<<2));
380 gpio_function_dis(GPIO_PD4|GPIO_PD5);
381 }
382 }
383
384
385 /**
386 * @brief This function serves to enable rx_dma channel.
387 * @return none
388 */
audio_rx_dma_en(void)389 void audio_rx_dma_en(void)
390 {
391 dma_chn_en(audio_rx_dma_chn);
392 }
393
394
395 /**
396 * @brief This function serves to disable rx_dma channel.
397 * @return none
398 */
audio_rx_dma_dis(void)399 void audio_rx_dma_dis(void)
400 {
401 dma_chn_dis(audio_rx_dma_chn);
402 }
403
404
405 /**
406 * @brief This function serves to enable tx_dma channel.
407 * @return none
408 */
audio_tx_dma_en(void)409 void audio_tx_dma_en(void)
410 {
411 dma_chn_en(audio_tx_dma_chn);
412 }
413
414
415 /**
416 * @brief This function serves to disable dis_dma channel.
417 * @return none
418 */
audio_tx_dma_dis(void)419 void audio_tx_dma_dis(void)
420 {
421 dma_chn_dis(audio_tx_dma_chn);
422 }
423
424 /**
425 * @brief This function serves to config rx_dma channel.
426 * @param[in] chn - dma channel
427 * @param[in] dst_addr - the dma address of destination
428 * @param[in] data_len - the length of dma rx size by byte
429 * @param[in] head_of_list - the head address of dma llp.
430 * @return none
431 */
audio_rx_dma_config(dma_chn_e chn,unsigned short * dst_addr,unsigned int data_len,dma_chain_config_t * head_of_list)432 void audio_rx_dma_config(dma_chn_e chn,unsigned short *dst_addr,unsigned int data_len,dma_chain_config_t *head_of_list)
433 {
434 audio_rx_dma_chn=chn;
435 audio_set_rx_buff_len(data_len);
436 dma_config(audio_rx_dma_chn,&audio_dma_rx_config);
437 dma_set_address( chn,REG_AUDIO_AHB_BASE,(unsigned int)convert_ram_addr_cpu2bus(dst_addr));
438 dma_set_size(chn,data_len,DMA_WORD_WIDTH);
439 reg_dma_llp(chn)=(unsigned int)convert_ram_addr_cpu2bus(head_of_list);
440
441 }
442
443 /**
444 * @brief This function serves to set rx dma chain transfer
445 * @param[in] rx_config - the head of list of llp_pointer.
446 * @param[in] llpointer - the next element of llp_pointer.
447 * @param[in] dst_addr -the dma address of destination.
448 * @param[in] data_len -the length of dma size by byte.
449 * @return none
450 */
audio_rx_dma_add_list_element(dma_chain_config_t * config_addr,dma_chain_config_t * llpointer,unsigned short * dst_addr,unsigned int data_len)451 void audio_rx_dma_add_list_element(dma_chain_config_t *config_addr,dma_chain_config_t *llpointer ,unsigned short * dst_addr,unsigned int data_len)
452 {
453 config_addr->dma_chain_ctl=reg_dma_ctrl(audio_rx_dma_chn)|BIT(0);
454 config_addr->dma_chain_src_addr=REG_AUDIO_AHB_BASE;
455 config_addr->dma_chain_dst_addr=(unsigned int)convert_ram_addr_cpu2bus(dst_addr);
456 config_addr->dma_chain_data_len=dma_cal_size(data_len,4);
457 config_addr->dma_chain_llp_ptr=(unsigned int)convert_ram_addr_cpu2bus(llpointer);
458 }
459
460
461 /**
462 * @brief This function serves to config tx_dma channel.
463 * @param[in] chn - dma channel
464 * @param[in] src_addr - the address of source
465 * @param[in] data_len - the length of dma rx size by byte
466 * @param[in] head_of_list - the head address of dma llp.
467 * @return none
468 */
audio_tx_dma_config(dma_chn_e chn,unsigned short * src_addr,unsigned int data_len,dma_chain_config_t * head_of_list)469 void audio_tx_dma_config(dma_chn_e chn,unsigned short * src_addr, unsigned int data_len,dma_chain_config_t * head_of_list)
470 {
471 audio_tx_dma_chn=chn;
472 audio_set_tx_buff_len(data_len);
473 dma_config(audio_tx_dma_chn,&audio_dma_tx_config);
474 dma_set_address( chn,(unsigned int)convert_ram_addr_cpu2bus(src_addr),REG_AUDIO_AHB_BASE);
475 dma_set_size(chn,data_len,DMA_WORD_WIDTH);
476 reg_dma_llp(chn)=(unsigned int)convert_ram_addr_cpu2bus(head_of_list);
477 }
478
479 /**
480 * @brief This function serves to set tx dma chain transfer
481 * @param[in] config_addr - the head of list of llp_pointer.
482 * @param[in] llpointer - the next element of llp_pointer.
483 * @param[in] src_addr - the address of source
484 * @param[in] data_len - the length of dma size by byte.
485 * @return none
486 */
audio_tx_dma_add_list_element(dma_chain_config_t * config_addr,dma_chain_config_t * llpointer,unsigned short * src_addr,unsigned int data_len)487 void audio_tx_dma_add_list_element(dma_chain_config_t *config_addr,dma_chain_config_t *llpointer ,unsigned short * src_addr,unsigned int data_len)
488 {
489 config_addr->dma_chain_ctl=reg_dma_ctrl(audio_tx_dma_chn)|BIT(0);
490 config_addr->dma_chain_src_addr=(unsigned int)convert_ram_addr_cpu2bus(src_addr);
491 config_addr->dma_chain_dst_addr=REG_AUDIO_AHB_BASE;
492 config_addr->dma_chain_data_len=dma_cal_size(data_len,4);
493 config_addr->dma_chain_llp_ptr=(unsigned int)convert_ram_addr_cpu2bus(llpointer);
494 }
495
496
497 /**
498 * @brief This function serves to initialize audio by mc
499 * @param[in] flow_mode - select input out flow mode
500 * @param[in] rate - audio sampling rate.
501 * @param[in] channel_wl - word length and channel number.
502 * @return none
503 */
audio_init(audio_flow_mode_e flow_mode,audio_sample_rate_e rate,audio_channel_wl_mode_e channel_wl)504 void audio_init(audio_flow_mode_e flow_mode,audio_sample_rate_e rate,audio_channel_wl_mode_e channel_wl)
505 {
506 aduio_set_chn_wl(channel_wl);
507 audio_set_codec_clk(1,16);//from ppl 192/16=12M
508 audio_mux_config(CODEC_I2S,audio_i2s_codec_config.audio_in_mode,audio_i2s_codec_config.audio_in_mode,audio_i2s_codec_config.audio_out_mode);
509 audio_i2s_config(I2S_I2S_MODE,audio_i2s_codec_config.i2s_data_select,audio_i2s_codec_config.i2s_codec_m_s_mode,&audio_i2s_invert_config);
510 audio_set_i2s_clock(rate,AUDIO_RATE_EQUAL,0);
511 audio_clk_en(1,1);
512 reg_audio_codec_vic_ctr=FLD_AUDIO_CODEC_SLEEP_ANALOG;//active analog sleep mode
513 while(!(reg_audio_codec_stat_ctr&FLD_AUDIO_CODEC_PON_ACK));//wait codec can be configed
514 if(flow_mode<BUF_TO_LINE_OUT)
515 {
516 audio_codec_adc_config(audio_i2s_codec_config.i2s_codec_m_s_mode,(flow_mode%3),rate,audio_i2s_codec_config.codec_data_select,MCU_WREG);
517 }
518
519 if(flow_mode>LINE_IN_TO_BUF)
520 {
521 audio_codec_dac_config(audio_i2s_codec_config.i2s_codec_m_s_mode,rate,audio_i2s_codec_config.codec_data_select,MCU_WREG);
522 }
523 while(!(reg_audio_codec_stat_ctr==(FLD_AUDIO_CODEC_ADC12_LOCKED|FLD_AUDIO_CODEC_DAC_LOCKED|FLD_AUDIO_CODEC_PON_ACK)));//wait codec adc/dac locked
524
525 audio_data_fifo0_path_sel(I2S_DATA_IN_FIFO,I2S_OUT);
526 }
527
528 /**
529 * @brief This function serves to read data from codec register.
530 * @param[in] addr: the address of codec register
531 * @attention This function only supports internal codec.
532 * @return none
533 */
audio_i2c_codec_read(unsigned char addr)534 unsigned char audio_i2c_codec_read(unsigned char addr)
535 {
536 unsigned char codec_addr_rdat[2]={0x00,0x00};
537 codec_addr_rdat[0]=addr<<1;
538 i2c_master_write_read(0x34<<1,&codec_addr_rdat[0],1,&codec_addr_rdat[1],1);
539 return codec_addr_rdat[1];
540 }
541
542 /**
543 * @brief This function serves to write data to codec register.
544 * @param[in] addr: the address of codec register
545 * @attention This function only supports internal codec.
546 * @return none
547 */
audio_i2c_codec_write(unsigned char addr,unsigned char wdat)548 void audio_i2c_codec_write(unsigned char addr ,unsigned char wdat)
549 {
550 unsigned char codec_addr_wdat[2]={0x00,0x00};
551 codec_addr_wdat[0]=addr<<1;
552 codec_addr_wdat[1]=wdat;
553 i2c_master_write(0x34<<1,codec_addr_wdat,2);
554 }
555
556 /**
557 * @brief This function serves to enable i2c master for codec i2c slave .
558 * @param[in] none.
559 * @return none.
560 */
audio_i2c_init(codec_type_e codec_type,i2c_sda_pin_e sda_pin,i2c_scl_pin_e scl_pin)561 void audio_i2c_init(codec_type_e codec_type, i2c_sda_pin_e sda_pin,i2c_scl_pin_e scl_pin)
562 {
563 i2c_master_init();
564 i2c_set_master_clk((unsigned char)(sys_clk.pclk*1000*1000/(4*200000)));//set i2c frequency 200K.
565 if(codec_type==INNER_CODEC)
566 {
567 reg_audio_i2c_mode=0x05;//codec config by i2c
568 reg_audio_i2c_addr=0x34;
569 }
570 else if(codec_type==EXT_CODEC)
571 {
572 i2c_set_pin(sda_pin,scl_pin);
573 }
574 }
575
576 /**
577 * @brief This function serves to initialize audio by i2c
578 * @param[in] flow_mode - select input out flow mode
579 * @param[in] rate - audio sampling rate.
580 * @param[in] channel_wl - word length and channel number.
581 * @return none
582 */
audio_init_i2c(audio_flow_mode_e flow_mode,audio_sample_rate_e rate,audio_channel_wl_mode_e channel_wl)583 void audio_init_i2c(audio_flow_mode_e flow_mode,audio_sample_rate_e rate,audio_channel_wl_mode_e channel_wl)
584 {
585 aduio_set_chn_wl(channel_wl);
586 audio_set_codec_clk(1,16);////from ppl 192/16=12M
587 audio_mux_config(CODEC_I2S,audio_i2s_codec_config.audio_in_mode,audio_i2s_codec_config.audio_in_mode,audio_i2s_codec_config.audio_out_mode);
588 audio_i2s_config(I2S_I2S_MODE,audio_i2s_codec_config.i2s_data_select,audio_i2s_codec_config.i2s_codec_m_s_mode,&audio_i2s_invert_config);
589 audio_set_i2s_clock(rate,AUDIO_RATE_EQUAL,0);
590 audio_clk_en(1,1);
591 audio_i2c_init(INNER_CODEC,0,0);
592 audio_i2c_codec_write(addr_audio_codec_vic_ctr,FLD_AUDIO_CODEC_SLEEP_ANALOG);//active analog sleep mode
593 while(!(audio_i2c_codec_read(addr_audio_codec_stat_ctr)&FLD_AUDIO_CODEC_PON_ACK));//wait codec can be configed
594 if(flow_mode<BUF_TO_LINE_OUT)
595 {
596 audio_codec_adc_config(audio_i2s_codec_config.i2s_codec_m_s_mode,(flow_mode%3),rate,audio_i2s_codec_config.codec_data_select,I2C_WREG);
597 }
598 if(flow_mode>LINE_IN_TO_BUF)
599 {
600 audio_codec_dac_config(audio_i2s_codec_config.i2s_codec_m_s_mode,rate,audio_i2s_codec_config.codec_data_select,I2C_WREG);
601 }
602 while(!(audio_i2c_codec_read(addr_audio_codec_stat_ctr)==(FLD_AUDIO_CODEC_ADC12_LOCKED|FLD_AUDIO_CODEC_DAC_LOCKED|FLD_AUDIO_CODEC_PON_ACK)));//wait codec adc/dac locked
603 audio_data_fifo0_path_sel(I2S_DATA_IN_FIFO,I2S_OUT);
604 }
605
606 /**
607 * @brief This function serves to config codec for dac.
608 * @param[in] mode - select i2s as master or slave
609 * @param[in] rate - audio sampling rate
610 * @param[in] data_select - codec dac word length
611 * @param[in] wreg_mode - mcu or i2c config codec
612 * @return none
613 */
audio_codec_dac_config(i2s_codec_m_s_mode_e mode,audio_sample_rate_e rate,codec_data_select_e data_select,codec_wreg_mode_e wreg_mode)614 void audio_codec_dac_config(i2s_codec_m_s_mode_e mode,audio_sample_rate_e rate,codec_data_select_e data_select,codec_wreg_mode_e wreg_mode)
615 {
616
617 if(wreg_mode==MCU_WREG)
618 {
619 BM_SET(reg_audio_codec_dac_ctr,FLD_AUDIO_CODEC_DAC_SOFT_MUTE); //dac mute
620 if(audio_i2s_codec_config.dac_output_chn_select)
621 {
622 BM_CLR(reg_audio_codec_dac_ctr,FLD_AUDIO_CODEC_DAC_SB); //active DAC power
623 BM_SET(reg_audio_codec_dac_ctr,FLD_AUDIO_CODEC_DAC_LEFT_ONLY); //active left channel only
624 }
625 else
626 {
627 BM_CLR(reg_audio_codec_dac_ctr,FLD_AUDIO_CODEC_DAC_SB|FLD_AUDIO_CODEC_DAC_LEFT_ONLY);//active DAC power,active left and right channel
628 }
629
630 BM_CLR(reg_audio_codec_vic_ctr,FLD_AUDIO_CODEC_SB|FLD_AUDIO_CODEC_SB_ANALOG|FLD_AUDIO_CODEC_SLEEP_ANALOG);//disable sleep mode ,disable sb_analog,disable global standby
631
632 /* data word length ,interface master/slave selection, audio interface protocol selection ,active dac audio interface*/
633 reg_audio_codec_dac_itf_ctr= MASK_VAL( FLD_AUDIO_CODEC_FORMAT, CODEC_I2S_MODE,\
634 FLD_AUDIO_CODEC_DAC_ITF_SB, CODEC_ITF_AC, \
635 FLD_AUDIO_CODEC_SLAVE, mode, \
636 FLD_AUDIO_CODEC_WL, data_select);
637
638 /*disable DAC digital gain coupling, Left channel DAC digital gain*/
639 reg_audio_codec_dacl_gain=MASK_VAL(FLD_AUDIO_CODEC_DAC_LRGOD,0,\
640 FLD_AUDIO_CODEC_DAC_GODL,audio_i2s_codec_config.out_digital_gain);
641
642 reg_audio_codec_dacr_gain=MASK_VAL(FLD_AUDIO_CODEC_DAC_GODR,audio_i2s_codec_config.out_digital_gain); /*Right channel DAC digital gain*/
643
644 /*disable Headphone gain coupling, set Left channel HP amplifier gain*/
645 reg_audio_codec_hpl_gain=MASK_VAL(FLD_AUDIO_CODEC_HPL_LRGO,0,\
646 FLD_AUDIO_CODEC_HPL_GOL,audio_i2s_codec_config.out_analog_gain);
647
648 reg_audio_codec_hpr_gain=MASK_VAL(FLD_AUDIO_CODEC_HPR_GOR, audio_i2s_codec_config.out_analog_gain); /* Right channel HP amplifier gain programming*/
649
650 reg_audio_codec_dac_freq_ctr=(FLD_AUDIO_CODEC_DAC_FREQ&(rate== AUDIO_ADC_16K_DAC_48K ? AUDIO_48K :rate));
651
652 BM_CLR(reg_audio_codec_dac_ctr,FLD_AUDIO_CODEC_DAC_SOFT_MUTE); /*dac mute*/
653 }
654
655 else if (wreg_mode==I2C_WREG)
656 {
657 /*active DAC power,active left and right channel,dac mute*/
658 audio_i2c_codec_write(addr_audio_codec_dac_ctr,MASK_VAL( FLD_AUDIO_CODEC_DAC_SB, 0,\
659 FLD_AUDIO_CODEC_DAC_LEFT_ONLY, 0, \
660 FLD_AUDIO_CODEC_DAC_SOFT_MUTE, 1));
661
662
663 /*disable sleep mode ,disable sb_analog,disable global standby*/
664 audio_i2c_codec_write(addr_audio_codec_vic_ctr,MASK_VAL( FLD_AUDIO_CODEC_SB, 0,\
665 FLD_AUDIO_CODEC_SB_ANALOG, 0, \
666 FLD_AUDIO_CODEC_SLEEP_ANALOG, 0));
667
668 /*data word length ,interface master/slave selection, audio interface protocol selection ,active dac audio interface */
669 audio_i2c_codec_write(addr_audio_codec_dac_itf_ctr,MASK_VAL( FLD_AUDIO_CODEC_FORMAT, CODEC_I2S_MODE,\
670 FLD_AUDIO_CODEC_DAC_ITF_SB, CODEC_ITF_AC, \
671 FLD_AUDIO_CODEC_SLAVE, mode, \
672 FLD_AUDIO_CODEC_WL, data_select));
673
674 /* disable DAC digital gain coupling, Left channel DAC digital gain */
675 audio_i2c_codec_write(addr_audio_codec_dacl_gain,MASK_VAL(FLD_AUDIO_CODEC_DAC_LRGOD,0,\
676 FLD_AUDIO_CODEC_DAC_GODL,audio_i2s_codec_config.out_digital_gain));
677
678
679 audio_i2c_codec_write(addr_audio_codec_dacr_gain,MASK_VAL(FLD_AUDIO_CODEC_DAC_GODR,audio_i2s_codec_config.out_digital_gain));/* Right channel DAC digital gain */
680
681
682 /* disable Headphone gain coupling, set Left channel HP amplifier gain */
683 audio_i2c_codec_write(addr_audio_codec_hpl_gain,MASK_VAL(FLD_AUDIO_CODEC_HPL_LRGO,0,\
684 FLD_AUDIO_CODEC_HPL_GOL,audio_i2s_codec_config.out_analog_gain));
685
686 audio_i2c_codec_write(addr_audio_codec_hpr_gain,MASK_VAL(FLD_AUDIO_CODEC_HPR_GOR, audio_i2s_codec_config.out_analog_gain));/* Right channel HP amplifier gain programming*/
687
688 audio_i2c_codec_write(addr_audio_codec_dac_freq_ctr,(FLD_AUDIO_CODEC_DAC_FREQ&rate));
689
690 /*dac mute*/
691 audio_i2c_codec_write(addr_audio_codec_dac_ctr,MASK_VAL( FLD_AUDIO_CODEC_DAC_SB, 0,\
692 FLD_AUDIO_CODEC_DAC_LEFT_ONLY, 0, \
693 FLD_AUDIO_CODEC_DAC_SOFT_MUTE, 0));
694 }
695
696 }
697
698
699
700 /**
701 * @brief This function serves to config codec for adc.
702 * @param[in] mode - select i2s as master or slave
703 * @param[in] in_mode - line_in/amic/dmic input mode select
704 * @param[in] rate - audio sampling rate
705 * @param[in] data_select - codec adc word length
706 * @param[in] wreg_mode - mcu or i2c config codec
707 * @return none
708 */
audio_codec_adc_config(i2s_codec_m_s_mode_e mode,audio_input_mode_e in_mode,audio_sample_rate_e rate,codec_data_select_e data_select,codec_wreg_mode_e wreg_mode)709 void audio_codec_adc_config(i2s_codec_m_s_mode_e mode,audio_input_mode_e in_mode,audio_sample_rate_e rate,codec_data_select_e data_select,codec_wreg_mode_e wreg_mode)
710 {
711
712 if(wreg_mode==MCU_WREG)
713 {
714 BM_SET(reg_audio_codec_adc12_ctr,FLD_AUDIO_CODEC_ADC12_SOFT_MUTE); /*adc mute*/
715 if((audio_i2s_codec_config.audio_in_mode==BIT_16_MONO)||((audio_i2s_codec_config.audio_in_mode==BIT_20_OR_24_MONO)))
716 {
717 BM_CLR(reg_audio_codec_adc12_ctr,FLD_AUDIO_CODEC_ADC1_SB);/*active anc0 channel,mono .*/
718 }
719 else
720 {
721 BM_CLR(reg_audio_codec_adc12_ctr,FLD_AUDIO_CODEC_ADC1_SB|FLD_AUDIO_CODEC_ADC2_SB);/*active adc0 and adc1 channel*/
722 }
723 BM_CLR(reg_audio_codec_vic_ctr,FLD_AUDIO_CODEC_SB|FLD_AUDIO_CODEC_SB_ANALOG|FLD_AUDIO_CODEC_SLEEP_ANALOG);/*disable sleep mode ,disable sb_analog,disable global standby*/
724
725 if (in_mode==AMIC_INPUT)
726 {
727 /*Microphone 1 input selection ,Microphone biasing active,Single-ended input,MICBIAS1 output=2.08V,*/
728 reg_audio_codec_mic1_ctr= MASK_VAL( FLD_AUDIO_CODEC_MIC1_SEL, 0,\
729 FLD_AUDIO_CODEC_MICBIAS1_SB, 0, \
730 FLD_AUDIO_CODEC_MIC_DIFF1, audio_i2s_codec_config.mic_input_mode_select,\
731 FLD_AUDIO_CODEC_MICBIAS1_V, 0);
732 /*Microphone 2 input selection,Single-ended input*/
733 reg_audio_codec_mic2_ctr= MASK_VAL( FLD_AUDIO_CODEC_MIC2_SEL, 0,\
734 FLD_AUDIO_CODEC_MIC_DIFF2, audio_i2s_codec_config.mic_input_mode_select);
735
736 /*set wind noise filter */
737 reg_audio_codec_adc_wnf_ctr = audio_i2s_codec_config.adc_wnf_mode_select;
738
739 /*analog 0/4/8/12/16/20 dB boost gain*/
740 reg_audio_codec_mic_l_R_gain= MASK_VAL( FLD_AUDIO_CODEC_AMIC_L_GAIN, audio_i2s_codec_config.in_analog_gain,\
741 FLD_AUDIO_CODEC_AMIC_R_GAIN, audio_i2s_codec_config.in_analog_gain);
742 }
743 else if(in_mode==DMIC_INPUT)
744 {
745 reg_audio_dmic_12=MASK_VAL( FLD_AUDIO_CODEC_ADC_DMIC_SEL2, 1,\
746 FLD_AUDIO_CODEC_ADC_DMIC_SEL1,1, \
747 FLD_AUDIO_CODEC_DMIC2_SB,CODEC_ITF_AC,\
748 FLD_AUDIO_CODEC_DMIC1_SB, CODEC_ITF_AC);
749 }
750
751 else if(in_mode==LINE_INPUT)
752 {
753 reg_audio_codec_mic1_ctr= MASK_VAL(FLD_AUDIO_CODEC_MIC_DIFF1, audio_i2s_codec_config.mic_input_mode_select);
754
755 reg_audio_codec_mic2_ctr= MASK_VAL(FLD_AUDIO_CODEC_MIC_DIFF2, audio_i2s_codec_config.mic_input_mode_select);
756
757 /*analog 0/4/8/12/16/20 dB boost gain*/
758 reg_audio_codec_mic_l_R_gain= MASK_VAL( FLD_AUDIO_CODEC_AMIC_L_GAIN, audio_i2s_codec_config.in_analog_gain,\
759 FLD_AUDIO_CODEC_AMIC_R_GAIN, audio_i2s_codec_config.in_analog_gain);
760 }
761
762 /*0db~43db 1db step ,digital programmable gain*/
763 reg_audio_adc1_gain=MASK_VAL( FLD_AUDIO_CODEC_ADC_LRGID,1,\
764 FLD_AUDIO_CODEC_ADC_GID1,audio_i2s_codec_config.in_digital_gain);
765 /*data word length ,interface master/slave selection, audio interface protocol selection */
766 reg_audio_codec_adc_itf_ctr= MASK_VAL( FLD_AUDIO_CODEC_FORMAT, CODEC_I2S_MODE,\
767 FLD_AUDIO_CODEC_SLAVE, mode, \
768 FLD_AUDIO_CODEC_WL, data_select);
769 /*audio adc interface active*/
770 BM_CLR(reg_audio_codec_adc2_ctr,FLD_AUDIO_CODEC_ADC12_SB);
771
772 /* adc high pass filter active, set adc sample rate */
773 reg_audio_codec_adc_freq_ctr=MASK_VAL( FLD_AUDIO_CODEC_ADC12_HPF_EN,1,\
774 FLD_AUDIO_CODEC_ADC_FREQ,rate == AUDIO_ADC_16K_DAC_48K ? AUDIO_16K :rate);
775
776 BM_CLR(reg_audio_codec_adc12_ctr,FLD_AUDIO_CODEC_ADC12_SOFT_MUTE);/*adc unmute*/
777 }
778
779 else if(wreg_mode==I2C_WREG)
780 {
781
782
783 /*active adc0 and adc1 channel, if mono only active adc1,adc mute*/
784 audio_i2c_codec_write(addr_audio_codec_adc12_ctr,MASK_VAL( FLD_AUDIO_CODEC_ADC1_SB, 0,\
785 FLD_AUDIO_CODEC_ADC2_SB, 0, \
786 FLD_AUDIO_CODEC_ADC12_SOFT_MUTE, 1));
787
788 /*disable sleep mode ,disable sb_analog,disable global standby*/
789 audio_i2c_codec_write(addr_audio_codec_vic_ctr,MASK_VAL( FLD_AUDIO_CODEC_SB, 0,\
790 FLD_AUDIO_CODEC_SB_ANALOG, 0, \
791 FLD_AUDIO_CODEC_SLEEP_ANALOG, 0));
792
793
794 if (in_mode==AMIC_INPUT)
795 {
796 /*Microphone 1 input selection ,Microphone biasing active,Single-ended input,MICBIAS1 output=2.08V,*/
797 audio_i2c_codec_write(addr_audio_codec_mic1_ctr,MASK_VAL( FLD_AUDIO_CODEC_MIC1_SEL, 0,\
798 FLD_AUDIO_CODEC_MICBIAS1_SB, 0, \
799 FLD_AUDIO_CODEC_MIC_DIFF1, 0,\
800 FLD_AUDIO_CODEC_MICBIAS1_V, 0));
801
802 /*Microphone 2 input selection,Single-ended input*/
803 audio_i2c_codec_write(addr_audio_codec_mic2_ctr,MASK_VAL( FLD_AUDIO_CODEC_MIC2_SEL, 0,\
804 FLD_AUDIO_CODEC_MIC_DIFF2, 0));
805
806 /*analog 0/4/8/12/16/20 dB boost gain*/
807 audio_i2c_codec_write(addr_audio_codec_mic_l_R_gain, MASK_VAL( FLD_AUDIO_CODEC_AMIC_L_GAIN, audio_i2s_codec_config.in_analog_gain,\
808 FLD_AUDIO_CODEC_AMIC_R_GAIN, audio_i2s_codec_config.in_analog_gain));
809
810 }
811 else if(in_mode==DMIC_INPUT)
812 {
813 audio_i2c_codec_write(addr_audio_dmic_12,MASK_VAL( FLD_AUDIO_CODEC_ADC_DMIC_SEL2, 1,\
814 FLD_AUDIO_CODEC_ADC_DMIC_SEL1,1, \
815 FLD_AUDIO_CODEC_DMIC2_SB,CODEC_ITF_AC,\
816 FLD_AUDIO_CODEC_DMIC1_SB, CODEC_ITF_AC));
817 }
818
819 else if(in_mode==LINE_INPUT)
820 {
821 /*analog 0/4/8/12/16/20 dB boost gain*/
822 audio_i2c_codec_write(addr_audio_codec_mic_l_R_gain, MASK_VAL( FLD_AUDIO_CODEC_AMIC_L_GAIN, audio_i2s_codec_config.in_analog_gain,\
823 FLD_AUDIO_CODEC_AMIC_R_GAIN, audio_i2s_codec_config.in_analog_gain));
824 }
825
826 /*0db~43db 1db step ,digital programmable gain*/
827 audio_i2c_codec_write(addr_audio_adc1_gain,MASK_VAL( FLD_AUDIO_CODEC_ADC_LRGID,1,\
828 FLD_AUDIO_CODEC_ADC_GID1,audio_i2s_codec_config.in_digital_gain));
829
830
831 audio_i2c_codec_write(addr_audio_codec_adc_itf_ctr,MASK_VAL( FLD_AUDIO_CODEC_FORMAT, CODEC_I2S_MODE,\
832 FLD_AUDIO_CODEC_SLAVE, mode, \
833 FLD_AUDIO_CODEC_WL, data_select));
834
835 audio_i2c_codec_write(addr_audio_codec_adc2_ctr,~FLD_AUDIO_CODEC_ADC12_SB); /*audio adc interface active*/
836
837
838 /* adc high pass filter active, set adc sample rate */
839 audio_i2c_codec_write(addr_audio_codec_adc_freq_ctr,MASK_VAL( FLD_AUDIO_CODEC_ADC12_HPF_EN,1,\
840 FLD_AUDIO_CODEC_ADC_FREQ,rate));
841
842 /*dac mute*/
843 audio_i2c_codec_write(addr_audio_codec_adc12_ctr,MASK_VAL( FLD_AUDIO_CODEC_ADC1_SB, 0,\
844 FLD_AUDIO_CODEC_ADC2_SB, 0, \
845 FLD_AUDIO_CODEC_ADC12_SOFT_MUTE, 0));
846
847 }
848
849
850 }
851
852
853 /**
854 * @brief This function serves to set data path.
855 * @param[in] audio_flow - audio flow select
856 * @param[in] ain0_mode - fifo0 input mode select
857 * @param[in] ain1_mode - fifo1 input mode select
858 * @param[in] i2s_aout_mode - fifo output source select
859 * @return none
860 */
audio_mux_config(audio_flow_e audio_flow,audio_in_mode_e ain0_mode,audio_in_mode_e ain1_mode,audio_out_mode_e i2s_aout_mode)861 void audio_mux_config(audio_flow_e audio_flow, audio_in_mode_e ain0_mode , audio_in_mode_e ain1_mode,audio_out_mode_e i2s_aout_mode)
862 {
863 reg_audio_ctrl |= audio_flow;
864 reg_audio_tune= MASK_VAL( FLD_AUDIO_I2S_I2S_AIN0_COME, ain0_mode,\
865 FLD_AUDIO_I2S_I2S_AIN1_COME, ain1_mode, \
866 FLD_AUDIO_I2S_I2S_AOUT_COME, i2s_aout_mode);
867 }
868
869
870 /**
871 * @brief This function serves to config interface, word length, and m/s .
872 * @param[in] i2s_format - interface protocol
873 * @param[in] wl - audio data word length
874 * @param[in] m_s - select i2s as master or slave
875 * @param[in] i2s_config_t - the prt of i2s_config_t that configure i2s lr_clk phase and lr_clk swap.
876 * i2s_config_t->i2s_lr_clk_invert_select-lr_clk phase control(in RJ,LJ or i2s modes),in i2s mode(opposite phasing in RJ,LJ mode), 0=right channel data when lr_clk high ,1=right channel data when lr_clk low.
877 * in DSP mode(in DSP mode only), DSP mode A/B select,0=DSP mode A ,1=DSP mode B.
878 * i2s_config_t->i2s_data_invert_select - 0=left channel data left,1=right channel data left.
879 * @attention:If the left and right channels are both active in i2s mode,there will be a phase difference(about 1 sample) between the left and right channels,you can set i2s_lr_clk_invert_select=1 to eliminate the phase difference,
880 * but data output channel will be inverted,you can also set i2s_config_t->i2s_data_invert_select=1 to recovery it.
881 * @return none
882 */
audio_i2s_config(i2s_mode_select_e i2s_format,i2s_data_select_e wl,i2s_codec_m_s_mode_e m_s,aduio_i2s_invert_config_t * i2s_config_t)883 void audio_i2s_config(i2s_mode_select_e i2s_format,i2s_data_select_e wl, i2s_codec_m_s_mode_e m_s , aduio_i2s_invert_config_t * i2s_config_t)
884 {
885
886 reg_i2s_cfg = MASK_VAL( FLD_AUDIO_I2S_FORMAT, i2s_format,\
887 FLD_AUDIO_I2S_WL, wl, \
888 FLD_AUDIO_I2S_LRP, i2s_config_t->i2s_lr_clk_invert_select, \
889 FLD_AUDIO_I2S_LRSWAP, i2s_config_t->i2s_data_invert_select, \
890 FLD_AUDIO_I2S_ADC_DCI_MS, m_s, \
891 FLD_AUDIO_I2S_DAC_DCI_MS, m_s);
892 }
893
894 /**
895 * @brief This function serves to set i2s clock and audio sampling rate when i2s as master.
896 * @param[in] audio_rate - audio sampling rate
897 * @param[in] match - the match of audio rate.
898 * @param[in] match_en - initial must 0, then change rate must 1
899 * @return none
900 * @attention i2s clock divider from pll,sampling rate calculation is based on pll=192M,so pll must be 192M
901 */
audio_set_i2s_clock(audio_sample_rate_e audio_rate,audio_rate_match_e match,unsigned char match_en)902 _attribute_ram_code_sec_noinline_ void audio_set_i2s_clock (audio_sample_rate_e audio_rate,audio_rate_match_e match,unsigned char match_en)
903 {
904 reg_tx_wptr=0xffff;//enable tx_rptr
905 unsigned short tx_rptr_old;
906 switch(audio_rate)
907 {
908 case AUDIO_8K :
909 audio_set_i2s_clk(1,8);//set i2s clk 24M
910 audio_set_i2s_bclk(12);//24/(2*12) = 1M bclk
911 audio_set_lrclk(125,125); //bclk/125=8k
912 break;
913
914 case AUDIO_16K:
915 audio_set_i2s_clk(1,8);//set i2s clk 24M
916 audio_set_i2s_bclk(6);//24/(2*6) = 2M bclk
917 audio_set_lrclk(125,125); //bclk/125=16k
918 break;
919
920 case AUDIO_32K:
921 audio_set_i2s_clk(1,8);//set i2s clk 24M
922 audio_set_i2s_bclk(3);//24/(2*3) = 4M bclk
923 audio_set_lrclk(125,125); //bclk/125=32k
924 break;
925
926 case AUDIO_ADC_16K_DAC_48K:
927 audio_set_i2s_clk(2,125);//i2s clk 3.072 M
928 audio_set_i2s_bclk(0);//3.072/1 = 3.072M bclk
929 audio_set_lrclk(192,64);//adc_lrclk=3.072/192=16K,dac_lrclk=3.072/64=48K
930 break;
931
932 case AUDIO_48K:
933 if(match_en)
934 {
935 tx_rptr_old = reg_tx_rptr;
936 while(tx_rptr_old==reg_tx_rptr);
937 }
938 if(match==AUDIO_RATE_EQUAL)//48000
939 {
940 audio_set_i2s_clk(2,125);//i2s clk 3.072 M
941 audio_set_i2s_bclk(0);//3.072/1 = 3.072M bclk
942 audio_set_lrclk(64,64);//bclk/64=48k
943 }
944
945 else if(match==AUDIO_RATE_GT_L0)//48004
946 {
947 audio_set_i2s_clk(3,169);
948 audio_set_i2s_bclk(0);
949 audio_set_lrclk(71,71);
950 }
951
952 else if(match==AUDIO_RATE_GT_L1)//48012.0
953 {
954 audio_set_i2s_clk(4,129);
955 audio_set_i2s_bclk(0);
956 audio_set_lrclk(124,124);
957 }
958 else if(match==AUDIO_RATE_LT_L0)
959 {
960 audio_set_i2s_clk(2,63);//47994.0
961 audio_set_i2s_bclk(0);
962 audio_set_lrclk(127,127);
963 }
964
965 else if(match==AUDIO_RATE_LT_L1)
966 {
967 audio_set_i2s_clk(4,165);//47985.0
968 audio_set_i2s_bclk(0);
969 audio_set_lrclk(97,97);
970 }
971 break;
972
973 case AUDIO_44EP1K:
974 if(match_en)
975 {
976 tx_rptr_old = reg_tx_rptr;
977 while(tx_rptr_old==reg_tx_rptr);
978 }
979
980 if(match==AUDIO_RATE_EQUAL)//44099.9
981 {
982 audio_set_i2s_clk(8,215);
983 audio_set_i2s_bclk(0);
984 audio_set_lrclk(162,162);
985 }
986 else if(match==AUDIO_RATE_GT_L0)//44110.2
987 {
988 audio_set_i2s_clk(11,228);
989 audio_set_i2s_bclk(0);
990 audio_set_lrclk(210,210);
991 }
992
993 else if(match==AUDIO_RATE_GT_L1)//44117.6
994 {
995 audio_set_i2s_clk(5,170);
996 audio_set_i2s_bclk(0);
997 audio_set_lrclk(128,128);
998 }
999
1000 else if(match==AUDIO_RATE_LT_L0)//44094.4
1001 {
1002 audio_set_i2s_clk(7,254);
1003 audio_set_i2s_bclk(0);
1004 audio_set_lrclk(120,120);
1005 }
1006
1007 else if(match==AUDIO_RATE_LT_L1)//44081.6
1008 {
1009 audio_set_i2s_clk(9,245);
1010 audio_set_i2s_bclk(0);
1011 audio_set_lrclk(160,160);
1012 }
1013 break;
1014 }
1015
1016 }
1017
1018
1019 /**
1020 * @brief This function serves to set audio rx dma chain transfer.
1021 * @param[in] chn - dma channel
1022 * @param[in] in_buff - the pointer of rx_buff.
1023 * @param[in] buff_size - the size of rx_buff.
1024 * @return none
1025 */
audio_rx_dma_chain_init(dma_chn_e chn,unsigned short * in_buff,unsigned int buff_size)1026 void audio_rx_dma_chain_init (dma_chn_e chn,unsigned short * in_buff,unsigned int buff_size )
1027 {
1028 audio_rx_dma_config(chn,(unsigned short*)in_buff, buff_size, &g_audio_rx_dma_list_cfg);
1029 audio_rx_dma_add_list_element(&g_audio_rx_dma_list_cfg, &g_audio_rx_dma_list_cfg,(unsigned short*)in_buff, buff_size);
1030 audio_rx_dma_en();
1031 }
1032
1033 /**
1034 * @brief This function serves to initialize audio tx dma chain transfer.
1035 * @param[in] chn - dma channel
1036 * @param[in] out_buff - the pointer of tx_buff.
1037 * @param[in] buff_size - the size of tx_buff.
1038 * @return none
1039 */
audio_tx_dma_chain_init(dma_chn_e chn,unsigned short * out_buff,unsigned int buff_size)1040 void audio_tx_dma_chain_init (dma_chn_e chn,unsigned short * out_buff,unsigned int buff_size)
1041 {
1042 audio_tx_dma_config(chn, (unsigned short*)out_buff, buff_size, &g_audio_tx_dma_list_cfg);
1043 audio_tx_dma_add_list_element(&g_audio_tx_dma_list_cfg, &g_audio_tx_dma_list_cfg, (unsigned short*)out_buff, buff_size);
1044 audio_tx_dma_en();
1045 }
1046
1047
1048
1049
1050 #define WM8731_ANA_AUDIO_PATH_CTRL 0x08 //Analogue Audio Path Control
1051 #define WM8731_DIG_AUDIO_PATH_CTRL 0x0a //Digital Audio Path Control
1052 #define WM8731_POWER_DOWN_CTRL 0x0c //Power Down Control
1053 #define WM8731_ST_LINE_VOL 0x00 //Set linmute volume
1054 #define WM8731_ST_RINE_VOL 0x02 //Set rinmute volume
1055 #define WM8731_DIG_AUDIO_INTERFACE_FORMAT 0x0e //Digital Audio Interface Format
1056 #define WM8731_SAMPLING_CTRL 0x10 //Sampling Control
1057 #define WM8731_ACTIVE_CTRL 0x12 //Active Control
1058 #define WM8731_RESET_CTRL 0x1e //Reset Register
1059
1060 unsigned char LineIn_To_I2S_CMD_TAB[9][2]={ {WM8731_RESET_CTRL, 0x00},
1061 {WM8731_ST_LINE_VOL, 0x10},
1062 {WM8731_ST_RINE_VOL, 0x10},
1063 {WM8731_ANA_AUDIO_PATH_CTRL, 0x13},
1064 {WM8731_DIG_AUDIO_PATH_CTRL, 0x00},
1065 {WM8731_POWER_DOWN_CTRL, 0x22},
1066 {WM8731_DIG_AUDIO_INTERFACE_FORMAT, 0x02},
1067 {WM8731_SAMPLING_CTRL, 0x19},
1068 {WM8731_ACTIVE_CTRL, 0x01},
1069
1070 };
1071
1072 /**
1073 * @brief This function serves to set external codec by i2c
1074 * @return none
1075 */
1076
audio_set_ext_codec(void)1077 void audio_set_ext_codec(void)
1078 {
1079 for (unsigned char i=0;i<9;i++)
1080 {
1081 i2c_master_write(0x34,&LineIn_To_I2S_CMD_TAB[i][0],2);
1082 }
1083 }
1084
1085
1086 /**
1087 * @brief This function serves to set pwm0 as external codec mclk
1088 * @param[in] pin - the pin of pwm0
1089 * @return none
1090 */
pwm_set(pwm_pin_e pin)1091 void pwm_set(pwm_pin_e pin)
1092 {
1093 pwm_set_pin(pin);
1094 pwm_set_clk((unsigned char) (sys_clk.pclk*1000*1000/24000000-1));//set pwm clk equal pclk 24M
1095 pwm_set_pwm0_mode(PWM_NORMAL_MODE);
1096 pwm_set_tcmp(PWM0_ID,1);
1097 pwm_set_tmax(PWM0_ID,2);//24M/2=12M pwm mclk to ext codec clk
1098 pwm_start(PWM0_ID);
1099
1100 }
1101
1102
1103 /**
1104 * @brief This function serves to initialize audio(external codec WM8731) by i2c.
1105 * @param[in] pwm0_pin - the pin of pwm0
1106 * @param[in] sda_pin - the pin port selected as I2C sda pin port.
1107 * @param[in] scl_pin - the pin port selected as I2C scl pin port.
1108 * @return none
1109 */
audio_i2s_init(pwm_pin_e pwm0_pin,i2c_sda_pin_e sda_pin,i2c_scl_pin_e scl_pin)1110 void audio_i2s_init(pwm_pin_e pwm0_pin, i2c_sda_pin_e sda_pin,i2c_scl_pin_e scl_pin)
1111 {
1112 pwm_set(pwm0_pin);
1113 audio_i2s_set_pin();
1114 audio_i2c_init(EXT_CODEC,sda_pin,scl_pin);
1115 aduio_set_chn_wl(MONO_BIT_16);
1116 audio_mux_config(IO_I2S,BIT_16_MONO,BIT_16_MONO,BIT_16_MONO_FIFO0);
1117 audio_i2s_config(I2S_I2S_MODE,I2S_BIT_16_DATA,I2S_M_CODEC_S,&audio_i2s_invert_config);
1118 audio_set_i2s_clock(AUDIO_32K,AUDIO_RATE_EQUAL,0);
1119 audio_clk_en(1,1);
1120 audio_set_ext_codec();
1121 audio_data_fifo0_path_sel(I2S_DATA_IN_FIFO,I2S_OUT);
1122
1123 }
1124
1125 /**
1126 * @brief This function serves to active soft mute dac and disable dma .
1127 * @return none
1128 */
audio_pause_out_path(void)1129 void audio_pause_out_path(void)
1130 {
1131 BM_SET(reg_audio_codec_dac_ctr,FLD_AUDIO_CODEC_DAC_SOFT_MUTE);//dac mute
1132 audio_tx_dma_dis();
1133 }
1134
1135 /**
1136 * @brief This function serves to inactive soft mute dac and enable dma after change_sample_rate.
1137 * @return none
1138 */
audio_resume_out_path(void)1139 void audio_resume_out_path(void)
1140 {
1141 BM_CLR(reg_audio_codec_dac_ctr,FLD_AUDIO_CODEC_DAC_SOFT_MUTE);//dac unmute
1142 audio_tx_dma_en();
1143 }
1144 /**
1145 * @brief This function serves to change sample rate for dac.
1146 * @param[in] rate - the sample rate of dac
1147 * @return none
1148 */
audio_change_sample_rate(audio_sample_rate_e rate)1149 _attribute_ram_code_sec_ void audio_change_sample_rate (audio_sample_rate_e rate)
1150 {
1151 audio_set_i2s_clock(rate, AUDIO_RATE_EQUAL,1);
1152 reg_audio_codec_dac_freq_ctr=(FLD_AUDIO_CODEC_DAC_FREQ&rate);
1153 }
1154
1155
1156
1157 /**
1158 * @brief This function serves to power down codec_dac.
1159 * @return none
1160 */
audio_codec_dac_power_down(void)1161 void audio_codec_dac_power_down(void)
1162 {
1163 BM_SET(reg_audio_codec_dac_ctr,FLD_AUDIO_CODEC_DAC_SOFT_MUTE);
1164 delay_ms(10);
1165 BM_SET(reg_audio_codec_dac_itf_ctr,FLD_AUDIO_CODEC_DAC_ITF_SB);
1166 BM_SET(reg_audio_codec_dac_ctr,FLD_AUDIO_CODEC_DAC_SB);
1167 delay_ms(1);
1168 BM_SET(reg_audio_codec_vic_ctr,FLD_AUDIO_CODEC_SLEEP_ANALOG);
1169 reg_audio_codec_vic_ctr= MASK_VAL( FLD_AUDIO_CODEC_SB, CODEC_ITF_PD,\
1170 FLD_AUDIO_CODEC_SB_ANALOG, CODEC_ITF_PD, \
1171 FLD_AUDIO_CODEC_SLEEP_ANALOG, CODEC_ITF_PD);
1172 audio_tx_dma_dis();
1173 audio_clk_en(0,0);
1174 }
1175
1176 /**
1177 * @brief This function serves to power on codec_dac.
1178 * @return none
1179 */
audio_codec_dac_power_on(void)1180 void audio_codec_dac_power_on(void)
1181 {
1182 audio_clk_en(1,1);
1183 BM_SET(reg_audio_codec_vic_ctr,FLD_AUDIO_CODEC_SLEEP_ANALOG);
1184 delay_ms(1);
1185 BM_CLR(reg_audio_codec_dac_ctr,FLD_AUDIO_CODEC_DAC_SB);
1186 BM_CLR(reg_audio_codec_dac_itf_ctr,FLD_AUDIO_CODEC_DAC_ITF_SB);
1187 reg_audio_codec_vic_ctr= MASK_VAL( FLD_AUDIO_CODEC_SB, CODEC_ITF_AC,\
1188 FLD_AUDIO_CODEC_SB_ANALOG, CODEC_ITF_AC, \
1189 FLD_AUDIO_CODEC_SLEEP_ANALOG, CODEC_ITF_AC);
1190 BM_CLR(reg_audio_codec_dac_ctr,FLD_AUDIO_CODEC_DAC_SOFT_MUTE);//un mute
1191 audio_tx_dma_en();
1192
1193 }
1194
1195 /**
1196 * @brief This function serves to power down codec_adc.
1197 * @return none
1198 */
audio_codec_adc_power_down(void)1199 void audio_codec_adc_power_down(void)
1200 {
1201 BM_SET(reg_audio_codec_adc12_ctr,FLD_AUDIO_CODEC_ADC12_SOFT_MUTE);
1202 delay_ms(10);
1203 BM_SET(reg_audio_codec_adc2_ctr,FLD_AUDIO_CODEC_ADC12_SB);
1204 BM_SET(reg_audio_codec_adc12_ctr,FLD_AUDIO_CODEC_ADC1_SB|FLD_AUDIO_CODEC_ADC2_SB);
1205
1206 BM_SET(reg_audio_codec_vic_ctr,FLD_AUDIO_CODEC_SLEEP_ANALOG);
1207 reg_audio_codec_vic_ctr= MASK_VAL( FLD_AUDIO_CODEC_SB, CODEC_ITF_PD,\
1208 FLD_AUDIO_CODEC_SB_ANALOG, CODEC_ITF_PD, \
1209 FLD_AUDIO_CODEC_SLEEP_ANALOG, CODEC_ITF_PD);
1210 audio_rx_dma_dis();
1211 audio_clk_en(0,0);
1212 }
1213
1214
1215 /**
1216 * @brief This function serves to power on codec_adc.
1217 * @return none
1218 */
audio_codec_adc_power_on(void)1219 void audio_codec_adc_power_on(void)
1220 {
1221 audio_clk_en(1,1);
1222 BM_SET(reg_audio_codec_vic_ctr,FLD_AUDIO_CODEC_SLEEP_ANALOG);
1223 delay_ms(1);
1224 BM_CLR(reg_audio_codec_adc12_ctr,FLD_AUDIO_CODEC_ADC1_SB|FLD_AUDIO_CODEC_ADC2_SB);
1225 BM_CLR(reg_audio_codec_adc2_ctr,FLD_AUDIO_CODEC_ADC12_SB);
1226 reg_audio_codec_vic_ctr= MASK_VAL( FLD_AUDIO_CODEC_SB, CODEC_ITF_AC,\
1227 FLD_AUDIO_CODEC_SB_ANALOG, CODEC_ITF_AC, \
1228 FLD_AUDIO_CODEC_SLEEP_ANALOG, CODEC_ITF_AC);
1229 BM_CLR(reg_audio_codec_adc12_ctr,FLD_AUDIO_CODEC_ADC12_SOFT_MUTE);
1230
1231 audio_rx_dma_en();
1232
1233 }
1234
1235
1236
1237
1238