blob: 6770e034438c2e14a6abf60d36099f1f39303bbb [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 mehta0d2943f2016-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
Vaughn Nf7c7d742016-12-10 18:53:04 -0500353// 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 mehta0d2943f2016-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
550 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500551 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700552 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700553 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800554
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800555 ALOGV("%s: exit", __func__);
556 return 0;
557}
558
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800559int disable_audio_route(struct audio_device *adev,
560 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800561{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700562 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800563 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800564
565 if (usecase == NULL)
566 return -EINVAL;
567
568 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700569 if (usecase->type == PCM_CAPTURE)
570 snd_device = usecase->in_snd_device;
571 else
572 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800573 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500574 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700575 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700576 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800577
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800578 ALOGV("%s: exit", __func__);
579 return 0;
580}
581
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800582int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700583 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800584{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700585 int i, num_devices = 0;
586 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800587 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800588 if (snd_device < SND_DEVICE_MIN ||
589 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800590 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800591 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800592 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700593
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700594 platform_send_audio_calibration(adev->platform, snd_device);
595
vivek mehtade4849c2016-03-03 17:23:38 -0800596 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700597 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700598 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800599 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700600 }
601
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700602 /* due to the possibility of calibration overwrite between listen
603 and audio, notify sound trigger hal before audio calibration is sent */
604 audio_extn_sound_trigger_update_device_status(snd_device,
605 ST_EVENT_SND_DEVICE_BUSY);
606
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700607 if (audio_extn_spkr_prot_is_enabled())
608 audio_extn_spkr_prot_calib_cancel(adev);
609
zhaoyang yin4211fad2015-06-04 21:13:25 +0800610 audio_extn_dsm_feedback_enable(adev, snd_device, true);
611
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700612 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
613 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
614 audio_extn_spkr_prot_is_enabled()) {
615 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800616 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700617 }
618 if (audio_extn_spkr_prot_start_processing(snd_device)) {
619 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800620 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700621 }
Vaughn Nf7c7d742016-12-10 18:53:04 -0500622 } else if (platform_can_split_snd_device(snd_device,
623 &num_devices,
624 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700625 for (i = 0; i < num_devices; i++) {
626 enable_snd_device(adev, new_snd_devices[i]);
627 }
vivek mehtab6506412015-08-07 16:55:17 -0700628 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700629 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800630 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
631 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
632 ALOGE(" %s: Invalid sound device returned", __func__);
633 goto on_error;
634 }
Ed Tam70b5c142016-03-21 19:14:29 -0700635
zaclimonb085d1a2016-08-28 13:53:25 -0400636 /*
637 * For some unknown reason, the device name gets empty for
638 * msm8960 devices. Because we're sure that the sound device is valid,
639 * copy it manually and apply the correct route.
640 */
641
642 if (strlen(device_name) == 0) {
643 strcpy(device_name, platform_get_snd_device_name(snd_device));
644 }
645
646 ALOGV("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800647 audio_route_apply_and_update_path(adev->audio_route, device_name);
648 }
649on_success:
650 adev->snd_dev_ref_cnt[snd_device]++;
651 ret_val = 0;
652on_error:
653 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800654}
655
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800656int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700657 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800658{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700659 int i, num_devices = 0;
660 snd_device_t new_snd_devices[2];
661
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800662 if (snd_device < SND_DEVICE_MIN ||
663 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800664 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800665 return -EINVAL;
666 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700667 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
668 ALOGE("%s: device ref cnt is already 0", __func__);
669 return -EINVAL;
670 }
671 adev->snd_dev_ref_cnt[snd_device]--;
672 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800673 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700674 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
675 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
676 audio_extn_spkr_prot_is_enabled()) {
677 audio_extn_spkr_prot_stop_processing(snd_device);
Vaughn Nf7c7d742016-12-10 18:53:04 -0500678 } else if (platform_can_split_snd_device(snd_device,
679 &num_devices,
680 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700681 for (i = 0; i < num_devices; i++) {
682 disable_snd_device(adev, new_snd_devices[i]);
683 }
vivek mehtab6506412015-08-07 16:55:17 -0700684 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700685 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800686 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
687 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
688 ALOGE(" %s: Invalid sound device returned", __func__);
689 return -EINVAL;
690 }
691
zaclimonb085d1a2016-08-28 13:53:25 -0400692 /*
693 * Same reason as in enable_snd_device()
694 */
695
696 if (strlen(device_name) == 0) {
697 strcpy(device_name, platform_get_snd_device_name(snd_device));
698 }
699
700 ALOGV("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800701 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700702 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700703 audio_extn_sound_trigger_update_device_status(snd_device,
704 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700705 }
vivek mehtab6506412015-08-07 16:55:17 -0700706
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800707 return 0;
708}
709
Vaughn Nf7c7d742016-12-10 18:53:04 -0500710/*
711 legend:
712 uc - existing usecase
713 new_uc - new usecase
714 d1, d11, d2 - SND_DEVICE enums
715 a1, a2 - corresponding ANDROID device enums
716 B, B1, B2 - backend strings
717
718case 1
719 uc->dev d1 (a1) B1
720 new_uc->dev d1 (a1), d2 (a2) B1, B2
721
722 resolution: disable and enable uc->dev on d1
723
724case 2
725 uc->dev d1 (a1) B1
726 new_uc->dev d11 (a1) B1
727
728 resolution: need to switch uc since d1 and d11 are related
729 (e.g. speaker and voice-speaker)
730 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
731
732case 3
733 uc->dev d1 (a1) B1
734 new_uc->dev d2 (a2) B2
735
736 resolution: no need to switch uc
737
738case 4
739 uc->dev d1 (a1) B
740 new_uc->dev d2 (a2) B
741
742 resolution: disable enable uc-dev on d2 since backends match
743 we cannot enable two streams on two different devices if they
744 share the same backend. e.g. if offload is on speaker device using
745 QUAD_MI2S backend and a low-latency stream is started on voice-handset
746 using the same backend, offload must also be switched to voice-handset.
747
748case 5
749 uc->dev d1 (a1) B
750 new_uc->dev d1 (a1), d2 (a2) B
751
752 resolution: disable enable uc-dev on d2 since backends match
753 we cannot enable two streams on two different devices if they
754 share the same backend.
755
756case 6
757 uc->dev d1 a1 B1
758 new_uc->dev d2 a1 B2
759
760 resolution: no need to switch
761
762case 7
763
764 uc->dev d1 (a1), d2 (a2) B1, B2
765 new_uc->dev d1 B1
766
767 resolution: no need to switch
768
769*/
770static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
771 struct audio_usecase *new_uc,
772 snd_device_t new_snd_device)
773{
774 audio_devices_t a1 = uc->stream.out->devices;
775 audio_devices_t a2 = new_uc->stream.out->devices;
776
777 snd_device_t d1 = uc->out_snd_device;
778 snd_device_t d2 = new_snd_device;
779
780 // Treat as a special case when a1 and a2 are not disjoint
781 if ((a1 != a2) && (a1 & a2)) {
782 snd_device_t d3[2];
783 int num_devices = 0;
784 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
785 &num_devices,
786 d3);
787 if (ret < 0) {
788 if (ret != -ENOSYS) {
789 ALOGW("%s failed to split snd_device %d",
790 __func__,
791 popcount(a1) > 1 ? d1 : d2);
792 }
793 goto end;
794 }
795
796 // NB: case 7 is hypothetical and isn't a practical usecase yet.
797 // But if it does happen, we need to give priority to d2 if
798 // the combo devices active on the existing usecase share a backend.
799 // This is because we cannot have a usecase active on a combo device
800 // and a new usecase requests one device in this combo pair.
801 if (platform_check_backends_match(d3[0], d3[1])) {
802 return d2; // case 5
803 } else {
804 return d1; // case 1
805 }
806 } else {
807 if (platform_check_backends_match(d1, d2)) {
808 return d2; // case 2, 4
809 } else {
810 return d1; // case 6, 3
811 }
812 }
813
814end:
815 return d2; // return whatever was calculated before.
816}
817
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700818static void check_and_route_playback_usecases(struct audio_device *adev,
819 struct audio_usecase *uc_info,
820 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700821{
822 struct listnode *node;
823 struct audio_usecase *usecase;
824 bool switch_device[AUDIO_USECASE_MAX];
825 int i, num_uc_to_switch = 0;
826
827 /*
828 * This function is to make sure that all the usecases that are active on
829 * the hardware codec backend are always routed to any one device that is
830 * handled by the hardware codec.
831 * For example, if low-latency and deep-buffer usecases are currently active
832 * on speaker and out_set_parameters(headset) is received on low-latency
833 * output, then we have to make sure deep-buffer is also switched to headset,
834 * because of the limitation that both the devices cannot be enabled
835 * at the same time as they share the same backend.
836 */
837 /* Disable all the usecases on the shared backend other than the
838 specified usecase */
839 for (i = 0; i < AUDIO_USECASE_MAX; i++)
840 switch_device[i] = false;
841
842 list_for_each(node, &adev->usecase_list) {
843 usecase = node_to_item(node, struct audio_usecase, list);
844 if (usecase->type != PCM_CAPTURE &&
845 usecase != uc_info &&
846 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700847 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
848 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700849 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
850 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700851 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700852 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700853 switch_device[usecase->id] = true;
854 num_uc_to_switch++;
855 }
856 }
857
858 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700859 list_for_each(node, &adev->usecase_list) {
860 usecase = node_to_item(node, struct audio_usecase, list);
861 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700862 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900863 }
864 }
865
Vaughn Nf7c7d742016-12-10 18:53:04 -0500866 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900867 list_for_each(node, &adev->usecase_list) {
868 usecase = node_to_item(node, struct audio_usecase, list);
869 if (switch_device[usecase->id]) {
Vaughn Nf7c7d742016-12-10 18:53:04 -0500870 d_device = derive_playback_snd_device(usecase, uc_info,
871 snd_device);
872 enable_snd_device(adev, d_device);
873 /* Update the out_snd_device before enabling the audio route */
874 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700875 }
876 }
877
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700878 /* Re-route all the usecases on the shared backend other than the
879 specified usecase to new snd devices */
880 list_for_each(node, &adev->usecase_list) {
881 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700883 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700884 }
885 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700886 }
887}
888
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700889static void check_and_route_capture_usecases(struct audio_device *adev,
890 struct audio_usecase *uc_info,
891 snd_device_t snd_device)
892{
893 struct listnode *node;
894 struct audio_usecase *usecase;
895 bool switch_device[AUDIO_USECASE_MAX];
896 int i, num_uc_to_switch = 0;
897
vivek mehta4ed66e62016-04-15 23:33:34 -0700898 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
899
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700900 /*
901 * This function is to make sure that all the active capture usecases
902 * are always routed to the same input sound device.
903 * For example, if audio-record and voice-call usecases are currently
904 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
905 * is received for voice call then we have to make sure that audio-record
906 * usecase is also switched to earpiece i.e. voice-dmic-ef,
907 * because of the limitation that two devices cannot be enabled
908 * at the same time if they share the same backend.
909 */
910 for (i = 0; i < AUDIO_USECASE_MAX; i++)
911 switch_device[i] = false;
912
913 list_for_each(node, &adev->usecase_list) {
914 usecase = node_to_item(node, struct audio_usecase, list);
915 if (usecase->type != PCM_PLAYBACK &&
916 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700917 usecase->in_snd_device != snd_device &&
918 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700919 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
920 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700921 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700922 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700923 switch_device[usecase->id] = true;
924 num_uc_to_switch++;
925 }
926 }
927
928 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700929 list_for_each(node, &adev->usecase_list) {
930 usecase = node_to_item(node, struct audio_usecase, list);
931 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700932 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700933 }
934 }
935
936 list_for_each(node, &adev->usecase_list) {
937 usecase = node_to_item(node, struct audio_usecase, list);
938 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700939 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700940 }
941 }
942
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700943 /* Re-route all the usecases on the shared backend other than the
944 specified usecase to new snd devices */
945 list_for_each(node, &adev->usecase_list) {
946 usecase = node_to_item(node, struct audio_usecase, list);
947 /* Update the in_snd_device only before enabling the audio route */
948 if (switch_device[usecase->id] ) {
949 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700950 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700951 }
952 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700953 }
954}
955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800956/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700957static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800958{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700959 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700960 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800961
962 switch (channels) {
963 /*
964 * Do not handle stereo output in Multi-channel cases
965 * Stereo case is handled in normal playback path
966 */
967 case 6:
968 ALOGV("%s: HDMI supports 5.1", __func__);
969 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
970 break;
971 case 8:
972 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
973 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
974 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
975 break;
976 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700977 ALOGE("HDMI does not support multi channel playback");
978 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800979 break;
980 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700981 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800982}
983
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700984static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
985{
986 struct audio_usecase *usecase;
987 struct listnode *node;
988
989 list_for_each(node, &adev->usecase_list) {
990 usecase = node_to_item(node, struct audio_usecase, list);
991 if (usecase->type == VOICE_CALL) {
992 ALOGV("%s: usecase id %d", __func__, usecase->id);
993 return usecase->id;
994 }
995 }
996 return USECASE_INVALID;
997}
998
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800999struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1000 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001001{
1002 struct audio_usecase *usecase;
1003 struct listnode *node;
1004
1005 list_for_each(node, &adev->usecase_list) {
1006 usecase = node_to_item(node, struct audio_usecase, list);
1007 if (usecase->id == uc_id)
1008 return usecase;
1009 }
1010 return NULL;
1011}
1012
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001013int select_devices(struct audio_device *adev,
1014 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001015{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001016 snd_device_t out_snd_device = SND_DEVICE_NONE;
1017 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001018 struct audio_usecase *usecase = NULL;
1019 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001020 struct audio_usecase *hfp_usecase = NULL;
1021 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001022 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001023 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001025 usecase = get_usecase_from_list(adev, uc_id);
1026 if (usecase == NULL) {
1027 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1028 return -EINVAL;
1029 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001030
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001031 if ((usecase->type == VOICE_CALL) ||
1032 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001033 out_snd_device = platform_get_output_snd_device(adev->platform,
1034 usecase->stream.out->devices);
1035 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001036 usecase->devices = usecase->stream.out->devices;
1037 } else {
1038 /*
1039 * If the voice call is active, use the sound devices of voice call usecase
1040 * so that it would not result any device switch. All the usecases will
1041 * be switched to new device when select_devices() is called for voice call
1042 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001043 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001044 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001045 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001046 vc_usecase = get_usecase_from_list(adev,
1047 get_voice_usecase_id_from_list(adev));
1048 if ((vc_usecase != NULL) &&
1049 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1050 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001051 in_snd_device = vc_usecase->in_snd_device;
1052 out_snd_device = vc_usecase->out_snd_device;
1053 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001054 } else if (audio_extn_hfp_is_active(adev)) {
1055 hfp_ucid = audio_extn_hfp_get_usecase();
1056 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1057 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1058 in_snd_device = hfp_usecase->in_snd_device;
1059 out_snd_device = hfp_usecase->out_snd_device;
1060 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001061 }
1062 if (usecase->type == PCM_PLAYBACK) {
1063 usecase->devices = usecase->stream.out->devices;
1064 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001065 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001066 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001067 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001068 if (usecase->stream.out == adev->primary_output &&
1069 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001070 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1071 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001072 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001073 select_devices(adev, adev->active_input->usecase);
1074 }
1075 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001076 } else if (usecase->type == PCM_CAPTURE) {
1077 usecase->devices = usecase->stream.in->device;
1078 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001079 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001080 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001081 if (adev->active_input &&
1082 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1083 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001084 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001085 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1086 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1087 } else if (adev->primary_output) {
1088 out_device = adev->primary_output->devices;
1089 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001090 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001091 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001092 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001093 }
1094 }
1095
1096 if (out_snd_device == usecase->out_snd_device &&
1097 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001098 return 0;
1099 }
1100
Eric Laurent2bafff12016-03-17 12:17:23 -07001101 if (out_snd_device != SND_DEVICE_NONE &&
1102 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1103 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1104 __func__,
1105 use_case_table[uc_id],
1106 adev->last_logged_snd_device[uc_id][0],
1107 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1108 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1109 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1110 -1,
1111 out_snd_device,
1112 platform_get_snd_device_name(out_snd_device),
1113 platform_get_snd_device_acdb_id(out_snd_device));
1114 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1115 }
1116 if (in_snd_device != SND_DEVICE_NONE &&
1117 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1118 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1119 __func__,
1120 use_case_table[uc_id],
1121 adev->last_logged_snd_device[uc_id][1],
1122 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1123 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1124 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1125 -1,
1126 in_snd_device,
1127 platform_get_snd_device_name(in_snd_device),
1128 platform_get_snd_device_acdb_id(in_snd_device));
1129 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1130 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001131
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001132 /*
1133 * Limitation: While in call, to do a device switch we need to disable
1134 * and enable both RX and TX devices though one of them is same as current
1135 * device.
1136 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001137 if ((usecase->type == VOICE_CALL) &&
1138 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1139 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001140 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001141 /* Disable sidetone only if voice call already exists */
1142 if (voice_is_call_state_active(adev))
1143 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001144 }
1145
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001146 /* Disable current sound devices */
1147 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001148 disable_audio_route(adev, usecase);
1149 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001150 }
1151
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001153 disable_audio_route(adev, usecase);
1154 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001155 }
1156
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001157 /* Applicable only on the targets that has external modem.
1158 * New device information should be sent to modem before enabling
1159 * the devices to reduce in-call device switch time.
1160 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001161 if ((usecase->type == VOICE_CALL) &&
1162 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1163 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001164 status = platform_switch_voice_call_enable_device_config(adev->platform,
1165 out_snd_device,
1166 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001167 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001168
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001169 /* Enable new sound devices */
1170 if (out_snd_device != SND_DEVICE_NONE) {
1171 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001172 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001173 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001174 }
1175
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001176 if (in_snd_device != SND_DEVICE_NONE) {
1177 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001178 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001179 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001180
Eric Laurentb23d5282013-05-14 15:27:20 -07001181 if (usecase->type == VOICE_CALL)
1182 status = platform_switch_voice_call_device_post(adev->platform,
1183 out_snd_device,
1184 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001185
sangwoo170731f2013-06-08 15:36:36 +09001186 usecase->in_snd_device = in_snd_device;
1187 usecase->out_snd_device = out_snd_device;
1188
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001189 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001190
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001191 /* Applicable only on the targets that has external modem.
1192 * Enable device command should be sent to modem only after
1193 * enabling voice call mixer controls
1194 */
vivek mehta765eb642015-08-07 19:46:06 -07001195 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001196 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1197 out_snd_device,
1198 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001199 /* Enable sidetone only if voice call already exists */
1200 if (voice_is_call_state_active(adev))
1201 voice_set_sidetone(adev, out_snd_device, true);
1202 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001204 return status;
1205}
1206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001207static int stop_input_stream(struct stream_in *in)
1208{
1209 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001210 struct audio_usecase *uc_info;
1211 struct audio_device *adev = in->dev;
1212
Eric Laurentc8400632013-02-14 19:04:54 -08001213 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001214
Eric Laurent994a6932013-07-17 11:51:42 -07001215 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001216 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001217 uc_info = get_usecase_from_list(adev, in->usecase);
1218 if (uc_info == NULL) {
1219 ALOGE("%s: Could not find the usecase (%d) in the list",
1220 __func__, in->usecase);
1221 return -EINVAL;
1222 }
1223
Eric Laurent150dbfe2013-02-27 14:31:02 -08001224 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001225 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001226
1227 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001228 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001229
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001230 list_remove(&uc_info->list);
1231 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232
Eric Laurent994a6932013-07-17 11:51:42 -07001233 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001234 return ret;
1235}
1236
1237int start_input_stream(struct stream_in *in)
1238{
1239 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001240 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001241 struct audio_usecase *uc_info;
1242 struct audio_device *adev = in->dev;
1243
Eric Laurent994a6932013-07-17 11:51:42 -07001244 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001245
1246 if (in->card_status == CARD_STATUS_OFFLINE ||
1247 adev->card_status == CARD_STATUS_OFFLINE) {
1248 ALOGW("in->card_status or adev->card_status offline, try again");
1249 ret = -EAGAIN;
1250 goto error_config;
1251 }
1252
Eric Laurentb23d5282013-05-14 15:27:20 -07001253 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001254 if (in->pcm_device_id < 0) {
1255 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1256 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001257 ret = -EINVAL;
1258 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001259 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001260
1261 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001262 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1263 uc_info->id = in->usecase;
1264 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001265 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001266 uc_info->devices = in->device;
1267 uc_info->in_snd_device = SND_DEVICE_NONE;
1268 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001269
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001270 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001271
1272 audio_extn_perf_lock_acquire();
1273
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001274 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275
Eric Laurentc8400632013-02-14 19:04:54 -08001276 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001277 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001278
Andy Hung6ebe5962016-01-15 17:46:57 -08001279 unsigned int flags = PCM_IN | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001280 unsigned int pcm_open_retry_count = 0;
1281
1282 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1283 flags |= PCM_MMAP | PCM_NOIRQ;
1284 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001285 } else if (in->realtime) {
1286 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001287 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001288
1289 while (1) {
1290 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1291 flags, &in->config);
1292 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1293 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1294 if (in->pcm != NULL) {
1295 pcm_close(in->pcm);
1296 in->pcm = NULL;
1297 }
1298 if (pcm_open_retry_count-- == 0) {
1299 ret = -EIO;
1300 goto error_open;
1301 }
1302 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1303 continue;
1304 }
1305 break;
1306 }
1307
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001308 ALOGV("%s: pcm_prepare", __func__);
1309 ret = pcm_prepare(in->pcm);
1310 if (ret < 0) {
1311 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1312 pcm_close(in->pcm);
1313 in->pcm = NULL;
1314 goto error_open;
1315 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001316 if (in->realtime) {
1317 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001318 if (ret < 0) {
1319 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1320 pcm_close(in->pcm);
1321 in->pcm = NULL;
1322 goto error_open;
1323 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001324 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001325 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001326 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001327 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001328
Eric Laurentc8400632013-02-14 19:04:54 -08001329 return ret;
1330
1331error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001332 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001333 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001334
1335error_config:
1336 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001337 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001338
1339 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001340}
1341
Eric Laurenta1478072015-09-21 17:21:52 -07001342void lock_input_stream(struct stream_in *in)
1343{
1344 pthread_mutex_lock(&in->pre_lock);
1345 pthread_mutex_lock(&in->lock);
1346 pthread_mutex_unlock(&in->pre_lock);
1347}
1348
1349void lock_output_stream(struct stream_out *out)
1350{
1351 pthread_mutex_lock(&out->pre_lock);
1352 pthread_mutex_lock(&out->lock);
1353 pthread_mutex_unlock(&out->pre_lock);
1354}
1355
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001356/* must be called with out->lock locked */
1357static int send_offload_cmd_l(struct stream_out* out, int command)
1358{
1359 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1360
1361 ALOGVV("%s %d", __func__, command);
1362
1363 cmd->cmd = command;
1364 list_add_tail(&out->offload_cmd_list, &cmd->node);
1365 pthread_cond_signal(&out->offload_cond);
1366 return 0;
1367}
1368
1369/* must be called iwth out->lock locked */
1370static void stop_compressed_output_l(struct stream_out *out)
1371{
1372 out->offload_state = OFFLOAD_STATE_IDLE;
1373 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001374 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001375 if (out->compr != NULL) {
1376 compress_stop(out->compr);
1377 while (out->offload_thread_blocked) {
1378 pthread_cond_wait(&out->cond, &out->lock);
1379 }
1380 }
1381}
1382
1383static void *offload_thread_loop(void *context)
1384{
1385 struct stream_out *out = (struct stream_out *) context;
1386 struct listnode *item;
1387
1388 out->offload_state = OFFLOAD_STATE_IDLE;
1389 out->playback_started = 0;
1390
1391 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1392 set_sched_policy(0, SP_FOREGROUND);
1393 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1394
1395 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001396 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001397 for (;;) {
1398 struct offload_cmd *cmd = NULL;
1399 stream_callback_event_t event;
1400 bool send_callback = false;
1401
1402 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1403 __func__, list_empty(&out->offload_cmd_list),
1404 out->offload_state);
1405 if (list_empty(&out->offload_cmd_list)) {
1406 ALOGV("%s SLEEPING", __func__);
1407 pthread_cond_wait(&out->offload_cond, &out->lock);
1408 ALOGV("%s RUNNING", __func__);
1409 continue;
1410 }
1411
1412 item = list_head(&out->offload_cmd_list);
1413 cmd = node_to_item(item, struct offload_cmd, node);
1414 list_remove(item);
1415
1416 ALOGVV("%s STATE %d CMD %d out->compr %p",
1417 __func__, out->offload_state, cmd->cmd, out->compr);
1418
1419 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1420 free(cmd);
1421 break;
1422 }
1423
1424 if (out->compr == NULL) {
1425 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001426 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001427 pthread_cond_signal(&out->cond);
1428 continue;
1429 }
1430 out->offload_thread_blocked = true;
1431 pthread_mutex_unlock(&out->lock);
1432 send_callback = false;
1433 switch(cmd->cmd) {
1434 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1435 compress_wait(out->compr, -1);
1436 send_callback = true;
1437 event = STREAM_CBK_EVENT_WRITE_READY;
1438 break;
1439 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001440 compress_next_track(out->compr);
1441 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001442 send_callback = true;
1443 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001444 /* Resend the metadata for next iteration */
1445 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001446 break;
1447 case OFFLOAD_CMD_DRAIN:
1448 compress_drain(out->compr);
1449 send_callback = true;
1450 event = STREAM_CBK_EVENT_DRAIN_READY;
1451 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001452 case OFFLOAD_CMD_ERROR:
1453 send_callback = true;
1454 event = STREAM_CBK_EVENT_ERROR;
1455 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001456 default:
1457 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1458 break;
1459 }
Eric Laurenta1478072015-09-21 17:21:52 -07001460 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001461 out->offload_thread_blocked = false;
1462 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001463 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001464 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001465 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001466 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001467 free(cmd);
1468 }
1469
1470 pthread_cond_signal(&out->cond);
1471 while (!list_empty(&out->offload_cmd_list)) {
1472 item = list_head(&out->offload_cmd_list);
1473 list_remove(item);
1474 free(node_to_item(item, struct offload_cmd, node));
1475 }
1476 pthread_mutex_unlock(&out->lock);
1477
1478 return NULL;
1479}
1480
1481static int create_offload_callback_thread(struct stream_out *out)
1482{
1483 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1484 list_init(&out->offload_cmd_list);
1485 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1486 offload_thread_loop, out);
1487 return 0;
1488}
1489
1490static int destroy_offload_callback_thread(struct stream_out *out)
1491{
Eric Laurenta1478072015-09-21 17:21:52 -07001492 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001493 stop_compressed_output_l(out);
1494 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1495
1496 pthread_mutex_unlock(&out->lock);
1497 pthread_join(out->offload_thread, (void **) NULL);
1498 pthread_cond_destroy(&out->offload_cond);
1499
1500 return 0;
1501}
1502
Eric Laurent07eeafd2013-10-06 12:52:49 -07001503static bool allow_hdmi_channel_config(struct audio_device *adev)
1504{
1505 struct listnode *node;
1506 struct audio_usecase *usecase;
1507 bool ret = true;
1508
1509 list_for_each(node, &adev->usecase_list) {
1510 usecase = node_to_item(node, struct audio_usecase, list);
1511 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1512 /*
1513 * If voice call is already existing, do not proceed further to avoid
1514 * disabling/enabling both RX and TX devices, CSD calls, etc.
1515 * Once the voice call done, the HDMI channels can be configured to
1516 * max channels of remaining use cases.
1517 */
1518 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001519 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001520 __func__);
1521 ret = false;
1522 break;
1523 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001524 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001525 "no change in HDMI channels", __func__);
1526 ret = false;
1527 break;
1528 }
1529 }
1530 }
1531 return ret;
1532}
1533
1534static int check_and_set_hdmi_channels(struct audio_device *adev,
1535 unsigned int channels)
1536{
1537 struct listnode *node;
1538 struct audio_usecase *usecase;
1539
1540 /* Check if change in HDMI channel config is allowed */
1541 if (!allow_hdmi_channel_config(adev))
1542 return 0;
1543
1544 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001545 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001546 return 0;
1547 }
1548
1549 platform_set_hdmi_channels(adev->platform, channels);
1550 adev->cur_hdmi_channels = channels;
1551
1552 /*
1553 * Deroute all the playback streams routed to HDMI so that
1554 * the back end is deactivated. Note that backend will not
1555 * be deactivated if any one stream is connected to it.
1556 */
1557 list_for_each(node, &adev->usecase_list) {
1558 usecase = node_to_item(node, struct audio_usecase, list);
1559 if (usecase->type == PCM_PLAYBACK &&
1560 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001561 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001562 }
1563 }
1564
1565 /*
1566 * Enable all the streams disabled above. Now the HDMI backend
1567 * will be activated with new channel configuration
1568 */
1569 list_for_each(node, &adev->usecase_list) {
1570 usecase = node_to_item(node, struct audio_usecase, list);
1571 if (usecase->type == PCM_PLAYBACK &&
1572 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001573 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001574 }
1575 }
1576
1577 return 0;
1578}
1579
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001580static int stop_output_stream(struct stream_out *out)
1581{
1582 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583 struct audio_usecase *uc_info;
1584 struct audio_device *adev = out->dev;
1585
Eric Laurent994a6932013-07-17 11:51:42 -07001586 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001587 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001588 uc_info = get_usecase_from_list(adev, out->usecase);
1589 if (uc_info == NULL) {
1590 ALOGE("%s: Could not find the usecase (%d) in the list",
1591 __func__, out->usecase);
1592 return -EINVAL;
1593 }
1594
Haynes Mathew George41f86652014-06-17 14:22:15 -07001595 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1596 if (adev->visualizer_stop_output != NULL)
1597 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1598 if (adev->offload_effects_stop_output != NULL)
1599 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1600 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001601
Eric Laurent150dbfe2013-02-27 14:31:02 -08001602 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001603 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001604
1605 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001606 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001607
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001608 list_remove(&uc_info->list);
1609 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001610
Eric Laurent0499d4f2014-08-25 22:39:29 -05001611 audio_extn_extspk_update(adev->extspk);
1612
Eric Laurent07eeafd2013-10-06 12:52:49 -07001613 /* Must be called after removing the usecase from list */
1614 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1615 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1616
Eric Laurent994a6932013-07-17 11:51:42 -07001617 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001618 return ret;
1619}
1620
1621int start_output_stream(struct stream_out *out)
1622{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001623 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624 struct audio_usecase *uc_info;
1625 struct audio_device *adev = out->dev;
1626
Eric Laurent994a6932013-07-17 11:51:42 -07001627 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001628 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001629
1630 if (out->card_status == CARD_STATUS_OFFLINE ||
1631 adev->card_status == CARD_STATUS_OFFLINE) {
1632 ALOGW("out->card_status or adev->card_status offline, try again");
1633 ret = -EAGAIN;
1634 goto error_config;
1635 }
1636
Eric Laurentb23d5282013-05-14 15:27:20 -07001637 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638 if (out->pcm_device_id < 0) {
1639 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1640 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001641 ret = -EINVAL;
1642 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001643 }
1644
1645 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1646 uc_info->id = out->usecase;
1647 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001648 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001649 uc_info->devices = out->devices;
1650 uc_info->in_snd_device = SND_DEVICE_NONE;
1651 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001652
Eric Laurent07eeafd2013-10-06 12:52:49 -07001653 /* This must be called before adding this usecase to the list */
1654 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1655 check_and_set_hdmi_channels(adev, out->config.channels);
1656
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001657 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001659 audio_extn_perf_lock_acquire();
1660
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001661 select_devices(adev, out->usecase);
1662
Eric Laurent0499d4f2014-08-25 22:39:29 -05001663 audio_extn_extspk_update(adev->extspk);
1664
Andy Hung31aca912014-03-20 17:14:59 -07001665 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001666 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001667 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001668 unsigned int flags = PCM_OUT;
1669 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001670
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001671 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1672 flags |= PCM_MMAP | PCM_NOIRQ;
1673 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001674 } else if (out->realtime) {
1675 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001676 } else
1677 flags |= PCM_MONOTONIC;
1678
1679 while (1) {
1680 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1681 flags, &out->config);
1682 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1683 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1684 if (out->pcm != NULL) {
1685 pcm_close(out->pcm);
1686 out->pcm = NULL;
1687 }
1688 if (pcm_open_retry_count-- == 0) {
1689 ret = -EIO;
1690 goto error_open;
1691 }
1692 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1693 continue;
1694 }
1695 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001696 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001697 ALOGV("%s: pcm_prepare", __func__);
1698 if (pcm_is_ready(out->pcm)) {
1699 ret = pcm_prepare(out->pcm);
1700 if (ret < 0) {
1701 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1702 pcm_close(out->pcm);
1703 out->pcm = NULL;
1704 goto error_open;
1705 }
1706 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001707 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708 out->pcm = NULL;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001709 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001710 COMPRESS_IN, &out->compr_config);
1711 if (out->compr && !is_compress_ready(out->compr)) {
1712 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1713 compress_close(out->compr);
1714 out->compr = NULL;
1715 ret = -EIO;
1716 goto error_open;
1717 }
1718 if (out->offload_callback)
1719 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001720
1721 if (adev->visualizer_start_output != NULL)
Haynes Mathew George41f86652014-06-17 14:22:15 -07001722 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1723 if (adev->offload_effects_start_output != NULL)
1724 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001726 ret = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001727 if (out->realtime) {
1728 ret = pcm_start(out->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001729 if (ret < 0) {
1730 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1731 pcm_close(out->pcm);
1732 out->pcm = NULL;
1733 goto error_open;
1734 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001735 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001736 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001737 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001738 ALOGV("%s: exit", __func__);
Haynes Mathew George03c40102016-01-29 17:57:48 -08001739 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001740error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001741 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001743error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001744 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745}
1746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747static int check_input_parameters(uint32_t sample_rate,
1748 audio_format_t format,
1749 int channel_count)
1750{
vivek mehta4ed66e62016-04-15 23:33:34 -07001751 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001752 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1753 return -EINVAL;
1754 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001755
vivek mehtadae44712015-07-27 14:13:18 -07001756 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001757 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001758 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1759 return -EINVAL;
1760 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001761
1762 switch (sample_rate) {
1763 case 8000:
1764 case 11025:
1765 case 12000:
1766 case 16000:
1767 case 22050:
1768 case 24000:
1769 case 32000:
1770 case 44100:
1771 case 48000:
1772 break;
1773 default:
vivek mehtadae44712015-07-27 14:13:18 -07001774 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001775 return -EINVAL;
1776 }
1777
1778 return 0;
1779}
1780
1781static size_t get_input_buffer_size(uint32_t sample_rate,
1782 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001783 int channel_count,
1784 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785{
1786 size_t size = 0;
1787
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001788 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1789 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001791 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001792 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001793 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001794
1795 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796
Glenn Kasten4f993392014-05-14 07:30:48 -07001797 /* make sure the size is multiple of 32 bytes
1798 * At 48 kHz mono 16-bit PCM:
1799 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1800 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1801 */
1802 size += 0x1f;
1803 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001804
1805 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806}
1807
1808static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1809{
1810 struct stream_out *out = (struct stream_out *)stream;
1811
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001812 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813}
1814
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001815static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001816{
1817 return -ENOSYS;
1818}
1819
1820static size_t out_get_buffer_size(const struct audio_stream *stream)
1821{
1822 struct stream_out *out = (struct stream_out *)stream;
1823
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001824 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1825 return out->compr_config.fragment_size;
1826 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001827 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001828 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001829}
1830
1831static uint32_t out_get_channels(const struct audio_stream *stream)
1832{
1833 struct stream_out *out = (struct stream_out *)stream;
1834
1835 return out->channel_mask;
1836}
1837
1838static audio_format_t out_get_format(const struct audio_stream *stream)
1839{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001840 struct stream_out *out = (struct stream_out *)stream;
1841
1842 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001843}
1844
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001845static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846{
1847 return -ENOSYS;
1848}
1849
1850static int out_standby(struct audio_stream *stream)
1851{
1852 struct stream_out *out = (struct stream_out *)stream;
1853 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001854
Eric Laurent994a6932013-07-17 11:51:42 -07001855 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001856 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001857
Eric Laurenta1478072015-09-21 17:21:52 -07001858 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001859 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001860 if (adev->adm_deregister_stream)
1861 adev->adm_deregister_stream(adev->adm_data, out->handle);
1862
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001863 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001865 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1866 if (out->pcm) {
1867 pcm_close(out->pcm);
1868 out->pcm = NULL;
1869 }
1870 } else {
1871 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001872 out->gapless_mdata.encoder_delay = 0;
1873 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001874 if (out->compr != NULL) {
1875 compress_close(out->compr);
1876 out->compr = NULL;
1877 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001878 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001880 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881 }
1882 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001883 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884 return 0;
1885}
1886
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001887static int out_on_error(struct audio_stream *stream)
1888{
1889 struct stream_out *out = (struct stream_out *)stream;
1890 struct audio_device *adev = out->dev;
1891 bool do_standby = false;
1892
1893 lock_output_stream(out);
1894 if (!out->standby) {
1895 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1896 stop_compressed_output_l(out);
1897 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1898 } else
1899 do_standby = true;
1900 }
1901 pthread_mutex_unlock(&out->lock);
1902
1903 if (do_standby)
1904 return out_standby(&out->stream.common);
1905
1906 return 0;
1907}
1908
Vaughn Nf7c7d742016-12-10 18:53:04 -05001909static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910{
Vaughn Nf7c7d742016-12-10 18:53:04 -05001911 struct stream_out *out = (struct stream_out *)stream;
1912
1913 // We try to get the lock for consistency,
1914 // but it isn't necessary for these variables.
1915 // If we're not in standby, we may be blocked on a write.
1916 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1917 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1918 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1919
1920 if (locked) {
1921 log_dump_l(&out->error_log, fd);
1922 pthread_mutex_unlock(&out->lock);
1923 } else {
1924 // We don't have the lock here, copy for safety.
1925 struct error_log log = out->error_log;
1926 log_dump_l(&log, fd);
1927 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928 return 0;
1929}
1930
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001931static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1932{
1933 int ret = 0;
1934 char value[32];
1935 struct compr_gapless_mdata tmp_mdata;
1936
1937 if (!out || !parms) {
1938 return -EINVAL;
1939 }
1940
1941 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1942 if (ret >= 0) {
1943 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1944 } else {
1945 return -EINVAL;
1946 }
1947
1948 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1949 if (ret >= 0) {
1950 tmp_mdata.encoder_padding = atoi(value);
1951 } else {
1952 return -EINVAL;
1953 }
1954
1955 out->gapless_mdata = tmp_mdata;
1956 out->send_new_metadata = 1;
1957 ALOGV("%s new encoder delay %u and padding %u", __func__,
1958 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1959
1960 return 0;
1961}
1962
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001963static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1964{
1965 return out == adev->primary_output || out == adev->voice_tx_output;
1966}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001967
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1969{
1970 struct stream_out *out = (struct stream_out *)stream;
1971 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001972 struct audio_usecase *usecase;
1973 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974 struct str_parms *parms;
1975 char value[32];
1976 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001977 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001978 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979
Eric Laurent2e140aa2016-06-30 17:14:46 -07001980 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001981 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982 parms = str_parms_create_str(kvpairs);
1983 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1984 if (ret >= 0) {
1985 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001986 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001987 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001989 /*
1990 * When HDMI cable is unplugged the music playback is paused and
1991 * the policy manager sends routing=0. But the audioflinger
1992 * continues to write data until standby time (3sec).
1993 * As the HDMI core is turned off, the write gets blocked.
1994 * Avoid this by routing audio to speaker until standby.
1995 */
1996 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1997 val == AUDIO_DEVICE_NONE) {
1998 val = AUDIO_DEVICE_OUT_SPEAKER;
1999 }
2000
2001 /*
2002 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002003 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002004 * the select_devices(). But how do we undo this?
2005 *
2006 * For example, music playback is active on headset (deep-buffer usecase)
2007 * and if we go to ringtones and select a ringtone, low-latency usecase
2008 * will be started on headset+speaker. As we can't enable headset+speaker
2009 * and headset devices at the same time, select_devices() switches the music
2010 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2011 * So when the ringtone playback is completed, how do we undo the same?
2012 *
2013 * We are relying on the out_set_parameters() call on deep-buffer output,
2014 * once the ringtone playback is ended.
2015 * NOTE: We should not check if the current devices are same as new devices.
2016 * Because select_devices() must be called to switch back the music
2017 * playback to headset.
2018 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002019 audio_devices_t new_dev = val;
2020 if (new_dev != AUDIO_DEVICE_NONE) {
2021 bool same_dev = out->devices == new_dev;
2022 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002023
Eric Laurenta7657192014-10-09 21:09:33 -07002024 if (output_drives_call(adev, out)) {
2025 if (!voice_is_in_call(adev)) {
2026 if (adev->mode == AUDIO_MODE_IN_CALL) {
2027 adev->current_call_output = out;
2028 ret = voice_start_call(adev);
2029 }
2030 } else {
2031 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002032 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002033 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002034 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002035
2036 if (!out->standby) {
2037 if (!same_dev) {
2038 ALOGV("update routing change");
2039 out->routing_change = true;
2040 }
2041 select_devices(adev, out->usecase);
2042 }
2043
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002044 }
2045
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002046 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002047 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002048
2049 /*handles device and call state changes*/
2050 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002051 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002052
2053 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2054 parse_compress_metadata(out, parms);
2055 }
2056
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002058 ALOGV("%s: exit: code(%d)", __func__, status);
2059 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060}
2061
2062static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2063{
2064 struct stream_out *out = (struct stream_out *)stream;
2065 struct str_parms *query = str_parms_create_str(keys);
2066 char *str;
2067 char value[256];
2068 struct str_parms *reply = str_parms_create();
2069 size_t i, j;
2070 int ret;
2071 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002072 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002073 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2074 if (ret >= 0) {
2075 value[0] = '\0';
2076 i = 0;
2077 while (out->supported_channel_masks[i] != 0) {
2078 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2079 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2080 if (!first) {
2081 strcat(value, "|");
2082 }
2083 strcat(value, out_channels_name_to_enum_table[j].name);
2084 first = false;
2085 break;
2086 }
2087 }
2088 i++;
2089 }
2090 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2091 str = str_parms_to_str(reply);
2092 } else {
2093 str = strdup(keys);
2094 }
2095 str_parms_destroy(query);
2096 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002097 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002098 return str;
2099}
2100
2101static uint32_t out_get_latency(const struct audio_stream_out *stream)
2102{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002103 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104 struct stream_out *out = (struct stream_out *)stream;
2105
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002106 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2107 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002108 else if (out->realtime) {
2109 // since the buffer won't be filled up faster than realtime,
2110 // return a smaller number
2111 period_ms = (out->af_period_multiplier * out->config.period_size *
2112 1000) / (out->config.rate);
2113 hw_delay = platform_render_latency(out->usecase)/1000;
2114 return period_ms + hw_delay;
2115 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002116
2117 return (out->config.period_count * out->config.period_size * 1000) /
2118 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002119}
2120
2121static int out_set_volume(struct audio_stream_out *stream, float left,
2122 float right)
2123{
Eric Laurenta9024de2013-04-04 09:19:12 -07002124 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002125 int volume[2];
2126
Eric Laurenta9024de2013-04-04 09:19:12 -07002127 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2128 /* only take left channel into account: the API is for stereo anyway */
2129 out->muted = (left == 0.0f);
2130 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002131 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2132 const char *mixer_ctl_name = "Compress Playback Volume";
2133 struct audio_device *adev = out->dev;
2134 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002135 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2136 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002137 /* try with the control based on device id */
2138 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2139 PCM_PLAYBACK);
2140 char ctl_name[128] = {0};
2141 snprintf(ctl_name, sizeof(ctl_name),
2142 "Compress Playback %d Volume", pcm_device_id);
2143 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2144 if (!ctl) {
2145 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2146 return -EINVAL;
2147 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002148 }
2149 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2150 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2151 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2152 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002153 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002154
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002155 return -ENOSYS;
2156}
2157
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002158// note: this call is safe only if the stream_cb is
2159// removed first in close_output_stream (as is done now).
2160static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2161{
2162 if (!stream || !parms)
2163 return;
2164
2165 struct stream_out *out = (struct stream_out *)stream;
2166 struct audio_device *adev = out->dev;
2167
2168 card_status_t status;
2169 int card;
2170 if (parse_snd_card_status(parms, &card, &status) < 0)
2171 return;
2172
2173 pthread_mutex_lock(&adev->lock);
2174 bool valid_cb = (card == adev->snd_card);
2175 pthread_mutex_unlock(&adev->lock);
2176
2177 if (!valid_cb)
2178 return;
2179
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002180 lock_output_stream(out);
2181 if (out->card_status != status)
2182 out->card_status = status;
2183 pthread_mutex_unlock(&out->lock);
2184
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002185 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2186 use_case_table[out->usecase],
2187 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2188
2189 if (status == CARD_STATUS_OFFLINE)
2190 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002191
2192 return;
2193}
2194
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002195#ifdef NO_AUDIO_OUT
2196static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
2197 const void *buffer, size_t bytes)
2198{
2199 struct stream_out *out = (struct stream_out *)stream;
2200
2201 /* No Output device supported other than BT for playback.
2202 * Sleep for the amount of buffer duration
2203 */
Eric Laurenta1478072015-09-21 17:21:52 -07002204 lock_output_stream(out);
Uday Kishore Pasupuletib14d76b2015-11-13 20:06:37 -08002205 usleep(bytes * 1000000 / audio_stream_out_frame_size(&out->stream.common) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002206 out_get_sample_rate(&out->stream.common));
2207 pthread_mutex_unlock(&out->lock);
2208 return bytes;
2209}
2210#endif
2211
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2213 size_t bytes)
2214{
2215 struct stream_out *out = (struct stream_out *)stream;
2216 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002217 ssize_t ret = 0;
Vaughn Nf7c7d742016-12-10 18:53:04 -05002218 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219
Eric Laurenta1478072015-09-21 17:21:52 -07002220 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002221 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002222 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002223 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002224 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002225 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002226 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002228 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229 goto exit;
2230 }
vivek mehta0d2943f2016-04-29 03:16:47 -07002231
2232 if (last_known_cal_step != -1) {
2233 ALOGD("%s: retry previous failed cal level set", __func__);
2234 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2235 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002238 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002239 ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
2240 if (out->send_new_metadata) {
2241 ALOGVV("send new gapless metadata");
2242 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2243 out->send_new_metadata = 0;
2244 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002245 unsigned int avail;
2246 struct timespec tstamp;
2247 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2248 /* Do not limit write size if the available frames count is unknown */
2249 if (ret != 0) {
2250 avail = bytes;
2251 }
2252 if (avail == 0) {
2253 ret = 0;
2254 } else {
2255 if (avail > bytes) {
2256 avail = bytes;
2257 }
2258 ret = compress_write(out->compr, buffer, avail);
2259 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2260 __func__, avail, ret);
2261 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002262
Eric Laurent6e895242013-09-05 16:10:57 -07002263 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002264 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2265 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002266 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002267 compress_start(out->compr);
2268 out->playback_started = 1;
2269 out->offload_state = OFFLOAD_STATE_PLAYING;
2270 }
Vaughn Nf7c7d742016-12-10 18:53:04 -05002271 if (ret < 0) {
2272 log_error_l(&out->error_log, ERROR_CODE_WRITE);
2273 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002274 pthread_mutex_unlock(&out->lock);
2275 return ret;
2276 } else {
Vaughn Nf7c7d742016-12-10 18:53:04 -05002277 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002278 if (out->pcm) {
2279 if (out->muted)
2280 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002281
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002282 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002283
Haynes Mathew George03c40102016-01-29 17:57:48 -08002284 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2285 out->config.rate;
2286 request_out_focus(out, ns);
2287
2288 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2289 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002290 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002291 else
2292 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002293
Haynes Mathew George03c40102016-01-29 17:57:48 -08002294 release_out_focus(out, ns);
Vaughn Nf7c7d742016-12-10 18:53:04 -05002295 } else {
2296 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002297 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002298 }
2299
2300exit:
Vaughn Nf7c7d742016-12-10 18:53:04 -05002301 // For PCM we always consume the buffer and return #bytes regardless of ret.
2302 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2303 out->written += bytes / (out->config.channels * sizeof(short));
2304 }
2305 long long sleeptime_us = 0;
2306 if (ret != 0) {
2307 log_error_l(&out->error_log, error_code);
2308 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2309 ALOGE_IF(out->pcm != NULL,
2310 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
2311 sleeptime_us = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2312 out_get_sample_rate(&out->stream.common);
2313 // usleep not guaranteed for values over 1 second but we don't limit here.
2314 }
2315 }
2316
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002317 pthread_mutex_unlock(&out->lock);
2318
2319 if (ret != 0) {
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002320 out_on_error(&out->stream.common);
Vaughn Nf7c7d742016-12-10 18:53:04 -05002321 if (sleeptime_us != 0)
2322 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002323 }
2324 return bytes;
2325}
2326
2327static int out_get_render_position(const struct audio_stream_out *stream,
2328 uint32_t *dsp_frames)
2329{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002330 struct stream_out *out = (struct stream_out *)stream;
2331 *dsp_frames = 0;
2332 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002333 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002334 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002335 unsigned long frames = 0;
2336 // TODO: check return value
2337 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2338 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002339 ALOGVV("%s rendered frames %d sample_rate %d",
2340 __func__, *dsp_frames, out->sample_rate);
2341 }
2342 pthread_mutex_unlock(&out->lock);
2343 return 0;
2344 } else
2345 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346}
2347
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002348static int out_add_audio_effect(const struct audio_stream *stream __unused,
2349 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350{
2351 return 0;
2352}
2353
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002354static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2355 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002356{
2357 return 0;
2358}
2359
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002360static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2361 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362{
2363 return -EINVAL;
2364}
2365
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002366static int out_get_presentation_position(const struct audio_stream_out *stream,
2367 uint64_t *frames, struct timespec *timestamp)
2368{
2369 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002370 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002371 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002372
Eric Laurenta1478072015-09-21 17:21:52 -07002373 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002374
Eric Laurent949a0892013-09-20 09:20:13 -07002375 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2376 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002377 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002378 compress_get_tstamp(out->compr, &dsp_frames,
2379 &out->sample_rate);
2380 ALOGVV("%s rendered frames %ld sample_rate %d",
2381 __func__, dsp_frames, out->sample_rate);
2382 *frames = dsp_frames;
2383 ret = 0;
2384 /* this is the best we can do */
2385 clock_gettime(CLOCK_MONOTONIC, timestamp);
2386 }
2387 } else {
2388 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002389 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002390 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2391 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002392 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002393 // This adjustment accounts for buffering after app processor.
2394 // It is based on estimated DSP latency per use case, rather than exact.
2395 signed_frames -=
2396 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2397
Eric Laurent949a0892013-09-20 09:20:13 -07002398 // It would be unusual for this value to be negative, but check just in case ...
2399 if (signed_frames >= 0) {
2400 *frames = signed_frames;
2401 ret = 0;
2402 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002403 }
2404 }
2405 }
2406
2407 pthread_mutex_unlock(&out->lock);
2408
2409 return ret;
2410}
2411
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002412static int out_set_callback(struct audio_stream_out *stream,
2413 stream_callback_t callback, void *cookie)
2414{
2415 struct stream_out *out = (struct stream_out *)stream;
2416
2417 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002418 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002419 out->offload_callback = callback;
2420 out->offload_cookie = cookie;
2421 pthread_mutex_unlock(&out->lock);
2422 return 0;
2423}
2424
2425static int out_pause(struct audio_stream_out* stream)
2426{
2427 struct stream_out *out = (struct stream_out *)stream;
2428 int status = -ENOSYS;
2429 ALOGV("%s", __func__);
2430 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
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_PLAYING) {
2433 status = compress_pause(out->compr);
2434 out->offload_state = OFFLOAD_STATE_PAUSED;
2435 }
2436 pthread_mutex_unlock(&out->lock);
2437 }
2438 return status;
2439}
2440
2441static int out_resume(struct audio_stream_out* stream)
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) {
2447 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002448 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002449 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2450 status = compress_resume(out->compr);
2451 out->offload_state = OFFLOAD_STATE_PLAYING;
2452 }
2453 pthread_mutex_unlock(&out->lock);
2454 }
2455 return status;
2456}
2457
2458static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2459{
2460 struct stream_out *out = (struct stream_out *)stream;
2461 int status = -ENOSYS;
2462 ALOGV("%s", __func__);
2463 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002464 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002465 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2466 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2467 else
2468 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2469 pthread_mutex_unlock(&out->lock);
2470 }
2471 return status;
2472}
2473
2474static int out_flush(struct audio_stream_out* stream)
2475{
2476 struct stream_out *out = (struct stream_out *)stream;
2477 ALOGV("%s", __func__);
2478 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002479 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002480 stop_compressed_output_l(out);
2481 pthread_mutex_unlock(&out->lock);
2482 return 0;
2483 }
2484 return -ENOSYS;
2485}
2486
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002487/** audio_stream_in implementation **/
2488static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2489{
2490 struct stream_in *in = (struct stream_in *)stream;
2491
2492 return in->config.rate;
2493}
2494
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002495static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496{
2497 return -ENOSYS;
2498}
2499
2500static size_t in_get_buffer_size(const struct audio_stream *stream)
2501{
2502 struct stream_in *in = (struct stream_in *)stream;
2503
Haynes Mathew George03c40102016-01-29 17:57:48 -08002504 return in->config.period_size * in->af_period_multiplier *
2505 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506}
2507
2508static uint32_t in_get_channels(const struct audio_stream *stream)
2509{
2510 struct stream_in *in = (struct stream_in *)stream;
2511
2512 return in->channel_mask;
2513}
2514
vivek mehta4ed66e62016-04-15 23:33:34 -07002515static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516{
vivek mehta4ed66e62016-04-15 23:33:34 -07002517 struct stream_in *in = (struct stream_in *)stream;
2518 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519}
2520
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002521static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522{
2523 return -ENOSYS;
2524}
2525
2526static int in_standby(struct audio_stream *stream)
2527{
2528 struct stream_in *in = (struct stream_in *)stream;
2529 struct audio_device *adev = in->dev;
2530 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07002531 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002532
2533 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002534
2535 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002536 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002537 audio_extn_sound_trigger_stop_lab(in);
2538 in->standby = true;
2539 }
2540
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002542 if (adev->adm_deregister_stream)
2543 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2544
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002545 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002547 if (in->pcm) {
2548 pcm_close(in->pcm);
2549 in->pcm = NULL;
2550 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002551 adev->enable_voicerx = false;
2552 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002554 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555 }
2556 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002557 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558 return status;
2559}
2560
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002561static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002562{
2563 return 0;
2564}
2565
2566static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2567{
2568 struct stream_in *in = (struct stream_in *)stream;
2569 struct audio_device *adev = in->dev;
2570 struct str_parms *parms;
2571 char *str;
2572 char value[32];
2573 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002574 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575
Eric Laurent994a6932013-07-17 11:51:42 -07002576 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 parms = str_parms_create_str(kvpairs);
2578
2579 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2580
Eric Laurenta1478072015-09-21 17:21:52 -07002581 lock_input_stream(in);
2582
Eric Laurent150dbfe2013-02-27 14:31:02 -08002583 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584 if (ret >= 0) {
2585 val = atoi(value);
2586 /* no audio source uses val == 0 */
2587 if ((in->source != val) && (val != 0)) {
2588 in->source = val;
2589 }
2590 }
2591
2592 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002593
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594 if (ret >= 0) {
2595 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002596 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597 in->device = val;
2598 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002599 if (!in->standby) {
2600 ALOGV("update input routing change");
2601 in->routing_change = true;
2602 select_devices(adev, in->usecase);
2603 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604 }
2605 }
2606
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002608 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609
2610 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002611 ALOGV("%s: exit: status(%d)", __func__, status);
2612 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613}
2614
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002615static char* in_get_parameters(const struct audio_stream *stream __unused,
2616 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002617{
2618 return strdup("");
2619}
2620
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002621static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622{
2623 return 0;
2624}
2625
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002626static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2627{
2628 if (!stream || !parms)
2629 return;
2630
2631 struct stream_in *in = (struct stream_in *)stream;
2632 struct audio_device *adev = in->dev;
2633
2634 card_status_t status;
2635 int card;
2636 if (parse_snd_card_status(parms, &card, &status) < 0)
2637 return;
2638
2639 pthread_mutex_lock(&adev->lock);
2640 bool valid_cb = (card == adev->snd_card);
2641 pthread_mutex_unlock(&adev->lock);
2642
2643 if (!valid_cb)
2644 return;
2645
2646 lock_input_stream(in);
2647 if (in->card_status != status)
2648 in->card_status = status;
2649 pthread_mutex_unlock(&in->lock);
2650
2651 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2652 use_case_table[in->usecase],
2653 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2654
2655 // a better solution would be to report error back to AF and let
2656 // it put the stream to standby
2657 if (status == CARD_STATUS_OFFLINE)
2658 in_standby(&in->stream.common);
2659
2660 return;
2661}
2662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2664 size_t bytes)
2665{
2666 struct stream_in *in = (struct stream_in *)stream;
2667 struct audio_device *adev = in->dev;
2668 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002669 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670
Eric Laurenta1478072015-09-21 17:21:52 -07002671 lock_input_stream(in);
2672
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002673 if (in->is_st_session) {
2674 ALOGVV(" %s: reading on st session bytes=%d", __func__, bytes);
2675 /* Read from sound trigger HAL */
2676 audio_extn_sound_trigger_read(in, buffer, bytes);
2677 pthread_mutex_unlock(&in->lock);
2678 return bytes;
2679 }
2680
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002682 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002684 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686 goto exit;
2687 }
2688 in->standby = 0;
2689 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690
Haynes Mathew George03c40102016-01-29 17:57:48 -08002691 //what's the duration requested by the client?
2692 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2693 in->config.rate;
2694 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002695
Haynes Mathew George03c40102016-01-29 17:57:48 -08002696 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002698 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002699 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002700 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002701 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002702 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002703 if (ret < 0) {
2704 ALOGE("Failed to read w/err %s", strerror(errno));
2705 ret = -errno;
2706 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002707 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2708 if (bytes % 4 == 0) {
2709 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2710 int_buf_stream = buffer;
2711 for (size_t itt=0; itt < bytes/4 ; itt++) {
2712 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002713 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002714 } else {
2715 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2716 ret = -EINVAL;
2717 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002718 }
2719 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720 }
2721
Haynes Mathew George03c40102016-01-29 17:57:48 -08002722 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002724 /*
2725 * Instead of writing zeroes here, we could trust the hardware
2726 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002727 * 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 -08002728 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002729 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730 memset(buffer, 0, bytes);
2731
2732exit:
2733 pthread_mutex_unlock(&in->lock);
2734
2735 if (ret != 0) {
2736 in_standby(&in->stream.common);
2737 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002738 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002740 memset(buffer, 0, bytes); // clear return data
2741 }
2742 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002743 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002744 }
2745 return bytes;
2746}
2747
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002748static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002749{
2750 return 0;
2751}
2752
Andy Hung6ebe5962016-01-15 17:46:57 -08002753static int in_get_capture_position(const struct audio_stream_in *stream,
2754 int64_t *frames, int64_t *time)
2755{
2756 if (stream == NULL || frames == NULL || time == NULL) {
2757 return -EINVAL;
2758 }
2759 struct stream_in *in = (struct stream_in *)stream;
2760 int ret = -ENOSYS;
2761
2762 lock_input_stream(in);
2763 if (in->pcm) {
2764 struct timespec timestamp;
2765 unsigned int avail;
2766 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2767 *frames = in->frames_read + avail;
2768 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2769 ret = 0;
2770 }
2771 }
2772 pthread_mutex_unlock(&in->lock);
2773 return ret;
2774}
2775
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002776static int add_remove_audio_effect(const struct audio_stream *stream,
2777 effect_handle_t effect,
2778 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002780 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002781 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002782 int status = 0;
2783 effect_descriptor_t desc;
2784
2785 status = (*effect)->get_descriptor(effect, &desc);
2786 if (status != 0)
2787 return status;
2788
Eric Laurenta1478072015-09-21 17:21:52 -07002789 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002790 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002791 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002792 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002793 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002794 in->enable_aec != enable &&
2795 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2796 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002797 if (!enable)
2798 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002799 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2800 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2801 adev->enable_voicerx = enable;
2802 struct audio_usecase *usecase;
2803 struct listnode *node;
2804 list_for_each(node, &adev->usecase_list) {
2805 usecase = node_to_item(node, struct audio_usecase, list);
2806 if (usecase->type == PCM_PLAYBACK) {
2807 select_devices(adev, usecase->id);
2808 break;
2809 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002810 }
2811 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002812 if (!in->standby)
2813 select_devices(in->dev, in->usecase);
2814 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07002815 if (in->enable_ns != enable &&
2816 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2817 in->enable_ns = enable;
2818 if (!in->standby)
2819 select_devices(in->dev, in->usecase);
2820 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002821 pthread_mutex_unlock(&in->dev->lock);
2822 pthread_mutex_unlock(&in->lock);
2823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824 return 0;
2825}
2826
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002827static int in_add_audio_effect(const struct audio_stream *stream,
2828 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829{
Eric Laurent994a6932013-07-17 11:51:42 -07002830 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002831 return add_remove_audio_effect(stream, effect, true);
2832}
2833
2834static int in_remove_audio_effect(const struct audio_stream *stream,
2835 effect_handle_t effect)
2836{
Eric Laurent994a6932013-07-17 11:51:42 -07002837 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002838 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839}
2840
2841static int adev_open_output_stream(struct audio_hw_device *dev,
2842 audio_io_handle_t handle,
2843 audio_devices_t devices,
2844 audio_output_flags_t flags,
2845 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07002846 struct audio_stream_out **stream_out,
2847 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002848{
2849 struct audio_device *adev = (struct audio_device *)dev;
2850 struct stream_out *out;
2851 int i, ret;
2852
Eric Laurent994a6932013-07-17 11:51:42 -07002853 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002854 __func__, config->sample_rate, config->channel_mask, devices, flags);
2855 *stream_out = NULL;
2856 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2857
2858 if (devices == AUDIO_DEVICE_NONE)
2859 devices = AUDIO_DEVICE_OUT_SPEAKER;
2860
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002861 out->flags = flags;
2862 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002863 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002864 out->format = config->format;
2865 out->sample_rate = config->sample_rate;
2866 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2867 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002868 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002869
2870 /* Init use case and pcm_config */
2871 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07002872 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002874 pthread_mutex_lock(&adev->lock);
2875 ret = read_hdmi_channel_masks(out);
2876 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002877 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002878 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002879
2880 if (config->sample_rate == 0)
2881 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2882 if (config->channel_mask == 0)
2883 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08002884 if (config->format == AUDIO_FORMAT_DEFAULT)
2885 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002886
2887 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002888 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08002889 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002890 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2891 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002892 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002893 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002894 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07002896 pthread_mutex_lock(&adev->lock);
2897 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
2898 pthread_mutex_unlock(&adev->lock);
2899
2900 // reject offload during card offline to allow
2901 // fallback to s/w paths
2902 if (offline) {
2903 ret = -ENODEV;
2904 goto error_open;
2905 }
2906
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002907 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2908 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2909 ALOGE("%s: Unsupported Offload information", __func__);
2910 ret = -EINVAL;
2911 goto error_open;
2912 }
2913 if (!is_supported_format(config->offload_info.format)) {
2914 ALOGE("%s: Unsupported audio format", __func__);
2915 ret = -EINVAL;
2916 goto error_open;
2917 }
2918
2919 out->compr_config.codec = (struct snd_codec *)
2920 calloc(1, sizeof(struct snd_codec));
2921
2922 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
2923 if (config->offload_info.channel_mask)
2924 out->channel_mask = config->offload_info.channel_mask;
2925 else if (config->channel_mask)
2926 out->channel_mask = config->channel_mask;
2927 out->format = config->offload_info.format;
2928 out->sample_rate = config->offload_info.sample_rate;
2929
2930 out->stream.set_callback = out_set_callback;
2931 out->stream.pause = out_pause;
2932 out->stream.resume = out_resume;
2933 out->stream.drain = out_drain;
2934 out->stream.flush = out_flush;
2935
2936 out->compr_config.codec->id =
2937 get_snd_codec_id(config->offload_info.format);
2938 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
2939 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07002940 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002941 out->compr_config.codec->bit_rate =
2942 config->offload_info.bit_rate;
2943 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002944 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002945 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
2946
2947 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2948 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002949
2950 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002951 create_offload_callback_thread(out);
2952 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2953 __func__, config->offload_info.version,
2954 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002955 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2956 if (config->sample_rate == 0)
2957 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2958 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2959 config->sample_rate != 8000) {
2960 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2961 ret = -EINVAL;
2962 goto error_open;
2963 }
2964 out->sample_rate = config->sample_rate;
2965 out->config.rate = config->sample_rate;
2966 if (config->format == AUDIO_FORMAT_DEFAULT)
2967 config->format = AUDIO_FORMAT_PCM_16_BIT;
2968 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2969 config->format = AUDIO_FORMAT_PCM_16_BIT;
2970 ret = -EINVAL;
2971 goto error_open;
2972 }
2973 out->format = config->format;
2974 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2975 out->config = pcm_config_afe_proxy_playback;
2976 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07002978 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2979 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2980 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07002981 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
2982 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
2983 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07002984 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
2985 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002986 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
2987 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
2988 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Andy Hung6fcba9c2014-03-18 11:53:32 -07002989 } else {
2990 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2991 out->config = pcm_config_low_latency;
2992 }
2993 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2994 if (k_enable_extended_precision
2995 && pcm_params_format_test(adev->use_case_table[out->usecase],
2996 pcm_format_from_audio_format(config->format))) {
2997 out->config.format = pcm_format_from_audio_format(config->format);
2998 /* out->format already set to config->format */
2999 } else {
3000 /* deny the externally proposed config format
3001 * and use the one specified in audio_hw layer configuration.
3002 * Note: out->format is returned by out->stream.common.get_format()
3003 * and is used to set config->format in the code several lines below.
3004 */
3005 out->format = audio_format_from_pcm_format(out->config.format);
3006 }
3007 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003008 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003010 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3011 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003013 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003014 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003015 adev->primary_output = out;
3016 else {
3017 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003018 ret = -EEXIST;
3019 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003020 }
3021 }
3022
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 /* Check if this usecase is already existing */
3024 pthread_mutex_lock(&adev->lock);
3025 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3026 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003028 ret = -EEXIST;
3029 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030 }
3031 pthread_mutex_unlock(&adev->lock);
3032
3033 out->stream.common.get_sample_rate = out_get_sample_rate;
3034 out->stream.common.set_sample_rate = out_set_sample_rate;
3035 out->stream.common.get_buffer_size = out_get_buffer_size;
3036 out->stream.common.get_channels = out_get_channels;
3037 out->stream.common.get_format = out_get_format;
3038 out->stream.common.set_format = out_set_format;
3039 out->stream.common.standby = out_standby;
3040 out->stream.common.dump = out_dump;
3041 out->stream.common.set_parameters = out_set_parameters;
3042 out->stream.common.get_parameters = out_get_parameters;
3043 out->stream.common.add_audio_effect = out_add_audio_effect;
3044 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3045 out->stream.get_latency = out_get_latency;
3046 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003047#ifdef NO_AUDIO_OUT
3048 out->stream.write = out_write_for_no_output;
3049#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003051#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052 out->stream.get_render_position = out_get_render_position;
3053 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003054 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055
Haynes Mathew George03c40102016-01-29 17:57:48 -08003056 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003058 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003059 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003061 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003062 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003063 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065 config->format = out->stream.common.get_format(&out->stream.common);
3066 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3067 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3068
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003069
3070 /*
3071 By locking output stream before registering, we allow the callback
3072 to update stream's state only after stream's initial state is set to
3073 adev state.
3074 */
3075 lock_output_stream(out);
3076 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3077 pthread_mutex_lock(&adev->lock);
3078 out->card_status = adev->card_status;
3079 pthread_mutex_unlock(&adev->lock);
3080 pthread_mutex_unlock(&out->lock);
3081
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003083 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003085
3086error_open:
3087 free(out);
3088 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003089 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003090 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003091}
3092
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003093static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003094 struct audio_stream_out *stream)
3095{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003096 struct stream_out *out = (struct stream_out *)stream;
3097 struct audio_device *adev = out->dev;
3098
Eric Laurent994a6932013-07-17 11:51:42 -07003099 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003100
3101 // must deregister from sndmonitor first to prevent races
3102 // between the callback and close_stream
3103 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003104 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003105 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3106 destroy_offload_callback_thread(out);
3107
3108 if (out->compr_config.codec != NULL)
3109 free(out->compr_config.codec);
3110 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003111
3112 if (adev->voice_tx_output == out)
3113 adev->voice_tx_output = NULL;
3114
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003115 pthread_cond_destroy(&out->cond);
3116 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003118 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119}
3120
3121static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3122{
3123 struct audio_device *adev = (struct audio_device *)dev;
3124 struct str_parms *parms;
3125 char *str;
3126 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003127 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003129 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130
Joe Onorato188b6222016-03-01 11:02:27 -08003131 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003132
3133 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134
3135 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003136 status = voice_set_parameters(adev, parms);
3137 if (status != 0) {
3138 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139 }
3140
3141 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3142 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003143 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3145 adev->bluetooth_nrec = true;
3146 else
3147 adev->bluetooth_nrec = false;
3148 }
3149
3150 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3151 if (ret >= 0) {
3152 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3153 adev->screen_off = false;
3154 else
3155 adev->screen_off = true;
3156 }
3157
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003158 ret = str_parms_get_int(parms, "rotation", &val);
3159 if (ret >= 0) {
3160 bool reverse_speakers = false;
3161 switch(val) {
3162 // FIXME: note that the code below assumes that the speakers are in the correct placement
3163 // relative to the user when the device is rotated 90deg from its default rotation. This
3164 // assumption is device-specific, not platform-specific like this code.
3165 case 270:
3166 reverse_speakers = true;
3167 break;
3168 case 0:
3169 case 90:
3170 case 180:
3171 break;
3172 default:
3173 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003174 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003175 }
Eric Laurent03f09432014-03-25 18:09:11 -07003176 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003177 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003178 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003179 }
3180
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003181 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3182 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003183 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003184 }
3185
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003186 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003187done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003188 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003189 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003190 ALOGV("%s: exit with code(%d)", __func__, status);
3191 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192}
3193
3194static char* adev_get_parameters(const struct audio_hw_device *dev,
3195 const char *keys)
3196{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003197 struct audio_device *adev = (struct audio_device *)dev;
3198 struct str_parms *reply = str_parms_create();
3199 struct str_parms *query = str_parms_create_str(keys);
3200 char *str;
3201
3202 pthread_mutex_lock(&adev->lock);
3203
3204 voice_get_parameters(adev, query, reply);
3205 str = str_parms_to_str(reply);
3206 str_parms_destroy(query);
3207 str_parms_destroy(reply);
3208
3209 pthread_mutex_unlock(&adev->lock);
3210 ALOGV("%s: exit: returns - %s", __func__, str);
3211 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212}
3213
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003214static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215{
3216 return 0;
3217}
3218
Haynes Mathew George5191a852013-09-11 14:19:36 -07003219static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3220{
3221 int ret;
3222 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003223
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003224 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3225
Haynes Mathew George5191a852013-09-11 14:19:36 -07003226 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003227 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003228 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003229
Haynes Mathew George5191a852013-09-11 14:19:36 -07003230 return ret;
3231}
3232
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003233static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234{
3235 return -ENOSYS;
3236}
3237
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003238static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3239 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240{
3241 return -ENOSYS;
3242}
3243
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003244static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003245{
3246 return -ENOSYS;
3247}
3248
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003249static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250{
3251 return -ENOSYS;
3252}
3253
3254static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3255{
3256 struct audio_device *adev = (struct audio_device *)dev;
3257
3258 pthread_mutex_lock(&adev->lock);
3259 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003260 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003262 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3263 voice_is_in_call(adev)) {
3264 voice_stop_call(adev);
3265 adev->current_call_output = NULL;
3266 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003267 }
3268 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003269
3270 audio_extn_extspk_set_mode(adev->extspk, mode);
3271
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272 return 0;
3273}
3274
3275static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3276{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003277 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279
Eric Laurent2bafff12016-03-17 12:17:23 -07003280 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003281 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003282 ret = voice_set_mic_mute(adev, state);
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003283 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003284 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003285
3286 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003287}
3288
3289static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3290{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003291 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292 return 0;
3293}
3294
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003295static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296 const struct audio_config *config)
3297{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003298 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003299
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003300 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3301 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302}
3303
3304static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003305 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306 audio_devices_t devices,
3307 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003308 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003309 audio_input_flags_t flags,
3310 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003311 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312{
3313 struct audio_device *adev = (struct audio_device *)dev;
3314 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003315 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003316 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003317 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318
Eric Laurent994a6932013-07-17 11:51:42 -07003319 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003320 *stream_in = NULL;
3321 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3322 return -EINVAL;
3323
3324 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3325
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003326 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003327 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003328
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329 in->stream.common.get_sample_rate = in_get_sample_rate;
3330 in->stream.common.set_sample_rate = in_set_sample_rate;
3331 in->stream.common.get_buffer_size = in_get_buffer_size;
3332 in->stream.common.get_channels = in_get_channels;
3333 in->stream.common.get_format = in_get_format;
3334 in->stream.common.set_format = in_set_format;
3335 in->stream.common.standby = in_standby;
3336 in->stream.common.dump = in_dump;
3337 in->stream.common.set_parameters = in_set_parameters;
3338 in->stream.common.get_parameters = in_get_parameters;
3339 in->stream.common.add_audio_effect = in_add_audio_effect;
3340 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3341 in->stream.set_gain = in_set_gain;
3342 in->stream.read = in_read;
3343 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003344 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345
3346 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003347 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349 in->standby = 1;
3350 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003351 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003352 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353
vivek mehta57ff9b52016-04-28 14:13:08 -07003354 // restrict 24 bit capture for unprocessed source only
3355 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3356 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003357 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003358 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3359 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3360 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3361 bool ret_error = false;
3362 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3363 from HAL is 8_24
3364 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3365 8_24 return error indicating supported format is 8_24
3366 *> In case of any other source requesting 24 bit or float return error
3367 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003368
vivek mehta57ff9b52016-04-28 14:13:08 -07003369 on error flinger will retry with supported format passed
3370 */
3371 if (source != AUDIO_SOURCE_UNPROCESSED) {
3372 config->format = AUDIO_FORMAT_PCM_16_BIT;
3373 ret_error = true;
3374 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3375 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3376 ret_error = true;
3377 }
3378
3379 if (ret_error) {
3380 ret = -EINVAL;
3381 goto err_open;
3382 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003383 }
3384
vivek mehta57ff9b52016-04-28 14:13:08 -07003385 in->format = config->format;
3386
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003388 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3389 if (config->sample_rate == 0)
3390 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3391 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3392 config->sample_rate != 8000) {
3393 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3394 ret = -EINVAL;
3395 goto err_open;
3396 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003397
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003398 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3399 config->format = AUDIO_FORMAT_PCM_16_BIT;
3400 ret = -EINVAL;
3401 goto err_open;
3402 }
3403
3404 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3405 in->config = pcm_config_afe_proxy_record;
3406 } else {
3407 in->usecase = USECASE_AUDIO_RECORD;
3408 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3409 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3410 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003411#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003412 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003413#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003414 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003415 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003416
Haynes Mathew George03c40102016-01-29 17:57:48 -08003417 in->config = in->realtime ? pcm_config_audio_capture_rt :
3418 pcm_config_audio_capture;
3419
vivek mehta4ed66e62016-04-15 23:33:34 -07003420 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3421 in->config.format = PCM_FORMAT_S24_LE;
3422
Haynes Mathew George03c40102016-01-29 17:57:48 -08003423 if (!in->realtime) {
3424 frame_size = audio_stream_in_frame_size(&in->stream);
3425 buffer_size = get_input_buffer_size(config->sample_rate,
3426 config->format,
3427 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003428 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003429 in->config.period_size = buffer_size / frame_size;
3430 } // period size is left untouched for rt mode playback
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003431 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003432
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003433 in->config.channels = channel_count;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003434 if (in->realtime) {
3435 in->af_period_multiplier = af_period_multiplier;
3436 } else {
3437 in->config.rate = config->sample_rate;
3438 in->af_period_multiplier = 1;
3439 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003441 /* This stream could be for sound trigger lab,
3442 get sound trigger pcm if present */
3443 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003444
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003445 lock_input_stream(in);
3446 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3447 pthread_mutex_lock(&adev->lock);
3448 in->card_status = adev->card_status;
3449 pthread_mutex_unlock(&adev->lock);
3450 pthread_mutex_unlock(&in->lock);
3451
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003453 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454 return 0;
3455
3456err_open:
3457 free(in);
3458 *stream_in = NULL;
3459 return ret;
3460}
3461
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003462static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463 struct audio_stream_in *stream)
3464{
Eric Laurent994a6932013-07-17 11:51:42 -07003465 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003466
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003467 // must deregister from sndmonitor first to prevent races
3468 // between the callback and close_stream
3469 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003470 in_standby(&stream->common);
3471 free(stream);
3472
3473 return;
3474}
3475
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003476static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477{
3478 return 0;
3479}
3480
Andy Hung31aca912014-03-20 17:14:59 -07003481/* verifies input and output devices and their capabilities.
3482 *
3483 * This verification is required when enabling extended bit-depth or
3484 * sampling rates, as not all qcom products support it.
3485 *
3486 * Suitable for calling only on initialization such as adev_open().
3487 * It fills the audio_device use_case_table[] array.
3488 *
3489 * Has a side-effect that it needs to configure audio routing / devices
3490 * in order to power up the devices and read the device parameters.
3491 * It does not acquire any hw device lock. Should restore the devices
3492 * back to "normal state" upon completion.
3493 */
3494static int adev_verify_devices(struct audio_device *adev)
3495{
3496 /* enumeration is a bit difficult because one really wants to pull
3497 * the use_case, device id, etc from the hidden pcm_device_table[].
3498 * In this case there are the following use cases and device ids.
3499 *
3500 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3501 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3502 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3503 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3504 * [USECASE_AUDIO_RECORD] = {0, 0},
3505 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3506 * [USECASE_VOICE_CALL] = {2, 2},
3507 *
3508 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3509 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3510 */
3511
3512 /* should be the usecases enabled in adev_open_input_stream() */
3513 static const int test_in_usecases[] = {
3514 USECASE_AUDIO_RECORD,
3515 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3516 };
3517 /* should be the usecases enabled in adev_open_output_stream()*/
3518 static const int test_out_usecases[] = {
3519 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3520 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3521 };
3522 static const usecase_type_t usecase_type_by_dir[] = {
3523 PCM_PLAYBACK,
3524 PCM_CAPTURE,
3525 };
3526 static const unsigned flags_by_dir[] = {
3527 PCM_OUT,
3528 PCM_IN,
3529 };
3530
3531 size_t i;
3532 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003533 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003534 char info[512]; /* for possible debug info */
3535
3536 for (dir = 0; dir < 2; ++dir) {
3537 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3538 const unsigned flags_dir = flags_by_dir[dir];
3539 const size_t testsize =
3540 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3541 const int *testcases =
3542 dir ? test_in_usecases : test_out_usecases;
3543 const audio_devices_t audio_device =
3544 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3545
3546 for (i = 0; i < testsize; ++i) {
3547 const audio_usecase_t audio_usecase = testcases[i];
3548 int device_id;
3549 snd_device_t snd_device;
3550 struct pcm_params **pparams;
3551 struct stream_out out;
3552 struct stream_in in;
3553 struct audio_usecase uc_info;
3554 int retval;
3555
3556 pparams = &adev->use_case_table[audio_usecase];
3557 pcm_params_free(*pparams); /* can accept null input */
3558 *pparams = NULL;
3559
3560 /* find the device ID for the use case (signed, for error) */
3561 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3562 if (device_id < 0)
3563 continue;
3564
3565 /* prepare structures for device probing */
3566 memset(&uc_info, 0, sizeof(uc_info));
3567 uc_info.id = audio_usecase;
3568 uc_info.type = usecase_type;
3569 if (dir) {
3570 adev->active_input = &in;
3571 memset(&in, 0, sizeof(in));
3572 in.device = audio_device;
3573 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3574 uc_info.stream.in = &in;
3575 } else {
3576 adev->active_input = NULL;
3577 }
3578 memset(&out, 0, sizeof(out));
3579 out.devices = audio_device; /* only field needed in select_devices */
3580 uc_info.stream.out = &out;
3581 uc_info.devices = audio_device;
3582 uc_info.in_snd_device = SND_DEVICE_NONE;
3583 uc_info.out_snd_device = SND_DEVICE_NONE;
3584 list_add_tail(&adev->usecase_list, &uc_info.list);
3585
3586 /* select device - similar to start_(in/out)put_stream() */
3587 retval = select_devices(adev, audio_usecase);
3588 if (retval >= 0) {
3589 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3590#if LOG_NDEBUG == 0
3591 if (*pparams) {
3592 ALOGV("%s: (%s) card %d device %d", __func__,
3593 dir ? "input" : "output", card_id, device_id);
3594 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07003595 } else {
3596 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3597 }
3598#endif
3599 }
3600
3601 /* deselect device - similar to stop_(in/out)put_stream() */
3602 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07003603 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07003604 /* 2. Disable the rx device */
3605 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07003606 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07003607 list_remove(&uc_info.list);
3608 }
3609 }
3610 adev->active_input = NULL; /* restore adev state */
3611 return 0;
3612}
3613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614static int adev_close(hw_device_t *device)
3615{
Andy Hung31aca912014-03-20 17:14:59 -07003616 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003618
3619 if (!adev)
3620 return 0;
3621
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003622 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003623 pthread_mutex_lock(&adev_init_lock);
3624
3625 if ((--audio_device_ref_count) == 0) {
3626 audio_route_free(adev->audio_route);
3627 free(adev->snd_dev_ref_cnt);
3628 platform_deinit(adev->platform);
3629 audio_extn_extspk_deinit(adev->extspk);
3630 audio_extn_sound_trigger_deinit(adev);
3631 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3632 pcm_params_free(adev->use_case_table[i]);
3633 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003634 if (adev->adm_deinit)
3635 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003636 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07003637 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07003638
3639 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003640
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641 return 0;
3642}
3643
Glenn Kasten4f993392014-05-14 07:30:48 -07003644/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3645 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3646 * just that it _might_ work.
3647 */
3648static int period_size_is_plausible_for_low_latency(int period_size)
3649{
3650 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003651 case 48:
3652 case 96:
3653 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07003654 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003655 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07003656 case 240:
3657 case 320:
3658 case 480:
3659 return 1;
3660 default:
3661 return 0;
3662 }
3663}
3664
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003665static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
3666{
3667 int card;
3668 card_status_t status;
3669
3670 if (!parms)
3671 return;
3672
3673 if (parse_snd_card_status(parms, &card, &status) < 0)
3674 return;
3675
3676 pthread_mutex_lock(&adev->lock);
3677 bool valid_cb = (card == adev->snd_card);
3678 if (valid_cb) {
3679 if (adev->card_status != status) {
3680 adev->card_status = status;
3681 platform_snd_card_update(adev->platform, status);
3682 }
3683 }
3684 pthread_mutex_unlock(&adev->lock);
3685 return;
3686}
3687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688static int adev_open(const hw_module_t *module, const char *name,
3689 hw_device_t **device)
3690{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003691 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692
Eric Laurent2bafff12016-03-17 12:17:23 -07003693 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003695 pthread_mutex_lock(&adev_init_lock);
3696 if (audio_device_ref_count != 0) {
3697 *device = &adev->device.common;
3698 audio_device_ref_count++;
3699 ALOGV("%s: returning existing instance of adev", __func__);
3700 ALOGV("%s: exit", __func__);
3701 pthread_mutex_unlock(&adev_init_lock);
3702 return 0;
3703 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704 adev = calloc(1, sizeof(struct audio_device));
3705
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003706 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3707
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3709 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3710 adev->device.common.module = (struct hw_module_t *)module;
3711 adev->device.common.close = adev_close;
3712
3713 adev->device.init_check = adev_init_check;
3714 adev->device.set_voice_volume = adev_set_voice_volume;
3715 adev->device.set_master_volume = adev_set_master_volume;
3716 adev->device.get_master_volume = adev_get_master_volume;
3717 adev->device.set_master_mute = adev_set_master_mute;
3718 adev->device.get_master_mute = adev_get_master_mute;
3719 adev->device.set_mode = adev_set_mode;
3720 adev->device.set_mic_mute = adev_set_mic_mute;
3721 adev->device.get_mic_mute = adev_get_mic_mute;
3722 adev->device.set_parameters = adev_set_parameters;
3723 adev->device.get_parameters = adev_get_parameters;
3724 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3725 adev->device.open_output_stream = adev_open_output_stream;
3726 adev->device.close_output_stream = adev_close_output_stream;
3727 adev->device.open_input_stream = adev_open_input_stream;
3728 adev->device.close_input_stream = adev_close_input_stream;
3729 adev->device.dump = adev_dump;
3730
3731 /* Set the default route before the PCM stream is opened */
3732 pthread_mutex_lock(&adev->lock);
3733 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003734 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003735 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003737 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003738 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003739 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003740 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003741 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742 pthread_mutex_unlock(&adev->lock);
3743
3744 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003745 adev->platform = platform_init(adev);
3746 if (!adev->platform) {
3747 free(adev->snd_dev_ref_cnt);
3748 free(adev);
3749 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3750 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003751 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003752 return -EINVAL;
3753 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05003754 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003755 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003756
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003757 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3758 if (adev->visualizer_lib == NULL) {
3759 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3760 } else {
3761 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3762 adev->visualizer_start_output =
3763 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3764 "visualizer_hal_start_output");
3765 adev->visualizer_stop_output =
3766 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3767 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07003768 }
3769
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003770 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3771 if (adev->offload_effects_lib == NULL) {
3772 ALOGW("%s: DLOPEN failed for %s", __func__,
3773 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3774 } else {
3775 ALOGV("%s: DLOPEN successful for %s", __func__,
3776 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3777 adev->offload_effects_start_output =
3778 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3779 "offload_effects_bundle_hal_start_output");
3780 adev->offload_effects_stop_output =
3781 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3782 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07003783 }
3784
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003785 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3786 if (adev->adm_lib == NULL) {
3787 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3788 } else {
3789 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3790 adev->adm_init = (adm_init_t)
3791 dlsym(adev->adm_lib, "adm_init");
3792 adev->adm_deinit = (adm_deinit_t)
3793 dlsym(adev->adm_lib, "adm_deinit");
3794 adev->adm_register_input_stream = (adm_register_input_stream_t)
3795 dlsym(adev->adm_lib, "adm_register_input_stream");
3796 adev->adm_register_output_stream = (adm_register_output_stream_t)
3797 dlsym(adev->adm_lib, "adm_register_output_stream");
3798 adev->adm_deregister_stream = (adm_deregister_stream_t)
3799 dlsym(adev->adm_lib, "adm_deregister_stream");
3800 adev->adm_request_focus = (adm_request_focus_t)
3801 dlsym(adev->adm_lib, "adm_request_focus");
3802 adev->adm_abandon_focus = (adm_abandon_focus_t)
3803 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08003804 adev->adm_set_config = (adm_set_config_t)
3805 dlsym(adev->adm_lib, "adm_set_config");
3806 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
3807 dlsym(adev->adm_lib, "adm_request_focus_v2");
3808 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
3809 dlsym(adev->adm_lib, "adm_is_noirq_avail");
3810 adev->adm_on_routing_change = (adm_on_routing_change_t)
3811 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003812 }
3813
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003814 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003815 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003816
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003818
Andy Hung31aca912014-03-20 17:14:59 -07003819 if (k_enable_extended_precision)
3820 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821
Glenn Kasten4f993392014-05-14 07:30:48 -07003822 char value[PROPERTY_VALUE_MAX];
3823 int trial;
3824 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3825 trial = atoi(value);
3826 if (period_size_is_plausible_for_low_latency(trial)) {
3827 pcm_config_low_latency.period_size = trial;
3828 pcm_config_low_latency.start_threshold = trial / 4;
3829 pcm_config_low_latency.avail_min = trial / 4;
3830 configured_low_latency_capture_period_size = trial;
3831 }
3832 }
3833 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3834 trial = atoi(value);
3835 if (period_size_is_plausible_for_low_latency(trial)) {
3836 configured_low_latency_capture_period_size = trial;
3837 }
3838 }
3839
vivek mehta1a9b7c02015-06-25 11:49:38 -07003840 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003841
3842 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
3843 af_period_multiplier = atoi(value);
3844 if (af_period_multiplier < 0) {
3845 af_period_multiplier = 2;
3846 } else if (af_period_multiplier > 4) {
3847 af_period_multiplier = 4;
3848 }
3849 ALOGV("new period_multiplier = %d", af_period_multiplier);
3850 }
3851
vivek mehta1a9b7c02015-06-25 11:49:38 -07003852 pthread_mutex_unlock(&adev_init_lock);
3853
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003854 if (adev->adm_init)
3855 adev->adm_data = adev->adm_init();
3856
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003857 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003858 audio_extn_snd_mon_init();
3859 pthread_mutex_lock(&adev->lock);
3860 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
3861 adev->card_status = CARD_STATUS_ONLINE;
3862 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003863
Eric Laurent2bafff12016-03-17 12:17:23 -07003864 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003865 return 0;
3866}
3867
3868static struct hw_module_methods_t hal_module_methods = {
3869 .open = adev_open,
3870};
3871
3872struct audio_module HAL_MODULE_INFO_SYM = {
3873 .common = {
3874 .tag = HARDWARE_MODULE_TAG,
3875 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3876 .hal_api_version = HARDWARE_HAL_API_VERSION,
3877 .id = AUDIO_HARDWARE_MODULE_ID,
3878 .name = "QCOM Audio HAL",
3879 .author = "Code Aurora Forum",
3880 .methods = &hal_module_methods,
3881 },
3882};