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