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