1 /*
2  * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3  */
4 
5 #include <ulog/ulog.h>
6 #include <string.h>
7 #include <stdio.h>
8 #include <aos/list.h>
9 #include "audio_rtos.h"
10 #include "control.h"
11 #include "drv/gpio.h"
12 #include "audio_internel.h"
13 
14 #define LOG_TAG    "[haas200_audio]"
15 
16 pcm_stream_handler_t audio_stream_hdl = NULL;
17 pcm_stream_handler_t playback_stream_hdl = NULL;
18 pcm_stream_handler_t capture_stream_hdl = NULL;
19 static int codec_hw_vol_get(struct audio_kcontrol *kcontrol, struct audio_ctl_elem_value *ucontrol);
20 static int codec_hw_vol_put(struct audio_kcontrol *kcontrol, struct audio_ctl_elem_value *ucontrol);
21 static int codec_hw_mute_state_get(struct audio_kcontrol *kcontrol, struct audio_ctl_elem_value *ucontrol);
22 static int codec_hw_mute_state_put(struct audio_kcontrol *kcontrol, struct audio_ctl_elem_value *ucontrol);
23 
24 
25 static const struct audio_kcontrol_new master_codec_controls[] = {
26     SOC_SINGLE_EXT("Master Volume TX",     /* master volume attribute name: defined in sound_mixer.h */
27             0,
28             0,                         /* codec volume minimum value */
29             100,                        /* codec volume maxmum value */
30             0,
31             codec_hw_vol_get,          /* get codec volume api */
32             codec_hw_vol_put),         /* set codec volume api */
33     SOC_SINGLE_EXT("Master Mute State",    /* master mute attribute name: defined in sound_mixer.h */
34             0,
35             0,                         /* codec mute state minimum value */
36             1,                         /* codec mute state maxmum value */
37             0,
38             codec_hw_mute_state_get,   /* get codec mute state */
39             codec_hw_mute_state_put),  /* put codec mute state */
40 };
41 
codec_hw_mute_state_get(struct audio_kcontrol * kcontrol,struct audio_ctl_elem_value * ucontrol)42 static int codec_hw_mute_state_get(struct audio_kcontrol *kcontrol, struct audio_ctl_elem_value *ucontrol)
43 {
44     int mute = 0;
45     if(!kcontrol || !ucontrol) {
46         LOGE(LOG_TAG, "%s:%d: invalid params. \r\n", __func__, __LINE__);
47         return -1;
48     }
49     mute = rl6548_get_mute();
50     LOGD(LOG_TAG, "%s:%d: get mute state %d \r\n", __func__, __LINE__, mute);
51     ucontrol->value.integer.value[0] = mute;
52     return 0;
53 }
54 
codec_hw_mute_state_put(struct audio_kcontrol * kcontrol,struct audio_ctl_elem_value * ucontrol)55 static int codec_hw_mute_state_put(struct audio_kcontrol *kcontrol, struct audio_ctl_elem_value *ucontrol)
56 {
57     int mute = 0;
58     if(!kcontrol || !ucontrol) {
59         LOGE(LOG_TAG, "%s:%d: invalid params. \r\n", __func__, __LINE__);
60         return -1;
61     }
62     mute = ucontrol->value.integer.value[0];
63     LOGD(LOG_TAG, "%s:%d: set mute state %d \r\n", __func__, __LINE__, mute);
64     rl6548_set_mute(mute);
65     return 0;
66 }
67 
68 
codec_hw_vol_get(struct audio_kcontrol * kcontrol,struct audio_ctl_elem_value * ucontrol)69 static int codec_hw_vol_get(struct audio_kcontrol *kcontrol, struct audio_ctl_elem_value *ucontrol)
70 {
71     int volume = 0;
72     if(!kcontrol || !ucontrol) {
73         LOGE(LOG_TAG, "%s:%d: invalid params. \r\n", __func__, __LINE__);
74         return -1;
75     }
76     // TBD: get codec volume, e.g. volume = ac97_get_vol();
77     volume = rl6548_volume_get();
78     LOGD(LOG_TAG, "%s:%d: get volume %d \r\n", __func__, __LINE__, volume);
79     ucontrol->value.integer.value[0] = volume;
80     return 0;
81 }
82 
codec_hw_vol_put(struct audio_kcontrol * kcontrol,struct audio_ctl_elem_value * ucontrol)83 static int codec_hw_vol_put(struct audio_kcontrol *kcontrol, struct audio_ctl_elem_value *ucontrol)
84 {
85     int volume = 0, dac_vol = 0;
86     if(!kcontrol || !ucontrol) {
87         LOGE(LOG_TAG, "%s:%d: invalid params. \r\n", __func__, __LINE__);
88         return -1;
89     }
90     volume = ucontrol->value.integer.value[0];
91     if (volume < 0)
92     {
93         volume = 0;
94     }
95     if (volume > 100)
96     {
97         volume = 100;
98     }
99     LOGD(LOG_TAG, "%s:%d: set volume %d \r\n", __func__, __LINE__, volume);
100     // dac_vol = volume_step[volume];
101     // alsa_volume_set(volume, dac_vol);
102     rl6548_volume_set(volume);
103     return 0;
104 }
105 
106 
codec_pcm_stream_open(int mode,int sampleRate,int channels,pcm_stream_format_t format,aos_hdl_t * event_hdl)107 static pcm_stream_handler_t codec_pcm_stream_open(int mode, int sampleRate, int channels, pcm_stream_format_t format, aos_hdl_t *event_hdl)
108 {
109     int word_len = WL_16;
110     if(format == PCM_STREAM_FORMAT_S8 ) {
111         word_len = WL_8;
112     } else if(format == PCM_STREAM_FORMAT_S16_LE) {
113         word_len = WL_16;
114     } else if(format == PCM_STREAM_FORMAT_S24_LE) {
115         word_len = WL_24;
116     }
117 
118     if(audio_stream_hdl == NULL) {
119         audio_stream_hdl = (pcm_stream_handler_t) rl6548_audio_init(sampleRate, channels, word_len);
120     }
121 
122     if(mode == PCM_STREAM_IN) {
123         capture_stream_hdl = (char*)audio_stream_hdl + 1;
124         LOGD(LOG_TAG, "%s:%d: capture_stream_hdl 0x%x, mode %d, sampleRate %d, channels %d, format %d \r\n", __func__, __LINE__,
125                 capture_stream_hdl, PCM_STREAM_OUT, sampleRate, channels, format);
126     } else if (mode == PCM_STREAM_OUT) {
127         playback_stream_hdl = (char*)audio_stream_hdl + 2;
128         LOGD(LOG_TAG, "%s:%d: playback_stream_hdl 0x%x, mode %d, sampleRate %d, channels %d, format %d \r\n", __func__, __LINE__,
129                 playback_stream_hdl, PCM_STREAM_OUT, sampleRate, channels, format);
130     }
131     return audio_stream_hdl;
132 }
133 
134 
135 
codec_pcm_stream_start(pcm_stream_handler_t hdl)136 static int codec_pcm_stream_start(pcm_stream_handler_t hdl)
137 {
138     int ret = 0;
139     if(NULL == hdl) {
140         LOGE(LOG_TAG, "%s:%d, invalid hdl.", __func__, __LINE__);
141         return ret;
142     }
143 
144     if(hdl == capture_stream_hdl) {
145         rl6548_capture_start();
146         LOGD(LOG_TAG, "rx codec_pcm_stream_start");
147     } else if (hdl == playback_stream_hdl) {
148         rl6548_playback_start();
149         LOGD(LOG_TAG, "tx codec_pcm_stream_start");
150     }
151 
152     // LOGD(LOG_TAG, "%s:%d, ret = %d.", __func__, __LINE__, ret);
153     return ret;
154 }
155 
codec_pcm_stream_write(pcm_stream_handler_t hdl,void * buf,unsigned int len)156 static int codec_pcm_stream_write(pcm_stream_handler_t hdl, void *buf, unsigned int len)
157 {
158     int ret = -1;
159     if(NULL == hdl) {
160         LOGE(LOG_TAG, "%s:%d, invalid hdl.", __func__, __LINE__);
161         return ret;
162     }
163     if(hdl == capture_stream_hdl) {
164         LOGE(LOG_TAG, "%s:%d, write operation not allowed on capture stream.", __func__, __LINE__);
165     } else
166         if (hdl == playback_stream_hdl) {
167             ret = rl6548_audio_write(playback_stream_hdl, (uint8_t *)buf, len);
168         }
169     return ret;
170 }
171 
codec_pcm_stream_read(pcm_stream_handler_t hdl,void * buf,unsigned int len)172 static int codec_pcm_stream_read(pcm_stream_handler_t hdl, void *buf, unsigned int len)
173 {
174     int ret = -1, i = 0, j = 0;
175     int channel_num = 3, sample_bytes = 2, frame_size;
176     char *tempBuf = NULL;
177     if(NULL == hdl) {
178         LOGE(LOG_TAG, "%s:%d, invalid hdl.", __func__, __LINE__);
179         return ret;
180     }
181     if(hdl == playback_stream_hdl) {
182         LOGE(LOG_TAG, "%s:%d, read operation not allowed on playback stream.", __func__, __LINE__);
183     } else
184         if (hdl == capture_stream_hdl) {
185             // TBD: read capture stream, get last channel data
186             frame_size = channel_num * sample_bytes;
187             ret = rl6548_data_read(hdl, buf, len);
188             LOGD(LOG_TAG, "%s:%d, data_dump_read %d bytes", __func__, __LINE__, ret);
189         }
190     return ret;
191 }
192 
codec_pcm_stream_pause(pcm_stream_handler_t hdl,int enable)193 static int codec_pcm_stream_pause(pcm_stream_handler_t hdl, int enable)
194 {
195     int ret = -1;
196     if(NULL == hdl) {
197         LOGE(LOG_TAG, "%s:%d, invalid hdl.", __func__, __LINE__);
198         return ret;
199     }
200     if(hdl == playback_stream_hdl) {
201         // TBD: pause playback stream
202     } else if (hdl == capture_stream_hdl) {
203         // TBD: pause capture stream
204     }
205     LOGD(LOG_TAG, "%s:%d, ret = %d.", __func__, __LINE__, ret);
206     return ret;
207 }
208 
codec_pcm_stream_suspend(pcm_stream_handler_t hdl)209 static int codec_pcm_stream_suspend(pcm_stream_handler_t hdl)
210 {
211     int ret = 0;
212     if(hdl == &playback_stream_hdl) {
213         // TBD: put playback stream into lowpower/suspend mode
214     } else if (hdl == &capture_stream_hdl) {
215         // TBD: put capture stream into lowpower/suspend mode
216     }
217     return ret;
218 }
219 
codec_pcm_stream_resume(pcm_stream_handler_t hdl)220 static int codec_pcm_stream_resume(pcm_stream_handler_t hdl)
221 {
222     int ret = 0;
223     if(hdl == &playback_stream_hdl) {
224         // TBD: put playback stream into active mode
225     } else if (hdl == &capture_stream_hdl) {
226         // TBD: put playback stream into active mode
227     }
228     return ret;
229 }
230 
codec_pcm_stream_stop(pcm_stream_handler_t hdl)231 static int codec_pcm_stream_stop(pcm_stream_handler_t hdl)
232 {
233     int ret = 0;
234     if(NULL == hdl) {
235         LOGE(LOG_TAG, "%s:%d, invalid hdl.", __func__, __LINE__);
236         return ret;
237     }
238     if(hdl == capture_stream_hdl) {
239         rl6548_capture_stop();
240     } else if (hdl == playback_stream_hdl) {
241         rl6548_playback_stop();
242     }
243     // LOGD(LOG_TAG, "%s:%d, ret = %d.", __func__, __LINE__, ret);
244     LOGD(LOG_TAG, "codec_pcm_stream_stop");
245     return ret;
246 }
247 
codec_pcm_stream_close(pcm_stream_handler_t hdl)248 static int codec_pcm_stream_close(pcm_stream_handler_t hdl)
249 {
250     int ret = 0;
251     if(NULL == hdl) {
252         LOGE(LOG_TAG, "%s:%d, invalid hdl.", __func__, __LINE__);
253         return ret;
254     }
255 
256     if(audio_stream_hdl == NULL) {
257         playback_stream_hdl = capture_stream_hdl = NULL;
258         return ret;
259     }
260 
261     if(hdl == capture_stream_hdl) {
262         rl6548_audio_deinit();
263         capture_stream_hdl = audio_stream_hdl = NULL;
264     } else if (hdl == playback_stream_hdl) {
265         rl6548_audio_deinit();
266         playback_stream_hdl = audio_stream_hdl = NULL;
267     }
268     LOGD(LOG_TAG, "%s:%d, ret = %d.", __func__, __LINE__, ret);
269     return ret;
270 }
271 
codec_pcm_stream_recover(pcm_stream_handler_t hdl)272 static int codec_pcm_stream_recover(pcm_stream_handler_t hdl)
273 {
274     int ret = -1;
275     if(NULL == hdl) {
276         LOGE(LOG_TAG, "%s:%d, invalid hdl.", __func__, __LINE__);
277         return ret;
278     }
279     if(hdl == capture_stream_hdl) {
280         // TBD: recover capture stream
281     } else if (hdl == playback_stream_hdl) {
282         // TBD: recover playback stream
283     }
284     LOGD(LOG_TAG, "%s:%d, ret = %d.", __func__, __LINE__, ret);
285     return ret;
286 }
287 
288 pcm_stream_ops_t codec_pcm_ops = {
289     .open = codec_pcm_stream_open,
290     .start = codec_pcm_stream_start,
291     .read = codec_pcm_stream_read,
292     .write = codec_pcm_stream_write,
293     // .pause = codec_pcm_stream_pause,
294     .stop = codec_pcm_stream_stop,
295     .close = codec_pcm_stream_close,
296     // .recover = codec_pcm_stream_recover,
297     // .suspend = codec_pcm_stream_suspend,
298     // .resume = codec_pcm_stream_resume,
299 };
300 
301 /* Application shall call this API to install codec driver instance. */
audio_install_codec_driver()302 int audio_install_codec_driver()
303 {
304     int pb_stream_num = 1;
305     int cap_stream_num = 1;
306     LOGD(LOG_TAG, "%s:%d, install RTOS codec driver %d Capture %d Playback", __func__, __LINE__, cap_stream_num, pb_stream_num);
307     return audio_native_card_register(cap_stream_num, pb_stream_num, &codec_pcm_ops, master_codec_controls, sizeof(master_codec_controls)/sizeof(master_codec_controls[0]));
308 }
309 //FINSH_FUNCTION_EXPORT_CMD(audio_install_codec_driver, insmod_audio_drv,  RTOS Codec Driver Test)