blob: 0a5bccb3b291d5a698e59b8a395ff3fe32bd1fda [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"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080056#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070057
Eric Laurent397db572016-05-11 11:31:47 -070058/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
59 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070060#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070061// 2 buffers causes problems with high bitrate files
62#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070063/* ToDo: Check and update a proper value in msec */
64#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
65#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
66
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070067#define PROXY_OPEN_RETRY_COUNT 100
68#define PROXY_OPEN_WAIT_TIME 20
69
vivek mehtadae44712015-07-27 14:13:18 -070070#define MIN_CHANNEL_COUNT 1
71#define DEFAULT_CHANNEL_COUNT 2
72
Jean-Michel Trivic0750692015-10-12 12:12:32 -070073#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
74#define MAX_CHANNEL_COUNT 1
75#else
vivek mehtadae44712015-07-27 14:13:18 -070076#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
77#define XSTR(x) STR(x)
78#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070079#endif
vivek mehtadae44712015-07-27 14:13:18 -070080
Haynes Mathew George03c40102016-01-29 17:57:48 -080081#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
82
Glenn Kasten4f993392014-05-14 07:30:48 -070083static unsigned int configured_low_latency_capture_period_size =
84 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
85
Andy Hung31aca912014-03-20 17:14:59 -070086/* This constant enables extended precision handling.
87 * TODO The flag is off until more testing is done.
88 */
89static const bool k_enable_extended_precision = false;
90
Eric Laurentb23d5282013-05-14 15:27:20 -070091struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -070092 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -070093 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
94 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
95 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
96 .format = PCM_FORMAT_S16_LE,
97 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
98 .stop_threshold = INT_MAX,
99 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
100};
101
102struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700103 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700104 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
105 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
106 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
107 .format = PCM_FORMAT_S16_LE,
108 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
109 .stop_threshold = INT_MAX,
110 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
111};
112
Haynes Mathew George03c40102016-01-29 17:57:48 -0800113static int af_period_multiplier = 4;
114struct pcm_config pcm_config_rt = {
115 .channels = DEFAULT_CHANNEL_COUNT,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = ULL_PERIOD_SIZE, //1 ms
118 .period_count = 512, //=> buffer size is 512ms
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
121 .stop_threshold = INT_MAX,
122 .silence_threshold = 0,
123 .silence_size = 0,
124 .avail_min = ULL_PERIOD_SIZE, //1 ms
125};
126
Eric Laurentb23d5282013-05-14 15:27:20 -0700127struct pcm_config pcm_config_hdmi_multi = {
128 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
129 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
130 .period_size = HDMI_MULTI_PERIOD_SIZE,
131 .period_count = HDMI_MULTI_PERIOD_COUNT,
132 .format = PCM_FORMAT_S16_LE,
133 .start_threshold = 0,
134 .stop_threshold = INT_MAX,
135 .avail_min = 0,
136};
137
138struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700139 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700140 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
141 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700142 .stop_threshold = INT_MAX,
143 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700144};
145
Haynes Mathew George03c40102016-01-29 17:57:48 -0800146struct pcm_config pcm_config_audio_capture_rt = {
147 .channels = DEFAULT_CHANNEL_COUNT,
148 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
149 .period_size = ULL_PERIOD_SIZE,
150 .period_count = 512,
151 .format = PCM_FORMAT_S16_LE,
152 .start_threshold = 0,
153 .stop_threshold = INT_MAX,
154 .silence_threshold = 0,
155 .silence_size = 0,
156 .avail_min = ULL_PERIOD_SIZE, //1 ms
157};
158
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700159#define AFE_PROXY_CHANNEL_COUNT 2
160#define AFE_PROXY_SAMPLING_RATE 48000
161
162#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
163#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
164
165struct pcm_config pcm_config_afe_proxy_playback = {
166 .channels = AFE_PROXY_CHANNEL_COUNT,
167 .rate = AFE_PROXY_SAMPLING_RATE,
168 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
169 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
170 .format = PCM_FORMAT_S16_LE,
171 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
172 .stop_threshold = INT_MAX,
173 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
174};
175
176#define AFE_PROXY_RECORD_PERIOD_SIZE 768
177#define AFE_PROXY_RECORD_PERIOD_COUNT 4
178
179struct pcm_config pcm_config_afe_proxy_record = {
180 .channels = AFE_PROXY_CHANNEL_COUNT,
181 .rate = AFE_PROXY_SAMPLING_RATE,
182 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
183 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
186 .stop_threshold = INT_MAX,
187 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
188};
189
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700190const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700191 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
192 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
193 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700194 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700195 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700196 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700197
Eric Laurentb23d5282013-05-14 15:27:20 -0700198 [USECASE_AUDIO_RECORD] = "audio-record",
199 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700200
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800201 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
202 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700203
Eric Laurentb23d5282013-05-14 15:27:20 -0700204 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700205 [USECASE_VOICE2_CALL] = "voice2-call",
206 [USECASE_VOLTE_CALL] = "volte-call",
207 [USECASE_QCHAT_CALL] = "qchat-call",
208 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800209 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
210 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700211
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700212 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
213 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
214
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700215 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
216 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700217};
218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800219
220#define STRING_TO_ENUM(string) { #string, string }
221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800222struct string_to_enum {
223 const char *name;
224 uint32_t value;
225};
226
227static const struct string_to_enum out_channels_name_to_enum_table[] = {
228 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
229 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
230 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
231};
232
Haynes Mathew George5191a852013-09-11 14:19:36 -0700233static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700234static struct audio_device *adev = NULL;
235static pthread_mutex_t adev_init_lock;
236static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700237//cache last MBDRC cal step level
238static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700239
Haynes Mathew George03c40102016-01-29 17:57:48 -0800240static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
241 int flags __unused)
242{
243 int dir = 0;
244 switch (uc_id) {
245 case USECASE_AUDIO_RECORD_LOW_LATENCY:
246 dir = 1;
247 case USECASE_AUDIO_PLAYBACK_ULL:
248 break;
249 default:
250 return false;
251 }
252
253 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
254 PCM_PLAYBACK : PCM_CAPTURE);
255 if (adev->adm_is_noirq_avail)
256 return adev->adm_is_noirq_avail(adev->adm_data,
257 adev->snd_card, dev_id, dir);
258 return false;
259}
260
261static void register_out_stream(struct stream_out *out)
262{
263 struct audio_device *adev = out->dev;
264 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
265 return;
266
267 if (!adev->adm_register_output_stream)
268 return;
269
270 adev->adm_register_output_stream(adev->adm_data,
271 out->handle,
272 out->flags);
273
274 if (!adev->adm_set_config)
275 return;
276
277 if (out->realtime) {
278 adev->adm_set_config(adev->adm_data,
279 out->handle,
280 out->pcm, &out->config);
281 }
282}
283
284static void register_in_stream(struct stream_in *in)
285{
286 struct audio_device *adev = in->dev;
287 if (!adev->adm_register_input_stream)
288 return;
289
290 adev->adm_register_input_stream(adev->adm_data,
291 in->capture_handle,
292 in->flags);
293
294 if (!adev->adm_set_config)
295 return;
296
297 if (in->realtime) {
298 adev->adm_set_config(adev->adm_data,
299 in->capture_handle,
300 in->pcm,
301 &in->config);
302 }
303}
304
305static void request_out_focus(struct stream_out *out, long ns)
306{
307 struct audio_device *adev = out->dev;
308
309 if (out->routing_change) {
310 out->routing_change = false;
311 if (adev->adm_on_routing_change)
312 adev->adm_on_routing_change(adev->adm_data, out->handle);
313 }
314
315 if (adev->adm_request_focus_v2) {
316 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
317 } else if (adev->adm_request_focus) {
318 adev->adm_request_focus(adev->adm_data, out->handle);
319 }
320}
321
322static void request_in_focus(struct stream_in *in, long ns)
323{
324 struct audio_device *adev = in->dev;
325
326 if (in->routing_change) {
327 in->routing_change = false;
328 if (adev->adm_on_routing_change)
329 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
330 }
331
332 if (adev->adm_request_focus_v2) {
333 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
334 } else if (adev->adm_request_focus) {
335 adev->adm_request_focus(adev->adm_data, in->capture_handle);
336 }
337}
338
339static void release_out_focus(struct stream_out *out, long ns __unused)
340{
341 struct audio_device *adev = out->dev;
342
343 if (adev->adm_abandon_focus)
344 adev->adm_abandon_focus(adev->adm_data, out->handle);
345}
346
347static void release_in_focus(struct stream_in *in, long ns __unused)
348{
349 struct audio_device *adev = in->dev;
350 if (adev->adm_abandon_focus)
351 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
352}
353
Andy Hung7401c7c2016-09-21 12:41:21 -0700354// Time string format similar to logcat, buffer_length must be >= 19 chars.
355static void ns2string(int64_t ns, char *buffer, int buffer_length)
356{
357 const int one_second = 1000000000;
358 const time_t sec = ns / one_second;
359 struct tm tm;
360 localtime_r(&sec, &tm);
361 snprintf(buffer, buffer_length, "%02d-%02d %02d:%02d:%02d.%03d",
362 tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range
363 tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
364 (int)(ns % one_second / 1000000));
365}
366
367// Convert timespec to nsec.
368static int64_t ts2ns(const struct timespec *ts)
369{
370 return ts->tv_sec * 1000000000LL + ts->tv_nsec;
371}
372
373// Log errors: consecutive errors with the same code will
374// be aggregated if they occur within one second.
375// A mutual exclusion lock must be held before calling.
376static void log_error_l(struct error_log *log, int code) {
377 ++log->errors;
378
379 struct timespec now_ts = { 0, 0 };
380 (void)clock_gettime(CLOCK_REALTIME, &now_ts);
381 const int64_t now = ts2ns(&now_ts);
382
383 // Within 1 second, cluster the same error codes together.
384 const int one_second = 1000000000;
385 if (code == log->entries[log->idx].code &&
386 now - log->entries[log->idx].last_time < one_second) {
387 log->entries[log->idx].count++;
388 log->entries[log->idx].last_time = now;
389 return;
390 }
391
392 // Add new error entry.
393 if (++log->idx >= ARRAY_SIZE(log->entries)) {
394 log->idx = 0;
395 }
396 log->entries[log->idx].count = 1;
397 log->entries[log->idx].code = code;
398 log->entries[log->idx].first_time = now;
399 log->entries[log->idx].last_time = now;
400}
401
402// Dump information in the error log. A mutual exclusion lock
403// should be held, but if that cannot be obtained, one should
404// make a copy of the error log before calling -- the call is
405// still safe, but there might be some misinterpreted data.
406static void log_dump_l(const struct error_log *log, int fd)
407{
408 dprintf(fd, " Errors: %u\n", log->errors);
409 if (log->errors == 0)
410 return;
411
412 dprintf(fd, " Index Code Freq First time Last time\n");
413 for (size_t i = 0; i < ARRAY_SIZE(log->entries); ++i) {
414 if (log->entries[i].count != 0) {
415 char first_time[32];
416 char last_time[32];
417 ns2string(log->entries[i].first_time, first_time, sizeof(first_time));
418 ns2string(log->entries[i].last_time, last_time, sizeof(last_time));
419 dprintf(fd, " %c%4zu %4d %5d %s %s\n",
420 i == log->idx ? '*' : ' ', // mark head position
421 i, log->entries[i].code, log->entries[i].count,
422 first_time, last_time);
423 }
424 }
425}
426
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700427static int parse_snd_card_status(struct str_parms * parms, int * card,
428 card_status_t * status)
429{
430 char value[32]={0};
431 char state[32]={0};
432
433 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
434
435 if (ret < 0)
436 return -1;
437
438 // sscanf should be okay as value is of max length 32.
439 // same as sizeof state.
440 if (sscanf(value, "%d,%s", card, state) < 2)
441 return -1;
442
443 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
444 CARD_STATUS_OFFLINE;
445 return 0;
446}
447
vivek mehta1a9b7c02015-06-25 11:49:38 -0700448__attribute__ ((visibility ("default")))
449bool audio_hw_send_gain_dep_calibration(int level) {
450 bool ret_val = false;
451 ALOGV("%s: enter ... ", __func__);
452
453 pthread_mutex_lock(&adev_init_lock);
454
455 if (adev != NULL && adev->platform != NULL) {
456 pthread_mutex_lock(&adev->lock);
457 ret_val = platform_send_gain_dep_cal(adev->platform, level);
458 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700459
460 // if cal set fails, cache level info
461 // if cal set succeds, reset known last cal set
462 if (!ret_val)
463 last_known_cal_step = level;
464 else if (last_known_cal_step != -1)
465 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700466 } else {
467 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
468 }
469
470 pthread_mutex_unlock(&adev_init_lock);
471
472 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
473 return ret_val;
474}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700475
vivek mehtaa8d7c922016-05-25 14:40:44 -0700476__attribute__ ((visibility ("default")))
477int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
478 int table_size) {
479 int ret_val = 0;
480 ALOGV("%s: enter ... ", __func__);
481
482 pthread_mutex_lock(&adev_init_lock);
483 if (adev == NULL) {
484 ALOGW("%s: adev is NULL .... ", __func__);
485 goto done;
486 }
487
488 pthread_mutex_lock(&adev->lock);
489 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
490 pthread_mutex_unlock(&adev->lock);
491done:
492 pthread_mutex_unlock(&adev_init_lock);
493 ALOGV("%s: exit ... ", __func__);
494 return ret_val;
495}
496
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700497static bool is_supported_format(audio_format_t format)
498{
Eric Laurent8251ac82014-07-23 11:00:25 -0700499 switch (format) {
500 case AUDIO_FORMAT_MP3:
501 case AUDIO_FORMAT_AAC_LC:
502 case AUDIO_FORMAT_AAC_HE_V1:
503 case AUDIO_FORMAT_AAC_HE_V2:
504 return true;
505 default:
506 break;
507 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700508 return false;
509}
510
Haynes Mathew George03c40102016-01-29 17:57:48 -0800511static inline bool is_mmap_usecase(audio_usecase_t uc_id)
512{
513 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
514 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
515}
516
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700517static int get_snd_codec_id(audio_format_t format)
518{
519 int id = 0;
520
Eric Laurent8251ac82014-07-23 11:00:25 -0700521 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700522 case AUDIO_FORMAT_MP3:
523 id = SND_AUDIOCODEC_MP3;
524 break;
525 case AUDIO_FORMAT_AAC:
526 id = SND_AUDIOCODEC_AAC;
527 break;
528 default:
529 ALOGE("%s: Unsupported audio format", __func__);
530 }
531
532 return id;
533}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800534
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800535static int audio_ssr_status(struct audio_device *adev)
536{
537 int ret = 0;
538 struct mixer_ctl *ctl;
539 const char *mixer_ctl_name = "Audio SSR Status";
540
541 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
542 ret = mixer_ctl_get_value(ctl, 0);
543 ALOGD("%s: value: %d", __func__, ret);
544 return ret;
545}
546
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800547int enable_audio_route(struct audio_device *adev,
548 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800549{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700550 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800551 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800552
553 if (usecase == NULL)
554 return -EINVAL;
555
556 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
557
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800558 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700559 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800560 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700561 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800562
Yamit Mehtae3b99562016-09-16 22:44:00 +0530563 audio_extn_utils_send_app_type_cfg(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800564 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500565 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700566 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700567 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800568
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800569 ALOGV("%s: exit", __func__);
570 return 0;
571}
572
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800573int disable_audio_route(struct audio_device *adev,
574 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800575{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700576 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800577 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800578
579 if (usecase == NULL)
580 return -EINVAL;
581
582 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700583 if (usecase->type == PCM_CAPTURE)
584 snd_device = usecase->in_snd_device;
585 else
586 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800587 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500588 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700589 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700590 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800592 ALOGV("%s: exit", __func__);
593 return 0;
594}
595
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800596int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700597 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800598{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700599 int i, num_devices = 0;
600 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800601 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800602 if (snd_device < SND_DEVICE_MIN ||
603 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800604 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800605 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800606 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700607
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700608 platform_send_audio_calibration(adev->platform, snd_device);
609
vivek mehtade4849c2016-03-03 17:23:38 -0800610 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700611 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700612 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800613 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700614 }
615
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700616 /* due to the possibility of calibration overwrite between listen
617 and audio, notify sound trigger hal before audio calibration is sent */
618 audio_extn_sound_trigger_update_device_status(snd_device,
619 ST_EVENT_SND_DEVICE_BUSY);
620
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700621 if (audio_extn_spkr_prot_is_enabled())
622 audio_extn_spkr_prot_calib_cancel(adev);
623
zhaoyang yin4211fad2015-06-04 21:13:25 +0800624 audio_extn_dsm_feedback_enable(adev, snd_device, true);
625
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700626 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
627 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
628 audio_extn_spkr_prot_is_enabled()) {
629 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800630 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700631 }
632 if (audio_extn_spkr_prot_start_processing(snd_device)) {
633 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800634 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700635 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700636 } else if (platform_can_split_snd_device(snd_device,
637 &num_devices,
638 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700639 for (i = 0; i < num_devices; i++) {
640 enable_snd_device(adev, new_snd_devices[i]);
641 }
vivek mehtab6506412015-08-07 16:55:17 -0700642 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700643 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800644 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
645 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
646 ALOGE(" %s: Invalid sound device returned", __func__);
647 goto on_error;
648 }
Ed Tam70b5c142016-03-21 19:14:29 -0700649
Eric Laurent2e140aa2016-06-30 17:14:46 -0700650 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800651 audio_route_apply_and_update_path(adev->audio_route, device_name);
652 }
653on_success:
654 adev->snd_dev_ref_cnt[snd_device]++;
655 ret_val = 0;
656on_error:
657 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800658}
659
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800660int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700661 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800662{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700663 int i, num_devices = 0;
664 snd_device_t new_snd_devices[2];
665
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800666 if (snd_device < SND_DEVICE_MIN ||
667 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800668 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800669 return -EINVAL;
670 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
672 ALOGE("%s: device ref cnt is already 0", __func__);
673 return -EINVAL;
674 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800675 audio_extn_tfa_98xx_disable_speaker(snd_device);
676
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700677 adev->snd_dev_ref_cnt[snd_device]--;
678 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800679 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700680 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
681 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
682 audio_extn_spkr_prot_is_enabled()) {
683 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700684 } else if (platform_can_split_snd_device(snd_device,
685 &num_devices,
686 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700687 for (i = 0; i < num_devices; i++) {
688 disable_snd_device(adev, new_snd_devices[i]);
689 }
vivek mehtab6506412015-08-07 16:55:17 -0700690 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700691 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800692 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
693 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
694 ALOGE(" %s: Invalid sound device returned", __func__);
695 return -EINVAL;
696 }
697
Eric Laurent2e140aa2016-06-30 17:14:46 -0700698 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800699 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700700 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700701 audio_extn_sound_trigger_update_device_status(snd_device,
702 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700703 }
vivek mehtab6506412015-08-07 16:55:17 -0700704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800705 return 0;
706}
707
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700708/*
709 legend:
710 uc - existing usecase
711 new_uc - new usecase
712 d1, d11, d2 - SND_DEVICE enums
713 a1, a2 - corresponding ANDROID device enums
714 B, B1, B2 - backend strings
715
716case 1
717 uc->dev d1 (a1) B1
718 new_uc->dev d1 (a1), d2 (a2) B1, B2
719
720 resolution: disable and enable uc->dev on d1
721
722case 2
723 uc->dev d1 (a1) B1
724 new_uc->dev d11 (a1) B1
725
726 resolution: need to switch uc since d1 and d11 are related
727 (e.g. speaker and voice-speaker)
728 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
729
730case 3
731 uc->dev d1 (a1) B1
732 new_uc->dev d2 (a2) B2
733
734 resolution: no need to switch uc
735
736case 4
737 uc->dev d1 (a1) B
738 new_uc->dev d2 (a2) B
739
740 resolution: disable enable uc-dev on d2 since backends match
741 we cannot enable two streams on two different devices if they
742 share the same backend. e.g. if offload is on speaker device using
743 QUAD_MI2S backend and a low-latency stream is started on voice-handset
744 using the same backend, offload must also be switched to voice-handset.
745
746case 5
747 uc->dev d1 (a1) B
748 new_uc->dev d1 (a1), d2 (a2) B
749
750 resolution: disable enable uc-dev on d2 since backends match
751 we cannot enable two streams on two different devices if they
752 share the same backend.
753
754case 6
755 uc->dev d1 a1 B1
756 new_uc->dev d2 a1 B2
757
758 resolution: no need to switch
759
760case 7
761
762 uc->dev d1 (a1), d2 (a2) B1, B2
763 new_uc->dev d1 B1
764
765 resolution: no need to switch
766
767*/
768static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
769 struct audio_usecase *new_uc,
770 snd_device_t new_snd_device)
771{
772 audio_devices_t a1 = uc->stream.out->devices;
773 audio_devices_t a2 = new_uc->stream.out->devices;
774
775 snd_device_t d1 = uc->out_snd_device;
776 snd_device_t d2 = new_snd_device;
777
778 // Treat as a special case when a1 and a2 are not disjoint
779 if ((a1 != a2) && (a1 & a2)) {
780 snd_device_t d3[2];
781 int num_devices = 0;
782 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
783 &num_devices,
784 d3);
785 if (ret < 0) {
786 if (ret != -ENOSYS) {
787 ALOGW("%s failed to split snd_device %d",
788 __func__,
789 popcount(a1) > 1 ? d1 : d2);
790 }
791 goto end;
792 }
793
794 // NB: case 7 is hypothetical and isn't a practical usecase yet.
795 // But if it does happen, we need to give priority to d2 if
796 // the combo devices active on the existing usecase share a backend.
797 // This is because we cannot have a usecase active on a combo device
798 // and a new usecase requests one device in this combo pair.
799 if (platform_check_backends_match(d3[0], d3[1])) {
800 return d2; // case 5
801 } else {
802 return d1; // case 1
803 }
804 } else {
805 if (platform_check_backends_match(d1, d2)) {
806 return d2; // case 2, 4
807 } else {
808 return d1; // case 6, 3
809 }
810 }
811
812end:
813 return d2; // return whatever was calculated before.
814}
815
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700816static void check_and_route_playback_usecases(struct audio_device *adev,
817 struct audio_usecase *uc_info,
818 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819{
820 struct listnode *node;
821 struct audio_usecase *usecase;
822 bool switch_device[AUDIO_USECASE_MAX];
823 int i, num_uc_to_switch = 0;
824
825 /*
826 * This function is to make sure that all the usecases that are active on
827 * the hardware codec backend are always routed to any one device that is
828 * handled by the hardware codec.
829 * For example, if low-latency and deep-buffer usecases are currently active
830 * on speaker and out_set_parameters(headset) is received on low-latency
831 * output, then we have to make sure deep-buffer is also switched to headset,
832 * because of the limitation that both the devices cannot be enabled
833 * at the same time as they share the same backend.
834 */
835 /* Disable all the usecases on the shared backend other than the
836 specified usecase */
837 for (i = 0; i < AUDIO_USECASE_MAX; i++)
838 switch_device[i] = false;
839
840 list_for_each(node, &adev->usecase_list) {
841 usecase = node_to_item(node, struct audio_usecase, list);
842 if (usecase->type != PCM_CAPTURE &&
843 usecase != uc_info &&
844 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700845 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
846 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700847 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
848 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700849 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700850 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700851 switch_device[usecase->id] = true;
852 num_uc_to_switch++;
853 }
854 }
855
856 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 list_for_each(node, &adev->usecase_list) {
858 usecase = node_to_item(node, struct audio_usecase, list);
859 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700860 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900861 }
862 }
863
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700864 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900865 list_for_each(node, &adev->usecase_list) {
866 usecase = node_to_item(node, struct audio_usecase, list);
867 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700868 d_device = derive_playback_snd_device(usecase, uc_info,
869 snd_device);
870 enable_snd_device(adev, d_device);
871 /* Update the out_snd_device before enabling the audio route */
872 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 }
874 }
875
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700876 /* Re-route all the usecases on the shared backend other than the
877 specified usecase to new snd devices */
878 list_for_each(node, &adev->usecase_list) {
879 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700880 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700881 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882 }
883 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700884 }
885}
886
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700887static void check_and_route_capture_usecases(struct audio_device *adev,
888 struct audio_usecase *uc_info,
889 snd_device_t snd_device)
890{
891 struct listnode *node;
892 struct audio_usecase *usecase;
893 bool switch_device[AUDIO_USECASE_MAX];
894 int i, num_uc_to_switch = 0;
895
vivek mehta4ed66e62016-04-15 23:33:34 -0700896 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
897
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700898 /*
899 * This function is to make sure that all the active capture usecases
900 * are always routed to the same input sound device.
901 * For example, if audio-record and voice-call usecases are currently
902 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
903 * is received for voice call then we have to make sure that audio-record
904 * usecase is also switched to earpiece i.e. voice-dmic-ef,
905 * because of the limitation that two devices cannot be enabled
906 * at the same time if they share the same backend.
907 */
908 for (i = 0; i < AUDIO_USECASE_MAX; i++)
909 switch_device[i] = false;
910
911 list_for_each(node, &adev->usecase_list) {
912 usecase = node_to_item(node, struct audio_usecase, list);
913 if (usecase->type != PCM_PLAYBACK &&
914 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700915 usecase->in_snd_device != snd_device &&
916 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700917 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
918 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700919 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700920 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700921 switch_device[usecase->id] = true;
922 num_uc_to_switch++;
923 }
924 }
925
926 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700927 list_for_each(node, &adev->usecase_list) {
928 usecase = node_to_item(node, struct audio_usecase, list);
929 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700930 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700931 }
932 }
933
934 list_for_each(node, &adev->usecase_list) {
935 usecase = node_to_item(node, struct audio_usecase, list);
936 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700937 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700938 }
939 }
940
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700941 /* Re-route all the usecases on the shared backend other than the
942 specified usecase to new snd devices */
943 list_for_each(node, &adev->usecase_list) {
944 usecase = node_to_item(node, struct audio_usecase, list);
945 /* Update the in_snd_device only before enabling the audio route */
946 if (switch_device[usecase->id] ) {
947 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700948 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700949 }
950 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700951 }
952}
953
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800954/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700955static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800956{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700957 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700958 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800959
960 switch (channels) {
961 /*
962 * Do not handle stereo output in Multi-channel cases
963 * Stereo case is handled in normal playback path
964 */
965 case 6:
966 ALOGV("%s: HDMI supports 5.1", __func__);
967 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
968 break;
969 case 8:
970 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
971 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
972 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
973 break;
974 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700975 ALOGE("HDMI does not support multi channel playback");
976 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800977 break;
978 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700979 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800980}
981
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700982static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
983{
984 struct audio_usecase *usecase;
985 struct listnode *node;
986
987 list_for_each(node, &adev->usecase_list) {
988 usecase = node_to_item(node, struct audio_usecase, list);
989 if (usecase->type == VOICE_CALL) {
990 ALOGV("%s: usecase id %d", __func__, usecase->id);
991 return usecase->id;
992 }
993 }
994 return USECASE_INVALID;
995}
996
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800997struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
998 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700999{
1000 struct audio_usecase *usecase;
1001 struct listnode *node;
1002
1003 list_for_each(node, &adev->usecase_list) {
1004 usecase = node_to_item(node, struct audio_usecase, list);
1005 if (usecase->id == uc_id)
1006 return usecase;
1007 }
1008 return NULL;
1009}
1010
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001011int select_devices(struct audio_device *adev,
1012 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001013{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001014 snd_device_t out_snd_device = SND_DEVICE_NONE;
1015 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001016 struct audio_usecase *usecase = NULL;
1017 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001018 struct audio_usecase *hfp_usecase = NULL;
1019 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001020 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001021 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001023 usecase = get_usecase_from_list(adev, uc_id);
1024 if (usecase == NULL) {
1025 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1026 return -EINVAL;
1027 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001029 if ((usecase->type == VOICE_CALL) ||
1030 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001031 out_snd_device = platform_get_output_snd_device(adev->platform,
1032 usecase->stream.out->devices);
1033 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001034 usecase->devices = usecase->stream.out->devices;
1035 } else {
1036 /*
1037 * If the voice call is active, use the sound devices of voice call usecase
1038 * so that it would not result any device switch. All the usecases will
1039 * be switched to new device when select_devices() is called for voice call
1040 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001041 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001042 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001043 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001044 vc_usecase = get_usecase_from_list(adev,
1045 get_voice_usecase_id_from_list(adev));
1046 if ((vc_usecase != NULL) &&
1047 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1048 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049 in_snd_device = vc_usecase->in_snd_device;
1050 out_snd_device = vc_usecase->out_snd_device;
1051 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001052 } else if (audio_extn_hfp_is_active(adev)) {
1053 hfp_ucid = audio_extn_hfp_get_usecase();
1054 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1055 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1056 in_snd_device = hfp_usecase->in_snd_device;
1057 out_snd_device = hfp_usecase->out_snd_device;
1058 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001059 }
1060 if (usecase->type == PCM_PLAYBACK) {
1061 usecase->devices = usecase->stream.out->devices;
1062 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001063 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001064 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001065 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001066 if (usecase->stream.out == adev->primary_output &&
1067 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001068 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1069 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001070 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001071 select_devices(adev, adev->active_input->usecase);
1072 }
1073 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001074 } else if (usecase->type == PCM_CAPTURE) {
1075 usecase->devices = usecase->stream.in->device;
1076 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001077 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001078 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001079 if (adev->active_input &&
1080 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1081 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001082 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001083 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1084 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1085 } else if (adev->primary_output) {
1086 out_device = adev->primary_output->devices;
1087 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001088 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001089 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001090 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001091 }
1092 }
1093
1094 if (out_snd_device == usecase->out_snd_device &&
1095 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001096 return 0;
1097 }
1098
Eric Laurent2bafff12016-03-17 12:17:23 -07001099 if (out_snd_device != SND_DEVICE_NONE &&
1100 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1101 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1102 __func__,
1103 use_case_table[uc_id],
1104 adev->last_logged_snd_device[uc_id][0],
1105 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1106 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1107 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1108 -1,
1109 out_snd_device,
1110 platform_get_snd_device_name(out_snd_device),
1111 platform_get_snd_device_acdb_id(out_snd_device));
1112 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1113 }
1114 if (in_snd_device != SND_DEVICE_NONE &&
1115 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1116 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1117 __func__,
1118 use_case_table[uc_id],
1119 adev->last_logged_snd_device[uc_id][1],
1120 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1121 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1122 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1123 -1,
1124 in_snd_device,
1125 platform_get_snd_device_name(in_snd_device),
1126 platform_get_snd_device_acdb_id(in_snd_device));
1127 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1128 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001130 /*
1131 * Limitation: While in call, to do a device switch we need to disable
1132 * and enable both RX and TX devices though one of them is same as current
1133 * device.
1134 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001135 if ((usecase->type == VOICE_CALL) &&
1136 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1137 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001138 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001139 /* Disable sidetone only if voice call already exists */
1140 if (voice_is_call_state_active(adev))
1141 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001142 }
1143
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001144 /* Disable current sound devices */
1145 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001146 disable_audio_route(adev, usecase);
1147 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001148 }
1149
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001150 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001151 disable_audio_route(adev, usecase);
1152 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001153 }
1154
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001155 /* Applicable only on the targets that has external modem.
1156 * New device information should be sent to modem before enabling
1157 * the devices to reduce in-call device switch time.
1158 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001159 if ((usecase->type == VOICE_CALL) &&
1160 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1161 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001162 status = platform_switch_voice_call_enable_device_config(adev->platform,
1163 out_snd_device,
1164 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001165 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001166
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001167 /* Enable new sound devices */
1168 if (out_snd_device != SND_DEVICE_NONE) {
1169 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001170 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001171 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001172 }
1173
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001174 if (in_snd_device != SND_DEVICE_NONE) {
1175 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001176 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001177 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001178
Eric Laurentb23d5282013-05-14 15:27:20 -07001179 if (usecase->type == VOICE_CALL)
1180 status = platform_switch_voice_call_device_post(adev->platform,
1181 out_snd_device,
1182 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001183
sangwoo170731f2013-06-08 15:36:36 +09001184 usecase->in_snd_device = in_snd_device;
1185 usecase->out_snd_device = out_snd_device;
1186
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001187 audio_extn_tfa_98xx_set_mode();
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
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001246 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1247 return -EIO;
1248
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001249 if (in->card_status == CARD_STATUS_OFFLINE ||
1250 adev->card_status == CARD_STATUS_OFFLINE) {
1251 ALOGW("in->card_status or adev->card_status offline, try again");
1252 ret = -EAGAIN;
1253 goto error_config;
1254 }
1255
Eric Laurentb23d5282013-05-14 15:27:20 -07001256 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001257 if (in->pcm_device_id < 0) {
1258 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1259 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001260 ret = -EINVAL;
1261 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001262 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001263
1264 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001265 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1266 uc_info->id = in->usecase;
1267 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001268 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001269 uc_info->devices = in->device;
1270 uc_info->in_snd_device = SND_DEVICE_NONE;
1271 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001273 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001274
1275 audio_extn_perf_lock_acquire();
1276
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001277 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278
Eric Laurentc8400632013-02-14 19:04:54 -08001279 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001280 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001281
Andy Hung6ebe5962016-01-15 17:46:57 -08001282 unsigned int flags = PCM_IN | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001283 unsigned int pcm_open_retry_count = 0;
1284
1285 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1286 flags |= PCM_MMAP | PCM_NOIRQ;
1287 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001288 } else if (in->realtime) {
1289 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001290 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001291
1292 while (1) {
1293 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1294 flags, &in->config);
1295 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1296 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1297 if (in->pcm != NULL) {
1298 pcm_close(in->pcm);
1299 in->pcm = NULL;
1300 }
1301 if (pcm_open_retry_count-- == 0) {
1302 ret = -EIO;
1303 goto error_open;
1304 }
1305 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1306 continue;
1307 }
1308 break;
1309 }
1310
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001311 ALOGV("%s: pcm_prepare", __func__);
1312 ret = pcm_prepare(in->pcm);
1313 if (ret < 0) {
1314 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1315 pcm_close(in->pcm);
1316 in->pcm = NULL;
1317 goto error_open;
1318 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001319 if (in->realtime) {
1320 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001321 if (ret < 0) {
1322 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1323 pcm_close(in->pcm);
1324 in->pcm = NULL;
1325 goto error_open;
1326 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001327 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001328 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001329 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001330 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001331
Eric Laurentc8400632013-02-14 19:04:54 -08001332 return ret;
1333
1334error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001335 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001336 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001337
1338error_config:
1339 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001340 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001341
1342 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001343}
1344
Eric Laurenta1478072015-09-21 17:21:52 -07001345void lock_input_stream(struct stream_in *in)
1346{
1347 pthread_mutex_lock(&in->pre_lock);
1348 pthread_mutex_lock(&in->lock);
1349 pthread_mutex_unlock(&in->pre_lock);
1350}
1351
1352void lock_output_stream(struct stream_out *out)
1353{
1354 pthread_mutex_lock(&out->pre_lock);
1355 pthread_mutex_lock(&out->lock);
1356 pthread_mutex_unlock(&out->pre_lock);
1357}
1358
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001359/* must be called with out->lock locked */
1360static int send_offload_cmd_l(struct stream_out* out, int command)
1361{
1362 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1363
1364 ALOGVV("%s %d", __func__, command);
1365
1366 cmd->cmd = command;
1367 list_add_tail(&out->offload_cmd_list, &cmd->node);
1368 pthread_cond_signal(&out->offload_cond);
1369 return 0;
1370}
1371
1372/* must be called iwth out->lock locked */
1373static void stop_compressed_output_l(struct stream_out *out)
1374{
1375 out->offload_state = OFFLOAD_STATE_IDLE;
1376 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001377 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001378 if (out->compr != NULL) {
1379 compress_stop(out->compr);
1380 while (out->offload_thread_blocked) {
1381 pthread_cond_wait(&out->cond, &out->lock);
1382 }
1383 }
1384}
1385
1386static void *offload_thread_loop(void *context)
1387{
1388 struct stream_out *out = (struct stream_out *) context;
1389 struct listnode *item;
1390
1391 out->offload_state = OFFLOAD_STATE_IDLE;
1392 out->playback_started = 0;
1393
1394 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1395 set_sched_policy(0, SP_FOREGROUND);
1396 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1397
1398 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001399 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001400 for (;;) {
1401 struct offload_cmd *cmd = NULL;
1402 stream_callback_event_t event;
1403 bool send_callback = false;
1404
1405 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1406 __func__, list_empty(&out->offload_cmd_list),
1407 out->offload_state);
1408 if (list_empty(&out->offload_cmd_list)) {
1409 ALOGV("%s SLEEPING", __func__);
1410 pthread_cond_wait(&out->offload_cond, &out->lock);
1411 ALOGV("%s RUNNING", __func__);
1412 continue;
1413 }
1414
1415 item = list_head(&out->offload_cmd_list);
1416 cmd = node_to_item(item, struct offload_cmd, node);
1417 list_remove(item);
1418
1419 ALOGVV("%s STATE %d CMD %d out->compr %p",
1420 __func__, out->offload_state, cmd->cmd, out->compr);
1421
1422 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1423 free(cmd);
1424 break;
1425 }
1426
1427 if (out->compr == NULL) {
1428 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001429 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001430 pthread_cond_signal(&out->cond);
1431 continue;
1432 }
1433 out->offload_thread_blocked = true;
1434 pthread_mutex_unlock(&out->lock);
1435 send_callback = false;
1436 switch(cmd->cmd) {
1437 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1438 compress_wait(out->compr, -1);
1439 send_callback = true;
1440 event = STREAM_CBK_EVENT_WRITE_READY;
1441 break;
1442 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001443 compress_next_track(out->compr);
1444 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001445 send_callback = true;
1446 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001447 /* Resend the metadata for next iteration */
1448 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001449 break;
1450 case OFFLOAD_CMD_DRAIN:
1451 compress_drain(out->compr);
1452 send_callback = true;
1453 event = STREAM_CBK_EVENT_DRAIN_READY;
1454 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001455 case OFFLOAD_CMD_ERROR:
1456 send_callback = true;
1457 event = STREAM_CBK_EVENT_ERROR;
1458 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001459 default:
1460 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1461 break;
1462 }
Eric Laurenta1478072015-09-21 17:21:52 -07001463 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001464 out->offload_thread_blocked = false;
1465 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001466 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001467 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001468 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001469 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001470 free(cmd);
1471 }
1472
1473 pthread_cond_signal(&out->cond);
1474 while (!list_empty(&out->offload_cmd_list)) {
1475 item = list_head(&out->offload_cmd_list);
1476 list_remove(item);
1477 free(node_to_item(item, struct offload_cmd, node));
1478 }
1479 pthread_mutex_unlock(&out->lock);
1480
1481 return NULL;
1482}
1483
1484static int create_offload_callback_thread(struct stream_out *out)
1485{
1486 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1487 list_init(&out->offload_cmd_list);
1488 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1489 offload_thread_loop, out);
1490 return 0;
1491}
1492
1493static int destroy_offload_callback_thread(struct stream_out *out)
1494{
Eric Laurenta1478072015-09-21 17:21:52 -07001495 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001496 stop_compressed_output_l(out);
1497 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1498
1499 pthread_mutex_unlock(&out->lock);
1500 pthread_join(out->offload_thread, (void **) NULL);
1501 pthread_cond_destroy(&out->offload_cond);
1502
1503 return 0;
1504}
1505
Eric Laurent07eeafd2013-10-06 12:52:49 -07001506static bool allow_hdmi_channel_config(struct audio_device *adev)
1507{
1508 struct listnode *node;
1509 struct audio_usecase *usecase;
1510 bool ret = true;
1511
1512 list_for_each(node, &adev->usecase_list) {
1513 usecase = node_to_item(node, struct audio_usecase, list);
1514 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1515 /*
1516 * If voice call is already existing, do not proceed further to avoid
1517 * disabling/enabling both RX and TX devices, CSD calls, etc.
1518 * Once the voice call done, the HDMI channels can be configured to
1519 * max channels of remaining use cases.
1520 */
1521 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001522 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001523 __func__);
1524 ret = false;
1525 break;
1526 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001527 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001528 "no change in HDMI channels", __func__);
1529 ret = false;
1530 break;
1531 }
1532 }
1533 }
1534 return ret;
1535}
1536
1537static int check_and_set_hdmi_channels(struct audio_device *adev,
1538 unsigned int channels)
1539{
1540 struct listnode *node;
1541 struct audio_usecase *usecase;
1542
1543 /* Check if change in HDMI channel config is allowed */
1544 if (!allow_hdmi_channel_config(adev))
1545 return 0;
1546
1547 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001548 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001549 return 0;
1550 }
1551
1552 platform_set_hdmi_channels(adev->platform, channels);
1553 adev->cur_hdmi_channels = channels;
1554
1555 /*
1556 * Deroute all the playback streams routed to HDMI so that
1557 * the back end is deactivated. Note that backend will not
1558 * be deactivated if any one stream is connected to it.
1559 */
1560 list_for_each(node, &adev->usecase_list) {
1561 usecase = node_to_item(node, struct audio_usecase, list);
1562 if (usecase->type == PCM_PLAYBACK &&
1563 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001564 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001565 }
1566 }
1567
1568 /*
1569 * Enable all the streams disabled above. Now the HDMI backend
1570 * will be activated with new channel configuration
1571 */
1572 list_for_each(node, &adev->usecase_list) {
1573 usecase = node_to_item(node, struct audio_usecase, list);
1574 if (usecase->type == PCM_PLAYBACK &&
1575 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001576 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001577 }
1578 }
1579
1580 return 0;
1581}
1582
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583static int stop_output_stream(struct stream_out *out)
1584{
1585 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586 struct audio_usecase *uc_info;
1587 struct audio_device *adev = out->dev;
1588
Eric Laurent994a6932013-07-17 11:51:42 -07001589 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001590 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001591 uc_info = get_usecase_from_list(adev, out->usecase);
1592 if (uc_info == NULL) {
1593 ALOGE("%s: Could not find the usecase (%d) in the list",
1594 __func__, out->usecase);
1595 return -EINVAL;
1596 }
1597
Haynes Mathew George41f86652014-06-17 14:22:15 -07001598 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1599 if (adev->visualizer_stop_output != NULL)
1600 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1601 if (adev->offload_effects_stop_output != NULL)
1602 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1603 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001604
Eric Laurent150dbfe2013-02-27 14:31:02 -08001605 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001606 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001607
1608 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001609 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001610
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001611 list_remove(&uc_info->list);
1612 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001613
Eric Laurent0499d4f2014-08-25 22:39:29 -05001614 audio_extn_extspk_update(adev->extspk);
1615
Eric Laurent07eeafd2013-10-06 12:52:49 -07001616 /* Must be called after removing the usecase from list */
1617 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1618 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1619
Eric Laurent994a6932013-07-17 11:51:42 -07001620 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621 return ret;
1622}
1623
1624int start_output_stream(struct stream_out *out)
1625{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001627 struct audio_usecase *uc_info;
1628 struct audio_device *adev = out->dev;
1629
Eric Laurent994a6932013-07-17 11:51:42 -07001630 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001631 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001632
1633 if (out->card_status == CARD_STATUS_OFFLINE ||
1634 adev->card_status == CARD_STATUS_OFFLINE) {
1635 ALOGW("out->card_status or adev->card_status offline, try again");
1636 ret = -EAGAIN;
1637 goto error_config;
1638 }
1639
Eric Laurentb23d5282013-05-14 15:27:20 -07001640 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001641 if (out->pcm_device_id < 0) {
1642 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1643 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001644 ret = -EINVAL;
1645 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646 }
1647
1648 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1649 uc_info->id = out->usecase;
1650 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001651 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001652 uc_info->devices = out->devices;
1653 uc_info->in_snd_device = SND_DEVICE_NONE;
1654 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655
Eric Laurent07eeafd2013-10-06 12:52:49 -07001656 /* This must be called before adding this usecase to the list */
1657 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1658 check_and_set_hdmi_channels(adev, out->config.channels);
1659
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001660 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001662 audio_extn_perf_lock_acquire();
1663
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001664 select_devices(adev, out->usecase);
1665
Eric Laurent0499d4f2014-08-25 22:39:29 -05001666 audio_extn_extspk_update(adev->extspk);
1667
Andy Hung31aca912014-03-20 17:14:59 -07001668 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001669 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001670 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001671 unsigned int flags = PCM_OUT;
1672 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001673
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001674 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1675 flags |= PCM_MMAP | PCM_NOIRQ;
1676 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001677 } else if (out->realtime) {
1678 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001679 } else
1680 flags |= PCM_MONOTONIC;
1681
1682 while (1) {
1683 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1684 flags, &out->config);
1685 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1686 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1687 if (out->pcm != NULL) {
1688 pcm_close(out->pcm);
1689 out->pcm = NULL;
1690 }
1691 if (pcm_open_retry_count-- == 0) {
1692 ret = -EIO;
1693 goto error_open;
1694 }
1695 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1696 continue;
1697 }
1698 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001699 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001700 ALOGV("%s: pcm_prepare", __func__);
1701 if (pcm_is_ready(out->pcm)) {
1702 ret = pcm_prepare(out->pcm);
1703 if (ret < 0) {
1704 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1705 pcm_close(out->pcm);
1706 out->pcm = NULL;
1707 goto error_open;
1708 }
1709 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001710 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001711 out->pcm = NULL;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001712 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001713 COMPRESS_IN, &out->compr_config);
1714 if (out->compr && !is_compress_ready(out->compr)) {
1715 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1716 compress_close(out->compr);
1717 out->compr = NULL;
1718 ret = -EIO;
1719 goto error_open;
1720 }
1721 if (out->offload_callback)
1722 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001723
1724 if (adev->visualizer_start_output != NULL)
Haynes Mathew George41f86652014-06-17 14:22:15 -07001725 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1726 if (adev->offload_effects_start_output != NULL)
1727 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001728 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001729 ret = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001730 if (out->realtime) {
1731 ret = pcm_start(out->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001732 if (ret < 0) {
1733 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1734 pcm_close(out->pcm);
1735 out->pcm = NULL;
1736 goto error_open;
1737 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001738 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001739 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001740 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001741 audio_extn_tfa_98xx_enable_speaker();
1742
Eric Laurent994a6932013-07-17 11:51:42 -07001743 ALOGV("%s: exit", __func__);
Haynes Mathew George03c40102016-01-29 17:57:48 -08001744 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001745error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001746 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001748error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001749 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001750}
1751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752static int check_input_parameters(uint32_t sample_rate,
1753 audio_format_t format,
1754 int channel_count)
1755{
vivek mehta4ed66e62016-04-15 23:33:34 -07001756 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001757 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1758 return -EINVAL;
1759 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760
vivek mehtadae44712015-07-27 14:13:18 -07001761 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001762 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001763 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1764 return -EINVAL;
1765 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001766
1767 switch (sample_rate) {
1768 case 8000:
1769 case 11025:
1770 case 12000:
1771 case 16000:
1772 case 22050:
1773 case 24000:
1774 case 32000:
1775 case 44100:
1776 case 48000:
1777 break;
1778 default:
vivek mehtadae44712015-07-27 14:13:18 -07001779 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780 return -EINVAL;
1781 }
1782
1783 return 0;
1784}
1785
1786static size_t get_input_buffer_size(uint32_t sample_rate,
1787 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001788 int channel_count,
1789 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790{
1791 size_t size = 0;
1792
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001793 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1794 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001796 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001797 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001798 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001799
1800 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801
Glenn Kasten4f993392014-05-14 07:30:48 -07001802 /* make sure the size is multiple of 32 bytes
1803 * At 48 kHz mono 16-bit PCM:
1804 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1805 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1806 */
1807 size += 0x1f;
1808 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001809
1810 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811}
1812
1813static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1814{
1815 struct stream_out *out = (struct stream_out *)stream;
1816
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001817 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818}
1819
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001820static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001821{
1822 return -ENOSYS;
1823}
1824
1825static size_t out_get_buffer_size(const struct audio_stream *stream)
1826{
1827 struct stream_out *out = (struct stream_out *)stream;
1828
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001829 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1830 return out->compr_config.fragment_size;
1831 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001832 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001833 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001834}
1835
1836static uint32_t out_get_channels(const struct audio_stream *stream)
1837{
1838 struct stream_out *out = (struct stream_out *)stream;
1839
1840 return out->channel_mask;
1841}
1842
1843static audio_format_t out_get_format(const struct audio_stream *stream)
1844{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001845 struct stream_out *out = (struct stream_out *)stream;
1846
1847 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001848}
1849
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001850static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851{
1852 return -ENOSYS;
1853}
1854
1855static int out_standby(struct audio_stream *stream)
1856{
1857 struct stream_out *out = (struct stream_out *)stream;
1858 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001859
Eric Laurent994a6932013-07-17 11:51:42 -07001860 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001861 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862
Eric Laurenta1478072015-09-21 17:21:52 -07001863 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001865 if (adev->adm_deregister_stream)
1866 adev->adm_deregister_stream(adev->adm_data, out->handle);
1867
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001868 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001870 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1871 if (out->pcm) {
1872 pcm_close(out->pcm);
1873 out->pcm = NULL;
1874 }
1875 } else {
1876 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001877 out->gapless_mdata.encoder_delay = 0;
1878 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001879 if (out->compr != NULL) {
1880 compress_close(out->compr);
1881 out->compr = NULL;
1882 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001883 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001885 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886 }
1887 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001888 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001889 return 0;
1890}
1891
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001892static int out_on_error(struct audio_stream *stream)
1893{
1894 struct stream_out *out = (struct stream_out *)stream;
1895 struct audio_device *adev = out->dev;
1896 bool do_standby = false;
1897
1898 lock_output_stream(out);
1899 if (!out->standby) {
1900 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1901 stop_compressed_output_l(out);
1902 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1903 } else
1904 do_standby = true;
1905 }
1906 pthread_mutex_unlock(&out->lock);
1907
1908 if (do_standby)
1909 return out_standby(&out->stream.common);
1910
1911 return 0;
1912}
1913
Andy Hung7401c7c2016-09-21 12:41:21 -07001914static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001915{
Andy Hung7401c7c2016-09-21 12:41:21 -07001916 struct stream_out *out = (struct stream_out *)stream;
1917
1918 // We try to get the lock for consistency,
1919 // but it isn't necessary for these variables.
1920 // If we're not in standby, we may be blocked on a write.
1921 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1922 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1923 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1924
1925 if (locked) {
1926 log_dump_l(&out->error_log, fd);
1927 pthread_mutex_unlock(&out->lock);
1928 } else {
1929 // We don't have the lock here, copy for safety.
1930 struct error_log log = out->error_log;
1931 log_dump_l(&log, fd);
1932 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001933 return 0;
1934}
1935
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001936static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1937{
1938 int ret = 0;
1939 char value[32];
1940 struct compr_gapless_mdata tmp_mdata;
1941
1942 if (!out || !parms) {
1943 return -EINVAL;
1944 }
1945
1946 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1947 if (ret >= 0) {
1948 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1949 } else {
1950 return -EINVAL;
1951 }
1952
1953 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1954 if (ret >= 0) {
1955 tmp_mdata.encoder_padding = atoi(value);
1956 } else {
1957 return -EINVAL;
1958 }
1959
1960 out->gapless_mdata = tmp_mdata;
1961 out->send_new_metadata = 1;
1962 ALOGV("%s new encoder delay %u and padding %u", __func__,
1963 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1964
1965 return 0;
1966}
1967
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001968static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1969{
1970 return out == adev->primary_output || out == adev->voice_tx_output;
1971}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1974{
1975 struct stream_out *out = (struct stream_out *)stream;
1976 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001977 struct audio_usecase *usecase;
1978 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979 struct str_parms *parms;
1980 char value[32];
1981 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001982 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001983 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984
Eric Laurent2e140aa2016-06-30 17:14:46 -07001985 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001986 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987 parms = str_parms_create_str(kvpairs);
1988 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1989 if (ret >= 0) {
1990 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001991 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001992 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001994 /*
1995 * When HDMI cable is unplugged the music playback is paused and
1996 * the policy manager sends routing=0. But the audioflinger
1997 * continues to write data until standby time (3sec).
1998 * As the HDMI core is turned off, the write gets blocked.
1999 * Avoid this by routing audio to speaker until standby.
2000 */
2001 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2002 val == AUDIO_DEVICE_NONE) {
2003 val = AUDIO_DEVICE_OUT_SPEAKER;
2004 }
2005
2006 /*
2007 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002008 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002009 * the select_devices(). But how do we undo this?
2010 *
2011 * For example, music playback is active on headset (deep-buffer usecase)
2012 * and if we go to ringtones and select a ringtone, low-latency usecase
2013 * will be started on headset+speaker. As we can't enable headset+speaker
2014 * and headset devices at the same time, select_devices() switches the music
2015 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2016 * So when the ringtone playback is completed, how do we undo the same?
2017 *
2018 * We are relying on the out_set_parameters() call on deep-buffer output,
2019 * once the ringtone playback is ended.
2020 * NOTE: We should not check if the current devices are same as new devices.
2021 * Because select_devices() must be called to switch back the music
2022 * playback to headset.
2023 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002024 audio_devices_t new_dev = val;
2025 if (new_dev != AUDIO_DEVICE_NONE) {
2026 bool same_dev = out->devices == new_dev;
2027 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002028
Eric Laurenta7657192014-10-09 21:09:33 -07002029 if (output_drives_call(adev, out)) {
2030 if (!voice_is_in_call(adev)) {
2031 if (adev->mode == AUDIO_MODE_IN_CALL) {
2032 adev->current_call_output = out;
2033 ret = voice_start_call(adev);
2034 }
2035 } else {
2036 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002037 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002038 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002039 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002040
2041 if (!out->standby) {
2042 if (!same_dev) {
2043 ALOGV("update routing change");
2044 out->routing_change = true;
2045 }
2046 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002047 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002048 }
2049
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002050 }
2051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002053 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002054
2055 /*handles device and call state changes*/
2056 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002058
2059 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2060 parse_compress_metadata(out, parms);
2061 }
2062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002064 ALOGV("%s: exit: code(%d)", __func__, status);
2065 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066}
2067
2068static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2069{
2070 struct stream_out *out = (struct stream_out *)stream;
2071 struct str_parms *query = str_parms_create_str(keys);
2072 char *str;
2073 char value[256];
2074 struct str_parms *reply = str_parms_create();
2075 size_t i, j;
2076 int ret;
2077 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002078 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002079 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2080 if (ret >= 0) {
2081 value[0] = '\0';
2082 i = 0;
2083 while (out->supported_channel_masks[i] != 0) {
2084 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2085 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2086 if (!first) {
2087 strcat(value, "|");
2088 }
2089 strcat(value, out_channels_name_to_enum_table[j].name);
2090 first = false;
2091 break;
2092 }
2093 }
2094 i++;
2095 }
2096 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2097 str = str_parms_to_str(reply);
2098 } else {
2099 str = strdup(keys);
2100 }
2101 str_parms_destroy(query);
2102 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002103 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104 return str;
2105}
2106
2107static uint32_t out_get_latency(const struct audio_stream_out *stream)
2108{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002109 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110 struct stream_out *out = (struct stream_out *)stream;
2111
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002112 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2113 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002114 else if (out->realtime) {
2115 // since the buffer won't be filled up faster than realtime,
2116 // return a smaller number
2117 period_ms = (out->af_period_multiplier * out->config.period_size *
2118 1000) / (out->config.rate);
2119 hw_delay = platform_render_latency(out->usecase)/1000;
2120 return period_ms + hw_delay;
2121 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002122
2123 return (out->config.period_count * out->config.period_size * 1000) /
2124 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125}
2126
2127static int out_set_volume(struct audio_stream_out *stream, float left,
2128 float right)
2129{
Eric Laurenta9024de2013-04-04 09:19:12 -07002130 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002131 int volume[2];
2132
Eric Laurenta9024de2013-04-04 09:19:12 -07002133 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2134 /* only take left channel into account: the API is for stereo anyway */
2135 out->muted = (left == 0.0f);
2136 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002137 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2138 const char *mixer_ctl_name = "Compress Playback Volume";
2139 struct audio_device *adev = out->dev;
2140 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002141 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2142 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002143 /* try with the control based on device id */
2144 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2145 PCM_PLAYBACK);
2146 char ctl_name[128] = {0};
2147 snprintf(ctl_name, sizeof(ctl_name),
2148 "Compress Playback %d Volume", pcm_device_id);
2149 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2150 if (!ctl) {
2151 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2152 return -EINVAL;
2153 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002154 }
2155 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2156 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2157 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2158 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002159 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161 return -ENOSYS;
2162}
2163
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002164// note: this call is safe only if the stream_cb is
2165// removed first in close_output_stream (as is done now).
2166static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2167{
2168 if (!stream || !parms)
2169 return;
2170
2171 struct stream_out *out = (struct stream_out *)stream;
2172 struct audio_device *adev = out->dev;
2173
2174 card_status_t status;
2175 int card;
2176 if (parse_snd_card_status(parms, &card, &status) < 0)
2177 return;
2178
2179 pthread_mutex_lock(&adev->lock);
2180 bool valid_cb = (card == adev->snd_card);
2181 pthread_mutex_unlock(&adev->lock);
2182
2183 if (!valid_cb)
2184 return;
2185
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002186 lock_output_stream(out);
2187 if (out->card_status != status)
2188 out->card_status = status;
2189 pthread_mutex_unlock(&out->lock);
2190
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002191 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2192 use_case_table[out->usecase],
2193 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2194
2195 if (status == CARD_STATUS_OFFLINE)
2196 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002197
2198 return;
2199}
2200
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002201#ifdef NO_AUDIO_OUT
2202static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
2203 const void *buffer, size_t bytes)
2204{
2205 struct stream_out *out = (struct stream_out *)stream;
Prashant Malanidc71a442016-12-27 10:55:44 -08002206 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
Devin Kim3927e172016-12-29 14:03:06 -08002207 int64_t now;
2208 int64_t elapsed_time_since_last_write = 0;
2209 int64_t sleep_time;
2210
Prashant Malanidc71a442016-12-27 10:55:44 -08002211 clock_gettime(CLOCK_MONOTONIC, &t);
Devin Kim3927e172016-12-29 14:03:06 -08002212 now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
2213
Eric Laurenta1478072015-09-21 17:21:52 -07002214 lock_output_stream(out);
Devin Kim3927e172016-12-29 14:03:06 -08002215 if (out->last_write_time_us)
2216 elapsed_time_since_last_write = now - out->last_write_time_us;
2217 sleep_time = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
Prashant Malanidc71a442016-12-27 10:55:44 -08002218 out_get_sample_rate(&stream->common) - elapsed_time_since_last_write;
2219 if (sleep_time > 0) {
2220 usleep(sleep_time);
2221 } else {
2222 // we don't sleep when we exit standby (this is typical for a real alsa buffer).
2223 sleep_time = 0;
2224 }
2225 out->last_write_time_us = now + sleep_time;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002226 pthread_mutex_unlock(&out->lock);
Prashant Malanidc71a442016-12-27 10:55:44 -08002227 // last_write_time_us is an approximation of when the (simulated) alsa
2228 // buffer is believed completely full. The usleep above waits for more space
2229 // in the buffer, but by the end of the sleep the buffer is considered
2230 // topped-off.
2231 //
2232 // On the subsequent out_write(), we measure the elapsed time spent in
2233 // the mixer. This is subtracted from the sleep estimate based on frames,
2234 // thereby accounting for drain in the alsa buffer during mixing.
2235 // This is a crude approximation; we don't handle underruns precisely.
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002236 return bytes;
2237}
2238#endif
2239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2241 size_t bytes)
2242{
2243 struct stream_out *out = (struct stream_out *)stream;
2244 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002245 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002246 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247
Eric Laurenta1478072015-09-21 17:21:52 -07002248 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002250 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002251 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002252 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002253 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002254 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002256 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257 goto exit;
2258 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002259
2260 if (last_known_cal_step != -1) {
2261 ALOGD("%s: retry previous failed cal level set", __func__);
2262 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2263 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002264 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002265
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002266 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002267 ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
2268 if (out->send_new_metadata) {
2269 ALOGVV("send new gapless metadata");
2270 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2271 out->send_new_metadata = 0;
2272 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002273 unsigned int avail;
2274 struct timespec tstamp;
2275 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2276 /* Do not limit write size if the available frames count is unknown */
2277 if (ret != 0) {
2278 avail = bytes;
2279 }
2280 if (avail == 0) {
2281 ret = 0;
2282 } else {
2283 if (avail > bytes) {
2284 avail = bytes;
2285 }
2286 ret = compress_write(out->compr, buffer, avail);
2287 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2288 __func__, avail, ret);
2289 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002290
Eric Laurent6e895242013-09-05 16:10:57 -07002291 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002292 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2293 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002294 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002295 compress_start(out->compr);
2296 out->playback_started = 1;
2297 out->offload_state = OFFLOAD_STATE_PLAYING;
2298 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002299 if (ret < 0) {
2300 log_error_l(&out->error_log, ERROR_CODE_WRITE);
2301 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002302 pthread_mutex_unlock(&out->lock);
2303 return ret;
2304 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002305 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002306 if (out->pcm) {
2307 if (out->muted)
2308 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002309
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002310 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002311
Haynes Mathew George03c40102016-01-29 17:57:48 -08002312 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2313 out->config.rate;
2314 request_out_focus(out, ns);
2315
2316 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2317 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002318 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002319 else
2320 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002321
Haynes Mathew George03c40102016-01-29 17:57:48 -08002322 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002323 } else {
2324 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002325 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002326 }
2327
2328exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002329 // For PCM we always consume the buffer and return #bytes regardless of ret.
2330 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2331 out->written += bytes / (out->config.channels * sizeof(short));
2332 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002333 long long sleeptime_us = 0;
2334 if (ret != 0) {
2335 log_error_l(&out->error_log, error_code);
2336 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2337 ALOGE_IF(out->pcm != NULL,
2338 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
2339 sleeptime_us = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2340 out_get_sample_rate(&out->stream.common);
2341 // usleep not guaranteed for values over 1 second but we don't limit here.
2342 }
2343 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002344
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002345 pthread_mutex_unlock(&out->lock);
2346
2347 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002348 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002349 if (sleeptime_us != 0)
2350 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351 }
2352 return bytes;
2353}
2354
2355static int out_get_render_position(const struct audio_stream_out *stream,
2356 uint32_t *dsp_frames)
2357{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002358 struct stream_out *out = (struct stream_out *)stream;
2359 *dsp_frames = 0;
2360 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002361 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002362 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002363 unsigned long frames = 0;
2364 // TODO: check return value
2365 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2366 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002367 ALOGVV("%s rendered frames %d sample_rate %d",
2368 __func__, *dsp_frames, out->sample_rate);
2369 }
2370 pthread_mutex_unlock(&out->lock);
2371 return 0;
2372 } else
2373 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374}
2375
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002376static int out_add_audio_effect(const struct audio_stream *stream __unused,
2377 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002378{
2379 return 0;
2380}
2381
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002382static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2383 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002384{
2385 return 0;
2386}
2387
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002388static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2389 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002390{
2391 return -EINVAL;
2392}
2393
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002394static int out_get_presentation_position(const struct audio_stream_out *stream,
2395 uint64_t *frames, struct timespec *timestamp)
2396{
2397 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002398 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002399 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002400
Eric Laurenta1478072015-09-21 17:21:52 -07002401 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002402
Eric Laurent949a0892013-09-20 09:20:13 -07002403 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2404 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002405 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002406 compress_get_tstamp(out->compr, &dsp_frames,
2407 &out->sample_rate);
2408 ALOGVV("%s rendered frames %ld sample_rate %d",
2409 __func__, dsp_frames, out->sample_rate);
2410 *frames = dsp_frames;
2411 ret = 0;
2412 /* this is the best we can do */
2413 clock_gettime(CLOCK_MONOTONIC, timestamp);
2414 }
2415 } else {
2416 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002417 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002418 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2419 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002420 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002421 // This adjustment accounts for buffering after app processor.
2422 // It is based on estimated DSP latency per use case, rather than exact.
2423 signed_frames -=
2424 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2425
Eric Laurent949a0892013-09-20 09:20:13 -07002426 // It would be unusual for this value to be negative, but check just in case ...
2427 if (signed_frames >= 0) {
2428 *frames = signed_frames;
2429 ret = 0;
2430 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002431 }
2432 }
2433 }
2434
2435 pthread_mutex_unlock(&out->lock);
2436
2437 return ret;
2438}
2439
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002440static int out_set_callback(struct audio_stream_out *stream,
2441 stream_callback_t callback, void *cookie)
2442{
2443 struct stream_out *out = (struct stream_out *)stream;
2444
2445 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002446 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002447 out->offload_callback = callback;
2448 out->offload_cookie = cookie;
2449 pthread_mutex_unlock(&out->lock);
2450 return 0;
2451}
2452
2453static int out_pause(struct audio_stream_out* stream)
2454{
2455 struct stream_out *out = (struct stream_out *)stream;
2456 int status = -ENOSYS;
2457 ALOGV("%s", __func__);
2458 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002459 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002460 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2461 status = compress_pause(out->compr);
2462 out->offload_state = OFFLOAD_STATE_PAUSED;
2463 }
2464 pthread_mutex_unlock(&out->lock);
2465 }
2466 return status;
2467}
2468
2469static int out_resume(struct audio_stream_out* stream)
2470{
2471 struct stream_out *out = (struct stream_out *)stream;
2472 int status = -ENOSYS;
2473 ALOGV("%s", __func__);
2474 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2475 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002476 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002477 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2478 status = compress_resume(out->compr);
2479 out->offload_state = OFFLOAD_STATE_PLAYING;
2480 }
2481 pthread_mutex_unlock(&out->lock);
2482 }
2483 return status;
2484}
2485
2486static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2487{
2488 struct stream_out *out = (struct stream_out *)stream;
2489 int status = -ENOSYS;
2490 ALOGV("%s", __func__);
2491 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002492 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002493 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2494 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2495 else
2496 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2497 pthread_mutex_unlock(&out->lock);
2498 }
2499 return status;
2500}
2501
2502static int out_flush(struct audio_stream_out* stream)
2503{
2504 struct stream_out *out = (struct stream_out *)stream;
2505 ALOGV("%s", __func__);
2506 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002507 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002508 stop_compressed_output_l(out);
2509 pthread_mutex_unlock(&out->lock);
2510 return 0;
2511 }
2512 return -ENOSYS;
2513}
2514
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515/** audio_stream_in implementation **/
2516static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2517{
2518 struct stream_in *in = (struct stream_in *)stream;
2519
2520 return in->config.rate;
2521}
2522
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002523static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524{
2525 return -ENOSYS;
2526}
2527
2528static size_t in_get_buffer_size(const struct audio_stream *stream)
2529{
2530 struct stream_in *in = (struct stream_in *)stream;
2531
Haynes Mathew George03c40102016-01-29 17:57:48 -08002532 return in->config.period_size * in->af_period_multiplier *
2533 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534}
2535
2536static uint32_t in_get_channels(const struct audio_stream *stream)
2537{
2538 struct stream_in *in = (struct stream_in *)stream;
2539
2540 return in->channel_mask;
2541}
2542
vivek mehta4ed66e62016-04-15 23:33:34 -07002543static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544{
vivek mehta4ed66e62016-04-15 23:33:34 -07002545 struct stream_in *in = (struct stream_in *)stream;
2546 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547}
2548
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002549static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550{
2551 return -ENOSYS;
2552}
2553
2554static int in_standby(struct audio_stream *stream)
2555{
2556 struct stream_in *in = (struct stream_in *)stream;
2557 struct audio_device *adev = in->dev;
2558 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07002559 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002560
2561 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002562
2563 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002564 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002565 audio_extn_sound_trigger_stop_lab(in);
2566 in->standby = true;
2567 }
2568
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002570 if (adev->adm_deregister_stream)
2571 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2572
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002573 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002575 if (in->pcm) {
2576 pcm_close(in->pcm);
2577 in->pcm = NULL;
2578 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002579 adev->enable_voicerx = false;
2580 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002582 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 }
2584 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002585 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586 return status;
2587}
2588
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002589static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590{
2591 return 0;
2592}
2593
2594static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2595{
2596 struct stream_in *in = (struct stream_in *)stream;
2597 struct audio_device *adev = in->dev;
2598 struct str_parms *parms;
2599 char *str;
2600 char value[32];
2601 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002602 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603
Eric Laurent994a6932013-07-17 11:51:42 -07002604 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002605 parms = str_parms_create_str(kvpairs);
2606
2607 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2608
Eric Laurenta1478072015-09-21 17:21:52 -07002609 lock_input_stream(in);
2610
Eric Laurent150dbfe2013-02-27 14:31:02 -08002611 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612 if (ret >= 0) {
2613 val = atoi(value);
2614 /* no audio source uses val == 0 */
2615 if ((in->source != val) && (val != 0)) {
2616 in->source = val;
2617 }
2618 }
2619
2620 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002621
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622 if (ret >= 0) {
2623 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002624 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002625 in->device = val;
2626 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002627 if (!in->standby) {
2628 ALOGV("update input routing change");
2629 in->routing_change = true;
2630 select_devices(adev, in->usecase);
2631 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632 }
2633 }
2634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002636 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002637
2638 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002639 ALOGV("%s: exit: status(%d)", __func__, status);
2640 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641}
2642
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002643static char* in_get_parameters(const struct audio_stream *stream __unused,
2644 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645{
2646 return strdup("");
2647}
2648
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002649static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650{
2651 return 0;
2652}
2653
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002654static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2655{
2656 if (!stream || !parms)
2657 return;
2658
2659 struct stream_in *in = (struct stream_in *)stream;
2660 struct audio_device *adev = in->dev;
2661
2662 card_status_t status;
2663 int card;
2664 if (parse_snd_card_status(parms, &card, &status) < 0)
2665 return;
2666
2667 pthread_mutex_lock(&adev->lock);
2668 bool valid_cb = (card == adev->snd_card);
2669 pthread_mutex_unlock(&adev->lock);
2670
2671 if (!valid_cb)
2672 return;
2673
2674 lock_input_stream(in);
2675 if (in->card_status != status)
2676 in->card_status = status;
2677 pthread_mutex_unlock(&in->lock);
2678
2679 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2680 use_case_table[in->usecase],
2681 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2682
2683 // a better solution would be to report error back to AF and let
2684 // it put the stream to standby
2685 if (status == CARD_STATUS_OFFLINE)
2686 in_standby(&in->stream.common);
2687
2688 return;
2689}
2690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2692 size_t bytes)
2693{
2694 struct stream_in *in = (struct stream_in *)stream;
2695 struct audio_device *adev = in->dev;
2696 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002697 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698
Eric Laurenta1478072015-09-21 17:21:52 -07002699 lock_input_stream(in);
2700
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002701 if (in->is_st_session) {
2702 ALOGVV(" %s: reading on st session bytes=%d", __func__, bytes);
2703 /* Read from sound trigger HAL */
2704 audio_extn_sound_trigger_read(in, buffer, bytes);
2705 pthread_mutex_unlock(&in->lock);
2706 return bytes;
2707 }
2708
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002710 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002712 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002714 goto exit;
2715 }
2716 in->standby = 0;
2717 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718
Haynes Mathew George03c40102016-01-29 17:57:48 -08002719 //what's the duration requested by the client?
2720 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2721 in->config.rate;
2722 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002723
Haynes Mathew George03c40102016-01-29 17:57:48 -08002724 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002726 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002727 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002728 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002729 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002730 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002731 if (ret < 0) {
2732 ALOGE("Failed to read w/err %s", strerror(errno));
2733 ret = -errno;
2734 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002735 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2736 if (bytes % 4 == 0) {
2737 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2738 int_buf_stream = buffer;
2739 for (size_t itt=0; itt < bytes/4 ; itt++) {
2740 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002741 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002742 } else {
2743 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2744 ret = -EINVAL;
2745 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002746 }
2747 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 }
2749
Haynes Mathew George03c40102016-01-29 17:57:48 -08002750 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002752 /*
2753 * Instead of writing zeroes here, we could trust the hardware
2754 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002755 * 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 -08002756 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002757 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758 memset(buffer, 0, bytes);
2759
2760exit:
2761 pthread_mutex_unlock(&in->lock);
2762
2763 if (ret != 0) {
2764 in_standby(&in->stream.common);
2765 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002766 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002768 memset(buffer, 0, bytes); // clear return data
2769 }
2770 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002771 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772 }
2773 return bytes;
2774}
2775
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002776static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002777{
2778 return 0;
2779}
2780
Andy Hung6ebe5962016-01-15 17:46:57 -08002781static int in_get_capture_position(const struct audio_stream_in *stream,
2782 int64_t *frames, int64_t *time)
2783{
2784 if (stream == NULL || frames == NULL || time == NULL) {
2785 return -EINVAL;
2786 }
2787 struct stream_in *in = (struct stream_in *)stream;
2788 int ret = -ENOSYS;
2789
2790 lock_input_stream(in);
2791 if (in->pcm) {
2792 struct timespec timestamp;
2793 unsigned int avail;
2794 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2795 *frames = in->frames_read + avail;
2796 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2797 ret = 0;
2798 }
2799 }
2800 pthread_mutex_unlock(&in->lock);
2801 return ret;
2802}
2803
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002804static int add_remove_audio_effect(const struct audio_stream *stream,
2805 effect_handle_t effect,
2806 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002807{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002808 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002809 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002810 int status = 0;
2811 effect_descriptor_t desc;
2812
2813 status = (*effect)->get_descriptor(effect, &desc);
2814 if (status != 0)
2815 return status;
2816
Eric Laurenta1478072015-09-21 17:21:52 -07002817 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002818 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002819 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002820 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002821 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002822 in->enable_aec != enable &&
2823 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2824 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002825 if (!enable)
2826 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002827 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2828 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2829 adev->enable_voicerx = enable;
2830 struct audio_usecase *usecase;
2831 struct listnode *node;
2832 list_for_each(node, &adev->usecase_list) {
2833 usecase = node_to_item(node, struct audio_usecase, list);
2834 if (usecase->type == PCM_PLAYBACK) {
2835 select_devices(adev, usecase->id);
2836 break;
2837 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002838 }
2839 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002840 if (!in->standby)
2841 select_devices(in->dev, in->usecase);
2842 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07002843 if (in->enable_ns != enable &&
2844 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2845 in->enable_ns = enable;
2846 if (!in->standby)
2847 select_devices(in->dev, in->usecase);
2848 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002849 pthread_mutex_unlock(&in->dev->lock);
2850 pthread_mutex_unlock(&in->lock);
2851
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002852 return 0;
2853}
2854
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002855static int in_add_audio_effect(const struct audio_stream *stream,
2856 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857{
Eric Laurent994a6932013-07-17 11:51:42 -07002858 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002859 return add_remove_audio_effect(stream, effect, true);
2860}
2861
2862static int in_remove_audio_effect(const struct audio_stream *stream,
2863 effect_handle_t effect)
2864{
Eric Laurent994a6932013-07-17 11:51:42 -07002865 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002866 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002867}
2868
2869static int adev_open_output_stream(struct audio_hw_device *dev,
2870 audio_io_handle_t handle,
2871 audio_devices_t devices,
2872 audio_output_flags_t flags,
2873 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07002874 struct audio_stream_out **stream_out,
2875 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002876{
2877 struct audio_device *adev = (struct audio_device *)dev;
2878 struct stream_out *out;
2879 int i, ret;
2880
Eric Laurent994a6932013-07-17 11:51:42 -07002881 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882 __func__, config->sample_rate, config->channel_mask, devices, flags);
2883 *stream_out = NULL;
2884 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2885
2886 if (devices == AUDIO_DEVICE_NONE)
2887 devices = AUDIO_DEVICE_OUT_SPEAKER;
2888
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002889 out->flags = flags;
2890 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002891 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892 out->format = config->format;
2893 out->sample_rate = config->sample_rate;
2894 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2895 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002896 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897
2898 /* Init use case and pcm_config */
2899 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07002900 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002901 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002902 pthread_mutex_lock(&adev->lock);
2903 ret = read_hdmi_channel_masks(out);
2904 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002905 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002906 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002907
2908 if (config->sample_rate == 0)
2909 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2910 if (config->channel_mask == 0)
2911 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08002912 if (config->format == AUDIO_FORMAT_DEFAULT)
2913 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002914
2915 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002916 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08002917 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002918 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2919 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002920 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002921 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002923 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07002924 pthread_mutex_lock(&adev->lock);
2925 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
2926 pthread_mutex_unlock(&adev->lock);
2927
2928 // reject offload during card offline to allow
2929 // fallback to s/w paths
2930 if (offline) {
2931 ret = -ENODEV;
2932 goto error_open;
2933 }
2934
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002935 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2936 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2937 ALOGE("%s: Unsupported Offload information", __func__);
2938 ret = -EINVAL;
2939 goto error_open;
2940 }
2941 if (!is_supported_format(config->offload_info.format)) {
2942 ALOGE("%s: Unsupported audio format", __func__);
2943 ret = -EINVAL;
2944 goto error_open;
2945 }
2946
2947 out->compr_config.codec = (struct snd_codec *)
2948 calloc(1, sizeof(struct snd_codec));
2949
2950 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
2951 if (config->offload_info.channel_mask)
2952 out->channel_mask = config->offload_info.channel_mask;
2953 else if (config->channel_mask)
2954 out->channel_mask = config->channel_mask;
2955 out->format = config->offload_info.format;
2956 out->sample_rate = config->offload_info.sample_rate;
2957
2958 out->stream.set_callback = out_set_callback;
2959 out->stream.pause = out_pause;
2960 out->stream.resume = out_resume;
2961 out->stream.drain = out_drain;
2962 out->stream.flush = out_flush;
2963
2964 out->compr_config.codec->id =
2965 get_snd_codec_id(config->offload_info.format);
2966 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
2967 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07002968 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002969 out->compr_config.codec->bit_rate =
2970 config->offload_info.bit_rate;
2971 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002972 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002973 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
2974
2975 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2976 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002977
2978 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002979 create_offload_callback_thread(out);
2980 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2981 __func__, config->offload_info.version,
2982 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002983 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2984 if (config->sample_rate == 0)
2985 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2986 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2987 config->sample_rate != 8000) {
2988 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2989 ret = -EINVAL;
2990 goto error_open;
2991 }
2992 out->sample_rate = config->sample_rate;
2993 out->config.rate = config->sample_rate;
2994 if (config->format == AUDIO_FORMAT_DEFAULT)
2995 config->format = AUDIO_FORMAT_PCM_16_BIT;
2996 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2997 config->format = AUDIO_FORMAT_PCM_16_BIT;
2998 ret = -EINVAL;
2999 goto error_open;
3000 }
3001 out->format = config->format;
3002 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3003 out->config = pcm_config_afe_proxy_playback;
3004 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003006 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3007 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3008 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003009 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3010 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3011 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003012 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3013 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003014 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
3015 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3016 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003017 } else {
3018 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3019 out->config = pcm_config_low_latency;
3020 }
3021 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3022 if (k_enable_extended_precision
3023 && pcm_params_format_test(adev->use_case_table[out->usecase],
3024 pcm_format_from_audio_format(config->format))) {
3025 out->config.format = pcm_format_from_audio_format(config->format);
3026 /* out->format already set to config->format */
3027 } else {
3028 /* deny the externally proposed config format
3029 * and use the one specified in audio_hw layer configuration.
3030 * Note: out->format is returned by out->stream.common.get_format()
3031 * and is used to set config->format in the code several lines below.
3032 */
3033 out->format = audio_format_from_pcm_format(out->config.format);
3034 }
3035 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003036 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003038 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3039 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003041 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003042 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003043 adev->primary_output = out;
3044 else {
3045 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003046 ret = -EEXIST;
3047 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003048 }
3049 }
3050
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051 /* Check if this usecase is already existing */
3052 pthread_mutex_lock(&adev->lock);
3053 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3054 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003056 ret = -EEXIST;
3057 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058 }
3059 pthread_mutex_unlock(&adev->lock);
3060
3061 out->stream.common.get_sample_rate = out_get_sample_rate;
3062 out->stream.common.set_sample_rate = out_set_sample_rate;
3063 out->stream.common.get_buffer_size = out_get_buffer_size;
3064 out->stream.common.get_channels = out_get_channels;
3065 out->stream.common.get_format = out_get_format;
3066 out->stream.common.set_format = out_set_format;
3067 out->stream.common.standby = out_standby;
3068 out->stream.common.dump = out_dump;
3069 out->stream.common.set_parameters = out_set_parameters;
3070 out->stream.common.get_parameters = out_get_parameters;
3071 out->stream.common.add_audio_effect = out_add_audio_effect;
3072 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3073 out->stream.get_latency = out_get_latency;
3074 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003075#ifdef NO_AUDIO_OUT
3076 out->stream.write = out_write_for_no_output;
3077#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003079#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080 out->stream.get_render_position = out_get_render_position;
3081 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003082 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083
Haynes Mathew George03c40102016-01-29 17:57:48 -08003084 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003085 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003086 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003087 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003089 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003090 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003091 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3092
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003093 config->format = out->stream.common.get_format(&out->stream.common);
3094 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3095 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3096
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003097
3098 /*
3099 By locking output stream before registering, we allow the callback
3100 to update stream's state only after stream's initial state is set to
3101 adev state.
3102 */
3103 lock_output_stream(out);
3104 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3105 pthread_mutex_lock(&adev->lock);
3106 out->card_status = adev->card_status;
3107 pthread_mutex_unlock(&adev->lock);
3108 pthread_mutex_unlock(&out->lock);
3109
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003111 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003112 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003113
3114error_open:
3115 free(out);
3116 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003117 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003118 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119}
3120
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003121static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122 struct audio_stream_out *stream)
3123{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003124 struct stream_out *out = (struct stream_out *)stream;
3125 struct audio_device *adev = out->dev;
3126
Eric Laurent994a6932013-07-17 11:51:42 -07003127 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003128
3129 // must deregister from sndmonitor first to prevent races
3130 // between the callback and close_stream
3131 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003133 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3134 destroy_offload_callback_thread(out);
3135
3136 if (out->compr_config.codec != NULL)
3137 free(out->compr_config.codec);
3138 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003139
3140 if (adev->voice_tx_output == out)
3141 adev->voice_tx_output = NULL;
3142
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003143 pthread_cond_destroy(&out->cond);
3144 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003146 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147}
3148
3149static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3150{
3151 struct audio_device *adev = (struct audio_device *)dev;
3152 struct str_parms *parms;
3153 char *str;
3154 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003155 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003156 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003157 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158
Joe Onorato188b6222016-03-01 11:02:27 -08003159 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003160
3161 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162
3163 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003164 status = voice_set_parameters(adev, parms);
3165 if (status != 0) {
3166 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003167 }
3168
3169 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3170 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003171 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3173 adev->bluetooth_nrec = true;
3174 else
3175 adev->bluetooth_nrec = false;
3176 }
3177
3178 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3179 if (ret >= 0) {
3180 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3181 adev->screen_off = false;
3182 else
3183 adev->screen_off = true;
3184 }
3185
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003186 ret = str_parms_get_int(parms, "rotation", &val);
3187 if (ret >= 0) {
3188 bool reverse_speakers = false;
3189 switch(val) {
3190 // FIXME: note that the code below assumes that the speakers are in the correct placement
3191 // relative to the user when the device is rotated 90deg from its default rotation. This
3192 // assumption is device-specific, not platform-specific like this code.
3193 case 270:
3194 reverse_speakers = true;
3195 break;
3196 case 0:
3197 case 90:
3198 case 180:
3199 break;
3200 default:
3201 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003202 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003203 }
Eric Laurent03f09432014-03-25 18:09:11 -07003204 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003205 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003206 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003207 }
3208
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003209 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3210 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003211 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003212 }
3213
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003214 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003215done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003216 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003217 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003218 ALOGV("%s: exit with code(%d)", __func__, status);
3219 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003220}
3221
3222static char* adev_get_parameters(const struct audio_hw_device *dev,
3223 const char *keys)
3224{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003225 struct audio_device *adev = (struct audio_device *)dev;
3226 struct str_parms *reply = str_parms_create();
3227 struct str_parms *query = str_parms_create_str(keys);
3228 char *str;
3229
3230 pthread_mutex_lock(&adev->lock);
3231
3232 voice_get_parameters(adev, query, reply);
3233 str = str_parms_to_str(reply);
3234 str_parms_destroy(query);
3235 str_parms_destroy(reply);
3236
3237 pthread_mutex_unlock(&adev->lock);
3238 ALOGV("%s: exit: returns - %s", __func__, str);
3239 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240}
3241
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003242static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003243{
3244 return 0;
3245}
3246
Haynes Mathew George5191a852013-09-11 14:19:36 -07003247static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3248{
3249 int ret;
3250 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003251
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003252 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3253
Haynes Mathew George5191a852013-09-11 14:19:36 -07003254 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003255 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003256 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003257
Haynes Mathew George5191a852013-09-11 14:19:36 -07003258 return ret;
3259}
3260
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003261static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262{
3263 return -ENOSYS;
3264}
3265
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003266static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3267 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268{
3269 return -ENOSYS;
3270}
3271
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003272static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273{
3274 return -ENOSYS;
3275}
3276
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003277static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278{
3279 return -ENOSYS;
3280}
3281
3282static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3283{
3284 struct audio_device *adev = (struct audio_device *)dev;
3285
3286 pthread_mutex_lock(&adev->lock);
3287 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003288 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003289 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003290 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3291 voice_is_in_call(adev)) {
3292 voice_stop_call(adev);
3293 adev->current_call_output = NULL;
3294 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295 }
3296 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003297
3298 audio_extn_extspk_set_mode(adev->extspk, mode);
3299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 return 0;
3301}
3302
3303static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3304{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003305 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307
Eric Laurent2bafff12016-03-17 12:17:23 -07003308 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003309 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003310 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3311 ret = audio_extn_hfp_set_mic_mute(adev, state);
3312 } else {
3313 ret = voice_set_mic_mute(adev, state);
3314 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003315 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003316 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003317
3318 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319}
3320
3321static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3322{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003323 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324 return 0;
3325}
3326
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003327static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328 const struct audio_config *config)
3329{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003330 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003332 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3333 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334}
3335
3336static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003337 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338 audio_devices_t devices,
3339 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003340 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003341 audio_input_flags_t flags,
3342 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003343 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344{
3345 struct audio_device *adev = (struct audio_device *)dev;
3346 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003347 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003348 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003349 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350
Eric Laurent994a6932013-07-17 11:51:42 -07003351 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352 *stream_in = NULL;
3353 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3354 return -EINVAL;
3355
Zheng Zhang6185d572016-12-01 20:35:17 +08003356 if (audio_extn_tfa_98xx_is_supported() && (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003357 return -EINVAL;
3358
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3360
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003361 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003362 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003363
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003364 in->stream.common.get_sample_rate = in_get_sample_rate;
3365 in->stream.common.set_sample_rate = in_set_sample_rate;
3366 in->stream.common.get_buffer_size = in_get_buffer_size;
3367 in->stream.common.get_channels = in_get_channels;
3368 in->stream.common.get_format = in_get_format;
3369 in->stream.common.set_format = in_set_format;
3370 in->stream.common.standby = in_standby;
3371 in->stream.common.dump = in_dump;
3372 in->stream.common.set_parameters = in_set_parameters;
3373 in->stream.common.get_parameters = in_get_parameters;
3374 in->stream.common.add_audio_effect = in_add_audio_effect;
3375 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3376 in->stream.set_gain = in_set_gain;
3377 in->stream.read = in_read;
3378 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003379 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380
3381 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003382 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003383 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384 in->standby = 1;
3385 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003386 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003387 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388
vivek mehta57ff9b52016-04-28 14:13:08 -07003389 // restrict 24 bit capture for unprocessed source only
3390 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3391 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003392 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003393 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3394 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3395 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3396 bool ret_error = false;
3397 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3398 from HAL is 8_24
3399 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3400 8_24 return error indicating supported format is 8_24
3401 *> In case of any other source requesting 24 bit or float return error
3402 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003403
vivek mehta57ff9b52016-04-28 14:13:08 -07003404 on error flinger will retry with supported format passed
3405 */
3406 if (source != AUDIO_SOURCE_UNPROCESSED) {
3407 config->format = AUDIO_FORMAT_PCM_16_BIT;
3408 ret_error = true;
3409 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3410 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3411 ret_error = true;
3412 }
3413
3414 if (ret_error) {
3415 ret = -EINVAL;
3416 goto err_open;
3417 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003418 }
3419
vivek mehta57ff9b52016-04-28 14:13:08 -07003420 in->format = config->format;
3421
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003423 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3424 if (config->sample_rate == 0)
3425 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3426 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3427 config->sample_rate != 8000) {
3428 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3429 ret = -EINVAL;
3430 goto err_open;
3431 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003432
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003433 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3434 config->format = AUDIO_FORMAT_PCM_16_BIT;
3435 ret = -EINVAL;
3436 goto err_open;
3437 }
3438
3439 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3440 in->config = pcm_config_afe_proxy_record;
3441 } else {
3442 in->usecase = USECASE_AUDIO_RECORD;
3443 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3444 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3445 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003446#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003447 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003448#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003449 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003450 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003451
Haynes Mathew George03c40102016-01-29 17:57:48 -08003452 in->config = in->realtime ? pcm_config_audio_capture_rt :
3453 pcm_config_audio_capture;
3454
vivek mehta4ed66e62016-04-15 23:33:34 -07003455 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3456 in->config.format = PCM_FORMAT_S24_LE;
3457
Haynes Mathew George03c40102016-01-29 17:57:48 -08003458 if (!in->realtime) {
3459 frame_size = audio_stream_in_frame_size(&in->stream);
3460 buffer_size = get_input_buffer_size(config->sample_rate,
3461 config->format,
3462 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003463 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003464 in->config.period_size = buffer_size / frame_size;
3465 } // period size is left untouched for rt mode playback
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003466 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003467
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468 in->config.channels = channel_count;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003469 if (in->realtime) {
3470 in->af_period_multiplier = af_period_multiplier;
3471 } else {
3472 in->config.rate = config->sample_rate;
3473 in->af_period_multiplier = 1;
3474 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003476 /* This stream could be for sound trigger lab,
3477 get sound trigger pcm if present */
3478 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003480 lock_input_stream(in);
3481 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3482 pthread_mutex_lock(&adev->lock);
3483 in->card_status = adev->card_status;
3484 pthread_mutex_unlock(&adev->lock);
3485 pthread_mutex_unlock(&in->lock);
3486
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003487 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003488 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489 return 0;
3490
3491err_open:
3492 free(in);
3493 *stream_in = NULL;
3494 return ret;
3495}
3496
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003497static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498 struct audio_stream_in *stream)
3499{
Eric Laurent994a6932013-07-17 11:51:42 -07003500 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003501
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003502 // must deregister from sndmonitor first to prevent races
3503 // between the callback and close_stream
3504 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505 in_standby(&stream->common);
3506 free(stream);
3507
3508 return;
3509}
3510
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003511static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512{
3513 return 0;
3514}
3515
Andy Hung31aca912014-03-20 17:14:59 -07003516/* verifies input and output devices and their capabilities.
3517 *
3518 * This verification is required when enabling extended bit-depth or
3519 * sampling rates, as not all qcom products support it.
3520 *
3521 * Suitable for calling only on initialization such as adev_open().
3522 * It fills the audio_device use_case_table[] array.
3523 *
3524 * Has a side-effect that it needs to configure audio routing / devices
3525 * in order to power up the devices and read the device parameters.
3526 * It does not acquire any hw device lock. Should restore the devices
3527 * back to "normal state" upon completion.
3528 */
3529static int adev_verify_devices(struct audio_device *adev)
3530{
3531 /* enumeration is a bit difficult because one really wants to pull
3532 * the use_case, device id, etc from the hidden pcm_device_table[].
3533 * In this case there are the following use cases and device ids.
3534 *
3535 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3536 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3537 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3538 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3539 * [USECASE_AUDIO_RECORD] = {0, 0},
3540 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3541 * [USECASE_VOICE_CALL] = {2, 2},
3542 *
3543 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3544 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3545 */
3546
3547 /* should be the usecases enabled in adev_open_input_stream() */
3548 static const int test_in_usecases[] = {
3549 USECASE_AUDIO_RECORD,
3550 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3551 };
3552 /* should be the usecases enabled in adev_open_output_stream()*/
3553 static const int test_out_usecases[] = {
3554 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3555 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3556 };
3557 static const usecase_type_t usecase_type_by_dir[] = {
3558 PCM_PLAYBACK,
3559 PCM_CAPTURE,
3560 };
3561 static const unsigned flags_by_dir[] = {
3562 PCM_OUT,
3563 PCM_IN,
3564 };
3565
3566 size_t i;
3567 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003568 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003569 char info[512]; /* for possible debug info */
3570
3571 for (dir = 0; dir < 2; ++dir) {
3572 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3573 const unsigned flags_dir = flags_by_dir[dir];
3574 const size_t testsize =
3575 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3576 const int *testcases =
3577 dir ? test_in_usecases : test_out_usecases;
3578 const audio_devices_t audio_device =
3579 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3580
3581 for (i = 0; i < testsize; ++i) {
3582 const audio_usecase_t audio_usecase = testcases[i];
3583 int device_id;
3584 snd_device_t snd_device;
3585 struct pcm_params **pparams;
3586 struct stream_out out;
3587 struct stream_in in;
3588 struct audio_usecase uc_info;
3589 int retval;
3590
3591 pparams = &adev->use_case_table[audio_usecase];
3592 pcm_params_free(*pparams); /* can accept null input */
3593 *pparams = NULL;
3594
3595 /* find the device ID for the use case (signed, for error) */
3596 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3597 if (device_id < 0)
3598 continue;
3599
3600 /* prepare structures for device probing */
3601 memset(&uc_info, 0, sizeof(uc_info));
3602 uc_info.id = audio_usecase;
3603 uc_info.type = usecase_type;
3604 if (dir) {
3605 adev->active_input = &in;
3606 memset(&in, 0, sizeof(in));
3607 in.device = audio_device;
3608 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3609 uc_info.stream.in = &in;
3610 } else {
3611 adev->active_input = NULL;
3612 }
3613 memset(&out, 0, sizeof(out));
3614 out.devices = audio_device; /* only field needed in select_devices */
3615 uc_info.stream.out = &out;
3616 uc_info.devices = audio_device;
3617 uc_info.in_snd_device = SND_DEVICE_NONE;
3618 uc_info.out_snd_device = SND_DEVICE_NONE;
3619 list_add_tail(&adev->usecase_list, &uc_info.list);
3620
3621 /* select device - similar to start_(in/out)put_stream() */
3622 retval = select_devices(adev, audio_usecase);
3623 if (retval >= 0) {
3624 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3625#if LOG_NDEBUG == 0
3626 if (*pparams) {
3627 ALOGV("%s: (%s) card %d device %d", __func__,
3628 dir ? "input" : "output", card_id, device_id);
3629 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07003630 } else {
3631 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3632 }
3633#endif
3634 }
3635
3636 /* deselect device - similar to stop_(in/out)put_stream() */
3637 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07003638 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07003639 /* 2. Disable the rx device */
3640 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07003641 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07003642 list_remove(&uc_info.list);
3643 }
3644 }
3645 adev->active_input = NULL; /* restore adev state */
3646 return 0;
3647}
3648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649static int adev_close(hw_device_t *device)
3650{
Andy Hung31aca912014-03-20 17:14:59 -07003651 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003653
3654 if (!adev)
3655 return 0;
3656
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003657 audio_extn_tfa_98xx_deinit();
3658
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003659 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003660 pthread_mutex_lock(&adev_init_lock);
3661
3662 if ((--audio_device_ref_count) == 0) {
3663 audio_route_free(adev->audio_route);
3664 free(adev->snd_dev_ref_cnt);
3665 platform_deinit(adev->platform);
3666 audio_extn_extspk_deinit(adev->extspk);
3667 audio_extn_sound_trigger_deinit(adev);
3668 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3669 pcm_params_free(adev->use_case_table[i]);
3670 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003671 if (adev->adm_deinit)
3672 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003673 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07003674 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07003675
3676 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003677
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678 return 0;
3679}
3680
Glenn Kasten4f993392014-05-14 07:30:48 -07003681/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3682 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3683 * just that it _might_ work.
3684 */
3685static int period_size_is_plausible_for_low_latency(int period_size)
3686{
3687 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003688 case 48:
3689 case 96:
3690 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07003691 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003692 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07003693 case 240:
3694 case 320:
3695 case 480:
3696 return 1;
3697 default:
3698 return 0;
3699 }
3700}
3701
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003702static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
3703{
3704 int card;
3705 card_status_t status;
3706
3707 if (!parms)
3708 return;
3709
3710 if (parse_snd_card_status(parms, &card, &status) < 0)
3711 return;
3712
3713 pthread_mutex_lock(&adev->lock);
3714 bool valid_cb = (card == adev->snd_card);
3715 if (valid_cb) {
3716 if (adev->card_status != status) {
3717 adev->card_status = status;
3718 platform_snd_card_update(adev->platform, status);
3719 }
3720 }
3721 pthread_mutex_unlock(&adev->lock);
3722 return;
3723}
3724
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725static int adev_open(const hw_module_t *module, const char *name,
3726 hw_device_t **device)
3727{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003728 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729
Eric Laurent2bafff12016-03-17 12:17:23 -07003730 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003731 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003732 pthread_mutex_lock(&adev_init_lock);
3733 if (audio_device_ref_count != 0) {
3734 *device = &adev->device.common;
3735 audio_device_ref_count++;
3736 ALOGV("%s: returning existing instance of adev", __func__);
3737 ALOGV("%s: exit", __func__);
3738 pthread_mutex_unlock(&adev_init_lock);
3739 return 0;
3740 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741 adev = calloc(1, sizeof(struct audio_device));
3742
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003743 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3744
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3746 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3747 adev->device.common.module = (struct hw_module_t *)module;
3748 adev->device.common.close = adev_close;
3749
3750 adev->device.init_check = adev_init_check;
3751 adev->device.set_voice_volume = adev_set_voice_volume;
3752 adev->device.set_master_volume = adev_set_master_volume;
3753 adev->device.get_master_volume = adev_get_master_volume;
3754 adev->device.set_master_mute = adev_set_master_mute;
3755 adev->device.get_master_mute = adev_get_master_mute;
3756 adev->device.set_mode = adev_set_mode;
3757 adev->device.set_mic_mute = adev_set_mic_mute;
3758 adev->device.get_mic_mute = adev_get_mic_mute;
3759 adev->device.set_parameters = adev_set_parameters;
3760 adev->device.get_parameters = adev_get_parameters;
3761 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3762 adev->device.open_output_stream = adev_open_output_stream;
3763 adev->device.close_output_stream = adev_close_output_stream;
3764 adev->device.open_input_stream = adev_open_input_stream;
3765 adev->device.close_input_stream = adev_close_input_stream;
3766 adev->device.dump = adev_dump;
3767
3768 /* Set the default route before the PCM stream is opened */
3769 pthread_mutex_lock(&adev->lock);
3770 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003771 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003772 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003774 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003775 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003776 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003777 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003778 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 pthread_mutex_unlock(&adev->lock);
3780
3781 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003782 adev->platform = platform_init(adev);
3783 if (!adev->platform) {
3784 free(adev->snd_dev_ref_cnt);
3785 free(adev);
3786 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3787 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003788 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003789 return -EINVAL;
3790 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05003791 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003792 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003793
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003794 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3795 if (adev->visualizer_lib == NULL) {
3796 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3797 } else {
3798 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3799 adev->visualizer_start_output =
3800 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3801 "visualizer_hal_start_output");
3802 adev->visualizer_stop_output =
3803 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3804 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07003805 }
3806
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003807 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3808 if (adev->offload_effects_lib == NULL) {
3809 ALOGW("%s: DLOPEN failed for %s", __func__,
3810 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3811 } else {
3812 ALOGV("%s: DLOPEN successful for %s", __func__,
3813 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3814 adev->offload_effects_start_output =
3815 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3816 "offload_effects_bundle_hal_start_output");
3817 adev->offload_effects_stop_output =
3818 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3819 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07003820 }
3821
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003822 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3823 if (adev->adm_lib == NULL) {
3824 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3825 } else {
3826 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3827 adev->adm_init = (adm_init_t)
3828 dlsym(adev->adm_lib, "adm_init");
3829 adev->adm_deinit = (adm_deinit_t)
3830 dlsym(adev->adm_lib, "adm_deinit");
3831 adev->adm_register_input_stream = (adm_register_input_stream_t)
3832 dlsym(adev->adm_lib, "adm_register_input_stream");
3833 adev->adm_register_output_stream = (adm_register_output_stream_t)
3834 dlsym(adev->adm_lib, "adm_register_output_stream");
3835 adev->adm_deregister_stream = (adm_deregister_stream_t)
3836 dlsym(adev->adm_lib, "adm_deregister_stream");
3837 adev->adm_request_focus = (adm_request_focus_t)
3838 dlsym(adev->adm_lib, "adm_request_focus");
3839 adev->adm_abandon_focus = (adm_abandon_focus_t)
3840 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08003841 adev->adm_set_config = (adm_set_config_t)
3842 dlsym(adev->adm_lib, "adm_set_config");
3843 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
3844 dlsym(adev->adm_lib, "adm_request_focus_v2");
3845 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
3846 dlsym(adev->adm_lib, "adm_is_noirq_avail");
3847 adev->adm_on_routing_change = (adm_on_routing_change_t)
3848 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003849 }
3850
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003851 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003852 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003853
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003855
Andy Hung31aca912014-03-20 17:14:59 -07003856 if (k_enable_extended_precision)
3857 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003858
Glenn Kasten4f993392014-05-14 07:30:48 -07003859 char value[PROPERTY_VALUE_MAX];
3860 int trial;
3861 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3862 trial = atoi(value);
3863 if (period_size_is_plausible_for_low_latency(trial)) {
3864 pcm_config_low_latency.period_size = trial;
3865 pcm_config_low_latency.start_threshold = trial / 4;
3866 pcm_config_low_latency.avail_min = trial / 4;
3867 configured_low_latency_capture_period_size = trial;
3868 }
3869 }
3870 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3871 trial = atoi(value);
3872 if (period_size_is_plausible_for_low_latency(trial)) {
3873 configured_low_latency_capture_period_size = trial;
3874 }
3875 }
3876
Yamit Mehtae3b99562016-09-16 22:44:00 +05303877 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003878 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003879
3880 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
3881 af_period_multiplier = atoi(value);
3882 if (af_period_multiplier < 0) {
3883 af_period_multiplier = 2;
3884 } else if (af_period_multiplier > 4) {
3885 af_period_multiplier = 4;
3886 }
3887 ALOGV("new period_multiplier = %d", af_period_multiplier);
3888 }
3889
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003890 audio_extn_tfa_98xx_init(adev);
3891
vivek mehta1a9b7c02015-06-25 11:49:38 -07003892 pthread_mutex_unlock(&adev_init_lock);
3893
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003894 if (adev->adm_init)
3895 adev->adm_data = adev->adm_init();
3896
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003897 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003898 audio_extn_snd_mon_init();
3899 pthread_mutex_lock(&adev->lock);
3900 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
3901 adev->card_status = CARD_STATUS_ONLINE;
3902 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003903
Eric Laurent2bafff12016-03-17 12:17:23 -07003904 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003905 return 0;
3906}
3907
3908static struct hw_module_methods_t hal_module_methods = {
3909 .open = adev_open,
3910};
3911
3912struct audio_module HAL_MODULE_INFO_SYM = {
3913 .common = {
3914 .tag = HARDWARE_MODULE_TAG,
3915 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3916 .hal_api_version = HARDWARE_HAL_API_VERSION,
3917 .id = AUDIO_HARDWARE_MODULE_ID,
3918 .name = "QCOM Audio HAL",
3919 .author = "Code Aurora Forum",
3920 .methods = &hal_module_methods,
3921 },
3922};