blob: d25dd0a6db3986216fd9ed07f7bdc9d6db4fe1f4 [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,
2180 const void *buffer, size_t bytes)
2181{
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);
Uday Kishore Pasupuletib14d76b2015-11-13 20:06:37 -08002188 usleep(bytes * 1000000 / audio_stream_out_frame_size(&out->stream.common) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002189 out_get_sample_rate(&out->stream.common));
2190 pthread_mutex_unlock(&out->lock);
2191 return bytes;
2192}
2193#endif
2194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2196 size_t bytes)
2197{
2198 struct stream_out *out = (struct stream_out *)stream;
2199 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002200 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002201 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002202
Eric Laurenta1478072015-09-21 17:21:52 -07002203 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002204 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002205 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002206 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002208 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002209 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002211 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212 goto exit;
2213 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002214
2215 if (last_known_cal_step != -1) {
2216 ALOGD("%s: retry previous failed cal level set", __func__);
2217 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2218 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002221 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002222 ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
2223 if (out->send_new_metadata) {
2224 ALOGVV("send new gapless metadata");
2225 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2226 out->send_new_metadata = 0;
2227 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002228 unsigned int avail;
2229 struct timespec tstamp;
2230 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2231 /* Do not limit write size if the available frames count is unknown */
2232 if (ret != 0) {
2233 avail = bytes;
2234 }
2235 if (avail == 0) {
2236 ret = 0;
2237 } else {
2238 if (avail > bytes) {
2239 avail = bytes;
2240 }
2241 ret = compress_write(out->compr, buffer, avail);
2242 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2243 __func__, avail, ret);
2244 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002245
Eric Laurent6e895242013-09-05 16:10:57 -07002246 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002247 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2248 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002249 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002250 compress_start(out->compr);
2251 out->playback_started = 1;
2252 out->offload_state = OFFLOAD_STATE_PLAYING;
2253 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002254 if (ret < 0) {
2255 log_error_l(&out->error_log, ERROR_CODE_WRITE);
2256 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002257 pthread_mutex_unlock(&out->lock);
2258 return ret;
2259 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002260 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002261 if (out->pcm) {
2262 if (out->muted)
2263 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002264
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002265 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002266
Haynes Mathew George03c40102016-01-29 17:57:48 -08002267 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2268 out->config.rate;
2269 request_out_focus(out, ns);
2270
2271 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2272 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002273 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002274 else
2275 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002276
Haynes Mathew George03c40102016-01-29 17:57:48 -08002277 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002278 } else {
2279 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002280 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002281 }
2282
2283exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002284 // For PCM we always consume the buffer and return #bytes regardless of ret.
2285 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2286 out->written += bytes / (out->config.channels * sizeof(short));
2287 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002288 long long sleeptime_us = 0;
2289 if (ret != 0) {
2290 log_error_l(&out->error_log, error_code);
2291 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2292 ALOGE_IF(out->pcm != NULL,
2293 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
2294 sleeptime_us = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2295 out_get_sample_rate(&out->stream.common);
2296 // usleep not guaranteed for values over 1 second but we don't limit here.
2297 }
2298 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300 pthread_mutex_unlock(&out->lock);
2301
2302 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002303 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002304 if (sleeptime_us != 0)
2305 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002306 }
2307 return bytes;
2308}
2309
2310static int out_get_render_position(const struct audio_stream_out *stream,
2311 uint32_t *dsp_frames)
2312{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002313 struct stream_out *out = (struct stream_out *)stream;
2314 *dsp_frames = 0;
2315 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002316 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002317 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002318 unsigned long frames = 0;
2319 // TODO: check return value
2320 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2321 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002322 ALOGVV("%s rendered frames %d sample_rate %d",
2323 __func__, *dsp_frames, out->sample_rate);
2324 }
2325 pthread_mutex_unlock(&out->lock);
2326 return 0;
2327 } else
2328 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002329}
2330
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002331static int out_add_audio_effect(const struct audio_stream *stream __unused,
2332 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002333{
2334 return 0;
2335}
2336
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002337static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2338 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002339{
2340 return 0;
2341}
2342
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002343static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2344 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002345{
2346 return -EINVAL;
2347}
2348
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002349static int out_get_presentation_position(const struct audio_stream_out *stream,
2350 uint64_t *frames, struct timespec *timestamp)
2351{
2352 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002353 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002354 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002355
Eric Laurenta1478072015-09-21 17:21:52 -07002356 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002357
Eric Laurent949a0892013-09-20 09:20:13 -07002358 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2359 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002360 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002361 compress_get_tstamp(out->compr, &dsp_frames,
2362 &out->sample_rate);
2363 ALOGVV("%s rendered frames %ld sample_rate %d",
2364 __func__, dsp_frames, out->sample_rate);
2365 *frames = dsp_frames;
2366 ret = 0;
2367 /* this is the best we can do */
2368 clock_gettime(CLOCK_MONOTONIC, timestamp);
2369 }
2370 } else {
2371 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002372 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002373 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2374 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002375 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002376 // This adjustment accounts for buffering after app processor.
2377 // It is based on estimated DSP latency per use case, rather than exact.
2378 signed_frames -=
2379 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2380
Eric Laurent949a0892013-09-20 09:20:13 -07002381 // It would be unusual for this value to be negative, but check just in case ...
2382 if (signed_frames >= 0) {
2383 *frames = signed_frames;
2384 ret = 0;
2385 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002386 }
2387 }
2388 }
2389
2390 pthread_mutex_unlock(&out->lock);
2391
2392 return ret;
2393}
2394
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002395static int out_set_callback(struct audio_stream_out *stream,
2396 stream_callback_t callback, void *cookie)
2397{
2398 struct stream_out *out = (struct stream_out *)stream;
2399
2400 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002401 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002402 out->offload_callback = callback;
2403 out->offload_cookie = cookie;
2404 pthread_mutex_unlock(&out->lock);
2405 return 0;
2406}
2407
2408static int out_pause(struct audio_stream_out* stream)
2409{
2410 struct stream_out *out = (struct stream_out *)stream;
2411 int status = -ENOSYS;
2412 ALOGV("%s", __func__);
2413 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002414 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002415 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2416 status = compress_pause(out->compr);
2417 out->offload_state = OFFLOAD_STATE_PAUSED;
2418 }
2419 pthread_mutex_unlock(&out->lock);
2420 }
2421 return status;
2422}
2423
2424static int out_resume(struct audio_stream_out* stream)
2425{
2426 struct stream_out *out = (struct stream_out *)stream;
2427 int status = -ENOSYS;
2428 ALOGV("%s", __func__);
2429 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2430 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002431 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002432 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2433 status = compress_resume(out->compr);
2434 out->offload_state = OFFLOAD_STATE_PLAYING;
2435 }
2436 pthread_mutex_unlock(&out->lock);
2437 }
2438 return status;
2439}
2440
2441static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2442{
2443 struct stream_out *out = (struct stream_out *)stream;
2444 int status = -ENOSYS;
2445 ALOGV("%s", __func__);
2446 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002447 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002448 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2449 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2450 else
2451 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2452 pthread_mutex_unlock(&out->lock);
2453 }
2454 return status;
2455}
2456
2457static int out_flush(struct audio_stream_out* stream)
2458{
2459 struct stream_out *out = (struct stream_out *)stream;
2460 ALOGV("%s", __func__);
2461 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002462 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002463 stop_compressed_output_l(out);
2464 pthread_mutex_unlock(&out->lock);
2465 return 0;
2466 }
2467 return -ENOSYS;
2468}
2469
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470/** audio_stream_in implementation **/
2471static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2472{
2473 struct stream_in *in = (struct stream_in *)stream;
2474
2475 return in->config.rate;
2476}
2477
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002478static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002479{
2480 return -ENOSYS;
2481}
2482
2483static size_t in_get_buffer_size(const struct audio_stream *stream)
2484{
2485 struct stream_in *in = (struct stream_in *)stream;
2486
Haynes Mathew George03c40102016-01-29 17:57:48 -08002487 return in->config.period_size * in->af_period_multiplier *
2488 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489}
2490
2491static uint32_t in_get_channels(const struct audio_stream *stream)
2492{
2493 struct stream_in *in = (struct stream_in *)stream;
2494
2495 return in->channel_mask;
2496}
2497
vivek mehta4ed66e62016-04-15 23:33:34 -07002498static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499{
vivek mehta4ed66e62016-04-15 23:33:34 -07002500 struct stream_in *in = (struct stream_in *)stream;
2501 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502}
2503
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002504static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505{
2506 return -ENOSYS;
2507}
2508
2509static int in_standby(struct audio_stream *stream)
2510{
2511 struct stream_in *in = (struct stream_in *)stream;
2512 struct audio_device *adev = in->dev;
2513 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07002514 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002515
2516 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002517
2518 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002519 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002520 audio_extn_sound_trigger_stop_lab(in);
2521 in->standby = true;
2522 }
2523
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002525 if (adev->adm_deregister_stream)
2526 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2527
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002528 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002530 if (in->pcm) {
2531 pcm_close(in->pcm);
2532 in->pcm = NULL;
2533 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002534 adev->enable_voicerx = false;
2535 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002537 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538 }
2539 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002540 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541 return status;
2542}
2543
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002544static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545{
2546 return 0;
2547}
2548
2549static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2550{
2551 struct stream_in *in = (struct stream_in *)stream;
2552 struct audio_device *adev = in->dev;
2553 struct str_parms *parms;
2554 char *str;
2555 char value[32];
2556 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002557 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558
Eric Laurent994a6932013-07-17 11:51:42 -07002559 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560 parms = str_parms_create_str(kvpairs);
2561
2562 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2563
Eric Laurenta1478072015-09-21 17:21:52 -07002564 lock_input_stream(in);
2565
Eric Laurent150dbfe2013-02-27 14:31:02 -08002566 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567 if (ret >= 0) {
2568 val = atoi(value);
2569 /* no audio source uses val == 0 */
2570 if ((in->source != val) && (val != 0)) {
2571 in->source = val;
2572 }
2573 }
2574
2575 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002576
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 if (ret >= 0) {
2578 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002579 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 in->device = val;
2581 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002582 if (!in->standby) {
2583 ALOGV("update input routing change");
2584 in->routing_change = true;
2585 select_devices(adev, in->usecase);
2586 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 }
2588 }
2589
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002591 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592
2593 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002594 ALOGV("%s: exit: status(%d)", __func__, status);
2595 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596}
2597
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002598static char* in_get_parameters(const struct audio_stream *stream __unused,
2599 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600{
2601 return strdup("");
2602}
2603
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002604static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002605{
2606 return 0;
2607}
2608
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002609static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2610{
2611 if (!stream || !parms)
2612 return;
2613
2614 struct stream_in *in = (struct stream_in *)stream;
2615 struct audio_device *adev = in->dev;
2616
2617 card_status_t status;
2618 int card;
2619 if (parse_snd_card_status(parms, &card, &status) < 0)
2620 return;
2621
2622 pthread_mutex_lock(&adev->lock);
2623 bool valid_cb = (card == adev->snd_card);
2624 pthread_mutex_unlock(&adev->lock);
2625
2626 if (!valid_cb)
2627 return;
2628
2629 lock_input_stream(in);
2630 if (in->card_status != status)
2631 in->card_status = status;
2632 pthread_mutex_unlock(&in->lock);
2633
2634 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2635 use_case_table[in->usecase],
2636 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2637
2638 // a better solution would be to report error back to AF and let
2639 // it put the stream to standby
2640 if (status == CARD_STATUS_OFFLINE)
2641 in_standby(&in->stream.common);
2642
2643 return;
2644}
2645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002646static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2647 size_t bytes)
2648{
2649 struct stream_in *in = (struct stream_in *)stream;
2650 struct audio_device *adev = in->dev;
2651 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002652 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653
Eric Laurenta1478072015-09-21 17:21:52 -07002654 lock_input_stream(in);
2655
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002656 if (in->is_st_session) {
2657 ALOGVV(" %s: reading on st session bytes=%d", __func__, bytes);
2658 /* Read from sound trigger HAL */
2659 audio_extn_sound_trigger_read(in, buffer, bytes);
2660 pthread_mutex_unlock(&in->lock);
2661 return bytes;
2662 }
2663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002665 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002667 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669 goto exit;
2670 }
2671 in->standby = 0;
2672 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673
Haynes Mathew George03c40102016-01-29 17:57:48 -08002674 //what's the duration requested by the client?
2675 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2676 in->config.rate;
2677 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002678
Haynes Mathew George03c40102016-01-29 17:57:48 -08002679 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002680 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002681 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002682 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002683 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002684 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002685 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002686 if (ret < 0) {
2687 ALOGE("Failed to read w/err %s", strerror(errno));
2688 ret = -errno;
2689 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002690 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2691 if (bytes % 4 == 0) {
2692 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2693 int_buf_stream = buffer;
2694 for (size_t itt=0; itt < bytes/4 ; itt++) {
2695 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002696 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002697 } else {
2698 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2699 ret = -EINVAL;
2700 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002701 }
2702 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703 }
2704
Haynes Mathew George03c40102016-01-29 17:57:48 -08002705 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002706
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707 /*
2708 * Instead of writing zeroes here, we could trust the hardware
2709 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002710 * 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 -08002711 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002712 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713 memset(buffer, 0, bytes);
2714
2715exit:
2716 pthread_mutex_unlock(&in->lock);
2717
2718 if (ret != 0) {
2719 in_standby(&in->stream.common);
2720 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002721 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002723 memset(buffer, 0, bytes); // clear return data
2724 }
2725 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002726 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727 }
2728 return bytes;
2729}
2730
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002731static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002732{
2733 return 0;
2734}
2735
Andy Hung6ebe5962016-01-15 17:46:57 -08002736static int in_get_capture_position(const struct audio_stream_in *stream,
2737 int64_t *frames, int64_t *time)
2738{
2739 if (stream == NULL || frames == NULL || time == NULL) {
2740 return -EINVAL;
2741 }
2742 struct stream_in *in = (struct stream_in *)stream;
2743 int ret = -ENOSYS;
2744
2745 lock_input_stream(in);
2746 if (in->pcm) {
2747 struct timespec timestamp;
2748 unsigned int avail;
2749 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2750 *frames = in->frames_read + avail;
2751 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2752 ret = 0;
2753 }
2754 }
2755 pthread_mutex_unlock(&in->lock);
2756 return ret;
2757}
2758
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002759static int add_remove_audio_effect(const struct audio_stream *stream,
2760 effect_handle_t effect,
2761 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002763 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002764 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002765 int status = 0;
2766 effect_descriptor_t desc;
2767
2768 status = (*effect)->get_descriptor(effect, &desc);
2769 if (status != 0)
2770 return status;
2771
Eric Laurenta1478072015-09-21 17:21:52 -07002772 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002773 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002774 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002775 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002776 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002777 in->enable_aec != enable &&
2778 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2779 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002780 if (!enable)
2781 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002782 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2783 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2784 adev->enable_voicerx = enable;
2785 struct audio_usecase *usecase;
2786 struct listnode *node;
2787 list_for_each(node, &adev->usecase_list) {
2788 usecase = node_to_item(node, struct audio_usecase, list);
2789 if (usecase->type == PCM_PLAYBACK) {
2790 select_devices(adev, usecase->id);
2791 break;
2792 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002793 }
2794 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002795 if (!in->standby)
2796 select_devices(in->dev, in->usecase);
2797 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07002798 if (in->enable_ns != enable &&
2799 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2800 in->enable_ns = enable;
2801 if (!in->standby)
2802 select_devices(in->dev, in->usecase);
2803 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002804 pthread_mutex_unlock(&in->dev->lock);
2805 pthread_mutex_unlock(&in->lock);
2806
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002807 return 0;
2808}
2809
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002810static int in_add_audio_effect(const struct audio_stream *stream,
2811 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812{
Eric Laurent994a6932013-07-17 11:51:42 -07002813 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002814 return add_remove_audio_effect(stream, effect, true);
2815}
2816
2817static int in_remove_audio_effect(const struct audio_stream *stream,
2818 effect_handle_t effect)
2819{
Eric Laurent994a6932013-07-17 11:51:42 -07002820 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002821 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822}
2823
2824static int adev_open_output_stream(struct audio_hw_device *dev,
2825 audio_io_handle_t handle,
2826 audio_devices_t devices,
2827 audio_output_flags_t flags,
2828 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07002829 struct audio_stream_out **stream_out,
2830 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831{
2832 struct audio_device *adev = (struct audio_device *)dev;
2833 struct stream_out *out;
2834 int i, ret;
2835
Eric Laurent994a6932013-07-17 11:51:42 -07002836 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002837 __func__, config->sample_rate, config->channel_mask, devices, flags);
2838 *stream_out = NULL;
2839 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2840
2841 if (devices == AUDIO_DEVICE_NONE)
2842 devices = AUDIO_DEVICE_OUT_SPEAKER;
2843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002844 out->flags = flags;
2845 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002846 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002847 out->format = config->format;
2848 out->sample_rate = config->sample_rate;
2849 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2850 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002851 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002852
2853 /* Init use case and pcm_config */
2854 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07002855 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002856 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002857 pthread_mutex_lock(&adev->lock);
2858 ret = read_hdmi_channel_masks(out);
2859 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002860 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002861 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002862
2863 if (config->sample_rate == 0)
2864 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2865 if (config->channel_mask == 0)
2866 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08002867 if (config->format == AUDIO_FORMAT_DEFAULT)
2868 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002869
2870 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002871 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08002872 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2874 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002876 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002877 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002878 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07002879 pthread_mutex_lock(&adev->lock);
2880 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
2881 pthread_mutex_unlock(&adev->lock);
2882
2883 // reject offload during card offline to allow
2884 // fallback to s/w paths
2885 if (offline) {
2886 ret = -ENODEV;
2887 goto error_open;
2888 }
2889
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002890 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2891 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2892 ALOGE("%s: Unsupported Offload information", __func__);
2893 ret = -EINVAL;
2894 goto error_open;
2895 }
2896 if (!is_supported_format(config->offload_info.format)) {
2897 ALOGE("%s: Unsupported audio format", __func__);
2898 ret = -EINVAL;
2899 goto error_open;
2900 }
2901
2902 out->compr_config.codec = (struct snd_codec *)
2903 calloc(1, sizeof(struct snd_codec));
2904
2905 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
2906 if (config->offload_info.channel_mask)
2907 out->channel_mask = config->offload_info.channel_mask;
2908 else if (config->channel_mask)
2909 out->channel_mask = config->channel_mask;
2910 out->format = config->offload_info.format;
2911 out->sample_rate = config->offload_info.sample_rate;
2912
2913 out->stream.set_callback = out_set_callback;
2914 out->stream.pause = out_pause;
2915 out->stream.resume = out_resume;
2916 out->stream.drain = out_drain;
2917 out->stream.flush = out_flush;
2918
2919 out->compr_config.codec->id =
2920 get_snd_codec_id(config->offload_info.format);
2921 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
2922 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07002923 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002924 out->compr_config.codec->bit_rate =
2925 config->offload_info.bit_rate;
2926 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002927 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002928 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
2929
2930 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2931 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002932
2933 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002934 create_offload_callback_thread(out);
2935 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2936 __func__, config->offload_info.version,
2937 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002938 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2939 if (config->sample_rate == 0)
2940 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2941 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2942 config->sample_rate != 8000) {
2943 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2944 ret = -EINVAL;
2945 goto error_open;
2946 }
2947 out->sample_rate = config->sample_rate;
2948 out->config.rate = config->sample_rate;
2949 if (config->format == AUDIO_FORMAT_DEFAULT)
2950 config->format = AUDIO_FORMAT_PCM_16_BIT;
2951 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2952 config->format = AUDIO_FORMAT_PCM_16_BIT;
2953 ret = -EINVAL;
2954 goto error_open;
2955 }
2956 out->format = config->format;
2957 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2958 out->config = pcm_config_afe_proxy_playback;
2959 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002960 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07002961 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2962 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2963 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07002964 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
2965 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
2966 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07002967 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
2968 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002969 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
2970 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
2971 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Andy Hung6fcba9c2014-03-18 11:53:32 -07002972 } else {
2973 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2974 out->config = pcm_config_low_latency;
2975 }
2976 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2977 if (k_enable_extended_precision
2978 && pcm_params_format_test(adev->use_case_table[out->usecase],
2979 pcm_format_from_audio_format(config->format))) {
2980 out->config.format = pcm_format_from_audio_format(config->format);
2981 /* out->format already set to config->format */
2982 } else {
2983 /* deny the externally proposed config format
2984 * and use the one specified in audio_hw layer configuration.
2985 * Note: out->format is returned by out->stream.common.get_format()
2986 * and is used to set config->format in the code several lines below.
2987 */
2988 out->format = audio_format_from_pcm_format(out->config.format);
2989 }
2990 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002991 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07002993 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
2994 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002996 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002997 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002998 adev->primary_output = out;
2999 else {
3000 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003001 ret = -EEXIST;
3002 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003003 }
3004 }
3005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006 /* Check if this usecase is already existing */
3007 pthread_mutex_lock(&adev->lock);
3008 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3009 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003011 ret = -EEXIST;
3012 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003013 }
3014 pthread_mutex_unlock(&adev->lock);
3015
3016 out->stream.common.get_sample_rate = out_get_sample_rate;
3017 out->stream.common.set_sample_rate = out_set_sample_rate;
3018 out->stream.common.get_buffer_size = out_get_buffer_size;
3019 out->stream.common.get_channels = out_get_channels;
3020 out->stream.common.get_format = out_get_format;
3021 out->stream.common.set_format = out_set_format;
3022 out->stream.common.standby = out_standby;
3023 out->stream.common.dump = out_dump;
3024 out->stream.common.set_parameters = out_set_parameters;
3025 out->stream.common.get_parameters = out_get_parameters;
3026 out->stream.common.add_audio_effect = out_add_audio_effect;
3027 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3028 out->stream.get_latency = out_get_latency;
3029 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003030#ifdef NO_AUDIO_OUT
3031 out->stream.write = out_write_for_no_output;
3032#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003034#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035 out->stream.get_render_position = out_get_render_position;
3036 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003037 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038
Haynes Mathew George03c40102016-01-29 17:57:48 -08003039 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003041 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003042 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003044 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003045 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003046 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3047
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048 config->format = out->stream.common.get_format(&out->stream.common);
3049 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3050 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3051
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003052
3053 /*
3054 By locking output stream before registering, we allow the callback
3055 to update stream's state only after stream's initial state is set to
3056 adev state.
3057 */
3058 lock_output_stream(out);
3059 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3060 pthread_mutex_lock(&adev->lock);
3061 out->card_status = adev->card_status;
3062 pthread_mutex_unlock(&adev->lock);
3063 pthread_mutex_unlock(&out->lock);
3064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003066 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003068
3069error_open:
3070 free(out);
3071 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003072 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003073 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074}
3075
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003076static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077 struct audio_stream_out *stream)
3078{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003079 struct stream_out *out = (struct stream_out *)stream;
3080 struct audio_device *adev = out->dev;
3081
Eric Laurent994a6932013-07-17 11:51:42 -07003082 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003083
3084 // must deregister from sndmonitor first to prevent races
3085 // between the callback and close_stream
3086 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003087 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003088 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3089 destroy_offload_callback_thread(out);
3090
3091 if (out->compr_config.codec != NULL)
3092 free(out->compr_config.codec);
3093 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003094
3095 if (adev->voice_tx_output == out)
3096 adev->voice_tx_output = NULL;
3097
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003098 pthread_cond_destroy(&out->cond);
3099 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003100 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003101 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102}
3103
3104static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3105{
3106 struct audio_device *adev = (struct audio_device *)dev;
3107 struct str_parms *parms;
3108 char *str;
3109 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003110 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003112 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113
Joe Onorato188b6222016-03-01 11:02:27 -08003114 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003115
3116 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117
3118 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003119 status = voice_set_parameters(adev, parms);
3120 if (status != 0) {
3121 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122 }
3123
3124 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3125 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003126 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3128 adev->bluetooth_nrec = true;
3129 else
3130 adev->bluetooth_nrec = false;
3131 }
3132
3133 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3134 if (ret >= 0) {
3135 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3136 adev->screen_off = false;
3137 else
3138 adev->screen_off = true;
3139 }
3140
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003141 ret = str_parms_get_int(parms, "rotation", &val);
3142 if (ret >= 0) {
3143 bool reverse_speakers = false;
3144 switch(val) {
3145 // FIXME: note that the code below assumes that the speakers are in the correct placement
3146 // relative to the user when the device is rotated 90deg from its default rotation. This
3147 // assumption is device-specific, not platform-specific like this code.
3148 case 270:
3149 reverse_speakers = true;
3150 break;
3151 case 0:
3152 case 90:
3153 case 180:
3154 break;
3155 default:
3156 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003157 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003158 }
Eric Laurent03f09432014-03-25 18:09:11 -07003159 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003160 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003161 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003162 }
3163
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003164 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3165 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003166 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003167 }
3168
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003169 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003170done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003172 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003173 ALOGV("%s: exit with code(%d)", __func__, status);
3174 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175}
3176
3177static char* adev_get_parameters(const struct audio_hw_device *dev,
3178 const char *keys)
3179{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003180 struct audio_device *adev = (struct audio_device *)dev;
3181 struct str_parms *reply = str_parms_create();
3182 struct str_parms *query = str_parms_create_str(keys);
3183 char *str;
3184
3185 pthread_mutex_lock(&adev->lock);
3186
3187 voice_get_parameters(adev, query, reply);
3188 str = str_parms_to_str(reply);
3189 str_parms_destroy(query);
3190 str_parms_destroy(reply);
3191
3192 pthread_mutex_unlock(&adev->lock);
3193 ALOGV("%s: exit: returns - %s", __func__, str);
3194 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195}
3196
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003197static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198{
3199 return 0;
3200}
3201
Haynes Mathew George5191a852013-09-11 14:19:36 -07003202static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3203{
3204 int ret;
3205 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003206
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003207 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3208
Haynes Mathew George5191a852013-09-11 14:19:36 -07003209 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003210 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003211 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003212
Haynes Mathew George5191a852013-09-11 14:19:36 -07003213 return ret;
3214}
3215
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003216static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003217{
3218 return -ENOSYS;
3219}
3220
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003221static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3222 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003223{
3224 return -ENOSYS;
3225}
3226
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003227static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003228{
3229 return -ENOSYS;
3230}
3231
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003232static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233{
3234 return -ENOSYS;
3235}
3236
3237static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3238{
3239 struct audio_device *adev = (struct audio_device *)dev;
3240
3241 pthread_mutex_lock(&adev->lock);
3242 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003243 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003245 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3246 voice_is_in_call(adev)) {
3247 voice_stop_call(adev);
3248 adev->current_call_output = NULL;
3249 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250 }
3251 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003252
3253 audio_extn_extspk_set_mode(adev->extspk, mode);
3254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003255 return 0;
3256}
3257
3258static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3259{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003260 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262
Eric Laurent2bafff12016-03-17 12:17:23 -07003263 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003264 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003265 ret = voice_set_mic_mute(adev, state);
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003266 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003267 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003268
3269 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003270}
3271
3272static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3273{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003274 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275 return 0;
3276}
3277
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003278static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279 const struct audio_config *config)
3280{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003281 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003282
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003283 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3284 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285}
3286
3287static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003288 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003289 audio_devices_t devices,
3290 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003291 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003292 audio_input_flags_t flags,
3293 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003294 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295{
3296 struct audio_device *adev = (struct audio_device *)dev;
3297 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003298 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003299 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003300 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003301
Eric Laurent994a6932013-07-17 11:51:42 -07003302 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003303 *stream_in = NULL;
3304 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3305 return -EINVAL;
3306
3307 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3308
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003309 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003310 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003311
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312 in->stream.common.get_sample_rate = in_get_sample_rate;
3313 in->stream.common.set_sample_rate = in_set_sample_rate;
3314 in->stream.common.get_buffer_size = in_get_buffer_size;
3315 in->stream.common.get_channels = in_get_channels;
3316 in->stream.common.get_format = in_get_format;
3317 in->stream.common.set_format = in_set_format;
3318 in->stream.common.standby = in_standby;
3319 in->stream.common.dump = in_dump;
3320 in->stream.common.set_parameters = in_set_parameters;
3321 in->stream.common.get_parameters = in_get_parameters;
3322 in->stream.common.add_audio_effect = in_add_audio_effect;
3323 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3324 in->stream.set_gain = in_set_gain;
3325 in->stream.read = in_read;
3326 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003327 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328
3329 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003330 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003332 in->standby = 1;
3333 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003334 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003335 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336
vivek mehta57ff9b52016-04-28 14:13:08 -07003337 // restrict 24 bit capture for unprocessed source only
3338 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3339 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003340 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003341 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3342 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3343 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3344 bool ret_error = false;
3345 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3346 from HAL is 8_24
3347 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3348 8_24 return error indicating supported format is 8_24
3349 *> In case of any other source requesting 24 bit or float return error
3350 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003351
vivek mehta57ff9b52016-04-28 14:13:08 -07003352 on error flinger will retry with supported format passed
3353 */
3354 if (source != AUDIO_SOURCE_UNPROCESSED) {
3355 config->format = AUDIO_FORMAT_PCM_16_BIT;
3356 ret_error = true;
3357 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3358 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3359 ret_error = true;
3360 }
3361
3362 if (ret_error) {
3363 ret = -EINVAL;
3364 goto err_open;
3365 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003366 }
3367
vivek mehta57ff9b52016-04-28 14:13:08 -07003368 in->format = config->format;
3369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003371 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3372 if (config->sample_rate == 0)
3373 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3374 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3375 config->sample_rate != 8000) {
3376 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3377 ret = -EINVAL;
3378 goto err_open;
3379 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003380
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003381 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3382 config->format = AUDIO_FORMAT_PCM_16_BIT;
3383 ret = -EINVAL;
3384 goto err_open;
3385 }
3386
3387 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3388 in->config = pcm_config_afe_proxy_record;
3389 } else {
3390 in->usecase = USECASE_AUDIO_RECORD;
3391 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3392 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3393 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003394#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003395 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003396#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003397 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003398 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003399
Haynes Mathew George03c40102016-01-29 17:57:48 -08003400 in->config = in->realtime ? pcm_config_audio_capture_rt :
3401 pcm_config_audio_capture;
3402
vivek mehta4ed66e62016-04-15 23:33:34 -07003403 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3404 in->config.format = PCM_FORMAT_S24_LE;
3405
Haynes Mathew George03c40102016-01-29 17:57:48 -08003406 if (!in->realtime) {
3407 frame_size = audio_stream_in_frame_size(&in->stream);
3408 buffer_size = get_input_buffer_size(config->sample_rate,
3409 config->format,
3410 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003411 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003412 in->config.period_size = buffer_size / frame_size;
3413 } // period size is left untouched for rt mode playback
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003414 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003415
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416 in->config.channels = channel_count;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003417 if (in->realtime) {
3418 in->af_period_multiplier = af_period_multiplier;
3419 } else {
3420 in->config.rate = config->sample_rate;
3421 in->af_period_multiplier = 1;
3422 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003424 /* This stream could be for sound trigger lab,
3425 get sound trigger pcm if present */
3426 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003428 lock_input_stream(in);
3429 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3430 pthread_mutex_lock(&adev->lock);
3431 in->card_status = adev->card_status;
3432 pthread_mutex_unlock(&adev->lock);
3433 pthread_mutex_unlock(&in->lock);
3434
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003436 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003437 return 0;
3438
3439err_open:
3440 free(in);
3441 *stream_in = NULL;
3442 return ret;
3443}
3444
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003445static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003446 struct audio_stream_in *stream)
3447{
Eric Laurent994a6932013-07-17 11:51:42 -07003448 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003449
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003450 // must deregister from sndmonitor first to prevent races
3451 // between the callback and close_stream
3452 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453 in_standby(&stream->common);
3454 free(stream);
3455
3456 return;
3457}
3458
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003459static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460{
3461 return 0;
3462}
3463
Andy Hung31aca912014-03-20 17:14:59 -07003464/* verifies input and output devices and their capabilities.
3465 *
3466 * This verification is required when enabling extended bit-depth or
3467 * sampling rates, as not all qcom products support it.
3468 *
3469 * Suitable for calling only on initialization such as adev_open().
3470 * It fills the audio_device use_case_table[] array.
3471 *
3472 * Has a side-effect that it needs to configure audio routing / devices
3473 * in order to power up the devices and read the device parameters.
3474 * It does not acquire any hw device lock. Should restore the devices
3475 * back to "normal state" upon completion.
3476 */
3477static int adev_verify_devices(struct audio_device *adev)
3478{
3479 /* enumeration is a bit difficult because one really wants to pull
3480 * the use_case, device id, etc from the hidden pcm_device_table[].
3481 * In this case there are the following use cases and device ids.
3482 *
3483 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3484 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3485 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3486 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3487 * [USECASE_AUDIO_RECORD] = {0, 0},
3488 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3489 * [USECASE_VOICE_CALL] = {2, 2},
3490 *
3491 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3492 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3493 */
3494
3495 /* should be the usecases enabled in adev_open_input_stream() */
3496 static const int test_in_usecases[] = {
3497 USECASE_AUDIO_RECORD,
3498 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3499 };
3500 /* should be the usecases enabled in adev_open_output_stream()*/
3501 static const int test_out_usecases[] = {
3502 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3503 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3504 };
3505 static const usecase_type_t usecase_type_by_dir[] = {
3506 PCM_PLAYBACK,
3507 PCM_CAPTURE,
3508 };
3509 static const unsigned flags_by_dir[] = {
3510 PCM_OUT,
3511 PCM_IN,
3512 };
3513
3514 size_t i;
3515 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003516 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003517 char info[512]; /* for possible debug info */
3518
3519 for (dir = 0; dir < 2; ++dir) {
3520 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3521 const unsigned flags_dir = flags_by_dir[dir];
3522 const size_t testsize =
3523 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3524 const int *testcases =
3525 dir ? test_in_usecases : test_out_usecases;
3526 const audio_devices_t audio_device =
3527 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3528
3529 for (i = 0; i < testsize; ++i) {
3530 const audio_usecase_t audio_usecase = testcases[i];
3531 int device_id;
3532 snd_device_t snd_device;
3533 struct pcm_params **pparams;
3534 struct stream_out out;
3535 struct stream_in in;
3536 struct audio_usecase uc_info;
3537 int retval;
3538
3539 pparams = &adev->use_case_table[audio_usecase];
3540 pcm_params_free(*pparams); /* can accept null input */
3541 *pparams = NULL;
3542
3543 /* find the device ID for the use case (signed, for error) */
3544 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3545 if (device_id < 0)
3546 continue;
3547
3548 /* prepare structures for device probing */
3549 memset(&uc_info, 0, sizeof(uc_info));
3550 uc_info.id = audio_usecase;
3551 uc_info.type = usecase_type;
3552 if (dir) {
3553 adev->active_input = &in;
3554 memset(&in, 0, sizeof(in));
3555 in.device = audio_device;
3556 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3557 uc_info.stream.in = &in;
3558 } else {
3559 adev->active_input = NULL;
3560 }
3561 memset(&out, 0, sizeof(out));
3562 out.devices = audio_device; /* only field needed in select_devices */
3563 uc_info.stream.out = &out;
3564 uc_info.devices = audio_device;
3565 uc_info.in_snd_device = SND_DEVICE_NONE;
3566 uc_info.out_snd_device = SND_DEVICE_NONE;
3567 list_add_tail(&adev->usecase_list, &uc_info.list);
3568
3569 /* select device - similar to start_(in/out)put_stream() */
3570 retval = select_devices(adev, audio_usecase);
3571 if (retval >= 0) {
3572 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3573#if LOG_NDEBUG == 0
3574 if (*pparams) {
3575 ALOGV("%s: (%s) card %d device %d", __func__,
3576 dir ? "input" : "output", card_id, device_id);
3577 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07003578 } else {
3579 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3580 }
3581#endif
3582 }
3583
3584 /* deselect device - similar to stop_(in/out)put_stream() */
3585 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07003586 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07003587 /* 2. Disable the rx device */
3588 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07003589 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07003590 list_remove(&uc_info.list);
3591 }
3592 }
3593 adev->active_input = NULL; /* restore adev state */
3594 return 0;
3595}
3596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597static int adev_close(hw_device_t *device)
3598{
Andy Hung31aca912014-03-20 17:14:59 -07003599 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003601
3602 if (!adev)
3603 return 0;
3604
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003605 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003606 pthread_mutex_lock(&adev_init_lock);
3607
3608 if ((--audio_device_ref_count) == 0) {
3609 audio_route_free(adev->audio_route);
3610 free(adev->snd_dev_ref_cnt);
3611 platform_deinit(adev->platform);
3612 audio_extn_extspk_deinit(adev->extspk);
3613 audio_extn_sound_trigger_deinit(adev);
3614 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3615 pcm_params_free(adev->use_case_table[i]);
3616 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003617 if (adev->adm_deinit)
3618 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003619 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07003620 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07003621
3622 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003623
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 return 0;
3625}
3626
Glenn Kasten4f993392014-05-14 07:30:48 -07003627/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3628 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3629 * just that it _might_ work.
3630 */
3631static int period_size_is_plausible_for_low_latency(int period_size)
3632{
3633 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003634 case 48:
3635 case 96:
3636 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07003637 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003638 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07003639 case 240:
3640 case 320:
3641 case 480:
3642 return 1;
3643 default:
3644 return 0;
3645 }
3646}
3647
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003648static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
3649{
3650 int card;
3651 card_status_t status;
3652
3653 if (!parms)
3654 return;
3655
3656 if (parse_snd_card_status(parms, &card, &status) < 0)
3657 return;
3658
3659 pthread_mutex_lock(&adev->lock);
3660 bool valid_cb = (card == adev->snd_card);
3661 if (valid_cb) {
3662 if (adev->card_status != status) {
3663 adev->card_status = status;
3664 platform_snd_card_update(adev->platform, status);
3665 }
3666 }
3667 pthread_mutex_unlock(&adev->lock);
3668 return;
3669}
3670
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671static int adev_open(const hw_module_t *module, const char *name,
3672 hw_device_t **device)
3673{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003674 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675
Eric Laurent2bafff12016-03-17 12:17:23 -07003676 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003678 pthread_mutex_lock(&adev_init_lock);
3679 if (audio_device_ref_count != 0) {
3680 *device = &adev->device.common;
3681 audio_device_ref_count++;
3682 ALOGV("%s: returning existing instance of adev", __func__);
3683 ALOGV("%s: exit", __func__);
3684 pthread_mutex_unlock(&adev_init_lock);
3685 return 0;
3686 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687 adev = calloc(1, sizeof(struct audio_device));
3688
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003689 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3692 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3693 adev->device.common.module = (struct hw_module_t *)module;
3694 adev->device.common.close = adev_close;
3695
3696 adev->device.init_check = adev_init_check;
3697 adev->device.set_voice_volume = adev_set_voice_volume;
3698 adev->device.set_master_volume = adev_set_master_volume;
3699 adev->device.get_master_volume = adev_get_master_volume;
3700 adev->device.set_master_mute = adev_set_master_mute;
3701 adev->device.get_master_mute = adev_get_master_mute;
3702 adev->device.set_mode = adev_set_mode;
3703 adev->device.set_mic_mute = adev_set_mic_mute;
3704 adev->device.get_mic_mute = adev_get_mic_mute;
3705 adev->device.set_parameters = adev_set_parameters;
3706 adev->device.get_parameters = adev_get_parameters;
3707 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3708 adev->device.open_output_stream = adev_open_output_stream;
3709 adev->device.close_output_stream = adev_close_output_stream;
3710 adev->device.open_input_stream = adev_open_input_stream;
3711 adev->device.close_input_stream = adev_close_input_stream;
3712 adev->device.dump = adev_dump;
3713
3714 /* Set the default route before the PCM stream is opened */
3715 pthread_mutex_lock(&adev->lock);
3716 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003717 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003718 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003720 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003721 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003722 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003723 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003724 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725 pthread_mutex_unlock(&adev->lock);
3726
3727 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003728 adev->platform = platform_init(adev);
3729 if (!adev->platform) {
3730 free(adev->snd_dev_ref_cnt);
3731 free(adev);
3732 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3733 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003734 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003735 return -EINVAL;
3736 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05003737 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003738 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003739
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003740 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3741 if (adev->visualizer_lib == NULL) {
3742 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3743 } else {
3744 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3745 adev->visualizer_start_output =
3746 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3747 "visualizer_hal_start_output");
3748 adev->visualizer_stop_output =
3749 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3750 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07003751 }
3752
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003753 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3754 if (adev->offload_effects_lib == NULL) {
3755 ALOGW("%s: DLOPEN failed for %s", __func__,
3756 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3757 } else {
3758 ALOGV("%s: DLOPEN successful for %s", __func__,
3759 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3760 adev->offload_effects_start_output =
3761 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3762 "offload_effects_bundle_hal_start_output");
3763 adev->offload_effects_stop_output =
3764 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3765 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07003766 }
3767
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003768 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3769 if (adev->adm_lib == NULL) {
3770 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3771 } else {
3772 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3773 adev->adm_init = (adm_init_t)
3774 dlsym(adev->adm_lib, "adm_init");
3775 adev->adm_deinit = (adm_deinit_t)
3776 dlsym(adev->adm_lib, "adm_deinit");
3777 adev->adm_register_input_stream = (adm_register_input_stream_t)
3778 dlsym(adev->adm_lib, "adm_register_input_stream");
3779 adev->adm_register_output_stream = (adm_register_output_stream_t)
3780 dlsym(adev->adm_lib, "adm_register_output_stream");
3781 adev->adm_deregister_stream = (adm_deregister_stream_t)
3782 dlsym(adev->adm_lib, "adm_deregister_stream");
3783 adev->adm_request_focus = (adm_request_focus_t)
3784 dlsym(adev->adm_lib, "adm_request_focus");
3785 adev->adm_abandon_focus = (adm_abandon_focus_t)
3786 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08003787 adev->adm_set_config = (adm_set_config_t)
3788 dlsym(adev->adm_lib, "adm_set_config");
3789 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
3790 dlsym(adev->adm_lib, "adm_request_focus_v2");
3791 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
3792 dlsym(adev->adm_lib, "adm_is_noirq_avail");
3793 adev->adm_on_routing_change = (adm_on_routing_change_t)
3794 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003795 }
3796
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003797 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003798 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003799
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003800 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003801
Andy Hung31aca912014-03-20 17:14:59 -07003802 if (k_enable_extended_precision)
3803 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804
Glenn Kasten4f993392014-05-14 07:30:48 -07003805 char value[PROPERTY_VALUE_MAX];
3806 int trial;
3807 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3808 trial = atoi(value);
3809 if (period_size_is_plausible_for_low_latency(trial)) {
3810 pcm_config_low_latency.period_size = trial;
3811 pcm_config_low_latency.start_threshold = trial / 4;
3812 pcm_config_low_latency.avail_min = trial / 4;
3813 configured_low_latency_capture_period_size = trial;
3814 }
3815 }
3816 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3817 trial = atoi(value);
3818 if (period_size_is_plausible_for_low_latency(trial)) {
3819 configured_low_latency_capture_period_size = trial;
3820 }
3821 }
3822
Yamit Mehtae3b99562016-09-16 22:44:00 +05303823 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003824 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003825
3826 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
3827 af_period_multiplier = atoi(value);
3828 if (af_period_multiplier < 0) {
3829 af_period_multiplier = 2;
3830 } else if (af_period_multiplier > 4) {
3831 af_period_multiplier = 4;
3832 }
3833 ALOGV("new period_multiplier = %d", af_period_multiplier);
3834 }
3835
vivek mehta1a9b7c02015-06-25 11:49:38 -07003836 pthread_mutex_unlock(&adev_init_lock);
3837
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003838 if (adev->adm_init)
3839 adev->adm_data = adev->adm_init();
3840
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003841 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003842 audio_extn_snd_mon_init();
3843 pthread_mutex_lock(&adev->lock);
3844 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
3845 adev->card_status = CARD_STATUS_ONLINE;
3846 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003847
Eric Laurent2bafff12016-03-17 12:17:23 -07003848 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849 return 0;
3850}
3851
3852static struct hw_module_methods_t hal_module_methods = {
3853 .open = adev_open,
3854};
3855
3856struct audio_module HAL_MODULE_INFO_SYM = {
3857 .common = {
3858 .tag = HARDWARE_MODULE_TAG,
3859 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3860 .hal_api_version = HARDWARE_HAL_API_VERSION,
3861 .id = AUDIO_HARDWARE_MODULE_ID,
3862 .name = "QCOM Audio HAL",
3863 .author = "Code Aurora Forum",
3864 .methods = &hal_module_methods,
3865 },
3866};