blob: abda10c78c95e958d3cd17bd7af29bdd964d2d01 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07002 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
3 * Not a Contribution.
4 *
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005 * Copyright (C) 2013 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#define LOG_TAG "audio_hw_primary"
21/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080022#define LOG_NDDEBUG 0
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080023
24#include <errno.h>
25#include <pthread.h>
26#include <stdint.h>
27#include <sys/time.h>
28#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080029#include <math.h>
30
31#include <cutils/log.h>
32#include <cutils/str_parms.h>
33#include <cutils/properties.h>
34
Eric Laurentb23d5282013-05-14 15:27:20 -070035#include <hardware/audio_effect.h>
36#include <audio_effects/effect_aec.h>
37#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080038#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070039#include "platform_api.h"
40#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070041#include "audio_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080042
Eric Laurentb23d5282013-05-14 15:27:20 -070043struct pcm_config pcm_config_deep_buffer = {
44 .channels = 2,
45 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
46 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
47 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
48 .format = PCM_FORMAT_S16_LE,
49 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
50 .stop_threshold = INT_MAX,
51 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
52};
53
54struct pcm_config pcm_config_low_latency = {
55 .channels = 2,
56 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
57 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
58 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
59 .format = PCM_FORMAT_S16_LE,
60 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
61 .stop_threshold = INT_MAX,
62 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
63};
64
65struct pcm_config pcm_config_hdmi_multi = {
66 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
67 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
68 .period_size = HDMI_MULTI_PERIOD_SIZE,
69 .period_count = HDMI_MULTI_PERIOD_COUNT,
70 .format = PCM_FORMAT_S16_LE,
71 .start_threshold = 0,
72 .stop_threshold = INT_MAX,
73 .avail_min = 0,
74};
75
76struct pcm_config pcm_config_audio_capture = {
77 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -070078 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
79 .format = PCM_FORMAT_S16_LE,
80};
81
Eric Laurentb23d5282013-05-14 15:27:20 -070082static const char * const use_case_table[AUDIO_USECASE_MAX] = {
83 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
84 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
85 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
86 [USECASE_AUDIO_RECORD] = "audio-record",
87 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070088 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070089 [USECASE_VOICE_CALL] = "voice-call",
90 [USECASE_VOICE2_CALL] = "voice2-call",
91 [USECASE_VOLTE_CALL] = "volte-call",
92 [USECASE_QCHAT_CALL] = "qchat-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -070093 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
94 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
95 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Eric Laurentb23d5282013-05-14 15:27:20 -070096};
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
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700112static struct audio_device *adev = NULL;
113static pthread_mutex_t adev_init_lock;
114static bool is_adev_initialised = false;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800115
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700116static int enable_audio_route(struct audio_device *adev,
117 struct audio_usecase *usecase,
118 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800119{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700120 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700121 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800122
123 if (usecase == NULL)
124 return -EINVAL;
125
126 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
127
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800128 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700129 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800130 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700131 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800132
133 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700134 platform_add_backend_name(mixer_path, snd_device);
Eric Laurent994a6932013-07-17 11:51:42 -0700135 ALOGV("%s: apply mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700136 audio_route_apply_path(adev->audio_route, mixer_path);
137 if (update_mixer)
138 audio_route_update_mixer(adev->audio_route);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800140 ALOGV("%s: exit", __func__);
141 return 0;
142}
143
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700144int disable_audio_route(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700145 struct audio_usecase *usecase,
146 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800147{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700148 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700149 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800150
151 if (usecase == NULL)
152 return -EINVAL;
153
154 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700155 if (usecase->type == PCM_CAPTURE)
156 snd_device = usecase->in_snd_device;
157 else
158 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800159 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700160 platform_add_backend_name(mixer_path, snd_device);
Eric Laurent994a6932013-07-17 11:51:42 -0700161 ALOGV("%s: reset mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700162 audio_route_reset_path(adev->audio_route, mixer_path);
163 if (update_mixer)
164 audio_route_update_mixer(adev->audio_route);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800165
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800166 ALOGV("%s: exit", __func__);
167 return 0;
168}
169
170static int enable_snd_device(struct audio_device *adev,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700171 snd_device_t snd_device,
172 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800173{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800174 if (snd_device < SND_DEVICE_MIN ||
175 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800176 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800177 return -EINVAL;
178 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700179
180 adev->snd_dev_ref_cnt[snd_device]++;
181 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700182 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700183 __func__, snd_device, platform_get_snd_device_name(snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700184 return 0;
185 }
186
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700187 /* start usb playback thread */
188 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
189 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
190 audio_extn_usb_start_playback(adev);
191
192 /* start usb capture thread */
193 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
194 audio_extn_usb_start_capture(adev);
195
Eric Laurentb23d5282013-05-14 15:27:20 -0700196 if (platform_send_audio_calibration(adev->platform, snd_device) < 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700197 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800198 return -EINVAL;
199 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800200
Eric Laurent994a6932013-07-17 11:51:42 -0700201 ALOGV("%s: snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700202 snd_device, platform_get_snd_device_name(snd_device));
203 audio_route_apply_path(adev->audio_route, platform_get_snd_device_name(snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700204 if (update_mixer)
205 audio_route_update_mixer(adev->audio_route);
206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800207 return 0;
208}
209
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700210int disable_snd_device(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700211 snd_device_t snd_device,
212 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800213{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800214 if (snd_device < SND_DEVICE_MIN ||
215 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800216 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800217 return -EINVAL;
218 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700219 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
220 ALOGE("%s: device ref cnt is already 0", __func__);
221 return -EINVAL;
222 }
223 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700224
225 /* exit usb play back thread */
226 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
227 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
228 audio_extn_usb_stop_playback();
229
230 /* exit usb capture thread */
231 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
232 audio_extn_usb_stop_capture(adev);
233
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700234 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700235 ALOGV("%s: snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700236 snd_device, platform_get_snd_device_name(snd_device));
237 audio_route_reset_path(adev->audio_route, platform_get_snd_device_name(snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700238 if (update_mixer)
239 audio_route_update_mixer(adev->audio_route);
240 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800241 return 0;
242}
243
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700244static void check_usecases_codec_backend(struct audio_device *adev,
245 struct audio_usecase *uc_info,
246 snd_device_t snd_device)
247{
248 struct listnode *node;
249 struct audio_usecase *usecase;
250 bool switch_device[AUDIO_USECASE_MAX];
251 int i, num_uc_to_switch = 0;
252
253 /*
254 * This function is to make sure that all the usecases that are active on
255 * the hardware codec backend are always routed to any one device that is
256 * handled by the hardware codec.
257 * For example, if low-latency and deep-buffer usecases are currently active
258 * on speaker and out_set_parameters(headset) is received on low-latency
259 * output, then we have to make sure deep-buffer is also switched to headset,
260 * because of the limitation that both the devices cannot be enabled
261 * at the same time as they share the same backend.
262 */
263 /* Disable all the usecases on the shared backend other than the
264 specified usecase */
265 for (i = 0; i < AUDIO_USECASE_MAX; i++)
266 switch_device[i] = false;
267
268 list_for_each(node, &adev->usecase_list) {
269 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700270 if (usecase->type == PCM_PLAYBACK &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700271 usecase != uc_info &&
272 usecase->out_snd_device != snd_device &&
273 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
274 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
275 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700276 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700277 disable_audio_route(adev, usecase, false);
278 switch_device[usecase->id] = true;
279 num_uc_to_switch++;
280 }
281 }
282
283 if (num_uc_to_switch) {
284 /* Make sure all the streams are de-routed before disabling the device */
285 audio_route_update_mixer(adev->audio_route);
286
287 list_for_each(node, &adev->usecase_list) {
288 usecase = node_to_item(node, struct audio_usecase, list);
289 if (switch_device[usecase->id]) {
290 disable_snd_device(adev, usecase->out_snd_device, false);
291 enable_snd_device(adev, snd_device, false);
292 }
293 }
294
295 /* Make sure new snd device is enabled before re-routing the streams */
296 audio_route_update_mixer(adev->audio_route);
297
298 /* Re-route all the usecases on the shared backend other than the
299 specified usecase to new snd devices */
300 list_for_each(node, &adev->usecase_list) {
301 usecase = node_to_item(node, struct audio_usecase, list);
302 /* Update the out_snd_device only before enabling the audio route */
303 if (switch_device[usecase->id] ) {
304 usecase->out_snd_device = snd_device;
305 enable_audio_route(adev, usecase, false);
306 }
307 }
308
309 audio_route_update_mixer(adev->audio_route);
310 }
311}
312
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700313static void check_and_route_capture_usecases(struct audio_device *adev,
314 struct audio_usecase *uc_info,
315 snd_device_t snd_device)
316{
317 struct listnode *node;
318 struct audio_usecase *usecase;
319 bool switch_device[AUDIO_USECASE_MAX];
320 int i, num_uc_to_switch = 0;
321
322 /*
323 * This function is to make sure that all the active capture usecases
324 * are always routed to the same input sound device.
325 * For example, if audio-record and voice-call usecases are currently
326 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
327 * is received for voice call then we have to make sure that audio-record
328 * usecase is also switched to earpiece i.e. voice-dmic-ef,
329 * because of the limitation that two devices cannot be enabled
330 * at the same time if they share the same backend.
331 */
332 for (i = 0; i < AUDIO_USECASE_MAX; i++)
333 switch_device[i] = false;
334
335 list_for_each(node, &adev->usecase_list) {
336 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700337 if (usecase->type == PCM_CAPTURE &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700338 usecase != uc_info &&
339 usecase->in_snd_device != snd_device) {
340 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
341 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700342 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700343 disable_audio_route(adev, usecase, false);
344 switch_device[usecase->id] = true;
345 num_uc_to_switch++;
346 }
347 }
348
349 if (num_uc_to_switch) {
350 /* Make sure all the streams are de-routed before disabling the device */
351 audio_route_update_mixer(adev->audio_route);
352
353 list_for_each(node, &adev->usecase_list) {
354 usecase = node_to_item(node, struct audio_usecase, list);
355 if (switch_device[usecase->id]) {
356 disable_snd_device(adev, usecase->in_snd_device, false);
357 enable_snd_device(adev, snd_device, false);
358 }
359 }
360
361 /* Make sure new snd device is enabled before re-routing the streams */
362 audio_route_update_mixer(adev->audio_route);
363
364 /* Re-route all the usecases on the shared backend other than the
365 specified usecase to new snd devices */
366 list_for_each(node, &adev->usecase_list) {
367 usecase = node_to_item(node, struct audio_usecase, list);
368 /* Update the in_snd_device only before enabling the audio route */
369 if (switch_device[usecase->id] ) {
370 usecase->in_snd_device = snd_device;
371 enable_audio_route(adev, usecase, false);
372 }
373 }
374
375 audio_route_update_mixer(adev->audio_route);
376 }
377}
378
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700379static int disable_all_usecases_of_type(struct audio_device *adev,
380 usecase_type_t usecase_type,
381 bool update_mixer)
382{
383 struct audio_usecase *usecase;
384 struct listnode *node;
385 int ret = 0;
386
387 list_for_each(node, &adev->usecase_list) {
388 usecase = node_to_item(node, struct audio_usecase, list);
389 if (usecase->type == usecase_type) {
390 ALOGV("%s: usecase id %d", __func__, usecase->id);
391 ret = disable_audio_route(adev, usecase, update_mixer);
392 if (ret) {
393 ALOGE("%s: Failed to disable usecase id %d",
394 __func__, usecase->id);
395 }
396 }
397 }
398
399 return ret;
400}
401
402static int enable_all_usecases_of_type(struct audio_device *adev,
403 usecase_type_t usecase_type,
404 bool update_mixer)
405{
406 struct audio_usecase *usecase;
407 struct listnode *node;
408 int ret = 0;
409
410 list_for_each(node, &adev->usecase_list) {
411 usecase = node_to_item(node, struct audio_usecase, list);
412 if (usecase->type == usecase_type) {
413 ALOGV("%s: usecase id %d", __func__, usecase->id);
414 ret = enable_audio_route(adev, usecase, update_mixer);
415 if (ret) {
416 ALOGE("%s: Failed to enable usecase id %d",
417 __func__, usecase->id);
418 }
419 }
420 }
421
422 return ret;
423}
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800424
425/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700426static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800427{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700428 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700429 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800430
431 switch (channels) {
432 /*
433 * Do not handle stereo output in Multi-channel cases
434 * Stereo case is handled in normal playback path
435 */
436 case 6:
437 ALOGV("%s: HDMI supports 5.1", __func__);
438 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
439 break;
440 case 8:
441 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
442 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
443 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
444 break;
445 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700446 ALOGE("HDMI does not support multi channel playback");
447 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800448 break;
449 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700450 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451}
452
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700453static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
454{
455 struct audio_usecase *usecase;
456 struct listnode *node;
457
458 list_for_each(node, &adev->usecase_list) {
459 usecase = node_to_item(node, struct audio_usecase, list);
460 if (usecase->type == VOICE_CALL) {
461 ALOGV("%s: usecase id %d", __func__, usecase->id);
462 return usecase->id;
463 }
464 }
465 return USECASE_INVALID;
466}
467
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700468struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700469 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700470{
471 struct audio_usecase *usecase;
472 struct listnode *node;
473
474 list_for_each(node, &adev->usecase_list) {
475 usecase = node_to_item(node, struct audio_usecase, list);
476 if (usecase->id == uc_id)
477 return usecase;
478 }
479 return NULL;
480}
481
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700482int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800483{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800484 snd_device_t out_snd_device = SND_DEVICE_NONE;
485 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700486 struct audio_usecase *usecase = NULL;
487 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800488 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700489 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800490
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700491 usecase = get_usecase_from_list(adev, uc_id);
492 if (usecase == NULL) {
493 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
494 return -EINVAL;
495 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800496
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700497 if (usecase->type == VOICE_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700498 out_snd_device = platform_get_output_snd_device(adev->platform,
499 usecase->stream.out->devices);
500 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700501 usecase->devices = usecase->stream.out->devices;
502 } else {
503 /*
504 * If the voice call is active, use the sound devices of voice call usecase
505 * so that it would not result any device switch. All the usecases will
506 * be switched to new device when select_devices() is called for voice call
507 * usecase. This is to avoid switching devices for voice call when
508 * check_usecases_codec_backend() is called below.
509 */
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700510 if (voice_is_in_call(adev)) {
511 vc_usecase = get_usecase_from_list(adev,
512 get_voice_usecase_id_from_list(adev));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700513 if (vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
514 in_snd_device = vc_usecase->in_snd_device;
515 out_snd_device = vc_usecase->out_snd_device;
516 }
517 }
518 if (usecase->type == PCM_PLAYBACK) {
519 usecase->devices = usecase->stream.out->devices;
520 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700521 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700522 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700523 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700524 if (usecase->stream.out == adev->primary_output &&
525 adev->active_input &&
526 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
527 select_devices(adev, adev->active_input->usecase);
528 }
529 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700530 } else if (usecase->type == PCM_CAPTURE) {
531 usecase->devices = usecase->stream.in->device;
532 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700533 if (in_snd_device == SND_DEVICE_NONE) {
534 if (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
535 adev->primary_output && !adev->primary_output->standby) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700536 in_snd_device = platform_get_input_snd_device(adev->platform,
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700537 adev->primary_output->devices);
538 } else {
Eric Laurentb23d5282013-05-14 15:27:20 -0700539 in_snd_device = platform_get_input_snd_device(adev->platform,
540 AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700541 }
542 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700543 }
544 }
545
546 if (out_snd_device == usecase->out_snd_device &&
547 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800548 return 0;
549 }
550
sangwoobc677242013-08-08 16:53:43 +0900551 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700552 out_snd_device, platform_get_snd_device_name(out_snd_device),
553 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800554
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800555 /*
556 * Limitation: While in call, to do a device switch we need to disable
557 * and enable both RX and TX devices though one of them is same as current
558 * device.
559 */
Eric Laurentb23d5282013-05-14 15:27:20 -0700560 if (usecase->type == VOICE_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700561 disable_all_usecases_of_type(adev, VOICE_CALL, true);
Eric Laurentb23d5282013-05-14 15:27:20 -0700562 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800563 }
564
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700565 /* Disable current sound devices */
566 if (usecase->out_snd_device != SND_DEVICE_NONE) {
567 disable_audio_route(adev, usecase, true);
568 disable_snd_device(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800569 }
570
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700571 if (usecase->in_snd_device != SND_DEVICE_NONE) {
572 disable_audio_route(adev, usecase, true);
573 disable_snd_device(adev, usecase->in_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800574 }
575
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700576 /* Enable new sound devices */
577 if (out_snd_device != SND_DEVICE_NONE) {
578 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
579 check_usecases_codec_backend(adev, usecase, out_snd_device);
580 enable_snd_device(adev, out_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800581 }
582
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700583 if (in_snd_device != SND_DEVICE_NONE) {
584 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700585 enable_snd_device(adev, in_snd_device, false);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700586 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700587
Eric Laurentb23d5282013-05-14 15:27:20 -0700588 if (usecase->type == VOICE_CALL)
589 status = platform_switch_voice_call_device_post(adev->platform,
590 out_snd_device,
591 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800592
sangwoo170731f2013-06-08 15:36:36 +0900593 audio_route_update_mixer(adev->audio_route);
594
595 usecase->in_snd_device = in_snd_device;
596 usecase->out_snd_device = out_snd_device;
597
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700598 if (usecase->type == VOICE_CALL)
599 enable_all_usecases_of_type(adev, VOICE_CALL, true);
600 else
601 enable_audio_route(adev, usecase, true);
sangwoo170731f2013-06-08 15:36:36 +0900602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800603 return status;
604}
605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800606static int stop_input_stream(struct stream_in *in)
607{
608 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800609 struct audio_usecase *uc_info;
610 struct audio_device *adev = in->dev;
611
Eric Laurentc8400632013-02-14 19:04:54 -0800612 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800613
Eric Laurent994a6932013-07-17 11:51:42 -0700614 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700615 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800616 uc_info = get_usecase_from_list(adev, in->usecase);
617 if (uc_info == NULL) {
618 ALOGE("%s: Could not find the usecase (%d) in the list",
619 __func__, in->usecase);
620 return -EINVAL;
621 }
622
Eric Laurent150dbfe2013-02-27 14:31:02 -0800623 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700624 disable_audio_route(adev, uc_info, true);
625
626 /* 2. Disable the tx device */
627 disable_snd_device(adev, uc_info->in_snd_device, true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800628
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800629 list_remove(&uc_info->list);
630 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800631
Eric Laurent994a6932013-07-17 11:51:42 -0700632 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800633 return ret;
634}
635
636int start_input_stream(struct stream_in *in)
637{
638 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800639 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800640 struct audio_usecase *uc_info;
641 struct audio_device *adev = in->dev;
642
Eric Laurent994a6932013-07-17 11:51:42 -0700643 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700644
645 /* Check if source matches incall recording usecase criteria */
646 ret = voice_check_and_set_incall_rec_usecase(adev, in);
647 if (ret)
648 goto error_config;
649 else
650 ALOGV("%s: usecase(%d)", __func__, in->usecase);
651
Eric Laurentb23d5282013-05-14 15:27:20 -0700652 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800653 if (in->pcm_device_id < 0) {
654 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
655 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -0800656 ret = -EINVAL;
657 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800658 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700659
660 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800661 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
662 uc_info->id = in->usecase;
663 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800664 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700665 uc_info->devices = in->device;
666 uc_info->in_snd_device = SND_DEVICE_NONE;
667 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800668
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800669 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700670 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800671
Eric Laurentc8400632013-02-14 19:04:54 -0800672 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
673 __func__, SOUND_CARD, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800674 in->pcm = pcm_open(SOUND_CARD, in->pcm_device_id,
675 PCM_IN, &in->config);
676 if (in->pcm && !pcm_is_ready(in->pcm)) {
677 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
678 pcm_close(in->pcm);
679 in->pcm = NULL;
Eric Laurentc8400632013-02-14 19:04:54 -0800680 ret = -EIO;
681 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800682 }
Eric Laurent994a6932013-07-17 11:51:42 -0700683 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -0800684 return ret;
685
686error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800687 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -0800688
689error_config:
690 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700691 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -0800692
693 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800694}
695
696static int stop_output_stream(struct stream_out *out)
697{
698 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800699 struct audio_usecase *uc_info;
700 struct audio_device *adev = out->dev;
701
Eric Laurent994a6932013-07-17 11:51:42 -0700702 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700703 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800704 uc_info = get_usecase_from_list(adev, out->usecase);
705 if (uc_info == NULL) {
706 ALOGE("%s: Could not find the usecase (%d) in the list",
707 __func__, out->usecase);
708 return -EINVAL;
709 }
710
Eric Laurent150dbfe2013-02-27 14:31:02 -0800711 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700712 disable_audio_route(adev, uc_info, true);
713
714 /* 2. Disable the rx device */
715 disable_snd_device(adev, uc_info->out_snd_device, true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800716
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800717 list_remove(&uc_info->list);
718 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800719
Eric Laurent994a6932013-07-17 11:51:42 -0700720 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800721 return ret;
722}
723
724int start_output_stream(struct stream_out *out)
725{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800726 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800727 struct audio_usecase *uc_info;
728 struct audio_device *adev = out->dev;
729
Eric Laurent994a6932013-07-17 11:51:42 -0700730 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700731 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Eric Laurentb23d5282013-05-14 15:27:20 -0700732 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800733 if (out->pcm_device_id < 0) {
734 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
735 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800736 ret = -EINVAL;
737 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800738 }
739
740 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
741 uc_info->id = out->usecase;
742 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800743 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744 uc_info->devices = out->devices;
745 uc_info->in_snd_device = SND_DEVICE_NONE;
746 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800747
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800748 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800749
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700750 select_devices(adev, out->usecase);
751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800752 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
753 __func__, 0, out->pcm_device_id);
754 out->pcm = pcm_open(SOUND_CARD, out->pcm_device_id,
755 PCM_OUT, &out->config);
756 if (out->pcm && !pcm_is_ready(out->pcm)) {
757 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
758 pcm_close(out->pcm);
759 out->pcm = NULL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800760 ret = -EIO;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700761 goto error_pcm_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800762 }
Eric Laurent994a6932013-07-17 11:51:42 -0700763 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800764 return 0;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700765error_pcm_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800766 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800767error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800768 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800769}
770
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800771static int check_input_parameters(uint32_t sample_rate,
772 audio_format_t format,
773 int channel_count)
774{
775 if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
776
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -0700777 if ((channel_count < 1) || (channel_count > 6)) return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800778
779 switch (sample_rate) {
780 case 8000:
781 case 11025:
782 case 12000:
783 case 16000:
784 case 22050:
785 case 24000:
786 case 32000:
787 case 44100:
788 case 48000:
789 break;
790 default:
791 return -EINVAL;
792 }
793
794 return 0;
795}
796
797static size_t get_input_buffer_size(uint32_t sample_rate,
798 audio_format_t format,
799 int channel_count)
800{
801 size_t size = 0;
802
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -0700803 if (check_input_parameters(sample_rate, format, channel_count) != 0)
804 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800805
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -0700806 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
807 /* ToDo: should use frame_size computed based on the format and
808 channel_count here. */
809 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800810
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -0700811 /* make sure the size is multiple of 64 */
812 size += 0x3f;
813 size &= ~0x3f;
814
815 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800816}
817
818static uint32_t out_get_sample_rate(const struct audio_stream *stream)
819{
820 struct stream_out *out = (struct stream_out *)stream;
821
822 return out->config.rate;
823}
824
825static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
826{
827 return -ENOSYS;
828}
829
830static size_t out_get_buffer_size(const struct audio_stream *stream)
831{
832 struct stream_out *out = (struct stream_out *)stream;
833
834 return out->config.period_size * audio_stream_frame_size(stream);
835}
836
837static uint32_t out_get_channels(const struct audio_stream *stream)
838{
839 struct stream_out *out = (struct stream_out *)stream;
840
841 return out->channel_mask;
842}
843
844static audio_format_t out_get_format(const struct audio_stream *stream)
845{
846 return AUDIO_FORMAT_PCM_16_BIT;
847}
848
849static int out_set_format(struct audio_stream *stream, audio_format_t format)
850{
851 return -ENOSYS;
852}
853
854static int out_standby(struct audio_stream *stream)
855{
856 struct stream_out *out = (struct stream_out *)stream;
857 struct audio_device *adev = out->dev;
Eric Laurent994a6932013-07-17 11:51:42 -0700858 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700859 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800860 pthread_mutex_lock(&out->lock);
861
862 if (!out->standby) {
863 out->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -0800864 if (out->pcm) {
865 pcm_close(out->pcm);
866 out->pcm = NULL;
867 }
868 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800869 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -0800870 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800871 }
872 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -0700873 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800874 return 0;
875}
876
877static int out_dump(const struct audio_stream *stream, int fd)
878{
879 return 0;
880}
881
882static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
883{
884 struct stream_out *out = (struct stream_out *)stream;
885 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800886 struct audio_usecase *usecase;
887 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800888 struct str_parms *parms;
889 char value[32];
890 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800891 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800892
sangwoobc677242013-08-08 16:53:43 +0900893 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700894 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800895 parms = str_parms_create_str(kvpairs);
896 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
897 if (ret >= 0) {
898 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800899 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -0800900 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800901
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700902 /*
903 * When HDMI cable is unplugged the music playback is paused and
904 * the policy manager sends routing=0. But the audioflinger
905 * continues to write data until standby time (3sec).
906 * As the HDMI core is turned off, the write gets blocked.
907 * Avoid this by routing audio to speaker until standby.
908 */
909 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
910 val == AUDIO_DEVICE_NONE) {
911 val = AUDIO_DEVICE_OUT_SPEAKER;
912 }
913
914 /*
915 * select_devices() call below switches all the usecases on the same
916 * backend to the new device. Refer to check_usecases_codec_backend() in
917 * the select_devices(). But how do we undo this?
918 *
919 * For example, music playback is active on headset (deep-buffer usecase)
920 * and if we go to ringtones and select a ringtone, low-latency usecase
921 * will be started on headset+speaker. As we can't enable headset+speaker
922 * and headset devices at the same time, select_devices() switches the music
923 * playback to headset+speaker while starting low-lateny usecase for ringtone.
924 * So when the ringtone playback is completed, how do we undo the same?
925 *
926 * We are relying on the out_set_parameters() call on deep-buffer output,
927 * once the ringtone playback is ended.
928 * NOTE: We should not check if the current devices are same as new devices.
929 * Because select_devices() must be called to switch back the music
930 * playback to headset.
931 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800932 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700933 out->devices = val;
934
935 if (!out->standby)
936 select_devices(adev, out->usecase);
937
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700938 if ((adev->mode == AUDIO_MODE_IN_CALL) &&
939 !voice_is_in_call(adev) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700940 (out == adev->primary_output)) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700941 voice_start_call(adev);
942 } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
943 voice_is_in_call(adev) &&
944 (out == adev->primary_output)) {
945 select_devices(adev, get_voice_usecase_id_from_list(adev));
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800946 }
947 }
948
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700949 if ((adev->mode == AUDIO_MODE_NORMAL) &&
950 voice_is_in_call(adev) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700951 (out == adev->primary_output)) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700952 voice_stop_call(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800953 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800954
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800955 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -0800956 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800957 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700958
959 if (out == adev->primary_output) {
960 pthread_mutex_lock(&adev->lock);
961 audio_extn_set_parameters(adev, parms);
962 pthread_mutex_unlock(&adev->lock);
963 }
964
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800965 str_parms_destroy(parms);
Eric Laurent994a6932013-07-17 11:51:42 -0700966 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800967 return ret;
968}
969
970static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
971{
972 struct stream_out *out = (struct stream_out *)stream;
973 struct str_parms *query = str_parms_create_str(keys);
974 char *str;
975 char value[256];
976 struct str_parms *reply = str_parms_create();
977 size_t i, j;
978 int ret;
979 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -0700980 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800981 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
982 if (ret >= 0) {
983 value[0] = '\0';
984 i = 0;
985 while (out->supported_channel_masks[i] != 0) {
986 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
987 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
988 if (!first) {
989 strcat(value, "|");
990 }
991 strcat(value, out_channels_name_to_enum_table[j].name);
992 first = false;
993 break;
994 }
995 }
996 i++;
997 }
998 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
999 str = str_parms_to_str(reply);
1000 } else {
1001 str = strdup(keys);
1002 }
1003 str_parms_destroy(query);
1004 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001005 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001006 return str;
1007}
1008
1009static uint32_t out_get_latency(const struct audio_stream_out *stream)
1010{
1011 struct stream_out *out = (struct stream_out *)stream;
1012
1013 return (out->config.period_count * out->config.period_size * 1000) / (out->config.rate);
1014}
1015
1016static int out_set_volume(struct audio_stream_out *stream, float left,
1017 float right)
1018{
Eric Laurenta9024de2013-04-04 09:19:12 -07001019 struct stream_out *out = (struct stream_out *)stream;
1020 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1021 /* only take left channel into account: the API is for stereo anyway */
1022 out->muted = (left == 0.0f);
1023 return 0;
1024 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025 return -ENOSYS;
1026}
1027
1028static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
1029 size_t bytes)
1030{
1031 struct stream_out *out = (struct stream_out *)stream;
1032 struct audio_device *adev = out->dev;
1033 int i, ret = -1;
1034
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001035 pthread_mutex_lock(&out->lock);
1036 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001037 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001038 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001040 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001041 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001042 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001043 goto exit;
1044 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001045 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046
1047 if (out->pcm) {
Eric Laurenta9024de2013-04-04 09:19:12 -07001048 if (out->muted)
1049 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001050 //ALOGV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
1051 ret = pcm_write(out->pcm, (void *)buffer, bytes);
1052 }
1053
1054exit:
1055 pthread_mutex_unlock(&out->lock);
1056
1057 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001058 if (out->pcm)
1059 ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001060 out_standby(&out->stream.common);
1061 usleep(bytes * 1000000 / audio_stream_frame_size(&out->stream.common) /
1062 out_get_sample_rate(&out->stream.common));
1063 }
1064 return bytes;
1065}
1066
1067static int out_get_render_position(const struct audio_stream_out *stream,
1068 uint32_t *dsp_frames)
1069{
1070 return -EINVAL;
1071}
1072
1073static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1074{
1075 return 0;
1076}
1077
1078static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1079{
1080 return 0;
1081}
1082
1083static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
1084 int64_t *timestamp)
1085{
1086 return -EINVAL;
1087}
1088
1089/** audio_stream_in implementation **/
1090static uint32_t in_get_sample_rate(const struct audio_stream *stream)
1091{
1092 struct stream_in *in = (struct stream_in *)stream;
1093
1094 return in->config.rate;
1095}
1096
1097static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1098{
1099 return -ENOSYS;
1100}
1101
1102static size_t in_get_buffer_size(const struct audio_stream *stream)
1103{
1104 struct stream_in *in = (struct stream_in *)stream;
1105
1106 return in->config.period_size * audio_stream_frame_size(stream);
1107}
1108
1109static uint32_t in_get_channels(const struct audio_stream *stream)
1110{
1111 struct stream_in *in = (struct stream_in *)stream;
1112
1113 return in->channel_mask;
1114}
1115
1116static audio_format_t in_get_format(const struct audio_stream *stream)
1117{
1118 return AUDIO_FORMAT_PCM_16_BIT;
1119}
1120
1121static int in_set_format(struct audio_stream *stream, audio_format_t format)
1122{
1123 return -ENOSYS;
1124}
1125
1126static int in_standby(struct audio_stream *stream)
1127{
1128 struct stream_in *in = (struct stream_in *)stream;
1129 struct audio_device *adev = in->dev;
1130 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07001131 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001132 pthread_mutex_lock(&in->lock);
1133 if (!in->standby) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001134 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001135 if (in->pcm) {
1136 pcm_close(in->pcm);
1137 in->pcm = NULL;
1138 }
1139 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001140 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001141 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001142 }
1143 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001144 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001145 return status;
1146}
1147
1148static int in_dump(const struct audio_stream *stream, int fd)
1149{
1150 return 0;
1151}
1152
1153static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1154{
1155 struct stream_in *in = (struct stream_in *)stream;
1156 struct audio_device *adev = in->dev;
1157 struct str_parms *parms;
1158 char *str;
1159 char value[32];
1160 int ret, val = 0;
1161
Eric Laurent994a6932013-07-17 11:51:42 -07001162 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001163 parms = str_parms_create_str(kvpairs);
1164
1165 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
1166
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001167 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001168 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001169 if (ret >= 0) {
1170 val = atoi(value);
1171 /* no audio source uses val == 0 */
1172 if ((in->source != val) && (val != 0)) {
1173 in->source = val;
1174 }
1175 }
1176
1177 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1178 if (ret >= 0) {
1179 val = atoi(value);
1180 if ((in->device != val) && (val != 0)) {
1181 in->device = val;
1182 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001183 if (!in->standby)
1184 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001185 }
1186 }
1187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001188 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001189 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001190
1191 str_parms_destroy(parms);
Eric Laurent994a6932013-07-17 11:51:42 -07001192 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001193 return ret;
1194}
1195
1196static char* in_get_parameters(const struct audio_stream *stream,
1197 const char *keys)
1198{
1199 return strdup("");
1200}
1201
1202static int in_set_gain(struct audio_stream_in *stream, float gain)
1203{
1204 return 0;
1205}
1206
1207static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
1208 size_t bytes)
1209{
1210 struct stream_in *in = (struct stream_in *)stream;
1211 struct audio_device *adev = in->dev;
1212 int i, ret = -1;
1213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001214 pthread_mutex_lock(&in->lock);
1215 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001216 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001217 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001218 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001219 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001220 goto exit;
1221 }
1222 in->standby = 0;
1223 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001224
1225 if (in->pcm) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07001226 if (audio_extn_ssr_get_enabled() && popcount(in->channel_mask) == 6)
1227 ret = audio_extn_ssr_read(stream, buffer, bytes);
1228 else
1229 ret = pcm_read(in->pcm, buffer, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001230 }
1231
1232 /*
1233 * Instead of writing zeroes here, we could trust the hardware
1234 * to always provide zeroes when muted.
1235 */
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001236 if (ret == 0 && voice_get_mic_mute(adev))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001237 memset(buffer, 0, bytes);
1238
1239exit:
1240 pthread_mutex_unlock(&in->lock);
1241
1242 if (ret != 0) {
1243 in_standby(&in->stream.common);
1244 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
1245 usleep(bytes * 1000000 / audio_stream_frame_size(&in->stream.common) /
1246 in_get_sample_rate(&in->stream.common));
1247 }
1248 return bytes;
1249}
1250
1251static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1252{
1253 return 0;
1254}
1255
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001256static int add_remove_audio_effect(const struct audio_stream *stream,
1257 effect_handle_t effect,
1258 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001259{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001260 struct stream_in *in = (struct stream_in *)stream;
1261 int status = 0;
1262 effect_descriptor_t desc;
1263
1264 status = (*effect)->get_descriptor(effect, &desc);
1265 if (status != 0)
1266 return status;
1267
1268 pthread_mutex_lock(&in->lock);
1269 pthread_mutex_lock(&in->dev->lock);
1270 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
1271 in->enable_aec != enable &&
1272 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
1273 in->enable_aec = enable;
1274 if (!in->standby)
1275 select_devices(in->dev, in->usecase);
1276 }
1277 pthread_mutex_unlock(&in->dev->lock);
1278 pthread_mutex_unlock(&in->lock);
1279
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001280 return 0;
1281}
1282
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001283static int in_add_audio_effect(const struct audio_stream *stream,
1284 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001285{
Eric Laurent994a6932013-07-17 11:51:42 -07001286 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001287 return add_remove_audio_effect(stream, effect, true);
1288}
1289
1290static int in_remove_audio_effect(const struct audio_stream *stream,
1291 effect_handle_t effect)
1292{
Eric Laurent994a6932013-07-17 11:51:42 -07001293 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001294 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001295}
1296
1297static int adev_open_output_stream(struct audio_hw_device *dev,
1298 audio_io_handle_t handle,
1299 audio_devices_t devices,
1300 audio_output_flags_t flags,
1301 struct audio_config *config,
1302 struct audio_stream_out **stream_out)
1303{
1304 struct audio_device *adev = (struct audio_device *)dev;
1305 struct stream_out *out;
1306 int i, ret;
1307
Eric Laurent994a6932013-07-17 11:51:42 -07001308 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001309 __func__, config->sample_rate, config->channel_mask, devices, flags);
1310 *stream_out = NULL;
1311 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
1312
1313 if (devices == AUDIO_DEVICE_NONE)
1314 devices = AUDIO_DEVICE_OUT_SPEAKER;
1315
1316 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
1317 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
1318 out->flags = flags;
1319 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001320 out->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001321
1322 /* Init use case and pcm_config */
1323 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
1324 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001325 pthread_mutex_lock(&adev->lock);
1326 ret = read_hdmi_channel_masks(out);
1327 pthread_mutex_unlock(&adev->lock);
1328 if (ret != 0) {
1329 /* If HDMI does not support multi channel playback, set the default */
1330 out->config.channels = popcount(out->channel_mask);
Eric Laurentb23d5282013-05-14 15:27:20 -07001331 platform_set_hdmi_channels(adev->platform, out->config.channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001332 goto error_open;
1333 }
1334
1335 if (config->sample_rate == 0)
1336 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1337 if (config->channel_mask == 0)
1338 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
1339
1340 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001341 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
1342 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001343 out->config.rate = config->sample_rate;
1344 out->config.channels = popcount(out->channel_mask);
1345 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Eric Laurentb23d5282013-05-14 15:27:20 -07001346 platform_set_hdmi_channels(adev->platform, out->config.channels);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001347 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
1348 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
1349 out->config = pcm_config_deep_buffer;
1350 } else {
1351 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
1352 out->config = pcm_config_low_latency;
1353 }
1354
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001355 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
1356 if(adev->primary_output == NULL)
1357 adev->primary_output = out;
1358 else {
1359 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001360 ret = -EEXIST;
1361 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001362 }
1363 }
1364
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001365 /* Check if this usecase is already existing */
1366 pthread_mutex_lock(&adev->lock);
1367 if (get_usecase_from_list(adev, out->usecase) != NULL) {
1368 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001369 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001370 ret = -EEXIST;
1371 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372 }
1373 pthread_mutex_unlock(&adev->lock);
1374
1375 out->stream.common.get_sample_rate = out_get_sample_rate;
1376 out->stream.common.set_sample_rate = out_set_sample_rate;
1377 out->stream.common.get_buffer_size = out_get_buffer_size;
1378 out->stream.common.get_channels = out_get_channels;
1379 out->stream.common.get_format = out_get_format;
1380 out->stream.common.set_format = out_set_format;
1381 out->stream.common.standby = out_standby;
1382 out->stream.common.dump = out_dump;
1383 out->stream.common.set_parameters = out_set_parameters;
1384 out->stream.common.get_parameters = out_get_parameters;
1385 out->stream.common.add_audio_effect = out_add_audio_effect;
1386 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1387 out->stream.get_latency = out_get_latency;
1388 out->stream.set_volume = out_set_volume;
1389 out->stream.write = out_write;
1390 out->stream.get_render_position = out_get_render_position;
1391 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
1392
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001393 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07001394 /* out->muted = false; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001395
1396 config->format = out->stream.common.get_format(&out->stream.common);
1397 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
1398 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
1399
1400 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07001401 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001402 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001403
1404error_open:
1405 free(out);
1406 *stream_out = NULL;
1407 ALOGD("%s: exit: ret %d", __func__, ret);
1408 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001409}
1410
1411static void adev_close_output_stream(struct audio_hw_device *dev,
1412 struct audio_stream_out *stream)
1413{
Eric Laurent994a6932013-07-17 11:51:42 -07001414 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001415 out_standby(&stream->common);
1416 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07001417 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001418}
1419
1420static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1421{
1422 struct audio_device *adev = (struct audio_device *)dev;
1423 struct str_parms *parms;
1424 char *str;
1425 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07001426 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001427 int ret;
1428
Eric Laurent994a6932013-07-17 11:51:42 -07001429 ALOGV("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001430 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001431
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001432 voice_set_parameters(adev, parms);
1433 platform_set_parameters(adev->platform, parms);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001434
1435 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
1436 if (ret >= 0) {
1437 /* When set to false, HAL should disable EC and NS
1438 * But it is currently not supported.
1439 */
1440 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
1441 adev->bluetooth_nrec = true;
1442 else
1443 adev->bluetooth_nrec = false;
1444 }
1445
1446 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
1447 if (ret >= 0) {
1448 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
1449 adev->screen_off = false;
1450 else
1451 adev->screen_off = true;
1452 }
1453
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07001454 ret = str_parms_get_int(parms, "rotation", &val);
1455 if (ret >= 0) {
1456 bool reverse_speakers = false;
1457 switch(val) {
1458 // FIXME: note that the code below assumes that the speakers are in the correct placement
1459 // relative to the user when the device is rotated 90deg from its default rotation. This
1460 // assumption is device-specific, not platform-specific like this code.
1461 case 270:
1462 reverse_speakers = true;
1463 break;
1464 case 0:
1465 case 90:
1466 case 180:
1467 break;
1468 default:
1469 ALOGE("%s: unexpected rotation of %d", __func__, val);
1470 }
1471 pthread_mutex_lock(&adev->lock);
1472 if (adev->speaker_lr_swap != reverse_speakers) {
1473 adev->speaker_lr_swap = reverse_speakers;
1474 // only update the selected device if there is active pcm playback
1475 struct audio_usecase *usecase;
1476 struct listnode *node;
1477 list_for_each(node, &adev->usecase_list) {
1478 usecase = node_to_item(node, struct audio_usecase, list);
1479 if (usecase->type == PCM_PLAYBACK) {
1480 select_devices(adev, usecase->id);
1481 break;
1482 }
1483 }
1484 }
1485 pthread_mutex_unlock(&adev->lock);
1486 }
1487
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07001488 audio_extn_set_parameters(adev, parms);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001489 str_parms_destroy(parms);
Eric Laurent994a6932013-07-17 11:51:42 -07001490 ALOGV("%s: exit with code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491 return ret;
1492}
1493
1494static char* adev_get_parameters(const struct audio_hw_device *dev,
1495 const char *keys)
1496{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001497 struct audio_device *adev = (struct audio_device *)dev;
1498 struct str_parms *reply = str_parms_create();
1499 struct str_parms *query = str_parms_create_str(keys);
1500 char *str;
1501
1502 audio_extn_get_parameters(adev, query, reply);
1503 platform_get_parameters(adev->platform, query, reply);
1504 str = str_parms_to_str(reply);
1505 str_parms_destroy(query);
1506 str_parms_destroy(reply);
1507
1508 ALOGV("%s: exit: returns - %s", __func__, str);
1509 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001510}
1511
1512static int adev_init_check(const struct audio_hw_device *dev)
1513{
1514 return 0;
1515}
1516
1517static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1518{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001519 return voice_set_volume((struct audio_device *)dev, volume);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001520}
1521
1522static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1523{
1524 return -ENOSYS;
1525}
1526
1527static int adev_get_master_volume(struct audio_hw_device *dev,
1528 float *volume)
1529{
1530 return -ENOSYS;
1531}
1532
1533static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
1534{
1535 return -ENOSYS;
1536}
1537
1538static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
1539{
1540 return -ENOSYS;
1541}
1542
1543static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1544{
1545 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001546 pthread_mutex_lock(&adev->lock);
1547 if (adev->mode != mode) {
1548 adev->mode = mode;
1549 }
1550 pthread_mutex_unlock(&adev->lock);
1551 return 0;
1552}
1553
1554static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1555{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001556 return voice_set_mic_mute((struct audio_device *)dev, state);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001557}
1558
1559static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1560{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001561 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001562 return 0;
1563}
1564
1565static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1566 const struct audio_config *config)
1567{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001568 int channel_count = popcount(config->channel_mask);
1569
1570 return get_input_buffer_size(config->sample_rate, config->format, channel_count);
1571}
1572
1573static int adev_open_input_stream(struct audio_hw_device *dev,
1574 audio_io_handle_t handle,
1575 audio_devices_t devices,
1576 struct audio_config *config,
1577 struct audio_stream_in **stream_in)
1578{
1579 struct audio_device *adev = (struct audio_device *)dev;
1580 struct stream_in *in;
1581 int ret, buffer_size, frame_size;
1582 int channel_count = popcount(config->channel_mask);
1583
Eric Laurent994a6932013-07-17 11:51:42 -07001584 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001585 *stream_in = NULL;
1586 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
1587 return -EINVAL;
1588
1589 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
1590
1591 in->stream.common.get_sample_rate = in_get_sample_rate;
1592 in->stream.common.set_sample_rate = in_set_sample_rate;
1593 in->stream.common.get_buffer_size = in_get_buffer_size;
1594 in->stream.common.get_channels = in_get_channels;
1595 in->stream.common.get_format = in_get_format;
1596 in->stream.common.set_format = in_set_format;
1597 in->stream.common.standby = in_standby;
1598 in->stream.common.dump = in_dump;
1599 in->stream.common.set_parameters = in_set_parameters;
1600 in->stream.common.get_parameters = in_get_parameters;
1601 in->stream.common.add_audio_effect = in_add_audio_effect;
1602 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1603 in->stream.set_gain = in_set_gain;
1604 in->stream.read = in_read;
1605 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1606
1607 in->device = devices;
1608 in->source = AUDIO_SOURCE_DEFAULT;
1609 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001610 in->standby = 1;
1611 in->channel_mask = config->channel_mask;
1612
1613 /* Update config params with the requested sample rate and channels */
1614 in->usecase = USECASE_AUDIO_RECORD;
1615 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001616 in->config.rate = config->sample_rate;
1617
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07001618 if (audio_extn_ssr_get_enabled()&& channel_count == 6) {
1619 if(audio_extn_ssr_init(adev, in))
1620 ALOGE("%s: audio_extn_ssr_init failed", __func__);
1621 } else {
1622 in->config.channels = channel_count;
1623 frame_size = audio_stream_frame_size((struct audio_stream *)in);
1624 buffer_size = get_input_buffer_size(config->sample_rate,
1625 config->format,
1626 channel_count);
1627 in->config.period_size = buffer_size / frame_size;
1628 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001629
1630 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07001631 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632 return 0;
1633
1634err_open:
1635 free(in);
1636 *stream_in = NULL;
1637 return ret;
1638}
1639
1640static void adev_close_input_stream(struct audio_hw_device *dev,
1641 struct audio_stream_in *stream)
1642{
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07001643 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07001644 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646 in_standby(&stream->common);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07001647 if (audio_extn_ssr_get_enabled() && (popcount(in->channel_mask) == 6)) {
1648 audio_extn_ssr_deinit();
1649 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001650 free(stream);
1651
1652 return;
1653}
1654
1655static int adev_dump(const audio_hw_device_t *device, int fd)
1656{
1657 return 0;
1658}
1659
1660static int adev_close(hw_device_t *device)
1661{
1662 struct audio_device *adev = (struct audio_device *)device;
1663 audio_route_free(adev->audio_route);
Eric Laurentb23d5282013-05-14 15:27:20 -07001664 free(adev->snd_dev_ref_cnt);
1665 platform_deinit(adev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001666 free(device);
1667 return 0;
1668}
1669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001670static int adev_open(const hw_module_t *module, const char *name,
1671 hw_device_t **device)
1672{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001673 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001675 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001676 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
1677
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001678 pthread_mutex_lock(&adev_init_lock);
1679 if (is_adev_initialised == true){
1680 *device = &adev->device.common;
1681 ALOGD("%s: returning existing instance of adev", __func__);
1682 ALOGD("%s: exit", __func__);
1683 pthread_mutex_unlock(&adev_init_lock);
1684 return 0;
1685 }
1686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001687 adev = calloc(1, sizeof(struct audio_device));
1688
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689 adev->device.common.tag = HARDWARE_DEVICE_TAG;
1690 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
1691 adev->device.common.module = (struct hw_module_t *)module;
1692 adev->device.common.close = adev_close;
1693
1694 adev->device.init_check = adev_init_check;
1695 adev->device.set_voice_volume = adev_set_voice_volume;
1696 adev->device.set_master_volume = adev_set_master_volume;
1697 adev->device.get_master_volume = adev_get_master_volume;
1698 adev->device.set_master_mute = adev_set_master_mute;
1699 adev->device.get_master_mute = adev_get_master_mute;
1700 adev->device.set_mode = adev_set_mode;
1701 adev->device.set_mic_mute = adev_set_mic_mute;
1702 adev->device.get_mic_mute = adev_get_mic_mute;
1703 adev->device.set_parameters = adev_set_parameters;
1704 adev->device.get_parameters = adev_get_parameters;
1705 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
1706 adev->device.open_output_stream = adev_open_output_stream;
1707 adev->device.close_output_stream = adev_close_output_stream;
1708 adev->device.open_input_stream = adev_open_input_stream;
1709 adev->device.close_input_stream = adev_close_input_stream;
1710 adev->device.dump = adev_dump;
1711
1712 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08001714 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001715 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001717 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08001718 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurentb23d5282013-05-14 15:27:20 -07001719 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001720 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001721 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722
1723 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07001724 adev->platform = platform_init(adev);
1725 if (!adev->platform) {
1726 free(adev->snd_dev_ref_cnt);
1727 free(adev);
1728 ALOGE("%s: Failed to init platform data, aborting.", __func__);
1729 *device = NULL;
1730 return -EINVAL;
1731 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001732 *device = &adev->device.common;
1733
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001734 /* update init flag*/
1735 is_adev_initialised = true;
1736 pthread_mutex_unlock(&adev_init_lock);
1737
Eric Laurent994a6932013-07-17 11:51:42 -07001738 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739 return 0;
1740}
1741
1742static struct hw_module_methods_t hal_module_methods = {
1743 .open = adev_open,
1744};
1745
1746struct audio_module HAL_MODULE_INFO_SYM = {
1747 .common = {
1748 .tag = HARDWARE_MODULE_TAG,
1749 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1750 .hal_api_version = HARDWARE_HAL_API_VERSION,
1751 .id = AUDIO_HARDWARE_MODULE_ID,
1752 .name = "QCOM Audio HAL",
1753 .author = "Code Aurora Forum",
1754 .methods = &hal_module_methods,
1755 },
1756};