blob: 71aecb30a2a76beac9eca6cb312b61d4ea14d6fa [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036
37#include <cutils/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080038#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080039#include <cutils/str_parms.h>
40#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041#include <cutils/atomic.h>
42#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080043
Eric Laurentb23d5282013-05-14 15:27:20 -070044#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070045#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070046#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070047#include <audio_effects/effect_aec.h>
48#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080049#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080050#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070051#include "platform_api.h"
52#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070053#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080054
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080056#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070057
Eric Laurent397db572016-05-11 11:31:47 -070058/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
59 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070060#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070061// 2 buffers causes problems with high bitrate files
62#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070063/* ToDo: Check and update a proper value in msec */
64#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
65#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
66
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070067#define PROXY_OPEN_RETRY_COUNT 100
68#define PROXY_OPEN_WAIT_TIME 20
69
vivek mehtadae44712015-07-27 14:13:18 -070070#define MIN_CHANNEL_COUNT 1
71#define DEFAULT_CHANNEL_COUNT 2
72
Jean-Michel Trivic0750692015-10-12 12:12:32 -070073#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
74#define MAX_CHANNEL_COUNT 1
75#else
vivek mehtadae44712015-07-27 14:13:18 -070076#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
77#define XSTR(x) STR(x)
78#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070079#endif
vivek mehtadae44712015-07-27 14:13:18 -070080
Haynes Mathew George03c40102016-01-29 17:57:48 -080081#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
82
Glenn Kasten4f993392014-05-14 07:30:48 -070083static unsigned int configured_low_latency_capture_period_size =
84 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
85
Andy Hung31aca912014-03-20 17:14:59 -070086/* This constant enables extended precision handling.
87 * TODO The flag is off until more testing is done.
88 */
89static const bool k_enable_extended_precision = false;
90
Eric Laurentb23d5282013-05-14 15:27:20 -070091struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -070092 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -070093 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
94 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
95 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
96 .format = PCM_FORMAT_S16_LE,
97 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
98 .stop_threshold = INT_MAX,
99 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
100};
101
102struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700103 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700104 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
105 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
106 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
107 .format = PCM_FORMAT_S16_LE,
108 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
109 .stop_threshold = INT_MAX,
110 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
111};
112
Haynes Mathew George03c40102016-01-29 17:57:48 -0800113static int af_period_multiplier = 4;
114struct pcm_config pcm_config_rt = {
115 .channels = DEFAULT_CHANNEL_COUNT,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = ULL_PERIOD_SIZE, //1 ms
118 .period_count = 512, //=> buffer size is 512ms
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
121 .stop_threshold = INT_MAX,
122 .silence_threshold = 0,
123 .silence_size = 0,
124 .avail_min = ULL_PERIOD_SIZE, //1 ms
125};
126
Eric Laurentb23d5282013-05-14 15:27:20 -0700127struct pcm_config pcm_config_hdmi_multi = {
128 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
129 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
130 .period_size = HDMI_MULTI_PERIOD_SIZE,
131 .period_count = HDMI_MULTI_PERIOD_COUNT,
132 .format = PCM_FORMAT_S16_LE,
133 .start_threshold = 0,
134 .stop_threshold = INT_MAX,
135 .avail_min = 0,
136};
137
138struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700139 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700140 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
141 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700142 .stop_threshold = INT_MAX,
143 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700144};
145
Haynes Mathew George03c40102016-01-29 17:57:48 -0800146struct pcm_config pcm_config_audio_capture_rt = {
147 .channels = DEFAULT_CHANNEL_COUNT,
148 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
149 .period_size = ULL_PERIOD_SIZE,
150 .period_count = 512,
151 .format = PCM_FORMAT_S16_LE,
152 .start_threshold = 0,
153 .stop_threshold = INT_MAX,
154 .silence_threshold = 0,
155 .silence_size = 0,
156 .avail_min = ULL_PERIOD_SIZE, //1 ms
157};
158
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700159#define AFE_PROXY_CHANNEL_COUNT 2
160#define AFE_PROXY_SAMPLING_RATE 48000
161
162#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
163#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
164
165struct pcm_config pcm_config_afe_proxy_playback = {
166 .channels = AFE_PROXY_CHANNEL_COUNT,
167 .rate = AFE_PROXY_SAMPLING_RATE,
168 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
169 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
170 .format = PCM_FORMAT_S16_LE,
171 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
172 .stop_threshold = INT_MAX,
173 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
174};
175
176#define AFE_PROXY_RECORD_PERIOD_SIZE 768
177#define AFE_PROXY_RECORD_PERIOD_COUNT 4
178
179struct pcm_config pcm_config_afe_proxy_record = {
180 .channels = AFE_PROXY_CHANNEL_COUNT,
181 .rate = AFE_PROXY_SAMPLING_RATE,
182 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
183 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
186 .stop_threshold = INT_MAX,
187 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
188};
189
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700190const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700191 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
192 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
193 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700194 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700195 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700196 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700197
Eric Laurentb23d5282013-05-14 15:27:20 -0700198 [USECASE_AUDIO_RECORD] = "audio-record",
199 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700200
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800201 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
202 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700203
Eric Laurentb23d5282013-05-14 15:27:20 -0700204 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700205 [USECASE_VOICE2_CALL] = "voice2-call",
206 [USECASE_VOLTE_CALL] = "volte-call",
207 [USECASE_QCHAT_CALL] = "qchat-call",
208 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800209 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
210 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700211
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700212 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
213 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
214
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700215 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
216 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700217};
218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800219
220#define STRING_TO_ENUM(string) { #string, string }
221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800222struct string_to_enum {
223 const char *name;
224 uint32_t value;
225};
226
227static const struct string_to_enum out_channels_name_to_enum_table[] = {
228 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
229 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
230 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
231};
232
Haynes Mathew George5191a852013-09-11 14:19:36 -0700233static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700234static struct audio_device *adev = NULL;
235static pthread_mutex_t adev_init_lock;
236static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700237//cache last MBDRC cal step level
238static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700239
Haynes Mathew George03c40102016-01-29 17:57:48 -0800240static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
241 int flags __unused)
242{
243 int dir = 0;
244 switch (uc_id) {
245 case USECASE_AUDIO_RECORD_LOW_LATENCY:
246 dir = 1;
247 case USECASE_AUDIO_PLAYBACK_ULL:
248 break;
249 default:
250 return false;
251 }
252
253 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
254 PCM_PLAYBACK : PCM_CAPTURE);
255 if (adev->adm_is_noirq_avail)
256 return adev->adm_is_noirq_avail(adev->adm_data,
257 adev->snd_card, dev_id, dir);
258 return false;
259}
260
261static void register_out_stream(struct stream_out *out)
262{
263 struct audio_device *adev = out->dev;
264 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
265 return;
266
267 if (!adev->adm_register_output_stream)
268 return;
269
270 adev->adm_register_output_stream(adev->adm_data,
271 out->handle,
272 out->flags);
273
274 if (!adev->adm_set_config)
275 return;
276
277 if (out->realtime) {
278 adev->adm_set_config(adev->adm_data,
279 out->handle,
280 out->pcm, &out->config);
281 }
282}
283
284static void register_in_stream(struct stream_in *in)
285{
286 struct audio_device *adev = in->dev;
287 if (!adev->adm_register_input_stream)
288 return;
289
290 adev->adm_register_input_stream(adev->adm_data,
291 in->capture_handle,
292 in->flags);
293
294 if (!adev->adm_set_config)
295 return;
296
297 if (in->realtime) {
298 adev->adm_set_config(adev->adm_data,
299 in->capture_handle,
300 in->pcm,
301 &in->config);
302 }
303}
304
305static void request_out_focus(struct stream_out *out, long ns)
306{
307 struct audio_device *adev = out->dev;
308
309 if (out->routing_change) {
310 out->routing_change = false;
311 if (adev->adm_on_routing_change)
312 adev->adm_on_routing_change(adev->adm_data, out->handle);
313 }
314
315 if (adev->adm_request_focus_v2) {
316 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
317 } else if (adev->adm_request_focus) {
318 adev->adm_request_focus(adev->adm_data, out->handle);
319 }
320}
321
322static void request_in_focus(struct stream_in *in, long ns)
323{
324 struct audio_device *adev = in->dev;
325
326 if (in->routing_change) {
327 in->routing_change = false;
328 if (adev->adm_on_routing_change)
329 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
330 }
331
332 if (adev->adm_request_focus_v2) {
333 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
334 } else if (adev->adm_request_focus) {
335 adev->adm_request_focus(adev->adm_data, in->capture_handle);
336 }
337}
338
339static void release_out_focus(struct stream_out *out, long ns __unused)
340{
341 struct audio_device *adev = out->dev;
342
343 if (adev->adm_abandon_focus)
344 adev->adm_abandon_focus(adev->adm_data, out->handle);
345}
346
347static void release_in_focus(struct stream_in *in, long ns __unused)
348{
349 struct audio_device *adev = in->dev;
350 if (adev->adm_abandon_focus)
351 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
352}
353
Andy Hung7401c7c2016-09-21 12:41:21 -0700354// Time string format similar to logcat, buffer_length must be >= 19 chars.
355static void ns2string(int64_t ns, char *buffer, int buffer_length)
356{
357 const int one_second = 1000000000;
358 const time_t sec = ns / one_second;
359 struct tm tm;
360 localtime_r(&sec, &tm);
361 snprintf(buffer, buffer_length, "%02d-%02d %02d:%02d:%02d.%03d",
362 tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range
363 tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
364 (int)(ns % one_second / 1000000));
365}
366
367// Convert timespec to nsec.
368static int64_t ts2ns(const struct timespec *ts)
369{
370 return ts->tv_sec * 1000000000LL + ts->tv_nsec;
371}
372
373// Log errors: consecutive errors with the same code will
374// be aggregated if they occur within one second.
375// A mutual exclusion lock must be held before calling.
376static void log_error_l(struct error_log *log, int code) {
377 ++log->errors;
378
379 struct timespec now_ts = { 0, 0 };
380 (void)clock_gettime(CLOCK_REALTIME, &now_ts);
381 const int64_t now = ts2ns(&now_ts);
382
383 // Within 1 second, cluster the same error codes together.
384 const int one_second = 1000000000;
385 if (code == log->entries[log->idx].code &&
386 now - log->entries[log->idx].last_time < one_second) {
387 log->entries[log->idx].count++;
388 log->entries[log->idx].last_time = now;
389 return;
390 }
391
392 // Add new error entry.
393 if (++log->idx >= ARRAY_SIZE(log->entries)) {
394 log->idx = 0;
395 }
396 log->entries[log->idx].count = 1;
397 log->entries[log->idx].code = code;
398 log->entries[log->idx].first_time = now;
399 log->entries[log->idx].last_time = now;
400}
401
402// Dump information in the error log. A mutual exclusion lock
403// should be held, but if that cannot be obtained, one should
404// make a copy of the error log before calling -- the call is
405// still safe, but there might be some misinterpreted data.
406static void log_dump_l(const struct error_log *log, int fd)
407{
408 dprintf(fd, " Errors: %u\n", log->errors);
409 if (log->errors == 0)
410 return;
411
412 dprintf(fd, " Index Code Freq First time Last time\n");
413 for (size_t i = 0; i < ARRAY_SIZE(log->entries); ++i) {
414 if (log->entries[i].count != 0) {
415 char first_time[32];
416 char last_time[32];
417 ns2string(log->entries[i].first_time, first_time, sizeof(first_time));
418 ns2string(log->entries[i].last_time, last_time, sizeof(last_time));
419 dprintf(fd, " %c%4zu %4d %5d %s %s\n",
420 i == log->idx ? '*' : ' ', // mark head position
421 i, log->entries[i].code, log->entries[i].count,
422 first_time, last_time);
423 }
424 }
425}
426
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700427static int parse_snd_card_status(struct str_parms * parms, int * card,
428 card_status_t * status)
429{
430 char value[32]={0};
431 char state[32]={0};
432
433 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
434
435 if (ret < 0)
436 return -1;
437
438 // sscanf should be okay as value is of max length 32.
439 // same as sizeof state.
440 if (sscanf(value, "%d,%s", card, state) < 2)
441 return -1;
442
443 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
444 CARD_STATUS_OFFLINE;
445 return 0;
446}
447
vivek mehta1a9b7c02015-06-25 11:49:38 -0700448__attribute__ ((visibility ("default")))
449bool audio_hw_send_gain_dep_calibration(int level) {
450 bool ret_val = false;
451 ALOGV("%s: enter ... ", __func__);
452
453 pthread_mutex_lock(&adev_init_lock);
454
455 if (adev != NULL && adev->platform != NULL) {
456 pthread_mutex_lock(&adev->lock);
457 ret_val = platform_send_gain_dep_cal(adev->platform, level);
458 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700459
460 // if cal set fails, cache level info
461 // if cal set succeds, reset known last cal set
462 if (!ret_val)
463 last_known_cal_step = level;
464 else if (last_known_cal_step != -1)
465 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700466 } else {
467 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
468 }
469
470 pthread_mutex_unlock(&adev_init_lock);
471
472 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
473 return ret_val;
474}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700475
vivek mehtaa8d7c922016-05-25 14:40:44 -0700476__attribute__ ((visibility ("default")))
477int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
478 int table_size) {
479 int ret_val = 0;
480 ALOGV("%s: enter ... ", __func__);
481
482 pthread_mutex_lock(&adev_init_lock);
483 if (adev == NULL) {
484 ALOGW("%s: adev is NULL .... ", __func__);
485 goto done;
486 }
487
488 pthread_mutex_lock(&adev->lock);
489 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
490 pthread_mutex_unlock(&adev->lock);
491done:
492 pthread_mutex_unlock(&adev_init_lock);
493 ALOGV("%s: exit ... ", __func__);
494 return ret_val;
495}
496
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700497static bool is_supported_format(audio_format_t format)
498{
Eric Laurent8251ac82014-07-23 11:00:25 -0700499 switch (format) {
500 case AUDIO_FORMAT_MP3:
501 case AUDIO_FORMAT_AAC_LC:
502 case AUDIO_FORMAT_AAC_HE_V1:
503 case AUDIO_FORMAT_AAC_HE_V2:
504 return true;
505 default:
506 break;
507 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700508 return false;
509}
510
Haynes Mathew George03c40102016-01-29 17:57:48 -0800511static inline bool is_mmap_usecase(audio_usecase_t uc_id)
512{
513 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
514 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
515}
516
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700517static int get_snd_codec_id(audio_format_t format)
518{
519 int id = 0;
520
Eric Laurent8251ac82014-07-23 11:00:25 -0700521 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700522 case AUDIO_FORMAT_MP3:
523 id = SND_AUDIOCODEC_MP3;
524 break;
525 case AUDIO_FORMAT_AAC:
526 id = SND_AUDIOCODEC_AAC;
527 break;
528 default:
529 ALOGE("%s: Unsupported audio format", __func__);
530 }
531
532 return id;
533}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800534
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800535static int audio_ssr_status(struct audio_device *adev)
536{
537 int ret = 0;
538 struct mixer_ctl *ctl;
539 const char *mixer_ctl_name = "Audio SSR Status";
540
541 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
542 ret = mixer_ctl_get_value(ctl, 0);
543 ALOGD("%s: value: %d", __func__, ret);
544 return ret;
545}
546
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800547int enable_audio_route(struct audio_device *adev,
548 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800549{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700550 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800551 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800552
553 if (usecase == NULL)
554 return -EINVAL;
555
556 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
557
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800558 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700559 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800560 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700561 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800562
Yamit Mehtae3b99562016-09-16 22:44:00 +0530563 audio_extn_utils_send_app_type_cfg(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800564 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500565 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700566 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700567 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800568
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800569 ALOGV("%s: exit", __func__);
570 return 0;
571}
572
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800573int disable_audio_route(struct audio_device *adev,
574 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800575{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700576 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800577 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800578
579 if (usecase == NULL)
580 return -EINVAL;
581
582 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700583 if (usecase->type == PCM_CAPTURE)
584 snd_device = usecase->in_snd_device;
585 else
586 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800587 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500588 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700589 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700590 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800592 ALOGV("%s: exit", __func__);
593 return 0;
594}
595
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800596int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700597 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800598{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700599 int i, num_devices = 0;
600 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800601 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800602 if (snd_device < SND_DEVICE_MIN ||
603 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800604 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800605 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800606 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700607
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700608 platform_send_audio_calibration(adev->platform, snd_device);
609
vivek mehtade4849c2016-03-03 17:23:38 -0800610 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700611 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700612 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800613 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700614 }
615
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700616 /* due to the possibility of calibration overwrite between listen
617 and audio, notify sound trigger hal before audio calibration is sent */
618 audio_extn_sound_trigger_update_device_status(snd_device,
619 ST_EVENT_SND_DEVICE_BUSY);
620
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700621 if (audio_extn_spkr_prot_is_enabled())
622 audio_extn_spkr_prot_calib_cancel(adev);
623
zhaoyang yin4211fad2015-06-04 21:13:25 +0800624 audio_extn_dsm_feedback_enable(adev, snd_device, true);
625
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700626 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
627 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
628 audio_extn_spkr_prot_is_enabled()) {
629 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800630 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700631 }
632 if (audio_extn_spkr_prot_start_processing(snd_device)) {
633 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800634 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700635 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700636 } else if (platform_can_split_snd_device(snd_device,
637 &num_devices,
638 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700639 for (i = 0; i < num_devices; i++) {
640 enable_snd_device(adev, new_snd_devices[i]);
641 }
vivek mehtab6506412015-08-07 16:55:17 -0700642 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700643 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800644 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
645 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
646 ALOGE(" %s: Invalid sound device returned", __func__);
647 goto on_error;
648 }
Ed Tam70b5c142016-03-21 19:14:29 -0700649
Eric Laurent2e140aa2016-06-30 17:14:46 -0700650 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800651 audio_route_apply_and_update_path(adev->audio_route, device_name);
652 }
653on_success:
654 adev->snd_dev_ref_cnt[snd_device]++;
655 ret_val = 0;
656on_error:
657 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800658}
659
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800660int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700661 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800662{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700663 int i, num_devices = 0;
664 snd_device_t new_snd_devices[2];
665
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800666 if (snd_device < SND_DEVICE_MIN ||
667 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800668 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800669 return -EINVAL;
670 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
672 ALOGE("%s: device ref cnt is already 0", __func__);
673 return -EINVAL;
674 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800675 audio_extn_tfa_98xx_disable_speaker(snd_device);
676
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700677 adev->snd_dev_ref_cnt[snd_device]--;
678 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800679 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700680 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
681 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
682 audio_extn_spkr_prot_is_enabled()) {
683 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700684 } else if (platform_can_split_snd_device(snd_device,
685 &num_devices,
686 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700687 for (i = 0; i < num_devices; i++) {
688 disable_snd_device(adev, new_snd_devices[i]);
689 }
vivek mehtab6506412015-08-07 16:55:17 -0700690 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700691 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800692 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
693 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
694 ALOGE(" %s: Invalid sound device returned", __func__);
695 return -EINVAL;
696 }
697
Eric Laurent2e140aa2016-06-30 17:14:46 -0700698 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800699 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700700 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700701 audio_extn_sound_trigger_update_device_status(snd_device,
702 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700703 }
vivek mehtab6506412015-08-07 16:55:17 -0700704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800705 return 0;
706}
707
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700708/*
709 legend:
710 uc - existing usecase
711 new_uc - new usecase
712 d1, d11, d2 - SND_DEVICE enums
713 a1, a2 - corresponding ANDROID device enums
714 B, B1, B2 - backend strings
715
716case 1
717 uc->dev d1 (a1) B1
718 new_uc->dev d1 (a1), d2 (a2) B1, B2
719
720 resolution: disable and enable uc->dev on d1
721
722case 2
723 uc->dev d1 (a1) B1
724 new_uc->dev d11 (a1) B1
725
726 resolution: need to switch uc since d1 and d11 are related
727 (e.g. speaker and voice-speaker)
728 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
729
730case 3
731 uc->dev d1 (a1) B1
732 new_uc->dev d2 (a2) B2
733
734 resolution: no need to switch uc
735
736case 4
737 uc->dev d1 (a1) B
738 new_uc->dev d2 (a2) B
739
740 resolution: disable enable uc-dev on d2 since backends match
741 we cannot enable two streams on two different devices if they
742 share the same backend. e.g. if offload is on speaker device using
743 QUAD_MI2S backend and a low-latency stream is started on voice-handset
744 using the same backend, offload must also be switched to voice-handset.
745
746case 5
747 uc->dev d1 (a1) B
748 new_uc->dev d1 (a1), d2 (a2) B
749
750 resolution: disable enable uc-dev on d2 since backends match
751 we cannot enable two streams on two different devices if they
752 share the same backend.
753
754case 6
755 uc->dev d1 a1 B1
756 new_uc->dev d2 a1 B2
757
758 resolution: no need to switch
759
760case 7
761
762 uc->dev d1 (a1), d2 (a2) B1, B2
763 new_uc->dev d1 B1
764
765 resolution: no need to switch
766
767*/
768static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
769 struct audio_usecase *new_uc,
770 snd_device_t new_snd_device)
771{
772 audio_devices_t a1 = uc->stream.out->devices;
773 audio_devices_t a2 = new_uc->stream.out->devices;
774
775 snd_device_t d1 = uc->out_snd_device;
776 snd_device_t d2 = new_snd_device;
777
778 // Treat as a special case when a1 and a2 are not disjoint
779 if ((a1 != a2) && (a1 & a2)) {
780 snd_device_t d3[2];
781 int num_devices = 0;
782 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
783 &num_devices,
784 d3);
785 if (ret < 0) {
786 if (ret != -ENOSYS) {
787 ALOGW("%s failed to split snd_device %d",
788 __func__,
789 popcount(a1) > 1 ? d1 : d2);
790 }
791 goto end;
792 }
793
794 // NB: case 7 is hypothetical and isn't a practical usecase yet.
795 // But if it does happen, we need to give priority to d2 if
796 // the combo devices active on the existing usecase share a backend.
797 // This is because we cannot have a usecase active on a combo device
798 // and a new usecase requests one device in this combo pair.
799 if (platform_check_backends_match(d3[0], d3[1])) {
800 return d2; // case 5
801 } else {
802 return d1; // case 1
803 }
804 } else {
805 if (platform_check_backends_match(d1, d2)) {
806 return d2; // case 2, 4
807 } else {
808 return d1; // case 6, 3
809 }
810 }
811
812end:
813 return d2; // return whatever was calculated before.
814}
815
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700816static void check_and_route_playback_usecases(struct audio_device *adev,
817 struct audio_usecase *uc_info,
818 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819{
820 struct listnode *node;
821 struct audio_usecase *usecase;
822 bool switch_device[AUDIO_USECASE_MAX];
823 int i, num_uc_to_switch = 0;
824
825 /*
826 * This function is to make sure that all the usecases that are active on
827 * the hardware codec backend are always routed to any one device that is
828 * handled by the hardware codec.
829 * For example, if low-latency and deep-buffer usecases are currently active
830 * on speaker and out_set_parameters(headset) is received on low-latency
831 * output, then we have to make sure deep-buffer is also switched to headset,
832 * because of the limitation that both the devices cannot be enabled
833 * at the same time as they share the same backend.
834 */
835 /* Disable all the usecases on the shared backend other than the
836 specified usecase */
837 for (i = 0; i < AUDIO_USECASE_MAX; i++)
838 switch_device[i] = false;
839
840 list_for_each(node, &adev->usecase_list) {
841 usecase = node_to_item(node, struct audio_usecase, list);
842 if (usecase->type != PCM_CAPTURE &&
843 usecase != uc_info &&
844 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700845 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
846 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700847 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
848 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700849 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700850 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700851 switch_device[usecase->id] = true;
852 num_uc_to_switch++;
853 }
854 }
855
856 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 list_for_each(node, &adev->usecase_list) {
858 usecase = node_to_item(node, struct audio_usecase, list);
859 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700860 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900861 }
862 }
863
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700864 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900865 list_for_each(node, &adev->usecase_list) {
866 usecase = node_to_item(node, struct audio_usecase, list);
867 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700868 d_device = derive_playback_snd_device(usecase, uc_info,
869 snd_device);
870 enable_snd_device(adev, d_device);
871 /* Update the out_snd_device before enabling the audio route */
872 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 }
874 }
875
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700876 /* Re-route all the usecases on the shared backend other than the
877 specified usecase to new snd devices */
878 list_for_each(node, &adev->usecase_list) {
879 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700880 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700881 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882 }
883 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700884 }
885}
886
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700887static void check_and_route_capture_usecases(struct audio_device *adev,
888 struct audio_usecase *uc_info,
889 snd_device_t snd_device)
890{
891 struct listnode *node;
892 struct audio_usecase *usecase;
893 bool switch_device[AUDIO_USECASE_MAX];
894 int i, num_uc_to_switch = 0;
895
vivek mehta4ed66e62016-04-15 23:33:34 -0700896 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
897
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700898 /*
899 * This function is to make sure that all the active capture usecases
900 * are always routed to the same input sound device.
901 * For example, if audio-record and voice-call usecases are currently
902 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
903 * is received for voice call then we have to make sure that audio-record
904 * usecase is also switched to earpiece i.e. voice-dmic-ef,
905 * because of the limitation that two devices cannot be enabled
906 * at the same time if they share the same backend.
907 */
908 for (i = 0; i < AUDIO_USECASE_MAX; i++)
909 switch_device[i] = false;
910
911 list_for_each(node, &adev->usecase_list) {
912 usecase = node_to_item(node, struct audio_usecase, list);
913 if (usecase->type != PCM_PLAYBACK &&
914 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700915 usecase->in_snd_device != snd_device &&
916 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700917 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
918 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700919 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700920 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700921 switch_device[usecase->id] = true;
922 num_uc_to_switch++;
923 }
924 }
925
926 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700927 list_for_each(node, &adev->usecase_list) {
928 usecase = node_to_item(node, struct audio_usecase, list);
929 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700930 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700931 }
932 }
933
934 list_for_each(node, &adev->usecase_list) {
935 usecase = node_to_item(node, struct audio_usecase, list);
936 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700937 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700938 }
939 }
940
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700941 /* Re-route all the usecases on the shared backend other than the
942 specified usecase to new snd devices */
943 list_for_each(node, &adev->usecase_list) {
944 usecase = node_to_item(node, struct audio_usecase, list);
945 /* Update the in_snd_device only before enabling the audio route */
946 if (switch_device[usecase->id] ) {
947 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700948 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700949 }
950 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700951 }
952}
953
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800954/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700955static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800956{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700957 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700958 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800959
960 switch (channels) {
961 /*
962 * Do not handle stereo output in Multi-channel cases
963 * Stereo case is handled in normal playback path
964 */
965 case 6:
966 ALOGV("%s: HDMI supports 5.1", __func__);
967 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
968 break;
969 case 8:
970 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
971 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
972 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
973 break;
974 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700975 ALOGE("HDMI does not support multi channel playback");
976 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800977 break;
978 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700979 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800980}
981
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700982static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
983{
984 struct audio_usecase *usecase;
985 struct listnode *node;
986
987 list_for_each(node, &adev->usecase_list) {
988 usecase = node_to_item(node, struct audio_usecase, list);
989 if (usecase->type == VOICE_CALL) {
990 ALOGV("%s: usecase id %d", __func__, usecase->id);
991 return usecase->id;
992 }
993 }
994 return USECASE_INVALID;
995}
996
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800997struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
998 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700999{
1000 struct audio_usecase *usecase;
1001 struct listnode *node;
1002
1003 list_for_each(node, &adev->usecase_list) {
1004 usecase = node_to_item(node, struct audio_usecase, list);
1005 if (usecase->id == uc_id)
1006 return usecase;
1007 }
1008 return NULL;
1009}
1010
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001011int select_devices(struct audio_device *adev,
1012 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001013{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001014 snd_device_t out_snd_device = SND_DEVICE_NONE;
1015 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001016 struct audio_usecase *usecase = NULL;
1017 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001018 struct audio_usecase *hfp_usecase = NULL;
1019 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001020 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001021 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001023 usecase = get_usecase_from_list(adev, uc_id);
1024 if (usecase == NULL) {
1025 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1026 return -EINVAL;
1027 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001029 if ((usecase->type == VOICE_CALL) ||
1030 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001031 out_snd_device = platform_get_output_snd_device(adev->platform,
1032 usecase->stream.out->devices);
1033 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001034 usecase->devices = usecase->stream.out->devices;
1035 } else {
1036 /*
1037 * If the voice call is active, use the sound devices of voice call usecase
1038 * so that it would not result any device switch. All the usecases will
1039 * be switched to new device when select_devices() is called for voice call
1040 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001041 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001042 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001043 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001044 vc_usecase = get_usecase_from_list(adev,
1045 get_voice_usecase_id_from_list(adev));
1046 if ((vc_usecase != NULL) &&
1047 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1048 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049 in_snd_device = vc_usecase->in_snd_device;
1050 out_snd_device = vc_usecase->out_snd_device;
1051 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001052 } else if (audio_extn_hfp_is_active(adev)) {
1053 hfp_ucid = audio_extn_hfp_get_usecase();
1054 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1055 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1056 in_snd_device = hfp_usecase->in_snd_device;
1057 out_snd_device = hfp_usecase->out_snd_device;
1058 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001059 }
1060 if (usecase->type == PCM_PLAYBACK) {
1061 usecase->devices = usecase->stream.out->devices;
1062 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001063 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001064 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001065 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001066 if (usecase->stream.out == adev->primary_output &&
1067 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001068 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1069 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001070 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001071 select_devices(adev, adev->active_input->usecase);
1072 }
1073 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001074 } else if (usecase->type == PCM_CAPTURE) {
1075 usecase->devices = usecase->stream.in->device;
1076 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001077 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001078 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001079 if (adev->active_input &&
1080 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1081 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001082 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001083 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1084 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1085 } else if (adev->primary_output) {
1086 out_device = adev->primary_output->devices;
1087 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001088 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001089 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001090 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001091 }
1092 }
1093
1094 if (out_snd_device == usecase->out_snd_device &&
1095 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001096 return 0;
1097 }
1098
Eric Laurent2bafff12016-03-17 12:17:23 -07001099 if (out_snd_device != SND_DEVICE_NONE &&
1100 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1101 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1102 __func__,
1103 use_case_table[uc_id],
1104 adev->last_logged_snd_device[uc_id][0],
1105 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1106 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1107 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1108 -1,
1109 out_snd_device,
1110 platform_get_snd_device_name(out_snd_device),
1111 platform_get_snd_device_acdb_id(out_snd_device));
1112 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1113 }
1114 if (in_snd_device != SND_DEVICE_NONE &&
1115 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1116 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1117 __func__,
1118 use_case_table[uc_id],
1119 adev->last_logged_snd_device[uc_id][1],
1120 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1121 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1122 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1123 -1,
1124 in_snd_device,
1125 platform_get_snd_device_name(in_snd_device),
1126 platform_get_snd_device_acdb_id(in_snd_device));
1127 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1128 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001130 /*
1131 * Limitation: While in call, to do a device switch we need to disable
1132 * and enable both RX and TX devices though one of them is same as current
1133 * device.
1134 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001135 if ((usecase->type == VOICE_CALL) &&
1136 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1137 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001138 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001139 /* Disable sidetone only if voice call already exists */
1140 if (voice_is_call_state_active(adev))
1141 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001142 }
1143
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001144 /* Disable current sound devices */
1145 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001146 disable_audio_route(adev, usecase);
1147 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001148 }
1149
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001150 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001151 disable_audio_route(adev, usecase);
1152 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001153 }
1154
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001155 /* Applicable only on the targets that has external modem.
1156 * New device information should be sent to modem before enabling
1157 * the devices to reduce in-call device switch time.
1158 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001159 if ((usecase->type == VOICE_CALL) &&
1160 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1161 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001162 status = platform_switch_voice_call_enable_device_config(adev->platform,
1163 out_snd_device,
1164 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001165 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001166
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001167 /* Enable new sound devices */
1168 if (out_snd_device != SND_DEVICE_NONE) {
1169 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001170 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001171 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001172 }
1173
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001174 if (in_snd_device != SND_DEVICE_NONE) {
1175 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001176 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001177 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001178
Eric Laurentb23d5282013-05-14 15:27:20 -07001179 if (usecase->type == VOICE_CALL)
1180 status = platform_switch_voice_call_device_post(adev->platform,
1181 out_snd_device,
1182 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001183
sangwoo170731f2013-06-08 15:36:36 +09001184 usecase->in_snd_device = in_snd_device;
1185 usecase->out_snd_device = out_snd_device;
1186
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001187 audio_extn_tfa_98xx_set_mode();
1188
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001189 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001190
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001191 /* Applicable only on the targets that has external modem.
1192 * Enable device command should be sent to modem only after
1193 * enabling voice call mixer controls
1194 */
vivek mehta765eb642015-08-07 19:46:06 -07001195 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001196 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1197 out_snd_device,
1198 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001199 /* Enable sidetone only if voice call already exists */
1200 if (voice_is_call_state_active(adev))
1201 voice_set_sidetone(adev, out_snd_device, true);
1202 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001204 return status;
1205}
1206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001207static int stop_input_stream(struct stream_in *in)
1208{
1209 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001210 struct audio_usecase *uc_info;
1211 struct audio_device *adev = in->dev;
1212
Eric Laurentc8400632013-02-14 19:04:54 -08001213 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001214
Eric Laurent994a6932013-07-17 11:51:42 -07001215 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001216 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001217 uc_info = get_usecase_from_list(adev, in->usecase);
1218 if (uc_info == NULL) {
1219 ALOGE("%s: Could not find the usecase (%d) in the list",
1220 __func__, in->usecase);
1221 return -EINVAL;
1222 }
1223
Eric Laurent150dbfe2013-02-27 14:31:02 -08001224 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001225 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001226
1227 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001228 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001229
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001230 list_remove(&uc_info->list);
1231 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232
Eric Laurent994a6932013-07-17 11:51:42 -07001233 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001234 return ret;
1235}
1236
1237int start_input_stream(struct stream_in *in)
1238{
1239 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001240 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001241 struct audio_usecase *uc_info;
1242 struct audio_device *adev = in->dev;
1243
Eric Laurent994a6932013-07-17 11:51:42 -07001244 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001245
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001246 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1247 return -EIO;
1248
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001249 if (in->card_status == CARD_STATUS_OFFLINE ||
1250 adev->card_status == CARD_STATUS_OFFLINE) {
1251 ALOGW("in->card_status or adev->card_status offline, try again");
1252 ret = -EAGAIN;
1253 goto error_config;
1254 }
1255
Eric Laurentb23d5282013-05-14 15:27:20 -07001256 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001257 if (in->pcm_device_id < 0) {
1258 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1259 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001260 ret = -EINVAL;
1261 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001262 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001263
1264 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001265 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1266 uc_info->id = in->usecase;
1267 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001268 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001269 uc_info->devices = in->device;
1270 uc_info->in_snd_device = SND_DEVICE_NONE;
1271 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001273 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001274
1275 audio_extn_perf_lock_acquire();
1276
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001277 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278
Eric Laurentc8400632013-02-14 19:04:54 -08001279 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001280 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001281
Andy Hung6ebe5962016-01-15 17:46:57 -08001282 unsigned int flags = PCM_IN | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001283 unsigned int pcm_open_retry_count = 0;
1284
1285 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1286 flags |= PCM_MMAP | PCM_NOIRQ;
1287 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001288 } else if (in->realtime) {
1289 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001290 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001291
1292 while (1) {
1293 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1294 flags, &in->config);
1295 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1296 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1297 if (in->pcm != NULL) {
1298 pcm_close(in->pcm);
1299 in->pcm = NULL;
1300 }
1301 if (pcm_open_retry_count-- == 0) {
1302 ret = -EIO;
1303 goto error_open;
1304 }
1305 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1306 continue;
1307 }
1308 break;
1309 }
1310
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001311 ALOGV("%s: pcm_prepare", __func__);
1312 ret = pcm_prepare(in->pcm);
1313 if (ret < 0) {
1314 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1315 pcm_close(in->pcm);
1316 in->pcm = NULL;
1317 goto error_open;
1318 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001319 if (in->realtime) {
1320 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001321 if (ret < 0) {
1322 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1323 pcm_close(in->pcm);
1324 in->pcm = NULL;
1325 goto error_open;
1326 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001327 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001328 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001329 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001330 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001331
Eric Laurentc8400632013-02-14 19:04:54 -08001332 return ret;
1333
1334error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001335 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001336 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001337
1338error_config:
1339 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001340 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001341
1342 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001343}
1344
Eric Laurenta1478072015-09-21 17:21:52 -07001345void lock_input_stream(struct stream_in *in)
1346{
1347 pthread_mutex_lock(&in->pre_lock);
1348 pthread_mutex_lock(&in->lock);
1349 pthread_mutex_unlock(&in->pre_lock);
1350}
1351
1352void lock_output_stream(struct stream_out *out)
1353{
1354 pthread_mutex_lock(&out->pre_lock);
1355 pthread_mutex_lock(&out->lock);
1356 pthread_mutex_unlock(&out->pre_lock);
1357}
1358
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001359/* must be called with out->lock locked */
1360static int send_offload_cmd_l(struct stream_out* out, int command)
1361{
1362 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1363
1364 ALOGVV("%s %d", __func__, command);
1365
1366 cmd->cmd = command;
1367 list_add_tail(&out->offload_cmd_list, &cmd->node);
1368 pthread_cond_signal(&out->offload_cond);
1369 return 0;
1370}
1371
1372/* must be called iwth out->lock locked */
1373static void stop_compressed_output_l(struct stream_out *out)
1374{
1375 out->offload_state = OFFLOAD_STATE_IDLE;
1376 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001377 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001378 if (out->compr != NULL) {
1379 compress_stop(out->compr);
1380 while (out->offload_thread_blocked) {
1381 pthread_cond_wait(&out->cond, &out->lock);
1382 }
1383 }
1384}
1385
1386static void *offload_thread_loop(void *context)
1387{
1388 struct stream_out *out = (struct stream_out *) context;
1389 struct listnode *item;
1390
1391 out->offload_state = OFFLOAD_STATE_IDLE;
1392 out->playback_started = 0;
1393
1394 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1395 set_sched_policy(0, SP_FOREGROUND);
1396 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1397
1398 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001399 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001400 for (;;) {
1401 struct offload_cmd *cmd = NULL;
1402 stream_callback_event_t event;
1403 bool send_callback = false;
1404
1405 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1406 __func__, list_empty(&out->offload_cmd_list),
1407 out->offload_state);
1408 if (list_empty(&out->offload_cmd_list)) {
1409 ALOGV("%s SLEEPING", __func__);
1410 pthread_cond_wait(&out->offload_cond, &out->lock);
1411 ALOGV("%s RUNNING", __func__);
1412 continue;
1413 }
1414
1415 item = list_head(&out->offload_cmd_list);
1416 cmd = node_to_item(item, struct offload_cmd, node);
1417 list_remove(item);
1418
1419 ALOGVV("%s STATE %d CMD %d out->compr %p",
1420 __func__, out->offload_state, cmd->cmd, out->compr);
1421
1422 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1423 free(cmd);
1424 break;
1425 }
1426
1427 if (out->compr == NULL) {
1428 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001429 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001430 pthread_cond_signal(&out->cond);
1431 continue;
1432 }
1433 out->offload_thread_blocked = true;
1434 pthread_mutex_unlock(&out->lock);
1435 send_callback = false;
1436 switch(cmd->cmd) {
1437 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1438 compress_wait(out->compr, -1);
1439 send_callback = true;
1440 event = STREAM_CBK_EVENT_WRITE_READY;
1441 break;
1442 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001443 compress_next_track(out->compr);
1444 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001445 send_callback = true;
1446 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001447 /* Resend the metadata for next iteration */
1448 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001449 break;
1450 case OFFLOAD_CMD_DRAIN:
1451 compress_drain(out->compr);
1452 send_callback = true;
1453 event = STREAM_CBK_EVENT_DRAIN_READY;
1454 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001455 case OFFLOAD_CMD_ERROR:
1456 send_callback = true;
1457 event = STREAM_CBK_EVENT_ERROR;
1458 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001459 default:
1460 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1461 break;
1462 }
Eric Laurenta1478072015-09-21 17:21:52 -07001463 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001464 out->offload_thread_blocked = false;
1465 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001466 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001467 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001468 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001469 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001470 free(cmd);
1471 }
1472
1473 pthread_cond_signal(&out->cond);
1474 while (!list_empty(&out->offload_cmd_list)) {
1475 item = list_head(&out->offload_cmd_list);
1476 list_remove(item);
1477 free(node_to_item(item, struct offload_cmd, node));
1478 }
1479 pthread_mutex_unlock(&out->lock);
1480
1481 return NULL;
1482}
1483
1484static int create_offload_callback_thread(struct stream_out *out)
1485{
1486 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1487 list_init(&out->offload_cmd_list);
1488 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1489 offload_thread_loop, out);
1490 return 0;
1491}
1492
1493static int destroy_offload_callback_thread(struct stream_out *out)
1494{
Eric Laurenta1478072015-09-21 17:21:52 -07001495 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001496 stop_compressed_output_l(out);
1497 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1498
1499 pthread_mutex_unlock(&out->lock);
1500 pthread_join(out->offload_thread, (void **) NULL);
1501 pthread_cond_destroy(&out->offload_cond);
1502
1503 return 0;
1504}
1505
Eric Laurent07eeafd2013-10-06 12:52:49 -07001506static bool allow_hdmi_channel_config(struct audio_device *adev)
1507{
1508 struct listnode *node;
1509 struct audio_usecase *usecase;
1510 bool ret = true;
1511
1512 list_for_each(node, &adev->usecase_list) {
1513 usecase = node_to_item(node, struct audio_usecase, list);
1514 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1515 /*
1516 * If voice call is already existing, do not proceed further to avoid
1517 * disabling/enabling both RX and TX devices, CSD calls, etc.
1518 * Once the voice call done, the HDMI channels can be configured to
1519 * max channels of remaining use cases.
1520 */
1521 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001522 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001523 __func__);
1524 ret = false;
1525 break;
1526 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001527 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001528 "no change in HDMI channels", __func__);
1529 ret = false;
1530 break;
1531 }
1532 }
1533 }
1534 return ret;
1535}
1536
1537static int check_and_set_hdmi_channels(struct audio_device *adev,
1538 unsigned int channels)
1539{
1540 struct listnode *node;
1541 struct audio_usecase *usecase;
1542
1543 /* Check if change in HDMI channel config is allowed */
1544 if (!allow_hdmi_channel_config(adev))
1545 return 0;
1546
1547 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001548 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001549 return 0;
1550 }
1551
1552 platform_set_hdmi_channels(adev->platform, channels);
1553 adev->cur_hdmi_channels = channels;
1554
1555 /*
1556 * Deroute all the playback streams routed to HDMI so that
1557 * the back end is deactivated. Note that backend will not
1558 * be deactivated if any one stream is connected to it.
1559 */
1560 list_for_each(node, &adev->usecase_list) {
1561 usecase = node_to_item(node, struct audio_usecase, list);
1562 if (usecase->type == PCM_PLAYBACK &&
1563 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001564 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001565 }
1566 }
1567
1568 /*
1569 * Enable all the streams disabled above. Now the HDMI backend
1570 * will be activated with new channel configuration
1571 */
1572 list_for_each(node, &adev->usecase_list) {
1573 usecase = node_to_item(node, struct audio_usecase, list);
1574 if (usecase->type == PCM_PLAYBACK &&
1575 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001576 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001577 }
1578 }
1579
1580 return 0;
1581}
1582
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583static int stop_output_stream(struct stream_out *out)
1584{
1585 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586 struct audio_usecase *uc_info;
1587 struct audio_device *adev = out->dev;
1588
Eric Laurent994a6932013-07-17 11:51:42 -07001589 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001590 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001591 uc_info = get_usecase_from_list(adev, out->usecase);
1592 if (uc_info == NULL) {
1593 ALOGE("%s: Could not find the usecase (%d) in the list",
1594 __func__, out->usecase);
1595 return -EINVAL;
1596 }
1597
Haynes Mathew George41f86652014-06-17 14:22:15 -07001598 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1599 if (adev->visualizer_stop_output != NULL)
1600 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1601 if (adev->offload_effects_stop_output != NULL)
1602 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1603 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001604
Eric Laurent150dbfe2013-02-27 14:31:02 -08001605 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001606 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001607
1608 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001609 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001610
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001611 list_remove(&uc_info->list);
1612 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001613
Eric Laurent0499d4f2014-08-25 22:39:29 -05001614 audio_extn_extspk_update(adev->extspk);
1615
Eric Laurent07eeafd2013-10-06 12:52:49 -07001616 /* Must be called after removing the usecase from list */
1617 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1618 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1619
Eric Laurent994a6932013-07-17 11:51:42 -07001620 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621 return ret;
1622}
1623
1624int start_output_stream(struct stream_out *out)
1625{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001627 struct audio_usecase *uc_info;
1628 struct audio_device *adev = out->dev;
1629
Eric Laurent994a6932013-07-17 11:51:42 -07001630 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001631 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001632
1633 if (out->card_status == CARD_STATUS_OFFLINE ||
1634 adev->card_status == CARD_STATUS_OFFLINE) {
1635 ALOGW("out->card_status or adev->card_status offline, try again");
1636 ret = -EAGAIN;
1637 goto error_config;
1638 }
1639
Eric Laurentb23d5282013-05-14 15:27:20 -07001640 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001641 if (out->pcm_device_id < 0) {
1642 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1643 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001644 ret = -EINVAL;
1645 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646 }
1647
1648 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1649 uc_info->id = out->usecase;
1650 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001651 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001652 uc_info->devices = out->devices;
1653 uc_info->in_snd_device = SND_DEVICE_NONE;
1654 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655
Eric Laurent07eeafd2013-10-06 12:52:49 -07001656 /* This must be called before adding this usecase to the list */
1657 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1658 check_and_set_hdmi_channels(adev, out->config.channels);
1659
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001660 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001662 audio_extn_perf_lock_acquire();
1663
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001664 select_devices(adev, out->usecase);
1665
Eric Laurent0499d4f2014-08-25 22:39:29 -05001666 audio_extn_extspk_update(adev->extspk);
1667
Andy Hung31aca912014-03-20 17:14:59 -07001668 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001669 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001670 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001671 unsigned int flags = PCM_OUT;
1672 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001673
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001674 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1675 flags |= PCM_MMAP | PCM_NOIRQ;
1676 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001677 } else if (out->realtime) {
1678 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001679 } else
1680 flags |= PCM_MONOTONIC;
1681
1682 while (1) {
1683 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1684 flags, &out->config);
1685 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1686 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1687 if (out->pcm != NULL) {
1688 pcm_close(out->pcm);
1689 out->pcm = NULL;
1690 }
1691 if (pcm_open_retry_count-- == 0) {
1692 ret = -EIO;
1693 goto error_open;
1694 }
1695 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1696 continue;
1697 }
1698 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001699 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001700 ALOGV("%s: pcm_prepare", __func__);
1701 if (pcm_is_ready(out->pcm)) {
1702 ret = pcm_prepare(out->pcm);
1703 if (ret < 0) {
1704 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1705 pcm_close(out->pcm);
1706 out->pcm = NULL;
1707 goto error_open;
1708 }
1709 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001710 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001711 out->pcm = NULL;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001712 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001713 COMPRESS_IN, &out->compr_config);
1714 if (out->compr && !is_compress_ready(out->compr)) {
1715 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1716 compress_close(out->compr);
1717 out->compr = NULL;
1718 ret = -EIO;
1719 goto error_open;
1720 }
1721 if (out->offload_callback)
1722 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001723
1724 if (adev->visualizer_start_output != NULL)
Haynes Mathew George41f86652014-06-17 14:22:15 -07001725 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1726 if (adev->offload_effects_start_output != NULL)
1727 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001728 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001729 ret = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001730 if (out->realtime) {
1731 ret = pcm_start(out->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001732 if (ret < 0) {
1733 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1734 pcm_close(out->pcm);
1735 out->pcm = NULL;
1736 goto error_open;
1737 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001738 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001739 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001740 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001741 audio_extn_tfa_98xx_enable_speaker();
1742
Eric Laurent994a6932013-07-17 11:51:42 -07001743 ALOGV("%s: exit", __func__);
Haynes Mathew George03c40102016-01-29 17:57:48 -08001744 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001745error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001746 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001748error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001749 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001750}
1751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752static int check_input_parameters(uint32_t sample_rate,
1753 audio_format_t format,
1754 int channel_count)
1755{
vivek mehta4ed66e62016-04-15 23:33:34 -07001756 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001757 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1758 return -EINVAL;
1759 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760
vivek mehtadae44712015-07-27 14:13:18 -07001761 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001762 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001763 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1764 return -EINVAL;
1765 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001766
1767 switch (sample_rate) {
1768 case 8000:
1769 case 11025:
1770 case 12000:
1771 case 16000:
1772 case 22050:
1773 case 24000:
1774 case 32000:
1775 case 44100:
1776 case 48000:
1777 break;
1778 default:
vivek mehtadae44712015-07-27 14:13:18 -07001779 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780 return -EINVAL;
1781 }
1782
1783 return 0;
1784}
1785
1786static size_t get_input_buffer_size(uint32_t sample_rate,
1787 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001788 int channel_count,
1789 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790{
1791 size_t size = 0;
1792
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001793 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1794 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001796 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001797 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001798 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001799
1800 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801
Glenn Kasten4f993392014-05-14 07:30:48 -07001802 /* make sure the size is multiple of 32 bytes
1803 * At 48 kHz mono 16-bit PCM:
1804 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1805 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1806 */
1807 size += 0x1f;
1808 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001809
1810 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811}
1812
1813static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1814{
1815 struct stream_out *out = (struct stream_out *)stream;
1816
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001817 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818}
1819
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001820static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001821{
1822 return -ENOSYS;
1823}
1824
1825static size_t out_get_buffer_size(const struct audio_stream *stream)
1826{
1827 struct stream_out *out = (struct stream_out *)stream;
1828
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001829 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1830 return out->compr_config.fragment_size;
1831 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001832 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001833 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001834}
1835
1836static uint32_t out_get_channels(const struct audio_stream *stream)
1837{
1838 struct stream_out *out = (struct stream_out *)stream;
1839
1840 return out->channel_mask;
1841}
1842
1843static audio_format_t out_get_format(const struct audio_stream *stream)
1844{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001845 struct stream_out *out = (struct stream_out *)stream;
1846
1847 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001848}
1849
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001850static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851{
1852 return -ENOSYS;
1853}
1854
1855static int out_standby(struct audio_stream *stream)
1856{
1857 struct stream_out *out = (struct stream_out *)stream;
1858 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001859
Eric Laurent994a6932013-07-17 11:51:42 -07001860 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001861 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862
Eric Laurenta1478072015-09-21 17:21:52 -07001863 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001865 if (adev->adm_deregister_stream)
1866 adev->adm_deregister_stream(adev->adm_data, out->handle);
1867
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001868 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001870 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1871 if (out->pcm) {
1872 pcm_close(out->pcm);
1873 out->pcm = NULL;
1874 }
1875 } else {
1876 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001877 out->gapless_mdata.encoder_delay = 0;
1878 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001879 if (out->compr != NULL) {
1880 compress_close(out->compr);
1881 out->compr = NULL;
1882 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001883 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001885 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886 }
1887 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001888 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001889 return 0;
1890}
1891
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001892static int out_on_error(struct audio_stream *stream)
1893{
1894 struct stream_out *out = (struct stream_out *)stream;
1895 struct audio_device *adev = out->dev;
1896 bool do_standby = false;
1897
1898 lock_output_stream(out);
1899 if (!out->standby) {
1900 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1901 stop_compressed_output_l(out);
1902 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1903 } else
1904 do_standby = true;
1905 }
1906 pthread_mutex_unlock(&out->lock);
1907
1908 if (do_standby)
1909 return out_standby(&out->stream.common);
1910
1911 return 0;
1912}
1913
Andy Hung7401c7c2016-09-21 12:41:21 -07001914static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001915{
Andy Hung7401c7c2016-09-21 12:41:21 -07001916 struct stream_out *out = (struct stream_out *)stream;
1917
1918 // We try to get the lock for consistency,
1919 // but it isn't necessary for these variables.
1920 // If we're not in standby, we may be blocked on a write.
1921 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1922 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1923 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1924
1925 if (locked) {
1926 log_dump_l(&out->error_log, fd);
1927 pthread_mutex_unlock(&out->lock);
1928 } else {
1929 // We don't have the lock here, copy for safety.
1930 struct error_log log = out->error_log;
1931 log_dump_l(&log, fd);
1932 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001933 return 0;
1934}
1935
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001936static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1937{
1938 int ret = 0;
1939 char value[32];
1940 struct compr_gapless_mdata tmp_mdata;
1941
1942 if (!out || !parms) {
1943 return -EINVAL;
1944 }
1945
1946 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1947 if (ret >= 0) {
1948 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1949 } else {
1950 return -EINVAL;
1951 }
1952
1953 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1954 if (ret >= 0) {
1955 tmp_mdata.encoder_padding = atoi(value);
1956 } else {
1957 return -EINVAL;
1958 }
1959
1960 out->gapless_mdata = tmp_mdata;
1961 out->send_new_metadata = 1;
1962 ALOGV("%s new encoder delay %u and padding %u", __func__,
1963 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1964
1965 return 0;
1966}
1967
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001968static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1969{
1970 return out == adev->primary_output || out == adev->voice_tx_output;
1971}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1974{
1975 struct stream_out *out = (struct stream_out *)stream;
1976 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001977 struct audio_usecase *usecase;
1978 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979 struct str_parms *parms;
1980 char value[32];
1981 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001982 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001983 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984
Eric Laurent2e140aa2016-06-30 17:14:46 -07001985 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001986 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987 parms = str_parms_create_str(kvpairs);
1988 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1989 if (ret >= 0) {
1990 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001991 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001992 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001994 /*
1995 * When HDMI cable is unplugged the music playback is paused and
1996 * the policy manager sends routing=0. But the audioflinger
1997 * continues to write data until standby time (3sec).
1998 * As the HDMI core is turned off, the write gets blocked.
1999 * Avoid this by routing audio to speaker until standby.
2000 */
2001 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2002 val == AUDIO_DEVICE_NONE) {
2003 val = AUDIO_DEVICE_OUT_SPEAKER;
2004 }
2005
2006 /*
2007 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002008 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002009 * the select_devices(). But how do we undo this?
2010 *
2011 * For example, music playback is active on headset (deep-buffer usecase)
2012 * and if we go to ringtones and select a ringtone, low-latency usecase
2013 * will be started on headset+speaker. As we can't enable headset+speaker
2014 * and headset devices at the same time, select_devices() switches the music
2015 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2016 * So when the ringtone playback is completed, how do we undo the same?
2017 *
2018 * We are relying on the out_set_parameters() call on deep-buffer output,
2019 * once the ringtone playback is ended.
2020 * NOTE: We should not check if the current devices are same as new devices.
2021 * Because select_devices() must be called to switch back the music
2022 * playback to headset.
2023 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002024 audio_devices_t new_dev = val;
2025 if (new_dev != AUDIO_DEVICE_NONE) {
2026 bool same_dev = out->devices == new_dev;
2027 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002028
Eric Laurenta7657192014-10-09 21:09:33 -07002029 if (output_drives_call(adev, out)) {
2030 if (!voice_is_in_call(adev)) {
2031 if (adev->mode == AUDIO_MODE_IN_CALL) {
2032 adev->current_call_output = out;
2033 ret = voice_start_call(adev);
2034 }
2035 } else {
2036 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002037 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002038 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002039 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002040
2041 if (!out->standby) {
2042 if (!same_dev) {
2043 ALOGV("update routing change");
2044 out->routing_change = true;
2045 }
2046 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002047 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002048 }
2049
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002050 }
2051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002053 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002054
2055 /*handles device and call state changes*/
2056 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002058
2059 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2060 parse_compress_metadata(out, parms);
2061 }
2062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002064 ALOGV("%s: exit: code(%d)", __func__, status);
2065 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066}
2067
2068static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2069{
2070 struct stream_out *out = (struct stream_out *)stream;
2071 struct str_parms *query = str_parms_create_str(keys);
2072 char *str;
2073 char value[256];
2074 struct str_parms *reply = str_parms_create();
2075 size_t i, j;
2076 int ret;
2077 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002078 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002079 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2080 if (ret >= 0) {
2081 value[0] = '\0';
2082 i = 0;
2083 while (out->supported_channel_masks[i] != 0) {
2084 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2085 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2086 if (!first) {
2087 strcat(value, "|");
2088 }
2089 strcat(value, out_channels_name_to_enum_table[j].name);
2090 first = false;
2091 break;
2092 }
2093 }
2094 i++;
2095 }
2096 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2097 str = str_parms_to_str(reply);
2098 } else {
2099 str = strdup(keys);
2100 }
2101 str_parms_destroy(query);
2102 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002103 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104 return str;
2105}
2106
2107static uint32_t out_get_latency(const struct audio_stream_out *stream)
2108{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002109 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110 struct stream_out *out = (struct stream_out *)stream;
2111
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002112 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2113 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002114 else if (out->realtime) {
2115 // since the buffer won't be filled up faster than realtime,
2116 // return a smaller number
2117 period_ms = (out->af_period_multiplier * out->config.period_size *
2118 1000) / (out->config.rate);
2119 hw_delay = platform_render_latency(out->usecase)/1000;
2120 return period_ms + hw_delay;
2121 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002122
2123 return (out->config.period_count * out->config.period_size * 1000) /
2124 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125}
2126
2127static int out_set_volume(struct audio_stream_out *stream, float left,
2128 float right)
2129{
Eric Laurenta9024de2013-04-04 09:19:12 -07002130 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002131 int volume[2];
2132
Eric Laurenta9024de2013-04-04 09:19:12 -07002133 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2134 /* only take left channel into account: the API is for stereo anyway */
2135 out->muted = (left == 0.0f);
2136 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002137 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2138 const char *mixer_ctl_name = "Compress Playback Volume";
2139 struct audio_device *adev = out->dev;
2140 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002141 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2142 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002143 /* try with the control based on device id */
2144 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2145 PCM_PLAYBACK);
2146 char ctl_name[128] = {0};
2147 snprintf(ctl_name, sizeof(ctl_name),
2148 "Compress Playback %d Volume", pcm_device_id);
2149 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2150 if (!ctl) {
2151 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2152 return -EINVAL;
2153 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002154 }
2155 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2156 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2157 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2158 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002159 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161 return -ENOSYS;
2162}
2163
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002164// note: this call is safe only if the stream_cb is
2165// removed first in close_output_stream (as is done now).
2166static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2167{
2168 if (!stream || !parms)
2169 return;
2170
2171 struct stream_out *out = (struct stream_out *)stream;
2172 struct audio_device *adev = out->dev;
2173
2174 card_status_t status;
2175 int card;
2176 if (parse_snd_card_status(parms, &card, &status) < 0)
2177 return;
2178
2179 pthread_mutex_lock(&adev->lock);
2180 bool valid_cb = (card == adev->snd_card);
2181 pthread_mutex_unlock(&adev->lock);
2182
2183 if (!valid_cb)
2184 return;
2185
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002186 lock_output_stream(out);
2187 if (out->card_status != status)
2188 out->card_status = status;
2189 pthread_mutex_unlock(&out->lock);
2190
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002191 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2192 use_case_table[out->usecase],
2193 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2194
2195 if (status == CARD_STATUS_OFFLINE)
2196 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002197
2198 return;
2199}
2200
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002201#ifdef NO_AUDIO_OUT
2202static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
2203 const void *buffer, size_t bytes)
2204{
2205 struct stream_out *out = (struct stream_out *)stream;
2206
2207 /* No Output device supported other than BT for playback.
2208 * Sleep for the amount of buffer duration
2209 */
Eric Laurenta1478072015-09-21 17:21:52 -07002210 lock_output_stream(out);
Uday Kishore Pasupuletib14d76b2015-11-13 20:06:37 -08002211 usleep(bytes * 1000000 / audio_stream_out_frame_size(&out->stream.common) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002212 out_get_sample_rate(&out->stream.common));
2213 pthread_mutex_unlock(&out->lock);
2214 return bytes;
2215}
2216#endif
2217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2219 size_t bytes)
2220{
2221 struct stream_out *out = (struct stream_out *)stream;
2222 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002223 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002224 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225
Eric Laurenta1478072015-09-21 17:21:52 -07002226 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002228 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002229 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002231 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002232 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002233 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002234 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235 goto exit;
2236 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002237
2238 if (last_known_cal_step != -1) {
2239 ALOGD("%s: retry previous failed cal level set", __func__);
2240 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2241 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002243
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002244 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002245 ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
2246 if (out->send_new_metadata) {
2247 ALOGVV("send new gapless metadata");
2248 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2249 out->send_new_metadata = 0;
2250 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002251 unsigned int avail;
2252 struct timespec tstamp;
2253 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2254 /* Do not limit write size if the available frames count is unknown */
2255 if (ret != 0) {
2256 avail = bytes;
2257 }
2258 if (avail == 0) {
2259 ret = 0;
2260 } else {
2261 if (avail > bytes) {
2262 avail = bytes;
2263 }
2264 ret = compress_write(out->compr, buffer, avail);
2265 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2266 __func__, avail, ret);
2267 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002268
Eric Laurent6e895242013-09-05 16:10:57 -07002269 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002270 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2271 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002272 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002273 compress_start(out->compr);
2274 out->playback_started = 1;
2275 out->offload_state = OFFLOAD_STATE_PLAYING;
2276 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002277 if (ret < 0) {
2278 log_error_l(&out->error_log, ERROR_CODE_WRITE);
2279 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002280 pthread_mutex_unlock(&out->lock);
2281 return ret;
2282 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002283 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002284 if (out->pcm) {
2285 if (out->muted)
2286 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002287
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002288 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002289
Haynes Mathew George03c40102016-01-29 17:57:48 -08002290 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2291 out->config.rate;
2292 request_out_focus(out, ns);
2293
2294 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2295 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002296 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002297 else
2298 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002299
Haynes Mathew George03c40102016-01-29 17:57:48 -08002300 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002301 } else {
2302 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002303 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002304 }
2305
2306exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002307 // For PCM we always consume the buffer and return #bytes regardless of ret.
2308 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2309 out->written += bytes / (out->config.channels * sizeof(short));
2310 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002311 long long sleeptime_us = 0;
2312 if (ret != 0) {
2313 log_error_l(&out->error_log, error_code);
2314 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2315 ALOGE_IF(out->pcm != NULL,
2316 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
2317 sleeptime_us = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2318 out_get_sample_rate(&out->stream.common);
2319 // usleep not guaranteed for values over 1 second but we don't limit here.
2320 }
2321 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002322
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002323 pthread_mutex_unlock(&out->lock);
2324
2325 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002326 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002327 if (sleeptime_us != 0)
2328 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002329 }
2330 return bytes;
2331}
2332
2333static int out_get_render_position(const struct audio_stream_out *stream,
2334 uint32_t *dsp_frames)
2335{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002336 struct stream_out *out = (struct stream_out *)stream;
2337 *dsp_frames = 0;
2338 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002339 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002340 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002341 unsigned long frames = 0;
2342 // TODO: check return value
2343 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2344 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002345 ALOGVV("%s rendered frames %d sample_rate %d",
2346 __func__, *dsp_frames, out->sample_rate);
2347 }
2348 pthread_mutex_unlock(&out->lock);
2349 return 0;
2350 } else
2351 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352}
2353
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002354static int out_add_audio_effect(const struct audio_stream *stream __unused,
2355 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002356{
2357 return 0;
2358}
2359
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002360static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2361 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362{
2363 return 0;
2364}
2365
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002366static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2367 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368{
2369 return -EINVAL;
2370}
2371
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002372static int out_get_presentation_position(const struct audio_stream_out *stream,
2373 uint64_t *frames, struct timespec *timestamp)
2374{
2375 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002376 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002377 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002378
Eric Laurenta1478072015-09-21 17:21:52 -07002379 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002380
Eric Laurent949a0892013-09-20 09:20:13 -07002381 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2382 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002383 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002384 compress_get_tstamp(out->compr, &dsp_frames,
2385 &out->sample_rate);
2386 ALOGVV("%s rendered frames %ld sample_rate %d",
2387 __func__, dsp_frames, out->sample_rate);
2388 *frames = dsp_frames;
2389 ret = 0;
2390 /* this is the best we can do */
2391 clock_gettime(CLOCK_MONOTONIC, timestamp);
2392 }
2393 } else {
2394 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002395 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002396 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2397 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002398 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002399 // This adjustment accounts for buffering after app processor.
2400 // It is based on estimated DSP latency per use case, rather than exact.
2401 signed_frames -=
2402 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2403
Eric Laurent949a0892013-09-20 09:20:13 -07002404 // It would be unusual for this value to be negative, but check just in case ...
2405 if (signed_frames >= 0) {
2406 *frames = signed_frames;
2407 ret = 0;
2408 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002409 }
2410 }
2411 }
2412
2413 pthread_mutex_unlock(&out->lock);
2414
2415 return ret;
2416}
2417
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002418static int out_set_callback(struct audio_stream_out *stream,
2419 stream_callback_t callback, void *cookie)
2420{
2421 struct stream_out *out = (struct stream_out *)stream;
2422
2423 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002424 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002425 out->offload_callback = callback;
2426 out->offload_cookie = cookie;
2427 pthread_mutex_unlock(&out->lock);
2428 return 0;
2429}
2430
2431static int out_pause(struct audio_stream_out* stream)
2432{
2433 struct stream_out *out = (struct stream_out *)stream;
2434 int status = -ENOSYS;
2435 ALOGV("%s", __func__);
2436 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002437 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002438 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2439 status = compress_pause(out->compr);
2440 out->offload_state = OFFLOAD_STATE_PAUSED;
2441 }
2442 pthread_mutex_unlock(&out->lock);
2443 }
2444 return status;
2445}
2446
2447static int out_resume(struct audio_stream_out* stream)
2448{
2449 struct stream_out *out = (struct stream_out *)stream;
2450 int status = -ENOSYS;
2451 ALOGV("%s", __func__);
2452 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2453 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002454 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002455 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2456 status = compress_resume(out->compr);
2457 out->offload_state = OFFLOAD_STATE_PLAYING;
2458 }
2459 pthread_mutex_unlock(&out->lock);
2460 }
2461 return status;
2462}
2463
2464static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2465{
2466 struct stream_out *out = (struct stream_out *)stream;
2467 int status = -ENOSYS;
2468 ALOGV("%s", __func__);
2469 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002470 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002471 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2472 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2473 else
2474 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2475 pthread_mutex_unlock(&out->lock);
2476 }
2477 return status;
2478}
2479
2480static int out_flush(struct audio_stream_out* stream)
2481{
2482 struct stream_out *out = (struct stream_out *)stream;
2483 ALOGV("%s", __func__);
2484 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002485 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002486 stop_compressed_output_l(out);
2487 pthread_mutex_unlock(&out->lock);
2488 return 0;
2489 }
2490 return -ENOSYS;
2491}
2492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493/** audio_stream_in implementation **/
2494static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2495{
2496 struct stream_in *in = (struct stream_in *)stream;
2497
2498 return in->config.rate;
2499}
2500
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002501static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502{
2503 return -ENOSYS;
2504}
2505
2506static size_t in_get_buffer_size(const struct audio_stream *stream)
2507{
2508 struct stream_in *in = (struct stream_in *)stream;
2509
Haynes Mathew George03c40102016-01-29 17:57:48 -08002510 return in->config.period_size * in->af_period_multiplier *
2511 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512}
2513
2514static uint32_t in_get_channels(const struct audio_stream *stream)
2515{
2516 struct stream_in *in = (struct stream_in *)stream;
2517
2518 return in->channel_mask;
2519}
2520
vivek mehta4ed66e62016-04-15 23:33:34 -07002521static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522{
vivek mehta4ed66e62016-04-15 23:33:34 -07002523 struct stream_in *in = (struct stream_in *)stream;
2524 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002525}
2526
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002527static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528{
2529 return -ENOSYS;
2530}
2531
2532static int in_standby(struct audio_stream *stream)
2533{
2534 struct stream_in *in = (struct stream_in *)stream;
2535 struct audio_device *adev = in->dev;
2536 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07002537 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002538
2539 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002540
2541 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002542 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002543 audio_extn_sound_trigger_stop_lab(in);
2544 in->standby = true;
2545 }
2546
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002548 if (adev->adm_deregister_stream)
2549 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2550
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002551 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002552 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002553 if (in->pcm) {
2554 pcm_close(in->pcm);
2555 in->pcm = NULL;
2556 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002557 adev->enable_voicerx = false;
2558 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002559 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002560 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561 }
2562 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002563 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564 return status;
2565}
2566
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002567static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568{
2569 return 0;
2570}
2571
2572static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2573{
2574 struct stream_in *in = (struct stream_in *)stream;
2575 struct audio_device *adev = in->dev;
2576 struct str_parms *parms;
2577 char *str;
2578 char value[32];
2579 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002580 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581
Eric Laurent994a6932013-07-17 11:51:42 -07002582 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 parms = str_parms_create_str(kvpairs);
2584
2585 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2586
Eric Laurenta1478072015-09-21 17:21:52 -07002587 lock_input_stream(in);
2588
Eric Laurent150dbfe2013-02-27 14:31:02 -08002589 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590 if (ret >= 0) {
2591 val = atoi(value);
2592 /* no audio source uses val == 0 */
2593 if ((in->source != val) && (val != 0)) {
2594 in->source = val;
2595 }
2596 }
2597
2598 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600 if (ret >= 0) {
2601 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002602 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603 in->device = val;
2604 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002605 if (!in->standby) {
2606 ALOGV("update input routing change");
2607 in->routing_change = true;
2608 select_devices(adev, in->usecase);
2609 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002610 }
2611 }
2612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002614 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615
2616 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002617 ALOGV("%s: exit: status(%d)", __func__, status);
2618 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619}
2620
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002621static char* in_get_parameters(const struct audio_stream *stream __unused,
2622 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002623{
2624 return strdup("");
2625}
2626
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002627static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628{
2629 return 0;
2630}
2631
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002632static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2633{
2634 if (!stream || !parms)
2635 return;
2636
2637 struct stream_in *in = (struct stream_in *)stream;
2638 struct audio_device *adev = in->dev;
2639
2640 card_status_t status;
2641 int card;
2642 if (parse_snd_card_status(parms, &card, &status) < 0)
2643 return;
2644
2645 pthread_mutex_lock(&adev->lock);
2646 bool valid_cb = (card == adev->snd_card);
2647 pthread_mutex_unlock(&adev->lock);
2648
2649 if (!valid_cb)
2650 return;
2651
2652 lock_input_stream(in);
2653 if (in->card_status != status)
2654 in->card_status = status;
2655 pthread_mutex_unlock(&in->lock);
2656
2657 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2658 use_case_table[in->usecase],
2659 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2660
2661 // a better solution would be to report error back to AF and let
2662 // it put the stream to standby
2663 if (status == CARD_STATUS_OFFLINE)
2664 in_standby(&in->stream.common);
2665
2666 return;
2667}
2668
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2670 size_t bytes)
2671{
2672 struct stream_in *in = (struct stream_in *)stream;
2673 struct audio_device *adev = in->dev;
2674 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002675 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676
Eric Laurenta1478072015-09-21 17:21:52 -07002677 lock_input_stream(in);
2678
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002679 if (in->is_st_session) {
2680 ALOGVV(" %s: reading on st session bytes=%d", __func__, bytes);
2681 /* Read from sound trigger HAL */
2682 audio_extn_sound_trigger_read(in, buffer, bytes);
2683 pthread_mutex_unlock(&in->lock);
2684 return bytes;
2685 }
2686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002688 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002689 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002690 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 goto exit;
2693 }
2694 in->standby = 0;
2695 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696
Haynes Mathew George03c40102016-01-29 17:57:48 -08002697 //what's the duration requested by the client?
2698 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2699 in->config.rate;
2700 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002701
Haynes Mathew George03c40102016-01-29 17:57:48 -08002702 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002704 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002705 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002706 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002707 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002708 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002709 if (ret < 0) {
2710 ALOGE("Failed to read w/err %s", strerror(errno));
2711 ret = -errno;
2712 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002713 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2714 if (bytes % 4 == 0) {
2715 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2716 int_buf_stream = buffer;
2717 for (size_t itt=0; itt < bytes/4 ; itt++) {
2718 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002719 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002720 } else {
2721 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2722 ret = -EINVAL;
2723 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002724 }
2725 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726 }
2727
Haynes Mathew George03c40102016-01-29 17:57:48 -08002728 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002729
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730 /*
2731 * Instead of writing zeroes here, we could trust the hardware
2732 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002733 * 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 -08002734 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002735 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736 memset(buffer, 0, bytes);
2737
2738exit:
2739 pthread_mutex_unlock(&in->lock);
2740
2741 if (ret != 0) {
2742 in_standby(&in->stream.common);
2743 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002744 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002746 memset(buffer, 0, bytes); // clear return data
2747 }
2748 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002749 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750 }
2751 return bytes;
2752}
2753
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002754static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755{
2756 return 0;
2757}
2758
Andy Hung6ebe5962016-01-15 17:46:57 -08002759static int in_get_capture_position(const struct audio_stream_in *stream,
2760 int64_t *frames, int64_t *time)
2761{
2762 if (stream == NULL || frames == NULL || time == NULL) {
2763 return -EINVAL;
2764 }
2765 struct stream_in *in = (struct stream_in *)stream;
2766 int ret = -ENOSYS;
2767
2768 lock_input_stream(in);
2769 if (in->pcm) {
2770 struct timespec timestamp;
2771 unsigned int avail;
2772 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2773 *frames = in->frames_read + avail;
2774 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2775 ret = 0;
2776 }
2777 }
2778 pthread_mutex_unlock(&in->lock);
2779 return ret;
2780}
2781
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002782static int add_remove_audio_effect(const struct audio_stream *stream,
2783 effect_handle_t effect,
2784 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002785{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002786 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002787 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002788 int status = 0;
2789 effect_descriptor_t desc;
2790
2791 status = (*effect)->get_descriptor(effect, &desc);
2792 if (status != 0)
2793 return status;
2794
Eric Laurenta1478072015-09-21 17:21:52 -07002795 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002796 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002797 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002798 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002799 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002800 in->enable_aec != enable &&
2801 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2802 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002803 if (!enable)
2804 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002805 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2806 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2807 adev->enable_voicerx = enable;
2808 struct audio_usecase *usecase;
2809 struct listnode *node;
2810 list_for_each(node, &adev->usecase_list) {
2811 usecase = node_to_item(node, struct audio_usecase, list);
2812 if (usecase->type == PCM_PLAYBACK) {
2813 select_devices(adev, usecase->id);
2814 break;
2815 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002816 }
2817 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002818 if (!in->standby)
2819 select_devices(in->dev, in->usecase);
2820 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07002821 if (in->enable_ns != enable &&
2822 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2823 in->enable_ns = enable;
2824 if (!in->standby)
2825 select_devices(in->dev, in->usecase);
2826 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002827 pthread_mutex_unlock(&in->dev->lock);
2828 pthread_mutex_unlock(&in->lock);
2829
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002830 return 0;
2831}
2832
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002833static int in_add_audio_effect(const struct audio_stream *stream,
2834 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002835{
Eric Laurent994a6932013-07-17 11:51:42 -07002836 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002837 return add_remove_audio_effect(stream, effect, true);
2838}
2839
2840static int in_remove_audio_effect(const struct audio_stream *stream,
2841 effect_handle_t effect)
2842{
Eric Laurent994a6932013-07-17 11:51:42 -07002843 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002844 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002845}
2846
2847static int adev_open_output_stream(struct audio_hw_device *dev,
2848 audio_io_handle_t handle,
2849 audio_devices_t devices,
2850 audio_output_flags_t flags,
2851 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07002852 struct audio_stream_out **stream_out,
2853 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002854{
2855 struct audio_device *adev = (struct audio_device *)dev;
2856 struct stream_out *out;
2857 int i, ret;
2858
Eric Laurent994a6932013-07-17 11:51:42 -07002859 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860 __func__, config->sample_rate, config->channel_mask, devices, flags);
2861 *stream_out = NULL;
2862 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2863
2864 if (devices == AUDIO_DEVICE_NONE)
2865 devices = AUDIO_DEVICE_OUT_SPEAKER;
2866
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002867 out->flags = flags;
2868 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002869 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002870 out->format = config->format;
2871 out->sample_rate = config->sample_rate;
2872 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2873 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002874 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875
2876 /* Init use case and pcm_config */
2877 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07002878 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002880 pthread_mutex_lock(&adev->lock);
2881 ret = read_hdmi_channel_masks(out);
2882 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002883 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002884 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002885
2886 if (config->sample_rate == 0)
2887 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2888 if (config->channel_mask == 0)
2889 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08002890 if (config->format == AUDIO_FORMAT_DEFAULT)
2891 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002892
2893 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002894 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08002895 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002896 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2897 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002898 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002899 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002900 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002901 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07002902 pthread_mutex_lock(&adev->lock);
2903 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
2904 pthread_mutex_unlock(&adev->lock);
2905
2906 // reject offload during card offline to allow
2907 // fallback to s/w paths
2908 if (offline) {
2909 ret = -ENODEV;
2910 goto error_open;
2911 }
2912
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002913 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2914 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2915 ALOGE("%s: Unsupported Offload information", __func__);
2916 ret = -EINVAL;
2917 goto error_open;
2918 }
2919 if (!is_supported_format(config->offload_info.format)) {
2920 ALOGE("%s: Unsupported audio format", __func__);
2921 ret = -EINVAL;
2922 goto error_open;
2923 }
2924
2925 out->compr_config.codec = (struct snd_codec *)
2926 calloc(1, sizeof(struct snd_codec));
2927
2928 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
2929 if (config->offload_info.channel_mask)
2930 out->channel_mask = config->offload_info.channel_mask;
2931 else if (config->channel_mask)
2932 out->channel_mask = config->channel_mask;
2933 out->format = config->offload_info.format;
2934 out->sample_rate = config->offload_info.sample_rate;
2935
2936 out->stream.set_callback = out_set_callback;
2937 out->stream.pause = out_pause;
2938 out->stream.resume = out_resume;
2939 out->stream.drain = out_drain;
2940 out->stream.flush = out_flush;
2941
2942 out->compr_config.codec->id =
2943 get_snd_codec_id(config->offload_info.format);
2944 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
2945 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07002946 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002947 out->compr_config.codec->bit_rate =
2948 config->offload_info.bit_rate;
2949 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002950 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002951 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
2952
2953 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2954 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002955
2956 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002957 create_offload_callback_thread(out);
2958 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2959 __func__, config->offload_info.version,
2960 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002961 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2962 if (config->sample_rate == 0)
2963 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2964 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2965 config->sample_rate != 8000) {
2966 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2967 ret = -EINVAL;
2968 goto error_open;
2969 }
2970 out->sample_rate = config->sample_rate;
2971 out->config.rate = config->sample_rate;
2972 if (config->format == AUDIO_FORMAT_DEFAULT)
2973 config->format = AUDIO_FORMAT_PCM_16_BIT;
2974 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2975 config->format = AUDIO_FORMAT_PCM_16_BIT;
2976 ret = -EINVAL;
2977 goto error_open;
2978 }
2979 out->format = config->format;
2980 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2981 out->config = pcm_config_afe_proxy_playback;
2982 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07002984 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2985 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2986 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07002987 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
2988 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
2989 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07002990 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
2991 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002992 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
2993 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
2994 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Andy Hung6fcba9c2014-03-18 11:53:32 -07002995 } else {
2996 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2997 out->config = pcm_config_low_latency;
2998 }
2999 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3000 if (k_enable_extended_precision
3001 && pcm_params_format_test(adev->use_case_table[out->usecase],
3002 pcm_format_from_audio_format(config->format))) {
3003 out->config.format = pcm_format_from_audio_format(config->format);
3004 /* out->format already set to config->format */
3005 } else {
3006 /* deny the externally proposed config format
3007 * and use the one specified in audio_hw layer configuration.
3008 * Note: out->format is returned by out->stream.common.get_format()
3009 * and is used to set config->format in the code several lines below.
3010 */
3011 out->format = audio_format_from_pcm_format(out->config.format);
3012 }
3013 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003014 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003016 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3017 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003019 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003020 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003021 adev->primary_output = out;
3022 else {
3023 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003024 ret = -EEXIST;
3025 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003026 }
3027 }
3028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029 /* Check if this usecase is already existing */
3030 pthread_mutex_lock(&adev->lock);
3031 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3032 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003034 ret = -EEXIST;
3035 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036 }
3037 pthread_mutex_unlock(&adev->lock);
3038
3039 out->stream.common.get_sample_rate = out_get_sample_rate;
3040 out->stream.common.set_sample_rate = out_set_sample_rate;
3041 out->stream.common.get_buffer_size = out_get_buffer_size;
3042 out->stream.common.get_channels = out_get_channels;
3043 out->stream.common.get_format = out_get_format;
3044 out->stream.common.set_format = out_set_format;
3045 out->stream.common.standby = out_standby;
3046 out->stream.common.dump = out_dump;
3047 out->stream.common.set_parameters = out_set_parameters;
3048 out->stream.common.get_parameters = out_get_parameters;
3049 out->stream.common.add_audio_effect = out_add_audio_effect;
3050 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3051 out->stream.get_latency = out_get_latency;
3052 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003053#ifdef NO_AUDIO_OUT
3054 out->stream.write = out_write_for_no_output;
3055#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003057#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058 out->stream.get_render_position = out_get_render_position;
3059 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003060 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003061
Haynes Mathew George03c40102016-01-29 17:57:48 -08003062 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003064 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003065 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003067 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003068 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003069 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003071 config->format = out->stream.common.get_format(&out->stream.common);
3072 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3073 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3074
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003075
3076 /*
3077 By locking output stream before registering, we allow the callback
3078 to update stream's state only after stream's initial state is set to
3079 adev state.
3080 */
3081 lock_output_stream(out);
3082 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3083 pthread_mutex_lock(&adev->lock);
3084 out->card_status = adev->card_status;
3085 pthread_mutex_unlock(&adev->lock);
3086 pthread_mutex_unlock(&out->lock);
3087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003089 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003091
3092error_open:
3093 free(out);
3094 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003095 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003096 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097}
3098
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003099static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003100 struct audio_stream_out *stream)
3101{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003102 struct stream_out *out = (struct stream_out *)stream;
3103 struct audio_device *adev = out->dev;
3104
Eric Laurent994a6932013-07-17 11:51:42 -07003105 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003106
3107 // must deregister from sndmonitor first to prevent races
3108 // between the callback and close_stream
3109 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003111 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3112 destroy_offload_callback_thread(out);
3113
3114 if (out->compr_config.codec != NULL)
3115 free(out->compr_config.codec);
3116 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003117
3118 if (adev->voice_tx_output == out)
3119 adev->voice_tx_output = NULL;
3120
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003121 pthread_cond_destroy(&out->cond);
3122 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003124 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125}
3126
3127static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3128{
3129 struct audio_device *adev = (struct audio_device *)dev;
3130 struct str_parms *parms;
3131 char *str;
3132 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003133 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003135 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136
Joe Onorato188b6222016-03-01 11:02:27 -08003137 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003138
3139 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140
3141 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003142 status = voice_set_parameters(adev, parms);
3143 if (status != 0) {
3144 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145 }
3146
3147 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3148 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003149 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3151 adev->bluetooth_nrec = true;
3152 else
3153 adev->bluetooth_nrec = false;
3154 }
3155
3156 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3157 if (ret >= 0) {
3158 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3159 adev->screen_off = false;
3160 else
3161 adev->screen_off = true;
3162 }
3163
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003164 ret = str_parms_get_int(parms, "rotation", &val);
3165 if (ret >= 0) {
3166 bool reverse_speakers = false;
3167 switch(val) {
3168 // FIXME: note that the code below assumes that the speakers are in the correct placement
3169 // relative to the user when the device is rotated 90deg from its default rotation. This
3170 // assumption is device-specific, not platform-specific like this code.
3171 case 270:
3172 reverse_speakers = true;
3173 break;
3174 case 0:
3175 case 90:
3176 case 180:
3177 break;
3178 default:
3179 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003180 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003181 }
Eric Laurent03f09432014-03-25 18:09:11 -07003182 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003183 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003184 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003185 }
3186
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003187 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3188 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003189 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003190 }
3191
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003192 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003193done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003195 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003196 ALOGV("%s: exit with code(%d)", __func__, status);
3197 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198}
3199
3200static char* adev_get_parameters(const struct audio_hw_device *dev,
3201 const char *keys)
3202{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003203 struct audio_device *adev = (struct audio_device *)dev;
3204 struct str_parms *reply = str_parms_create();
3205 struct str_parms *query = str_parms_create_str(keys);
3206 char *str;
3207
3208 pthread_mutex_lock(&adev->lock);
3209
3210 voice_get_parameters(adev, query, reply);
3211 str = str_parms_to_str(reply);
3212 str_parms_destroy(query);
3213 str_parms_destroy(reply);
3214
3215 pthread_mutex_unlock(&adev->lock);
3216 ALOGV("%s: exit: returns - %s", __func__, str);
3217 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218}
3219
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003220static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221{
3222 return 0;
3223}
3224
Haynes Mathew George5191a852013-09-11 14:19:36 -07003225static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3226{
3227 int ret;
3228 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003229
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003230 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3231
Haynes Mathew George5191a852013-09-11 14:19:36 -07003232 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003233 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003234 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003235
Haynes Mathew George5191a852013-09-11 14:19:36 -07003236 return ret;
3237}
3238
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003239static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240{
3241 return -ENOSYS;
3242}
3243
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003244static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3245 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003246{
3247 return -ENOSYS;
3248}
3249
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003250static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003251{
3252 return -ENOSYS;
3253}
3254
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003255static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256{
3257 return -ENOSYS;
3258}
3259
3260static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3261{
3262 struct audio_device *adev = (struct audio_device *)dev;
3263
3264 pthread_mutex_lock(&adev->lock);
3265 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003266 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003267 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003268 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3269 voice_is_in_call(adev)) {
3270 voice_stop_call(adev);
3271 adev->current_call_output = NULL;
3272 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273 }
3274 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003275
3276 audio_extn_extspk_set_mode(adev->extspk, mode);
3277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278 return 0;
3279}
3280
3281static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3282{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003283 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003284 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285
Eric Laurent2bafff12016-03-17 12:17:23 -07003286 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003287 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003288 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3289 ret = audio_extn_hfp_set_mic_mute(adev, state);
3290 } else {
3291 ret = voice_set_mic_mute(adev, state);
3292 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003293 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003294 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003295
3296 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003297}
3298
3299static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3300{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003301 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302 return 0;
3303}
3304
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003305static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306 const struct audio_config *config)
3307{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003308 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003310 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3311 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312}
3313
3314static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003315 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316 audio_devices_t devices,
3317 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003318 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003319 audio_input_flags_t flags,
3320 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003321 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322{
3323 struct audio_device *adev = (struct audio_device *)dev;
3324 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003325 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003326 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003327 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328
Eric Laurent994a6932013-07-17 11:51:42 -07003329 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330 *stream_in = NULL;
3331 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3332 return -EINVAL;
3333
Zheng Zhang6185d572016-12-01 20:35:17 +08003334 if (audio_extn_tfa_98xx_is_supported() && (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003335 return -EINVAL;
3336
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3338
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003339 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003340 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003341
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003342 in->stream.common.get_sample_rate = in_get_sample_rate;
3343 in->stream.common.set_sample_rate = in_set_sample_rate;
3344 in->stream.common.get_buffer_size = in_get_buffer_size;
3345 in->stream.common.get_channels = in_get_channels;
3346 in->stream.common.get_format = in_get_format;
3347 in->stream.common.set_format = in_set_format;
3348 in->stream.common.standby = in_standby;
3349 in->stream.common.dump = in_dump;
3350 in->stream.common.set_parameters = in_set_parameters;
3351 in->stream.common.get_parameters = in_get_parameters;
3352 in->stream.common.add_audio_effect = in_add_audio_effect;
3353 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3354 in->stream.set_gain = in_set_gain;
3355 in->stream.read = in_read;
3356 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003357 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003358
3359 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003360 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003361 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362 in->standby = 1;
3363 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003364 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003365 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366
vivek mehta57ff9b52016-04-28 14:13:08 -07003367 // restrict 24 bit capture for unprocessed source only
3368 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3369 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003370 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003371 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3372 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3373 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3374 bool ret_error = false;
3375 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3376 from HAL is 8_24
3377 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3378 8_24 return error indicating supported format is 8_24
3379 *> In case of any other source requesting 24 bit or float return error
3380 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003381
vivek mehta57ff9b52016-04-28 14:13:08 -07003382 on error flinger will retry with supported format passed
3383 */
3384 if (source != AUDIO_SOURCE_UNPROCESSED) {
3385 config->format = AUDIO_FORMAT_PCM_16_BIT;
3386 ret_error = true;
3387 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3388 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3389 ret_error = true;
3390 }
3391
3392 if (ret_error) {
3393 ret = -EINVAL;
3394 goto err_open;
3395 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003396 }
3397
vivek mehta57ff9b52016-04-28 14:13:08 -07003398 in->format = config->format;
3399
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003401 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3402 if (config->sample_rate == 0)
3403 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3404 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3405 config->sample_rate != 8000) {
3406 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3407 ret = -EINVAL;
3408 goto err_open;
3409 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003410
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003411 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3412 config->format = AUDIO_FORMAT_PCM_16_BIT;
3413 ret = -EINVAL;
3414 goto err_open;
3415 }
3416
3417 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3418 in->config = pcm_config_afe_proxy_record;
3419 } else {
3420 in->usecase = USECASE_AUDIO_RECORD;
3421 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3422 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3423 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003424#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003425 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003426#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003427 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003428 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003429
Haynes Mathew George03c40102016-01-29 17:57:48 -08003430 in->config = in->realtime ? pcm_config_audio_capture_rt :
3431 pcm_config_audio_capture;
3432
vivek mehta4ed66e62016-04-15 23:33:34 -07003433 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3434 in->config.format = PCM_FORMAT_S24_LE;
3435
Haynes Mathew George03c40102016-01-29 17:57:48 -08003436 if (!in->realtime) {
3437 frame_size = audio_stream_in_frame_size(&in->stream);
3438 buffer_size = get_input_buffer_size(config->sample_rate,
3439 config->format,
3440 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003441 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003442 in->config.period_size = buffer_size / frame_size;
3443 } // period size is left untouched for rt mode playback
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003444 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003445
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003446 in->config.channels = channel_count;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003447 if (in->realtime) {
3448 in->af_period_multiplier = af_period_multiplier;
3449 } else {
3450 in->config.rate = config->sample_rate;
3451 in->af_period_multiplier = 1;
3452 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003454 /* This stream could be for sound trigger lab,
3455 get sound trigger pcm if present */
3456 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003458 lock_input_stream(in);
3459 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3460 pthread_mutex_lock(&adev->lock);
3461 in->card_status = adev->card_status;
3462 pthread_mutex_unlock(&adev->lock);
3463 pthread_mutex_unlock(&in->lock);
3464
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003466 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003467 return 0;
3468
3469err_open:
3470 free(in);
3471 *stream_in = NULL;
3472 return ret;
3473}
3474
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003475static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476 struct audio_stream_in *stream)
3477{
Eric Laurent994a6932013-07-17 11:51:42 -07003478 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003479
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003480 // must deregister from sndmonitor first to prevent races
3481 // between the callback and close_stream
3482 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483 in_standby(&stream->common);
3484 free(stream);
3485
3486 return;
3487}
3488
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003489static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490{
3491 return 0;
3492}
3493
Andy Hung31aca912014-03-20 17:14:59 -07003494/* verifies input and output devices and their capabilities.
3495 *
3496 * This verification is required when enabling extended bit-depth or
3497 * sampling rates, as not all qcom products support it.
3498 *
3499 * Suitable for calling only on initialization such as adev_open().
3500 * It fills the audio_device use_case_table[] array.
3501 *
3502 * Has a side-effect that it needs to configure audio routing / devices
3503 * in order to power up the devices and read the device parameters.
3504 * It does not acquire any hw device lock. Should restore the devices
3505 * back to "normal state" upon completion.
3506 */
3507static int adev_verify_devices(struct audio_device *adev)
3508{
3509 /* enumeration is a bit difficult because one really wants to pull
3510 * the use_case, device id, etc from the hidden pcm_device_table[].
3511 * In this case there are the following use cases and device ids.
3512 *
3513 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3514 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3515 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3516 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3517 * [USECASE_AUDIO_RECORD] = {0, 0},
3518 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3519 * [USECASE_VOICE_CALL] = {2, 2},
3520 *
3521 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3522 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3523 */
3524
3525 /* should be the usecases enabled in adev_open_input_stream() */
3526 static const int test_in_usecases[] = {
3527 USECASE_AUDIO_RECORD,
3528 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3529 };
3530 /* should be the usecases enabled in adev_open_output_stream()*/
3531 static const int test_out_usecases[] = {
3532 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3533 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3534 };
3535 static const usecase_type_t usecase_type_by_dir[] = {
3536 PCM_PLAYBACK,
3537 PCM_CAPTURE,
3538 };
3539 static const unsigned flags_by_dir[] = {
3540 PCM_OUT,
3541 PCM_IN,
3542 };
3543
3544 size_t i;
3545 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003546 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003547 char info[512]; /* for possible debug info */
3548
3549 for (dir = 0; dir < 2; ++dir) {
3550 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3551 const unsigned flags_dir = flags_by_dir[dir];
3552 const size_t testsize =
3553 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3554 const int *testcases =
3555 dir ? test_in_usecases : test_out_usecases;
3556 const audio_devices_t audio_device =
3557 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3558
3559 for (i = 0; i < testsize; ++i) {
3560 const audio_usecase_t audio_usecase = testcases[i];
3561 int device_id;
3562 snd_device_t snd_device;
3563 struct pcm_params **pparams;
3564 struct stream_out out;
3565 struct stream_in in;
3566 struct audio_usecase uc_info;
3567 int retval;
3568
3569 pparams = &adev->use_case_table[audio_usecase];
3570 pcm_params_free(*pparams); /* can accept null input */
3571 *pparams = NULL;
3572
3573 /* find the device ID for the use case (signed, for error) */
3574 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3575 if (device_id < 0)
3576 continue;
3577
3578 /* prepare structures for device probing */
3579 memset(&uc_info, 0, sizeof(uc_info));
3580 uc_info.id = audio_usecase;
3581 uc_info.type = usecase_type;
3582 if (dir) {
3583 adev->active_input = &in;
3584 memset(&in, 0, sizeof(in));
3585 in.device = audio_device;
3586 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3587 uc_info.stream.in = &in;
3588 } else {
3589 adev->active_input = NULL;
3590 }
3591 memset(&out, 0, sizeof(out));
3592 out.devices = audio_device; /* only field needed in select_devices */
3593 uc_info.stream.out = &out;
3594 uc_info.devices = audio_device;
3595 uc_info.in_snd_device = SND_DEVICE_NONE;
3596 uc_info.out_snd_device = SND_DEVICE_NONE;
3597 list_add_tail(&adev->usecase_list, &uc_info.list);
3598
3599 /* select device - similar to start_(in/out)put_stream() */
3600 retval = select_devices(adev, audio_usecase);
3601 if (retval >= 0) {
3602 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3603#if LOG_NDEBUG == 0
3604 if (*pparams) {
3605 ALOGV("%s: (%s) card %d device %d", __func__,
3606 dir ? "input" : "output", card_id, device_id);
3607 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07003608 } else {
3609 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3610 }
3611#endif
3612 }
3613
3614 /* deselect device - similar to stop_(in/out)put_stream() */
3615 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07003616 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07003617 /* 2. Disable the rx device */
3618 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07003619 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07003620 list_remove(&uc_info.list);
3621 }
3622 }
3623 adev->active_input = NULL; /* restore adev state */
3624 return 0;
3625}
3626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627static int adev_close(hw_device_t *device)
3628{
Andy Hung31aca912014-03-20 17:14:59 -07003629 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003631
3632 if (!adev)
3633 return 0;
3634
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003635 audio_extn_tfa_98xx_deinit();
3636
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003637 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003638 pthread_mutex_lock(&adev_init_lock);
3639
3640 if ((--audio_device_ref_count) == 0) {
3641 audio_route_free(adev->audio_route);
3642 free(adev->snd_dev_ref_cnt);
3643 platform_deinit(adev->platform);
3644 audio_extn_extspk_deinit(adev->extspk);
3645 audio_extn_sound_trigger_deinit(adev);
3646 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3647 pcm_params_free(adev->use_case_table[i]);
3648 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003649 if (adev->adm_deinit)
3650 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003651 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07003652 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07003653
3654 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656 return 0;
3657}
3658
Glenn Kasten4f993392014-05-14 07:30:48 -07003659/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3660 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3661 * just that it _might_ work.
3662 */
3663static int period_size_is_plausible_for_low_latency(int period_size)
3664{
3665 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003666 case 48:
3667 case 96:
3668 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07003669 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003670 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07003671 case 240:
3672 case 320:
3673 case 480:
3674 return 1;
3675 default:
3676 return 0;
3677 }
3678}
3679
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003680static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
3681{
3682 int card;
3683 card_status_t status;
3684
3685 if (!parms)
3686 return;
3687
3688 if (parse_snd_card_status(parms, &card, &status) < 0)
3689 return;
3690
3691 pthread_mutex_lock(&adev->lock);
3692 bool valid_cb = (card == adev->snd_card);
3693 if (valid_cb) {
3694 if (adev->card_status != status) {
3695 adev->card_status = status;
3696 platform_snd_card_update(adev->platform, status);
3697 }
3698 }
3699 pthread_mutex_unlock(&adev->lock);
3700 return;
3701}
3702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703static int adev_open(const hw_module_t *module, const char *name,
3704 hw_device_t **device)
3705{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003706 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707
Eric Laurent2bafff12016-03-17 12:17:23 -07003708 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003710 pthread_mutex_lock(&adev_init_lock);
3711 if (audio_device_ref_count != 0) {
3712 *device = &adev->device.common;
3713 audio_device_ref_count++;
3714 ALOGV("%s: returning existing instance of adev", __func__);
3715 ALOGV("%s: exit", __func__);
3716 pthread_mutex_unlock(&adev_init_lock);
3717 return 0;
3718 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719 adev = calloc(1, sizeof(struct audio_device));
3720
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003721 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3724 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3725 adev->device.common.module = (struct hw_module_t *)module;
3726 adev->device.common.close = adev_close;
3727
3728 adev->device.init_check = adev_init_check;
3729 adev->device.set_voice_volume = adev_set_voice_volume;
3730 adev->device.set_master_volume = adev_set_master_volume;
3731 adev->device.get_master_volume = adev_get_master_volume;
3732 adev->device.set_master_mute = adev_set_master_mute;
3733 adev->device.get_master_mute = adev_get_master_mute;
3734 adev->device.set_mode = adev_set_mode;
3735 adev->device.set_mic_mute = adev_set_mic_mute;
3736 adev->device.get_mic_mute = adev_get_mic_mute;
3737 adev->device.set_parameters = adev_set_parameters;
3738 adev->device.get_parameters = adev_get_parameters;
3739 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3740 adev->device.open_output_stream = adev_open_output_stream;
3741 adev->device.close_output_stream = adev_close_output_stream;
3742 adev->device.open_input_stream = adev_open_input_stream;
3743 adev->device.close_input_stream = adev_close_input_stream;
3744 adev->device.dump = adev_dump;
3745
3746 /* Set the default route before the PCM stream is opened */
3747 pthread_mutex_lock(&adev->lock);
3748 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003749 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003750 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003751 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003752 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003753 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003754 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003755 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003756 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757 pthread_mutex_unlock(&adev->lock);
3758
3759 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003760 adev->platform = platform_init(adev);
3761 if (!adev->platform) {
3762 free(adev->snd_dev_ref_cnt);
3763 free(adev);
3764 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3765 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003766 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003767 return -EINVAL;
3768 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05003769 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003770 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003771
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003772 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3773 if (adev->visualizer_lib == NULL) {
3774 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3775 } else {
3776 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3777 adev->visualizer_start_output =
3778 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3779 "visualizer_hal_start_output");
3780 adev->visualizer_stop_output =
3781 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3782 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07003783 }
3784
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003785 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3786 if (adev->offload_effects_lib == NULL) {
3787 ALOGW("%s: DLOPEN failed for %s", __func__,
3788 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3789 } else {
3790 ALOGV("%s: DLOPEN successful for %s", __func__,
3791 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3792 adev->offload_effects_start_output =
3793 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3794 "offload_effects_bundle_hal_start_output");
3795 adev->offload_effects_stop_output =
3796 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3797 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07003798 }
3799
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003800 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3801 if (adev->adm_lib == NULL) {
3802 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3803 } else {
3804 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3805 adev->adm_init = (adm_init_t)
3806 dlsym(adev->adm_lib, "adm_init");
3807 adev->adm_deinit = (adm_deinit_t)
3808 dlsym(adev->adm_lib, "adm_deinit");
3809 adev->adm_register_input_stream = (adm_register_input_stream_t)
3810 dlsym(adev->adm_lib, "adm_register_input_stream");
3811 adev->adm_register_output_stream = (adm_register_output_stream_t)
3812 dlsym(adev->adm_lib, "adm_register_output_stream");
3813 adev->adm_deregister_stream = (adm_deregister_stream_t)
3814 dlsym(adev->adm_lib, "adm_deregister_stream");
3815 adev->adm_request_focus = (adm_request_focus_t)
3816 dlsym(adev->adm_lib, "adm_request_focus");
3817 adev->adm_abandon_focus = (adm_abandon_focus_t)
3818 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08003819 adev->adm_set_config = (adm_set_config_t)
3820 dlsym(adev->adm_lib, "adm_set_config");
3821 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
3822 dlsym(adev->adm_lib, "adm_request_focus_v2");
3823 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
3824 dlsym(adev->adm_lib, "adm_is_noirq_avail");
3825 adev->adm_on_routing_change = (adm_on_routing_change_t)
3826 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003827 }
3828
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003829 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003830 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003831
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003832 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003833
Andy Hung31aca912014-03-20 17:14:59 -07003834 if (k_enable_extended_precision)
3835 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003836
Glenn Kasten4f993392014-05-14 07:30:48 -07003837 char value[PROPERTY_VALUE_MAX];
3838 int trial;
3839 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3840 trial = atoi(value);
3841 if (period_size_is_plausible_for_low_latency(trial)) {
3842 pcm_config_low_latency.period_size = trial;
3843 pcm_config_low_latency.start_threshold = trial / 4;
3844 pcm_config_low_latency.avail_min = trial / 4;
3845 configured_low_latency_capture_period_size = trial;
3846 }
3847 }
3848 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3849 trial = atoi(value);
3850 if (period_size_is_plausible_for_low_latency(trial)) {
3851 configured_low_latency_capture_period_size = trial;
3852 }
3853 }
3854
Yamit Mehtae3b99562016-09-16 22:44:00 +05303855 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003856 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003857
3858 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
3859 af_period_multiplier = atoi(value);
3860 if (af_period_multiplier < 0) {
3861 af_period_multiplier = 2;
3862 } else if (af_period_multiplier > 4) {
3863 af_period_multiplier = 4;
3864 }
3865 ALOGV("new period_multiplier = %d", af_period_multiplier);
3866 }
3867
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003868 audio_extn_tfa_98xx_init(adev);
3869
vivek mehta1a9b7c02015-06-25 11:49:38 -07003870 pthread_mutex_unlock(&adev_init_lock);
3871
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003872 if (adev->adm_init)
3873 adev->adm_data = adev->adm_init();
3874
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003875 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003876 audio_extn_snd_mon_init();
3877 pthread_mutex_lock(&adev->lock);
3878 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
3879 adev->card_status = CARD_STATUS_ONLINE;
3880 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003881
Eric Laurent2bafff12016-03-17 12:17:23 -07003882 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003883 return 0;
3884}
3885
3886static struct hw_module_methods_t hal_module_methods = {
3887 .open = adev_open,
3888};
3889
3890struct audio_module HAL_MODULE_INFO_SYM = {
3891 .common = {
3892 .tag = HARDWARE_MODULE_TAG,
3893 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3894 .hal_api_version = HARDWARE_HAL_API_VERSION,
3895 .id = AUDIO_HARDWARE_MODULE_ID,
3896 .name = "QCOM Audio HAL",
3897 .author = "Code Aurora Forum",
3898 .methods = &hal_module_methods,
3899 },
3900};