blob: 7b10f566825e775089e4487f2458b5e2d68aeb6a [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"
Eric Park244c1572017-04-18 11:36:26 -040056#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 mehta0d2943f2016-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
Vaughn Nf7c7d742016-12-10 18:53:04 -0500354// 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 mehta0d2943f2016-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
Eric Park244c1572017-04-18 11:36:26 -0400535static 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
Eric Park244c1572017-04-18 11:36:26 -0400563 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 }
Vaughn Nf7c7d742016-12-10 18:53:04 -0500636 } 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
zaclimonb085d1a2016-08-28 13:53:25 -0400650 /*
651 * For some unknown reason, the device name gets empty for
652 * msm8960 devices. Because we're sure that the sound device is valid,
653 * copy it manually and apply the correct route.
654 */
655
656 if (strlen(device_name) == 0) {
657 strcpy(device_name, platform_get_snd_device_name(snd_device));
658 }
659
660 ALOGV("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800661 audio_route_apply_and_update_path(adev->audio_route, device_name);
662 }
663on_success:
664 adev->snd_dev_ref_cnt[snd_device]++;
665 ret_val = 0;
666on_error:
667 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800668}
669
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800670int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700671 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800672{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700673 int i, num_devices = 0;
674 snd_device_t new_snd_devices[2];
675
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800676 if (snd_device < SND_DEVICE_MIN ||
677 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800678 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800679 return -EINVAL;
680 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700681 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
682 ALOGE("%s: device ref cnt is already 0", __func__);
683 return -EINVAL;
684 }
Eric Park244c1572017-04-18 11:36:26 -0400685 audio_extn_tfa_98xx_disable_speaker(snd_device);
686
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700687 adev->snd_dev_ref_cnt[snd_device]--;
688 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800689 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700690 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
691 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
692 audio_extn_spkr_prot_is_enabled()) {
693 audio_extn_spkr_prot_stop_processing(snd_device);
Vaughn Nf7c7d742016-12-10 18:53:04 -0500694 } else if (platform_can_split_snd_device(snd_device,
695 &num_devices,
696 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700697 for (i = 0; i < num_devices; i++) {
698 disable_snd_device(adev, new_snd_devices[i]);
699 }
vivek mehtab6506412015-08-07 16:55:17 -0700700 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700701 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800702 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
703 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
704 ALOGE(" %s: Invalid sound device returned", __func__);
705 return -EINVAL;
706 }
707
zaclimonb085d1a2016-08-28 13:53:25 -0400708 /*
709 * Same reason as in enable_snd_device()
710 */
711
712 if (strlen(device_name) == 0) {
713 strcpy(device_name, platform_get_snd_device_name(snd_device));
714 }
715
716 ALOGV("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800717 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700718 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700719 audio_extn_sound_trigger_update_device_status(snd_device,
720 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700721 }
vivek mehtab6506412015-08-07 16:55:17 -0700722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800723 return 0;
724}
725
Vaughn Nf7c7d742016-12-10 18:53:04 -0500726/*
727 legend:
728 uc - existing usecase
729 new_uc - new usecase
730 d1, d11, d2 - SND_DEVICE enums
731 a1, a2 - corresponding ANDROID device enums
732 B, B1, B2 - backend strings
733
734case 1
735 uc->dev d1 (a1) B1
736 new_uc->dev d1 (a1), d2 (a2) B1, B2
737
738 resolution: disable and enable uc->dev on d1
739
740case 2
741 uc->dev d1 (a1) B1
742 new_uc->dev d11 (a1) B1
743
744 resolution: need to switch uc since d1 and d11 are related
745 (e.g. speaker and voice-speaker)
746 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
747
748case 3
749 uc->dev d1 (a1) B1
750 new_uc->dev d2 (a2) B2
751
752 resolution: no need to switch uc
753
754case 4
755 uc->dev d1 (a1) B
756 new_uc->dev d2 (a2) B
757
758 resolution: disable enable uc-dev on d2 since backends match
759 we cannot enable two streams on two different devices if they
760 share the same backend. e.g. if offload is on speaker device using
761 QUAD_MI2S backend and a low-latency stream is started on voice-handset
762 using the same backend, offload must also be switched to voice-handset.
763
764case 5
765 uc->dev d1 (a1) B
766 new_uc->dev d1 (a1), d2 (a2) B
767
768 resolution: disable enable uc-dev on d2 since backends match
769 we cannot enable two streams on two different devices if they
770 share the same backend.
771
772case 6
773 uc->dev d1 a1 B1
774 new_uc->dev d2 a1 B2
775
776 resolution: no need to switch
777
778case 7
779
780 uc->dev d1 (a1), d2 (a2) B1, B2
781 new_uc->dev d1 B1
782
783 resolution: no need to switch
784
785*/
786static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
787 struct audio_usecase *new_uc,
788 snd_device_t new_snd_device)
789{
790 audio_devices_t a1 = uc->stream.out->devices;
791 audio_devices_t a2 = new_uc->stream.out->devices;
792
793 snd_device_t d1 = uc->out_snd_device;
794 snd_device_t d2 = new_snd_device;
795
796 // Treat as a special case when a1 and a2 are not disjoint
797 if ((a1 != a2) && (a1 & a2)) {
798 snd_device_t d3[2];
799 int num_devices = 0;
800 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
801 &num_devices,
802 d3);
803 if (ret < 0) {
804 if (ret != -ENOSYS) {
805 ALOGW("%s failed to split snd_device %d",
806 __func__,
807 popcount(a1) > 1 ? d1 : d2);
808 }
809 goto end;
810 }
811
812 // NB: case 7 is hypothetical and isn't a practical usecase yet.
813 // But if it does happen, we need to give priority to d2 if
814 // the combo devices active on the existing usecase share a backend.
815 // This is because we cannot have a usecase active on a combo device
816 // and a new usecase requests one device in this combo pair.
817 if (platform_check_backends_match(d3[0], d3[1])) {
818 return d2; // case 5
819 } else {
820 return d1; // case 1
821 }
822 } else {
823 if (platform_check_backends_match(d1, d2)) {
824 return d2; // case 2, 4
825 } else {
826 return d1; // case 6, 3
827 }
828 }
829
830end:
831 return d2; // return whatever was calculated before.
832}
833
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700834static void check_and_route_playback_usecases(struct audio_device *adev,
835 struct audio_usecase *uc_info,
836 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700837{
838 struct listnode *node;
839 struct audio_usecase *usecase;
840 bool switch_device[AUDIO_USECASE_MAX];
841 int i, num_uc_to_switch = 0;
842
843 /*
844 * This function is to make sure that all the usecases that are active on
845 * the hardware codec backend are always routed to any one device that is
846 * handled by the hardware codec.
847 * For example, if low-latency and deep-buffer usecases are currently active
848 * on speaker and out_set_parameters(headset) is received on low-latency
849 * output, then we have to make sure deep-buffer is also switched to headset,
850 * because of the limitation that both the devices cannot be enabled
851 * at the same time as they share the same backend.
852 */
853 /* Disable all the usecases on the shared backend other than the
854 specified usecase */
855 for (i = 0; i < AUDIO_USECASE_MAX; i++)
856 switch_device[i] = false;
857
858 list_for_each(node, &adev->usecase_list) {
859 usecase = node_to_item(node, struct audio_usecase, list);
860 if (usecase->type != PCM_CAPTURE &&
861 usecase != uc_info &&
862 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700863 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
864 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700865 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
866 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700867 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700868 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869 switch_device[usecase->id] = true;
870 num_uc_to_switch++;
871 }
872 }
873
874 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700875 list_for_each(node, &adev->usecase_list) {
876 usecase = node_to_item(node, struct audio_usecase, list);
877 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700878 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900879 }
880 }
881
Vaughn Nf7c7d742016-12-10 18:53:04 -0500882 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900883 list_for_each(node, &adev->usecase_list) {
884 usecase = node_to_item(node, struct audio_usecase, list);
885 if (switch_device[usecase->id]) {
Vaughn Nf7c7d742016-12-10 18:53:04 -0500886 d_device = derive_playback_snd_device(usecase, uc_info,
887 snd_device);
888 enable_snd_device(adev, d_device);
889 /* Update the out_snd_device before enabling the audio route */
890 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700891 }
892 }
893
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700894 /* Re-route all the usecases on the shared backend other than the
895 specified usecase to new snd devices */
896 list_for_each(node, &adev->usecase_list) {
897 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700898 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700899 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700900 }
901 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700902 }
903}
904
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700905static void check_and_route_capture_usecases(struct audio_device *adev,
906 struct audio_usecase *uc_info,
907 snd_device_t snd_device)
908{
909 struct listnode *node;
910 struct audio_usecase *usecase;
911 bool switch_device[AUDIO_USECASE_MAX];
912 int i, num_uc_to_switch = 0;
913
vivek mehta4ed66e62016-04-15 23:33:34 -0700914 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
915
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700916 /*
917 * This function is to make sure that all the active capture usecases
918 * are always routed to the same input sound device.
919 * For example, if audio-record and voice-call usecases are currently
920 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
921 * is received for voice call then we have to make sure that audio-record
922 * usecase is also switched to earpiece i.e. voice-dmic-ef,
923 * because of the limitation that two devices cannot be enabled
924 * at the same time if they share the same backend.
925 */
926 for (i = 0; i < AUDIO_USECASE_MAX; i++)
927 switch_device[i] = false;
928
929 list_for_each(node, &adev->usecase_list) {
930 usecase = node_to_item(node, struct audio_usecase, list);
931 if (usecase->type != PCM_PLAYBACK &&
932 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700933 usecase->in_snd_device != snd_device &&
934 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700935 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
936 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700937 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700938 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700939 switch_device[usecase->id] = true;
940 num_uc_to_switch++;
941 }
942 }
943
944 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700945 list_for_each(node, &adev->usecase_list) {
946 usecase = node_to_item(node, struct audio_usecase, list);
947 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700948 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700949 }
950 }
951
952 list_for_each(node, &adev->usecase_list) {
953 usecase = node_to_item(node, struct audio_usecase, list);
954 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700955 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700956 }
957 }
958
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700959 /* Re-route all the usecases on the shared backend other than the
960 specified usecase to new snd devices */
961 list_for_each(node, &adev->usecase_list) {
962 usecase = node_to_item(node, struct audio_usecase, list);
963 /* Update the in_snd_device only before enabling the audio route */
964 if (switch_device[usecase->id] ) {
965 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700966 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700967 }
968 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700969 }
970}
971
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800972/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700973static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800974{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700975 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700976 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800977
978 switch (channels) {
979 /*
980 * Do not handle stereo output in Multi-channel cases
981 * Stereo case is handled in normal playback path
982 */
983 case 6:
984 ALOGV("%s: HDMI supports 5.1", __func__);
985 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
986 break;
987 case 8:
988 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
989 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
990 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
991 break;
992 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700993 ALOGE("HDMI does not support multi channel playback");
994 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800995 break;
996 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700997 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800998}
999
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001000static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1001{
1002 struct audio_usecase *usecase;
1003 struct listnode *node;
1004
1005 list_for_each(node, &adev->usecase_list) {
1006 usecase = node_to_item(node, struct audio_usecase, list);
1007 if (usecase->type == VOICE_CALL) {
1008 ALOGV("%s: usecase id %d", __func__, usecase->id);
1009 return usecase->id;
1010 }
1011 }
1012 return USECASE_INVALID;
1013}
1014
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001015struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1016 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001017{
1018 struct audio_usecase *usecase;
1019 struct listnode *node;
1020
1021 list_for_each(node, &adev->usecase_list) {
1022 usecase = node_to_item(node, struct audio_usecase, list);
1023 if (usecase->id == uc_id)
1024 return usecase;
1025 }
1026 return NULL;
1027}
1028
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001029int select_devices(struct audio_device *adev,
1030 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001032 snd_device_t out_snd_device = SND_DEVICE_NONE;
1033 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001034 struct audio_usecase *usecase = NULL;
1035 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001036 struct audio_usecase *hfp_usecase = NULL;
1037 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001038 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001039 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001040
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001041 usecase = get_usecase_from_list(adev, uc_id);
1042 if (usecase == NULL) {
1043 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1044 return -EINVAL;
1045 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001047 if ((usecase->type == VOICE_CALL) ||
1048 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001049 out_snd_device = platform_get_output_snd_device(adev->platform,
1050 usecase->stream.out->devices);
1051 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001052 usecase->devices = usecase->stream.out->devices;
1053 } else {
1054 /*
1055 * If the voice call is active, use the sound devices of voice call usecase
1056 * so that it would not result any device switch. All the usecases will
1057 * be switched to new device when select_devices() is called for voice call
1058 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001059 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001060 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001061 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001062 vc_usecase = get_usecase_from_list(adev,
1063 get_voice_usecase_id_from_list(adev));
1064 if ((vc_usecase != NULL) &&
1065 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1066 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001067 in_snd_device = vc_usecase->in_snd_device;
1068 out_snd_device = vc_usecase->out_snd_device;
1069 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001070 } else if (audio_extn_hfp_is_active(adev)) {
1071 hfp_ucid = audio_extn_hfp_get_usecase();
1072 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1073 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1074 in_snd_device = hfp_usecase->in_snd_device;
1075 out_snd_device = hfp_usecase->out_snd_device;
1076 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001077 }
1078 if (usecase->type == PCM_PLAYBACK) {
1079 usecase->devices = usecase->stream.out->devices;
1080 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001081 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001082 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001083 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001084 if (usecase->stream.out == adev->primary_output &&
1085 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001086 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1087 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001088 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001089 select_devices(adev, adev->active_input->usecase);
1090 }
1091 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001092 } else if (usecase->type == PCM_CAPTURE) {
1093 usecase->devices = usecase->stream.in->device;
1094 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001095 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001096 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001097 if (adev->active_input &&
1098 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1099 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001100 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001101 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1102 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1103 } else if (adev->primary_output) {
1104 out_device = adev->primary_output->devices;
1105 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001106 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001107 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001108 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001109 }
1110 }
1111
1112 if (out_snd_device == usecase->out_snd_device &&
1113 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001114 return 0;
1115 }
1116
Eric Laurent2bafff12016-03-17 12:17:23 -07001117 if (out_snd_device != SND_DEVICE_NONE &&
1118 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1119 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1120 __func__,
1121 use_case_table[uc_id],
1122 adev->last_logged_snd_device[uc_id][0],
1123 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1124 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1125 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1126 -1,
1127 out_snd_device,
1128 platform_get_snd_device_name(out_snd_device),
1129 platform_get_snd_device_acdb_id(out_snd_device));
1130 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1131 }
1132 if (in_snd_device != SND_DEVICE_NONE &&
1133 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1134 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1135 __func__,
1136 use_case_table[uc_id],
1137 adev->last_logged_snd_device[uc_id][1],
1138 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1139 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1140 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1141 -1,
1142 in_snd_device,
1143 platform_get_snd_device_name(in_snd_device),
1144 platform_get_snd_device_acdb_id(in_snd_device));
1145 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1146 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001148 /*
1149 * Limitation: While in call, to do a device switch we need to disable
1150 * and enable both RX and TX devices though one of them is same as current
1151 * device.
1152 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001153 if ((usecase->type == VOICE_CALL) &&
1154 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1155 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001156 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001157 /* Disable sidetone only if voice call already exists */
1158 if (voice_is_call_state_active(adev))
1159 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001160 }
1161
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001162 /* Disable current sound devices */
1163 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001164 disable_audio_route(adev, usecase);
1165 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001166 }
1167
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001168 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001169 disable_audio_route(adev, usecase);
1170 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001171 }
1172
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001173 /* Applicable only on the targets that has external modem.
1174 * New device information should be sent to modem before enabling
1175 * the devices to reduce in-call device switch time.
1176 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001177 if ((usecase->type == VOICE_CALL) &&
1178 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1179 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001180 status = platform_switch_voice_call_enable_device_config(adev->platform,
1181 out_snd_device,
1182 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001183 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001184
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001185 /* Enable new sound devices */
1186 if (out_snd_device != SND_DEVICE_NONE) {
1187 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001188 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001189 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001190 }
1191
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001192 if (in_snd_device != SND_DEVICE_NONE) {
1193 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001194 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001195 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001196
Eric Laurentb23d5282013-05-14 15:27:20 -07001197 if (usecase->type == VOICE_CALL)
1198 status = platform_switch_voice_call_device_post(adev->platform,
1199 out_snd_device,
1200 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001201
sangwoo170731f2013-06-08 15:36:36 +09001202 usecase->in_snd_device = in_snd_device;
1203 usecase->out_snd_device = out_snd_device;
1204
Eric Park244c1572017-04-18 11:36:26 -04001205 audio_extn_tfa_98xx_set_mode();
1206
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001207 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001208
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001209 /* Applicable only on the targets that has external modem.
1210 * Enable device command should be sent to modem only after
1211 * enabling voice call mixer controls
1212 */
vivek mehta765eb642015-08-07 19:46:06 -07001213 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001214 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1215 out_snd_device,
1216 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001217 /* Enable sidetone only if voice call already exists */
1218 if (voice_is_call_state_active(adev))
1219 voice_set_sidetone(adev, out_snd_device, true);
1220 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001222 return status;
1223}
1224
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001225static int stop_input_stream(struct stream_in *in)
1226{
1227 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001228 struct audio_usecase *uc_info;
1229 struct audio_device *adev = in->dev;
1230
Eric Laurentc8400632013-02-14 19:04:54 -08001231 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232
Eric Laurent994a6932013-07-17 11:51:42 -07001233 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001234 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001235 uc_info = get_usecase_from_list(adev, in->usecase);
1236 if (uc_info == NULL) {
1237 ALOGE("%s: Could not find the usecase (%d) in the list",
1238 __func__, in->usecase);
1239 return -EINVAL;
1240 }
1241
Eric Laurent150dbfe2013-02-27 14:31:02 -08001242 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001243 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001244
1245 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001246 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001247
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001248 list_remove(&uc_info->list);
1249 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001250
Eric Laurent994a6932013-07-17 11:51:42 -07001251 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001252 return ret;
1253}
1254
1255int start_input_stream(struct stream_in *in)
1256{
1257 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001258 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001259 struct audio_usecase *uc_info;
1260 struct audio_device *adev = in->dev;
1261
Eric Laurent994a6932013-07-17 11:51:42 -07001262 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001263
Eric Park244c1572017-04-18 11:36:26 -04001264 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1265 return -EIO;
1266
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001267 if (in->card_status == CARD_STATUS_OFFLINE ||
1268 adev->card_status == CARD_STATUS_OFFLINE) {
1269 ALOGW("in->card_status or adev->card_status offline, try again");
1270 ret = -EAGAIN;
1271 goto error_config;
1272 }
1273
Eric Laurentb23d5282013-05-14 15:27:20 -07001274 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275 if (in->pcm_device_id < 0) {
1276 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1277 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001278 ret = -EINVAL;
1279 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001280 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001281
1282 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001283 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1284 uc_info->id = in->usecase;
1285 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001286 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001287 uc_info->devices = in->device;
1288 uc_info->in_snd_device = SND_DEVICE_NONE;
1289 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001290
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001291 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001292
1293 audio_extn_perf_lock_acquire();
1294
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001295 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001296
Eric Laurentc8400632013-02-14 19:04:54 -08001297 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001298 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001299
Andy Hung6ebe5962016-01-15 17:46:57 -08001300 unsigned int flags = PCM_IN | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001301 unsigned int pcm_open_retry_count = 0;
1302
1303 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1304 flags |= PCM_MMAP | PCM_NOIRQ;
1305 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001306 } else if (in->realtime) {
1307 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001308 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001309
1310 while (1) {
1311 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1312 flags, &in->config);
1313 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1314 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1315 if (in->pcm != NULL) {
1316 pcm_close(in->pcm);
1317 in->pcm = NULL;
1318 }
1319 if (pcm_open_retry_count-- == 0) {
1320 ret = -EIO;
1321 goto error_open;
1322 }
1323 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1324 continue;
1325 }
1326 break;
1327 }
1328
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001329 ALOGV("%s: pcm_prepare", __func__);
1330 ret = pcm_prepare(in->pcm);
1331 if (ret < 0) {
1332 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1333 pcm_close(in->pcm);
1334 in->pcm = NULL;
1335 goto error_open;
1336 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001337 if (in->realtime) {
1338 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001339 if (ret < 0) {
1340 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1341 pcm_close(in->pcm);
1342 in->pcm = NULL;
1343 goto error_open;
1344 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001345 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001346 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001347 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001348 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001349
Eric Laurentc8400632013-02-14 19:04:54 -08001350 return ret;
1351
1352error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001353 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001354 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001355
1356error_config:
1357 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001358 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001359
1360 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001361}
1362
Eric Laurenta1478072015-09-21 17:21:52 -07001363void lock_input_stream(struct stream_in *in)
1364{
1365 pthread_mutex_lock(&in->pre_lock);
1366 pthread_mutex_lock(&in->lock);
1367 pthread_mutex_unlock(&in->pre_lock);
1368}
1369
1370void lock_output_stream(struct stream_out *out)
1371{
1372 pthread_mutex_lock(&out->pre_lock);
1373 pthread_mutex_lock(&out->lock);
1374 pthread_mutex_unlock(&out->pre_lock);
1375}
1376
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001377/* must be called with out->lock locked */
1378static int send_offload_cmd_l(struct stream_out* out, int command)
1379{
1380 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1381
1382 ALOGVV("%s %d", __func__, command);
1383
1384 cmd->cmd = command;
1385 list_add_tail(&out->offload_cmd_list, &cmd->node);
1386 pthread_cond_signal(&out->offload_cond);
1387 return 0;
1388}
1389
1390/* must be called iwth out->lock locked */
1391static void stop_compressed_output_l(struct stream_out *out)
1392{
1393 out->offload_state = OFFLOAD_STATE_IDLE;
1394 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001395 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001396 if (out->compr != NULL) {
1397 compress_stop(out->compr);
1398 while (out->offload_thread_blocked) {
1399 pthread_cond_wait(&out->cond, &out->lock);
1400 }
1401 }
1402}
1403
1404static void *offload_thread_loop(void *context)
1405{
1406 struct stream_out *out = (struct stream_out *) context;
1407 struct listnode *item;
1408
1409 out->offload_state = OFFLOAD_STATE_IDLE;
1410 out->playback_started = 0;
1411
1412 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1413 set_sched_policy(0, SP_FOREGROUND);
1414 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1415
1416 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001417 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001418 for (;;) {
1419 struct offload_cmd *cmd = NULL;
1420 stream_callback_event_t event;
1421 bool send_callback = false;
1422
1423 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1424 __func__, list_empty(&out->offload_cmd_list),
1425 out->offload_state);
1426 if (list_empty(&out->offload_cmd_list)) {
1427 ALOGV("%s SLEEPING", __func__);
1428 pthread_cond_wait(&out->offload_cond, &out->lock);
1429 ALOGV("%s RUNNING", __func__);
1430 continue;
1431 }
1432
1433 item = list_head(&out->offload_cmd_list);
1434 cmd = node_to_item(item, struct offload_cmd, node);
1435 list_remove(item);
1436
1437 ALOGVV("%s STATE %d CMD %d out->compr %p",
1438 __func__, out->offload_state, cmd->cmd, out->compr);
1439
1440 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1441 free(cmd);
1442 break;
1443 }
1444
1445 if (out->compr == NULL) {
1446 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001447 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001448 pthread_cond_signal(&out->cond);
1449 continue;
1450 }
1451 out->offload_thread_blocked = true;
1452 pthread_mutex_unlock(&out->lock);
1453 send_callback = false;
1454 switch(cmd->cmd) {
1455 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1456 compress_wait(out->compr, -1);
1457 send_callback = true;
1458 event = STREAM_CBK_EVENT_WRITE_READY;
1459 break;
1460 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001461 compress_next_track(out->compr);
1462 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001463 send_callback = true;
1464 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001465 /* Resend the metadata for next iteration */
1466 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001467 break;
1468 case OFFLOAD_CMD_DRAIN:
1469 compress_drain(out->compr);
1470 send_callback = true;
1471 event = STREAM_CBK_EVENT_DRAIN_READY;
1472 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001473 case OFFLOAD_CMD_ERROR:
1474 send_callback = true;
1475 event = STREAM_CBK_EVENT_ERROR;
1476 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001477 default:
1478 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1479 break;
1480 }
Eric Laurenta1478072015-09-21 17:21:52 -07001481 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001482 out->offload_thread_blocked = false;
1483 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001484 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001485 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001486 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001487 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001488 free(cmd);
1489 }
1490
1491 pthread_cond_signal(&out->cond);
1492 while (!list_empty(&out->offload_cmd_list)) {
1493 item = list_head(&out->offload_cmd_list);
1494 list_remove(item);
1495 free(node_to_item(item, struct offload_cmd, node));
1496 }
1497 pthread_mutex_unlock(&out->lock);
1498
1499 return NULL;
1500}
1501
1502static int create_offload_callback_thread(struct stream_out *out)
1503{
1504 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1505 list_init(&out->offload_cmd_list);
1506 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1507 offload_thread_loop, out);
1508 return 0;
1509}
1510
1511static int destroy_offload_callback_thread(struct stream_out *out)
1512{
Eric Laurenta1478072015-09-21 17:21:52 -07001513 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001514 stop_compressed_output_l(out);
1515 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1516
1517 pthread_mutex_unlock(&out->lock);
1518 pthread_join(out->offload_thread, (void **) NULL);
1519 pthread_cond_destroy(&out->offload_cond);
1520
1521 return 0;
1522}
1523
Eric Laurent07eeafd2013-10-06 12:52:49 -07001524static bool allow_hdmi_channel_config(struct audio_device *adev)
1525{
1526 struct listnode *node;
1527 struct audio_usecase *usecase;
1528 bool ret = true;
1529
1530 list_for_each(node, &adev->usecase_list) {
1531 usecase = node_to_item(node, struct audio_usecase, list);
1532 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1533 /*
1534 * If voice call is already existing, do not proceed further to avoid
1535 * disabling/enabling both RX and TX devices, CSD calls, etc.
1536 * Once the voice call done, the HDMI channels can be configured to
1537 * max channels of remaining use cases.
1538 */
1539 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001540 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001541 __func__);
1542 ret = false;
1543 break;
1544 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001545 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001546 "no change in HDMI channels", __func__);
1547 ret = false;
1548 break;
1549 }
1550 }
1551 }
1552 return ret;
1553}
1554
1555static int check_and_set_hdmi_channels(struct audio_device *adev,
1556 unsigned int channels)
1557{
1558 struct listnode *node;
1559 struct audio_usecase *usecase;
1560
1561 /* Check if change in HDMI channel config is allowed */
1562 if (!allow_hdmi_channel_config(adev))
1563 return 0;
1564
1565 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001566 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001567 return 0;
1568 }
1569
1570 platform_set_hdmi_channels(adev->platform, channels);
1571 adev->cur_hdmi_channels = channels;
1572
1573 /*
1574 * Deroute all the playback streams routed to HDMI so that
1575 * the back end is deactivated. Note that backend will not
1576 * be deactivated if any one stream is connected to it.
1577 */
1578 list_for_each(node, &adev->usecase_list) {
1579 usecase = node_to_item(node, struct audio_usecase, list);
1580 if (usecase->type == PCM_PLAYBACK &&
1581 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001582 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001583 }
1584 }
1585
1586 /*
1587 * Enable all the streams disabled above. Now the HDMI backend
1588 * will be activated with new channel configuration
1589 */
1590 list_for_each(node, &adev->usecase_list) {
1591 usecase = node_to_item(node, struct audio_usecase, list);
1592 if (usecase->type == PCM_PLAYBACK &&
1593 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001594 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001595 }
1596 }
1597
1598 return 0;
1599}
1600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001601static int stop_output_stream(struct stream_out *out)
1602{
1603 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001604 struct audio_usecase *uc_info;
1605 struct audio_device *adev = out->dev;
1606
Eric Laurent994a6932013-07-17 11:51:42 -07001607 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001608 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001609 uc_info = get_usecase_from_list(adev, out->usecase);
1610 if (uc_info == NULL) {
1611 ALOGE("%s: Could not find the usecase (%d) in the list",
1612 __func__, out->usecase);
1613 return -EINVAL;
1614 }
1615
Haynes Mathew George41f86652014-06-17 14:22:15 -07001616 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1617 if (adev->visualizer_stop_output != NULL)
1618 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1619 if (adev->offload_effects_stop_output != NULL)
1620 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1621 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001622
Eric Laurent150dbfe2013-02-27 14:31:02 -08001623 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001624 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001625
1626 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001627 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001628
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001629 list_remove(&uc_info->list);
1630 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001631
Eric Laurent0499d4f2014-08-25 22:39:29 -05001632 audio_extn_extspk_update(adev->extspk);
1633
Eric Laurent07eeafd2013-10-06 12:52:49 -07001634 /* Must be called after removing the usecase from list */
1635 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1636 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1637
Eric Laurent994a6932013-07-17 11:51:42 -07001638 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001639 return ret;
1640}
1641
1642int start_output_stream(struct stream_out *out)
1643{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001645 struct audio_usecase *uc_info;
1646 struct audio_device *adev = out->dev;
1647
Eric Laurent994a6932013-07-17 11:51:42 -07001648 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001649 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001650
1651 if (out->card_status == CARD_STATUS_OFFLINE ||
1652 adev->card_status == CARD_STATUS_OFFLINE) {
1653 ALOGW("out->card_status or adev->card_status offline, try again");
1654 ret = -EAGAIN;
1655 goto error_config;
1656 }
1657
Eric Laurentb23d5282013-05-14 15:27:20 -07001658 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001659 if (out->pcm_device_id < 0) {
1660 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1661 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001662 ret = -EINVAL;
1663 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664 }
1665
1666 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1667 uc_info->id = out->usecase;
1668 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001669 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001670 uc_info->devices = out->devices;
1671 uc_info->in_snd_device = SND_DEVICE_NONE;
1672 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673
Eric Laurent07eeafd2013-10-06 12:52:49 -07001674 /* This must be called before adding this usecase to the list */
1675 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1676 check_and_set_hdmi_channels(adev, out->config.channels);
1677
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001678 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001680 audio_extn_perf_lock_acquire();
1681
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001682 select_devices(adev, out->usecase);
1683
Eric Laurent0499d4f2014-08-25 22:39:29 -05001684 audio_extn_extspk_update(adev->extspk);
1685
Andy Hung31aca912014-03-20 17:14:59 -07001686 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001687 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001688 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001689 unsigned int flags = PCM_OUT;
1690 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001691
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001692 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1693 flags |= PCM_MMAP | PCM_NOIRQ;
1694 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001695 } else if (out->realtime) {
1696 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001697 } else
1698 flags |= PCM_MONOTONIC;
1699
1700 while (1) {
1701 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1702 flags, &out->config);
1703 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1704 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1705 if (out->pcm != NULL) {
1706 pcm_close(out->pcm);
1707 out->pcm = NULL;
1708 }
1709 if (pcm_open_retry_count-- == 0) {
1710 ret = -EIO;
1711 goto error_open;
1712 }
1713 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1714 continue;
1715 }
1716 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001717 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001718 ALOGV("%s: pcm_prepare", __func__);
1719 if (pcm_is_ready(out->pcm)) {
1720 ret = pcm_prepare(out->pcm);
1721 if (ret < 0) {
1722 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1723 pcm_close(out->pcm);
1724 out->pcm = NULL;
1725 goto error_open;
1726 }
1727 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001728 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729 out->pcm = NULL;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001730 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001731 COMPRESS_IN, &out->compr_config);
1732 if (out->compr && !is_compress_ready(out->compr)) {
1733 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1734 compress_close(out->compr);
1735 out->compr = NULL;
1736 ret = -EIO;
1737 goto error_open;
1738 }
1739 if (out->offload_callback)
1740 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001741
1742 if (adev->visualizer_start_output != NULL)
Haynes Mathew George41f86652014-06-17 14:22:15 -07001743 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1744 if (adev->offload_effects_start_output != NULL)
1745 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001746 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001747 ret = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001748 if (out->realtime) {
1749 ret = pcm_start(out->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001750 if (ret < 0) {
1751 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1752 pcm_close(out->pcm);
1753 out->pcm = NULL;
1754 goto error_open;
1755 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001756 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001757 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001758 audio_extn_perf_lock_release();
Eric Park244c1572017-04-18 11:36:26 -04001759 audio_extn_tfa_98xx_enable_speaker();
1760
Eric Laurent994a6932013-07-17 11:51:42 -07001761 ALOGV("%s: exit", __func__);
Haynes Mathew George03c40102016-01-29 17:57:48 -08001762 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001763error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001764 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001766error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001767 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768}
1769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770static int check_input_parameters(uint32_t sample_rate,
1771 audio_format_t format,
1772 int channel_count)
1773{
vivek mehta4ed66e62016-04-15 23:33:34 -07001774 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001775 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1776 return -EINVAL;
1777 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778
vivek mehtadae44712015-07-27 14:13:18 -07001779 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001780 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001781 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1782 return -EINVAL;
1783 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784
1785 switch (sample_rate) {
1786 case 8000:
1787 case 11025:
1788 case 12000:
1789 case 16000:
1790 case 22050:
1791 case 24000:
1792 case 32000:
1793 case 44100:
1794 case 48000:
1795 break;
1796 default:
vivek mehtadae44712015-07-27 14:13:18 -07001797 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798 return -EINVAL;
1799 }
1800
1801 return 0;
1802}
1803
1804static size_t get_input_buffer_size(uint32_t sample_rate,
1805 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001806 int channel_count,
1807 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001808{
1809 size_t size = 0;
1810
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001811 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1812 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001814 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001815 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001816 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001817
1818 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001819
Glenn Kasten4f993392014-05-14 07:30:48 -07001820 /* make sure the size is multiple of 32 bytes
1821 * At 48 kHz mono 16-bit PCM:
1822 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1823 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1824 */
1825 size += 0x1f;
1826 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001827
1828 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001829}
1830
1831static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1832{
1833 struct stream_out *out = (struct stream_out *)stream;
1834
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001835 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001836}
1837
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001838static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839{
1840 return -ENOSYS;
1841}
1842
1843static size_t out_get_buffer_size(const struct audio_stream *stream)
1844{
1845 struct stream_out *out = (struct stream_out *)stream;
1846
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001847 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1848 return out->compr_config.fragment_size;
1849 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001850 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001851 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852}
1853
1854static uint32_t out_get_channels(const struct audio_stream *stream)
1855{
1856 struct stream_out *out = (struct stream_out *)stream;
1857
1858 return out->channel_mask;
1859}
1860
1861static audio_format_t out_get_format(const struct audio_stream *stream)
1862{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001863 struct stream_out *out = (struct stream_out *)stream;
1864
1865 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001866}
1867
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001868static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869{
1870 return -ENOSYS;
1871}
1872
1873static int out_standby(struct audio_stream *stream)
1874{
1875 struct stream_out *out = (struct stream_out *)stream;
1876 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001877
Eric Laurent994a6932013-07-17 11:51:42 -07001878 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001879 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880
Eric Laurenta1478072015-09-21 17:21:52 -07001881 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001883 if (adev->adm_deregister_stream)
1884 adev->adm_deregister_stream(adev->adm_data, out->handle);
1885
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001886 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001887 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001888 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1889 if (out->pcm) {
1890 pcm_close(out->pcm);
1891 out->pcm = NULL;
1892 }
1893 } else {
1894 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001895 out->gapless_mdata.encoder_delay = 0;
1896 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001897 if (out->compr != NULL) {
1898 compress_close(out->compr);
1899 out->compr = NULL;
1900 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001901 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001902 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001903 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904 }
1905 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001906 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001907 return 0;
1908}
1909
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001910static int out_on_error(struct audio_stream *stream)
1911{
1912 struct stream_out *out = (struct stream_out *)stream;
1913 struct audio_device *adev = out->dev;
1914 bool do_standby = false;
1915
1916 lock_output_stream(out);
1917 if (!out->standby) {
1918 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1919 stop_compressed_output_l(out);
1920 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1921 } else
1922 do_standby = true;
1923 }
1924 pthread_mutex_unlock(&out->lock);
1925
1926 if (do_standby)
1927 return out_standby(&out->stream.common);
1928
1929 return 0;
1930}
1931
Vaughn Nf7c7d742016-12-10 18:53:04 -05001932static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001933{
Vaughn Nf7c7d742016-12-10 18:53:04 -05001934 struct stream_out *out = (struct stream_out *)stream;
1935
1936 // We try to get the lock for consistency,
1937 // but it isn't necessary for these variables.
1938 // If we're not in standby, we may be blocked on a write.
1939 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1940 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1941 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1942
1943 if (locked) {
1944 log_dump_l(&out->error_log, fd);
1945 pthread_mutex_unlock(&out->lock);
1946 } else {
1947 // We don't have the lock here, copy for safety.
1948 struct error_log log = out->error_log;
1949 log_dump_l(&log, fd);
1950 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001951 return 0;
1952}
1953
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001954static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1955{
1956 int ret = 0;
1957 char value[32];
1958 struct compr_gapless_mdata tmp_mdata;
1959
1960 if (!out || !parms) {
1961 return -EINVAL;
1962 }
1963
1964 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1965 if (ret >= 0) {
1966 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1967 } else {
1968 return -EINVAL;
1969 }
1970
1971 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1972 if (ret >= 0) {
1973 tmp_mdata.encoder_padding = atoi(value);
1974 } else {
1975 return -EINVAL;
1976 }
1977
1978 out->gapless_mdata = tmp_mdata;
1979 out->send_new_metadata = 1;
1980 ALOGV("%s new encoder delay %u and padding %u", __func__,
1981 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1982
1983 return 0;
1984}
1985
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001986static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1987{
1988 return out == adev->primary_output || out == adev->voice_tx_output;
1989}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001990
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1992{
1993 struct stream_out *out = (struct stream_out *)stream;
1994 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001995 struct audio_usecase *usecase;
1996 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997 struct str_parms *parms;
1998 char value[32];
1999 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002000 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002001 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002
Eric Laurent2e140aa2016-06-30 17:14:46 -07002003 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002004 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002005 parms = str_parms_create_str(kvpairs);
2006 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2007 if (ret >= 0) {
2008 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002009 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002010 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002012 /*
2013 * When HDMI cable is unplugged the music playback is paused and
2014 * the policy manager sends routing=0. But the audioflinger
2015 * continues to write data until standby time (3sec).
2016 * As the HDMI core is turned off, the write gets blocked.
2017 * Avoid this by routing audio to speaker until standby.
2018 */
2019 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2020 val == AUDIO_DEVICE_NONE) {
2021 val = AUDIO_DEVICE_OUT_SPEAKER;
2022 }
2023
2024 /*
2025 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002026 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002027 * the select_devices(). But how do we undo this?
2028 *
2029 * For example, music playback is active on headset (deep-buffer usecase)
2030 * and if we go to ringtones and select a ringtone, low-latency usecase
2031 * will be started on headset+speaker. As we can't enable headset+speaker
2032 * and headset devices at the same time, select_devices() switches the music
2033 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2034 * So when the ringtone playback is completed, how do we undo the same?
2035 *
2036 * We are relying on the out_set_parameters() call on deep-buffer output,
2037 * once the ringtone playback is ended.
2038 * NOTE: We should not check if the current devices are same as new devices.
2039 * Because select_devices() must be called to switch back the music
2040 * playback to headset.
2041 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002042 audio_devices_t new_dev = val;
2043 if (new_dev != AUDIO_DEVICE_NONE) {
2044 bool same_dev = out->devices == new_dev;
2045 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002046
Eric Laurenta7657192014-10-09 21:09:33 -07002047 if (output_drives_call(adev, out)) {
2048 if (!voice_is_in_call(adev)) {
2049 if (adev->mode == AUDIO_MODE_IN_CALL) {
2050 adev->current_call_output = out;
2051 ret = voice_start_call(adev);
2052 }
2053 } else {
2054 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002055 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002056 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002057 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002058
2059 if (!out->standby) {
2060 if (!same_dev) {
2061 ALOGV("update routing change");
2062 out->routing_change = true;
2063 }
2064 select_devices(adev, out->usecase);
Eric Park244c1572017-04-18 11:36:26 -04002065 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002066 }
2067
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002068 }
2069
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002070 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002071 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002072
2073 /*handles device and call state changes*/
2074 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002076
2077 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2078 parse_compress_metadata(out, parms);
2079 }
2080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002081 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002082 ALOGV("%s: exit: code(%d)", __func__, status);
2083 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002084}
2085
2086static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2087{
2088 struct stream_out *out = (struct stream_out *)stream;
2089 struct str_parms *query = str_parms_create_str(keys);
2090 char *str;
2091 char value[256];
2092 struct str_parms *reply = str_parms_create();
2093 size_t i, j;
2094 int ret;
2095 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002096 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002097 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2098 if (ret >= 0) {
2099 value[0] = '\0';
2100 i = 0;
2101 while (out->supported_channel_masks[i] != 0) {
2102 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2103 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2104 if (!first) {
2105 strcat(value, "|");
2106 }
2107 strcat(value, out_channels_name_to_enum_table[j].name);
2108 first = false;
2109 break;
2110 }
2111 }
2112 i++;
2113 }
2114 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2115 str = str_parms_to_str(reply);
2116 } else {
2117 str = strdup(keys);
2118 }
2119 str_parms_destroy(query);
2120 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002121 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122 return str;
2123}
2124
2125static uint32_t out_get_latency(const struct audio_stream_out *stream)
2126{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002127 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002128 struct stream_out *out = (struct stream_out *)stream;
2129
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002130 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2131 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002132 else if (out->realtime) {
2133 // since the buffer won't be filled up faster than realtime,
2134 // return a smaller number
2135 period_ms = (out->af_period_multiplier * out->config.period_size *
2136 1000) / (out->config.rate);
2137 hw_delay = platform_render_latency(out->usecase)/1000;
2138 return period_ms + hw_delay;
2139 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002140
2141 return (out->config.period_count * out->config.period_size * 1000) /
2142 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143}
2144
2145static int out_set_volume(struct audio_stream_out *stream, float left,
2146 float right)
2147{
Eric Laurenta9024de2013-04-04 09:19:12 -07002148 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002149 int volume[2];
2150
Eric Laurenta9024de2013-04-04 09:19:12 -07002151 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2152 /* only take left channel into account: the API is for stereo anyway */
2153 out->muted = (left == 0.0f);
2154 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002155 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2156 const char *mixer_ctl_name = "Compress Playback Volume";
2157 struct audio_device *adev = out->dev;
2158 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002159 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2160 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002161 /* try with the control based on device id */
2162 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2163 PCM_PLAYBACK);
2164 char ctl_name[128] = {0};
2165 snprintf(ctl_name, sizeof(ctl_name),
2166 "Compress Playback %d Volume", pcm_device_id);
2167 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2168 if (!ctl) {
2169 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2170 return -EINVAL;
2171 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002172 }
2173 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2174 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2175 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2176 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002177 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002178
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179 return -ENOSYS;
2180}
2181
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002182// note: this call is safe only if the stream_cb is
2183// removed first in close_output_stream (as is done now).
2184static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2185{
2186 if (!stream || !parms)
2187 return;
2188
2189 struct stream_out *out = (struct stream_out *)stream;
2190 struct audio_device *adev = out->dev;
2191
2192 card_status_t status;
2193 int card;
2194 if (parse_snd_card_status(parms, &card, &status) < 0)
2195 return;
2196
2197 pthread_mutex_lock(&adev->lock);
2198 bool valid_cb = (card == adev->snd_card);
2199 pthread_mutex_unlock(&adev->lock);
2200
2201 if (!valid_cb)
2202 return;
2203
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002204 lock_output_stream(out);
2205 if (out->card_status != status)
2206 out->card_status = status;
2207 pthread_mutex_unlock(&out->lock);
2208
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002209 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2210 use_case_table[out->usecase],
2211 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2212
2213 if (status == CARD_STATUS_OFFLINE)
2214 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002215
2216 return;
2217}
2218
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002219#ifdef NO_AUDIO_OUT
2220static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
2221 const void *buffer, size_t bytes)
2222{
2223 struct stream_out *out = (struct stream_out *)stream;
Eric Park244c1572017-04-18 11:36:26 -04002224 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
2225 int64_t now;
2226 int64_t elapsed_time_since_last_write = 0;
2227 int64_t sleep_time;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002228
Eric Park244c1572017-04-18 11:36:26 -04002229 clock_gettime(CLOCK_MONOTONIC, &t);
2230 now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
2231
Eric Laurenta1478072015-09-21 17:21:52 -07002232 lock_output_stream(out);
Eric Park244c1572017-04-18 11:36:26 -04002233 if (out->last_write_time_us)
2234 elapsed_time_since_last_write = now - out->last_write_time_us;
2235 sleep_time = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2236 out_get_sample_rate(&stream->common) - elapsed_time_since_last_write;
2237 if (sleep_time > 0) {
2238 usleep(sleep_time);
2239 } else {
2240 // we don't sleep when we exit standby (this is typical for a real alsa buffer).
2241 sleep_time = 0;
2242 }
2243 out->last_write_time_us = now + sleep_time;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002244 pthread_mutex_unlock(&out->lock);
Eric Park244c1572017-04-18 11:36:26 -04002245 // last_write_time_us is an approximation of when the (simulated) alsa
2246 // buffer is believed completely full. The usleep above waits for more space
2247 // in the buffer, but by the end of the sleep the buffer is considered
2248 // topped-off.
2249 //
2250 // On the subsequent out_write(), we measure the elapsed time spent in
2251 // the mixer. This is subtracted from the sleep estimate based on frames,
2252 // thereby accounting for drain in the alsa buffer during mixing.
2253 // This is a crude approximation; we don't handle underruns precisely.
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002254 return bytes;
2255}
2256#endif
2257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2259 size_t bytes)
2260{
2261 struct stream_out *out = (struct stream_out *)stream;
2262 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002263 ssize_t ret = 0;
Vaughn Nf7c7d742016-12-10 18:53:04 -05002264 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002265
Eric Laurenta1478072015-09-21 17:21:52 -07002266 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002267 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002268 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002269 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002271 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002272 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002273 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002274 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002275 goto exit;
2276 }
vivek mehta0d2943f2016-04-29 03:16:47 -07002277
2278 if (last_known_cal_step != -1) {
2279 ALOGD("%s: retry previous failed cal level set", __func__);
2280 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2281 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002282 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002283
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002284 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002285 ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
2286 if (out->send_new_metadata) {
2287 ALOGVV("send new gapless metadata");
2288 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2289 out->send_new_metadata = 0;
2290 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002291 unsigned int avail;
2292 struct timespec tstamp;
2293 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2294 /* Do not limit write size if the available frames count is unknown */
2295 if (ret != 0) {
2296 avail = bytes;
2297 }
2298 if (avail == 0) {
2299 ret = 0;
2300 } else {
2301 if (avail > bytes) {
2302 avail = bytes;
2303 }
2304 ret = compress_write(out->compr, buffer, avail);
2305 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2306 __func__, avail, ret);
2307 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002308
Eric Laurent6e895242013-09-05 16:10:57 -07002309 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002310 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2311 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002312 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002313 compress_start(out->compr);
2314 out->playback_started = 1;
2315 out->offload_state = OFFLOAD_STATE_PLAYING;
2316 }
Vaughn Nf7c7d742016-12-10 18:53:04 -05002317 if (ret < 0) {
2318 log_error_l(&out->error_log, ERROR_CODE_WRITE);
2319 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002320 pthread_mutex_unlock(&out->lock);
2321 return ret;
2322 } else {
Vaughn Nf7c7d742016-12-10 18:53:04 -05002323 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002324 if (out->pcm) {
2325 if (out->muted)
2326 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002327
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002328 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002329
Haynes Mathew George03c40102016-01-29 17:57:48 -08002330 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2331 out->config.rate;
2332 request_out_focus(out, ns);
2333
2334 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2335 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002336 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002337 else
2338 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002339
Haynes Mathew George03c40102016-01-29 17:57:48 -08002340 release_out_focus(out, ns);
Vaughn Nf7c7d742016-12-10 18:53:04 -05002341 } else {
2342 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344 }
2345
2346exit:
Vaughn Nf7c7d742016-12-10 18:53:04 -05002347 // For PCM we always consume the buffer and return #bytes regardless of ret.
2348 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2349 out->written += bytes / (out->config.channels * sizeof(short));
2350 }
2351 long long sleeptime_us = 0;
2352 if (ret != 0) {
2353 log_error_l(&out->error_log, error_code);
2354 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2355 ALOGE_IF(out->pcm != NULL,
2356 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
2357 sleeptime_us = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2358 out_get_sample_rate(&out->stream.common);
2359 // usleep not guaranteed for values over 1 second but we don't limit here.
2360 }
2361 }
2362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363 pthread_mutex_unlock(&out->lock);
2364
2365 if (ret != 0) {
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002366 out_on_error(&out->stream.common);
Vaughn Nf7c7d742016-12-10 18:53:04 -05002367 if (sleeptime_us != 0)
2368 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002369 }
2370 return bytes;
2371}
2372
2373static int out_get_render_position(const struct audio_stream_out *stream,
2374 uint32_t *dsp_frames)
2375{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002376 struct stream_out *out = (struct stream_out *)stream;
2377 *dsp_frames = 0;
2378 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002379 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002380 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002381 unsigned long frames = 0;
2382 // TODO: check return value
2383 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2384 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002385 ALOGVV("%s rendered frames %d sample_rate %d",
2386 __func__, *dsp_frames, out->sample_rate);
2387 }
2388 pthread_mutex_unlock(&out->lock);
2389 return 0;
2390 } else
2391 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002392}
2393
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002394static int out_add_audio_effect(const struct audio_stream *stream __unused,
2395 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002396{
2397 return 0;
2398}
2399
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002400static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2401 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002402{
2403 return 0;
2404}
2405
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002406static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2407 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002408{
2409 return -EINVAL;
2410}
2411
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002412static int out_get_presentation_position(const struct audio_stream_out *stream,
2413 uint64_t *frames, struct timespec *timestamp)
2414{
2415 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002416 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002417 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002418
Eric Laurenta1478072015-09-21 17:21:52 -07002419 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002420
Eric Laurent949a0892013-09-20 09:20:13 -07002421 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2422 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002423 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002424 compress_get_tstamp(out->compr, &dsp_frames,
2425 &out->sample_rate);
2426 ALOGVV("%s rendered frames %ld sample_rate %d",
2427 __func__, dsp_frames, out->sample_rate);
2428 *frames = dsp_frames;
2429 ret = 0;
2430 /* this is the best we can do */
2431 clock_gettime(CLOCK_MONOTONIC, timestamp);
2432 }
2433 } else {
2434 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002435 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002436 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2437 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002438 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002439 // This adjustment accounts for buffering after app processor.
2440 // It is based on estimated DSP latency per use case, rather than exact.
2441 signed_frames -=
2442 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2443
Eric Laurent949a0892013-09-20 09:20:13 -07002444 // It would be unusual for this value to be negative, but check just in case ...
2445 if (signed_frames >= 0) {
2446 *frames = signed_frames;
2447 ret = 0;
2448 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002449 }
2450 }
2451 }
2452
2453 pthread_mutex_unlock(&out->lock);
2454
2455 return ret;
2456}
2457
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002458static int out_set_callback(struct audio_stream_out *stream,
2459 stream_callback_t callback, void *cookie)
2460{
2461 struct stream_out *out = (struct stream_out *)stream;
2462
2463 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002464 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002465 out->offload_callback = callback;
2466 out->offload_cookie = cookie;
2467 pthread_mutex_unlock(&out->lock);
2468 return 0;
2469}
2470
2471static int out_pause(struct audio_stream_out* stream)
2472{
2473 struct stream_out *out = (struct stream_out *)stream;
2474 int status = -ENOSYS;
2475 ALOGV("%s", __func__);
2476 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002477 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002478 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2479 status = compress_pause(out->compr);
2480 out->offload_state = OFFLOAD_STATE_PAUSED;
2481 }
2482 pthread_mutex_unlock(&out->lock);
2483 }
2484 return status;
2485}
2486
2487static int out_resume(struct audio_stream_out* stream)
2488{
2489 struct stream_out *out = (struct stream_out *)stream;
2490 int status = -ENOSYS;
2491 ALOGV("%s", __func__);
2492 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2493 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002494 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002495 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2496 status = compress_resume(out->compr);
2497 out->offload_state = OFFLOAD_STATE_PLAYING;
2498 }
2499 pthread_mutex_unlock(&out->lock);
2500 }
2501 return status;
2502}
2503
2504static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2505{
2506 struct stream_out *out = (struct stream_out *)stream;
2507 int status = -ENOSYS;
2508 ALOGV("%s", __func__);
2509 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002510 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002511 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2512 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2513 else
2514 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2515 pthread_mutex_unlock(&out->lock);
2516 }
2517 return status;
2518}
2519
2520static int out_flush(struct audio_stream_out* stream)
2521{
2522 struct stream_out *out = (struct stream_out *)stream;
2523 ALOGV("%s", __func__);
2524 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002525 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002526 stop_compressed_output_l(out);
2527 pthread_mutex_unlock(&out->lock);
2528 return 0;
2529 }
2530 return -ENOSYS;
2531}
2532
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533/** audio_stream_in implementation **/
2534static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2535{
2536 struct stream_in *in = (struct stream_in *)stream;
2537
2538 return in->config.rate;
2539}
2540
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002541static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542{
2543 return -ENOSYS;
2544}
2545
2546static size_t in_get_buffer_size(const struct audio_stream *stream)
2547{
2548 struct stream_in *in = (struct stream_in *)stream;
2549
Haynes Mathew George03c40102016-01-29 17:57:48 -08002550 return in->config.period_size * in->af_period_multiplier *
2551 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002552}
2553
2554static uint32_t in_get_channels(const struct audio_stream *stream)
2555{
2556 struct stream_in *in = (struct stream_in *)stream;
2557
2558 return in->channel_mask;
2559}
2560
vivek mehta4ed66e62016-04-15 23:33:34 -07002561static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002562{
vivek mehta4ed66e62016-04-15 23:33:34 -07002563 struct stream_in *in = (struct stream_in *)stream;
2564 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565}
2566
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002567static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568{
2569 return -ENOSYS;
2570}
2571
2572static int in_standby(struct audio_stream *stream)
2573{
2574 struct stream_in *in = (struct stream_in *)stream;
2575 struct audio_device *adev = in->dev;
2576 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07002577 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002578
2579 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002580
2581 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002582 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002583 audio_extn_sound_trigger_stop_lab(in);
2584 in->standby = true;
2585 }
2586
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002588 if (adev->adm_deregister_stream)
2589 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2590
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002591 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002593 if (in->pcm) {
2594 pcm_close(in->pcm);
2595 in->pcm = NULL;
2596 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002597 adev->enable_voicerx = false;
2598 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002600 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601 }
2602 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002603 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604 return status;
2605}
2606
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002607static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608{
2609 return 0;
2610}
2611
2612static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2613{
2614 struct stream_in *in = (struct stream_in *)stream;
2615 struct audio_device *adev = in->dev;
2616 struct str_parms *parms;
2617 char *str;
2618 char value[32];
2619 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002620 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621
Eric Laurent994a6932013-07-17 11:51:42 -07002622 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002623 parms = str_parms_create_str(kvpairs);
2624
2625 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2626
Eric Laurenta1478072015-09-21 17:21:52 -07002627 lock_input_stream(in);
2628
Eric Laurent150dbfe2013-02-27 14:31:02 -08002629 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630 if (ret >= 0) {
2631 val = atoi(value);
2632 /* no audio source uses val == 0 */
2633 if ((in->source != val) && (val != 0)) {
2634 in->source = val;
2635 }
2636 }
2637
2638 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002639
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002640 if (ret >= 0) {
2641 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002642 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002643 in->device = val;
2644 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002645 if (!in->standby) {
2646 ALOGV("update input routing change");
2647 in->routing_change = true;
2648 select_devices(adev, in->usecase);
2649 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650 }
2651 }
2652
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002654 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655
2656 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002657 ALOGV("%s: exit: status(%d)", __func__, status);
2658 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659}
2660
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002661static char* in_get_parameters(const struct audio_stream *stream __unused,
2662 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663{
2664 return strdup("");
2665}
2666
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002667static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668{
2669 return 0;
2670}
2671
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002672static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2673{
2674 if (!stream || !parms)
2675 return;
2676
2677 struct stream_in *in = (struct stream_in *)stream;
2678 struct audio_device *adev = in->dev;
2679
2680 card_status_t status;
2681 int card;
2682 if (parse_snd_card_status(parms, &card, &status) < 0)
2683 return;
2684
2685 pthread_mutex_lock(&adev->lock);
2686 bool valid_cb = (card == adev->snd_card);
2687 pthread_mutex_unlock(&adev->lock);
2688
2689 if (!valid_cb)
2690 return;
2691
2692 lock_input_stream(in);
2693 if (in->card_status != status)
2694 in->card_status = status;
2695 pthread_mutex_unlock(&in->lock);
2696
2697 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2698 use_case_table[in->usecase],
2699 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2700
2701 // a better solution would be to report error back to AF and let
2702 // it put the stream to standby
2703 if (status == CARD_STATUS_OFFLINE)
2704 in_standby(&in->stream.common);
2705
2706 return;
2707}
2708
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2710 size_t bytes)
2711{
2712 struct stream_in *in = (struct stream_in *)stream;
2713 struct audio_device *adev = in->dev;
2714 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002715 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716
Eric Laurenta1478072015-09-21 17:21:52 -07002717 lock_input_stream(in);
2718
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002719 if (in->is_st_session) {
2720 ALOGVV(" %s: reading on st session bytes=%d", __func__, bytes);
2721 /* Read from sound trigger HAL */
2722 audio_extn_sound_trigger_read(in, buffer, bytes);
2723 pthread_mutex_unlock(&in->lock);
2724 return bytes;
2725 }
2726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002728 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002730 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002732 goto exit;
2733 }
2734 in->standby = 0;
2735 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736
Haynes Mathew George03c40102016-01-29 17:57:48 -08002737 //what's the duration requested by the client?
2738 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2739 in->config.rate;
2740 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002741
Haynes Mathew George03c40102016-01-29 17:57:48 -08002742 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002744 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002745 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002746 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002747 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002748 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002749 if (ret < 0) {
2750 ALOGE("Failed to read w/err %s", strerror(errno));
2751 ret = -errno;
2752 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002753 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2754 if (bytes % 4 == 0) {
2755 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2756 int_buf_stream = buffer;
2757 for (size_t itt=0; itt < bytes/4 ; itt++) {
2758 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002759 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002760 } else {
2761 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2762 ret = -EINVAL;
2763 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002764 }
2765 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766 }
2767
Haynes Mathew George03c40102016-01-29 17:57:48 -08002768 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002770 /*
2771 * Instead of writing zeroes here, we could trust the hardware
2772 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002773 * 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 -08002774 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002775 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776 memset(buffer, 0, bytes);
2777
2778exit:
2779 pthread_mutex_unlock(&in->lock);
2780
2781 if (ret != 0) {
2782 in_standby(&in->stream.common);
2783 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002784 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002785 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002786 memset(buffer, 0, bytes); // clear return data
2787 }
2788 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002789 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002790 }
2791 return bytes;
2792}
2793
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002794static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795{
2796 return 0;
2797}
2798
Andy Hung6ebe5962016-01-15 17:46:57 -08002799static int in_get_capture_position(const struct audio_stream_in *stream,
2800 int64_t *frames, int64_t *time)
2801{
2802 if (stream == NULL || frames == NULL || time == NULL) {
2803 return -EINVAL;
2804 }
2805 struct stream_in *in = (struct stream_in *)stream;
2806 int ret = -ENOSYS;
2807
2808 lock_input_stream(in);
2809 if (in->pcm) {
2810 struct timespec timestamp;
2811 unsigned int avail;
2812 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2813 *frames = in->frames_read + avail;
2814 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2815 ret = 0;
2816 }
2817 }
2818 pthread_mutex_unlock(&in->lock);
2819 return ret;
2820}
2821
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002822static int add_remove_audio_effect(const struct audio_stream *stream,
2823 effect_handle_t effect,
2824 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002826 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002827 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002828 int status = 0;
2829 effect_descriptor_t desc;
2830
2831 status = (*effect)->get_descriptor(effect, &desc);
2832 if (status != 0)
2833 return status;
2834
Eric Laurenta1478072015-09-21 17:21:52 -07002835 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002836 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002837 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002838 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002839 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002840 in->enable_aec != enable &&
2841 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2842 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002843 if (!enable)
2844 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002845 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2846 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2847 adev->enable_voicerx = enable;
2848 struct audio_usecase *usecase;
2849 struct listnode *node;
2850 list_for_each(node, &adev->usecase_list) {
2851 usecase = node_to_item(node, struct audio_usecase, list);
2852 if (usecase->type == PCM_PLAYBACK) {
2853 select_devices(adev, usecase->id);
2854 break;
2855 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002856 }
2857 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002858 if (!in->standby)
2859 select_devices(in->dev, in->usecase);
2860 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07002861 if (in->enable_ns != enable &&
2862 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2863 in->enable_ns = enable;
2864 if (!in->standby)
2865 select_devices(in->dev, in->usecase);
2866 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002867 pthread_mutex_unlock(&in->dev->lock);
2868 pthread_mutex_unlock(&in->lock);
2869
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870 return 0;
2871}
2872
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002873static int in_add_audio_effect(const struct audio_stream *stream,
2874 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875{
Eric Laurent994a6932013-07-17 11:51:42 -07002876 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002877 return add_remove_audio_effect(stream, effect, true);
2878}
2879
2880static int in_remove_audio_effect(const struct audio_stream *stream,
2881 effect_handle_t effect)
2882{
Eric Laurent994a6932013-07-17 11:51:42 -07002883 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002884 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002885}
2886
2887static int adev_open_output_stream(struct audio_hw_device *dev,
2888 audio_io_handle_t handle,
2889 audio_devices_t devices,
2890 audio_output_flags_t flags,
2891 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07002892 struct audio_stream_out **stream_out,
2893 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002894{
2895 struct audio_device *adev = (struct audio_device *)dev;
2896 struct stream_out *out;
2897 int i, ret;
2898
Eric Laurent994a6932013-07-17 11:51:42 -07002899 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002900 __func__, config->sample_rate, config->channel_mask, devices, flags);
2901 *stream_out = NULL;
2902 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2903
2904 if (devices == AUDIO_DEVICE_NONE)
2905 devices = AUDIO_DEVICE_OUT_SPEAKER;
2906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002907 out->flags = flags;
2908 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002909 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002910 out->format = config->format;
2911 out->sample_rate = config->sample_rate;
2912 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2913 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002914 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002915
2916 /* Init use case and pcm_config */
2917 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07002918 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002919 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002920 pthread_mutex_lock(&adev->lock);
2921 ret = read_hdmi_channel_masks(out);
2922 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002923 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002924 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002925
2926 if (config->sample_rate == 0)
2927 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2928 if (config->channel_mask == 0)
2929 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08002930 if (config->format == AUDIO_FORMAT_DEFAULT)
2931 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002932
2933 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002934 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08002935 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002936 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2937 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002939 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002940 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002941 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07002942 pthread_mutex_lock(&adev->lock);
2943 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
2944 pthread_mutex_unlock(&adev->lock);
2945
2946 // reject offload during card offline to allow
2947 // fallback to s/w paths
2948 if (offline) {
2949 ret = -ENODEV;
2950 goto error_open;
2951 }
2952
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002953 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2954 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2955 ALOGE("%s: Unsupported Offload information", __func__);
2956 ret = -EINVAL;
2957 goto error_open;
2958 }
2959 if (!is_supported_format(config->offload_info.format)) {
2960 ALOGE("%s: Unsupported audio format", __func__);
2961 ret = -EINVAL;
2962 goto error_open;
2963 }
2964
2965 out->compr_config.codec = (struct snd_codec *)
2966 calloc(1, sizeof(struct snd_codec));
2967
2968 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
2969 if (config->offload_info.channel_mask)
2970 out->channel_mask = config->offload_info.channel_mask;
2971 else if (config->channel_mask)
2972 out->channel_mask = config->channel_mask;
2973 out->format = config->offload_info.format;
2974 out->sample_rate = config->offload_info.sample_rate;
2975
2976 out->stream.set_callback = out_set_callback;
2977 out->stream.pause = out_pause;
2978 out->stream.resume = out_resume;
2979 out->stream.drain = out_drain;
2980 out->stream.flush = out_flush;
2981
2982 out->compr_config.codec->id =
2983 get_snd_codec_id(config->offload_info.format);
2984 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
2985 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07002986 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002987 out->compr_config.codec->bit_rate =
2988 config->offload_info.bit_rate;
2989 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002990 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002991 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
2992
2993 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2994 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002995
2996 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002997 create_offload_callback_thread(out);
2998 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2999 __func__, config->offload_info.version,
3000 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003001 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3002 if (config->sample_rate == 0)
3003 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3004 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3005 config->sample_rate != 8000) {
3006 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3007 ret = -EINVAL;
3008 goto error_open;
3009 }
3010 out->sample_rate = config->sample_rate;
3011 out->config.rate = config->sample_rate;
3012 if (config->format == AUDIO_FORMAT_DEFAULT)
3013 config->format = AUDIO_FORMAT_PCM_16_BIT;
3014 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3015 config->format = AUDIO_FORMAT_PCM_16_BIT;
3016 ret = -EINVAL;
3017 goto error_open;
3018 }
3019 out->format = config->format;
3020 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3021 out->config = pcm_config_afe_proxy_playback;
3022 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003024 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3025 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3026 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003027 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3028 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3029 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003030 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3031 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003032 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
3033 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3034 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003035 } else {
3036 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3037 out->config = pcm_config_low_latency;
3038 }
3039 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3040 if (k_enable_extended_precision
3041 && pcm_params_format_test(adev->use_case_table[out->usecase],
3042 pcm_format_from_audio_format(config->format))) {
3043 out->config.format = pcm_format_from_audio_format(config->format);
3044 /* out->format already set to config->format */
3045 } else {
3046 /* deny the externally proposed config format
3047 * and use the one specified in audio_hw layer configuration.
3048 * Note: out->format is returned by out->stream.common.get_format()
3049 * and is used to set config->format in the code several lines below.
3050 */
3051 out->format = audio_format_from_pcm_format(out->config.format);
3052 }
3053 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003054 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003056 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3057 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003059 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003060 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003061 adev->primary_output = out;
3062 else {
3063 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003064 ret = -EEXIST;
3065 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003066 }
3067 }
3068
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069 /* Check if this usecase is already existing */
3070 pthread_mutex_lock(&adev->lock);
3071 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3072 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003074 ret = -EEXIST;
3075 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076 }
3077 pthread_mutex_unlock(&adev->lock);
3078
3079 out->stream.common.get_sample_rate = out_get_sample_rate;
3080 out->stream.common.set_sample_rate = out_set_sample_rate;
3081 out->stream.common.get_buffer_size = out_get_buffer_size;
3082 out->stream.common.get_channels = out_get_channels;
3083 out->stream.common.get_format = out_get_format;
3084 out->stream.common.set_format = out_set_format;
3085 out->stream.common.standby = out_standby;
3086 out->stream.common.dump = out_dump;
3087 out->stream.common.set_parameters = out_set_parameters;
3088 out->stream.common.get_parameters = out_get_parameters;
3089 out->stream.common.add_audio_effect = out_add_audio_effect;
3090 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3091 out->stream.get_latency = out_get_latency;
3092 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003093#ifdef NO_AUDIO_OUT
3094 out->stream.write = out_write_for_no_output;
3095#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003097#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098 out->stream.get_render_position = out_get_render_position;
3099 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003100 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101
Haynes Mathew George03c40102016-01-29 17:57:48 -08003102 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003103 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003104 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003105 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003107 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003108 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003109 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111 config->format = out->stream.common.get_format(&out->stream.common);
3112 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3113 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3114
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003115
3116 /*
3117 By locking output stream before registering, we allow the callback
3118 to update stream's state only after stream's initial state is set to
3119 adev state.
3120 */
3121 lock_output_stream(out);
3122 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3123 pthread_mutex_lock(&adev->lock);
3124 out->card_status = adev->card_status;
3125 pthread_mutex_unlock(&adev->lock);
3126 pthread_mutex_unlock(&out->lock);
3127
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003129 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003131
3132error_open:
3133 free(out);
3134 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003135 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003136 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137}
3138
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003139static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140 struct audio_stream_out *stream)
3141{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003142 struct stream_out *out = (struct stream_out *)stream;
3143 struct audio_device *adev = out->dev;
3144
Eric Laurent994a6932013-07-17 11:51:42 -07003145 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003146
3147 // must deregister from sndmonitor first to prevent races
3148 // between the callback and close_stream
3149 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003151 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3152 destroy_offload_callback_thread(out);
3153
3154 if (out->compr_config.codec != NULL)
3155 free(out->compr_config.codec);
3156 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003157
3158 if (adev->voice_tx_output == out)
3159 adev->voice_tx_output = NULL;
3160
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003161 pthread_cond_destroy(&out->cond);
3162 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003163 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003164 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165}
3166
3167static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3168{
3169 struct audio_device *adev = (struct audio_device *)dev;
3170 struct str_parms *parms;
3171 char *str;
3172 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003173 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003175 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176
Joe Onorato188b6222016-03-01 11:02:27 -08003177 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003178
3179 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180
3181 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003182 status = voice_set_parameters(adev, parms);
3183 if (status != 0) {
3184 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 }
3186
3187 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3188 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003189 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3191 adev->bluetooth_nrec = true;
3192 else
3193 adev->bluetooth_nrec = false;
3194 }
3195
3196 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3197 if (ret >= 0) {
3198 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3199 adev->screen_off = false;
3200 else
3201 adev->screen_off = true;
3202 }
3203
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003204 ret = str_parms_get_int(parms, "rotation", &val);
3205 if (ret >= 0) {
3206 bool reverse_speakers = false;
3207 switch(val) {
3208 // FIXME: note that the code below assumes that the speakers are in the correct placement
3209 // relative to the user when the device is rotated 90deg from its default rotation. This
3210 // assumption is device-specific, not platform-specific like this code.
3211 case 270:
3212 reverse_speakers = true;
3213 break;
3214 case 0:
3215 case 90:
3216 case 180:
3217 break;
3218 default:
3219 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003220 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003221 }
Eric Laurent03f09432014-03-25 18:09:11 -07003222 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003223 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003224 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003225 }
3226
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003227 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3228 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003229 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003230 }
3231
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003232 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003233done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003235 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003236 ALOGV("%s: exit with code(%d)", __func__, status);
3237 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238}
3239
3240static char* adev_get_parameters(const struct audio_hw_device *dev,
3241 const char *keys)
3242{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003243 struct audio_device *adev = (struct audio_device *)dev;
3244 struct str_parms *reply = str_parms_create();
3245 struct str_parms *query = str_parms_create_str(keys);
3246 char *str;
3247
3248 pthread_mutex_lock(&adev->lock);
3249
3250 voice_get_parameters(adev, query, reply);
3251 str = str_parms_to_str(reply);
3252 str_parms_destroy(query);
3253 str_parms_destroy(reply);
3254
3255 pthread_mutex_unlock(&adev->lock);
3256 ALOGV("%s: exit: returns - %s", __func__, str);
3257 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003258}
3259
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003260static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261{
3262 return 0;
3263}
3264
Haynes Mathew George5191a852013-09-11 14:19:36 -07003265static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3266{
3267 int ret;
3268 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003269
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003270 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3271
Haynes Mathew George5191a852013-09-11 14:19:36 -07003272 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003273 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003274 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003275
Haynes Mathew George5191a852013-09-11 14:19:36 -07003276 return ret;
3277}
3278
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003279static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003280{
3281 return -ENOSYS;
3282}
3283
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003284static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3285 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003286{
3287 return -ENOSYS;
3288}
3289
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003290static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003291{
3292 return -ENOSYS;
3293}
3294
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003295static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296{
3297 return -ENOSYS;
3298}
3299
3300static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3301{
3302 struct audio_device *adev = (struct audio_device *)dev;
3303
3304 pthread_mutex_lock(&adev->lock);
3305 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003306 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003308 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3309 voice_is_in_call(adev)) {
3310 voice_stop_call(adev);
3311 adev->current_call_output = NULL;
3312 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313 }
3314 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003315
3316 audio_extn_extspk_set_mode(adev->extspk, mode);
3317
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318 return 0;
3319}
3320
3321static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3322{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003323 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325
Eric Laurent2bafff12016-03-17 12:17:23 -07003326 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003327 pthread_mutex_lock(&adev->lock);
Eric Park244c1572017-04-18 11:36:26 -04003328 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3329 ret = audio_extn_hfp_set_mic_mute(adev, state);
3330 } else {
3331 ret = voice_set_mic_mute(adev, state);
3332 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003333 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003334 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003335
3336 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337}
3338
3339static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3340{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003341 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003342 return 0;
3343}
3344
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003345static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003346 const struct audio_config *config)
3347{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003348 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003350 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3351 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352}
3353
3354static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003355 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356 audio_devices_t devices,
3357 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003358 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003359 audio_input_flags_t flags,
3360 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003361 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362{
3363 struct audio_device *adev = (struct audio_device *)dev;
3364 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003365 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003366 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003367 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003368
Eric Laurent994a6932013-07-17 11:51:42 -07003369 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370 *stream_in = NULL;
3371 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3372 return -EINVAL;
3373
Eric Park244c1572017-04-18 11:36:26 -04003374 if (audio_extn_tfa_98xx_is_supported() && (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
3375 return -EINVAL;
3376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3378
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003379 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003380 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382 in->stream.common.get_sample_rate = in_get_sample_rate;
3383 in->stream.common.set_sample_rate = in_set_sample_rate;
3384 in->stream.common.get_buffer_size = in_get_buffer_size;
3385 in->stream.common.get_channels = in_get_channels;
3386 in->stream.common.get_format = in_get_format;
3387 in->stream.common.set_format = in_set_format;
3388 in->stream.common.standby = in_standby;
3389 in->stream.common.dump = in_dump;
3390 in->stream.common.set_parameters = in_set_parameters;
3391 in->stream.common.get_parameters = in_get_parameters;
3392 in->stream.common.add_audio_effect = in_add_audio_effect;
3393 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3394 in->stream.set_gain = in_set_gain;
3395 in->stream.read = in_read;
3396 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003397 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003398
3399 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003400 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402 in->standby = 1;
3403 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003404 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003405 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406
vivek mehta57ff9b52016-04-28 14:13:08 -07003407 // restrict 24 bit capture for unprocessed source only
3408 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3409 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003410 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003411 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3412 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3413 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3414 bool ret_error = false;
3415 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3416 from HAL is 8_24
3417 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3418 8_24 return error indicating supported format is 8_24
3419 *> In case of any other source requesting 24 bit or float return error
3420 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003421
vivek mehta57ff9b52016-04-28 14:13:08 -07003422 on error flinger will retry with supported format passed
3423 */
3424 if (source != AUDIO_SOURCE_UNPROCESSED) {
3425 config->format = AUDIO_FORMAT_PCM_16_BIT;
3426 ret_error = true;
3427 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3428 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3429 ret_error = true;
3430 }
3431
3432 if (ret_error) {
3433 ret = -EINVAL;
3434 goto err_open;
3435 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003436 }
3437
vivek mehta57ff9b52016-04-28 14:13:08 -07003438 in->format = config->format;
3439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003441 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3442 if (config->sample_rate == 0)
3443 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3444 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3445 config->sample_rate != 8000) {
3446 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3447 ret = -EINVAL;
3448 goto err_open;
3449 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003450
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003451 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3452 config->format = AUDIO_FORMAT_PCM_16_BIT;
3453 ret = -EINVAL;
3454 goto err_open;
3455 }
3456
3457 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3458 in->config = pcm_config_afe_proxy_record;
3459 } else {
3460 in->usecase = USECASE_AUDIO_RECORD;
3461 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3462 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3463 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003464#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003465 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003466#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003467 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003468 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003469
Haynes Mathew George03c40102016-01-29 17:57:48 -08003470 in->config = in->realtime ? pcm_config_audio_capture_rt :
3471 pcm_config_audio_capture;
3472
vivek mehta4ed66e62016-04-15 23:33:34 -07003473 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3474 in->config.format = PCM_FORMAT_S24_LE;
3475
Haynes Mathew George03c40102016-01-29 17:57:48 -08003476 if (!in->realtime) {
3477 frame_size = audio_stream_in_frame_size(&in->stream);
3478 buffer_size = get_input_buffer_size(config->sample_rate,
3479 config->format,
3480 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003481 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003482 in->config.period_size = buffer_size / frame_size;
3483 } // period size is left untouched for rt mode playback
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003484 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003485
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486 in->config.channels = channel_count;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003487 if (in->realtime) {
3488 in->af_period_multiplier = af_period_multiplier;
3489 } else {
3490 in->config.rate = config->sample_rate;
3491 in->af_period_multiplier = 1;
3492 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003493
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003494 /* This stream could be for sound trigger lab,
3495 get sound trigger pcm if present */
3496 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003498 lock_input_stream(in);
3499 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3500 pthread_mutex_lock(&adev->lock);
3501 in->card_status = adev->card_status;
3502 pthread_mutex_unlock(&adev->lock);
3503 pthread_mutex_unlock(&in->lock);
3504
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003506 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507 return 0;
3508
3509err_open:
3510 free(in);
3511 *stream_in = NULL;
3512 return ret;
3513}
3514
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003515static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516 struct audio_stream_in *stream)
3517{
Eric Laurent994a6932013-07-17 11:51:42 -07003518 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003519
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003520 // must deregister from sndmonitor first to prevent races
3521 // between the callback and close_stream
3522 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523 in_standby(&stream->common);
3524 free(stream);
3525
3526 return;
3527}
3528
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003529static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530{
3531 return 0;
3532}
3533
Andy Hung31aca912014-03-20 17:14:59 -07003534/* verifies input and output devices and their capabilities.
3535 *
3536 * This verification is required when enabling extended bit-depth or
3537 * sampling rates, as not all qcom products support it.
3538 *
3539 * Suitable for calling only on initialization such as adev_open().
3540 * It fills the audio_device use_case_table[] array.
3541 *
3542 * Has a side-effect that it needs to configure audio routing / devices
3543 * in order to power up the devices and read the device parameters.
3544 * It does not acquire any hw device lock. Should restore the devices
3545 * back to "normal state" upon completion.
3546 */
3547static int adev_verify_devices(struct audio_device *adev)
3548{
3549 /* enumeration is a bit difficult because one really wants to pull
3550 * the use_case, device id, etc from the hidden pcm_device_table[].
3551 * In this case there are the following use cases and device ids.
3552 *
3553 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3554 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3555 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3556 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3557 * [USECASE_AUDIO_RECORD] = {0, 0},
3558 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3559 * [USECASE_VOICE_CALL] = {2, 2},
3560 *
3561 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3562 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3563 */
3564
3565 /* should be the usecases enabled in adev_open_input_stream() */
3566 static const int test_in_usecases[] = {
3567 USECASE_AUDIO_RECORD,
3568 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3569 };
3570 /* should be the usecases enabled in adev_open_output_stream()*/
3571 static const int test_out_usecases[] = {
3572 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3573 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3574 };
3575 static const usecase_type_t usecase_type_by_dir[] = {
3576 PCM_PLAYBACK,
3577 PCM_CAPTURE,
3578 };
3579 static const unsigned flags_by_dir[] = {
3580 PCM_OUT,
3581 PCM_IN,
3582 };
3583
3584 size_t i;
3585 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003586 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003587 char info[512]; /* for possible debug info */
3588
3589 for (dir = 0; dir < 2; ++dir) {
3590 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3591 const unsigned flags_dir = flags_by_dir[dir];
3592 const size_t testsize =
3593 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3594 const int *testcases =
3595 dir ? test_in_usecases : test_out_usecases;
3596 const audio_devices_t audio_device =
3597 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3598
3599 for (i = 0; i < testsize; ++i) {
3600 const audio_usecase_t audio_usecase = testcases[i];
3601 int device_id;
3602 snd_device_t snd_device;
3603 struct pcm_params **pparams;
3604 struct stream_out out;
3605 struct stream_in in;
3606 struct audio_usecase uc_info;
3607 int retval;
3608
3609 pparams = &adev->use_case_table[audio_usecase];
3610 pcm_params_free(*pparams); /* can accept null input */
3611 *pparams = NULL;
3612
3613 /* find the device ID for the use case (signed, for error) */
3614 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3615 if (device_id < 0)
3616 continue;
3617
3618 /* prepare structures for device probing */
3619 memset(&uc_info, 0, sizeof(uc_info));
3620 uc_info.id = audio_usecase;
3621 uc_info.type = usecase_type;
3622 if (dir) {
3623 adev->active_input = &in;
3624 memset(&in, 0, sizeof(in));
3625 in.device = audio_device;
3626 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3627 uc_info.stream.in = &in;
3628 } else {
3629 adev->active_input = NULL;
3630 }
3631 memset(&out, 0, sizeof(out));
3632 out.devices = audio_device; /* only field needed in select_devices */
3633 uc_info.stream.out = &out;
3634 uc_info.devices = audio_device;
3635 uc_info.in_snd_device = SND_DEVICE_NONE;
3636 uc_info.out_snd_device = SND_DEVICE_NONE;
3637 list_add_tail(&adev->usecase_list, &uc_info.list);
3638
3639 /* select device - similar to start_(in/out)put_stream() */
3640 retval = select_devices(adev, audio_usecase);
3641 if (retval >= 0) {
3642 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3643#if LOG_NDEBUG == 0
3644 if (*pparams) {
3645 ALOGV("%s: (%s) card %d device %d", __func__,
3646 dir ? "input" : "output", card_id, device_id);
3647 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07003648 } else {
3649 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3650 }
3651#endif
3652 }
3653
3654 /* deselect device - similar to stop_(in/out)put_stream() */
3655 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07003656 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07003657 /* 2. Disable the rx device */
3658 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07003659 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07003660 list_remove(&uc_info.list);
3661 }
3662 }
3663 adev->active_input = NULL; /* restore adev state */
3664 return 0;
3665}
3666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667static int adev_close(hw_device_t *device)
3668{
Andy Hung31aca912014-03-20 17:14:59 -07003669 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003671
3672 if (!adev)
3673 return 0;
3674
Eric Park244c1572017-04-18 11:36:26 -04003675 audio_extn_tfa_98xx_deinit();
3676
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003677 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003678 pthread_mutex_lock(&adev_init_lock);
3679
3680 if ((--audio_device_ref_count) == 0) {
3681 audio_route_free(adev->audio_route);
3682 free(adev->snd_dev_ref_cnt);
3683 platform_deinit(adev->platform);
3684 audio_extn_extspk_deinit(adev->extspk);
3685 audio_extn_sound_trigger_deinit(adev);
3686 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3687 pcm_params_free(adev->use_case_table[i]);
3688 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003689 if (adev->adm_deinit)
3690 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003691 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07003692 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07003693
3694 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003695
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696 return 0;
3697}
3698
Glenn Kasten4f993392014-05-14 07:30:48 -07003699/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3700 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3701 * just that it _might_ work.
3702 */
3703static int period_size_is_plausible_for_low_latency(int period_size)
3704{
3705 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003706 case 48:
3707 case 96:
3708 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07003709 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003710 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07003711 case 240:
3712 case 320:
3713 case 480:
3714 return 1;
3715 default:
3716 return 0;
3717 }
3718}
3719
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003720static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
3721{
3722 int card;
3723 card_status_t status;
3724
3725 if (!parms)
3726 return;
3727
3728 if (parse_snd_card_status(parms, &card, &status) < 0)
3729 return;
3730
3731 pthread_mutex_lock(&adev->lock);
3732 bool valid_cb = (card == adev->snd_card);
3733 if (valid_cb) {
3734 if (adev->card_status != status) {
3735 adev->card_status = status;
3736 platform_snd_card_update(adev->platform, status);
3737 }
3738 }
3739 pthread_mutex_unlock(&adev->lock);
3740 return;
3741}
3742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743static int adev_open(const hw_module_t *module, const char *name,
3744 hw_device_t **device)
3745{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003746 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747
Eric Laurent2bafff12016-03-17 12:17:23 -07003748 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003750 pthread_mutex_lock(&adev_init_lock);
3751 if (audio_device_ref_count != 0) {
3752 *device = &adev->device.common;
3753 audio_device_ref_count++;
3754 ALOGV("%s: returning existing instance of adev", __func__);
3755 ALOGV("%s: exit", __func__);
3756 pthread_mutex_unlock(&adev_init_lock);
3757 return 0;
3758 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759 adev = calloc(1, sizeof(struct audio_device));
3760
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003761 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3762
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3764 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3765 adev->device.common.module = (struct hw_module_t *)module;
3766 adev->device.common.close = adev_close;
3767
3768 adev->device.init_check = adev_init_check;
3769 adev->device.set_voice_volume = adev_set_voice_volume;
3770 adev->device.set_master_volume = adev_set_master_volume;
3771 adev->device.get_master_volume = adev_get_master_volume;
3772 adev->device.set_master_mute = adev_set_master_mute;
3773 adev->device.get_master_mute = adev_get_master_mute;
3774 adev->device.set_mode = adev_set_mode;
3775 adev->device.set_mic_mute = adev_set_mic_mute;
3776 adev->device.get_mic_mute = adev_get_mic_mute;
3777 adev->device.set_parameters = adev_set_parameters;
3778 adev->device.get_parameters = adev_get_parameters;
3779 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3780 adev->device.open_output_stream = adev_open_output_stream;
3781 adev->device.close_output_stream = adev_close_output_stream;
3782 adev->device.open_input_stream = adev_open_input_stream;
3783 adev->device.close_input_stream = adev_close_input_stream;
3784 adev->device.dump = adev_dump;
3785
3786 /* Set the default route before the PCM stream is opened */
3787 pthread_mutex_lock(&adev->lock);
3788 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003789 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003790 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003791 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003792 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003793 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003794 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003795 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003796 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797 pthread_mutex_unlock(&adev->lock);
3798
3799 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003800 adev->platform = platform_init(adev);
3801 if (!adev->platform) {
3802 free(adev->snd_dev_ref_cnt);
3803 free(adev);
3804 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3805 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003806 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003807 return -EINVAL;
3808 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05003809 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003810 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003811
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003812 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3813 if (adev->visualizer_lib == NULL) {
3814 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3815 } else {
3816 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3817 adev->visualizer_start_output =
3818 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3819 "visualizer_hal_start_output");
3820 adev->visualizer_stop_output =
3821 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3822 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07003823 }
3824
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003825 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3826 if (adev->offload_effects_lib == NULL) {
3827 ALOGW("%s: DLOPEN failed for %s", __func__,
3828 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3829 } else {
3830 ALOGV("%s: DLOPEN successful for %s", __func__,
3831 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3832 adev->offload_effects_start_output =
3833 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3834 "offload_effects_bundle_hal_start_output");
3835 adev->offload_effects_stop_output =
3836 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3837 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07003838 }
3839
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003840 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3841 if (adev->adm_lib == NULL) {
3842 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3843 } else {
3844 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3845 adev->adm_init = (adm_init_t)
3846 dlsym(adev->adm_lib, "adm_init");
3847 adev->adm_deinit = (adm_deinit_t)
3848 dlsym(adev->adm_lib, "adm_deinit");
3849 adev->adm_register_input_stream = (adm_register_input_stream_t)
3850 dlsym(adev->adm_lib, "adm_register_input_stream");
3851 adev->adm_register_output_stream = (adm_register_output_stream_t)
3852 dlsym(adev->adm_lib, "adm_register_output_stream");
3853 adev->adm_deregister_stream = (adm_deregister_stream_t)
3854 dlsym(adev->adm_lib, "adm_deregister_stream");
3855 adev->adm_request_focus = (adm_request_focus_t)
3856 dlsym(adev->adm_lib, "adm_request_focus");
3857 adev->adm_abandon_focus = (adm_abandon_focus_t)
3858 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08003859 adev->adm_set_config = (adm_set_config_t)
3860 dlsym(adev->adm_lib, "adm_set_config");
3861 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
3862 dlsym(adev->adm_lib, "adm_request_focus_v2");
3863 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
3864 dlsym(adev->adm_lib, "adm_is_noirq_avail");
3865 adev->adm_on_routing_change = (adm_on_routing_change_t)
3866 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003867 }
3868
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003869 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003870 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003871
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003872 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003873
Andy Hung31aca912014-03-20 17:14:59 -07003874 if (k_enable_extended_precision)
3875 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003876
Glenn Kasten4f993392014-05-14 07:30:48 -07003877 char value[PROPERTY_VALUE_MAX];
3878 int trial;
3879 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3880 trial = atoi(value);
3881 if (period_size_is_plausible_for_low_latency(trial)) {
3882 pcm_config_low_latency.period_size = trial;
3883 pcm_config_low_latency.start_threshold = trial / 4;
3884 pcm_config_low_latency.avail_min = trial / 4;
3885 configured_low_latency_capture_period_size = trial;
3886 }
3887 }
3888 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3889 trial = atoi(value);
3890 if (period_size_is_plausible_for_low_latency(trial)) {
3891 configured_low_latency_capture_period_size = trial;
3892 }
3893 }
3894
Eric Park244c1572017-04-18 11:36:26 -04003895 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003896 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003897
3898 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
3899 af_period_multiplier = atoi(value);
3900 if (af_period_multiplier < 0) {
3901 af_period_multiplier = 2;
3902 } else if (af_period_multiplier > 4) {
3903 af_period_multiplier = 4;
3904 }
3905 ALOGV("new period_multiplier = %d", af_period_multiplier);
3906 }
3907
Eric Park244c1572017-04-18 11:36:26 -04003908 audio_extn_tfa_98xx_init(adev);
3909
vivek mehta1a9b7c02015-06-25 11:49:38 -07003910 pthread_mutex_unlock(&adev_init_lock);
3911
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003912 if (adev->adm_init)
3913 adev->adm_data = adev->adm_init();
3914
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003915 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003916 audio_extn_snd_mon_init();
3917 pthread_mutex_lock(&adev->lock);
3918 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
3919 adev->card_status = CARD_STATUS_ONLINE;
3920 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003921
Eric Laurent2bafff12016-03-17 12:17:23 -07003922 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923 return 0;
3924}
3925
3926static struct hw_module_methods_t hal_module_methods = {
3927 .open = adev_open,
3928};
3929
3930struct audio_module HAL_MODULE_INFO_SYM = {
3931 .common = {
3932 .tag = HARDWARE_MODULE_TAG,
3933 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3934 .hal_api_version = HARDWARE_HAL_API_VERSION,
3935 .id = AUDIO_HARDWARE_MODULE_ID,
3936 .name = "QCOM Audio HAL",
3937 .author = "Code Aurora Forum",
3938 .methods = &hal_module_methods,
3939 },
3940};