blob: 3245fa58e03c9339187f906501cea7d40a83f529 [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,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002203 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002204{
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);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002211 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2212 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002213 out_get_sample_rate(&out->stream.common));
2214 pthread_mutex_unlock(&out->lock);
2215 return bytes;
2216}
2217#endif
2218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2220 size_t bytes)
2221{
2222 struct stream_out *out = (struct stream_out *)stream;
2223 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002224 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002225 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226
Eric Laurenta1478072015-09-21 17:21:52 -07002227 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002229 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002230 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002232 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002233 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002235 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236 goto exit;
2237 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002238
2239 if (last_known_cal_step != -1) {
2240 ALOGD("%s: retry previous failed cal level set", __func__);
2241 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2242 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002243 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002245 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002246 ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
2247 if (out->send_new_metadata) {
2248 ALOGVV("send new gapless metadata");
2249 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2250 out->send_new_metadata = 0;
2251 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002252 unsigned int avail;
2253 struct timespec tstamp;
2254 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2255 /* Do not limit write size if the available frames count is unknown */
2256 if (ret != 0) {
2257 avail = bytes;
2258 }
2259 if (avail == 0) {
2260 ret = 0;
2261 } else {
2262 if (avail > bytes) {
2263 avail = bytes;
2264 }
2265 ret = compress_write(out->compr, buffer, avail);
2266 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2267 __func__, avail, ret);
2268 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002269
Eric Laurent6e895242013-09-05 16:10:57 -07002270 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002271 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2272 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002273 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002274 compress_start(out->compr);
2275 out->playback_started = 1;
2276 out->offload_state = OFFLOAD_STATE_PLAYING;
2277 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002278 if (ret < 0) {
2279 log_error_l(&out->error_log, ERROR_CODE_WRITE);
2280 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002281 pthread_mutex_unlock(&out->lock);
2282 return ret;
2283 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002284 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002285 if (out->pcm) {
2286 if (out->muted)
2287 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002288
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002289 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002290
Haynes Mathew George03c40102016-01-29 17:57:48 -08002291 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2292 out->config.rate;
2293 request_out_focus(out, ns);
2294
2295 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2296 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002297 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002298 else
2299 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002300
Haynes Mathew George03c40102016-01-29 17:57:48 -08002301 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002302 } else {
2303 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002304 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305 }
2306
2307exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002308 // For PCM we always consume the buffer and return #bytes regardless of ret.
2309 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2310 out->written += bytes / (out->config.channels * sizeof(short));
2311 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002312 long long sleeptime_us = 0;
2313 if (ret != 0) {
2314 log_error_l(&out->error_log, error_code);
2315 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2316 ALOGE_IF(out->pcm != NULL,
2317 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
2318 sleeptime_us = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2319 out_get_sample_rate(&out->stream.common);
2320 // usleep not guaranteed for values over 1 second but we don't limit here.
2321 }
2322 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002323
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002324 pthread_mutex_unlock(&out->lock);
2325
2326 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002327 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002328 if (sleeptime_us != 0)
2329 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002330 }
2331 return bytes;
2332}
2333
2334static int out_get_render_position(const struct audio_stream_out *stream,
2335 uint32_t *dsp_frames)
2336{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002337 struct stream_out *out = (struct stream_out *)stream;
2338 *dsp_frames = 0;
2339 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002340 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002341 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002342 unsigned long frames = 0;
2343 // TODO: check return value
2344 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2345 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002346 ALOGVV("%s rendered frames %d sample_rate %d",
2347 __func__, *dsp_frames, out->sample_rate);
2348 }
2349 pthread_mutex_unlock(&out->lock);
2350 return 0;
2351 } else
2352 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353}
2354
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002355static int out_add_audio_effect(const struct audio_stream *stream __unused,
2356 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002357{
2358 return 0;
2359}
2360
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002361static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2362 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363{
2364 return 0;
2365}
2366
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002367static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2368 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002369{
2370 return -EINVAL;
2371}
2372
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002373static int out_get_presentation_position(const struct audio_stream_out *stream,
2374 uint64_t *frames, struct timespec *timestamp)
2375{
2376 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002377 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002378 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002379
Eric Laurenta1478072015-09-21 17:21:52 -07002380 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002381
Eric Laurent949a0892013-09-20 09:20:13 -07002382 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2383 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002384 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002385 compress_get_tstamp(out->compr, &dsp_frames,
2386 &out->sample_rate);
2387 ALOGVV("%s rendered frames %ld sample_rate %d",
2388 __func__, dsp_frames, out->sample_rate);
2389 *frames = dsp_frames;
2390 ret = 0;
2391 /* this is the best we can do */
2392 clock_gettime(CLOCK_MONOTONIC, timestamp);
2393 }
2394 } else {
2395 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002396 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002397 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2398 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002399 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002400 // This adjustment accounts for buffering after app processor.
2401 // It is based on estimated DSP latency per use case, rather than exact.
2402 signed_frames -=
2403 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2404
Eric Laurent949a0892013-09-20 09:20:13 -07002405 // It would be unusual for this value to be negative, but check just in case ...
2406 if (signed_frames >= 0) {
2407 *frames = signed_frames;
2408 ret = 0;
2409 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002410 }
2411 }
2412 }
2413
2414 pthread_mutex_unlock(&out->lock);
2415
2416 return ret;
2417}
2418
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002419static int out_set_callback(struct audio_stream_out *stream,
2420 stream_callback_t callback, void *cookie)
2421{
2422 struct stream_out *out = (struct stream_out *)stream;
2423
2424 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002425 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002426 out->offload_callback = callback;
2427 out->offload_cookie = cookie;
2428 pthread_mutex_unlock(&out->lock);
2429 return 0;
2430}
2431
2432static int out_pause(struct audio_stream_out* stream)
2433{
2434 struct stream_out *out = (struct stream_out *)stream;
2435 int status = -ENOSYS;
2436 ALOGV("%s", __func__);
2437 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002438 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002439 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2440 status = compress_pause(out->compr);
2441 out->offload_state = OFFLOAD_STATE_PAUSED;
2442 }
2443 pthread_mutex_unlock(&out->lock);
2444 }
2445 return status;
2446}
2447
2448static int out_resume(struct audio_stream_out* stream)
2449{
2450 struct stream_out *out = (struct stream_out *)stream;
2451 int status = -ENOSYS;
2452 ALOGV("%s", __func__);
2453 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2454 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002455 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002456 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2457 status = compress_resume(out->compr);
2458 out->offload_state = OFFLOAD_STATE_PLAYING;
2459 }
2460 pthread_mutex_unlock(&out->lock);
2461 }
2462 return status;
2463}
2464
2465static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2466{
2467 struct stream_out *out = (struct stream_out *)stream;
2468 int status = -ENOSYS;
2469 ALOGV("%s", __func__);
2470 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002471 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002472 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2473 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2474 else
2475 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2476 pthread_mutex_unlock(&out->lock);
2477 }
2478 return status;
2479}
2480
2481static int out_flush(struct audio_stream_out* stream)
2482{
2483 struct stream_out *out = (struct stream_out *)stream;
2484 ALOGV("%s", __func__);
2485 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002486 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002487 stop_compressed_output_l(out);
2488 pthread_mutex_unlock(&out->lock);
2489 return 0;
2490 }
2491 return -ENOSYS;
2492}
2493
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494/** audio_stream_in implementation **/
2495static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2496{
2497 struct stream_in *in = (struct stream_in *)stream;
2498
2499 return in->config.rate;
2500}
2501
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002502static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503{
2504 return -ENOSYS;
2505}
2506
2507static size_t in_get_buffer_size(const struct audio_stream *stream)
2508{
2509 struct stream_in *in = (struct stream_in *)stream;
2510
Haynes Mathew George03c40102016-01-29 17:57:48 -08002511 return in->config.period_size * in->af_period_multiplier *
2512 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513}
2514
2515static uint32_t in_get_channels(const struct audio_stream *stream)
2516{
2517 struct stream_in *in = (struct stream_in *)stream;
2518
2519 return in->channel_mask;
2520}
2521
vivek mehta4ed66e62016-04-15 23:33:34 -07002522static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523{
vivek mehta4ed66e62016-04-15 23:33:34 -07002524 struct stream_in *in = (struct stream_in *)stream;
2525 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526}
2527
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002528static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529{
2530 return -ENOSYS;
2531}
2532
2533static int in_standby(struct audio_stream *stream)
2534{
2535 struct stream_in *in = (struct stream_in *)stream;
2536 struct audio_device *adev = in->dev;
2537 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07002538 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002539
2540 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002541
2542 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002543 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002544 audio_extn_sound_trigger_stop_lab(in);
2545 in->standby = true;
2546 }
2547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002549 if (adev->adm_deregister_stream)
2550 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2551
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002552 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002554 if (in->pcm) {
2555 pcm_close(in->pcm);
2556 in->pcm = NULL;
2557 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002558 adev->enable_voicerx = false;
2559 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002561 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002562 }
2563 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002564 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565 return status;
2566}
2567
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002568static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569{
2570 return 0;
2571}
2572
2573static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2574{
2575 struct stream_in *in = (struct stream_in *)stream;
2576 struct audio_device *adev = in->dev;
2577 struct str_parms *parms;
2578 char *str;
2579 char value[32];
2580 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002581 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582
Eric Laurent994a6932013-07-17 11:51:42 -07002583 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584 parms = str_parms_create_str(kvpairs);
2585
2586 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2587
Eric Laurenta1478072015-09-21 17:21:52 -07002588 lock_input_stream(in);
2589
Eric Laurent150dbfe2013-02-27 14:31:02 -08002590 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591 if (ret >= 0) {
2592 val = atoi(value);
2593 /* no audio source uses val == 0 */
2594 if ((in->source != val) && (val != 0)) {
2595 in->source = val;
2596 }
2597 }
2598
2599 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601 if (ret >= 0) {
2602 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002603 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604 in->device = val;
2605 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002606 if (!in->standby) {
2607 ALOGV("update input routing change");
2608 in->routing_change = true;
2609 select_devices(adev, in->usecase);
2610 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 }
2612 }
2613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002615 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616
2617 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002618 ALOGV("%s: exit: status(%d)", __func__, status);
2619 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002620}
2621
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002622static char* in_get_parameters(const struct audio_stream *stream __unused,
2623 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624{
2625 return strdup("");
2626}
2627
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002628static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629{
2630 return 0;
2631}
2632
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002633static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2634{
2635 if (!stream || !parms)
2636 return;
2637
2638 struct stream_in *in = (struct stream_in *)stream;
2639 struct audio_device *adev = in->dev;
2640
2641 card_status_t status;
2642 int card;
2643 if (parse_snd_card_status(parms, &card, &status) < 0)
2644 return;
2645
2646 pthread_mutex_lock(&adev->lock);
2647 bool valid_cb = (card == adev->snd_card);
2648 pthread_mutex_unlock(&adev->lock);
2649
2650 if (!valid_cb)
2651 return;
2652
2653 lock_input_stream(in);
2654 if (in->card_status != status)
2655 in->card_status = status;
2656 pthread_mutex_unlock(&in->lock);
2657
2658 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2659 use_case_table[in->usecase],
2660 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2661
2662 // a better solution would be to report error back to AF and let
2663 // it put the stream to standby
2664 if (status == CARD_STATUS_OFFLINE)
2665 in_standby(&in->stream.common);
2666
2667 return;
2668}
2669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2671 size_t bytes)
2672{
2673 struct stream_in *in = (struct stream_in *)stream;
2674 struct audio_device *adev = in->dev;
2675 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002676 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677
Eric Laurenta1478072015-09-21 17:21:52 -07002678 lock_input_stream(in);
2679
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002680 if (in->is_st_session) {
2681 ALOGVV(" %s: reading on st session bytes=%d", __func__, bytes);
2682 /* Read from sound trigger HAL */
2683 audio_extn_sound_trigger_read(in, buffer, bytes);
2684 pthread_mutex_unlock(&in->lock);
2685 return bytes;
2686 }
2687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002689 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002691 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002693 goto exit;
2694 }
2695 in->standby = 0;
2696 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697
Haynes Mathew George03c40102016-01-29 17:57:48 -08002698 //what's the duration requested by the client?
2699 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2700 in->config.rate;
2701 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002702
Haynes Mathew George03c40102016-01-29 17:57:48 -08002703 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002705 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002706 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002707 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002708 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002709 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002710 if (ret < 0) {
2711 ALOGE("Failed to read w/err %s", strerror(errno));
2712 ret = -errno;
2713 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002714 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2715 if (bytes % 4 == 0) {
2716 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2717 int_buf_stream = buffer;
2718 for (size_t itt=0; itt < bytes/4 ; itt++) {
2719 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002720 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002721 } else {
2722 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2723 ret = -EINVAL;
2724 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002725 }
2726 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727 }
2728
Haynes Mathew George03c40102016-01-29 17:57:48 -08002729 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731 /*
2732 * Instead of writing zeroes here, we could trust the hardware
2733 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002734 * 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 -08002735 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002736 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737 memset(buffer, 0, bytes);
2738
2739exit:
2740 pthread_mutex_unlock(&in->lock);
2741
2742 if (ret != 0) {
2743 in_standby(&in->stream.common);
2744 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002745 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002746 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002747 memset(buffer, 0, bytes); // clear return data
2748 }
2749 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002750 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751 }
2752 return bytes;
2753}
2754
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002755static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002756{
2757 return 0;
2758}
2759
Andy Hung6ebe5962016-01-15 17:46:57 -08002760static int in_get_capture_position(const struct audio_stream_in *stream,
2761 int64_t *frames, int64_t *time)
2762{
2763 if (stream == NULL || frames == NULL || time == NULL) {
2764 return -EINVAL;
2765 }
2766 struct stream_in *in = (struct stream_in *)stream;
2767 int ret = -ENOSYS;
2768
2769 lock_input_stream(in);
2770 if (in->pcm) {
2771 struct timespec timestamp;
2772 unsigned int avail;
2773 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2774 *frames = in->frames_read + avail;
2775 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2776 ret = 0;
2777 }
2778 }
2779 pthread_mutex_unlock(&in->lock);
2780 return ret;
2781}
2782
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002783static int add_remove_audio_effect(const struct audio_stream *stream,
2784 effect_handle_t effect,
2785 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002787 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002788 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002789 int status = 0;
2790 effect_descriptor_t desc;
2791
2792 status = (*effect)->get_descriptor(effect, &desc);
2793 if (status != 0)
2794 return status;
2795
Eric Laurenta1478072015-09-21 17:21:52 -07002796 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002797 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002798 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002799 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002800 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002801 in->enable_aec != enable &&
2802 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2803 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002804 if (!enable)
2805 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002806 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2807 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2808 adev->enable_voicerx = enable;
2809 struct audio_usecase *usecase;
2810 struct listnode *node;
2811 list_for_each(node, &adev->usecase_list) {
2812 usecase = node_to_item(node, struct audio_usecase, list);
2813 if (usecase->type == PCM_PLAYBACK) {
2814 select_devices(adev, usecase->id);
2815 break;
2816 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002817 }
2818 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002819 if (!in->standby)
2820 select_devices(in->dev, in->usecase);
2821 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07002822 if (in->enable_ns != enable &&
2823 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2824 in->enable_ns = enable;
2825 if (!in->standby)
2826 select_devices(in->dev, in->usecase);
2827 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002828 pthread_mutex_unlock(&in->dev->lock);
2829 pthread_mutex_unlock(&in->lock);
2830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 return 0;
2832}
2833
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002834static int in_add_audio_effect(const struct audio_stream *stream,
2835 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002836{
Eric Laurent994a6932013-07-17 11:51:42 -07002837 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002838 return add_remove_audio_effect(stream, effect, true);
2839}
2840
2841static int in_remove_audio_effect(const struct audio_stream *stream,
2842 effect_handle_t effect)
2843{
Eric Laurent994a6932013-07-17 11:51:42 -07002844 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002845 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002846}
2847
2848static int adev_open_output_stream(struct audio_hw_device *dev,
2849 audio_io_handle_t handle,
2850 audio_devices_t devices,
2851 audio_output_flags_t flags,
2852 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07002853 struct audio_stream_out **stream_out,
2854 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855{
2856 struct audio_device *adev = (struct audio_device *)dev;
2857 struct stream_out *out;
2858 int i, ret;
2859
Eric Laurent994a6932013-07-17 11:51:42 -07002860 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002861 __func__, config->sample_rate, config->channel_mask, devices, flags);
2862 *stream_out = NULL;
2863 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2864
2865 if (devices == AUDIO_DEVICE_NONE)
2866 devices = AUDIO_DEVICE_OUT_SPEAKER;
2867
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002868 out->flags = flags;
2869 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002870 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002871 out->format = config->format;
2872 out->sample_rate = config->sample_rate;
2873 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2874 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002875 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002876
2877 /* Init use case and pcm_config */
2878 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07002879 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002881 pthread_mutex_lock(&adev->lock);
2882 ret = read_hdmi_channel_masks(out);
2883 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002884 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002885 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002886
2887 if (config->sample_rate == 0)
2888 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2889 if (config->channel_mask == 0)
2890 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08002891 if (config->format == AUDIO_FORMAT_DEFAULT)
2892 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002893
2894 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08002896 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2898 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002899 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002900 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002901 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002902 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07002903 pthread_mutex_lock(&adev->lock);
2904 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
2905 pthread_mutex_unlock(&adev->lock);
2906
2907 // reject offload during card offline to allow
2908 // fallback to s/w paths
2909 if (offline) {
2910 ret = -ENODEV;
2911 goto error_open;
2912 }
2913
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002914 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2915 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2916 ALOGE("%s: Unsupported Offload information", __func__);
2917 ret = -EINVAL;
2918 goto error_open;
2919 }
2920 if (!is_supported_format(config->offload_info.format)) {
2921 ALOGE("%s: Unsupported audio format", __func__);
2922 ret = -EINVAL;
2923 goto error_open;
2924 }
2925
2926 out->compr_config.codec = (struct snd_codec *)
2927 calloc(1, sizeof(struct snd_codec));
2928
2929 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
2930 if (config->offload_info.channel_mask)
2931 out->channel_mask = config->offload_info.channel_mask;
2932 else if (config->channel_mask)
2933 out->channel_mask = config->channel_mask;
2934 out->format = config->offload_info.format;
2935 out->sample_rate = config->offload_info.sample_rate;
2936
2937 out->stream.set_callback = out_set_callback;
2938 out->stream.pause = out_pause;
2939 out->stream.resume = out_resume;
2940 out->stream.drain = out_drain;
2941 out->stream.flush = out_flush;
2942
2943 out->compr_config.codec->id =
2944 get_snd_codec_id(config->offload_info.format);
2945 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
2946 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07002947 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002948 out->compr_config.codec->bit_rate =
2949 config->offload_info.bit_rate;
2950 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002951 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002952 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
2953
2954 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2955 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002956
2957 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002958 create_offload_callback_thread(out);
2959 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2960 __func__, config->offload_info.version,
2961 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002962 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2963 if (config->sample_rate == 0)
2964 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2965 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2966 config->sample_rate != 8000) {
2967 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2968 ret = -EINVAL;
2969 goto error_open;
2970 }
2971 out->sample_rate = config->sample_rate;
2972 out->config.rate = config->sample_rate;
2973 if (config->format == AUDIO_FORMAT_DEFAULT)
2974 config->format = AUDIO_FORMAT_PCM_16_BIT;
2975 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2976 config->format = AUDIO_FORMAT_PCM_16_BIT;
2977 ret = -EINVAL;
2978 goto error_open;
2979 }
2980 out->format = config->format;
2981 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2982 out->config = pcm_config_afe_proxy_playback;
2983 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002984 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07002985 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2986 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2987 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07002988 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
2989 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
2990 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07002991 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
2992 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002993 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
2994 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
2995 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Andy Hung6fcba9c2014-03-18 11:53:32 -07002996 } else {
2997 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2998 out->config = pcm_config_low_latency;
2999 }
3000 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3001 if (k_enable_extended_precision
3002 && pcm_params_format_test(adev->use_case_table[out->usecase],
3003 pcm_format_from_audio_format(config->format))) {
3004 out->config.format = pcm_format_from_audio_format(config->format);
3005 /* out->format already set to config->format */
3006 } else {
3007 /* deny the externally proposed config format
3008 * and use the one specified in audio_hw layer configuration.
3009 * Note: out->format is returned by out->stream.common.get_format()
3010 * and is used to set config->format in the code several lines below.
3011 */
3012 out->format = audio_format_from_pcm_format(out->config.format);
3013 }
3014 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003015 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003017 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3018 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003020 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003021 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003022 adev->primary_output = out;
3023 else {
3024 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003025 ret = -EEXIST;
3026 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003027 }
3028 }
3029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030 /* Check if this usecase is already existing */
3031 pthread_mutex_lock(&adev->lock);
3032 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3033 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003035 ret = -EEXIST;
3036 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 }
3038 pthread_mutex_unlock(&adev->lock);
3039
3040 out->stream.common.get_sample_rate = out_get_sample_rate;
3041 out->stream.common.set_sample_rate = out_set_sample_rate;
3042 out->stream.common.get_buffer_size = out_get_buffer_size;
3043 out->stream.common.get_channels = out_get_channels;
3044 out->stream.common.get_format = out_get_format;
3045 out->stream.common.set_format = out_set_format;
3046 out->stream.common.standby = out_standby;
3047 out->stream.common.dump = out_dump;
3048 out->stream.common.set_parameters = out_set_parameters;
3049 out->stream.common.get_parameters = out_get_parameters;
3050 out->stream.common.add_audio_effect = out_add_audio_effect;
3051 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3052 out->stream.get_latency = out_get_latency;
3053 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003054#ifdef NO_AUDIO_OUT
3055 out->stream.write = out_write_for_no_output;
3056#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003058#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059 out->stream.get_render_position = out_get_render_position;
3060 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003061 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062
Haynes Mathew George03c40102016-01-29 17:57:48 -08003063 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003064 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003065 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003066 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003068 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003069 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003070 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3071
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003072 config->format = out->stream.common.get_format(&out->stream.common);
3073 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3074 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3075
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003076
3077 /*
3078 By locking output stream before registering, we allow the callback
3079 to update stream's state only after stream's initial state is set to
3080 adev state.
3081 */
3082 lock_output_stream(out);
3083 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3084 pthread_mutex_lock(&adev->lock);
3085 out->card_status = adev->card_status;
3086 pthread_mutex_unlock(&adev->lock);
3087 pthread_mutex_unlock(&out->lock);
3088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003090 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003091 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003092
3093error_open:
3094 free(out);
3095 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003096 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003097 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098}
3099
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003100static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101 struct audio_stream_out *stream)
3102{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003103 struct stream_out *out = (struct stream_out *)stream;
3104 struct audio_device *adev = out->dev;
3105
Eric Laurent994a6932013-07-17 11:51:42 -07003106 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003107
3108 // must deregister from sndmonitor first to prevent races
3109 // between the callback and close_stream
3110 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003112 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3113 destroy_offload_callback_thread(out);
3114
3115 if (out->compr_config.codec != NULL)
3116 free(out->compr_config.codec);
3117 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003118
3119 if (adev->voice_tx_output == out)
3120 adev->voice_tx_output = NULL;
3121
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003122 pthread_cond_destroy(&out->cond);
3123 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003124 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003125 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126}
3127
3128static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3129{
3130 struct audio_device *adev = (struct audio_device *)dev;
3131 struct str_parms *parms;
3132 char *str;
3133 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003134 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003136 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137
Joe Onorato188b6222016-03-01 11:02:27 -08003138 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003139
3140 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141
3142 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003143 status = voice_set_parameters(adev, parms);
3144 if (status != 0) {
3145 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146 }
3147
3148 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3149 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003150 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3152 adev->bluetooth_nrec = true;
3153 else
3154 adev->bluetooth_nrec = false;
3155 }
3156
3157 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3158 if (ret >= 0) {
3159 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3160 adev->screen_off = false;
3161 else
3162 adev->screen_off = true;
3163 }
3164
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003165 ret = str_parms_get_int(parms, "rotation", &val);
3166 if (ret >= 0) {
3167 bool reverse_speakers = false;
3168 switch(val) {
3169 // FIXME: note that the code below assumes that the speakers are in the correct placement
3170 // relative to the user when the device is rotated 90deg from its default rotation. This
3171 // assumption is device-specific, not platform-specific like this code.
3172 case 270:
3173 reverse_speakers = true;
3174 break;
3175 case 0:
3176 case 90:
3177 case 180:
3178 break;
3179 default:
3180 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003181 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003182 }
Eric Laurent03f09432014-03-25 18:09:11 -07003183 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003184 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003185 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003186 }
3187
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003188 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3189 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003190 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003191 }
3192
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003193 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003194done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003196 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003197 ALOGV("%s: exit with code(%d)", __func__, status);
3198 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199}
3200
3201static char* adev_get_parameters(const struct audio_hw_device *dev,
3202 const char *keys)
3203{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003204 struct audio_device *adev = (struct audio_device *)dev;
3205 struct str_parms *reply = str_parms_create();
3206 struct str_parms *query = str_parms_create_str(keys);
3207 char *str;
3208
3209 pthread_mutex_lock(&adev->lock);
3210
3211 voice_get_parameters(adev, query, reply);
3212 str = str_parms_to_str(reply);
3213 str_parms_destroy(query);
3214 str_parms_destroy(reply);
3215
3216 pthread_mutex_unlock(&adev->lock);
3217 ALOGV("%s: exit: returns - %s", __func__, str);
3218 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219}
3220
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003221static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222{
3223 return 0;
3224}
3225
Haynes Mathew George5191a852013-09-11 14:19:36 -07003226static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3227{
3228 int ret;
3229 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003230
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003231 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3232
Haynes Mathew George5191a852013-09-11 14:19:36 -07003233 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003234 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003235 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003236
Haynes Mathew George5191a852013-09-11 14:19:36 -07003237 return ret;
3238}
3239
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003240static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003241{
3242 return -ENOSYS;
3243}
3244
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003245static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3246 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247{
3248 return -ENOSYS;
3249}
3250
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003251static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252{
3253 return -ENOSYS;
3254}
3255
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003256static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257{
3258 return -ENOSYS;
3259}
3260
3261static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3262{
3263 struct audio_device *adev = (struct audio_device *)dev;
3264
3265 pthread_mutex_lock(&adev->lock);
3266 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003267 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003269 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3270 voice_is_in_call(adev)) {
3271 voice_stop_call(adev);
3272 adev->current_call_output = NULL;
3273 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274 }
3275 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003276
3277 audio_extn_extspk_set_mode(adev->extspk, mode);
3278
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279 return 0;
3280}
3281
3282static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3283{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003284 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003286
Eric Laurent2bafff12016-03-17 12:17:23 -07003287 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003288 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003289 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3290 ret = audio_extn_hfp_set_mic_mute(adev, state);
3291 } else {
3292 ret = voice_set_mic_mute(adev, state);
3293 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003294 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003295 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003296
3297 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298}
3299
3300static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3301{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003302 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003303 return 0;
3304}
3305
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003306static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307 const struct audio_config *config)
3308{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003309 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003311 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3312 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313}
3314
3315static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003316 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317 audio_devices_t devices,
3318 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003319 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003320 audio_input_flags_t flags,
3321 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003322 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003323{
3324 struct audio_device *adev = (struct audio_device *)dev;
3325 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003326 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003327 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003328 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329
Eric Laurent994a6932013-07-17 11:51:42 -07003330 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331 *stream_in = NULL;
3332 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3333 return -EINVAL;
3334
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003335 if (audio_extn_tfa_98xx_is_supported() && audio_extn_hfp_is_active(adev))
3336 return -EINVAL;
3337
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3339
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003340 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003341 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003342
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343 in->stream.common.get_sample_rate = in_get_sample_rate;
3344 in->stream.common.set_sample_rate = in_set_sample_rate;
3345 in->stream.common.get_buffer_size = in_get_buffer_size;
3346 in->stream.common.get_channels = in_get_channels;
3347 in->stream.common.get_format = in_get_format;
3348 in->stream.common.set_format = in_set_format;
3349 in->stream.common.standby = in_standby;
3350 in->stream.common.dump = in_dump;
3351 in->stream.common.set_parameters = in_set_parameters;
3352 in->stream.common.get_parameters = in_get_parameters;
3353 in->stream.common.add_audio_effect = in_add_audio_effect;
3354 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3355 in->stream.set_gain = in_set_gain;
3356 in->stream.read = in_read;
3357 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003358 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359
3360 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003361 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363 in->standby = 1;
3364 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003365 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003366 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367
vivek mehta57ff9b52016-04-28 14:13:08 -07003368 // restrict 24 bit capture for unprocessed source only
3369 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3370 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003371 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003372 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3373 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3374 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3375 bool ret_error = false;
3376 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3377 from HAL is 8_24
3378 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3379 8_24 return error indicating supported format is 8_24
3380 *> In case of any other source requesting 24 bit or float return error
3381 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003382
vivek mehta57ff9b52016-04-28 14:13:08 -07003383 on error flinger will retry with supported format passed
3384 */
3385 if (source != AUDIO_SOURCE_UNPROCESSED) {
3386 config->format = AUDIO_FORMAT_PCM_16_BIT;
3387 ret_error = true;
3388 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3389 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3390 ret_error = true;
3391 }
3392
3393 if (ret_error) {
3394 ret = -EINVAL;
3395 goto err_open;
3396 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003397 }
3398
vivek mehta57ff9b52016-04-28 14:13:08 -07003399 in->format = config->format;
3400
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003402 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3403 if (config->sample_rate == 0)
3404 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3405 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3406 config->sample_rate != 8000) {
3407 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3408 ret = -EINVAL;
3409 goto err_open;
3410 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003411
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003412 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3413 config->format = AUDIO_FORMAT_PCM_16_BIT;
3414 ret = -EINVAL;
3415 goto err_open;
3416 }
3417
3418 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3419 in->config = pcm_config_afe_proxy_record;
3420 } else {
3421 in->usecase = USECASE_AUDIO_RECORD;
3422 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3423 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3424 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003425#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003426 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003427#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003428 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003429 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003430
Haynes Mathew George03c40102016-01-29 17:57:48 -08003431 in->config = in->realtime ? pcm_config_audio_capture_rt :
3432 pcm_config_audio_capture;
3433
vivek mehta4ed66e62016-04-15 23:33:34 -07003434 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3435 in->config.format = PCM_FORMAT_S24_LE;
3436
Haynes Mathew George03c40102016-01-29 17:57:48 -08003437 if (!in->realtime) {
3438 frame_size = audio_stream_in_frame_size(&in->stream);
3439 buffer_size = get_input_buffer_size(config->sample_rate,
3440 config->format,
3441 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003442 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003443 in->config.period_size = buffer_size / frame_size;
3444 } // period size is left untouched for rt mode playback
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003445 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003446
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447 in->config.channels = channel_count;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003448 if (in->realtime) {
3449 in->af_period_multiplier = af_period_multiplier;
3450 } else {
3451 in->config.rate = config->sample_rate;
3452 in->af_period_multiplier = 1;
3453 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003455 /* This stream could be for sound trigger lab,
3456 get sound trigger pcm if present */
3457 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003458
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003459 lock_input_stream(in);
3460 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3461 pthread_mutex_lock(&adev->lock);
3462 in->card_status = adev->card_status;
3463 pthread_mutex_unlock(&adev->lock);
3464 pthread_mutex_unlock(&in->lock);
3465
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003467 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468 return 0;
3469
3470err_open:
3471 free(in);
3472 *stream_in = NULL;
3473 return ret;
3474}
3475
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003476static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477 struct audio_stream_in *stream)
3478{
Eric Laurent994a6932013-07-17 11:51:42 -07003479 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003480
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003481 // must deregister from sndmonitor first to prevent races
3482 // between the callback and close_stream
3483 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484 in_standby(&stream->common);
3485 free(stream);
3486
3487 return;
3488}
3489
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003490static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491{
3492 return 0;
3493}
3494
Andy Hung31aca912014-03-20 17:14:59 -07003495/* verifies input and output devices and their capabilities.
3496 *
3497 * This verification is required when enabling extended bit-depth or
3498 * sampling rates, as not all qcom products support it.
3499 *
3500 * Suitable for calling only on initialization such as adev_open().
3501 * It fills the audio_device use_case_table[] array.
3502 *
3503 * Has a side-effect that it needs to configure audio routing / devices
3504 * in order to power up the devices and read the device parameters.
3505 * It does not acquire any hw device lock. Should restore the devices
3506 * back to "normal state" upon completion.
3507 */
3508static int adev_verify_devices(struct audio_device *adev)
3509{
3510 /* enumeration is a bit difficult because one really wants to pull
3511 * the use_case, device id, etc from the hidden pcm_device_table[].
3512 * In this case there are the following use cases and device ids.
3513 *
3514 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3515 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3516 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3517 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3518 * [USECASE_AUDIO_RECORD] = {0, 0},
3519 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3520 * [USECASE_VOICE_CALL] = {2, 2},
3521 *
3522 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3523 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3524 */
3525
3526 /* should be the usecases enabled in adev_open_input_stream() */
3527 static const int test_in_usecases[] = {
3528 USECASE_AUDIO_RECORD,
3529 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3530 };
3531 /* should be the usecases enabled in adev_open_output_stream()*/
3532 static const int test_out_usecases[] = {
3533 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3534 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3535 };
3536 static const usecase_type_t usecase_type_by_dir[] = {
3537 PCM_PLAYBACK,
3538 PCM_CAPTURE,
3539 };
3540 static const unsigned flags_by_dir[] = {
3541 PCM_OUT,
3542 PCM_IN,
3543 };
3544
3545 size_t i;
3546 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003547 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003548 char info[512]; /* for possible debug info */
3549
3550 for (dir = 0; dir < 2; ++dir) {
3551 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3552 const unsigned flags_dir = flags_by_dir[dir];
3553 const size_t testsize =
3554 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3555 const int *testcases =
3556 dir ? test_in_usecases : test_out_usecases;
3557 const audio_devices_t audio_device =
3558 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3559
3560 for (i = 0; i < testsize; ++i) {
3561 const audio_usecase_t audio_usecase = testcases[i];
3562 int device_id;
3563 snd_device_t snd_device;
3564 struct pcm_params **pparams;
3565 struct stream_out out;
3566 struct stream_in in;
3567 struct audio_usecase uc_info;
3568 int retval;
3569
3570 pparams = &adev->use_case_table[audio_usecase];
3571 pcm_params_free(*pparams); /* can accept null input */
3572 *pparams = NULL;
3573
3574 /* find the device ID for the use case (signed, for error) */
3575 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3576 if (device_id < 0)
3577 continue;
3578
3579 /* prepare structures for device probing */
3580 memset(&uc_info, 0, sizeof(uc_info));
3581 uc_info.id = audio_usecase;
3582 uc_info.type = usecase_type;
3583 if (dir) {
3584 adev->active_input = &in;
3585 memset(&in, 0, sizeof(in));
3586 in.device = audio_device;
3587 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3588 uc_info.stream.in = &in;
3589 } else {
3590 adev->active_input = NULL;
3591 }
3592 memset(&out, 0, sizeof(out));
3593 out.devices = audio_device; /* only field needed in select_devices */
3594 uc_info.stream.out = &out;
3595 uc_info.devices = audio_device;
3596 uc_info.in_snd_device = SND_DEVICE_NONE;
3597 uc_info.out_snd_device = SND_DEVICE_NONE;
3598 list_add_tail(&adev->usecase_list, &uc_info.list);
3599
3600 /* select device - similar to start_(in/out)put_stream() */
3601 retval = select_devices(adev, audio_usecase);
3602 if (retval >= 0) {
3603 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3604#if LOG_NDEBUG == 0
3605 if (*pparams) {
3606 ALOGV("%s: (%s) card %d device %d", __func__,
3607 dir ? "input" : "output", card_id, device_id);
3608 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07003609 } else {
3610 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3611 }
3612#endif
3613 }
3614
3615 /* deselect device - similar to stop_(in/out)put_stream() */
3616 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07003617 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07003618 /* 2. Disable the rx device */
3619 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07003620 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07003621 list_remove(&uc_info.list);
3622 }
3623 }
3624 adev->active_input = NULL; /* restore adev state */
3625 return 0;
3626}
3627
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628static int adev_close(hw_device_t *device)
3629{
Andy Hung31aca912014-03-20 17:14:59 -07003630 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003632
3633 if (!adev)
3634 return 0;
3635
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003636 audio_extn_tfa_98xx_deinit();
3637
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003638 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003639 pthread_mutex_lock(&adev_init_lock);
3640
3641 if ((--audio_device_ref_count) == 0) {
3642 audio_route_free(adev->audio_route);
3643 free(adev->snd_dev_ref_cnt);
3644 platform_deinit(adev->platform);
3645 audio_extn_extspk_deinit(adev->extspk);
3646 audio_extn_sound_trigger_deinit(adev);
3647 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3648 pcm_params_free(adev->use_case_table[i]);
3649 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003650 if (adev->adm_deinit)
3651 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003652 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07003653 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07003654
3655 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657 return 0;
3658}
3659
Glenn Kasten4f993392014-05-14 07:30:48 -07003660/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3661 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3662 * just that it _might_ work.
3663 */
3664static int period_size_is_plausible_for_low_latency(int period_size)
3665{
3666 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003667 case 48:
3668 case 96:
3669 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07003670 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003671 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07003672 case 240:
3673 case 320:
3674 case 480:
3675 return 1;
3676 default:
3677 return 0;
3678 }
3679}
3680
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003681static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
3682{
3683 int card;
3684 card_status_t status;
3685
3686 if (!parms)
3687 return;
3688
3689 if (parse_snd_card_status(parms, &card, &status) < 0)
3690 return;
3691
3692 pthread_mutex_lock(&adev->lock);
3693 bool valid_cb = (card == adev->snd_card);
3694 if (valid_cb) {
3695 if (adev->card_status != status) {
3696 adev->card_status = status;
3697 platform_snd_card_update(adev->platform, status);
3698 }
3699 }
3700 pthread_mutex_unlock(&adev->lock);
3701 return;
3702}
3703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704static int adev_open(const hw_module_t *module, const char *name,
3705 hw_device_t **device)
3706{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003707 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708
Eric Laurent2bafff12016-03-17 12:17:23 -07003709 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003710 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003711 pthread_mutex_lock(&adev_init_lock);
3712 if (audio_device_ref_count != 0) {
3713 *device = &adev->device.common;
3714 audio_device_ref_count++;
3715 ALOGV("%s: returning existing instance of adev", __func__);
3716 ALOGV("%s: exit", __func__);
3717 pthread_mutex_unlock(&adev_init_lock);
3718 return 0;
3719 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720 adev = calloc(1, sizeof(struct audio_device));
3721
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003722 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3725 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3726 adev->device.common.module = (struct hw_module_t *)module;
3727 adev->device.common.close = adev_close;
3728
3729 adev->device.init_check = adev_init_check;
3730 adev->device.set_voice_volume = adev_set_voice_volume;
3731 adev->device.set_master_volume = adev_set_master_volume;
3732 adev->device.get_master_volume = adev_get_master_volume;
3733 adev->device.set_master_mute = adev_set_master_mute;
3734 adev->device.get_master_mute = adev_get_master_mute;
3735 adev->device.set_mode = adev_set_mode;
3736 adev->device.set_mic_mute = adev_set_mic_mute;
3737 adev->device.get_mic_mute = adev_get_mic_mute;
3738 adev->device.set_parameters = adev_set_parameters;
3739 adev->device.get_parameters = adev_get_parameters;
3740 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3741 adev->device.open_output_stream = adev_open_output_stream;
3742 adev->device.close_output_stream = adev_close_output_stream;
3743 adev->device.open_input_stream = adev_open_input_stream;
3744 adev->device.close_input_stream = adev_close_input_stream;
3745 adev->device.dump = adev_dump;
3746
3747 /* Set the default route before the PCM stream is opened */
3748 pthread_mutex_lock(&adev->lock);
3749 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003750 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003751 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003752 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003753 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003754 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003755 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003756 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003757 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003758 pthread_mutex_unlock(&adev->lock);
3759
3760 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003761 adev->platform = platform_init(adev);
3762 if (!adev->platform) {
3763 free(adev->snd_dev_ref_cnt);
3764 free(adev);
3765 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3766 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003767 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003768 return -EINVAL;
3769 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05003770 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003771 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003772
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003773 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3774 if (adev->visualizer_lib == NULL) {
3775 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3776 } else {
3777 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3778 adev->visualizer_start_output =
3779 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3780 "visualizer_hal_start_output");
3781 adev->visualizer_stop_output =
3782 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3783 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07003784 }
3785
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003786 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3787 if (adev->offload_effects_lib == NULL) {
3788 ALOGW("%s: DLOPEN failed for %s", __func__,
3789 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3790 } else {
3791 ALOGV("%s: DLOPEN successful for %s", __func__,
3792 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3793 adev->offload_effects_start_output =
3794 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3795 "offload_effects_bundle_hal_start_output");
3796 adev->offload_effects_stop_output =
3797 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3798 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07003799 }
3800
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003801 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3802 if (adev->adm_lib == NULL) {
3803 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3804 } else {
3805 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3806 adev->adm_init = (adm_init_t)
3807 dlsym(adev->adm_lib, "adm_init");
3808 adev->adm_deinit = (adm_deinit_t)
3809 dlsym(adev->adm_lib, "adm_deinit");
3810 adev->adm_register_input_stream = (adm_register_input_stream_t)
3811 dlsym(adev->adm_lib, "adm_register_input_stream");
3812 adev->adm_register_output_stream = (adm_register_output_stream_t)
3813 dlsym(adev->adm_lib, "adm_register_output_stream");
3814 adev->adm_deregister_stream = (adm_deregister_stream_t)
3815 dlsym(adev->adm_lib, "adm_deregister_stream");
3816 adev->adm_request_focus = (adm_request_focus_t)
3817 dlsym(adev->adm_lib, "adm_request_focus");
3818 adev->adm_abandon_focus = (adm_abandon_focus_t)
3819 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08003820 adev->adm_set_config = (adm_set_config_t)
3821 dlsym(adev->adm_lib, "adm_set_config");
3822 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
3823 dlsym(adev->adm_lib, "adm_request_focus_v2");
3824 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
3825 dlsym(adev->adm_lib, "adm_is_noirq_avail");
3826 adev->adm_on_routing_change = (adm_on_routing_change_t)
3827 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003828 }
3829
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003830 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003831 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003832
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003833 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003834
Andy Hung31aca912014-03-20 17:14:59 -07003835 if (k_enable_extended_precision)
3836 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003837
Glenn Kasten4f993392014-05-14 07:30:48 -07003838 char value[PROPERTY_VALUE_MAX];
3839 int trial;
3840 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3841 trial = atoi(value);
3842 if (period_size_is_plausible_for_low_latency(trial)) {
3843 pcm_config_low_latency.period_size = trial;
3844 pcm_config_low_latency.start_threshold = trial / 4;
3845 pcm_config_low_latency.avail_min = trial / 4;
3846 configured_low_latency_capture_period_size = trial;
3847 }
3848 }
3849 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3850 trial = atoi(value);
3851 if (period_size_is_plausible_for_low_latency(trial)) {
3852 configured_low_latency_capture_period_size = trial;
3853 }
3854 }
3855
Yamit Mehtae3b99562016-09-16 22:44:00 +05303856 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003857 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003858
3859 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
3860 af_period_multiplier = atoi(value);
3861 if (af_period_multiplier < 0) {
3862 af_period_multiplier = 2;
3863 } else if (af_period_multiplier > 4) {
3864 af_period_multiplier = 4;
3865 }
3866 ALOGV("new period_multiplier = %d", af_period_multiplier);
3867 }
3868
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003869 audio_extn_tfa_98xx_init(adev);
3870
vivek mehta1a9b7c02015-06-25 11:49:38 -07003871 pthread_mutex_unlock(&adev_init_lock);
3872
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003873 if (adev->adm_init)
3874 adev->adm_data = adev->adm_init();
3875
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003876 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003877 audio_extn_snd_mon_init();
3878 pthread_mutex_lock(&adev->lock);
3879 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
3880 adev->card_status = CARD_STATUS_ONLINE;
3881 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003882
Eric Laurent2bafff12016-03-17 12:17:23 -07003883 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003884 return 0;
3885}
3886
3887static struct hw_module_methods_t hal_module_methods = {
3888 .open = adev_open,
3889};
3890
3891struct audio_module HAL_MODULE_INFO_SYM = {
3892 .common = {
3893 .tag = HARDWARE_MODULE_TAG,
3894 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3895 .hal_api_version = HARDWARE_HAL_API_VERSION,
3896 .id = AUDIO_HARDWARE_MODULE_ID,
3897 .name = "QCOM Audio HAL",
3898 .author = "Code Aurora Forum",
3899 .methods = &hal_module_methods,
3900 },
3901};