blob: 3656b409398150efec72e582918a155d95a4e04c [file] [log] [blame]
Fei Tongaffdf732020-02-20 20:39:05 +08001/* synth.c
2Copyright (c) 2012-2015,2016,2020 The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10 copyright notice, this list of conditions and the following
11 disclaimer in the documentation and/or other materials provided
12 with the distribution.
13 * Neither the name of The Linux Foundation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
28
29#define LOG_TAG "audio_hw_synth"
30/*#define LOG_NDEBUG 0*/
31#define LOG_NDDEBUG 0
32
33#include <errno.h>
34#include <math.h>
35#include <log/log.h>
36#include <unistd.h>
37
38#include "audio_hw.h"
39#include "platform.h"
40#include "platform_api.h"
41#include <stdlib.h>
42#include <cutils/str_parms.h>
43#include <audio_extn.h>
44
45#ifdef DYNAMIC_LOG_ENABLED
46#include <log_xml_parser.h>
47#define LOG_MASK HAL_MOD_FILE_FM
48#include <log_utils.h>
49#endif
50
51#define AUDIO_PARAMETER_KEY_SYNTH_ENABLE "synth_enable"
52
53static int32_t synth_start(struct audio_device *adev);
54static int32_t synth_stop(struct audio_device *adev);
55
56static struct pcm_config pcm_config_synth = {
57 .channels = 4,
58 .rate = 16000,
59 .period_size = 240,
60 .period_count = 2,
61 .format = PCM_FORMAT_S16_LE,
62 .start_threshold = 0,
63 .stop_threshold = INT_MAX,
64 .avail_min = 0,
65};
66
67struct synth_module {
68 struct pcm *pcm_rx;
69 struct pcm *pcm_tx;
70 bool is_synth_running;
71 audio_usecase_t ucid;
72};
73
74static struct synth_module synthmod = {
75 .pcm_rx = NULL,
76 .pcm_tx = NULL,
77 .is_synth_running = 0,
78 .ucid = USECASE_AUDIO_PLAYBACK_SYNTHESIZER,
79};
80
81static fp_platform_get_pcm_device_id_t fp_platform_get_pcm_device_id;
82static fp_get_usecase_from_list_t fp_get_usecase_from_list;
83static fp_select_devices_t fp_select_devices;
84static fp_platform_get_pcm_device_id_t fp_platform_get_pcm_device_id;
85static fp_platform_send_audio_calibration_t fp_platform_send_audio_calibration;
86static fp_disable_audio_route_t fp_disable_audio_route;
87static fp_disable_snd_device_t fp_disable_snd_device;
88
89
90int32_t synth_start(struct audio_device *adev)
91{
92 int32_t ret = 0;
93 int pcm_dev_rx = -1, pcm_dev_tx = -1;
94 char mixer_path[MIXER_PATH_MAX_LENGTH];
95 struct audio_usecase *uc_info = NULL;
96
97 ALOGD("%s: Enable Synth", __func__);
98
99 // select devices
100 uc_info = (struct audio_usecase *)calloc(1, sizeof(*uc_info));
101 if (!uc_info) {
102 ALOGE("%s: allocate memory failed", __func__);
103 return -ENOMEM;
104 }
105
106 uc_info->id = synthmod.ucid;
107 uc_info->type = SYNTH_LOOPBACK;
108 uc_info->stream.out = adev->primary_output;
109 list_init(&uc_info->device_list);
110 assign_devices(&uc_info->device_list, &adev->primary_output->device_list);
111 uc_info->in_snd_device = SND_DEVICE_NONE;
112 uc_info->out_snd_device = SND_DEVICE_OUT_SPEAKER;
113
114 list_add_tail(&adev->usecase_list, &uc_info->list);
115
116 fp_select_devices(adev, synthmod.ucid);
117
118 // open pcm rx/tx
119 pcm_dev_tx = fp_platform_get_pcm_device_id(USECASE_AUDIO_PLAYBACK_SYNTHESIZER, PCM_CAPTURE);
120 pcm_dev_rx = fp_platform_get_pcm_device_id(USECASE_AUDIO_PLAYBACK_SYNTHESIZER, PCM_PLAYBACK);
121
122 if (pcm_dev_tx < 0 || pcm_dev_rx < 0 ) {
123 ALOGE("%s: Invalid PCM devices (rx: %d tx: %d) for the usecase(%d)",
124 __func__, pcm_dev_rx, pcm_dev_tx, uc_info->id);
125 ret = -EIO;
126 goto exit;
127 }
128
129 //open pcm rx/tx
130 synthmod.pcm_tx = pcm_open(adev->snd_card,
131 pcm_dev_tx,
132 PCM_IN, &pcm_config_synth);
133 if (synthmod.pcm_tx &&
134 !pcm_is_ready(synthmod.pcm_tx)) {
135 ALOGE("%s: pcm_tx %s", __func__,
136 pcm_get_error(synthmod.pcm_tx));
137 ret = -EIO;
138 goto exit;
139 }
140 synthmod.pcm_rx = pcm_open(adev->snd_card,
141 pcm_dev_rx,
142 PCM_OUT, &pcm_config_synth);
143 if (synthmod.pcm_rx &&
144 !pcm_is_ready(synthmod.pcm_rx)) {
145 ALOGE("%s: pcm_rx %s", __func__,
146 pcm_get_error(synthmod.pcm_rx));
147 ret = -EIO;
148 goto exit;
149 }
150
151 if (pcm_start(synthmod.pcm_tx) < 0) {
152 ALOGE("%s: pcm start for pcm tx failed", __func__);
153 ret = -EIO;
154 goto exit;
155 }
156 if (pcm_start(synthmod.pcm_rx) < 0) {
157 ALOGE("%s: pcm start for pcm rx failed", __func__);
158 ret = -EIO;
159 goto exit;
160 }
161
162 synthmod.is_synth_running = true;
163 return ret;
164
165exit:
166 synth_stop(adev);
167 ALOGE("%s: Problem in Synth start: status(%d)", __func__, ret);
168 return ret;
169}
170
171int32_t synth_stop(struct audio_device *adev)
172{
173 int32_t ret = 0;
174 struct audio_usecase *uc_info;
175
176 ALOGD("Enter %s:", __func__);
177 synthmod.is_synth_running = false;
178
179 if (synthmod.pcm_tx) {
180 pcm_close(synthmod.pcm_tx);
181 synthmod.pcm_tx = NULL;
182 }
183
184 if (synthmod.pcm_rx) {
185 pcm_close(synthmod.pcm_rx);
186 synthmod.pcm_rx = NULL;
187 }
188
189 uc_info = fp_get_usecase_from_list(adev, synthmod.ucid);
190 if (uc_info == NULL) {
191 ALOGE("%s: Could not find the usecase (%d) in the list",
192 __func__, synthmod.ucid);
193 return -EINVAL;
194 }
195
196 /* 3. Get and set stream specific mixer controls */
197 fp_disable_audio_route(adev, uc_info);
198
199 /* 4. Disable the rx and tx devices */
200 fp_disable_snd_device(adev, uc_info->out_snd_device);
201 fp_disable_snd_device(adev, uc_info->in_snd_device);
202
203 list_remove(&uc_info->list);
204 free(uc_info);
205
206 ALOGD("%s: exit: status(%d)", __func__, ret);
207 return ret;
208}
209
210bool synth_is_active(struct audio_device *adev) {
211 struct audio_usecase *synth_usecase = NULL;
212 synth_usecase = fp_get_usecase_from_list(adev, synthmod.ucid);
213 if (synth_usecase != NULL)
214 return true;
215 else
216 return false;
217}
218
219void synth_set_parameters(struct audio_device *adev,
220 struct str_parms *parms)
221{
222 int ret, val;
223 char value[32]={0};
224
225 ALOGD("%s: enter", __func__);
226 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SYNTH_ENABLE, value, sizeof(value));
227 if (ret >= 0) {
228 if (!strncmp(value,"true",sizeof(value)) && !synthmod.is_synth_running) {
229 synth_start(adev);
230 }
231 else if (!strncmp(value,"false",sizeof(value)) && synthmod.is_synth_running) {
232 synth_stop(adev);
233 } else {
234 ALOGE("Not support key value");
235 }
236 }
237
238 ALOGD("%s: exit", __func__);
239}
240
241void synth_init(synth_init_config_t init_config)
242{
243 fp_platform_get_pcm_device_id = init_config.fp_platform_get_pcm_device_id;
244 fp_get_usecase_from_list = init_config.fp_get_usecase_from_list;
245 fp_select_devices = init_config.fp_select_devices;
246 fp_disable_audio_route = init_config.fp_disable_audio_route;
247 fp_disable_snd_device = init_config.fp_disable_snd_device;
248}
249