blob: cafe0d8bebe3afbda97cd8e3a3e7736507f57c21 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
18/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080019#define LOG_NDDEBUG 0
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080020
21#include <errno.h>
22#include <pthread.h>
23#include <stdint.h>
24#include <sys/time.h>
25#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026#include <math.h>
27
28#include <cutils/log.h>
29#include <cutils/str_parms.h>
30#include <cutils/properties.h>
31
Eric Laurentb23d5282013-05-14 15:27:20 -070032#include <hardware/audio_effect.h>
33#include <audio_effects/effect_aec.h>
34#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080035#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070036#include "platform_api.h"
37#include <platform.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080038
Eric Laurentb23d5282013-05-14 15:27:20 -070039struct pcm_config pcm_config_deep_buffer = {
40 .channels = 2,
41 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
42 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
43 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
44 .format = PCM_FORMAT_S16_LE,
45 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
46 .stop_threshold = INT_MAX,
47 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
48};
49
50struct pcm_config pcm_config_low_latency = {
51 .channels = 2,
52 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
53 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
54 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
55 .format = PCM_FORMAT_S16_LE,
56 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
57 .stop_threshold = INT_MAX,
58 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
59};
60
61struct pcm_config pcm_config_hdmi_multi = {
62 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
63 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
64 .period_size = HDMI_MULTI_PERIOD_SIZE,
65 .period_count = HDMI_MULTI_PERIOD_COUNT,
66 .format = PCM_FORMAT_S16_LE,
67 .start_threshold = 0,
68 .stop_threshold = INT_MAX,
69 .avail_min = 0,
70};
71
72struct pcm_config pcm_config_audio_capture = {
73 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -070074 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
75 .format = PCM_FORMAT_S16_LE,
76};
77
78struct pcm_config pcm_config_voice_call = {
79 .channels = 1,
80 .rate = 8000,
81 .period_size = 160,
82 .period_count = 2,
83 .format = PCM_FORMAT_S16_LE,
84};
85
86static const char * const use_case_table[AUDIO_USECASE_MAX] = {
87 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
88 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
89 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
90 [USECASE_AUDIO_RECORD] = "audio-record",
91 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
92 [USECASE_VOICE_CALL] = "voice-call",
93};
94
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080095
96#define STRING_TO_ENUM(string) { #string, string }
97
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080098struct string_to_enum {
99 const char *name;
100 uint32_t value;
101};
102
103static const struct string_to_enum out_channels_name_to_enum_table[] = {
104 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
105 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
106 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
107};
108
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800109
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700110static int enable_audio_route(struct audio_device *adev,
111 struct audio_usecase *usecase,
112 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800113{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700114 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800115 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800116
117 if (usecase == NULL)
118 return -EINVAL;
119
120 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
121
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800122 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700123 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800124 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700125 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800126
127 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700128 platform_add_backend_name(mixer_path, snd_device);
Eric Laurent994a6932013-07-17 11:51:42 -0700129 ALOGV("%s: apply mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700130 audio_route_apply_path(adev->audio_route, mixer_path);
131 if (update_mixer)
132 audio_route_update_mixer(adev->audio_route);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800134 ALOGV("%s: exit", __func__);
135 return 0;
136}
137
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700138static int disable_audio_route(struct audio_device *adev,
139 struct audio_usecase *usecase,
140 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800141{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700142 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800143 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800144
145 if (usecase == NULL)
146 return -EINVAL;
147
148 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700149 if (usecase->type == PCM_CAPTURE)
150 snd_device = usecase->in_snd_device;
151 else
152 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800153 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700154 platform_add_backend_name(mixer_path, snd_device);
Eric Laurent994a6932013-07-17 11:51:42 -0700155 ALOGV("%s: reset mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700156 audio_route_reset_path(adev->audio_route, mixer_path);
157 if (update_mixer)
158 audio_route_update_mixer(adev->audio_route);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800159
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800160 ALOGV("%s: exit", __func__);
161 return 0;
162}
163
164static int enable_snd_device(struct audio_device *adev,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700165 snd_device_t snd_device,
166 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800167{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800168 if (snd_device < SND_DEVICE_MIN ||
169 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800170 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800171 return -EINVAL;
172 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700173
174 adev->snd_dev_ref_cnt[snd_device]++;
175 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700176 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700177 __func__, snd_device, platform_get_snd_device_name(snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700178 return 0;
179 }
180
Eric Laurentb23d5282013-05-14 15:27:20 -0700181 if (platform_send_audio_calibration(adev->platform, snd_device) < 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700182 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800183 return -EINVAL;
184 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800185
Eric Laurent994a6932013-07-17 11:51:42 -0700186 ALOGV("%s: snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700187 snd_device, platform_get_snd_device_name(snd_device));
188 audio_route_apply_path(adev->audio_route, platform_get_snd_device_name(snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700189 if (update_mixer)
190 audio_route_update_mixer(adev->audio_route);
191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800192 return 0;
193}
194
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700195static int disable_snd_device(struct audio_device *adev,
196 snd_device_t snd_device,
197 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800198{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800199 if (snd_device < SND_DEVICE_MIN ||
200 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800201 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800202 return -EINVAL;
203 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700204 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
205 ALOGE("%s: device ref cnt is already 0", __func__);
206 return -EINVAL;
207 }
208 adev->snd_dev_ref_cnt[snd_device]--;
209 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700210 ALOGV("%s: snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700211 snd_device, platform_get_snd_device_name(snd_device));
212 audio_route_reset_path(adev->audio_route, platform_get_snd_device_name(snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700213 if (update_mixer)
214 audio_route_update_mixer(adev->audio_route);
215 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800216 return 0;
217}
218
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700219static void check_usecases_codec_backend(struct audio_device *adev,
220 struct audio_usecase *uc_info,
221 snd_device_t snd_device)
222{
223 struct listnode *node;
224 struct audio_usecase *usecase;
225 bool switch_device[AUDIO_USECASE_MAX];
226 int i, num_uc_to_switch = 0;
227
228 /*
229 * This function is to make sure that all the usecases that are active on
230 * the hardware codec backend are always routed to any one device that is
231 * handled by the hardware codec.
232 * For example, if low-latency and deep-buffer usecases are currently active
233 * on speaker and out_set_parameters(headset) is received on low-latency
234 * output, then we have to make sure deep-buffer is also switched to headset,
235 * because of the limitation that both the devices cannot be enabled
236 * at the same time as they share the same backend.
237 */
238 /* Disable all the usecases on the shared backend other than the
239 specified usecase */
240 for (i = 0; i < AUDIO_USECASE_MAX; i++)
241 switch_device[i] = false;
242
243 list_for_each(node, &adev->usecase_list) {
244 usecase = node_to_item(node, struct audio_usecase, list);
245 if (usecase->type != PCM_CAPTURE &&
246 usecase != uc_info &&
247 usecase->out_snd_device != snd_device &&
248 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
249 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
250 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700251 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700252 disable_audio_route(adev, usecase, false);
253 switch_device[usecase->id] = true;
254 num_uc_to_switch++;
255 }
256 }
257
258 if (num_uc_to_switch) {
259 /* Make sure all the streams are de-routed before disabling the device */
260 audio_route_update_mixer(adev->audio_route);
261
262 list_for_each(node, &adev->usecase_list) {
263 usecase = node_to_item(node, struct audio_usecase, list);
264 if (switch_device[usecase->id]) {
265 disable_snd_device(adev, usecase->out_snd_device, false);
266 enable_snd_device(adev, snd_device, false);
267 }
268 }
269
270 /* Make sure new snd device is enabled before re-routing the streams */
271 audio_route_update_mixer(adev->audio_route);
272
273 /* Re-route all the usecases on the shared backend other than the
274 specified usecase to new snd devices */
275 list_for_each(node, &adev->usecase_list) {
276 usecase = node_to_item(node, struct audio_usecase, list);
277 /* Update the out_snd_device only before enabling the audio route */
278 if (switch_device[usecase->id] ) {
279 usecase->out_snd_device = snd_device;
280 enable_audio_route(adev, usecase, false);
281 }
282 }
283
284 audio_route_update_mixer(adev->audio_route);
285 }
286}
287
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700288static void check_and_route_capture_usecases(struct audio_device *adev,
289 struct audio_usecase *uc_info,
290 snd_device_t snd_device)
291{
292 struct listnode *node;
293 struct audio_usecase *usecase;
294 bool switch_device[AUDIO_USECASE_MAX];
295 int i, num_uc_to_switch = 0;
296
297 /*
298 * This function is to make sure that all the active capture usecases
299 * are always routed to the same input sound device.
300 * For example, if audio-record and voice-call usecases are currently
301 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
302 * is received for voice call then we have to make sure that audio-record
303 * usecase is also switched to earpiece i.e. voice-dmic-ef,
304 * because of the limitation that two devices cannot be enabled
305 * at the same time if they share the same backend.
306 */
307 for (i = 0; i < AUDIO_USECASE_MAX; i++)
308 switch_device[i] = false;
309
310 list_for_each(node, &adev->usecase_list) {
311 usecase = node_to_item(node, struct audio_usecase, list);
312 if (usecase->type != PCM_PLAYBACK &&
313 usecase != uc_info &&
314 usecase->in_snd_device != snd_device) {
315 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
316 __func__, use_case_table[usecase->id],
317 device_table[usecase->in_snd_device]);
318 disable_audio_route(adev, usecase, false);
319 switch_device[usecase->id] = true;
320 num_uc_to_switch++;
321 }
322 }
323
324 if (num_uc_to_switch) {
325 /* Make sure all the streams are de-routed before disabling the device */
326 audio_route_update_mixer(adev->audio_route);
327
328 list_for_each(node, &adev->usecase_list) {
329 usecase = node_to_item(node, struct audio_usecase, list);
330 if (switch_device[usecase->id]) {
331 disable_snd_device(adev, usecase->in_snd_device, false);
332 enable_snd_device(adev, snd_device, false);
333 }
334 }
335
336 /* Make sure new snd device is enabled before re-routing the streams */
337 audio_route_update_mixer(adev->audio_route);
338
339 /* Re-route all the usecases on the shared backend other than the
340 specified usecase to new snd devices */
341 list_for_each(node, &adev->usecase_list) {
342 usecase = node_to_item(node, struct audio_usecase, list);
343 /* Update the in_snd_device only before enabling the audio route */
344 if (switch_device[usecase->id] ) {
345 usecase->in_snd_device = snd_device;
346 enable_audio_route(adev, usecase, false);
347 }
348 }
349
350 audio_route_update_mixer(adev->audio_route);
351 }
352}
353
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800354
355/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700356static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800357{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700358 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700359 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800360
361 switch (channels) {
362 /*
363 * Do not handle stereo output in Multi-channel cases
364 * Stereo case is handled in normal playback path
365 */
366 case 6:
367 ALOGV("%s: HDMI supports 5.1", __func__);
368 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
369 break;
370 case 8:
371 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
372 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
373 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
374 break;
375 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700376 ALOGE("HDMI does not support multi channel playback");
377 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800378 break;
379 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700380 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800381}
382
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700383static struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
384 audio_usecase_t uc_id)
385{
386 struct audio_usecase *usecase;
387 struct listnode *node;
388
389 list_for_each(node, &adev->usecase_list) {
390 usecase = node_to_item(node, struct audio_usecase, list);
391 if (usecase->id == uc_id)
392 return usecase;
393 }
394 return NULL;
395}
396
397static int select_devices(struct audio_device *adev,
398 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800399{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800400 snd_device_t out_snd_device = SND_DEVICE_NONE;
401 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700402 struct audio_usecase *usecase = NULL;
403 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800404 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700405 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800406
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700407 usecase = get_usecase_from_list(adev, uc_id);
408 if (usecase == NULL) {
409 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
410 return -EINVAL;
411 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800412
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700413 if (usecase->type == VOICE_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700414 out_snd_device = platform_get_output_snd_device(adev->platform,
415 usecase->stream.out->devices);
416 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700417 usecase->devices = usecase->stream.out->devices;
418 } else {
419 /*
420 * If the voice call is active, use the sound devices of voice call usecase
421 * so that it would not result any device switch. All the usecases will
422 * be switched to new device when select_devices() is called for voice call
423 * usecase. This is to avoid switching devices for voice call when
424 * check_usecases_codec_backend() is called below.
425 */
426 if (adev->in_call) {
427 vc_usecase = get_usecase_from_list(adev, USECASE_VOICE_CALL);
428 if (vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
429 in_snd_device = vc_usecase->in_snd_device;
430 out_snd_device = vc_usecase->out_snd_device;
431 }
432 }
433 if (usecase->type == PCM_PLAYBACK) {
434 usecase->devices = usecase->stream.out->devices;
435 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700436 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700437 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700438 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700439 if (usecase->stream.out == adev->primary_output &&
440 adev->active_input &&
441 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
442 select_devices(adev, adev->active_input->usecase);
443 }
444 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700445 } else if (usecase->type == PCM_CAPTURE) {
446 usecase->devices = usecase->stream.in->device;
447 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700448 if (in_snd_device == SND_DEVICE_NONE) {
449 if (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
450 adev->primary_output && !adev->primary_output->standby) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700451 in_snd_device = platform_get_input_snd_device(adev->platform,
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700452 adev->primary_output->devices);
453 } else {
Eric Laurentb23d5282013-05-14 15:27:20 -0700454 in_snd_device = platform_get_input_snd_device(adev->platform,
455 AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700456 }
457 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700458 }
459 }
460
461 if (out_snd_device == usecase->out_snd_device &&
462 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800463 return 0;
464 }
465
sangwoobc677242013-08-08 16:53:43 +0900466 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700467 out_snd_device, platform_get_snd_device_name(out_snd_device),
468 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800469
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800470 /*
471 * Limitation: While in call, to do a device switch we need to disable
472 * and enable both RX and TX devices though one of them is same as current
473 * device.
474 */
Eric Laurentb23d5282013-05-14 15:27:20 -0700475 if (usecase->type == VOICE_CALL) {
476 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800477 }
478
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700479 /* Disable current sound devices */
480 if (usecase->out_snd_device != SND_DEVICE_NONE) {
481 disable_audio_route(adev, usecase, true);
482 disable_snd_device(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800483 }
484
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700485 if (usecase->in_snd_device != SND_DEVICE_NONE) {
486 disable_audio_route(adev, usecase, true);
487 disable_snd_device(adev, usecase->in_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800488 }
489
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700490 /* Enable new sound devices */
491 if (out_snd_device != SND_DEVICE_NONE) {
492 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
493 check_usecases_codec_backend(adev, usecase, out_snd_device);
494 enable_snd_device(adev, out_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800495 }
496
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700497 if (in_snd_device != SND_DEVICE_NONE) {
498 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700499 enable_snd_device(adev, in_snd_device, false);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700500 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700501
Eric Laurentb23d5282013-05-14 15:27:20 -0700502 if (usecase->type == VOICE_CALL)
503 status = platform_switch_voice_call_device_post(adev->platform,
504 out_snd_device,
505 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800506
sangwoo170731f2013-06-08 15:36:36 +0900507 audio_route_update_mixer(adev->audio_route);
508
509 usecase->in_snd_device = in_snd_device;
510 usecase->out_snd_device = out_snd_device;
511
512 enable_audio_route(adev, usecase, true);
513
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800514 return status;
515}
516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800517static int stop_input_stream(struct stream_in *in)
518{
519 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800520 struct audio_usecase *uc_info;
521 struct audio_device *adev = in->dev;
522
Eric Laurentc8400632013-02-14 19:04:54 -0800523 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800524
Eric Laurent994a6932013-07-17 11:51:42 -0700525 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700526 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800527 uc_info = get_usecase_from_list(adev, in->usecase);
528 if (uc_info == NULL) {
529 ALOGE("%s: Could not find the usecase (%d) in the list",
530 __func__, in->usecase);
531 return -EINVAL;
532 }
533
Eric Laurent150dbfe2013-02-27 14:31:02 -0800534 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700535 disable_audio_route(adev, uc_info, true);
536
537 /* 2. Disable the tx device */
538 disable_snd_device(adev, uc_info->in_snd_device, true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800539
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800540 list_remove(&uc_info->list);
541 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800542
Eric Laurent994a6932013-07-17 11:51:42 -0700543 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800544 return ret;
545}
546
547int start_input_stream(struct stream_in *in)
548{
549 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800550 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800551 struct audio_usecase *uc_info;
552 struct audio_device *adev = in->dev;
553
Eric Laurent994a6932013-07-17 11:51:42 -0700554 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Eric Laurentb23d5282013-05-14 15:27:20 -0700555 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800556 if (in->pcm_device_id < 0) {
557 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
558 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -0800559 ret = -EINVAL;
560 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800561 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700562
563 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800564 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
565 uc_info->id = in->usecase;
566 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800567 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700568 uc_info->devices = in->device;
569 uc_info->in_snd_device = SND_DEVICE_NONE;
570 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800571
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800572 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700573 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800574
Eric Laurentc8400632013-02-14 19:04:54 -0800575 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
576 __func__, SOUND_CARD, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800577 in->pcm = pcm_open(SOUND_CARD, in->pcm_device_id,
578 PCM_IN, &in->config);
579 if (in->pcm && !pcm_is_ready(in->pcm)) {
580 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
581 pcm_close(in->pcm);
582 in->pcm = NULL;
Eric Laurentc8400632013-02-14 19:04:54 -0800583 ret = -EIO;
584 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800585 }
Eric Laurent994a6932013-07-17 11:51:42 -0700586 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -0800587 return ret;
588
589error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800590 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -0800591
592error_config:
593 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700594 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -0800595
596 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800597}
598
599static int stop_output_stream(struct stream_out *out)
600{
601 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800602 struct audio_usecase *uc_info;
603 struct audio_device *adev = out->dev;
604
Eric Laurent994a6932013-07-17 11:51:42 -0700605 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700606 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800607 uc_info = get_usecase_from_list(adev, out->usecase);
608 if (uc_info == NULL) {
609 ALOGE("%s: Could not find the usecase (%d) in the list",
610 __func__, out->usecase);
611 return -EINVAL;
612 }
613
Eric Laurent150dbfe2013-02-27 14:31:02 -0800614 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700615 disable_audio_route(adev, uc_info, true);
616
617 /* 2. Disable the rx device */
618 disable_snd_device(adev, uc_info->out_snd_device, true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800619
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800620 list_remove(&uc_info->list);
621 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800622
Eric Laurent994a6932013-07-17 11:51:42 -0700623 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800624 return ret;
625}
626
627int start_output_stream(struct stream_out *out)
628{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800629 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800630 struct audio_usecase *uc_info;
631 struct audio_device *adev = out->dev;
632
Eric Laurent994a6932013-07-17 11:51:42 -0700633 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700634 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Eric Laurentb23d5282013-05-14 15:27:20 -0700635 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800636 if (out->pcm_device_id < 0) {
637 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
638 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800639 ret = -EINVAL;
640 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800641 }
642
643 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
644 uc_info->id = out->usecase;
645 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800646 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700647 uc_info->devices = out->devices;
648 uc_info->in_snd_device = SND_DEVICE_NONE;
649 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800650
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800651 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800652
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700653 select_devices(adev, out->usecase);
654
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800655 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
656 __func__, 0, out->pcm_device_id);
657 out->pcm = pcm_open(SOUND_CARD, out->pcm_device_id,
658 PCM_OUT, &out->config);
659 if (out->pcm && !pcm_is_ready(out->pcm)) {
660 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
661 pcm_close(out->pcm);
662 out->pcm = NULL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800663 ret = -EIO;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700664 goto error_pcm_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800665 }
Eric Laurent994a6932013-07-17 11:51:42 -0700666 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800667 return 0;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700668error_pcm_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800669 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800670error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800671 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800672}
673
674static int stop_voice_call(struct audio_device *adev)
675{
676 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800677 struct audio_usecase *uc_info;
678
Eric Laurent994a6932013-07-17 11:51:42 -0700679 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -0800680 adev->in_call = false;
Eric Laurentb23d5282013-05-14 15:27:20 -0700681
682 ret = platform_stop_voice_call(adev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800683
684 /* 1. Close the PCM devices */
685 if (adev->voice_call_rx) {
686 pcm_close(adev->voice_call_rx);
687 adev->voice_call_rx = NULL;
688 }
689 if (adev->voice_call_tx) {
690 pcm_close(adev->voice_call_tx);
691 adev->voice_call_tx = NULL;
692 }
693
694 uc_info = get_usecase_from_list(adev, USECASE_VOICE_CALL);
695 if (uc_info == NULL) {
696 ALOGE("%s: Could not find the usecase (%d) in the list",
697 __func__, USECASE_VOICE_CALL);
698 return -EINVAL;
699 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800700
701 /* 2. Get and set stream specific mixer controls */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700702 disable_audio_route(adev, uc_info, true);
703
704 /* 3. Disable the rx and tx devices */
705 disable_snd_device(adev, uc_info->out_snd_device, false);
706 disable_snd_device(adev, uc_info->in_snd_device, true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800707
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800708 list_remove(&uc_info->list);
709 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800710
Eric Laurent994a6932013-07-17 11:51:42 -0700711 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800712 return ret;
713}
714
715static int start_voice_call(struct audio_device *adev)
716{
717 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800718 struct audio_usecase *uc_info;
719 int pcm_dev_rx_id, pcm_dev_tx_id;
720
Eric Laurent994a6932013-07-17 11:51:42 -0700721 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722
723 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
724 uc_info->id = USECASE_VOICE_CALL;
725 uc_info->type = VOICE_CALL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800726 uc_info->stream.out = adev->primary_output;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700727 uc_info->devices = adev->primary_output->devices;
728 uc_info->in_snd_device = SND_DEVICE_NONE;
729 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800730
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800731 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800732
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700733 select_devices(adev, USECASE_VOICE_CALL);
734
Eric Laurentb23d5282013-05-14 15:27:20 -0700735 pcm_dev_rx_id = platform_get_pcm_device_id(uc_info->id, PCM_PLAYBACK);
736 pcm_dev_tx_id = platform_get_pcm_device_id(uc_info->id, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800737
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800738 if (pcm_dev_rx_id < 0 || pcm_dev_tx_id < 0) {
739 ALOGE("%s: Invalid PCM devices (rx: %d tx: %d) for the usecase(%d)",
740 __func__, pcm_dev_rx_id, pcm_dev_tx_id, uc_info->id);
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -0800741 ret = -EIO;
742 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800743 }
744
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -0800745 ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800746 __func__, SOUND_CARD, pcm_dev_rx_id);
747 adev->voice_call_rx = pcm_open(SOUND_CARD,
748 pcm_dev_rx_id,
749 PCM_OUT, &pcm_config_voice_call);
750 if (adev->voice_call_rx && !pcm_is_ready(adev->voice_call_rx)) {
751 ALOGE("%s: %s", __func__, pcm_get_error(adev->voice_call_rx));
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -0800752 ret = -EIO;
753 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800754 }
755
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -0800756 ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800757 __func__, SOUND_CARD, pcm_dev_tx_id);
758 adev->voice_call_tx = pcm_open(SOUND_CARD,
759 pcm_dev_tx_id,
760 PCM_IN, &pcm_config_voice_call);
761 if (adev->voice_call_tx && !pcm_is_ready(adev->voice_call_tx)) {
762 ALOGE("%s: %s", __func__, pcm_get_error(adev->voice_call_tx));
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -0800763 ret = -EIO;
764 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800765 }
766 pcm_start(adev->voice_call_rx);
767 pcm_start(adev->voice_call_tx);
768
Eric Laurentb23d5282013-05-14 15:27:20 -0700769 ret = platform_start_voice_call(adev->platform);
770 if (ret < 0) {
771 ALOGE("%s: platform_start_voice_call error %d\n", __func__, ret);
772 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800773 }
774
775 adev->in_call = true;
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -0800776 return 0;
777
778error_start_voice:
779 stop_voice_call(adev);
780
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800781 ALOGD("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800782 return ret;
783}
784
785static int check_input_parameters(uint32_t sample_rate,
786 audio_format_t format,
787 int channel_count)
788{
789 if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
790
791 if ((channel_count < 1) || (channel_count > 2)) return -EINVAL;
792
793 switch (sample_rate) {
794 case 8000:
795 case 11025:
796 case 12000:
797 case 16000:
798 case 22050:
799 case 24000:
800 case 32000:
801 case 44100:
802 case 48000:
803 break;
804 default:
805 return -EINVAL;
806 }
807
808 return 0;
809}
810
811static size_t get_input_buffer_size(uint32_t sample_rate,
812 audio_format_t format,
813 int channel_count)
814{
815 size_t size = 0;
816
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -0700817 if (check_input_parameters(sample_rate, format, channel_count) != 0)
818 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800819
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -0700820 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
821 /* ToDo: should use frame_size computed based on the format and
822 channel_count here. */
823 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800824
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -0700825 /* make sure the size is multiple of 64 */
826 size += 0x3f;
827 size &= ~0x3f;
828
829 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800830}
831
832static uint32_t out_get_sample_rate(const struct audio_stream *stream)
833{
834 struct stream_out *out = (struct stream_out *)stream;
835
836 return out->config.rate;
837}
838
839static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
840{
841 return -ENOSYS;
842}
843
844static size_t out_get_buffer_size(const struct audio_stream *stream)
845{
846 struct stream_out *out = (struct stream_out *)stream;
847
848 return out->config.period_size * audio_stream_frame_size(stream);
849}
850
851static uint32_t out_get_channels(const struct audio_stream *stream)
852{
853 struct stream_out *out = (struct stream_out *)stream;
854
855 return out->channel_mask;
856}
857
858static audio_format_t out_get_format(const struct audio_stream *stream)
859{
860 return AUDIO_FORMAT_PCM_16_BIT;
861}
862
863static int out_set_format(struct audio_stream *stream, audio_format_t format)
864{
865 return -ENOSYS;
866}
867
868static int out_standby(struct audio_stream *stream)
869{
870 struct stream_out *out = (struct stream_out *)stream;
871 struct audio_device *adev = out->dev;
Eric Laurent994a6932013-07-17 11:51:42 -0700872 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800874 pthread_mutex_lock(&out->lock);
875
876 if (!out->standby) {
877 out->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -0800878 if (out->pcm) {
879 pcm_close(out->pcm);
880 out->pcm = NULL;
881 }
882 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800883 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -0800884 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800885 }
886 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -0700887 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800888 return 0;
889}
890
891static int out_dump(const struct audio_stream *stream, int fd)
892{
893 return 0;
894}
895
896static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
897{
898 struct stream_out *out = (struct stream_out *)stream;
899 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800900 struct audio_usecase *usecase;
901 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800902 struct str_parms *parms;
903 char value[32];
904 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800905 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800906
sangwoobc677242013-08-08 16:53:43 +0900907 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700908 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800909 parms = str_parms_create_str(kvpairs);
910 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
911 if (ret >= 0) {
912 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800913 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -0800914 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800915
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916 /*
917 * When HDMI cable is unplugged the music playback is paused and
918 * the policy manager sends routing=0. But the audioflinger
919 * continues to write data until standby time (3sec).
920 * As the HDMI core is turned off, the write gets blocked.
921 * Avoid this by routing audio to speaker until standby.
922 */
923 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
924 val == AUDIO_DEVICE_NONE) {
925 val = AUDIO_DEVICE_OUT_SPEAKER;
926 }
927
928 /*
929 * select_devices() call below switches all the usecases on the same
930 * backend to the new device. Refer to check_usecases_codec_backend() in
931 * the select_devices(). But how do we undo this?
932 *
933 * For example, music playback is active on headset (deep-buffer usecase)
934 * and if we go to ringtones and select a ringtone, low-latency usecase
935 * will be started on headset+speaker. As we can't enable headset+speaker
936 * and headset devices at the same time, select_devices() switches the music
937 * playback to headset+speaker while starting low-lateny usecase for ringtone.
938 * So when the ringtone playback is completed, how do we undo the same?
939 *
940 * We are relying on the out_set_parameters() call on deep-buffer output,
941 * once the ringtone playback is ended.
942 * NOTE: We should not check if the current devices are same as new devices.
943 * Because select_devices() must be called to switch back the music
944 * playback to headset.
945 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800946 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700947 out->devices = val;
948
949 if (!out->standby)
950 select_devices(adev, out->usecase);
951
952 if ((adev->mode == AUDIO_MODE_IN_CALL) && !adev->in_call &&
953 (out == adev->primary_output)) {
954 start_voice_call(adev);
955 } else if ((adev->mode == AUDIO_MODE_IN_CALL) && adev->in_call &&
956 (out == adev->primary_output)) {
957 select_devices(adev, USECASE_VOICE_CALL);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800958 }
959 }
960
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700961 if ((adev->mode != AUDIO_MODE_IN_CALL) && adev->in_call &&
962 (out == adev->primary_output)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800963 stop_voice_call(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800964 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800966 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -0800967 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800968 }
969 str_parms_destroy(parms);
Eric Laurent994a6932013-07-17 11:51:42 -0700970 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800971 return ret;
972}
973
974static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
975{
976 struct stream_out *out = (struct stream_out *)stream;
977 struct str_parms *query = str_parms_create_str(keys);
978 char *str;
979 char value[256];
980 struct str_parms *reply = str_parms_create();
981 size_t i, j;
982 int ret;
983 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -0700984 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800985 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
986 if (ret >= 0) {
987 value[0] = '\0';
988 i = 0;
989 while (out->supported_channel_masks[i] != 0) {
990 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
991 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
992 if (!first) {
993 strcat(value, "|");
994 }
995 strcat(value, out_channels_name_to_enum_table[j].name);
996 first = false;
997 break;
998 }
999 }
1000 i++;
1001 }
1002 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1003 str = str_parms_to_str(reply);
1004 } else {
1005 str = strdup(keys);
1006 }
1007 str_parms_destroy(query);
1008 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001009 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001010 return str;
1011}
1012
1013static uint32_t out_get_latency(const struct audio_stream_out *stream)
1014{
1015 struct stream_out *out = (struct stream_out *)stream;
1016
1017 return (out->config.period_count * out->config.period_size * 1000) / (out->config.rate);
1018}
1019
1020static int out_set_volume(struct audio_stream_out *stream, float left,
1021 float right)
1022{
Eric Laurenta9024de2013-04-04 09:19:12 -07001023 struct stream_out *out = (struct stream_out *)stream;
1024 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1025 /* only take left channel into account: the API is for stereo anyway */
1026 out->muted = (left == 0.0f);
1027 return 0;
1028 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001029 return -ENOSYS;
1030}
1031
1032static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
1033 size_t bytes)
1034{
1035 struct stream_out *out = (struct stream_out *)stream;
1036 struct audio_device *adev = out->dev;
1037 int i, ret = -1;
1038
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039 pthread_mutex_lock(&out->lock);
1040 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001041 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001042 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001043 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001044 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001045 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001046 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001047 goto exit;
1048 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001050
1051 if (out->pcm) {
Eric Laurenta9024de2013-04-04 09:19:12 -07001052 if (out->muted)
1053 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001054 //ALOGV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
1055 ret = pcm_write(out->pcm, (void *)buffer, bytes);
1056 }
1057
1058exit:
1059 pthread_mutex_unlock(&out->lock);
1060
1061 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001062 if (out->pcm)
1063 ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001064 out_standby(&out->stream.common);
1065 usleep(bytes * 1000000 / audio_stream_frame_size(&out->stream.common) /
1066 out_get_sample_rate(&out->stream.common));
1067 }
1068 return bytes;
1069}
1070
1071static int out_get_render_position(const struct audio_stream_out *stream,
1072 uint32_t *dsp_frames)
1073{
1074 return -EINVAL;
1075}
1076
1077static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1078{
1079 return 0;
1080}
1081
1082static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1083{
1084 return 0;
1085}
1086
1087static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
1088 int64_t *timestamp)
1089{
1090 return -EINVAL;
1091}
1092
1093/** audio_stream_in implementation **/
1094static uint32_t in_get_sample_rate(const struct audio_stream *stream)
1095{
1096 struct stream_in *in = (struct stream_in *)stream;
1097
1098 return in->config.rate;
1099}
1100
1101static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1102{
1103 return -ENOSYS;
1104}
1105
1106static size_t in_get_buffer_size(const struct audio_stream *stream)
1107{
1108 struct stream_in *in = (struct stream_in *)stream;
1109
1110 return in->config.period_size * audio_stream_frame_size(stream);
1111}
1112
1113static uint32_t in_get_channels(const struct audio_stream *stream)
1114{
1115 struct stream_in *in = (struct stream_in *)stream;
1116
1117 return in->channel_mask;
1118}
1119
1120static audio_format_t in_get_format(const struct audio_stream *stream)
1121{
1122 return AUDIO_FORMAT_PCM_16_BIT;
1123}
1124
1125static int in_set_format(struct audio_stream *stream, audio_format_t format)
1126{
1127 return -ENOSYS;
1128}
1129
1130static int in_standby(struct audio_stream *stream)
1131{
1132 struct stream_in *in = (struct stream_in *)stream;
1133 struct audio_device *adev = in->dev;
1134 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07001135 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001136 pthread_mutex_lock(&in->lock);
1137 if (!in->standby) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001138 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001139 if (in->pcm) {
1140 pcm_close(in->pcm);
1141 in->pcm = NULL;
1142 }
1143 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001144 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001145 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001146 }
1147 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001148 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001149 return status;
1150}
1151
1152static int in_dump(const struct audio_stream *stream, int fd)
1153{
1154 return 0;
1155}
1156
1157static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1158{
1159 struct stream_in *in = (struct stream_in *)stream;
1160 struct audio_device *adev = in->dev;
1161 struct str_parms *parms;
1162 char *str;
1163 char value[32];
1164 int ret, val = 0;
1165
Eric Laurent994a6932013-07-17 11:51:42 -07001166 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001167 parms = str_parms_create_str(kvpairs);
1168
1169 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
1170
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001171 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001172 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001173 if (ret >= 0) {
1174 val = atoi(value);
1175 /* no audio source uses val == 0 */
1176 if ((in->source != val) && (val != 0)) {
1177 in->source = val;
1178 }
1179 }
1180
1181 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1182 if (ret >= 0) {
1183 val = atoi(value);
1184 if ((in->device != val) && (val != 0)) {
1185 in->device = val;
1186 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001187 if (!in->standby)
1188 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001189 }
1190 }
1191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001192 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001193 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001194
1195 str_parms_destroy(parms);
Eric Laurent994a6932013-07-17 11:51:42 -07001196 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001197 return ret;
1198}
1199
1200static char* in_get_parameters(const struct audio_stream *stream,
1201 const char *keys)
1202{
1203 return strdup("");
1204}
1205
1206static int in_set_gain(struct audio_stream_in *stream, float gain)
1207{
1208 return 0;
1209}
1210
1211static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
1212 size_t bytes)
1213{
1214 struct stream_in *in = (struct stream_in *)stream;
1215 struct audio_device *adev = in->dev;
1216 int i, ret = -1;
1217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001218 pthread_mutex_lock(&in->lock);
1219 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001220 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001221 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001222 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001223 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001224 goto exit;
1225 }
1226 in->standby = 0;
1227 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001228
1229 if (in->pcm) {
1230 ret = pcm_read(in->pcm, buffer, bytes);
1231 }
1232
1233 /*
1234 * Instead of writing zeroes here, we could trust the hardware
1235 * to always provide zeroes when muted.
1236 */
1237 if (ret == 0 && adev->mic_mute)
1238 memset(buffer, 0, bytes);
1239
1240exit:
1241 pthread_mutex_unlock(&in->lock);
1242
1243 if (ret != 0) {
1244 in_standby(&in->stream.common);
1245 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
1246 usleep(bytes * 1000000 / audio_stream_frame_size(&in->stream.common) /
1247 in_get_sample_rate(&in->stream.common));
1248 }
1249 return bytes;
1250}
1251
1252static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1253{
1254 return 0;
1255}
1256
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001257static int add_remove_audio_effect(const struct audio_stream *stream,
1258 effect_handle_t effect,
1259 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001260{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001261 struct stream_in *in = (struct stream_in *)stream;
1262 int status = 0;
1263 effect_descriptor_t desc;
1264
1265 status = (*effect)->get_descriptor(effect, &desc);
1266 if (status != 0)
1267 return status;
1268
1269 pthread_mutex_lock(&in->lock);
1270 pthread_mutex_lock(&in->dev->lock);
1271 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
1272 in->enable_aec != enable &&
1273 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
1274 in->enable_aec = enable;
1275 if (!in->standby)
1276 select_devices(in->dev, in->usecase);
1277 }
1278 pthread_mutex_unlock(&in->dev->lock);
1279 pthread_mutex_unlock(&in->lock);
1280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001281 return 0;
1282}
1283
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001284static int in_add_audio_effect(const struct audio_stream *stream,
1285 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001286{
Eric Laurent994a6932013-07-17 11:51:42 -07001287 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001288 return add_remove_audio_effect(stream, effect, true);
1289}
1290
1291static int in_remove_audio_effect(const struct audio_stream *stream,
1292 effect_handle_t effect)
1293{
Eric Laurent994a6932013-07-17 11:51:42 -07001294 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001295 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001296}
1297
1298static int adev_open_output_stream(struct audio_hw_device *dev,
1299 audio_io_handle_t handle,
1300 audio_devices_t devices,
1301 audio_output_flags_t flags,
1302 struct audio_config *config,
1303 struct audio_stream_out **stream_out)
1304{
1305 struct audio_device *adev = (struct audio_device *)dev;
1306 struct stream_out *out;
1307 int i, ret;
1308
Eric Laurent994a6932013-07-17 11:51:42 -07001309 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001310 __func__, config->sample_rate, config->channel_mask, devices, flags);
1311 *stream_out = NULL;
1312 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
1313
1314 if (devices == AUDIO_DEVICE_NONE)
1315 devices = AUDIO_DEVICE_OUT_SPEAKER;
1316
1317 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
1318 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
1319 out->flags = flags;
1320 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001321 out->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001322
1323 /* Init use case and pcm_config */
1324 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
1325 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001326 pthread_mutex_lock(&adev->lock);
1327 ret = read_hdmi_channel_masks(out);
1328 pthread_mutex_unlock(&adev->lock);
1329 if (ret != 0) {
1330 /* If HDMI does not support multi channel playback, set the default */
1331 out->config.channels = popcount(out->channel_mask);
Eric Laurentb23d5282013-05-14 15:27:20 -07001332 platform_set_hdmi_channels(adev->platform, out->config.channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001333 goto error_open;
1334 }
1335
1336 if (config->sample_rate == 0)
1337 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1338 if (config->channel_mask == 0)
1339 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
1340
1341 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001342 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
1343 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344 out->config.rate = config->sample_rate;
1345 out->config.channels = popcount(out->channel_mask);
1346 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Eric Laurentb23d5282013-05-14 15:27:20 -07001347 platform_set_hdmi_channels(adev->platform, out->config.channels);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001348 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
1349 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
1350 out->config = pcm_config_deep_buffer;
1351 } else {
1352 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
1353 out->config = pcm_config_low_latency;
1354 }
1355
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001356 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
1357 if(adev->primary_output == NULL)
1358 adev->primary_output = out;
1359 else {
1360 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001361 ret = -EEXIST;
1362 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001363 }
1364 }
1365
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001366 /* Check if this usecase is already existing */
1367 pthread_mutex_lock(&adev->lock);
1368 if (get_usecase_from_list(adev, out->usecase) != NULL) {
1369 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001370 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001371 ret = -EEXIST;
1372 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001373 }
1374 pthread_mutex_unlock(&adev->lock);
1375
1376 out->stream.common.get_sample_rate = out_get_sample_rate;
1377 out->stream.common.set_sample_rate = out_set_sample_rate;
1378 out->stream.common.get_buffer_size = out_get_buffer_size;
1379 out->stream.common.get_channels = out_get_channels;
1380 out->stream.common.get_format = out_get_format;
1381 out->stream.common.set_format = out_set_format;
1382 out->stream.common.standby = out_standby;
1383 out->stream.common.dump = out_dump;
1384 out->stream.common.set_parameters = out_set_parameters;
1385 out->stream.common.get_parameters = out_get_parameters;
1386 out->stream.common.add_audio_effect = out_add_audio_effect;
1387 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1388 out->stream.get_latency = out_get_latency;
1389 out->stream.set_volume = out_set_volume;
1390 out->stream.write = out_write;
1391 out->stream.get_render_position = out_get_render_position;
1392 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
1393
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001394 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07001395 /* out->muted = false; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001396
1397 config->format = out->stream.common.get_format(&out->stream.common);
1398 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
1399 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
1400
1401 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07001402 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001403 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001404
1405error_open:
1406 free(out);
1407 *stream_out = NULL;
1408 ALOGD("%s: exit: ret %d", __func__, ret);
1409 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001410}
1411
1412static void adev_close_output_stream(struct audio_hw_device *dev,
1413 struct audio_stream_out *stream)
1414{
Eric Laurent994a6932013-07-17 11:51:42 -07001415 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001416 out_standby(&stream->common);
1417 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07001418 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001419}
1420
1421static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1422{
1423 struct audio_device *adev = (struct audio_device *)dev;
1424 struct str_parms *parms;
1425 char *str;
1426 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07001427 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001428 int ret;
1429
Eric Laurent994a6932013-07-17 11:51:42 -07001430 ALOGV("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001431
1432 parms = str_parms_create_str(kvpairs);
1433 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_TTY_MODE, value, sizeof(value));
1434 if (ret >= 0) {
1435 int tty_mode;
1436
1437 if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_OFF) == 0)
1438 tty_mode = TTY_MODE_OFF;
1439 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_VCO) == 0)
1440 tty_mode = TTY_MODE_VCO;
1441 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_HCO) == 0)
1442 tty_mode = TTY_MODE_HCO;
1443 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_FULL) == 0)
1444 tty_mode = TTY_MODE_FULL;
1445 else
1446 return -EINVAL;
1447
1448 pthread_mutex_lock(&adev->lock);
1449 if (tty_mode != adev->tty_mode) {
1450 adev->tty_mode = tty_mode;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08001451 adev->acdb_settings = (adev->acdb_settings & TTY_MODE_CLEAR) | tty_mode;
1452 if (adev->in_call)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001453 select_devices(adev, USECASE_VOICE_CALL);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001454 }
1455 pthread_mutex_unlock(&adev->lock);
1456 }
1457
1458 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
1459 if (ret >= 0) {
1460 /* When set to false, HAL should disable EC and NS
1461 * But it is currently not supported.
1462 */
1463 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
1464 adev->bluetooth_nrec = true;
1465 else
1466 adev->bluetooth_nrec = false;
1467 }
1468
1469 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
1470 if (ret >= 0) {
1471 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
1472 adev->screen_off = false;
1473 else
1474 adev->screen_off = true;
1475 }
1476
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07001477 ret = str_parms_get_int(parms, "rotation", &val);
1478 if (ret >= 0) {
1479 bool reverse_speakers = false;
1480 switch(val) {
1481 // FIXME: note that the code below assumes that the speakers are in the correct placement
1482 // relative to the user when the device is rotated 90deg from its default rotation. This
1483 // assumption is device-specific, not platform-specific like this code.
1484 case 270:
1485 reverse_speakers = true;
1486 break;
1487 case 0:
1488 case 90:
1489 case 180:
1490 break;
1491 default:
1492 ALOGE("%s: unexpected rotation of %d", __func__, val);
1493 }
1494 pthread_mutex_lock(&adev->lock);
1495 if (adev->speaker_lr_swap != reverse_speakers) {
1496 adev->speaker_lr_swap = reverse_speakers;
1497 // only update the selected device if there is active pcm playback
1498 struct audio_usecase *usecase;
1499 struct listnode *node;
1500 list_for_each(node, &adev->usecase_list) {
1501 usecase = node_to_item(node, struct audio_usecase, list);
1502 if (usecase->type == PCM_PLAYBACK) {
1503 select_devices(adev, usecase->id);
1504 break;
1505 }
1506 }
1507 }
1508 pthread_mutex_unlock(&adev->lock);
1509 }
1510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001511 str_parms_destroy(parms);
Eric Laurent994a6932013-07-17 11:51:42 -07001512 ALOGV("%s: exit with code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001513 return ret;
1514}
1515
1516static char* adev_get_parameters(const struct audio_hw_device *dev,
1517 const char *keys)
1518{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001519 return strdup("");
1520}
1521
1522static int adev_init_check(const struct audio_hw_device *dev)
1523{
1524 return 0;
1525}
1526
1527static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1528{
1529 struct audio_device *adev = (struct audio_device *)dev;
1530 int vol, err = 0;
1531
1532 pthread_mutex_lock(&adev->lock);
1533 adev->voice_volume = volume;
1534 if (adev->mode == AUDIO_MODE_IN_CALL) {
1535 if (volume < 0.0) {
1536 volume = 0.0;
1537 } else if (volume > 1.0) {
1538 volume = 1.0;
1539 }
1540
1541 vol = lrint(volume * 100.0);
1542
1543 // Voice volume levels from android are mapped to driver volume levels as follows.
1544 // 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0
1545 // So adjust the volume to get the correct volume index in driver
1546 vol = 100 - vol;
Eric Laurentb23d5282013-05-14 15:27:20 -07001547
1548 err = platform_set_voice_volume(adev->platform, vol);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001549 }
1550 pthread_mutex_unlock(&adev->lock);
1551 return err;
1552}
1553
1554static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1555{
1556 return -ENOSYS;
1557}
1558
1559static int adev_get_master_volume(struct audio_hw_device *dev,
1560 float *volume)
1561{
1562 return -ENOSYS;
1563}
1564
1565static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
1566{
1567 return -ENOSYS;
1568}
1569
1570static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
1571{
1572 return -ENOSYS;
1573}
1574
1575static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1576{
1577 struct audio_device *adev = (struct audio_device *)dev;
1578
1579 pthread_mutex_lock(&adev->lock);
1580 if (adev->mode != mode) {
1581 adev->mode = mode;
1582 }
1583 pthread_mutex_unlock(&adev->lock);
1584 return 0;
1585}
1586
1587static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1588{
1589 struct audio_device *adev = (struct audio_device *)dev;
1590 int err = 0;
1591
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001592 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001593 adev->mic_mute = state;
Eric Laurentb23d5282013-05-14 15:27:20 -07001594
1595 err = platform_set_mic_mute(adev->platform, state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001596 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001597 return err;
1598}
1599
1600static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1601{
1602 struct audio_device *adev = (struct audio_device *)dev;
1603
1604 *state = adev->mic_mute;
1605
1606 return 0;
1607}
1608
1609static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1610 const struct audio_config *config)
1611{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001612 int channel_count = popcount(config->channel_mask);
1613
1614 return get_input_buffer_size(config->sample_rate, config->format, channel_count);
1615}
1616
1617static int adev_open_input_stream(struct audio_hw_device *dev,
1618 audio_io_handle_t handle,
1619 audio_devices_t devices,
1620 struct audio_config *config,
1621 struct audio_stream_in **stream_in)
1622{
1623 struct audio_device *adev = (struct audio_device *)dev;
1624 struct stream_in *in;
1625 int ret, buffer_size, frame_size;
1626 int channel_count = popcount(config->channel_mask);
1627
Eric Laurent994a6932013-07-17 11:51:42 -07001628 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001629 *stream_in = NULL;
1630 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
1631 return -EINVAL;
1632
1633 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
1634
1635 in->stream.common.get_sample_rate = in_get_sample_rate;
1636 in->stream.common.set_sample_rate = in_set_sample_rate;
1637 in->stream.common.get_buffer_size = in_get_buffer_size;
1638 in->stream.common.get_channels = in_get_channels;
1639 in->stream.common.get_format = in_get_format;
1640 in->stream.common.set_format = in_set_format;
1641 in->stream.common.standby = in_standby;
1642 in->stream.common.dump = in_dump;
1643 in->stream.common.set_parameters = in_set_parameters;
1644 in->stream.common.get_parameters = in_get_parameters;
1645 in->stream.common.add_audio_effect = in_add_audio_effect;
1646 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1647 in->stream.set_gain = in_set_gain;
1648 in->stream.read = in_read;
1649 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1650
1651 in->device = devices;
1652 in->source = AUDIO_SOURCE_DEFAULT;
1653 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001654 in->standby = 1;
1655 in->channel_mask = config->channel_mask;
1656
1657 /* Update config params with the requested sample rate and channels */
1658 in->usecase = USECASE_AUDIO_RECORD;
1659 in->config = pcm_config_audio_capture;
1660 in->config.channels = channel_count;
1661 in->config.rate = config->sample_rate;
1662
1663 frame_size = audio_stream_frame_size((struct audio_stream *)in);
1664 buffer_size = get_input_buffer_size(config->sample_rate,
1665 config->format,
1666 channel_count);
1667 in->config.period_size = buffer_size / frame_size;
1668
1669 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07001670 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001671 return 0;
1672
1673err_open:
1674 free(in);
1675 *stream_in = NULL;
1676 return ret;
1677}
1678
1679static void adev_close_input_stream(struct audio_hw_device *dev,
1680 struct audio_stream_in *stream)
1681{
Eric Laurent994a6932013-07-17 11:51:42 -07001682 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001683
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684 in_standby(&stream->common);
1685 free(stream);
1686
1687 return;
1688}
1689
1690static int adev_dump(const audio_hw_device_t *device, int fd)
1691{
1692 return 0;
1693}
1694
1695static int adev_close(hw_device_t *device)
1696{
1697 struct audio_device *adev = (struct audio_device *)device;
1698 audio_route_free(adev->audio_route);
Eric Laurentb23d5282013-05-14 15:27:20 -07001699 free(adev->snd_dev_ref_cnt);
1700 platform_deinit(adev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701 free(device);
1702 return 0;
1703}
1704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705static int adev_open(const hw_module_t *module, const char *name,
1706 hw_device_t **device)
1707{
1708 struct audio_device *adev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001709 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001710
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001711 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001712 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
1713
1714 adev = calloc(1, sizeof(struct audio_device));
1715
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716 adev->device.common.tag = HARDWARE_DEVICE_TAG;
1717 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
1718 adev->device.common.module = (struct hw_module_t *)module;
1719 adev->device.common.close = adev_close;
1720
1721 adev->device.init_check = adev_init_check;
1722 adev->device.set_voice_volume = adev_set_voice_volume;
1723 adev->device.set_master_volume = adev_set_master_volume;
1724 adev->device.get_master_volume = adev_get_master_volume;
1725 adev->device.set_master_mute = adev_set_master_mute;
1726 adev->device.get_master_mute = adev_get_master_mute;
1727 adev->device.set_mode = adev_set_mode;
1728 adev->device.set_mic_mute = adev_set_mic_mute;
1729 adev->device.get_mic_mute = adev_get_mic_mute;
1730 adev->device.set_parameters = adev_set_parameters;
1731 adev->device.get_parameters = adev_get_parameters;
1732 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
1733 adev->device.open_output_stream = adev_open_output_stream;
1734 adev->device.close_output_stream = adev_close_output_stream;
1735 adev->device.open_input_stream = adev_open_input_stream;
1736 adev->device.close_input_stream = adev_close_input_stream;
1737 adev->device.dump = adev_dump;
1738
1739 /* Set the default route before the PCM stream is opened */
1740 pthread_mutex_lock(&adev->lock);
1741 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08001742 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001743 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745 adev->voice_call_rx = NULL;
1746 adev->voice_call_tx = NULL;
1747 adev->voice_volume = 1.0f;
1748 adev->tty_mode = TTY_MODE_OFF;
1749 adev->bluetooth_nrec = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001750 adev->in_call = false;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08001751 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurentb23d5282013-05-14 15:27:20 -07001752 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001753 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754 pthread_mutex_unlock(&adev->lock);
1755
1756 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07001757 adev->platform = platform_init(adev);
1758 if (!adev->platform) {
1759 free(adev->snd_dev_ref_cnt);
1760 free(adev);
1761 ALOGE("%s: Failed to init platform data, aborting.", __func__);
1762 *device = NULL;
1763 return -EINVAL;
1764 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765 *device = &adev->device.common;
1766
Eric Laurent994a6932013-07-17 11:51:42 -07001767 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768 return 0;
1769}
1770
1771static struct hw_module_methods_t hal_module_methods = {
1772 .open = adev_open,
1773};
1774
1775struct audio_module HAL_MODULE_INFO_SYM = {
1776 .common = {
1777 .tag = HARDWARE_MODULE_TAG,
1778 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1779 .hal_api_version = HARDWARE_HAL_API_VERSION,
1780 .id = AUDIO_HARDWARE_MODULE_ID,
1781 .name = "QCOM Audio HAL",
1782 .author = "Code Aurora Forum",
1783 .methods = &hal_module_methods,
1784 },
1785};