blob: b73c95e022adb13ac33ed14ccb8f2e140e6561ca [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
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080039#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
Eric Laurentb23d5282013-05-14 15:27:20 -070040
41struct pcm_config pcm_config_deep_buffer = {
42 .channels = 2,
43 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
44 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
45 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
46 .format = PCM_FORMAT_S16_LE,
47 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
48 .stop_threshold = INT_MAX,
49 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
50};
51
52struct pcm_config pcm_config_low_latency = {
53 .channels = 2,
54 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
55 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
56 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
57 .format = PCM_FORMAT_S16_LE,
58 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
59 .stop_threshold = INT_MAX,
60 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
61};
62
63struct pcm_config pcm_config_hdmi_multi = {
64 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
65 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
66 .period_size = HDMI_MULTI_PERIOD_SIZE,
67 .period_count = HDMI_MULTI_PERIOD_COUNT,
68 .format = PCM_FORMAT_S16_LE,
69 .start_threshold = 0,
70 .stop_threshold = INT_MAX,
71 .avail_min = 0,
72};
73
74struct pcm_config pcm_config_audio_capture = {
75 .channels = 2,
76 .period_size = AUDIO_CAPTURE_PERIOD_SIZE,
77 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
78 .format = PCM_FORMAT_S16_LE,
79};
80
81struct pcm_config pcm_config_voice_call = {
82 .channels = 1,
83 .rate = 8000,
84 .period_size = 160,
85 .period_count = 2,
86 .format = PCM_FORMAT_S16_LE,
87};
88
89static const char * const use_case_table[AUDIO_USECASE_MAX] = {
90 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
91 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
92 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
93 [USECASE_AUDIO_RECORD] = "audio-record",
94 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
95 [USECASE_VOICE_CALL] = "voice-call",
96};
97
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080098
99#define STRING_TO_ENUM(string) { #string, string }
100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800101struct string_to_enum {
102 const char *name;
103 uint32_t value;
104};
105
106static const struct string_to_enum out_channels_name_to_enum_table[] = {
107 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
108 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
109 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
110};
111
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800112
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700113static int enable_audio_route(struct audio_device *adev,
114 struct audio_usecase *usecase,
115 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800116{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700117 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800118 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800119
120 if (usecase == NULL)
121 return -EINVAL;
122
123 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
124
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800125 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700126 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800127 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700128 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800129
130 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700131 platform_add_backend_name(mixer_path, snd_device);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800132 ALOGD("%s: apply mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700133 audio_route_apply_path(adev->audio_route, mixer_path);
134 if (update_mixer)
135 audio_route_update_mixer(adev->audio_route);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800137 ALOGV("%s: exit", __func__);
138 return 0;
139}
140
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700141static int disable_audio_route(struct audio_device *adev,
142 struct audio_usecase *usecase,
143 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800144{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700145 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800146 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800147
148 if (usecase == NULL)
149 return -EINVAL;
150
151 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700152 if (usecase->type == PCM_CAPTURE)
153 snd_device = usecase->in_snd_device;
154 else
155 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800156 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700157 platform_add_backend_name(mixer_path, snd_device);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800158 ALOGD("%s: reset mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700159 audio_route_reset_path(adev->audio_route, mixer_path);
160 if (update_mixer)
161 audio_route_update_mixer(adev->audio_route);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800163 ALOGV("%s: exit", __func__);
164 return 0;
165}
166
167static int enable_snd_device(struct audio_device *adev,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700168 snd_device_t snd_device,
169 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800170{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800171 if (snd_device < SND_DEVICE_MIN ||
172 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800173 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800174 return -EINVAL;
175 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700176
177 adev->snd_dev_ref_cnt[snd_device]++;
178 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
179 ALOGD("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 __func__, snd_device, platform_get_snd_device_name(snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700181 return 0;
182 }
183
Eric Laurentb23d5282013-05-14 15:27:20 -0700184 if (platform_send_audio_calibration(adev->platform, snd_device) < 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700185 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800186 return -EINVAL;
187 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800188
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700189 ALOGD("%s: snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700190 snd_device, platform_get_snd_device_name(snd_device));
191 audio_route_apply_path(adev->audio_route, platform_get_snd_device_name(snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700192 if (update_mixer)
193 audio_route_update_mixer(adev->audio_route);
194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800195 return 0;
196}
197
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700198static int disable_snd_device(struct audio_device *adev,
199 snd_device_t snd_device,
200 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800201{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800202 if (snd_device < SND_DEVICE_MIN ||
203 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800204 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800205 return -EINVAL;
206 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700207 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
208 ALOGE("%s: device ref cnt is already 0", __func__);
209 return -EINVAL;
210 }
211 adev->snd_dev_ref_cnt[snd_device]--;
212 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
213 ALOGD("%s: snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700214 snd_device, platform_get_snd_device_name(snd_device));
215 audio_route_reset_path(adev->audio_route, platform_get_snd_device_name(snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700216 if (update_mixer)
217 audio_route_update_mixer(adev->audio_route);
218 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800219 return 0;
220}
221
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700222static void check_usecases_codec_backend(struct audio_device *adev,
223 struct audio_usecase *uc_info,
224 snd_device_t snd_device)
225{
226 struct listnode *node;
227 struct audio_usecase *usecase;
228 bool switch_device[AUDIO_USECASE_MAX];
229 int i, num_uc_to_switch = 0;
230
231 /*
232 * This function is to make sure that all the usecases that are active on
233 * the hardware codec backend are always routed to any one device that is
234 * handled by the hardware codec.
235 * For example, if low-latency and deep-buffer usecases are currently active
236 * on speaker and out_set_parameters(headset) is received on low-latency
237 * output, then we have to make sure deep-buffer is also switched to headset,
238 * because of the limitation that both the devices cannot be enabled
239 * at the same time as they share the same backend.
240 */
241 /* Disable all the usecases on the shared backend other than the
242 specified usecase */
243 for (i = 0; i < AUDIO_USECASE_MAX; i++)
244 switch_device[i] = false;
245
246 list_for_each(node, &adev->usecase_list) {
247 usecase = node_to_item(node, struct audio_usecase, list);
248 if (usecase->type != PCM_CAPTURE &&
249 usecase != uc_info &&
250 usecase->out_snd_device != snd_device &&
251 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
252 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
253 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700254 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700255 disable_audio_route(adev, usecase, false);
256 switch_device[usecase->id] = true;
257 num_uc_to_switch++;
258 }
259 }
260
261 if (num_uc_to_switch) {
262 /* Make sure all the streams are de-routed before disabling the device */
263 audio_route_update_mixer(adev->audio_route);
264
265 list_for_each(node, &adev->usecase_list) {
266 usecase = node_to_item(node, struct audio_usecase, list);
267 if (switch_device[usecase->id]) {
268 disable_snd_device(adev, usecase->out_snd_device, false);
269 enable_snd_device(adev, snd_device, false);
270 }
271 }
272
273 /* Make sure new snd device is enabled before re-routing the streams */
274 audio_route_update_mixer(adev->audio_route);
275
276 /* Re-route all the usecases on the shared backend other than the
277 specified usecase to new snd devices */
278 list_for_each(node, &adev->usecase_list) {
279 usecase = node_to_item(node, struct audio_usecase, list);
280 /* Update the out_snd_device only before enabling the audio route */
281 if (switch_device[usecase->id] ) {
282 usecase->out_snd_device = snd_device;
283 enable_audio_route(adev, usecase, false);
284 }
285 }
286
287 audio_route_update_mixer(adev->audio_route);
288 }
289}
290
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700291static void check_and_route_capture_usecases(struct audio_device *adev,
292 struct audio_usecase *uc_info,
293 snd_device_t snd_device)
294{
295 struct listnode *node;
296 struct audio_usecase *usecase;
297 bool switch_device[AUDIO_USECASE_MAX];
298 int i, num_uc_to_switch = 0;
299
300 /*
301 * This function is to make sure that all the active capture usecases
302 * are always routed to the same input sound device.
303 * For example, if audio-record and voice-call usecases are currently
304 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
305 * is received for voice call then we have to make sure that audio-record
306 * usecase is also switched to earpiece i.e. voice-dmic-ef,
307 * because of the limitation that two devices cannot be enabled
308 * at the same time if they share the same backend.
309 */
310 for (i = 0; i < AUDIO_USECASE_MAX; i++)
311 switch_device[i] = false;
312
313 list_for_each(node, &adev->usecase_list) {
314 usecase = node_to_item(node, struct audio_usecase, list);
315 if (usecase->type != PCM_PLAYBACK &&
316 usecase != uc_info &&
317 usecase->in_snd_device != snd_device) {
318 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
319 __func__, use_case_table[usecase->id],
320 device_table[usecase->in_snd_device]);
321 disable_audio_route(adev, usecase, false);
322 switch_device[usecase->id] = true;
323 num_uc_to_switch++;
324 }
325 }
326
327 if (num_uc_to_switch) {
328 /* Make sure all the streams are de-routed before disabling the device */
329 audio_route_update_mixer(adev->audio_route);
330
331 list_for_each(node, &adev->usecase_list) {
332 usecase = node_to_item(node, struct audio_usecase, list);
333 if (switch_device[usecase->id]) {
334 disable_snd_device(adev, usecase->in_snd_device, false);
335 enable_snd_device(adev, snd_device, false);
336 }
337 }
338
339 /* Make sure new snd device is enabled before re-routing the streams */
340 audio_route_update_mixer(adev->audio_route);
341
342 /* Re-route all the usecases on the shared backend other than the
343 specified usecase to new snd devices */
344 list_for_each(node, &adev->usecase_list) {
345 usecase = node_to_item(node, struct audio_usecase, list);
346 /* Update the in_snd_device only before enabling the audio route */
347 if (switch_device[usecase->id] ) {
348 usecase->in_snd_device = snd_device;
349 enable_audio_route(adev, usecase, false);
350 }
351 }
352
353 audio_route_update_mixer(adev->audio_route);
354 }
355}
356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800357
358/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700359static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800360{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700361 int ret = 0;
Eric Laurentb23d5282013-05-14 15:27:20 -0700362 int channels = platform_edid_get_max_channels();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800363
364 switch (channels) {
365 /*
366 * Do not handle stereo output in Multi-channel cases
367 * Stereo case is handled in normal playback path
368 */
369 case 6:
370 ALOGV("%s: HDMI supports 5.1", __func__);
371 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
372 break;
373 case 8:
374 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
375 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
376 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
377 break;
378 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700379 ALOGE("HDMI does not support multi channel playback");
380 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800381 break;
382 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700383 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800384}
385
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700386static struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
387 audio_usecase_t uc_id)
388{
389 struct audio_usecase *usecase;
390 struct listnode *node;
391
392 list_for_each(node, &adev->usecase_list) {
393 usecase = node_to_item(node, struct audio_usecase, list);
394 if (usecase->id == uc_id)
395 return usecase;
396 }
397 return NULL;
398}
399
400static int select_devices(struct audio_device *adev,
401 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800402{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800403 snd_device_t out_snd_device = SND_DEVICE_NONE;
404 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700405 struct audio_usecase *usecase = NULL;
406 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800407 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700408 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800409
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700410 usecase = get_usecase_from_list(adev, uc_id);
411 if (usecase == NULL) {
412 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
413 return -EINVAL;
414 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800415
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700416 if (usecase->type == VOICE_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700417 out_snd_device = platform_get_output_snd_device(adev->platform,
418 usecase->stream.out->devices);
419 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700420 usecase->devices = usecase->stream.out->devices;
421 } else {
422 /*
423 * If the voice call is active, use the sound devices of voice call usecase
424 * so that it would not result any device switch. All the usecases will
425 * be switched to new device when select_devices() is called for voice call
426 * usecase. This is to avoid switching devices for voice call when
427 * check_usecases_codec_backend() is called below.
428 */
429 if (adev->in_call) {
430 vc_usecase = get_usecase_from_list(adev, USECASE_VOICE_CALL);
431 if (vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
432 in_snd_device = vc_usecase->in_snd_device;
433 out_snd_device = vc_usecase->out_snd_device;
434 }
435 }
436 if (usecase->type == PCM_PLAYBACK) {
437 usecase->devices = usecase->stream.out->devices;
438 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700439 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700440 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700441 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700442 if (usecase->stream.out == adev->primary_output &&
443 adev->active_input &&
444 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
445 select_devices(adev, adev->active_input->usecase);
446 }
447 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700448 } else if (usecase->type == PCM_CAPTURE) {
449 usecase->devices = usecase->stream.in->device;
450 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700451 if (in_snd_device == SND_DEVICE_NONE) {
452 if (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
453 adev->primary_output && !adev->primary_output->standby) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700454 in_snd_device = platform_get_input_snd_device(adev->platform,
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700455 adev->primary_output->devices);
456 } else {
Eric Laurentb23d5282013-05-14 15:27:20 -0700457 in_snd_device = platform_get_input_snd_device(adev->platform,
458 AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700459 }
460 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700461 }
462 }
463
464 if (out_snd_device == usecase->out_snd_device &&
465 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800466 return 0;
467 }
468
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800469 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700470 out_snd_device, platform_get_snd_device_name(out_snd_device),
471 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800472
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800473 /*
474 * Limitation: While in call, to do a device switch we need to disable
475 * and enable both RX and TX devices though one of them is same as current
476 * device.
477 */
Eric Laurentb23d5282013-05-14 15:27:20 -0700478 if (usecase->type == VOICE_CALL) {
479 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800480 }
481
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700482 /* Disable current sound devices */
483 if (usecase->out_snd_device != SND_DEVICE_NONE) {
484 disable_audio_route(adev, usecase, true);
485 disable_snd_device(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800486 }
487
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700488 if (usecase->in_snd_device != SND_DEVICE_NONE) {
489 disable_audio_route(adev, usecase, true);
490 disable_snd_device(adev, usecase->in_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800491 }
492
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700493 /* Enable new sound devices */
494 if (out_snd_device != SND_DEVICE_NONE) {
495 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
496 check_usecases_codec_backend(adev, usecase, out_snd_device);
497 enable_snd_device(adev, out_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800498 }
499
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700500 if (in_snd_device != SND_DEVICE_NONE) {
501 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700502 enable_snd_device(adev, in_snd_device, false);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700503 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700504
Eric Laurentb23d5282013-05-14 15:27:20 -0700505 if (usecase->type == VOICE_CALL)
506 status = platform_switch_voice_call_device_post(adev->platform,
507 out_snd_device,
508 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800509
sangwoo170731f2013-06-08 15:36:36 +0900510 audio_route_update_mixer(adev->audio_route);
511
512 usecase->in_snd_device = in_snd_device;
513 usecase->out_snd_device = out_snd_device;
514
515 enable_audio_route(adev, usecase, true);
516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800517 return status;
518}
519
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800520static int stop_input_stream(struct stream_in *in)
521{
522 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800523 struct audio_usecase *uc_info;
524 struct audio_device *adev = in->dev;
525
Eric Laurentc8400632013-02-14 19:04:54 -0800526 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800527
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700528 ALOGD("%s: enter: usecase(%d: %s)", __func__,
529 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800530 uc_info = get_usecase_from_list(adev, in->usecase);
531 if (uc_info == NULL) {
532 ALOGE("%s: Could not find the usecase (%d) in the list",
533 __func__, in->usecase);
534 return -EINVAL;
535 }
536
Eric Laurent150dbfe2013-02-27 14:31:02 -0800537 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700538 disable_audio_route(adev, uc_info, true);
539
540 /* 2. Disable the tx device */
541 disable_snd_device(adev, uc_info->in_snd_device, true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800542
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800543 list_remove(&uc_info->list);
544 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800545
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800546 ALOGD("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800547 return ret;
548}
549
550int start_input_stream(struct stream_in *in)
551{
552 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800553 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800554 struct audio_usecase *uc_info;
555 struct audio_device *adev = in->dev;
556
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800557 ALOGD("%s: enter: usecase(%d)", __func__, in->usecase);
Eric Laurentb23d5282013-05-14 15:27:20 -0700558 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800559 if (in->pcm_device_id < 0) {
560 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
561 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -0800562 ret = -EINVAL;
563 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800564 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700565
566 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800567 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
568 uc_info->id = in->usecase;
569 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800570 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700571 uc_info->devices = in->device;
572 uc_info->in_snd_device = SND_DEVICE_NONE;
573 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800574
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800575 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700576 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800577
Eric Laurentc8400632013-02-14 19:04:54 -0800578 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
579 __func__, SOUND_CARD, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800580 in->pcm = pcm_open(SOUND_CARD, in->pcm_device_id,
581 PCM_IN, &in->config);
582 if (in->pcm && !pcm_is_ready(in->pcm)) {
583 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
584 pcm_close(in->pcm);
585 in->pcm = NULL;
Eric Laurentc8400632013-02-14 19:04:54 -0800586 ret = -EIO;
587 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800588 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800589 ALOGD("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -0800590 return ret;
591
592error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800593 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -0800594
595error_config:
596 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700597 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -0800598
599 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800600}
601
602static int stop_output_stream(struct stream_out *out)
603{
604 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800605 struct audio_usecase *uc_info;
606 struct audio_device *adev = out->dev;
607
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700608 ALOGD("%s: enter: usecase(%d: %s)", __func__,
609 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800610 uc_info = get_usecase_from_list(adev, out->usecase);
611 if (uc_info == NULL) {
612 ALOGE("%s: Could not find the usecase (%d) in the list",
613 __func__, out->usecase);
614 return -EINVAL;
615 }
616
Eric Laurent150dbfe2013-02-27 14:31:02 -0800617 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700618 disable_audio_route(adev, uc_info, true);
619
620 /* 2. Disable the rx device */
621 disable_snd_device(adev, uc_info->out_snd_device, true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800622
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800623 list_remove(&uc_info->list);
624 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800625
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700626 ALOGD("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800627 return ret;
628}
629
630int start_output_stream(struct stream_out *out)
631{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800632 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800633 struct audio_usecase *uc_info;
634 struct audio_device *adev = out->dev;
635
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700636 ALOGD("%s: enter: usecase(%d: %s) devices(%#x)",
637 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Eric Laurentb23d5282013-05-14 15:27:20 -0700638 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800639 if (out->pcm_device_id < 0) {
640 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
641 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800642 ret = -EINVAL;
643 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800644 }
645
646 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
647 uc_info->id = out->usecase;
648 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800649 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700650 uc_info->devices = out->devices;
651 uc_info->in_snd_device = SND_DEVICE_NONE;
652 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800653
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800654 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800655
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700656 select_devices(adev, out->usecase);
657
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800658 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
659 __func__, 0, out->pcm_device_id);
660 out->pcm = pcm_open(SOUND_CARD, out->pcm_device_id,
661 PCM_OUT, &out->config);
662 if (out->pcm && !pcm_is_ready(out->pcm)) {
663 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
664 pcm_close(out->pcm);
665 out->pcm = NULL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800666 ret = -EIO;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700667 goto error_pcm_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800668 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800669 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800670 return 0;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671error_pcm_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800672 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800673error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800674 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800675}
676
677static int stop_voice_call(struct audio_device *adev)
678{
679 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800680 struct audio_usecase *uc_info;
681
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800682 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -0800683 adev->in_call = false;
Eric Laurentb23d5282013-05-14 15:27:20 -0700684
685 ret = platform_stop_voice_call(adev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800686
687 /* 1. Close the PCM devices */
688 if (adev->voice_call_rx) {
689 pcm_close(adev->voice_call_rx);
690 adev->voice_call_rx = NULL;
691 }
692 if (adev->voice_call_tx) {
693 pcm_close(adev->voice_call_tx);
694 adev->voice_call_tx = NULL;
695 }
696
697 uc_info = get_usecase_from_list(adev, USECASE_VOICE_CALL);
698 if (uc_info == NULL) {
699 ALOGE("%s: Could not find the usecase (%d) in the list",
700 __func__, USECASE_VOICE_CALL);
701 return -EINVAL;
702 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800703
704 /* 2. Get and set stream specific mixer controls */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700705 disable_audio_route(adev, uc_info, true);
706
707 /* 3. Disable the rx and tx devices */
708 disable_snd_device(adev, uc_info->out_snd_device, false);
709 disable_snd_device(adev, uc_info->in_snd_device, true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800710
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800711 list_remove(&uc_info->list);
712 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800713
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800714 ALOGD("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800715 return ret;
716}
717
718static int start_voice_call(struct audio_device *adev)
719{
720 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800721 struct audio_usecase *uc_info;
722 int pcm_dev_rx_id, pcm_dev_tx_id;
723
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800724 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800725
726 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
727 uc_info->id = USECASE_VOICE_CALL;
728 uc_info->type = VOICE_CALL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800729 uc_info->stream.out = adev->primary_output;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700730 uc_info->devices = adev->primary_output->devices;
731 uc_info->in_snd_device = SND_DEVICE_NONE;
732 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800733
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800734 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800735
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700736 select_devices(adev, USECASE_VOICE_CALL);
737
Eric Laurentb23d5282013-05-14 15:27:20 -0700738 pcm_dev_rx_id = platform_get_pcm_device_id(uc_info->id, PCM_PLAYBACK);
739 pcm_dev_tx_id = platform_get_pcm_device_id(uc_info->id, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800741 if (pcm_dev_rx_id < 0 || pcm_dev_tx_id < 0) {
742 ALOGE("%s: Invalid PCM devices (rx: %d tx: %d) for the usecase(%d)",
743 __func__, pcm_dev_rx_id, pcm_dev_tx_id, uc_info->id);
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -0800744 ret = -EIO;
745 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800746 }
747
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -0800748 ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800749 __func__, SOUND_CARD, pcm_dev_rx_id);
750 adev->voice_call_rx = pcm_open(SOUND_CARD,
751 pcm_dev_rx_id,
752 PCM_OUT, &pcm_config_voice_call);
753 if (adev->voice_call_rx && !pcm_is_ready(adev->voice_call_rx)) {
754 ALOGE("%s: %s", __func__, pcm_get_error(adev->voice_call_rx));
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -0800755 ret = -EIO;
756 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800757 }
758
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -0800759 ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760 __func__, SOUND_CARD, pcm_dev_tx_id);
761 adev->voice_call_tx = pcm_open(SOUND_CARD,
762 pcm_dev_tx_id,
763 PCM_IN, &pcm_config_voice_call);
764 if (adev->voice_call_tx && !pcm_is_ready(adev->voice_call_tx)) {
765 ALOGE("%s: %s", __func__, pcm_get_error(adev->voice_call_tx));
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -0800766 ret = -EIO;
767 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800768 }
769 pcm_start(adev->voice_call_rx);
770 pcm_start(adev->voice_call_tx);
771
Eric Laurentb23d5282013-05-14 15:27:20 -0700772 ret = platform_start_voice_call(adev->platform);
773 if (ret < 0) {
774 ALOGE("%s: platform_start_voice_call error %d\n", __func__, ret);
775 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776 }
777
778 adev->in_call = true;
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -0800779 return 0;
780
781error_start_voice:
782 stop_voice_call(adev);
783
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800784 ALOGD("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800785 return ret;
786}
787
788static int check_input_parameters(uint32_t sample_rate,
789 audio_format_t format,
790 int channel_count)
791{
792 if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
793
794 if ((channel_count < 1) || (channel_count > 2)) return -EINVAL;
795
796 switch (sample_rate) {
797 case 8000:
798 case 11025:
799 case 12000:
800 case 16000:
801 case 22050:
802 case 24000:
803 case 32000:
804 case 44100:
805 case 48000:
806 break;
807 default:
808 return -EINVAL;
809 }
810
811 return 0;
812}
813
814static size_t get_input_buffer_size(uint32_t sample_rate,
815 audio_format_t format,
816 int channel_count)
817{
818 size_t size = 0;
819
820 if (check_input_parameters(sample_rate, format, channel_count) != 0) return 0;
821
822 if (sample_rate == 8000 || sample_rate == 16000 || sample_rate == 32000) {
823 size = (sample_rate * 20) / 1000;
824 } else if (sample_rate == 11025 || sample_rate == 12000) {
825 size = 256;
826 } else if (sample_rate == 22050 || sample_rate == 24000) {
827 size = 512;
828 } else if (sample_rate == 44100 || sample_rate == 48000) {
829 size = 1024;
830 }
831
832 return size * sizeof(short) * channel_count;
833}
834
835static uint32_t out_get_sample_rate(const struct audio_stream *stream)
836{
837 struct stream_out *out = (struct stream_out *)stream;
838
839 return out->config.rate;
840}
841
842static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
843{
844 return -ENOSYS;
845}
846
847static size_t out_get_buffer_size(const struct audio_stream *stream)
848{
849 struct stream_out *out = (struct stream_out *)stream;
850
851 return out->config.period_size * audio_stream_frame_size(stream);
852}
853
854static uint32_t out_get_channels(const struct audio_stream *stream)
855{
856 struct stream_out *out = (struct stream_out *)stream;
857
858 return out->channel_mask;
859}
860
861static audio_format_t out_get_format(const struct audio_stream *stream)
862{
863 return AUDIO_FORMAT_PCM_16_BIT;
864}
865
866static int out_set_format(struct audio_stream *stream, audio_format_t format)
867{
868 return -ENOSYS;
869}
870
871static int out_standby(struct audio_stream *stream)
872{
873 struct stream_out *out = (struct stream_out *)stream;
874 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700875 ALOGD("%s: enter: usecase(%d: %s)", __func__,
876 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800877 pthread_mutex_lock(&out->lock);
878
879 if (!out->standby) {
880 out->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -0800881 if (out->pcm) {
882 pcm_close(out->pcm);
883 out->pcm = NULL;
884 }
885 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800886 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -0800887 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800888 }
889 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800890 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800891 return 0;
892}
893
894static int out_dump(const struct audio_stream *stream, int fd)
895{
896 return 0;
897}
898
899static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
900{
901 struct stream_out *out = (struct stream_out *)stream;
902 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800903 struct audio_usecase *usecase;
904 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800905 struct str_parms *parms;
906 char value[32];
907 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800908 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800909
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700910 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
911 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800912 parms = str_parms_create_str(kvpairs);
913 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
914 if (ret >= 0) {
915 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800916 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -0800917 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800918
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700919 /*
920 * When HDMI cable is unplugged the music playback is paused and
921 * the policy manager sends routing=0. But the audioflinger
922 * continues to write data until standby time (3sec).
923 * As the HDMI core is turned off, the write gets blocked.
924 * Avoid this by routing audio to speaker until standby.
925 */
926 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
927 val == AUDIO_DEVICE_NONE) {
928 val = AUDIO_DEVICE_OUT_SPEAKER;
929 }
930
931 /*
932 * select_devices() call below switches all the usecases on the same
933 * backend to the new device. Refer to check_usecases_codec_backend() in
934 * the select_devices(). But how do we undo this?
935 *
936 * For example, music playback is active on headset (deep-buffer usecase)
937 * and if we go to ringtones and select a ringtone, low-latency usecase
938 * will be started on headset+speaker. As we can't enable headset+speaker
939 * and headset devices at the same time, select_devices() switches the music
940 * playback to headset+speaker while starting low-lateny usecase for ringtone.
941 * So when the ringtone playback is completed, how do we undo the same?
942 *
943 * We are relying on the out_set_parameters() call on deep-buffer output,
944 * once the ringtone playback is ended.
945 * NOTE: We should not check if the current devices are same as new devices.
946 * Because select_devices() must be called to switch back the music
947 * playback to headset.
948 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800949 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700950 out->devices = val;
951
952 if (!out->standby)
953 select_devices(adev, out->usecase);
954
955 if ((adev->mode == AUDIO_MODE_IN_CALL) && !adev->in_call &&
956 (out == adev->primary_output)) {
957 start_voice_call(adev);
958 } else if ((adev->mode == AUDIO_MODE_IN_CALL) && adev->in_call &&
959 (out == adev->primary_output)) {
960 select_devices(adev, USECASE_VOICE_CALL);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800961 }
962 }
963
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700964 if ((adev->mode != AUDIO_MODE_IN_CALL) && adev->in_call &&
965 (out == adev->primary_output)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800966 stop_voice_call(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800967 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800968
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800969 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -0800970 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800971 }
972 str_parms_destroy(parms);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800973 ALOGD("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800974 return ret;
975}
976
977static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
978{
979 struct stream_out *out = (struct stream_out *)stream;
980 struct str_parms *query = str_parms_create_str(keys);
981 char *str;
982 char value[256];
983 struct str_parms *reply = str_parms_create();
984 size_t i, j;
985 int ret;
986 bool first = true;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800987 ALOGD("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800988 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
989 if (ret >= 0) {
990 value[0] = '\0';
991 i = 0;
992 while (out->supported_channel_masks[i] != 0) {
993 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
994 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
995 if (!first) {
996 strcat(value, "|");
997 }
998 strcat(value, out_channels_name_to_enum_table[j].name);
999 first = false;
1000 break;
1001 }
1002 }
1003 i++;
1004 }
1005 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1006 str = str_parms_to_str(reply);
1007 } else {
1008 str = strdup(keys);
1009 }
1010 str_parms_destroy(query);
1011 str_parms_destroy(reply);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001012 ALOGD("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001013 return str;
1014}
1015
1016static uint32_t out_get_latency(const struct audio_stream_out *stream)
1017{
1018 struct stream_out *out = (struct stream_out *)stream;
1019
1020 return (out->config.period_count * out->config.period_size * 1000) / (out->config.rate);
1021}
1022
1023static int out_set_volume(struct audio_stream_out *stream, float left,
1024 float right)
1025{
Eric Laurenta9024de2013-04-04 09:19:12 -07001026 struct stream_out *out = (struct stream_out *)stream;
1027 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1028 /* only take left channel into account: the API is for stereo anyway */
1029 out->muted = (left == 0.0f);
1030 return 0;
1031 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001032 return -ENOSYS;
1033}
1034
1035static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
1036 size_t bytes)
1037{
1038 struct stream_out *out = (struct stream_out *)stream;
1039 struct audio_device *adev = out->dev;
1040 int i, ret = -1;
1041
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001042 pthread_mutex_lock(&out->lock);
1043 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001044 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001045 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001047 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001048 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001049 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001050 goto exit;
1051 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001052 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001053
1054 if (out->pcm) {
Eric Laurenta9024de2013-04-04 09:19:12 -07001055 if (out->muted)
1056 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001057 //ALOGV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
1058 ret = pcm_write(out->pcm, (void *)buffer, bytes);
1059 }
1060
1061exit:
1062 pthread_mutex_unlock(&out->lock);
1063
1064 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001065 if (out->pcm)
1066 ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001067 out_standby(&out->stream.common);
1068 usleep(bytes * 1000000 / audio_stream_frame_size(&out->stream.common) /
1069 out_get_sample_rate(&out->stream.common));
1070 }
1071 return bytes;
1072}
1073
1074static int out_get_render_position(const struct audio_stream_out *stream,
1075 uint32_t *dsp_frames)
1076{
1077 return -EINVAL;
1078}
1079
1080static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1081{
1082 return 0;
1083}
1084
1085static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1086{
1087 return 0;
1088}
1089
1090static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
1091 int64_t *timestamp)
1092{
1093 return -EINVAL;
1094}
1095
1096/** audio_stream_in implementation **/
1097static uint32_t in_get_sample_rate(const struct audio_stream *stream)
1098{
1099 struct stream_in *in = (struct stream_in *)stream;
1100
1101 return in->config.rate;
1102}
1103
1104static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1105{
1106 return -ENOSYS;
1107}
1108
1109static size_t in_get_buffer_size(const struct audio_stream *stream)
1110{
1111 struct stream_in *in = (struct stream_in *)stream;
1112
1113 return in->config.period_size * audio_stream_frame_size(stream);
1114}
1115
1116static uint32_t in_get_channels(const struct audio_stream *stream)
1117{
1118 struct stream_in *in = (struct stream_in *)stream;
1119
1120 return in->channel_mask;
1121}
1122
1123static audio_format_t in_get_format(const struct audio_stream *stream)
1124{
1125 return AUDIO_FORMAT_PCM_16_BIT;
1126}
1127
1128static int in_set_format(struct audio_stream *stream, audio_format_t format)
1129{
1130 return -ENOSYS;
1131}
1132
1133static int in_standby(struct audio_stream *stream)
1134{
1135 struct stream_in *in = (struct stream_in *)stream;
1136 struct audio_device *adev = in->dev;
1137 int status = 0;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001138 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001139 pthread_mutex_lock(&in->lock);
1140 if (!in->standby) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001141 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001142 if (in->pcm) {
1143 pcm_close(in->pcm);
1144 in->pcm = NULL;
1145 }
1146 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001147 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001148 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001149 }
1150 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001151 ALOGD("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001152 return status;
1153}
1154
1155static int in_dump(const struct audio_stream *stream, int fd)
1156{
1157 return 0;
1158}
1159
1160static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1161{
1162 struct stream_in *in = (struct stream_in *)stream;
1163 struct audio_device *adev = in->dev;
1164 struct str_parms *parms;
1165 char *str;
1166 char value[32];
1167 int ret, val = 0;
1168
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001169 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001170 parms = str_parms_create_str(kvpairs);
1171
1172 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
1173
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001174 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001175 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001176 if (ret >= 0) {
1177 val = atoi(value);
1178 /* no audio source uses val == 0 */
1179 if ((in->source != val) && (val != 0)) {
1180 in->source = val;
1181 }
1182 }
1183
1184 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1185 if (ret >= 0) {
1186 val = atoi(value);
1187 if ((in->device != val) && (val != 0)) {
1188 in->device = val;
1189 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001190 if (!in->standby)
1191 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001192 }
1193 }
1194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001195 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001196 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001197
1198 str_parms_destroy(parms);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001199 ALOGD("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001200 return ret;
1201}
1202
1203static char* in_get_parameters(const struct audio_stream *stream,
1204 const char *keys)
1205{
1206 return strdup("");
1207}
1208
1209static int in_set_gain(struct audio_stream_in *stream, float gain)
1210{
1211 return 0;
1212}
1213
1214static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
1215 size_t bytes)
1216{
1217 struct stream_in *in = (struct stream_in *)stream;
1218 struct audio_device *adev = in->dev;
1219 int i, ret = -1;
1220
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001221 pthread_mutex_lock(&in->lock);
1222 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001223 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001224 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001225 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001226 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001227 goto exit;
1228 }
1229 in->standby = 0;
1230 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001231
1232 if (in->pcm) {
1233 ret = pcm_read(in->pcm, buffer, bytes);
1234 }
1235
1236 /*
1237 * Instead of writing zeroes here, we could trust the hardware
1238 * to always provide zeroes when muted.
1239 */
1240 if (ret == 0 && adev->mic_mute)
1241 memset(buffer, 0, bytes);
1242
1243exit:
1244 pthread_mutex_unlock(&in->lock);
1245
1246 if (ret != 0) {
1247 in_standby(&in->stream.common);
1248 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
1249 usleep(bytes * 1000000 / audio_stream_frame_size(&in->stream.common) /
1250 in_get_sample_rate(&in->stream.common));
1251 }
1252 return bytes;
1253}
1254
1255static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1256{
1257 return 0;
1258}
1259
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001260static int add_remove_audio_effect(const struct audio_stream *stream,
1261 effect_handle_t effect,
1262 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001263{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001264 struct stream_in *in = (struct stream_in *)stream;
1265 int status = 0;
1266 effect_descriptor_t desc;
1267
1268 status = (*effect)->get_descriptor(effect, &desc);
1269 if (status != 0)
1270 return status;
1271
1272 pthread_mutex_lock(&in->lock);
1273 pthread_mutex_lock(&in->dev->lock);
1274 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
1275 in->enable_aec != enable &&
1276 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
1277 in->enable_aec = enable;
1278 if (!in->standby)
1279 select_devices(in->dev, in->usecase);
1280 }
1281 pthread_mutex_unlock(&in->dev->lock);
1282 pthread_mutex_unlock(&in->lock);
1283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001284 return 0;
1285}
1286
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001287static int in_add_audio_effect(const struct audio_stream *stream,
1288 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001289{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001290 ALOGD("%s: effect %p", __func__, effect);
1291 return add_remove_audio_effect(stream, effect, true);
1292}
1293
1294static int in_remove_audio_effect(const struct audio_stream *stream,
1295 effect_handle_t effect)
1296{
1297 ALOGD("%s: effect %p", __func__, effect);
1298 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001299}
1300
1301static int adev_open_output_stream(struct audio_hw_device *dev,
1302 audio_io_handle_t handle,
1303 audio_devices_t devices,
1304 audio_output_flags_t flags,
1305 struct audio_config *config,
1306 struct audio_stream_out **stream_out)
1307{
1308 struct audio_device *adev = (struct audio_device *)dev;
1309 struct stream_out *out;
1310 int i, ret;
1311
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001312 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001313 __func__, config->sample_rate, config->channel_mask, devices, flags);
1314 *stream_out = NULL;
1315 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
1316
1317 if (devices == AUDIO_DEVICE_NONE)
1318 devices = AUDIO_DEVICE_OUT_SPEAKER;
1319
1320 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
1321 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
1322 out->flags = flags;
1323 out->devices = devices;
1324
1325 /* Init use case and pcm_config */
1326 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
1327 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001328 pthread_mutex_lock(&adev->lock);
1329 ret = read_hdmi_channel_masks(out);
1330 pthread_mutex_unlock(&adev->lock);
1331 if (ret != 0) {
1332 /* If HDMI does not support multi channel playback, set the default */
1333 out->config.channels = popcount(out->channel_mask);
Eric Laurentb23d5282013-05-14 15:27:20 -07001334 platform_set_hdmi_channels(adev->platform, out->config.channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001335 goto error_open;
1336 }
1337
1338 if (config->sample_rate == 0)
1339 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1340 if (config->channel_mask == 0)
1341 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
1342
1343 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
1345 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001346 out->config.rate = config->sample_rate;
1347 out->config.channels = popcount(out->channel_mask);
1348 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Eric Laurentb23d5282013-05-14 15:27:20 -07001349 platform_set_hdmi_channels(adev->platform, out->config.channels);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001350 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
1351 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
1352 out->config = pcm_config_deep_buffer;
1353 } else {
1354 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
1355 out->config = pcm_config_low_latency;
1356 }
1357
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001358 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
1359 if(adev->primary_output == NULL)
1360 adev->primary_output = out;
1361 else {
1362 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001363 ret = -EEXIST;
1364 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001365 }
1366 }
1367
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001368 /* Check if this usecase is already existing */
1369 pthread_mutex_lock(&adev->lock);
1370 if (get_usecase_from_list(adev, out->usecase) != NULL) {
1371 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001373 ret = -EEXIST;
1374 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001375 }
1376 pthread_mutex_unlock(&adev->lock);
1377
1378 out->stream.common.get_sample_rate = out_get_sample_rate;
1379 out->stream.common.set_sample_rate = out_set_sample_rate;
1380 out->stream.common.get_buffer_size = out_get_buffer_size;
1381 out->stream.common.get_channels = out_get_channels;
1382 out->stream.common.get_format = out_get_format;
1383 out->stream.common.set_format = out_set_format;
1384 out->stream.common.standby = out_standby;
1385 out->stream.common.dump = out_dump;
1386 out->stream.common.set_parameters = out_set_parameters;
1387 out->stream.common.get_parameters = out_get_parameters;
1388 out->stream.common.add_audio_effect = out_add_audio_effect;
1389 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1390 out->stream.get_latency = out_get_latency;
1391 out->stream.set_volume = out_set_volume;
1392 out->stream.write = out_write;
1393 out->stream.get_render_position = out_get_render_position;
1394 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
1395
1396 out->dev = adev;
1397 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07001398 /* out->muted = false; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001399
1400 config->format = out->stream.common.get_format(&out->stream.common);
1401 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
1402 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
1403
1404 *stream_out = &out->stream;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001405 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001406 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001407
1408error_open:
1409 free(out);
1410 *stream_out = NULL;
1411 ALOGD("%s: exit: ret %d", __func__, ret);
1412 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001413}
1414
1415static void adev_close_output_stream(struct audio_hw_device *dev,
1416 struct audio_stream_out *stream)
1417{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001418 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001419 out_standby(&stream->common);
1420 free(stream);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001421 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001422}
1423
1424static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1425{
1426 struct audio_device *adev = (struct audio_device *)dev;
1427 struct str_parms *parms;
1428 char *str;
1429 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07001430 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001431 int ret;
1432
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001433 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001434
1435 parms = str_parms_create_str(kvpairs);
1436 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_TTY_MODE, value, sizeof(value));
1437 if (ret >= 0) {
1438 int tty_mode;
1439
1440 if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_OFF) == 0)
1441 tty_mode = TTY_MODE_OFF;
1442 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_VCO) == 0)
1443 tty_mode = TTY_MODE_VCO;
1444 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_HCO) == 0)
1445 tty_mode = TTY_MODE_HCO;
1446 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_FULL) == 0)
1447 tty_mode = TTY_MODE_FULL;
1448 else
1449 return -EINVAL;
1450
1451 pthread_mutex_lock(&adev->lock);
1452 if (tty_mode != adev->tty_mode) {
1453 adev->tty_mode = tty_mode;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08001454 adev->acdb_settings = (adev->acdb_settings & TTY_MODE_CLEAR) | tty_mode;
1455 if (adev->in_call)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001456 select_devices(adev, USECASE_VOICE_CALL);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001457 }
1458 pthread_mutex_unlock(&adev->lock);
1459 }
1460
1461 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
1462 if (ret >= 0) {
1463 /* When set to false, HAL should disable EC and NS
1464 * But it is currently not supported.
1465 */
1466 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
1467 adev->bluetooth_nrec = true;
1468 else
1469 adev->bluetooth_nrec = false;
1470 }
1471
1472 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
1473 if (ret >= 0) {
1474 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
1475 adev->screen_off = false;
1476 else
1477 adev->screen_off = true;
1478 }
1479
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07001480 ret = str_parms_get_int(parms, "rotation", &val);
1481 if (ret >= 0) {
1482 bool reverse_speakers = false;
1483 switch(val) {
1484 // FIXME: note that the code below assumes that the speakers are in the correct placement
1485 // relative to the user when the device is rotated 90deg from its default rotation. This
1486 // assumption is device-specific, not platform-specific like this code.
1487 case 270:
1488 reverse_speakers = true;
1489 break;
1490 case 0:
1491 case 90:
1492 case 180:
1493 break;
1494 default:
1495 ALOGE("%s: unexpected rotation of %d", __func__, val);
1496 }
1497 pthread_mutex_lock(&adev->lock);
1498 if (adev->speaker_lr_swap != reverse_speakers) {
1499 adev->speaker_lr_swap = reverse_speakers;
1500 // only update the selected device if there is active pcm playback
1501 struct audio_usecase *usecase;
1502 struct listnode *node;
1503 list_for_each(node, &adev->usecase_list) {
1504 usecase = node_to_item(node, struct audio_usecase, list);
1505 if (usecase->type == PCM_PLAYBACK) {
1506 select_devices(adev, usecase->id);
1507 break;
1508 }
1509 }
1510 }
1511 pthread_mutex_unlock(&adev->lock);
1512 }
1513
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001514 str_parms_destroy(parms);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001515 ALOGD("%s: exit with code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001516 return ret;
1517}
1518
1519static char* adev_get_parameters(const struct audio_hw_device *dev,
1520 const char *keys)
1521{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001522 return strdup("");
1523}
1524
1525static int adev_init_check(const struct audio_hw_device *dev)
1526{
1527 return 0;
1528}
1529
1530static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1531{
1532 struct audio_device *adev = (struct audio_device *)dev;
1533 int vol, err = 0;
1534
1535 pthread_mutex_lock(&adev->lock);
1536 adev->voice_volume = volume;
1537 if (adev->mode == AUDIO_MODE_IN_CALL) {
1538 if (volume < 0.0) {
1539 volume = 0.0;
1540 } else if (volume > 1.0) {
1541 volume = 1.0;
1542 }
1543
1544 vol = lrint(volume * 100.0);
1545
1546 // Voice volume levels from android are mapped to driver volume levels as follows.
1547 // 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0
1548 // So adjust the volume to get the correct volume index in driver
1549 vol = 100 - vol;
Eric Laurentb23d5282013-05-14 15:27:20 -07001550
1551 err = platform_set_voice_volume(adev->platform, vol);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552 }
1553 pthread_mutex_unlock(&adev->lock);
1554 return err;
1555}
1556
1557static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1558{
1559 return -ENOSYS;
1560}
1561
1562static int adev_get_master_volume(struct audio_hw_device *dev,
1563 float *volume)
1564{
1565 return -ENOSYS;
1566}
1567
1568static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
1569{
1570 return -ENOSYS;
1571}
1572
1573static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
1574{
1575 return -ENOSYS;
1576}
1577
1578static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1579{
1580 struct audio_device *adev = (struct audio_device *)dev;
1581
1582 pthread_mutex_lock(&adev->lock);
1583 if (adev->mode != mode) {
1584 adev->mode = mode;
1585 }
1586 pthread_mutex_unlock(&adev->lock);
1587 return 0;
1588}
1589
1590static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1591{
1592 struct audio_device *adev = (struct audio_device *)dev;
1593 int err = 0;
1594
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001595 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001596 adev->mic_mute = state;
Eric Laurentb23d5282013-05-14 15:27:20 -07001597
1598 err = platform_set_mic_mute(adev->platform, state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001599 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001600 return err;
1601}
1602
1603static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1604{
1605 struct audio_device *adev = (struct audio_device *)dev;
1606
1607 *state = adev->mic_mute;
1608
1609 return 0;
1610}
1611
1612static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1613 const struct audio_config *config)
1614{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001615 int channel_count = popcount(config->channel_mask);
1616
1617 return get_input_buffer_size(config->sample_rate, config->format, channel_count);
1618}
1619
1620static int adev_open_input_stream(struct audio_hw_device *dev,
1621 audio_io_handle_t handle,
1622 audio_devices_t devices,
1623 struct audio_config *config,
1624 struct audio_stream_in **stream_in)
1625{
1626 struct audio_device *adev = (struct audio_device *)dev;
1627 struct stream_in *in;
1628 int ret, buffer_size, frame_size;
1629 int channel_count = popcount(config->channel_mask);
1630
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001631 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632 *stream_in = NULL;
1633 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
1634 return -EINVAL;
1635
1636 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
1637
1638 in->stream.common.get_sample_rate = in_get_sample_rate;
1639 in->stream.common.set_sample_rate = in_set_sample_rate;
1640 in->stream.common.get_buffer_size = in_get_buffer_size;
1641 in->stream.common.get_channels = in_get_channels;
1642 in->stream.common.get_format = in_get_format;
1643 in->stream.common.set_format = in_set_format;
1644 in->stream.common.standby = in_standby;
1645 in->stream.common.dump = in_dump;
1646 in->stream.common.set_parameters = in_set_parameters;
1647 in->stream.common.get_parameters = in_get_parameters;
1648 in->stream.common.add_audio_effect = in_add_audio_effect;
1649 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1650 in->stream.set_gain = in_set_gain;
1651 in->stream.read = in_read;
1652 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1653
1654 in->device = devices;
1655 in->source = AUDIO_SOURCE_DEFAULT;
1656 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657 in->standby = 1;
1658 in->channel_mask = config->channel_mask;
1659
1660 /* Update config params with the requested sample rate and channels */
1661 in->usecase = USECASE_AUDIO_RECORD;
1662 in->config = pcm_config_audio_capture;
1663 in->config.channels = channel_count;
1664 in->config.rate = config->sample_rate;
1665
1666 frame_size = audio_stream_frame_size((struct audio_stream *)in);
1667 buffer_size = get_input_buffer_size(config->sample_rate,
1668 config->format,
1669 channel_count);
1670 in->config.period_size = buffer_size / frame_size;
1671
1672 *stream_in = &in->stream;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001673 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674 return 0;
1675
1676err_open:
1677 free(in);
1678 *stream_in = NULL;
1679 return ret;
1680}
1681
1682static void adev_close_input_stream(struct audio_hw_device *dev,
1683 struct audio_stream_in *stream)
1684{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001685 ALOGD("%s", __func__);
1686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001687 in_standby(&stream->common);
1688 free(stream);
1689
1690 return;
1691}
1692
1693static int adev_dump(const audio_hw_device_t *device, int fd)
1694{
1695 return 0;
1696}
1697
1698static int adev_close(hw_device_t *device)
1699{
1700 struct audio_device *adev = (struct audio_device *)device;
1701 audio_route_free(adev->audio_route);
Eric Laurentb23d5282013-05-14 15:27:20 -07001702 free(adev->snd_dev_ref_cnt);
1703 platform_deinit(adev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001704 free(device);
1705 return 0;
1706}
1707
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708static int adev_open(const hw_module_t *module, const char *name,
1709 hw_device_t **device)
1710{
1711 struct audio_device *adev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001712 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001714 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001715 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
1716
1717 adev = calloc(1, sizeof(struct audio_device));
1718
1719 adev->mixer = mixer_open(MIXER_CARD);
1720 if (!adev->mixer) {
1721 ALOGE("Unable to open the mixer, aborting.");
1722 return -ENOSYS;
1723 }
1724
1725 adev->audio_route = audio_route_init(MIXER_CARD, MIXER_XML_PATH);
1726 if (!adev->audio_route) {
1727 free(adev);
1728 ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
1729 *device = NULL;
1730 return -EINVAL;
1731 }
1732
1733 adev->device.common.tag = HARDWARE_DEVICE_TAG;
1734 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
1735 adev->device.common.module = (struct hw_module_t *)module;
1736 adev->device.common.close = adev_close;
1737
1738 adev->device.init_check = adev_init_check;
1739 adev->device.set_voice_volume = adev_set_voice_volume;
1740 adev->device.set_master_volume = adev_set_master_volume;
1741 adev->device.get_master_volume = adev_get_master_volume;
1742 adev->device.set_master_mute = adev_set_master_mute;
1743 adev->device.get_master_mute = adev_get_master_mute;
1744 adev->device.set_mode = adev_set_mode;
1745 adev->device.set_mic_mute = adev_set_mic_mute;
1746 adev->device.get_mic_mute = adev_get_mic_mute;
1747 adev->device.set_parameters = adev_set_parameters;
1748 adev->device.get_parameters = adev_get_parameters;
1749 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
1750 adev->device.open_output_stream = adev_open_output_stream;
1751 adev->device.close_output_stream = adev_close_output_stream;
1752 adev->device.open_input_stream = adev_open_input_stream;
1753 adev->device.close_input_stream = adev_close_input_stream;
1754 adev->device.dump = adev_dump;
1755
1756 /* Set the default route before the PCM stream is opened */
1757 pthread_mutex_lock(&adev->lock);
1758 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08001759 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001760 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001761 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001762 adev->voice_call_rx = NULL;
1763 adev->voice_call_tx = NULL;
1764 adev->voice_volume = 1.0f;
1765 adev->tty_mode = TTY_MODE_OFF;
1766 adev->bluetooth_nrec = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001767 adev->in_call = false;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08001768 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurentb23d5282013-05-14 15:27:20 -07001769 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001770 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771 pthread_mutex_unlock(&adev->lock);
1772
1773 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07001774 adev->platform = platform_init(adev);
1775 if (!adev->platform) {
1776 free(adev->snd_dev_ref_cnt);
1777 free(adev);
1778 ALOGE("%s: Failed to init platform data, aborting.", __func__);
1779 *device = NULL;
1780 return -EINVAL;
1781 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782 *device = &adev->device.common;
1783
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001784 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785 return 0;
1786}
1787
1788static struct hw_module_methods_t hal_module_methods = {
1789 .open = adev_open,
1790};
1791
1792struct audio_module HAL_MODULE_INFO_SYM = {
1793 .common = {
1794 .tag = HARDWARE_MODULE_TAG,
1795 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1796 .hal_api_version = HARDWARE_HAL_API_VERSION,
1797 .id = AUDIO_HARDWARE_MODULE_ID,
1798 .name = "QCOM Audio HAL",
1799 .author = "Code Aurora Forum",
1800 .methods = &hal_module_methods,
1801 },
1802};