blob: ffbc0710c91bb63e94e54d77afd196c2357aa44f [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
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"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036
37#include <cutils/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080038#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080039#include <cutils/str_parms.h>
40#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041#include <cutils/atomic.h>
42#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080043
Eric Laurentb23d5282013-05-14 15:27:20 -070044#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070045#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070046#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070047#include <audio_effects/effect_aec.h>
48#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080049#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080050#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070051#include "platform_api.h"
52#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070053#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080054
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include "sound/compress_params.h"
56
Eric Laurent397db572016-05-11 11:31:47 -070057/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
58 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070059#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070060// 2 buffers causes problems with high bitrate files
61#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062/* ToDo: Check and update a proper value in msec */
63#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
64#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
65
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070066#define PROXY_OPEN_RETRY_COUNT 100
67#define PROXY_OPEN_WAIT_TIME 20
68
vivek mehtadae44712015-07-27 14:13:18 -070069#define MIN_CHANNEL_COUNT 1
70#define DEFAULT_CHANNEL_COUNT 2
71
Jean-Michel Trivic0750692015-10-12 12:12:32 -070072#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
73#define MAX_CHANNEL_COUNT 1
74#else
vivek mehtadae44712015-07-27 14:13:18 -070075#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
76#define XSTR(x) STR(x)
77#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070078#endif
vivek mehtadae44712015-07-27 14:13:18 -070079
Haynes Mathew George03c40102016-01-29 17:57:48 -080080#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
81
Glenn Kasten4f993392014-05-14 07:30:48 -070082static unsigned int configured_low_latency_capture_period_size =
83 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
84
Andy Hung31aca912014-03-20 17:14:59 -070085/* This constant enables extended precision handling.
86 * TODO The flag is off until more testing is done.
87 */
88static const bool k_enable_extended_precision = false;
89
Eric Laurentb23d5282013-05-14 15:27:20 -070090struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -070091 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -070092 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
93 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
94 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
95 .format = PCM_FORMAT_S16_LE,
96 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
97 .stop_threshold = INT_MAX,
98 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
99};
100
101struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700102 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700103 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
104 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
105 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
106 .format = PCM_FORMAT_S16_LE,
107 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
108 .stop_threshold = INT_MAX,
109 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
110};
111
Haynes Mathew George03c40102016-01-29 17:57:48 -0800112static int af_period_multiplier = 4;
113struct pcm_config pcm_config_rt = {
114 .channels = DEFAULT_CHANNEL_COUNT,
115 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
116 .period_size = ULL_PERIOD_SIZE, //1 ms
117 .period_count = 512, //=> buffer size is 512ms
118 .format = PCM_FORMAT_S16_LE,
119 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
120 .stop_threshold = INT_MAX,
121 .silence_threshold = 0,
122 .silence_size = 0,
123 .avail_min = ULL_PERIOD_SIZE, //1 ms
124};
125
Eric Laurentb23d5282013-05-14 15:27:20 -0700126struct pcm_config pcm_config_hdmi_multi = {
127 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
129 .period_size = HDMI_MULTI_PERIOD_SIZE,
130 .period_count = HDMI_MULTI_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = 0,
133 .stop_threshold = INT_MAX,
134 .avail_min = 0,
135};
136
137struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700138 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700139 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
140 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700141 .stop_threshold = INT_MAX,
142 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700143};
144
Haynes Mathew George03c40102016-01-29 17:57:48 -0800145struct pcm_config pcm_config_audio_capture_rt = {
146 .channels = DEFAULT_CHANNEL_COUNT,
147 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
148 .period_size = ULL_PERIOD_SIZE,
149 .period_count = 512,
150 .format = PCM_FORMAT_S16_LE,
151 .start_threshold = 0,
152 .stop_threshold = INT_MAX,
153 .silence_threshold = 0,
154 .silence_size = 0,
155 .avail_min = ULL_PERIOD_SIZE, //1 ms
156};
157
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700158#define AFE_PROXY_CHANNEL_COUNT 2
159#define AFE_PROXY_SAMPLING_RATE 48000
160
161#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
162#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
163
164struct pcm_config pcm_config_afe_proxy_playback = {
165 .channels = AFE_PROXY_CHANNEL_COUNT,
166 .rate = AFE_PROXY_SAMPLING_RATE,
167 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
168 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
169 .format = PCM_FORMAT_S16_LE,
170 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
171 .stop_threshold = INT_MAX,
172 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
173};
174
175#define AFE_PROXY_RECORD_PERIOD_SIZE 768
176#define AFE_PROXY_RECORD_PERIOD_COUNT 4
177
178struct pcm_config pcm_config_afe_proxy_record = {
179 .channels = AFE_PROXY_CHANNEL_COUNT,
180 .rate = AFE_PROXY_SAMPLING_RATE,
181 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
182 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
183 .format = PCM_FORMAT_S16_LE,
184 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
185 .stop_threshold = INT_MAX,
186 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
187};
188
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700189const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700190 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
191 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
192 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700193 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700194 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700195 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700196
Eric Laurentb23d5282013-05-14 15:27:20 -0700197 [USECASE_AUDIO_RECORD] = "audio-record",
198 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700199
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800200 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
201 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700202
Eric Laurentb23d5282013-05-14 15:27:20 -0700203 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700204 [USECASE_VOICE2_CALL] = "voice2-call",
205 [USECASE_VOLTE_CALL] = "volte-call",
206 [USECASE_QCHAT_CALL] = "qchat-call",
207 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800208 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
209 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700210
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700211 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
212 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
213
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700214 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
215 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700216};
217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800218
219#define STRING_TO_ENUM(string) { #string, string }
220
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800221struct string_to_enum {
222 const char *name;
223 uint32_t value;
224};
225
226static const struct string_to_enum out_channels_name_to_enum_table[] = {
227 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
228 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
229 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
230};
231
Haynes Mathew George5191a852013-09-11 14:19:36 -0700232static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700233static struct audio_device *adev = NULL;
234static pthread_mutex_t adev_init_lock;
235static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700236//cache last MBDRC cal step level
237static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700238
Haynes Mathew George03c40102016-01-29 17:57:48 -0800239static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
240 int flags __unused)
241{
242 int dir = 0;
243 switch (uc_id) {
244 case USECASE_AUDIO_RECORD_LOW_LATENCY:
245 dir = 1;
246 case USECASE_AUDIO_PLAYBACK_ULL:
247 break;
248 default:
249 return false;
250 }
251
252 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
253 PCM_PLAYBACK : PCM_CAPTURE);
254 if (adev->adm_is_noirq_avail)
255 return adev->adm_is_noirq_avail(adev->adm_data,
256 adev->snd_card, dev_id, dir);
257 return false;
258}
259
260static void register_out_stream(struct stream_out *out)
261{
262 struct audio_device *adev = out->dev;
263 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
264 return;
265
266 if (!adev->adm_register_output_stream)
267 return;
268
269 adev->adm_register_output_stream(adev->adm_data,
270 out->handle,
271 out->flags);
272
273 if (!adev->adm_set_config)
274 return;
275
276 if (out->realtime) {
277 adev->adm_set_config(adev->adm_data,
278 out->handle,
279 out->pcm, &out->config);
280 }
281}
282
283static void register_in_stream(struct stream_in *in)
284{
285 struct audio_device *adev = in->dev;
286 if (!adev->adm_register_input_stream)
287 return;
288
289 adev->adm_register_input_stream(adev->adm_data,
290 in->capture_handle,
291 in->flags);
292
293 if (!adev->adm_set_config)
294 return;
295
296 if (in->realtime) {
297 adev->adm_set_config(adev->adm_data,
298 in->capture_handle,
299 in->pcm,
300 &in->config);
301 }
302}
303
304static void request_out_focus(struct stream_out *out, long ns)
305{
306 struct audio_device *adev = out->dev;
307
308 if (out->routing_change) {
309 out->routing_change = false;
310 if (adev->adm_on_routing_change)
311 adev->adm_on_routing_change(adev->adm_data, out->handle);
312 }
313
314 if (adev->adm_request_focus_v2) {
315 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
316 } else if (adev->adm_request_focus) {
317 adev->adm_request_focus(adev->adm_data, out->handle);
318 }
319}
320
321static void request_in_focus(struct stream_in *in, long ns)
322{
323 struct audio_device *adev = in->dev;
324
325 if (in->routing_change) {
326 in->routing_change = false;
327 if (adev->adm_on_routing_change)
328 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
329 }
330
331 if (adev->adm_request_focus_v2) {
332 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
333 } else if (adev->adm_request_focus) {
334 adev->adm_request_focus(adev->adm_data, in->capture_handle);
335 }
336}
337
338static void release_out_focus(struct stream_out *out, long ns __unused)
339{
340 struct audio_device *adev = out->dev;
341
342 if (adev->adm_abandon_focus)
343 adev->adm_abandon_focus(adev->adm_data, out->handle);
344}
345
346static void release_in_focus(struct stream_in *in, long ns __unused)
347{
348 struct audio_device *adev = in->dev;
349 if (adev->adm_abandon_focus)
350 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
351}
352
Andy Hung7401c7c2016-09-21 12:41:21 -0700353// Time string format similar to logcat, buffer_length must be >= 19 chars.
354static void ns2string(int64_t ns, char *buffer, int buffer_length)
355{
356 const int one_second = 1000000000;
357 const time_t sec = ns / one_second;
358 struct tm tm;
359 localtime_r(&sec, &tm);
360 snprintf(buffer, buffer_length, "%02d-%02d %02d:%02d:%02d.%03d",
361 tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range
362 tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
363 (int)(ns % one_second / 1000000));
364}
365
366// Convert timespec to nsec.
367static int64_t ts2ns(const struct timespec *ts)
368{
369 return ts->tv_sec * 1000000000LL + ts->tv_nsec;
370}
371
372// Log errors: consecutive errors with the same code will
373// be aggregated if they occur within one second.
374// A mutual exclusion lock must be held before calling.
375static void log_error_l(struct error_log *log, int code) {
376 ++log->errors;
377
378 struct timespec now_ts = { 0, 0 };
379 (void)clock_gettime(CLOCK_REALTIME, &now_ts);
380 const int64_t now = ts2ns(&now_ts);
381
382 // Within 1 second, cluster the same error codes together.
383 const int one_second = 1000000000;
384 if (code == log->entries[log->idx].code &&
385 now - log->entries[log->idx].last_time < one_second) {
386 log->entries[log->idx].count++;
387 log->entries[log->idx].last_time = now;
388 return;
389 }
390
391 // Add new error entry.
392 if (++log->idx >= ARRAY_SIZE(log->entries)) {
393 log->idx = 0;
394 }
395 log->entries[log->idx].count = 1;
396 log->entries[log->idx].code = code;
397 log->entries[log->idx].first_time = now;
398 log->entries[log->idx].last_time = now;
399}
400
401// Dump information in the error log. A mutual exclusion lock
402// should be held, but if that cannot be obtained, one should
403// make a copy of the error log before calling -- the call is
404// still safe, but there might be some misinterpreted data.
405static void log_dump_l(const struct error_log *log, int fd)
406{
407 dprintf(fd, " Errors: %u\n", log->errors);
408 if (log->errors == 0)
409 return;
410
411 dprintf(fd, " Index Code Freq First time Last time\n");
412 for (size_t i = 0; i < ARRAY_SIZE(log->entries); ++i) {
413 if (log->entries[i].count != 0) {
414 char first_time[32];
415 char last_time[32];
416 ns2string(log->entries[i].first_time, first_time, sizeof(first_time));
417 ns2string(log->entries[i].last_time, last_time, sizeof(last_time));
418 dprintf(fd, " %c%4zu %4d %5d %s %s\n",
419 i == log->idx ? '*' : ' ', // mark head position
420 i, log->entries[i].code, log->entries[i].count,
421 first_time, last_time);
422 }
423 }
424}
425
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700426static int parse_snd_card_status(struct str_parms * parms, int * card,
427 card_status_t * status)
428{
429 char value[32]={0};
430 char state[32]={0};
431
432 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
433
434 if (ret < 0)
435 return -1;
436
437 // sscanf should be okay as value is of max length 32.
438 // same as sizeof state.
439 if (sscanf(value, "%d,%s", card, state) < 2)
440 return -1;
441
442 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
443 CARD_STATUS_OFFLINE;
444 return 0;
445}
446
vivek mehta1a9b7c02015-06-25 11:49:38 -0700447__attribute__ ((visibility ("default")))
448bool audio_hw_send_gain_dep_calibration(int level) {
449 bool ret_val = false;
450 ALOGV("%s: enter ... ", __func__);
451
452 pthread_mutex_lock(&adev_init_lock);
453
454 if (adev != NULL && adev->platform != NULL) {
455 pthread_mutex_lock(&adev->lock);
456 ret_val = platform_send_gain_dep_cal(adev->platform, level);
457 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700458
459 // if cal set fails, cache level info
460 // if cal set succeds, reset known last cal set
461 if (!ret_val)
462 last_known_cal_step = level;
463 else if (last_known_cal_step != -1)
464 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700465 } else {
466 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
467 }
468
469 pthread_mutex_unlock(&adev_init_lock);
470
471 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
472 return ret_val;
473}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700474
vivek mehtaa8d7c922016-05-25 14:40:44 -0700475__attribute__ ((visibility ("default")))
476int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
477 int table_size) {
478 int ret_val = 0;
479 ALOGV("%s: enter ... ", __func__);
480
481 pthread_mutex_lock(&adev_init_lock);
482 if (adev == NULL) {
483 ALOGW("%s: adev is NULL .... ", __func__);
484 goto done;
485 }
486
487 pthread_mutex_lock(&adev->lock);
488 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
489 pthread_mutex_unlock(&adev->lock);
490done:
491 pthread_mutex_unlock(&adev_init_lock);
492 ALOGV("%s: exit ... ", __func__);
493 return ret_val;
494}
495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700496static bool is_supported_format(audio_format_t format)
497{
Eric Laurent8251ac82014-07-23 11:00:25 -0700498 switch (format) {
499 case AUDIO_FORMAT_MP3:
500 case AUDIO_FORMAT_AAC_LC:
501 case AUDIO_FORMAT_AAC_HE_V1:
502 case AUDIO_FORMAT_AAC_HE_V2:
503 return true;
504 default:
505 break;
506 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700507 return false;
508}
509
Haynes Mathew George03c40102016-01-29 17:57:48 -0800510static inline bool is_mmap_usecase(audio_usecase_t uc_id)
511{
512 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
513 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
514}
515
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700516static int get_snd_codec_id(audio_format_t format)
517{
518 int id = 0;
519
Eric Laurent8251ac82014-07-23 11:00:25 -0700520 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700521 case AUDIO_FORMAT_MP3:
522 id = SND_AUDIOCODEC_MP3;
523 break;
524 case AUDIO_FORMAT_AAC:
525 id = SND_AUDIOCODEC_AAC;
526 break;
527 default:
528 ALOGE("%s: Unsupported audio format", __func__);
529 }
530
531 return id;
532}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800533
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800534int enable_audio_route(struct audio_device *adev,
535 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800536{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700537 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800538 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800539
540 if (usecase == NULL)
541 return -EINVAL;
542
543 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
544
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800545 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700546 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800547 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700548 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800549
Yamit Mehtae3b99562016-09-16 22:44:00 +0530550 audio_extn_utils_send_app_type_cfg(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800551 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500552 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700553 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700554 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800555
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800556 ALOGV("%s: exit", __func__);
557 return 0;
558}
559
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800560int disable_audio_route(struct audio_device *adev,
561 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800562{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700563 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800564 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800565
566 if (usecase == NULL)
567 return -EINVAL;
568
569 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700570 if (usecase->type == PCM_CAPTURE)
571 snd_device = usecase->in_snd_device;
572 else
573 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800574 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500575 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700576 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700577 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800579 ALOGV("%s: exit", __func__);
580 return 0;
581}
582
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800583int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700584 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800585{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700586 int i, num_devices = 0;
587 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800588 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800589 if (snd_device < SND_DEVICE_MIN ||
590 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800591 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800592 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800593 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700594
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700595 platform_send_audio_calibration(adev->platform, snd_device);
596
vivek mehtade4849c2016-03-03 17:23:38 -0800597 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700598 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700599 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800600 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700601 }
602
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700603 /* due to the possibility of calibration overwrite between listen
604 and audio, notify sound trigger hal before audio calibration is sent */
605 audio_extn_sound_trigger_update_device_status(snd_device,
606 ST_EVENT_SND_DEVICE_BUSY);
607
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700608 if (audio_extn_spkr_prot_is_enabled())
609 audio_extn_spkr_prot_calib_cancel(adev);
610
zhaoyang yin4211fad2015-06-04 21:13:25 +0800611 audio_extn_dsm_feedback_enable(adev, snd_device, true);
612
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700613 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
614 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
615 audio_extn_spkr_prot_is_enabled()) {
616 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800617 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700618 }
619 if (audio_extn_spkr_prot_start_processing(snd_device)) {
620 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800621 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700622 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700623 } else if (platform_can_split_snd_device(snd_device,
624 &num_devices,
625 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700626 for (i = 0; i < num_devices; i++) {
627 enable_snd_device(adev, new_snd_devices[i]);
628 }
vivek mehtab6506412015-08-07 16:55:17 -0700629 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700630 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800631 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
632 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
633 ALOGE(" %s: Invalid sound device returned", __func__);
634 goto on_error;
635 }
Ed Tam70b5c142016-03-21 19:14:29 -0700636
Eric Laurent2e140aa2016-06-30 17:14:46 -0700637 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800638 audio_route_apply_and_update_path(adev->audio_route, device_name);
639 }
640on_success:
641 adev->snd_dev_ref_cnt[snd_device]++;
642 ret_val = 0;
643on_error:
644 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800645}
646
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800647int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700648 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800649{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700650 int i, num_devices = 0;
651 snd_device_t new_snd_devices[2];
652
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800653 if (snd_device < SND_DEVICE_MIN ||
654 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800655 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800656 return -EINVAL;
657 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700658 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
659 ALOGE("%s: device ref cnt is already 0", __func__);
660 return -EINVAL;
661 }
662 adev->snd_dev_ref_cnt[snd_device]--;
663 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800664 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700665 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
666 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
667 audio_extn_spkr_prot_is_enabled()) {
668 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700669 } else if (platform_can_split_snd_device(snd_device,
670 &num_devices,
671 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700672 for (i = 0; i < num_devices; i++) {
673 disable_snd_device(adev, new_snd_devices[i]);
674 }
vivek mehtab6506412015-08-07 16:55:17 -0700675 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700676 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800677 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
678 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
679 ALOGE(" %s: Invalid sound device returned", __func__);
680 return -EINVAL;
681 }
682
Eric Laurent2e140aa2016-06-30 17:14:46 -0700683 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800684 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700685 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700686 audio_extn_sound_trigger_update_device_status(snd_device,
687 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700688 }
vivek mehtab6506412015-08-07 16:55:17 -0700689
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800690 return 0;
691}
692
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700693/*
694 legend:
695 uc - existing usecase
696 new_uc - new usecase
697 d1, d11, d2 - SND_DEVICE enums
698 a1, a2 - corresponding ANDROID device enums
699 B, B1, B2 - backend strings
700
701case 1
702 uc->dev d1 (a1) B1
703 new_uc->dev d1 (a1), d2 (a2) B1, B2
704
705 resolution: disable and enable uc->dev on d1
706
707case 2
708 uc->dev d1 (a1) B1
709 new_uc->dev d11 (a1) B1
710
711 resolution: need to switch uc since d1 and d11 are related
712 (e.g. speaker and voice-speaker)
713 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
714
715case 3
716 uc->dev d1 (a1) B1
717 new_uc->dev d2 (a2) B2
718
719 resolution: no need to switch uc
720
721case 4
722 uc->dev d1 (a1) B
723 new_uc->dev d2 (a2) B
724
725 resolution: disable enable uc-dev on d2 since backends match
726 we cannot enable two streams on two different devices if they
727 share the same backend. e.g. if offload is on speaker device using
728 QUAD_MI2S backend and a low-latency stream is started on voice-handset
729 using the same backend, offload must also be switched to voice-handset.
730
731case 5
732 uc->dev d1 (a1) B
733 new_uc->dev d1 (a1), d2 (a2) B
734
735 resolution: disable enable uc-dev on d2 since backends match
736 we cannot enable two streams on two different devices if they
737 share the same backend.
738
739case 6
740 uc->dev d1 a1 B1
741 new_uc->dev d2 a1 B2
742
743 resolution: no need to switch
744
745case 7
746
747 uc->dev d1 (a1), d2 (a2) B1, B2
748 new_uc->dev d1 B1
749
750 resolution: no need to switch
751
752*/
753static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
754 struct audio_usecase *new_uc,
755 snd_device_t new_snd_device)
756{
757 audio_devices_t a1 = uc->stream.out->devices;
758 audio_devices_t a2 = new_uc->stream.out->devices;
759
760 snd_device_t d1 = uc->out_snd_device;
761 snd_device_t d2 = new_snd_device;
762
763 // Treat as a special case when a1 and a2 are not disjoint
764 if ((a1 != a2) && (a1 & a2)) {
765 snd_device_t d3[2];
766 int num_devices = 0;
767 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
768 &num_devices,
769 d3);
770 if (ret < 0) {
771 if (ret != -ENOSYS) {
772 ALOGW("%s failed to split snd_device %d",
773 __func__,
774 popcount(a1) > 1 ? d1 : d2);
775 }
776 goto end;
777 }
778
779 // NB: case 7 is hypothetical and isn't a practical usecase yet.
780 // But if it does happen, we need to give priority to d2 if
781 // the combo devices active on the existing usecase share a backend.
782 // This is because we cannot have a usecase active on a combo device
783 // and a new usecase requests one device in this combo pair.
784 if (platform_check_backends_match(d3[0], d3[1])) {
785 return d2; // case 5
786 } else {
787 return d1; // case 1
788 }
789 } else {
790 if (platform_check_backends_match(d1, d2)) {
791 return d2; // case 2, 4
792 } else {
793 return d1; // case 6, 3
794 }
795 }
796
797end:
798 return d2; // return whatever was calculated before.
799}
800
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700801static void check_and_route_playback_usecases(struct audio_device *adev,
802 struct audio_usecase *uc_info,
803 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700804{
805 struct listnode *node;
806 struct audio_usecase *usecase;
807 bool switch_device[AUDIO_USECASE_MAX];
808 int i, num_uc_to_switch = 0;
809
810 /*
811 * This function is to make sure that all the usecases that are active on
812 * the hardware codec backend are always routed to any one device that is
813 * handled by the hardware codec.
814 * For example, if low-latency and deep-buffer usecases are currently active
815 * on speaker and out_set_parameters(headset) is received on low-latency
816 * output, then we have to make sure deep-buffer is also switched to headset,
817 * because of the limitation that both the devices cannot be enabled
818 * at the same time as they share the same backend.
819 */
820 /* Disable all the usecases on the shared backend other than the
821 specified usecase */
822 for (i = 0; i < AUDIO_USECASE_MAX; i++)
823 switch_device[i] = false;
824
825 list_for_each(node, &adev->usecase_list) {
826 usecase = node_to_item(node, struct audio_usecase, list);
827 if (usecase->type != PCM_CAPTURE &&
828 usecase != uc_info &&
829 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700830 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
831 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700832 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
833 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700834 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700835 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700836 switch_device[usecase->id] = true;
837 num_uc_to_switch++;
838 }
839 }
840
841 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700842 list_for_each(node, &adev->usecase_list) {
843 usecase = node_to_item(node, struct audio_usecase, list);
844 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700845 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900846 }
847 }
848
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700849 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900850 list_for_each(node, &adev->usecase_list) {
851 usecase = node_to_item(node, struct audio_usecase, list);
852 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700853 d_device = derive_playback_snd_device(usecase, uc_info,
854 snd_device);
855 enable_snd_device(adev, d_device);
856 /* Update the out_snd_device before enabling the audio route */
857 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700858 }
859 }
860
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700861 /* Re-route all the usecases on the shared backend other than the
862 specified usecase to new snd devices */
863 list_for_each(node, &adev->usecase_list) {
864 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700865 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700866 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700867 }
868 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869 }
870}
871
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700872static void check_and_route_capture_usecases(struct audio_device *adev,
873 struct audio_usecase *uc_info,
874 snd_device_t snd_device)
875{
876 struct listnode *node;
877 struct audio_usecase *usecase;
878 bool switch_device[AUDIO_USECASE_MAX];
879 int i, num_uc_to_switch = 0;
880
vivek mehta4ed66e62016-04-15 23:33:34 -0700881 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
882
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700883 /*
884 * This function is to make sure that all the active capture usecases
885 * are always routed to the same input sound device.
886 * For example, if audio-record and voice-call usecases are currently
887 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
888 * is received for voice call then we have to make sure that audio-record
889 * usecase is also switched to earpiece i.e. voice-dmic-ef,
890 * because of the limitation that two devices cannot be enabled
891 * at the same time if they share the same backend.
892 */
893 for (i = 0; i < AUDIO_USECASE_MAX; i++)
894 switch_device[i] = false;
895
896 list_for_each(node, &adev->usecase_list) {
897 usecase = node_to_item(node, struct audio_usecase, list);
898 if (usecase->type != PCM_PLAYBACK &&
899 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700900 usecase->in_snd_device != snd_device &&
901 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700902 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
903 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700904 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700905 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700906 switch_device[usecase->id] = true;
907 num_uc_to_switch++;
908 }
909 }
910
911 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700912 list_for_each(node, &adev->usecase_list) {
913 usecase = node_to_item(node, struct audio_usecase, list);
914 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700915 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700916 }
917 }
918
919 list_for_each(node, &adev->usecase_list) {
920 usecase = node_to_item(node, struct audio_usecase, list);
921 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700922 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700923 }
924 }
925
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700926 /* Re-route all the usecases on the shared backend other than the
927 specified usecase to new snd devices */
928 list_for_each(node, &adev->usecase_list) {
929 usecase = node_to_item(node, struct audio_usecase, list);
930 /* Update the in_snd_device only before enabling the audio route */
931 if (switch_device[usecase->id] ) {
932 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700933 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700934 }
935 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700936 }
937}
938
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800939/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700940static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800941{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700942 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700943 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800944
945 switch (channels) {
946 /*
947 * Do not handle stereo output in Multi-channel cases
948 * Stereo case is handled in normal playback path
949 */
950 case 6:
951 ALOGV("%s: HDMI supports 5.1", __func__);
952 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
953 break;
954 case 8:
955 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
956 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
957 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
958 break;
959 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700960 ALOGE("HDMI does not support multi channel playback");
961 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800962 break;
963 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700964 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800965}
966
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700967static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
968{
969 struct audio_usecase *usecase;
970 struct listnode *node;
971
972 list_for_each(node, &adev->usecase_list) {
973 usecase = node_to_item(node, struct audio_usecase, list);
974 if (usecase->type == VOICE_CALL) {
975 ALOGV("%s: usecase id %d", __func__, usecase->id);
976 return usecase->id;
977 }
978 }
979 return USECASE_INVALID;
980}
981
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800982struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
983 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700984{
985 struct audio_usecase *usecase;
986 struct listnode *node;
987
988 list_for_each(node, &adev->usecase_list) {
989 usecase = node_to_item(node, struct audio_usecase, list);
990 if (usecase->id == uc_id)
991 return usecase;
992 }
993 return NULL;
994}
995
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800996int select_devices(struct audio_device *adev,
997 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800998{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800999 snd_device_t out_snd_device = SND_DEVICE_NONE;
1000 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001001 struct audio_usecase *usecase = NULL;
1002 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001003 struct audio_usecase *hfp_usecase = NULL;
1004 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001005 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001006 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001007
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001008 usecase = get_usecase_from_list(adev, uc_id);
1009 if (usecase == NULL) {
1010 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1011 return -EINVAL;
1012 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001013
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001014 if ((usecase->type == VOICE_CALL) ||
1015 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001016 out_snd_device = platform_get_output_snd_device(adev->platform,
1017 usecase->stream.out->devices);
1018 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001019 usecase->devices = usecase->stream.out->devices;
1020 } else {
1021 /*
1022 * If the voice call is active, use the sound devices of voice call usecase
1023 * so that it would not result any device switch. All the usecases will
1024 * be switched to new device when select_devices() is called for voice call
1025 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001026 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001027 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001028 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001029 vc_usecase = get_usecase_from_list(adev,
1030 get_voice_usecase_id_from_list(adev));
1031 if ((vc_usecase != NULL) &&
1032 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1033 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001034 in_snd_device = vc_usecase->in_snd_device;
1035 out_snd_device = vc_usecase->out_snd_device;
1036 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001037 } else if (audio_extn_hfp_is_active(adev)) {
1038 hfp_ucid = audio_extn_hfp_get_usecase();
1039 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1040 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1041 in_snd_device = hfp_usecase->in_snd_device;
1042 out_snd_device = hfp_usecase->out_snd_device;
1043 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001044 }
1045 if (usecase->type == PCM_PLAYBACK) {
1046 usecase->devices = usecase->stream.out->devices;
1047 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001048 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001049 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001050 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001051 if (usecase->stream.out == adev->primary_output &&
1052 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001053 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1054 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001055 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001056 select_devices(adev, adev->active_input->usecase);
1057 }
1058 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001059 } else if (usecase->type == PCM_CAPTURE) {
1060 usecase->devices = usecase->stream.in->device;
1061 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001062 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001063 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001064 if (adev->active_input &&
1065 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1066 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001067 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001068 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1069 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1070 } else if (adev->primary_output) {
1071 out_device = adev->primary_output->devices;
1072 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001073 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001074 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001075 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001076 }
1077 }
1078
1079 if (out_snd_device == usecase->out_snd_device &&
1080 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001081 return 0;
1082 }
1083
Eric Laurent2bafff12016-03-17 12:17:23 -07001084 if (out_snd_device != SND_DEVICE_NONE &&
1085 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1086 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1087 __func__,
1088 use_case_table[uc_id],
1089 adev->last_logged_snd_device[uc_id][0],
1090 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1091 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1092 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1093 -1,
1094 out_snd_device,
1095 platform_get_snd_device_name(out_snd_device),
1096 platform_get_snd_device_acdb_id(out_snd_device));
1097 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1098 }
1099 if (in_snd_device != SND_DEVICE_NONE &&
1100 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1101 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1102 __func__,
1103 use_case_table[uc_id],
1104 adev->last_logged_snd_device[uc_id][1],
1105 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1106 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1107 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1108 -1,
1109 in_snd_device,
1110 platform_get_snd_device_name(in_snd_device),
1111 platform_get_snd_device_acdb_id(in_snd_device));
1112 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1113 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001115 /*
1116 * Limitation: While in call, to do a device switch we need to disable
1117 * and enable both RX and TX devices though one of them is same as current
1118 * device.
1119 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001120 if ((usecase->type == VOICE_CALL) &&
1121 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1122 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001123 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001124 /* Disable sidetone only if voice call already exists */
1125 if (voice_is_call_state_active(adev))
1126 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001127 }
1128
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001129 /* Disable current sound devices */
1130 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001131 disable_audio_route(adev, usecase);
1132 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001133 }
1134
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001136 disable_audio_route(adev, usecase);
1137 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001138 }
1139
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001140 /* Applicable only on the targets that has external modem.
1141 * New device information should be sent to modem before enabling
1142 * the devices to reduce in-call device switch time.
1143 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001144 if ((usecase->type == VOICE_CALL) &&
1145 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1146 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001147 status = platform_switch_voice_call_enable_device_config(adev->platform,
1148 out_snd_device,
1149 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001150 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001151
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152 /* Enable new sound devices */
1153 if (out_snd_device != SND_DEVICE_NONE) {
1154 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001155 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001156 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001157 }
1158
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001159 if (in_snd_device != SND_DEVICE_NONE) {
1160 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001161 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001162 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001163
Eric Laurentb23d5282013-05-14 15:27:20 -07001164 if (usecase->type == VOICE_CALL)
1165 status = platform_switch_voice_call_device_post(adev->platform,
1166 out_snd_device,
1167 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001168
sangwoo170731f2013-06-08 15:36:36 +09001169 usecase->in_snd_device = in_snd_device;
1170 usecase->out_snd_device = out_snd_device;
1171
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001172 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001173
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001174 /* Applicable only on the targets that has external modem.
1175 * Enable device command should be sent to modem only after
1176 * enabling voice call mixer controls
1177 */
vivek mehta765eb642015-08-07 19:46:06 -07001178 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001179 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1180 out_snd_device,
1181 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001182 /* Enable sidetone only if voice call already exists */
1183 if (voice_is_call_state_active(adev))
1184 voice_set_sidetone(adev, out_snd_device, true);
1185 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001187 return status;
1188}
1189
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001190static int stop_input_stream(struct stream_in *in)
1191{
1192 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001193 struct audio_usecase *uc_info;
1194 struct audio_device *adev = in->dev;
1195
Eric Laurentc8400632013-02-14 19:04:54 -08001196 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001197
Eric Laurent994a6932013-07-17 11:51:42 -07001198 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001199 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001200 uc_info = get_usecase_from_list(adev, in->usecase);
1201 if (uc_info == NULL) {
1202 ALOGE("%s: Could not find the usecase (%d) in the list",
1203 __func__, in->usecase);
1204 return -EINVAL;
1205 }
1206
Eric Laurent150dbfe2013-02-27 14:31:02 -08001207 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001208 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001209
1210 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001211 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001212
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001213 list_remove(&uc_info->list);
1214 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001215
Eric Laurent994a6932013-07-17 11:51:42 -07001216 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001217 return ret;
1218}
1219
1220int start_input_stream(struct stream_in *in)
1221{
1222 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001223 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001224 struct audio_usecase *uc_info;
1225 struct audio_device *adev = in->dev;
1226
Eric Laurent994a6932013-07-17 11:51:42 -07001227 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001228
1229 if (in->card_status == CARD_STATUS_OFFLINE ||
1230 adev->card_status == CARD_STATUS_OFFLINE) {
1231 ALOGW("in->card_status or adev->card_status offline, try again");
1232 ret = -EAGAIN;
1233 goto error_config;
1234 }
1235
Eric Laurentb23d5282013-05-14 15:27:20 -07001236 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001237 if (in->pcm_device_id < 0) {
1238 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1239 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001240 ret = -EINVAL;
1241 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001242 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001243
1244 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001245 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1246 uc_info->id = in->usecase;
1247 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001248 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001249 uc_info->devices = in->device;
1250 uc_info->in_snd_device = SND_DEVICE_NONE;
1251 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001252
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001253 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001254
1255 audio_extn_perf_lock_acquire();
1256
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001257 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001258
Eric Laurentc8400632013-02-14 19:04:54 -08001259 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001260 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001261
Andy Hung6ebe5962016-01-15 17:46:57 -08001262 unsigned int flags = PCM_IN | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001263 unsigned int pcm_open_retry_count = 0;
1264
1265 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1266 flags |= PCM_MMAP | PCM_NOIRQ;
1267 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001268 } else if (in->realtime) {
1269 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001270 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001271
1272 while (1) {
1273 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1274 flags, &in->config);
1275 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1276 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1277 if (in->pcm != NULL) {
1278 pcm_close(in->pcm);
1279 in->pcm = NULL;
1280 }
1281 if (pcm_open_retry_count-- == 0) {
1282 ret = -EIO;
1283 goto error_open;
1284 }
1285 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1286 continue;
1287 }
1288 break;
1289 }
1290
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001291 ALOGV("%s: pcm_prepare", __func__);
1292 ret = pcm_prepare(in->pcm);
1293 if (ret < 0) {
1294 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1295 pcm_close(in->pcm);
1296 in->pcm = NULL;
1297 goto error_open;
1298 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001299 if (in->realtime) {
1300 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001301 if (ret < 0) {
1302 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1303 pcm_close(in->pcm);
1304 in->pcm = NULL;
1305 goto error_open;
1306 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001307 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001308 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001309 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001310 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001311
Eric Laurentc8400632013-02-14 19:04:54 -08001312 return ret;
1313
1314error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001315 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001316 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001317
1318error_config:
1319 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001320 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001321
1322 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001323}
1324
Eric Laurenta1478072015-09-21 17:21:52 -07001325void lock_input_stream(struct stream_in *in)
1326{
1327 pthread_mutex_lock(&in->pre_lock);
1328 pthread_mutex_lock(&in->lock);
1329 pthread_mutex_unlock(&in->pre_lock);
1330}
1331
1332void lock_output_stream(struct stream_out *out)
1333{
1334 pthread_mutex_lock(&out->pre_lock);
1335 pthread_mutex_lock(&out->lock);
1336 pthread_mutex_unlock(&out->pre_lock);
1337}
1338
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001339/* must be called with out->lock locked */
1340static int send_offload_cmd_l(struct stream_out* out, int command)
1341{
1342 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1343
1344 ALOGVV("%s %d", __func__, command);
1345
1346 cmd->cmd = command;
1347 list_add_tail(&out->offload_cmd_list, &cmd->node);
1348 pthread_cond_signal(&out->offload_cond);
1349 return 0;
1350}
1351
1352/* must be called iwth out->lock locked */
1353static void stop_compressed_output_l(struct stream_out *out)
1354{
1355 out->offload_state = OFFLOAD_STATE_IDLE;
1356 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001357 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001358 if (out->compr != NULL) {
1359 compress_stop(out->compr);
1360 while (out->offload_thread_blocked) {
1361 pthread_cond_wait(&out->cond, &out->lock);
1362 }
1363 }
1364}
1365
1366static void *offload_thread_loop(void *context)
1367{
1368 struct stream_out *out = (struct stream_out *) context;
1369 struct listnode *item;
1370
1371 out->offload_state = OFFLOAD_STATE_IDLE;
1372 out->playback_started = 0;
1373
1374 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1375 set_sched_policy(0, SP_FOREGROUND);
1376 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1377
1378 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001379 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001380 for (;;) {
1381 struct offload_cmd *cmd = NULL;
1382 stream_callback_event_t event;
1383 bool send_callback = false;
1384
1385 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1386 __func__, list_empty(&out->offload_cmd_list),
1387 out->offload_state);
1388 if (list_empty(&out->offload_cmd_list)) {
1389 ALOGV("%s SLEEPING", __func__);
1390 pthread_cond_wait(&out->offload_cond, &out->lock);
1391 ALOGV("%s RUNNING", __func__);
1392 continue;
1393 }
1394
1395 item = list_head(&out->offload_cmd_list);
1396 cmd = node_to_item(item, struct offload_cmd, node);
1397 list_remove(item);
1398
1399 ALOGVV("%s STATE %d CMD %d out->compr %p",
1400 __func__, out->offload_state, cmd->cmd, out->compr);
1401
1402 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1403 free(cmd);
1404 break;
1405 }
1406
1407 if (out->compr == NULL) {
1408 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001409 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001410 pthread_cond_signal(&out->cond);
1411 continue;
1412 }
1413 out->offload_thread_blocked = true;
1414 pthread_mutex_unlock(&out->lock);
1415 send_callback = false;
1416 switch(cmd->cmd) {
1417 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1418 compress_wait(out->compr, -1);
1419 send_callback = true;
1420 event = STREAM_CBK_EVENT_WRITE_READY;
1421 break;
1422 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001423 compress_next_track(out->compr);
1424 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001425 send_callback = true;
1426 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001427 /* Resend the metadata for next iteration */
1428 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001429 break;
1430 case OFFLOAD_CMD_DRAIN:
1431 compress_drain(out->compr);
1432 send_callback = true;
1433 event = STREAM_CBK_EVENT_DRAIN_READY;
1434 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001435 case OFFLOAD_CMD_ERROR:
1436 send_callback = true;
1437 event = STREAM_CBK_EVENT_ERROR;
1438 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001439 default:
1440 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1441 break;
1442 }
Eric Laurenta1478072015-09-21 17:21:52 -07001443 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001444 out->offload_thread_blocked = false;
1445 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001446 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001447 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001448 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001449 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001450 free(cmd);
1451 }
1452
1453 pthread_cond_signal(&out->cond);
1454 while (!list_empty(&out->offload_cmd_list)) {
1455 item = list_head(&out->offload_cmd_list);
1456 list_remove(item);
1457 free(node_to_item(item, struct offload_cmd, node));
1458 }
1459 pthread_mutex_unlock(&out->lock);
1460
1461 return NULL;
1462}
1463
1464static int create_offload_callback_thread(struct stream_out *out)
1465{
1466 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1467 list_init(&out->offload_cmd_list);
1468 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1469 offload_thread_loop, out);
1470 return 0;
1471}
1472
1473static int destroy_offload_callback_thread(struct stream_out *out)
1474{
Eric Laurenta1478072015-09-21 17:21:52 -07001475 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001476 stop_compressed_output_l(out);
1477 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1478
1479 pthread_mutex_unlock(&out->lock);
1480 pthread_join(out->offload_thread, (void **) NULL);
1481 pthread_cond_destroy(&out->offload_cond);
1482
1483 return 0;
1484}
1485
Eric Laurent07eeafd2013-10-06 12:52:49 -07001486static bool allow_hdmi_channel_config(struct audio_device *adev)
1487{
1488 struct listnode *node;
1489 struct audio_usecase *usecase;
1490 bool ret = true;
1491
1492 list_for_each(node, &adev->usecase_list) {
1493 usecase = node_to_item(node, struct audio_usecase, list);
1494 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1495 /*
1496 * If voice call is already existing, do not proceed further to avoid
1497 * disabling/enabling both RX and TX devices, CSD calls, etc.
1498 * Once the voice call done, the HDMI channels can be configured to
1499 * max channels of remaining use cases.
1500 */
1501 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001502 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001503 __func__);
1504 ret = false;
1505 break;
1506 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001507 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001508 "no change in HDMI channels", __func__);
1509 ret = false;
1510 break;
1511 }
1512 }
1513 }
1514 return ret;
1515}
1516
1517static int check_and_set_hdmi_channels(struct audio_device *adev,
1518 unsigned int channels)
1519{
1520 struct listnode *node;
1521 struct audio_usecase *usecase;
1522
1523 /* Check if change in HDMI channel config is allowed */
1524 if (!allow_hdmi_channel_config(adev))
1525 return 0;
1526
1527 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001528 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001529 return 0;
1530 }
1531
1532 platform_set_hdmi_channels(adev->platform, channels);
1533 adev->cur_hdmi_channels = channels;
1534
1535 /*
1536 * Deroute all the playback streams routed to HDMI so that
1537 * the back end is deactivated. Note that backend will not
1538 * be deactivated if any one stream is connected to it.
1539 */
1540 list_for_each(node, &adev->usecase_list) {
1541 usecase = node_to_item(node, struct audio_usecase, list);
1542 if (usecase->type == PCM_PLAYBACK &&
1543 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001544 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001545 }
1546 }
1547
1548 /*
1549 * Enable all the streams disabled above. Now the HDMI backend
1550 * will be activated with new channel configuration
1551 */
1552 list_for_each(node, &adev->usecase_list) {
1553 usecase = node_to_item(node, struct audio_usecase, list);
1554 if (usecase->type == PCM_PLAYBACK &&
1555 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001556 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001557 }
1558 }
1559
1560 return 0;
1561}
1562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001563static int stop_output_stream(struct stream_out *out)
1564{
1565 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001566 struct audio_usecase *uc_info;
1567 struct audio_device *adev = out->dev;
1568
Eric Laurent994a6932013-07-17 11:51:42 -07001569 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001570 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001571 uc_info = get_usecase_from_list(adev, out->usecase);
1572 if (uc_info == NULL) {
1573 ALOGE("%s: Could not find the usecase (%d) in the list",
1574 __func__, out->usecase);
1575 return -EINVAL;
1576 }
1577
Haynes Mathew George41f86652014-06-17 14:22:15 -07001578 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1579 if (adev->visualizer_stop_output != NULL)
1580 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1581 if (adev->offload_effects_stop_output != NULL)
1582 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1583 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001584
Eric Laurent150dbfe2013-02-27 14:31:02 -08001585 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001586 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001587
1588 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001589 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001590
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001591 list_remove(&uc_info->list);
1592 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001593
Eric Laurent0499d4f2014-08-25 22:39:29 -05001594 audio_extn_extspk_update(adev->extspk);
1595
Eric Laurent07eeafd2013-10-06 12:52:49 -07001596 /* Must be called after removing the usecase from list */
1597 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1598 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1599
Eric Laurent994a6932013-07-17 11:51:42 -07001600 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001601 return ret;
1602}
1603
1604int start_output_stream(struct stream_out *out)
1605{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001606 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001607 struct audio_usecase *uc_info;
1608 struct audio_device *adev = out->dev;
1609
Eric Laurent994a6932013-07-17 11:51:42 -07001610 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001611 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001612
1613 if (out->card_status == CARD_STATUS_OFFLINE ||
1614 adev->card_status == CARD_STATUS_OFFLINE) {
1615 ALOGW("out->card_status or adev->card_status offline, try again");
1616 ret = -EAGAIN;
1617 goto error_config;
1618 }
1619
Eric Laurentb23d5282013-05-14 15:27:20 -07001620 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621 if (out->pcm_device_id < 0) {
1622 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1623 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001624 ret = -EINVAL;
1625 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626 }
1627
1628 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1629 uc_info->id = out->usecase;
1630 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001631 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001632 uc_info->devices = out->devices;
1633 uc_info->in_snd_device = SND_DEVICE_NONE;
1634 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001635
Eric Laurent07eeafd2013-10-06 12:52:49 -07001636 /* This must be called before adding this usecase to the list */
1637 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1638 check_and_set_hdmi_channels(adev, out->config.channels);
1639
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001640 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001641
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001642 audio_extn_perf_lock_acquire();
1643
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001644 select_devices(adev, out->usecase);
1645
Eric Laurent0499d4f2014-08-25 22:39:29 -05001646 audio_extn_extspk_update(adev->extspk);
1647
Andy Hung31aca912014-03-20 17:14:59 -07001648 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001649 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001650 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001651 unsigned int flags = PCM_OUT;
1652 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001653
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001654 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1655 flags |= PCM_MMAP | PCM_NOIRQ;
1656 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001657 } else if (out->realtime) {
1658 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001659 } else
1660 flags |= PCM_MONOTONIC;
1661
1662 while (1) {
1663 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1664 flags, &out->config);
1665 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1666 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1667 if (out->pcm != NULL) {
1668 pcm_close(out->pcm);
1669 out->pcm = NULL;
1670 }
1671 if (pcm_open_retry_count-- == 0) {
1672 ret = -EIO;
1673 goto error_open;
1674 }
1675 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1676 continue;
1677 }
1678 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001679 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001680 ALOGV("%s: pcm_prepare", __func__);
1681 if (pcm_is_ready(out->pcm)) {
1682 ret = pcm_prepare(out->pcm);
1683 if (ret < 0) {
1684 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1685 pcm_close(out->pcm);
1686 out->pcm = NULL;
1687 goto error_open;
1688 }
1689 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001690 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691 out->pcm = NULL;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001692 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001693 COMPRESS_IN, &out->compr_config);
1694 if (out->compr && !is_compress_ready(out->compr)) {
1695 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1696 compress_close(out->compr);
1697 out->compr = NULL;
1698 ret = -EIO;
1699 goto error_open;
1700 }
1701 if (out->offload_callback)
1702 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001703
1704 if (adev->visualizer_start_output != NULL)
Haynes Mathew George41f86652014-06-17 14:22:15 -07001705 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1706 if (adev->offload_effects_start_output != NULL)
1707 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001709 ret = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001710 if (out->realtime) {
1711 ret = pcm_start(out->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001712 if (ret < 0) {
1713 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1714 pcm_close(out->pcm);
1715 out->pcm = NULL;
1716 goto error_open;
1717 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001718 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001719 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001720 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001721 ALOGV("%s: exit", __func__);
Haynes Mathew George03c40102016-01-29 17:57:48 -08001722 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001723error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001724 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001726error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001727 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001728}
1729
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730static int check_input_parameters(uint32_t sample_rate,
1731 audio_format_t format,
1732 int channel_count)
1733{
vivek mehta4ed66e62016-04-15 23:33:34 -07001734 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001735 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1736 return -EINVAL;
1737 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738
vivek mehtadae44712015-07-27 14:13:18 -07001739 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001740 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001741 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1742 return -EINVAL;
1743 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744
1745 switch (sample_rate) {
1746 case 8000:
1747 case 11025:
1748 case 12000:
1749 case 16000:
1750 case 22050:
1751 case 24000:
1752 case 32000:
1753 case 44100:
1754 case 48000:
1755 break;
1756 default:
vivek mehtadae44712015-07-27 14:13:18 -07001757 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758 return -EINVAL;
1759 }
1760
1761 return 0;
1762}
1763
1764static size_t get_input_buffer_size(uint32_t sample_rate,
1765 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001766 int channel_count,
1767 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768{
1769 size_t size = 0;
1770
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001771 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1772 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001774 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001775 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001776 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001777
1778 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001779
Glenn Kasten4f993392014-05-14 07:30:48 -07001780 /* make sure the size is multiple of 32 bytes
1781 * At 48 kHz mono 16-bit PCM:
1782 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1783 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1784 */
1785 size += 0x1f;
1786 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001787
1788 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789}
1790
1791static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1792{
1793 struct stream_out *out = (struct stream_out *)stream;
1794
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001795 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796}
1797
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001798static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799{
1800 return -ENOSYS;
1801}
1802
1803static size_t out_get_buffer_size(const struct audio_stream *stream)
1804{
1805 struct stream_out *out = (struct stream_out *)stream;
1806
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1808 return out->compr_config.fragment_size;
1809 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001810 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001811 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812}
1813
1814static uint32_t out_get_channels(const struct audio_stream *stream)
1815{
1816 struct stream_out *out = (struct stream_out *)stream;
1817
1818 return out->channel_mask;
1819}
1820
1821static audio_format_t out_get_format(const struct audio_stream *stream)
1822{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001823 struct stream_out *out = (struct stream_out *)stream;
1824
1825 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826}
1827
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001828static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001829{
1830 return -ENOSYS;
1831}
1832
1833static int out_standby(struct audio_stream *stream)
1834{
1835 struct stream_out *out = (struct stream_out *)stream;
1836 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001837
Eric Laurent994a6932013-07-17 11:51:42 -07001838 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001839 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840
Eric Laurenta1478072015-09-21 17:21:52 -07001841 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001842 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001843 if (adev->adm_deregister_stream)
1844 adev->adm_deregister_stream(adev->adm_data, out->handle);
1845
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001846 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001848 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1849 if (out->pcm) {
1850 pcm_close(out->pcm);
1851 out->pcm = NULL;
1852 }
1853 } else {
1854 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001855 out->gapless_mdata.encoder_delay = 0;
1856 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001857 if (out->compr != NULL) {
1858 compress_close(out->compr);
1859 out->compr = NULL;
1860 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001861 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001863 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864 }
1865 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001866 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867 return 0;
1868}
1869
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001870static int out_on_error(struct audio_stream *stream)
1871{
1872 struct stream_out *out = (struct stream_out *)stream;
1873 struct audio_device *adev = out->dev;
1874 bool do_standby = false;
1875
1876 lock_output_stream(out);
1877 if (!out->standby) {
1878 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1879 stop_compressed_output_l(out);
1880 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1881 } else
1882 do_standby = true;
1883 }
1884 pthread_mutex_unlock(&out->lock);
1885
1886 if (do_standby)
1887 return out_standby(&out->stream.common);
1888
1889 return 0;
1890}
1891
Andy Hung7401c7c2016-09-21 12:41:21 -07001892static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001893{
Andy Hung7401c7c2016-09-21 12:41:21 -07001894 struct stream_out *out = (struct stream_out *)stream;
1895
1896 // We try to get the lock for consistency,
1897 // but it isn't necessary for these variables.
1898 // If we're not in standby, we may be blocked on a write.
1899 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1900 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1901 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1902
1903 if (locked) {
1904 log_dump_l(&out->error_log, fd);
1905 pthread_mutex_unlock(&out->lock);
1906 } else {
1907 // We don't have the lock here, copy for safety.
1908 struct error_log log = out->error_log;
1909 log_dump_l(&log, fd);
1910 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001911 return 0;
1912}
1913
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001914static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1915{
1916 int ret = 0;
1917 char value[32];
1918 struct compr_gapless_mdata tmp_mdata;
1919
1920 if (!out || !parms) {
1921 return -EINVAL;
1922 }
1923
1924 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1925 if (ret >= 0) {
1926 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1927 } else {
1928 return -EINVAL;
1929 }
1930
1931 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1932 if (ret >= 0) {
1933 tmp_mdata.encoder_padding = atoi(value);
1934 } else {
1935 return -EINVAL;
1936 }
1937
1938 out->gapless_mdata = tmp_mdata;
1939 out->send_new_metadata = 1;
1940 ALOGV("%s new encoder delay %u and padding %u", __func__,
1941 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1942
1943 return 0;
1944}
1945
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001946static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1947{
1948 return out == adev->primary_output || out == adev->voice_tx_output;
1949}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001950
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001951static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1952{
1953 struct stream_out *out = (struct stream_out *)stream;
1954 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001955 struct audio_usecase *usecase;
1956 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001957 struct str_parms *parms;
1958 char value[32];
1959 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001960 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001961 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001962
Eric Laurent2e140aa2016-06-30 17:14:46 -07001963 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001964 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001965 parms = str_parms_create_str(kvpairs);
1966 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1967 if (ret >= 0) {
1968 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001969 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001970 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001971
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001972 /*
1973 * When HDMI cable is unplugged the music playback is paused and
1974 * the policy manager sends routing=0. But the audioflinger
1975 * continues to write data until standby time (3sec).
1976 * As the HDMI core is turned off, the write gets blocked.
1977 * Avoid this by routing audio to speaker until standby.
1978 */
1979 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1980 val == AUDIO_DEVICE_NONE) {
1981 val = AUDIO_DEVICE_OUT_SPEAKER;
1982 }
1983
1984 /*
1985 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001986 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001987 * the select_devices(). But how do we undo this?
1988 *
1989 * For example, music playback is active on headset (deep-buffer usecase)
1990 * and if we go to ringtones and select a ringtone, low-latency usecase
1991 * will be started on headset+speaker. As we can't enable headset+speaker
1992 * and headset devices at the same time, select_devices() switches the music
1993 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1994 * So when the ringtone playback is completed, how do we undo the same?
1995 *
1996 * We are relying on the out_set_parameters() call on deep-buffer output,
1997 * once the ringtone playback is ended.
1998 * NOTE: We should not check if the current devices are same as new devices.
1999 * Because select_devices() must be called to switch back the music
2000 * playback to headset.
2001 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002002 audio_devices_t new_dev = val;
2003 if (new_dev != AUDIO_DEVICE_NONE) {
2004 bool same_dev = out->devices == new_dev;
2005 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002006
Eric Laurenta7657192014-10-09 21:09:33 -07002007 if (output_drives_call(adev, out)) {
2008 if (!voice_is_in_call(adev)) {
2009 if (adev->mode == AUDIO_MODE_IN_CALL) {
2010 adev->current_call_output = out;
2011 ret = voice_start_call(adev);
2012 }
2013 } else {
2014 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002015 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002016 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002017 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002018
2019 if (!out->standby) {
2020 if (!same_dev) {
2021 ALOGV("update routing change");
2022 out->routing_change = true;
2023 }
2024 select_devices(adev, out->usecase);
2025 }
2026
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002027 }
2028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002030 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002031
2032 /*handles device and call state changes*/
2033 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002034 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002035
2036 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2037 parse_compress_metadata(out, parms);
2038 }
2039
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002041 ALOGV("%s: exit: code(%d)", __func__, status);
2042 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043}
2044
2045static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2046{
2047 struct stream_out *out = (struct stream_out *)stream;
2048 struct str_parms *query = str_parms_create_str(keys);
2049 char *str;
2050 char value[256];
2051 struct str_parms *reply = str_parms_create();
2052 size_t i, j;
2053 int ret;
2054 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002055 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2057 if (ret >= 0) {
2058 value[0] = '\0';
2059 i = 0;
2060 while (out->supported_channel_masks[i] != 0) {
2061 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2062 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2063 if (!first) {
2064 strcat(value, "|");
2065 }
2066 strcat(value, out_channels_name_to_enum_table[j].name);
2067 first = false;
2068 break;
2069 }
2070 }
2071 i++;
2072 }
2073 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2074 str = str_parms_to_str(reply);
2075 } else {
2076 str = strdup(keys);
2077 }
2078 str_parms_destroy(query);
2079 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002080 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002081 return str;
2082}
2083
2084static uint32_t out_get_latency(const struct audio_stream_out *stream)
2085{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002086 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002087 struct stream_out *out = (struct stream_out *)stream;
2088
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002089 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2090 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002091 else if (out->realtime) {
2092 // since the buffer won't be filled up faster than realtime,
2093 // return a smaller number
2094 period_ms = (out->af_period_multiplier * out->config.period_size *
2095 1000) / (out->config.rate);
2096 hw_delay = platform_render_latency(out->usecase)/1000;
2097 return period_ms + hw_delay;
2098 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002099
2100 return (out->config.period_count * out->config.period_size * 1000) /
2101 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102}
2103
2104static int out_set_volume(struct audio_stream_out *stream, float left,
2105 float right)
2106{
Eric Laurenta9024de2013-04-04 09:19:12 -07002107 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002108 int volume[2];
2109
Eric Laurenta9024de2013-04-04 09:19:12 -07002110 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2111 /* only take left channel into account: the API is for stereo anyway */
2112 out->muted = (left == 0.0f);
2113 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002114 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2115 const char *mixer_ctl_name = "Compress Playback Volume";
2116 struct audio_device *adev = out->dev;
2117 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002118 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2119 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002120 /* try with the control based on device id */
2121 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2122 PCM_PLAYBACK);
2123 char ctl_name[128] = {0};
2124 snprintf(ctl_name, sizeof(ctl_name),
2125 "Compress Playback %d Volume", pcm_device_id);
2126 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2127 if (!ctl) {
2128 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2129 return -EINVAL;
2130 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002131 }
2132 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2133 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2134 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2135 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002136 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002137
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138 return -ENOSYS;
2139}
2140
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002141// note: this call is safe only if the stream_cb is
2142// removed first in close_output_stream (as is done now).
2143static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2144{
2145 if (!stream || !parms)
2146 return;
2147
2148 struct stream_out *out = (struct stream_out *)stream;
2149 struct audio_device *adev = out->dev;
2150
2151 card_status_t status;
2152 int card;
2153 if (parse_snd_card_status(parms, &card, &status) < 0)
2154 return;
2155
2156 pthread_mutex_lock(&adev->lock);
2157 bool valid_cb = (card == adev->snd_card);
2158 pthread_mutex_unlock(&adev->lock);
2159
2160 if (!valid_cb)
2161 return;
2162
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002163 lock_output_stream(out);
2164 if (out->card_status != status)
2165 out->card_status = status;
2166 pthread_mutex_unlock(&out->lock);
2167
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002168 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2169 use_case_table[out->usecase],
2170 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2171
2172 if (status == CARD_STATUS_OFFLINE)
2173 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002174
2175 return;
2176}
2177
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002178#ifdef NO_AUDIO_OUT
2179static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002180 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002181{
2182 struct stream_out *out = (struct stream_out *)stream;
2183
2184 /* No Output device supported other than BT for playback.
2185 * Sleep for the amount of buffer duration
2186 */
Eric Laurenta1478072015-09-21 17:21:52 -07002187 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002188 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2189 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002190 out_get_sample_rate(&out->stream.common));
2191 pthread_mutex_unlock(&out->lock);
2192 return bytes;
2193}
2194#endif
2195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2197 size_t bytes)
2198{
2199 struct stream_out *out = (struct stream_out *)stream;
2200 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002201 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002202 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203
Eric Laurenta1478072015-09-21 17:21:52 -07002204 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002205 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002206 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002207 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002209 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002210 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002211 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002212 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002213 goto exit;
2214 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002215
2216 if (last_known_cal_step != -1) {
2217 ALOGD("%s: retry previous failed cal level set", __func__);
2218 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2219 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002221
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002222 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002223 ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
2224 if (out->send_new_metadata) {
2225 ALOGVV("send new gapless metadata");
2226 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2227 out->send_new_metadata = 0;
2228 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002229 unsigned int avail;
2230 struct timespec tstamp;
2231 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2232 /* Do not limit write size if the available frames count is unknown */
2233 if (ret != 0) {
2234 avail = bytes;
2235 }
2236 if (avail == 0) {
2237 ret = 0;
2238 } else {
2239 if (avail > bytes) {
2240 avail = bytes;
2241 }
2242 ret = compress_write(out->compr, buffer, avail);
2243 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2244 __func__, avail, ret);
2245 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002246
Eric Laurent6e895242013-09-05 16:10:57 -07002247 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002248 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2249 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002250 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002251 compress_start(out->compr);
2252 out->playback_started = 1;
2253 out->offload_state = OFFLOAD_STATE_PLAYING;
2254 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002255 if (ret < 0) {
2256 log_error_l(&out->error_log, ERROR_CODE_WRITE);
2257 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002258 pthread_mutex_unlock(&out->lock);
2259 return ret;
2260 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002261 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002262 if (out->pcm) {
2263 if (out->muted)
2264 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002265
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002266 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002267
Haynes Mathew George03c40102016-01-29 17:57:48 -08002268 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2269 out->config.rate;
2270 request_out_focus(out, ns);
2271
2272 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2273 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002274 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002275 else
2276 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002277
Haynes Mathew George03c40102016-01-29 17:57:48 -08002278 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002279 } else {
2280 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002281 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002282 }
2283
2284exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002285 // For PCM we always consume the buffer and return #bytes regardless of ret.
2286 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2287 out->written += bytes / (out->config.channels * sizeof(short));
2288 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002289 long long sleeptime_us = 0;
2290 if (ret != 0) {
2291 log_error_l(&out->error_log, error_code);
2292 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2293 ALOGE_IF(out->pcm != NULL,
2294 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
2295 sleeptime_us = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2296 out_get_sample_rate(&out->stream.common);
2297 // usleep not guaranteed for values over 1 second but we don't limit here.
2298 }
2299 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002301 pthread_mutex_unlock(&out->lock);
2302
2303 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002304 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002305 if (sleeptime_us != 0)
2306 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002307 }
2308 return bytes;
2309}
2310
2311static int out_get_render_position(const struct audio_stream_out *stream,
2312 uint32_t *dsp_frames)
2313{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002314 struct stream_out *out = (struct stream_out *)stream;
2315 *dsp_frames = 0;
2316 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002317 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002318 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002319 unsigned long frames = 0;
2320 // TODO: check return value
2321 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2322 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002323 ALOGVV("%s rendered frames %d sample_rate %d",
2324 __func__, *dsp_frames, out->sample_rate);
2325 }
2326 pthread_mutex_unlock(&out->lock);
2327 return 0;
2328 } else
2329 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002330}
2331
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002332static int out_add_audio_effect(const struct audio_stream *stream __unused,
2333 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002334{
2335 return 0;
2336}
2337
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002338static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2339 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002340{
2341 return 0;
2342}
2343
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002344static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2345 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346{
2347 return -EINVAL;
2348}
2349
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002350static int out_get_presentation_position(const struct audio_stream_out *stream,
2351 uint64_t *frames, struct timespec *timestamp)
2352{
2353 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002354 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002355 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002356
Eric Laurenta1478072015-09-21 17:21:52 -07002357 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002358
Eric Laurent949a0892013-09-20 09:20:13 -07002359 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2360 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002361 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002362 compress_get_tstamp(out->compr, &dsp_frames,
2363 &out->sample_rate);
2364 ALOGVV("%s rendered frames %ld sample_rate %d",
2365 __func__, dsp_frames, out->sample_rate);
2366 *frames = dsp_frames;
2367 ret = 0;
2368 /* this is the best we can do */
2369 clock_gettime(CLOCK_MONOTONIC, timestamp);
2370 }
2371 } else {
2372 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002373 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002374 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2375 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002376 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002377 // This adjustment accounts for buffering after app processor.
2378 // It is based on estimated DSP latency per use case, rather than exact.
2379 signed_frames -=
2380 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2381
Eric Laurent949a0892013-09-20 09:20:13 -07002382 // It would be unusual for this value to be negative, but check just in case ...
2383 if (signed_frames >= 0) {
2384 *frames = signed_frames;
2385 ret = 0;
2386 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002387 }
2388 }
2389 }
2390
2391 pthread_mutex_unlock(&out->lock);
2392
2393 return ret;
2394}
2395
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002396static int out_set_callback(struct audio_stream_out *stream,
2397 stream_callback_t callback, void *cookie)
2398{
2399 struct stream_out *out = (struct stream_out *)stream;
2400
2401 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002402 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002403 out->offload_callback = callback;
2404 out->offload_cookie = cookie;
2405 pthread_mutex_unlock(&out->lock);
2406 return 0;
2407}
2408
2409static int out_pause(struct audio_stream_out* stream)
2410{
2411 struct stream_out *out = (struct stream_out *)stream;
2412 int status = -ENOSYS;
2413 ALOGV("%s", __func__);
2414 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002415 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002416 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2417 status = compress_pause(out->compr);
2418 out->offload_state = OFFLOAD_STATE_PAUSED;
2419 }
2420 pthread_mutex_unlock(&out->lock);
2421 }
2422 return status;
2423}
2424
2425static int out_resume(struct audio_stream_out* stream)
2426{
2427 struct stream_out *out = (struct stream_out *)stream;
2428 int status = -ENOSYS;
2429 ALOGV("%s", __func__);
2430 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2431 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002432 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002433 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2434 status = compress_resume(out->compr);
2435 out->offload_state = OFFLOAD_STATE_PLAYING;
2436 }
2437 pthread_mutex_unlock(&out->lock);
2438 }
2439 return status;
2440}
2441
2442static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2443{
2444 struct stream_out *out = (struct stream_out *)stream;
2445 int status = -ENOSYS;
2446 ALOGV("%s", __func__);
2447 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002448 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002449 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2450 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2451 else
2452 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2453 pthread_mutex_unlock(&out->lock);
2454 }
2455 return status;
2456}
2457
2458static int out_flush(struct audio_stream_out* stream)
2459{
2460 struct stream_out *out = (struct stream_out *)stream;
2461 ALOGV("%s", __func__);
2462 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002463 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002464 stop_compressed_output_l(out);
2465 pthread_mutex_unlock(&out->lock);
2466 return 0;
2467 }
2468 return -ENOSYS;
2469}
2470
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002471/** audio_stream_in implementation **/
2472static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2473{
2474 struct stream_in *in = (struct stream_in *)stream;
2475
2476 return in->config.rate;
2477}
2478
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002479static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480{
2481 return -ENOSYS;
2482}
2483
2484static size_t in_get_buffer_size(const struct audio_stream *stream)
2485{
2486 struct stream_in *in = (struct stream_in *)stream;
2487
Haynes Mathew George03c40102016-01-29 17:57:48 -08002488 return in->config.period_size * in->af_period_multiplier *
2489 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490}
2491
2492static uint32_t in_get_channels(const struct audio_stream *stream)
2493{
2494 struct stream_in *in = (struct stream_in *)stream;
2495
2496 return in->channel_mask;
2497}
2498
vivek mehta4ed66e62016-04-15 23:33:34 -07002499static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500{
vivek mehta4ed66e62016-04-15 23:33:34 -07002501 struct stream_in *in = (struct stream_in *)stream;
2502 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503}
2504
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002505static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506{
2507 return -ENOSYS;
2508}
2509
2510static int in_standby(struct audio_stream *stream)
2511{
2512 struct stream_in *in = (struct stream_in *)stream;
2513 struct audio_device *adev = in->dev;
2514 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07002515 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002516
2517 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002518
2519 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002520 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002521 audio_extn_sound_trigger_stop_lab(in);
2522 in->standby = true;
2523 }
2524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002525 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002526 if (adev->adm_deregister_stream)
2527 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2528
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002529 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002530 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002531 if (in->pcm) {
2532 pcm_close(in->pcm);
2533 in->pcm = NULL;
2534 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002535 adev->enable_voicerx = false;
2536 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002538 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539 }
2540 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002541 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 return status;
2543}
2544
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002545static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546{
2547 return 0;
2548}
2549
2550static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2551{
2552 struct stream_in *in = (struct stream_in *)stream;
2553 struct audio_device *adev = in->dev;
2554 struct str_parms *parms;
2555 char *str;
2556 char value[32];
2557 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002558 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002559
Eric Laurent994a6932013-07-17 11:51:42 -07002560 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561 parms = str_parms_create_str(kvpairs);
2562
2563 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2564
Eric Laurenta1478072015-09-21 17:21:52 -07002565 lock_input_stream(in);
2566
Eric Laurent150dbfe2013-02-27 14:31:02 -08002567 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 if (ret >= 0) {
2569 val = atoi(value);
2570 /* no audio source uses val == 0 */
2571 if ((in->source != val) && (val != 0)) {
2572 in->source = val;
2573 }
2574 }
2575
2576 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002577
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578 if (ret >= 0) {
2579 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002580 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581 in->device = val;
2582 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002583 if (!in->standby) {
2584 ALOGV("update input routing change");
2585 in->routing_change = true;
2586 select_devices(adev, in->usecase);
2587 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002588 }
2589 }
2590
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002592 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593
2594 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002595 ALOGV("%s: exit: status(%d)", __func__, status);
2596 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597}
2598
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002599static char* in_get_parameters(const struct audio_stream *stream __unused,
2600 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601{
2602 return strdup("");
2603}
2604
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002605static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002606{
2607 return 0;
2608}
2609
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002610static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2611{
2612 if (!stream || !parms)
2613 return;
2614
2615 struct stream_in *in = (struct stream_in *)stream;
2616 struct audio_device *adev = in->dev;
2617
2618 card_status_t status;
2619 int card;
2620 if (parse_snd_card_status(parms, &card, &status) < 0)
2621 return;
2622
2623 pthread_mutex_lock(&adev->lock);
2624 bool valid_cb = (card == adev->snd_card);
2625 pthread_mutex_unlock(&adev->lock);
2626
2627 if (!valid_cb)
2628 return;
2629
2630 lock_input_stream(in);
2631 if (in->card_status != status)
2632 in->card_status = status;
2633 pthread_mutex_unlock(&in->lock);
2634
2635 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2636 use_case_table[in->usecase],
2637 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2638
2639 // a better solution would be to report error back to AF and let
2640 // it put the stream to standby
2641 if (status == CARD_STATUS_OFFLINE)
2642 in_standby(&in->stream.common);
2643
2644 return;
2645}
2646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2648 size_t bytes)
2649{
2650 struct stream_in *in = (struct stream_in *)stream;
2651 struct audio_device *adev = in->dev;
2652 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002653 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654
Eric Laurenta1478072015-09-21 17:21:52 -07002655 lock_input_stream(in);
2656
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002657 if (in->is_st_session) {
2658 ALOGVV(" %s: reading on st session bytes=%d", __func__, bytes);
2659 /* Read from sound trigger HAL */
2660 audio_extn_sound_trigger_read(in, buffer, bytes);
2661 pthread_mutex_unlock(&in->lock);
2662 return bytes;
2663 }
2664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002666 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002668 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670 goto exit;
2671 }
2672 in->standby = 0;
2673 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674
Haynes Mathew George03c40102016-01-29 17:57:48 -08002675 //what's the duration requested by the client?
2676 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2677 in->config.rate;
2678 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002679
Haynes Mathew George03c40102016-01-29 17:57:48 -08002680 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002682 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002683 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002684 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002685 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002686 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002687 if (ret < 0) {
2688 ALOGE("Failed to read w/err %s", strerror(errno));
2689 ret = -errno;
2690 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002691 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2692 if (bytes % 4 == 0) {
2693 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2694 int_buf_stream = buffer;
2695 for (size_t itt=0; itt < bytes/4 ; itt++) {
2696 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002697 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002698 } else {
2699 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2700 ret = -EINVAL;
2701 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002702 }
2703 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704 }
2705
Haynes Mathew George03c40102016-01-29 17:57:48 -08002706 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002707
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708 /*
2709 * Instead of writing zeroes here, we could trust the hardware
2710 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002711 * No need to acquire adev->lock to read mic_muted here as we don't change its state.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002713 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002714 memset(buffer, 0, bytes);
2715
2716exit:
2717 pthread_mutex_unlock(&in->lock);
2718
2719 if (ret != 0) {
2720 in_standby(&in->stream.common);
2721 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002722 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002723 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002724 memset(buffer, 0, bytes); // clear return data
2725 }
2726 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002727 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728 }
2729 return bytes;
2730}
2731
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002732static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733{
2734 return 0;
2735}
2736
Andy Hung6ebe5962016-01-15 17:46:57 -08002737static int in_get_capture_position(const struct audio_stream_in *stream,
2738 int64_t *frames, int64_t *time)
2739{
2740 if (stream == NULL || frames == NULL || time == NULL) {
2741 return -EINVAL;
2742 }
2743 struct stream_in *in = (struct stream_in *)stream;
2744 int ret = -ENOSYS;
2745
2746 lock_input_stream(in);
2747 if (in->pcm) {
2748 struct timespec timestamp;
2749 unsigned int avail;
2750 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2751 *frames = in->frames_read + avail;
2752 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2753 ret = 0;
2754 }
2755 }
2756 pthread_mutex_unlock(&in->lock);
2757 return ret;
2758}
2759
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002760static int add_remove_audio_effect(const struct audio_stream *stream,
2761 effect_handle_t effect,
2762 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002763{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002764 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002765 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002766 int status = 0;
2767 effect_descriptor_t desc;
2768
2769 status = (*effect)->get_descriptor(effect, &desc);
2770 if (status != 0)
2771 return status;
2772
Eric Laurenta1478072015-09-21 17:21:52 -07002773 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002774 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002775 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002776 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002777 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002778 in->enable_aec != enable &&
2779 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2780 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002781 if (!enable)
2782 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002783 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2784 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2785 adev->enable_voicerx = enable;
2786 struct audio_usecase *usecase;
2787 struct listnode *node;
2788 list_for_each(node, &adev->usecase_list) {
2789 usecase = node_to_item(node, struct audio_usecase, list);
2790 if (usecase->type == PCM_PLAYBACK) {
2791 select_devices(adev, usecase->id);
2792 break;
2793 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002794 }
2795 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002796 if (!in->standby)
2797 select_devices(in->dev, in->usecase);
2798 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07002799 if (in->enable_ns != enable &&
2800 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2801 in->enable_ns = enable;
2802 if (!in->standby)
2803 select_devices(in->dev, in->usecase);
2804 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002805 pthread_mutex_unlock(&in->dev->lock);
2806 pthread_mutex_unlock(&in->lock);
2807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808 return 0;
2809}
2810
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002811static int in_add_audio_effect(const struct audio_stream *stream,
2812 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813{
Eric Laurent994a6932013-07-17 11:51:42 -07002814 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002815 return add_remove_audio_effect(stream, effect, true);
2816}
2817
2818static int in_remove_audio_effect(const struct audio_stream *stream,
2819 effect_handle_t effect)
2820{
Eric Laurent994a6932013-07-17 11:51:42 -07002821 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002822 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823}
2824
2825static int adev_open_output_stream(struct audio_hw_device *dev,
2826 audio_io_handle_t handle,
2827 audio_devices_t devices,
2828 audio_output_flags_t flags,
2829 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07002830 struct audio_stream_out **stream_out,
2831 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832{
2833 struct audio_device *adev = (struct audio_device *)dev;
2834 struct stream_out *out;
2835 int i, ret;
2836
Eric Laurent994a6932013-07-17 11:51:42 -07002837 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002838 __func__, config->sample_rate, config->channel_mask, devices, flags);
2839 *stream_out = NULL;
2840 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2841
2842 if (devices == AUDIO_DEVICE_NONE)
2843 devices = AUDIO_DEVICE_OUT_SPEAKER;
2844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002845 out->flags = flags;
2846 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002847 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002848 out->format = config->format;
2849 out->sample_rate = config->sample_rate;
2850 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2851 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002852 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002853
2854 /* Init use case and pcm_config */
2855 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07002856 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002858 pthread_mutex_lock(&adev->lock);
2859 ret = read_hdmi_channel_masks(out);
2860 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002861 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002862 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002863
2864 if (config->sample_rate == 0)
2865 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2866 if (config->channel_mask == 0)
2867 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08002868 if (config->format == AUDIO_FORMAT_DEFAULT)
2869 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002870
2871 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002872 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08002873 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002874 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2875 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002876 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002877 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002878 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002879 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07002880 pthread_mutex_lock(&adev->lock);
2881 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
2882 pthread_mutex_unlock(&adev->lock);
2883
2884 // reject offload during card offline to allow
2885 // fallback to s/w paths
2886 if (offline) {
2887 ret = -ENODEV;
2888 goto error_open;
2889 }
2890
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002891 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2892 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2893 ALOGE("%s: Unsupported Offload information", __func__);
2894 ret = -EINVAL;
2895 goto error_open;
2896 }
2897 if (!is_supported_format(config->offload_info.format)) {
2898 ALOGE("%s: Unsupported audio format", __func__);
2899 ret = -EINVAL;
2900 goto error_open;
2901 }
2902
2903 out->compr_config.codec = (struct snd_codec *)
2904 calloc(1, sizeof(struct snd_codec));
2905
2906 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
2907 if (config->offload_info.channel_mask)
2908 out->channel_mask = config->offload_info.channel_mask;
2909 else if (config->channel_mask)
2910 out->channel_mask = config->channel_mask;
2911 out->format = config->offload_info.format;
2912 out->sample_rate = config->offload_info.sample_rate;
2913
2914 out->stream.set_callback = out_set_callback;
2915 out->stream.pause = out_pause;
2916 out->stream.resume = out_resume;
2917 out->stream.drain = out_drain;
2918 out->stream.flush = out_flush;
2919
2920 out->compr_config.codec->id =
2921 get_snd_codec_id(config->offload_info.format);
2922 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
2923 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07002924 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002925 out->compr_config.codec->bit_rate =
2926 config->offload_info.bit_rate;
2927 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002928 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002929 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
2930
2931 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2932 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002933
2934 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002935 create_offload_callback_thread(out);
2936 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2937 __func__, config->offload_info.version,
2938 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002939 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2940 if (config->sample_rate == 0)
2941 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2942 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2943 config->sample_rate != 8000) {
2944 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2945 ret = -EINVAL;
2946 goto error_open;
2947 }
2948 out->sample_rate = config->sample_rate;
2949 out->config.rate = config->sample_rate;
2950 if (config->format == AUDIO_FORMAT_DEFAULT)
2951 config->format = AUDIO_FORMAT_PCM_16_BIT;
2952 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2953 config->format = AUDIO_FORMAT_PCM_16_BIT;
2954 ret = -EINVAL;
2955 goto error_open;
2956 }
2957 out->format = config->format;
2958 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2959 out->config = pcm_config_afe_proxy_playback;
2960 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002961 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07002962 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2963 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2964 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07002965 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
2966 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
2967 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07002968 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
2969 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002970 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
2971 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
2972 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Andy Hung6fcba9c2014-03-18 11:53:32 -07002973 } else {
2974 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2975 out->config = pcm_config_low_latency;
2976 }
2977 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2978 if (k_enable_extended_precision
2979 && pcm_params_format_test(adev->use_case_table[out->usecase],
2980 pcm_format_from_audio_format(config->format))) {
2981 out->config.format = pcm_format_from_audio_format(config->format);
2982 /* out->format already set to config->format */
2983 } else {
2984 /* deny the externally proposed config format
2985 * and use the one specified in audio_hw layer configuration.
2986 * Note: out->format is returned by out->stream.common.get_format()
2987 * and is used to set config->format in the code several lines below.
2988 */
2989 out->format = audio_format_from_pcm_format(out->config.format);
2990 }
2991 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002992 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07002994 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
2995 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002997 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002998 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002999 adev->primary_output = out;
3000 else {
3001 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003002 ret = -EEXIST;
3003 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003004 }
3005 }
3006
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007 /* Check if this usecase is already existing */
3008 pthread_mutex_lock(&adev->lock);
3009 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3010 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003011 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003012 ret = -EEXIST;
3013 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014 }
3015 pthread_mutex_unlock(&adev->lock);
3016
3017 out->stream.common.get_sample_rate = out_get_sample_rate;
3018 out->stream.common.set_sample_rate = out_set_sample_rate;
3019 out->stream.common.get_buffer_size = out_get_buffer_size;
3020 out->stream.common.get_channels = out_get_channels;
3021 out->stream.common.get_format = out_get_format;
3022 out->stream.common.set_format = out_set_format;
3023 out->stream.common.standby = out_standby;
3024 out->stream.common.dump = out_dump;
3025 out->stream.common.set_parameters = out_set_parameters;
3026 out->stream.common.get_parameters = out_get_parameters;
3027 out->stream.common.add_audio_effect = out_add_audio_effect;
3028 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3029 out->stream.get_latency = out_get_latency;
3030 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003031#ifdef NO_AUDIO_OUT
3032 out->stream.write = out_write_for_no_output;
3033#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003035#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036 out->stream.get_render_position = out_get_render_position;
3037 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003038 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003039
Haynes Mathew George03c40102016-01-29 17:57:48 -08003040 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003041 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003042 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003043 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003044
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003045 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003046 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003047 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049 config->format = out->stream.common.get_format(&out->stream.common);
3050 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3051 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3052
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003053
3054 /*
3055 By locking output stream before registering, we allow the callback
3056 to update stream's state only after stream's initial state is set to
3057 adev state.
3058 */
3059 lock_output_stream(out);
3060 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3061 pthread_mutex_lock(&adev->lock);
3062 out->card_status = adev->card_status;
3063 pthread_mutex_unlock(&adev->lock);
3064 pthread_mutex_unlock(&out->lock);
3065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003067 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003069
3070error_open:
3071 free(out);
3072 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003073 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003074 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075}
3076
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003077static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078 struct audio_stream_out *stream)
3079{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003080 struct stream_out *out = (struct stream_out *)stream;
3081 struct audio_device *adev = out->dev;
3082
Eric Laurent994a6932013-07-17 11:51:42 -07003083 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003084
3085 // must deregister from sndmonitor first to prevent races
3086 // between the callback and close_stream
3087 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003089 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3090 destroy_offload_callback_thread(out);
3091
3092 if (out->compr_config.codec != NULL)
3093 free(out->compr_config.codec);
3094 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003095
3096 if (adev->voice_tx_output == out)
3097 adev->voice_tx_output = NULL;
3098
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003099 pthread_cond_destroy(&out->cond);
3100 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003102 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003103}
3104
3105static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3106{
3107 struct audio_device *adev = (struct audio_device *)dev;
3108 struct str_parms *parms;
3109 char *str;
3110 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003111 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003112 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003113 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114
Joe Onorato188b6222016-03-01 11:02:27 -08003115 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003116
3117 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118
3119 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003120 status = voice_set_parameters(adev, parms);
3121 if (status != 0) {
3122 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123 }
3124
3125 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3126 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003127 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3129 adev->bluetooth_nrec = true;
3130 else
3131 adev->bluetooth_nrec = false;
3132 }
3133
3134 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3135 if (ret >= 0) {
3136 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3137 adev->screen_off = false;
3138 else
3139 adev->screen_off = true;
3140 }
3141
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003142 ret = str_parms_get_int(parms, "rotation", &val);
3143 if (ret >= 0) {
3144 bool reverse_speakers = false;
3145 switch(val) {
3146 // FIXME: note that the code below assumes that the speakers are in the correct placement
3147 // relative to the user when the device is rotated 90deg from its default rotation. This
3148 // assumption is device-specific, not platform-specific like this code.
3149 case 270:
3150 reverse_speakers = true;
3151 break;
3152 case 0:
3153 case 90:
3154 case 180:
3155 break;
3156 default:
3157 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003158 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003159 }
Eric Laurent03f09432014-03-25 18:09:11 -07003160 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003161 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003162 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003163 }
3164
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003165 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3166 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003167 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003168 }
3169
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003170 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003171done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003173 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003174 ALOGV("%s: exit with code(%d)", __func__, status);
3175 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176}
3177
3178static char* adev_get_parameters(const struct audio_hw_device *dev,
3179 const char *keys)
3180{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003181 struct audio_device *adev = (struct audio_device *)dev;
3182 struct str_parms *reply = str_parms_create();
3183 struct str_parms *query = str_parms_create_str(keys);
3184 char *str;
3185
3186 pthread_mutex_lock(&adev->lock);
3187
3188 voice_get_parameters(adev, query, reply);
3189 str = str_parms_to_str(reply);
3190 str_parms_destroy(query);
3191 str_parms_destroy(reply);
3192
3193 pthread_mutex_unlock(&adev->lock);
3194 ALOGV("%s: exit: returns - %s", __func__, str);
3195 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196}
3197
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003198static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199{
3200 return 0;
3201}
3202
Haynes Mathew George5191a852013-09-11 14:19:36 -07003203static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3204{
3205 int ret;
3206 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003207
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003208 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3209
Haynes Mathew George5191a852013-09-11 14:19:36 -07003210 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003211 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003212 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003213
Haynes Mathew George5191a852013-09-11 14:19:36 -07003214 return ret;
3215}
3216
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003217static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218{
3219 return -ENOSYS;
3220}
3221
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003222static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3223 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003224{
3225 return -ENOSYS;
3226}
3227
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003228static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003229{
3230 return -ENOSYS;
3231}
3232
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003233static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234{
3235 return -ENOSYS;
3236}
3237
3238static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3239{
3240 struct audio_device *adev = (struct audio_device *)dev;
3241
3242 pthread_mutex_lock(&adev->lock);
3243 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003244 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003245 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003246 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3247 voice_is_in_call(adev)) {
3248 voice_stop_call(adev);
3249 adev->current_call_output = NULL;
3250 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003251 }
3252 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003253
3254 audio_extn_extspk_set_mode(adev->extspk, mode);
3255
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256 return 0;
3257}
3258
3259static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3260{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003261 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263
Eric Laurent2bafff12016-03-17 12:17:23 -07003264 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003265 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003266 ret = voice_set_mic_mute(adev, state);
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003267 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003268 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003269
3270 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271}
3272
3273static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3274{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003275 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276 return 0;
3277}
3278
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003279static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003280 const struct audio_config *config)
3281{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003282 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003284 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3285 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003286}
3287
3288static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003289 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003290 audio_devices_t devices,
3291 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003292 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003293 audio_input_flags_t flags,
3294 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003295 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296{
3297 struct audio_device *adev = (struct audio_device *)dev;
3298 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003299 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003300 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003301 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302
Eric Laurent994a6932013-07-17 11:51:42 -07003303 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304 *stream_in = NULL;
3305 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3306 return -EINVAL;
3307
3308 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3309
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003310 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003311 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003312
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313 in->stream.common.get_sample_rate = in_get_sample_rate;
3314 in->stream.common.set_sample_rate = in_set_sample_rate;
3315 in->stream.common.get_buffer_size = in_get_buffer_size;
3316 in->stream.common.get_channels = in_get_channels;
3317 in->stream.common.get_format = in_get_format;
3318 in->stream.common.set_format = in_set_format;
3319 in->stream.common.standby = in_standby;
3320 in->stream.common.dump = in_dump;
3321 in->stream.common.set_parameters = in_set_parameters;
3322 in->stream.common.get_parameters = in_get_parameters;
3323 in->stream.common.add_audio_effect = in_add_audio_effect;
3324 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3325 in->stream.set_gain = in_set_gain;
3326 in->stream.read = in_read;
3327 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003328 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329
3330 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003331 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003332 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333 in->standby = 1;
3334 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003335 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003336 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337
vivek mehta57ff9b52016-04-28 14:13:08 -07003338 // restrict 24 bit capture for unprocessed source only
3339 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3340 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003341 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003342 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3343 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3344 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3345 bool ret_error = false;
3346 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3347 from HAL is 8_24
3348 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3349 8_24 return error indicating supported format is 8_24
3350 *> In case of any other source requesting 24 bit or float return error
3351 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003352
vivek mehta57ff9b52016-04-28 14:13:08 -07003353 on error flinger will retry with supported format passed
3354 */
3355 if (source != AUDIO_SOURCE_UNPROCESSED) {
3356 config->format = AUDIO_FORMAT_PCM_16_BIT;
3357 ret_error = true;
3358 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3359 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3360 ret_error = true;
3361 }
3362
3363 if (ret_error) {
3364 ret = -EINVAL;
3365 goto err_open;
3366 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003367 }
3368
vivek mehta57ff9b52016-04-28 14:13:08 -07003369 in->format = config->format;
3370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003372 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3373 if (config->sample_rate == 0)
3374 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3375 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3376 config->sample_rate != 8000) {
3377 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3378 ret = -EINVAL;
3379 goto err_open;
3380 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003381
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003382 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3383 config->format = AUDIO_FORMAT_PCM_16_BIT;
3384 ret = -EINVAL;
3385 goto err_open;
3386 }
3387
3388 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3389 in->config = pcm_config_afe_proxy_record;
3390 } else {
3391 in->usecase = USECASE_AUDIO_RECORD;
3392 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3393 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3394 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003395#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003396 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003397#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003398 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003399 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003400
Haynes Mathew George03c40102016-01-29 17:57:48 -08003401 in->config = in->realtime ? pcm_config_audio_capture_rt :
3402 pcm_config_audio_capture;
3403
vivek mehta4ed66e62016-04-15 23:33:34 -07003404 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3405 in->config.format = PCM_FORMAT_S24_LE;
3406
Haynes Mathew George03c40102016-01-29 17:57:48 -08003407 if (!in->realtime) {
3408 frame_size = audio_stream_in_frame_size(&in->stream);
3409 buffer_size = get_input_buffer_size(config->sample_rate,
3410 config->format,
3411 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003412 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003413 in->config.period_size = buffer_size / frame_size;
3414 } // period size is left untouched for rt mode playback
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003415 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003416
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417 in->config.channels = channel_count;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003418 if (in->realtime) {
3419 in->af_period_multiplier = af_period_multiplier;
3420 } else {
3421 in->config.rate = config->sample_rate;
3422 in->af_period_multiplier = 1;
3423 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003425 /* This stream could be for sound trigger lab,
3426 get sound trigger pcm if present */
3427 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003429 lock_input_stream(in);
3430 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3431 pthread_mutex_lock(&adev->lock);
3432 in->card_status = adev->card_status;
3433 pthread_mutex_unlock(&adev->lock);
3434 pthread_mutex_unlock(&in->lock);
3435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003436 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003437 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438 return 0;
3439
3440err_open:
3441 free(in);
3442 *stream_in = NULL;
3443 return ret;
3444}
3445
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003446static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447 struct audio_stream_in *stream)
3448{
Eric Laurent994a6932013-07-17 11:51:42 -07003449 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003450
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003451 // must deregister from sndmonitor first to prevent races
3452 // between the callback and close_stream
3453 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454 in_standby(&stream->common);
3455 free(stream);
3456
3457 return;
3458}
3459
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003460static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461{
3462 return 0;
3463}
3464
Andy Hung31aca912014-03-20 17:14:59 -07003465/* verifies input and output devices and their capabilities.
3466 *
3467 * This verification is required when enabling extended bit-depth or
3468 * sampling rates, as not all qcom products support it.
3469 *
3470 * Suitable for calling only on initialization such as adev_open().
3471 * It fills the audio_device use_case_table[] array.
3472 *
3473 * Has a side-effect that it needs to configure audio routing / devices
3474 * in order to power up the devices and read the device parameters.
3475 * It does not acquire any hw device lock. Should restore the devices
3476 * back to "normal state" upon completion.
3477 */
3478static int adev_verify_devices(struct audio_device *adev)
3479{
3480 /* enumeration is a bit difficult because one really wants to pull
3481 * the use_case, device id, etc from the hidden pcm_device_table[].
3482 * In this case there are the following use cases and device ids.
3483 *
3484 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3485 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3486 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3487 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3488 * [USECASE_AUDIO_RECORD] = {0, 0},
3489 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3490 * [USECASE_VOICE_CALL] = {2, 2},
3491 *
3492 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3493 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3494 */
3495
3496 /* should be the usecases enabled in adev_open_input_stream() */
3497 static const int test_in_usecases[] = {
3498 USECASE_AUDIO_RECORD,
3499 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3500 };
3501 /* should be the usecases enabled in adev_open_output_stream()*/
3502 static const int test_out_usecases[] = {
3503 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3504 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3505 };
3506 static const usecase_type_t usecase_type_by_dir[] = {
3507 PCM_PLAYBACK,
3508 PCM_CAPTURE,
3509 };
3510 static const unsigned flags_by_dir[] = {
3511 PCM_OUT,
3512 PCM_IN,
3513 };
3514
3515 size_t i;
3516 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003517 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003518 char info[512]; /* for possible debug info */
3519
3520 for (dir = 0; dir < 2; ++dir) {
3521 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3522 const unsigned flags_dir = flags_by_dir[dir];
3523 const size_t testsize =
3524 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3525 const int *testcases =
3526 dir ? test_in_usecases : test_out_usecases;
3527 const audio_devices_t audio_device =
3528 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3529
3530 for (i = 0; i < testsize; ++i) {
3531 const audio_usecase_t audio_usecase = testcases[i];
3532 int device_id;
3533 snd_device_t snd_device;
3534 struct pcm_params **pparams;
3535 struct stream_out out;
3536 struct stream_in in;
3537 struct audio_usecase uc_info;
3538 int retval;
3539
3540 pparams = &adev->use_case_table[audio_usecase];
3541 pcm_params_free(*pparams); /* can accept null input */
3542 *pparams = NULL;
3543
3544 /* find the device ID for the use case (signed, for error) */
3545 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3546 if (device_id < 0)
3547 continue;
3548
3549 /* prepare structures for device probing */
3550 memset(&uc_info, 0, sizeof(uc_info));
3551 uc_info.id = audio_usecase;
3552 uc_info.type = usecase_type;
3553 if (dir) {
3554 adev->active_input = &in;
3555 memset(&in, 0, sizeof(in));
3556 in.device = audio_device;
3557 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3558 uc_info.stream.in = &in;
3559 } else {
3560 adev->active_input = NULL;
3561 }
3562 memset(&out, 0, sizeof(out));
3563 out.devices = audio_device; /* only field needed in select_devices */
3564 uc_info.stream.out = &out;
3565 uc_info.devices = audio_device;
3566 uc_info.in_snd_device = SND_DEVICE_NONE;
3567 uc_info.out_snd_device = SND_DEVICE_NONE;
3568 list_add_tail(&adev->usecase_list, &uc_info.list);
3569
3570 /* select device - similar to start_(in/out)put_stream() */
3571 retval = select_devices(adev, audio_usecase);
3572 if (retval >= 0) {
3573 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3574#if LOG_NDEBUG == 0
3575 if (*pparams) {
3576 ALOGV("%s: (%s) card %d device %d", __func__,
3577 dir ? "input" : "output", card_id, device_id);
3578 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07003579 } else {
3580 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3581 }
3582#endif
3583 }
3584
3585 /* deselect device - similar to stop_(in/out)put_stream() */
3586 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07003587 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07003588 /* 2. Disable the rx device */
3589 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07003590 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07003591 list_remove(&uc_info.list);
3592 }
3593 }
3594 adev->active_input = NULL; /* restore adev state */
3595 return 0;
3596}
3597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003598static int adev_close(hw_device_t *device)
3599{
Andy Hung31aca912014-03-20 17:14:59 -07003600 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003601 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003602
3603 if (!adev)
3604 return 0;
3605
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003606 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003607 pthread_mutex_lock(&adev_init_lock);
3608
3609 if ((--audio_device_ref_count) == 0) {
3610 audio_route_free(adev->audio_route);
3611 free(adev->snd_dev_ref_cnt);
3612 platform_deinit(adev->platform);
3613 audio_extn_extspk_deinit(adev->extspk);
3614 audio_extn_sound_trigger_deinit(adev);
3615 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3616 pcm_params_free(adev->use_case_table[i]);
3617 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003618 if (adev->adm_deinit)
3619 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003620 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07003621 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07003622
3623 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003624
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625 return 0;
3626}
3627
Glenn Kasten4f993392014-05-14 07:30:48 -07003628/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3629 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3630 * just that it _might_ work.
3631 */
3632static int period_size_is_plausible_for_low_latency(int period_size)
3633{
3634 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003635 case 48:
3636 case 96:
3637 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07003638 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003639 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07003640 case 240:
3641 case 320:
3642 case 480:
3643 return 1;
3644 default:
3645 return 0;
3646 }
3647}
3648
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003649static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
3650{
3651 int card;
3652 card_status_t status;
3653
3654 if (!parms)
3655 return;
3656
3657 if (parse_snd_card_status(parms, &card, &status) < 0)
3658 return;
3659
3660 pthread_mutex_lock(&adev->lock);
3661 bool valid_cb = (card == adev->snd_card);
3662 if (valid_cb) {
3663 if (adev->card_status != status) {
3664 adev->card_status = status;
3665 platform_snd_card_update(adev->platform, status);
3666 }
3667 }
3668 pthread_mutex_unlock(&adev->lock);
3669 return;
3670}
3671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672static int adev_open(const hw_module_t *module, const char *name,
3673 hw_device_t **device)
3674{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003675 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003676
Eric Laurent2bafff12016-03-17 12:17:23 -07003677 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003679 pthread_mutex_lock(&adev_init_lock);
3680 if (audio_device_ref_count != 0) {
3681 *device = &adev->device.common;
3682 audio_device_ref_count++;
3683 ALOGV("%s: returning existing instance of adev", __func__);
3684 ALOGV("%s: exit", __func__);
3685 pthread_mutex_unlock(&adev_init_lock);
3686 return 0;
3687 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688 adev = calloc(1, sizeof(struct audio_device));
3689
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003690 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3691
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3693 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3694 adev->device.common.module = (struct hw_module_t *)module;
3695 adev->device.common.close = adev_close;
3696
3697 adev->device.init_check = adev_init_check;
3698 adev->device.set_voice_volume = adev_set_voice_volume;
3699 adev->device.set_master_volume = adev_set_master_volume;
3700 adev->device.get_master_volume = adev_get_master_volume;
3701 adev->device.set_master_mute = adev_set_master_mute;
3702 adev->device.get_master_mute = adev_get_master_mute;
3703 adev->device.set_mode = adev_set_mode;
3704 adev->device.set_mic_mute = adev_set_mic_mute;
3705 adev->device.get_mic_mute = adev_get_mic_mute;
3706 adev->device.set_parameters = adev_set_parameters;
3707 adev->device.get_parameters = adev_get_parameters;
3708 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3709 adev->device.open_output_stream = adev_open_output_stream;
3710 adev->device.close_output_stream = adev_close_output_stream;
3711 adev->device.open_input_stream = adev_open_input_stream;
3712 adev->device.close_input_stream = adev_close_input_stream;
3713 adev->device.dump = adev_dump;
3714
3715 /* Set the default route before the PCM stream is opened */
3716 pthread_mutex_lock(&adev->lock);
3717 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003718 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003719 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003721 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003722 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003723 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003724 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003725 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726 pthread_mutex_unlock(&adev->lock);
3727
3728 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003729 adev->platform = platform_init(adev);
3730 if (!adev->platform) {
3731 free(adev->snd_dev_ref_cnt);
3732 free(adev);
3733 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3734 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003735 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003736 return -EINVAL;
3737 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05003738 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003739 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003740
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003741 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3742 if (adev->visualizer_lib == NULL) {
3743 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3744 } else {
3745 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3746 adev->visualizer_start_output =
3747 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3748 "visualizer_hal_start_output");
3749 adev->visualizer_stop_output =
3750 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3751 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07003752 }
3753
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003754 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3755 if (adev->offload_effects_lib == NULL) {
3756 ALOGW("%s: DLOPEN failed for %s", __func__,
3757 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3758 } else {
3759 ALOGV("%s: DLOPEN successful for %s", __func__,
3760 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3761 adev->offload_effects_start_output =
3762 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3763 "offload_effects_bundle_hal_start_output");
3764 adev->offload_effects_stop_output =
3765 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3766 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07003767 }
3768
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003769 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3770 if (adev->adm_lib == NULL) {
3771 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3772 } else {
3773 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3774 adev->adm_init = (adm_init_t)
3775 dlsym(adev->adm_lib, "adm_init");
3776 adev->adm_deinit = (adm_deinit_t)
3777 dlsym(adev->adm_lib, "adm_deinit");
3778 adev->adm_register_input_stream = (adm_register_input_stream_t)
3779 dlsym(adev->adm_lib, "adm_register_input_stream");
3780 adev->adm_register_output_stream = (adm_register_output_stream_t)
3781 dlsym(adev->adm_lib, "adm_register_output_stream");
3782 adev->adm_deregister_stream = (adm_deregister_stream_t)
3783 dlsym(adev->adm_lib, "adm_deregister_stream");
3784 adev->adm_request_focus = (adm_request_focus_t)
3785 dlsym(adev->adm_lib, "adm_request_focus");
3786 adev->adm_abandon_focus = (adm_abandon_focus_t)
3787 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08003788 adev->adm_set_config = (adm_set_config_t)
3789 dlsym(adev->adm_lib, "adm_set_config");
3790 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
3791 dlsym(adev->adm_lib, "adm_request_focus_v2");
3792 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
3793 dlsym(adev->adm_lib, "adm_is_noirq_avail");
3794 adev->adm_on_routing_change = (adm_on_routing_change_t)
3795 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003796 }
3797
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003798 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003799 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003802
Andy Hung31aca912014-03-20 17:14:59 -07003803 if (k_enable_extended_precision)
3804 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805
Glenn Kasten4f993392014-05-14 07:30:48 -07003806 char value[PROPERTY_VALUE_MAX];
3807 int trial;
3808 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3809 trial = atoi(value);
3810 if (period_size_is_plausible_for_low_latency(trial)) {
3811 pcm_config_low_latency.period_size = trial;
3812 pcm_config_low_latency.start_threshold = trial / 4;
3813 pcm_config_low_latency.avail_min = trial / 4;
3814 configured_low_latency_capture_period_size = trial;
3815 }
3816 }
3817 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3818 trial = atoi(value);
3819 if (period_size_is_plausible_for_low_latency(trial)) {
3820 configured_low_latency_capture_period_size = trial;
3821 }
3822 }
3823
Yamit Mehtae3b99562016-09-16 22:44:00 +05303824 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003825 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003826
3827 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
3828 af_period_multiplier = atoi(value);
3829 if (af_period_multiplier < 0) {
3830 af_period_multiplier = 2;
3831 } else if (af_period_multiplier > 4) {
3832 af_period_multiplier = 4;
3833 }
3834 ALOGV("new period_multiplier = %d", af_period_multiplier);
3835 }
3836
vivek mehta1a9b7c02015-06-25 11:49:38 -07003837 pthread_mutex_unlock(&adev_init_lock);
3838
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003839 if (adev->adm_init)
3840 adev->adm_data = adev->adm_init();
3841
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003842 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003843 audio_extn_snd_mon_init();
3844 pthread_mutex_lock(&adev->lock);
3845 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
3846 adev->card_status = CARD_STATUS_ONLINE;
3847 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003848
Eric Laurent2bafff12016-03-17 12:17:23 -07003849 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003850 return 0;
3851}
3852
3853static struct hw_module_methods_t hal_module_methods = {
3854 .open = adev_open,
3855};
3856
3857struct audio_module HAL_MODULE_INFO_SYM = {
3858 .common = {
3859 .tag = HARDWARE_MODULE_TAG,
3860 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3861 .hal_api_version = HARDWARE_HAL_API_VERSION,
3862 .id = AUDIO_HARDWARE_MODULE_ID,
3863 .name = "QCOM Audio HAL",
3864 .author = "Code Aurora Forum",
3865 .methods = &hal_module_methods,
3866 },
3867};