blob: 19b8fbebfc88655c102af45163758c8e6283d589 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036
37#include <cutils/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080038#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080039#include <cutils/str_parms.h>
40#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041#include <cutils/atomic.h>
42#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080043
Eric Laurentb23d5282013-05-14 15:27:20 -070044#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070045#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070046#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070047#include <audio_effects/effect_aec.h>
48#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080049#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080050#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070051#include "platform_api.h"
52#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070053#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080054
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080056#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070057
Eric Laurent397db572016-05-11 11:31:47 -070058/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
59 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070060#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070061// 2 buffers causes problems with high bitrate files
62#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070063/* ToDo: Check and update a proper value in msec */
64#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
65#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
66
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070067#define PROXY_OPEN_RETRY_COUNT 100
68#define PROXY_OPEN_WAIT_TIME 20
69
vivek mehtadae44712015-07-27 14:13:18 -070070#define MIN_CHANNEL_COUNT 1
71#define DEFAULT_CHANNEL_COUNT 2
72
Jean-Michel Trivic0750692015-10-12 12:12:32 -070073#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
74#define MAX_CHANNEL_COUNT 1
75#else
vivek mehtadae44712015-07-27 14:13:18 -070076#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
77#define XSTR(x) STR(x)
78#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070079#endif
vivek mehtadae44712015-07-27 14:13:18 -070080
Haynes Mathew George03c40102016-01-29 17:57:48 -080081#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
82
Glenn Kasten4f993392014-05-14 07:30:48 -070083static unsigned int configured_low_latency_capture_period_size =
84 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
85
Andy Hung31aca912014-03-20 17:14:59 -070086/* This constant enables extended precision handling.
87 * TODO The flag is off until more testing is done.
88 */
89static const bool k_enable_extended_precision = false;
90
Eric Laurentb23d5282013-05-14 15:27:20 -070091struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -070092 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -070093 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
94 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
95 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
96 .format = PCM_FORMAT_S16_LE,
97 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
98 .stop_threshold = INT_MAX,
99 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
100};
101
102struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700103 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700104 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
105 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
106 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
107 .format = PCM_FORMAT_S16_LE,
108 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
109 .stop_threshold = INT_MAX,
110 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
111};
112
Haynes Mathew George03c40102016-01-29 17:57:48 -0800113static int af_period_multiplier = 4;
114struct pcm_config pcm_config_rt = {
115 .channels = DEFAULT_CHANNEL_COUNT,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = ULL_PERIOD_SIZE, //1 ms
118 .period_count = 512, //=> buffer size is 512ms
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
121 .stop_threshold = INT_MAX,
122 .silence_threshold = 0,
123 .silence_size = 0,
124 .avail_min = ULL_PERIOD_SIZE, //1 ms
125};
126
Eric Laurentb23d5282013-05-14 15:27:20 -0700127struct pcm_config pcm_config_hdmi_multi = {
128 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
129 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
130 .period_size = HDMI_MULTI_PERIOD_SIZE,
131 .period_count = HDMI_MULTI_PERIOD_COUNT,
132 .format = PCM_FORMAT_S16_LE,
133 .start_threshold = 0,
134 .stop_threshold = INT_MAX,
135 .avail_min = 0,
136};
137
138struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700139 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700140 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
141 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700142 .stop_threshold = INT_MAX,
143 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700144};
145
Haynes Mathew George03c40102016-01-29 17:57:48 -0800146struct pcm_config pcm_config_audio_capture_rt = {
147 .channels = DEFAULT_CHANNEL_COUNT,
148 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
149 .period_size = ULL_PERIOD_SIZE,
150 .period_count = 512,
151 .format = PCM_FORMAT_S16_LE,
152 .start_threshold = 0,
153 .stop_threshold = INT_MAX,
154 .silence_threshold = 0,
155 .silence_size = 0,
156 .avail_min = ULL_PERIOD_SIZE, //1 ms
157};
158
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700159#define AFE_PROXY_CHANNEL_COUNT 2
160#define AFE_PROXY_SAMPLING_RATE 48000
161
162#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
163#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
164
165struct pcm_config pcm_config_afe_proxy_playback = {
166 .channels = AFE_PROXY_CHANNEL_COUNT,
167 .rate = AFE_PROXY_SAMPLING_RATE,
168 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
169 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
170 .format = PCM_FORMAT_S16_LE,
171 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
172 .stop_threshold = INT_MAX,
173 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
174};
175
176#define AFE_PROXY_RECORD_PERIOD_SIZE 768
177#define AFE_PROXY_RECORD_PERIOD_COUNT 4
178
179struct pcm_config pcm_config_afe_proxy_record = {
180 .channels = AFE_PROXY_CHANNEL_COUNT,
181 .rate = AFE_PROXY_SAMPLING_RATE,
182 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
183 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
186 .stop_threshold = INT_MAX,
187 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
188};
189
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700190const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700191 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
192 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
193 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700194 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700195 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700196 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700197
Eric Laurentb23d5282013-05-14 15:27:20 -0700198 [USECASE_AUDIO_RECORD] = "audio-record",
199 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700200
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800201 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
202 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700203
Eric Laurentb23d5282013-05-14 15:27:20 -0700204 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700205 [USECASE_VOICE2_CALL] = "voice2-call",
206 [USECASE_VOLTE_CALL] = "volte-call",
207 [USECASE_QCHAT_CALL] = "qchat-call",
208 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800209 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
210 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700211
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700212 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
213 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
214
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700215 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
216 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700217};
218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800219
220#define STRING_TO_ENUM(string) { #string, string }
221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800222struct string_to_enum {
223 const char *name;
224 uint32_t value;
225};
226
227static const struct string_to_enum out_channels_name_to_enum_table[] = {
228 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
229 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
230 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
231};
232
Haynes Mathew George5191a852013-09-11 14:19:36 -0700233static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700234static struct audio_device *adev = NULL;
235static pthread_mutex_t adev_init_lock;
236static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700237//cache last MBDRC cal step level
238static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700239
Haynes Mathew George03c40102016-01-29 17:57:48 -0800240static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
241 int flags __unused)
242{
243 int dir = 0;
244 switch (uc_id) {
245 case USECASE_AUDIO_RECORD_LOW_LATENCY:
246 dir = 1;
247 case USECASE_AUDIO_PLAYBACK_ULL:
248 break;
249 default:
250 return false;
251 }
252
253 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
254 PCM_PLAYBACK : PCM_CAPTURE);
255 if (adev->adm_is_noirq_avail)
256 return adev->adm_is_noirq_avail(adev->adm_data,
257 adev->snd_card, dev_id, dir);
258 return false;
259}
260
261static void register_out_stream(struct stream_out *out)
262{
263 struct audio_device *adev = out->dev;
264 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
265 return;
266
267 if (!adev->adm_register_output_stream)
268 return;
269
270 adev->adm_register_output_stream(adev->adm_data,
271 out->handle,
272 out->flags);
273
274 if (!adev->adm_set_config)
275 return;
276
277 if (out->realtime) {
278 adev->adm_set_config(adev->adm_data,
279 out->handle,
280 out->pcm, &out->config);
281 }
282}
283
284static void register_in_stream(struct stream_in *in)
285{
286 struct audio_device *adev = in->dev;
287 if (!adev->adm_register_input_stream)
288 return;
289
290 adev->adm_register_input_stream(adev->adm_data,
291 in->capture_handle,
292 in->flags);
293
294 if (!adev->adm_set_config)
295 return;
296
297 if (in->realtime) {
298 adev->adm_set_config(adev->adm_data,
299 in->capture_handle,
300 in->pcm,
301 &in->config);
302 }
303}
304
305static void request_out_focus(struct stream_out *out, long ns)
306{
307 struct audio_device *adev = out->dev;
308
309 if (out->routing_change) {
310 out->routing_change = false;
311 if (adev->adm_on_routing_change)
312 adev->adm_on_routing_change(adev->adm_data, out->handle);
313 }
314
315 if (adev->adm_request_focus_v2) {
316 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
317 } else if (adev->adm_request_focus) {
318 adev->adm_request_focus(adev->adm_data, out->handle);
319 }
320}
321
322static void request_in_focus(struct stream_in *in, long ns)
323{
324 struct audio_device *adev = in->dev;
325
326 if (in->routing_change) {
327 in->routing_change = false;
328 if (adev->adm_on_routing_change)
329 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
330 }
331
332 if (adev->adm_request_focus_v2) {
333 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
334 } else if (adev->adm_request_focus) {
335 adev->adm_request_focus(adev->adm_data, in->capture_handle);
336 }
337}
338
339static void release_out_focus(struct stream_out *out, long ns __unused)
340{
341 struct audio_device *adev = out->dev;
342
343 if (adev->adm_abandon_focus)
344 adev->adm_abandon_focus(adev->adm_data, out->handle);
345}
346
347static void release_in_focus(struct stream_in *in, long ns __unused)
348{
349 struct audio_device *adev = in->dev;
350 if (adev->adm_abandon_focus)
351 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
352}
353
Andy Hung7401c7c2016-09-21 12:41:21 -0700354// Time string format similar to logcat, buffer_length must be >= 19 chars.
355static void ns2string(int64_t ns, char *buffer, int buffer_length)
356{
357 const int one_second = 1000000000;
358 const time_t sec = ns / one_second;
359 struct tm tm;
360 localtime_r(&sec, &tm);
361 snprintf(buffer, buffer_length, "%02d-%02d %02d:%02d:%02d.%03d",
362 tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range
363 tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
364 (int)(ns % one_second / 1000000));
365}
366
367// Convert timespec to nsec.
368static int64_t ts2ns(const struct timespec *ts)
369{
370 return ts->tv_sec * 1000000000LL + ts->tv_nsec;
371}
372
373// Log errors: consecutive errors with the same code will
374// be aggregated if they occur within one second.
375// A mutual exclusion lock must be held before calling.
376static void log_error_l(struct error_log *log, int code) {
377 ++log->errors;
378
379 struct timespec now_ts = { 0, 0 };
380 (void)clock_gettime(CLOCK_REALTIME, &now_ts);
381 const int64_t now = ts2ns(&now_ts);
382
383 // Within 1 second, cluster the same error codes together.
384 const int one_second = 1000000000;
385 if (code == log->entries[log->idx].code &&
386 now - log->entries[log->idx].last_time < one_second) {
387 log->entries[log->idx].count++;
388 log->entries[log->idx].last_time = now;
389 return;
390 }
391
392 // Add new error entry.
393 if (++log->idx >= ARRAY_SIZE(log->entries)) {
394 log->idx = 0;
395 }
396 log->entries[log->idx].count = 1;
397 log->entries[log->idx].code = code;
398 log->entries[log->idx].first_time = now;
399 log->entries[log->idx].last_time = now;
400}
401
402// Dump information in the error log. A mutual exclusion lock
403// should be held, but if that cannot be obtained, one should
404// make a copy of the error log before calling -- the call is
405// still safe, but there might be some misinterpreted data.
406static void log_dump_l(const struct error_log *log, int fd)
407{
408 dprintf(fd, " Errors: %u\n", log->errors);
409 if (log->errors == 0)
410 return;
411
412 dprintf(fd, " Index Code Freq First time Last time\n");
413 for (size_t i = 0; i < ARRAY_SIZE(log->entries); ++i) {
414 if (log->entries[i].count != 0) {
415 char first_time[32];
416 char last_time[32];
417 ns2string(log->entries[i].first_time, first_time, sizeof(first_time));
418 ns2string(log->entries[i].last_time, last_time, sizeof(last_time));
419 dprintf(fd, " %c%4zu %4d %5d %s %s\n",
420 i == log->idx ? '*' : ' ', // mark head position
421 i, log->entries[i].code, log->entries[i].count,
422 first_time, last_time);
423 }
424 }
425}
426
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700427static int parse_snd_card_status(struct str_parms * parms, int * card,
428 card_status_t * status)
429{
430 char value[32]={0};
431 char state[32]={0};
432
433 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
434
435 if (ret < 0)
436 return -1;
437
438 // sscanf should be okay as value is of max length 32.
439 // same as sizeof state.
440 if (sscanf(value, "%d,%s", card, state) < 2)
441 return -1;
442
443 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
444 CARD_STATUS_OFFLINE;
445 return 0;
446}
447
vivek mehta1a9b7c02015-06-25 11:49:38 -0700448__attribute__ ((visibility ("default")))
449bool audio_hw_send_gain_dep_calibration(int level) {
450 bool ret_val = false;
451 ALOGV("%s: enter ... ", __func__);
452
453 pthread_mutex_lock(&adev_init_lock);
454
455 if (adev != NULL && adev->platform != NULL) {
456 pthread_mutex_lock(&adev->lock);
457 ret_val = platform_send_gain_dep_cal(adev->platform, level);
458 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700459
460 // if cal set fails, cache level info
461 // if cal set succeds, reset known last cal set
462 if (!ret_val)
463 last_known_cal_step = level;
464 else if (last_known_cal_step != -1)
465 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700466 } else {
467 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
468 }
469
470 pthread_mutex_unlock(&adev_init_lock);
471
472 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
473 return ret_val;
474}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700475
vivek mehtaa8d7c922016-05-25 14:40:44 -0700476__attribute__ ((visibility ("default")))
477int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
478 int table_size) {
479 int ret_val = 0;
480 ALOGV("%s: enter ... ", __func__);
481
482 pthread_mutex_lock(&adev_init_lock);
483 if (adev == NULL) {
484 ALOGW("%s: adev is NULL .... ", __func__);
485 goto done;
486 }
487
488 pthread_mutex_lock(&adev->lock);
489 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
490 pthread_mutex_unlock(&adev->lock);
491done:
492 pthread_mutex_unlock(&adev_init_lock);
493 ALOGV("%s: exit ... ", __func__);
494 return ret_val;
495}
496
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700497static bool is_supported_format(audio_format_t format)
498{
Eric Laurent8251ac82014-07-23 11:00:25 -0700499 switch (format) {
500 case AUDIO_FORMAT_MP3:
501 case AUDIO_FORMAT_AAC_LC:
502 case AUDIO_FORMAT_AAC_HE_V1:
503 case AUDIO_FORMAT_AAC_HE_V2:
504 return true;
505 default:
506 break;
507 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700508 return false;
509}
510
Haynes Mathew George03c40102016-01-29 17:57:48 -0800511static inline bool is_mmap_usecase(audio_usecase_t uc_id)
512{
513 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
514 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
515}
516
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700517static int get_snd_codec_id(audio_format_t format)
518{
519 int id = 0;
520
Eric Laurent8251ac82014-07-23 11:00:25 -0700521 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700522 case AUDIO_FORMAT_MP3:
523 id = SND_AUDIOCODEC_MP3;
524 break;
525 case AUDIO_FORMAT_AAC:
526 id = SND_AUDIOCODEC_AAC;
527 break;
528 default:
529 ALOGE("%s: Unsupported audio format", __func__);
530 }
531
532 return id;
533}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800534
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800535static int audio_ssr_status(struct audio_device *adev)
536{
537 int ret = 0;
538 struct mixer_ctl *ctl;
539 const char *mixer_ctl_name = "Audio SSR Status";
540
541 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
542 ret = mixer_ctl_get_value(ctl, 0);
543 ALOGD("%s: value: %d", __func__, ret);
544 return ret;
545}
546
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800547int enable_audio_route(struct audio_device *adev,
548 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800549{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700550 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800551 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800552
553 if (usecase == NULL)
554 return -EINVAL;
555
556 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
557
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800558 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700559 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800560 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700561 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800562
Yamit Mehtae3b99562016-09-16 22:44:00 +0530563 audio_extn_utils_send_app_type_cfg(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800564 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500565 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700566 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700567 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800568
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800569 ALOGV("%s: exit", __func__);
570 return 0;
571}
572
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800573int disable_audio_route(struct audio_device *adev,
574 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800575{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700576 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800577 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800578
579 if (usecase == NULL)
580 return -EINVAL;
581
582 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700583 if (usecase->type == PCM_CAPTURE)
584 snd_device = usecase->in_snd_device;
585 else
586 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800587 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500588 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700589 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700590 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800592 ALOGV("%s: exit", __func__);
593 return 0;
594}
595
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800596int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700597 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800598{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700599 int i, num_devices = 0;
600 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800601 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800602 if (snd_device < SND_DEVICE_MIN ||
603 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800604 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800605 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800606 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700607
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700608 platform_send_audio_calibration(adev->platform, snd_device);
609
vivek mehtade4849c2016-03-03 17:23:38 -0800610 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700611 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700612 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800613 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700614 }
615
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700616 /* due to the possibility of calibration overwrite between listen
617 and audio, notify sound trigger hal before audio calibration is sent */
618 audio_extn_sound_trigger_update_device_status(snd_device,
619 ST_EVENT_SND_DEVICE_BUSY);
620
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700621 if (audio_extn_spkr_prot_is_enabled())
622 audio_extn_spkr_prot_calib_cancel(adev);
623
zhaoyang yin4211fad2015-06-04 21:13:25 +0800624 audio_extn_dsm_feedback_enable(adev, snd_device, true);
625
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700626 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
627 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
628 audio_extn_spkr_prot_is_enabled()) {
629 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800630 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700631 }
632 if (audio_extn_spkr_prot_start_processing(snd_device)) {
633 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800634 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700635 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700636 } else if (platform_can_split_snd_device(snd_device,
637 &num_devices,
638 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700639 for (i = 0; i < num_devices; i++) {
640 enable_snd_device(adev, new_snd_devices[i]);
641 }
vivek mehtab6506412015-08-07 16:55:17 -0700642 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700643 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800644 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
645 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
646 ALOGE(" %s: Invalid sound device returned", __func__);
647 goto on_error;
648 }
Ed Tam70b5c142016-03-21 19:14:29 -0700649
Eric Laurent2e140aa2016-06-30 17:14:46 -0700650 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800651 audio_route_apply_and_update_path(adev->audio_route, device_name);
652 }
653on_success:
654 adev->snd_dev_ref_cnt[snd_device]++;
655 ret_val = 0;
656on_error:
657 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800658}
659
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800660int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700661 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800662{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700663 int i, num_devices = 0;
664 snd_device_t new_snd_devices[2];
665
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800666 if (snd_device < SND_DEVICE_MIN ||
667 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800668 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800669 return -EINVAL;
670 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
672 ALOGE("%s: device ref cnt is already 0", __func__);
673 return -EINVAL;
674 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800675 audio_extn_tfa_98xx_disable_speaker(snd_device);
676
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700677 adev->snd_dev_ref_cnt[snd_device]--;
678 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800679 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700680 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
681 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
682 audio_extn_spkr_prot_is_enabled()) {
683 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700684 } else if (platform_can_split_snd_device(snd_device,
685 &num_devices,
686 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700687 for (i = 0; i < num_devices; i++) {
688 disable_snd_device(adev, new_snd_devices[i]);
689 }
vivek mehtab6506412015-08-07 16:55:17 -0700690 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700691 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800692 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
693 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
694 ALOGE(" %s: Invalid sound device returned", __func__);
695 return -EINVAL;
696 }
697
Eric Laurent2e140aa2016-06-30 17:14:46 -0700698 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800699 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700700 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700701 audio_extn_sound_trigger_update_device_status(snd_device,
702 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700703 }
vivek mehtab6506412015-08-07 16:55:17 -0700704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800705 return 0;
706}
707
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700708/*
709 legend:
710 uc - existing usecase
711 new_uc - new usecase
712 d1, d11, d2 - SND_DEVICE enums
713 a1, a2 - corresponding ANDROID device enums
714 B, B1, B2 - backend strings
715
716case 1
717 uc->dev d1 (a1) B1
718 new_uc->dev d1 (a1), d2 (a2) B1, B2
719
720 resolution: disable and enable uc->dev on d1
721
722case 2
723 uc->dev d1 (a1) B1
724 new_uc->dev d11 (a1) B1
725
726 resolution: need to switch uc since d1 and d11 are related
727 (e.g. speaker and voice-speaker)
728 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
729
730case 3
731 uc->dev d1 (a1) B1
732 new_uc->dev d2 (a2) B2
733
734 resolution: no need to switch uc
735
736case 4
737 uc->dev d1 (a1) B
738 new_uc->dev d2 (a2) B
739
740 resolution: disable enable uc-dev on d2 since backends match
741 we cannot enable two streams on two different devices if they
742 share the same backend. e.g. if offload is on speaker device using
743 QUAD_MI2S backend and a low-latency stream is started on voice-handset
744 using the same backend, offload must also be switched to voice-handset.
745
746case 5
747 uc->dev d1 (a1) B
748 new_uc->dev d1 (a1), d2 (a2) B
749
750 resolution: disable enable uc-dev on d2 since backends match
751 we cannot enable two streams on two different devices if they
752 share the same backend.
753
754case 6
755 uc->dev d1 a1 B1
756 new_uc->dev d2 a1 B2
757
758 resolution: no need to switch
759
760case 7
761
762 uc->dev d1 (a1), d2 (a2) B1, B2
763 new_uc->dev d1 B1
764
765 resolution: no need to switch
766
767*/
768static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
769 struct audio_usecase *new_uc,
770 snd_device_t new_snd_device)
771{
772 audio_devices_t a1 = uc->stream.out->devices;
773 audio_devices_t a2 = new_uc->stream.out->devices;
774
775 snd_device_t d1 = uc->out_snd_device;
776 snd_device_t d2 = new_snd_device;
777
778 // Treat as a special case when a1 and a2 are not disjoint
779 if ((a1 != a2) && (a1 & a2)) {
780 snd_device_t d3[2];
781 int num_devices = 0;
782 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
783 &num_devices,
784 d3);
785 if (ret < 0) {
786 if (ret != -ENOSYS) {
787 ALOGW("%s failed to split snd_device %d",
788 __func__,
789 popcount(a1) > 1 ? d1 : d2);
790 }
791 goto end;
792 }
793
794 // NB: case 7 is hypothetical and isn't a practical usecase yet.
795 // But if it does happen, we need to give priority to d2 if
796 // the combo devices active on the existing usecase share a backend.
797 // This is because we cannot have a usecase active on a combo device
798 // and a new usecase requests one device in this combo pair.
799 if (platform_check_backends_match(d3[0], d3[1])) {
800 return d2; // case 5
801 } else {
802 return d1; // case 1
803 }
804 } else {
805 if (platform_check_backends_match(d1, d2)) {
806 return d2; // case 2, 4
807 } else {
808 return d1; // case 6, 3
809 }
810 }
811
812end:
813 return d2; // return whatever was calculated before.
814}
815
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700816static void check_and_route_playback_usecases(struct audio_device *adev,
817 struct audio_usecase *uc_info,
818 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819{
820 struct listnode *node;
821 struct audio_usecase *usecase;
822 bool switch_device[AUDIO_USECASE_MAX];
823 int i, num_uc_to_switch = 0;
824
825 /*
826 * This function is to make sure that all the usecases that are active on
827 * the hardware codec backend are always routed to any one device that is
828 * handled by the hardware codec.
829 * For example, if low-latency and deep-buffer usecases are currently active
830 * on speaker and out_set_parameters(headset) is received on low-latency
831 * output, then we have to make sure deep-buffer is also switched to headset,
832 * because of the limitation that both the devices cannot be enabled
833 * at the same time as they share the same backend.
834 */
835 /* Disable all the usecases on the shared backend other than the
836 specified usecase */
837 for (i = 0; i < AUDIO_USECASE_MAX; i++)
838 switch_device[i] = false;
839
840 list_for_each(node, &adev->usecase_list) {
841 usecase = node_to_item(node, struct audio_usecase, list);
842 if (usecase->type != PCM_CAPTURE &&
843 usecase != uc_info &&
844 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700845 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
846 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700847 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
848 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700849 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700850 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700851 switch_device[usecase->id] = true;
852 num_uc_to_switch++;
853 }
854 }
855
856 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 list_for_each(node, &adev->usecase_list) {
858 usecase = node_to_item(node, struct audio_usecase, list);
859 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700860 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900861 }
862 }
863
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700864 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900865 list_for_each(node, &adev->usecase_list) {
866 usecase = node_to_item(node, struct audio_usecase, list);
867 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700868 d_device = derive_playback_snd_device(usecase, uc_info,
869 snd_device);
870 enable_snd_device(adev, d_device);
871 /* Update the out_snd_device before enabling the audio route */
872 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 }
874 }
875
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700876 /* Re-route all the usecases on the shared backend other than the
877 specified usecase to new snd devices */
878 list_for_each(node, &adev->usecase_list) {
879 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700880 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700881 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882 }
883 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700884 }
885}
886
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700887static void check_and_route_capture_usecases(struct audio_device *adev,
888 struct audio_usecase *uc_info,
889 snd_device_t snd_device)
890{
891 struct listnode *node;
892 struct audio_usecase *usecase;
893 bool switch_device[AUDIO_USECASE_MAX];
894 int i, num_uc_to_switch = 0;
895
vivek mehta4ed66e62016-04-15 23:33:34 -0700896 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
897
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700898 /*
899 * This function is to make sure that all the active capture usecases
900 * are always routed to the same input sound device.
901 * For example, if audio-record and voice-call usecases are currently
902 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
903 * is received for voice call then we have to make sure that audio-record
904 * usecase is also switched to earpiece i.e. voice-dmic-ef,
905 * because of the limitation that two devices cannot be enabled
906 * at the same time if they share the same backend.
907 */
908 for (i = 0; i < AUDIO_USECASE_MAX; i++)
909 switch_device[i] = false;
910
911 list_for_each(node, &adev->usecase_list) {
912 usecase = node_to_item(node, struct audio_usecase, list);
913 if (usecase->type != PCM_PLAYBACK &&
914 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700915 usecase->in_snd_device != snd_device &&
916 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700917 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
918 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700919 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700920 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700921 switch_device[usecase->id] = true;
922 num_uc_to_switch++;
923 }
924 }
925
926 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700927 list_for_each(node, &adev->usecase_list) {
928 usecase = node_to_item(node, struct audio_usecase, list);
929 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700930 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700931 }
932 }
933
934 list_for_each(node, &adev->usecase_list) {
935 usecase = node_to_item(node, struct audio_usecase, list);
936 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700937 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700938 }
939 }
940
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700941 /* Re-route all the usecases on the shared backend other than the
942 specified usecase to new snd devices */
943 list_for_each(node, &adev->usecase_list) {
944 usecase = node_to_item(node, struct audio_usecase, list);
945 /* Update the in_snd_device only before enabling the audio route */
946 if (switch_device[usecase->id] ) {
947 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700948 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700949 }
950 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700951 }
952}
953
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800954/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700955static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800956{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700957 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700958 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800959
960 switch (channels) {
961 /*
962 * Do not handle stereo output in Multi-channel cases
963 * Stereo case is handled in normal playback path
964 */
965 case 6:
966 ALOGV("%s: HDMI supports 5.1", __func__);
967 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
968 break;
969 case 8:
970 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
971 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
972 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
973 break;
974 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700975 ALOGE("HDMI does not support multi channel playback");
976 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800977 break;
978 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700979 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800980}
981
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700982static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
983{
984 struct audio_usecase *usecase;
985 struct listnode *node;
986
987 list_for_each(node, &adev->usecase_list) {
988 usecase = node_to_item(node, struct audio_usecase, list);
989 if (usecase->type == VOICE_CALL) {
990 ALOGV("%s: usecase id %d", __func__, usecase->id);
991 return usecase->id;
992 }
993 }
994 return USECASE_INVALID;
995}
996
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800997struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
998 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700999{
1000 struct audio_usecase *usecase;
1001 struct listnode *node;
1002
1003 list_for_each(node, &adev->usecase_list) {
1004 usecase = node_to_item(node, struct audio_usecase, list);
1005 if (usecase->id == uc_id)
1006 return usecase;
1007 }
1008 return NULL;
1009}
1010
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001011int select_devices(struct audio_device *adev,
1012 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001013{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001014 snd_device_t out_snd_device = SND_DEVICE_NONE;
1015 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001016 struct audio_usecase *usecase = NULL;
1017 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001018 struct audio_usecase *hfp_usecase = NULL;
1019 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001020 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001021 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001023 usecase = get_usecase_from_list(adev, uc_id);
1024 if (usecase == NULL) {
1025 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1026 return -EINVAL;
1027 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001029 if ((usecase->type == VOICE_CALL) ||
1030 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001031 out_snd_device = platform_get_output_snd_device(adev->platform,
1032 usecase->stream.out->devices);
1033 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001034 usecase->devices = usecase->stream.out->devices;
1035 } else {
1036 /*
1037 * If the voice call is active, use the sound devices of voice call usecase
1038 * so that it would not result any device switch. All the usecases will
1039 * be switched to new device when select_devices() is called for voice call
1040 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001041 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001042 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001043 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001044 vc_usecase = get_usecase_from_list(adev,
1045 get_voice_usecase_id_from_list(adev));
1046 if ((vc_usecase != NULL) &&
1047 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1048 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049 in_snd_device = vc_usecase->in_snd_device;
1050 out_snd_device = vc_usecase->out_snd_device;
1051 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001052 } else if (audio_extn_hfp_is_active(adev)) {
1053 hfp_ucid = audio_extn_hfp_get_usecase();
1054 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1055 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1056 in_snd_device = hfp_usecase->in_snd_device;
1057 out_snd_device = hfp_usecase->out_snd_device;
1058 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001059 }
1060 if (usecase->type == PCM_PLAYBACK) {
1061 usecase->devices = usecase->stream.out->devices;
1062 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001063 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001064 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001065 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001066 if (usecase->stream.out == adev->primary_output &&
1067 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001068 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1069 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001070 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001071 select_devices(adev, adev->active_input->usecase);
1072 }
1073 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001074 } else if (usecase->type == PCM_CAPTURE) {
1075 usecase->devices = usecase->stream.in->device;
1076 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001077 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001078 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001079 if (adev->active_input &&
1080 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1081 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001082 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001083 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1084 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1085 } else if (adev->primary_output) {
1086 out_device = adev->primary_output->devices;
1087 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001088 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001089 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001090 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001091 }
1092 }
1093
1094 if (out_snd_device == usecase->out_snd_device &&
1095 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001096 return 0;
1097 }
1098
Eric Laurent2bafff12016-03-17 12:17:23 -07001099 if (out_snd_device != SND_DEVICE_NONE &&
1100 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1101 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1102 __func__,
1103 use_case_table[uc_id],
1104 adev->last_logged_snd_device[uc_id][0],
1105 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1106 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1107 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1108 -1,
1109 out_snd_device,
1110 platform_get_snd_device_name(out_snd_device),
1111 platform_get_snd_device_acdb_id(out_snd_device));
1112 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1113 }
1114 if (in_snd_device != SND_DEVICE_NONE &&
1115 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1116 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1117 __func__,
1118 use_case_table[uc_id],
1119 adev->last_logged_snd_device[uc_id][1],
1120 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1121 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1122 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1123 -1,
1124 in_snd_device,
1125 platform_get_snd_device_name(in_snd_device),
1126 platform_get_snd_device_acdb_id(in_snd_device));
1127 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1128 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001130 /*
1131 * Limitation: While in call, to do a device switch we need to disable
1132 * and enable both RX and TX devices though one of them is same as current
1133 * device.
1134 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001135 if ((usecase->type == VOICE_CALL) &&
1136 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1137 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001138 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001139 /* Disable sidetone only if voice call already exists */
1140 if (voice_is_call_state_active(adev))
1141 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001142 }
1143
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001144 /* Disable current sound devices */
1145 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001146 disable_audio_route(adev, usecase);
1147 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001148 }
1149
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001150 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001151 disable_audio_route(adev, usecase);
1152 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001153 }
1154
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001155 /* Applicable only on the targets that has external modem.
1156 * New device information should be sent to modem before enabling
1157 * the devices to reduce in-call device switch time.
1158 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001159 if ((usecase->type == VOICE_CALL) &&
1160 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1161 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001162 status = platform_switch_voice_call_enable_device_config(adev->platform,
1163 out_snd_device,
1164 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001165 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001166
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001167 /* Enable new sound devices */
1168 if (out_snd_device != SND_DEVICE_NONE) {
1169 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001170 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001171 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001172 }
1173
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001174 if (in_snd_device != SND_DEVICE_NONE) {
1175 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001176 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001177 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001178
Eric Laurentb23d5282013-05-14 15:27:20 -07001179 if (usecase->type == VOICE_CALL)
1180 status = platform_switch_voice_call_device_post(adev->platform,
1181 out_snd_device,
1182 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001183
sangwoo170731f2013-06-08 15:36:36 +09001184 usecase->in_snd_device = in_snd_device;
1185 usecase->out_snd_device = out_snd_device;
1186
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001187 audio_extn_tfa_98xx_set_mode();
1188
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001189 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001190
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001191 /* Applicable only on the targets that has external modem.
1192 * Enable device command should be sent to modem only after
1193 * enabling voice call mixer controls
1194 */
vivek mehta765eb642015-08-07 19:46:06 -07001195 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001196 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1197 out_snd_device,
1198 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001199 /* Enable sidetone only if voice call already exists */
1200 if (voice_is_call_state_active(adev))
1201 voice_set_sidetone(adev, out_snd_device, true);
1202 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001204 return status;
1205}
1206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001207static int stop_input_stream(struct stream_in *in)
1208{
1209 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001210 struct audio_usecase *uc_info;
1211 struct audio_device *adev = in->dev;
1212
Eric Laurentc8400632013-02-14 19:04:54 -08001213 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001214
Eric Laurent994a6932013-07-17 11:51:42 -07001215 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001216 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001217 uc_info = get_usecase_from_list(adev, in->usecase);
1218 if (uc_info == NULL) {
1219 ALOGE("%s: Could not find the usecase (%d) in the list",
1220 __func__, in->usecase);
1221 return -EINVAL;
1222 }
1223
Eric Laurent150dbfe2013-02-27 14:31:02 -08001224 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001225 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001226
1227 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001228 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001229
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001230 list_remove(&uc_info->list);
1231 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232
Eric Laurent994a6932013-07-17 11:51:42 -07001233 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001234 return ret;
1235}
1236
1237int start_input_stream(struct stream_in *in)
1238{
1239 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001240 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001241 struct audio_usecase *uc_info;
1242 struct audio_device *adev = in->dev;
1243
Eric Laurent994a6932013-07-17 11:51:42 -07001244 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001245
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001246 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1247 return -EIO;
1248
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001249 if (in->card_status == CARD_STATUS_OFFLINE ||
1250 adev->card_status == CARD_STATUS_OFFLINE) {
1251 ALOGW("in->card_status or adev->card_status offline, try again");
1252 ret = -EAGAIN;
1253 goto error_config;
1254 }
1255
Eric Laurentb23d5282013-05-14 15:27:20 -07001256 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001257 if (in->pcm_device_id < 0) {
1258 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1259 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001260 ret = -EINVAL;
1261 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001262 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001263
1264 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001265 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1266 uc_info->id = in->usecase;
1267 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001268 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001269 uc_info->devices = in->device;
1270 uc_info->in_snd_device = SND_DEVICE_NONE;
1271 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001273 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001274
1275 audio_extn_perf_lock_acquire();
1276
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001277 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278
Eric Laurentc8400632013-02-14 19:04:54 -08001279 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001280 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001281
Andy Hung6ebe5962016-01-15 17:46:57 -08001282 unsigned int flags = PCM_IN | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001283 unsigned int pcm_open_retry_count = 0;
1284
1285 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1286 flags |= PCM_MMAP | PCM_NOIRQ;
1287 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001288 } else if (in->realtime) {
1289 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001290 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001291
1292 while (1) {
1293 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1294 flags, &in->config);
1295 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1296 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1297 if (in->pcm != NULL) {
1298 pcm_close(in->pcm);
1299 in->pcm = NULL;
1300 }
1301 if (pcm_open_retry_count-- == 0) {
1302 ret = -EIO;
1303 goto error_open;
1304 }
1305 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1306 continue;
1307 }
1308 break;
1309 }
1310
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001311 ALOGV("%s: pcm_prepare", __func__);
1312 ret = pcm_prepare(in->pcm);
1313 if (ret < 0) {
1314 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1315 pcm_close(in->pcm);
1316 in->pcm = NULL;
1317 goto error_open;
1318 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001319 if (in->realtime) {
1320 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001321 if (ret < 0) {
1322 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1323 pcm_close(in->pcm);
1324 in->pcm = NULL;
1325 goto error_open;
1326 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001327 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001328 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001329 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001330 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001331
Eric Laurentc8400632013-02-14 19:04:54 -08001332 return ret;
1333
1334error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001335 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001336 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001337
1338error_config:
1339 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001340 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001341
1342 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001343}
1344
Eric Laurenta1478072015-09-21 17:21:52 -07001345void lock_input_stream(struct stream_in *in)
1346{
1347 pthread_mutex_lock(&in->pre_lock);
1348 pthread_mutex_lock(&in->lock);
1349 pthread_mutex_unlock(&in->pre_lock);
1350}
1351
1352void lock_output_stream(struct stream_out *out)
1353{
1354 pthread_mutex_lock(&out->pre_lock);
1355 pthread_mutex_lock(&out->lock);
1356 pthread_mutex_unlock(&out->pre_lock);
1357}
1358
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001359/* must be called with out->lock locked */
1360static int send_offload_cmd_l(struct stream_out* out, int command)
1361{
1362 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1363
1364 ALOGVV("%s %d", __func__, command);
1365
1366 cmd->cmd = command;
1367 list_add_tail(&out->offload_cmd_list, &cmd->node);
1368 pthread_cond_signal(&out->offload_cond);
1369 return 0;
1370}
1371
1372/* must be called iwth out->lock locked */
1373static void stop_compressed_output_l(struct stream_out *out)
1374{
1375 out->offload_state = OFFLOAD_STATE_IDLE;
1376 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001377 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001378 if (out->compr != NULL) {
1379 compress_stop(out->compr);
1380 while (out->offload_thread_blocked) {
1381 pthread_cond_wait(&out->cond, &out->lock);
1382 }
1383 }
1384}
1385
1386static void *offload_thread_loop(void *context)
1387{
1388 struct stream_out *out = (struct stream_out *) context;
1389 struct listnode *item;
1390
1391 out->offload_state = OFFLOAD_STATE_IDLE;
1392 out->playback_started = 0;
1393
1394 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1395 set_sched_policy(0, SP_FOREGROUND);
1396 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1397
1398 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001399 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001400 for (;;) {
1401 struct offload_cmd *cmd = NULL;
1402 stream_callback_event_t event;
1403 bool send_callback = false;
1404
1405 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1406 __func__, list_empty(&out->offload_cmd_list),
1407 out->offload_state);
1408 if (list_empty(&out->offload_cmd_list)) {
1409 ALOGV("%s SLEEPING", __func__);
1410 pthread_cond_wait(&out->offload_cond, &out->lock);
1411 ALOGV("%s RUNNING", __func__);
1412 continue;
1413 }
1414
1415 item = list_head(&out->offload_cmd_list);
1416 cmd = node_to_item(item, struct offload_cmd, node);
1417 list_remove(item);
1418
1419 ALOGVV("%s STATE %d CMD %d out->compr %p",
1420 __func__, out->offload_state, cmd->cmd, out->compr);
1421
1422 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1423 free(cmd);
1424 break;
1425 }
1426
1427 if (out->compr == NULL) {
1428 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001429 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001430 pthread_cond_signal(&out->cond);
1431 continue;
1432 }
1433 out->offload_thread_blocked = true;
1434 pthread_mutex_unlock(&out->lock);
1435 send_callback = false;
1436 switch(cmd->cmd) {
1437 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1438 compress_wait(out->compr, -1);
1439 send_callback = true;
1440 event = STREAM_CBK_EVENT_WRITE_READY;
1441 break;
1442 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001443 compress_next_track(out->compr);
1444 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001445 send_callback = true;
1446 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001447 /* Resend the metadata for next iteration */
1448 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001449 break;
1450 case OFFLOAD_CMD_DRAIN:
1451 compress_drain(out->compr);
1452 send_callback = true;
1453 event = STREAM_CBK_EVENT_DRAIN_READY;
1454 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001455 case OFFLOAD_CMD_ERROR:
1456 send_callback = true;
1457 event = STREAM_CBK_EVENT_ERROR;
1458 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001459 default:
1460 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1461 break;
1462 }
Eric Laurenta1478072015-09-21 17:21:52 -07001463 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001464 out->offload_thread_blocked = false;
1465 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001466 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001467 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001468 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001469 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001470 free(cmd);
1471 }
1472
1473 pthread_cond_signal(&out->cond);
1474 while (!list_empty(&out->offload_cmd_list)) {
1475 item = list_head(&out->offload_cmd_list);
1476 list_remove(item);
1477 free(node_to_item(item, struct offload_cmd, node));
1478 }
1479 pthread_mutex_unlock(&out->lock);
1480
1481 return NULL;
1482}
1483
1484static int create_offload_callback_thread(struct stream_out *out)
1485{
1486 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1487 list_init(&out->offload_cmd_list);
1488 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1489 offload_thread_loop, out);
1490 return 0;
1491}
1492
1493static int destroy_offload_callback_thread(struct stream_out *out)
1494{
Eric Laurenta1478072015-09-21 17:21:52 -07001495 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001496 stop_compressed_output_l(out);
1497 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1498
1499 pthread_mutex_unlock(&out->lock);
1500 pthread_join(out->offload_thread, (void **) NULL);
1501 pthread_cond_destroy(&out->offload_cond);
1502
1503 return 0;
1504}
1505
Eric Laurent07eeafd2013-10-06 12:52:49 -07001506static bool allow_hdmi_channel_config(struct audio_device *adev)
1507{
1508 struct listnode *node;
1509 struct audio_usecase *usecase;
1510 bool ret = true;
1511
1512 list_for_each(node, &adev->usecase_list) {
1513 usecase = node_to_item(node, struct audio_usecase, list);
1514 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1515 /*
1516 * If voice call is already existing, do not proceed further to avoid
1517 * disabling/enabling both RX and TX devices, CSD calls, etc.
1518 * Once the voice call done, the HDMI channels can be configured to
1519 * max channels of remaining use cases.
1520 */
1521 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001522 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001523 __func__);
1524 ret = false;
1525 break;
1526 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001527 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001528 "no change in HDMI channels", __func__);
1529 ret = false;
1530 break;
1531 }
1532 }
1533 }
1534 return ret;
1535}
1536
1537static int check_and_set_hdmi_channels(struct audio_device *adev,
1538 unsigned int channels)
1539{
1540 struct listnode *node;
1541 struct audio_usecase *usecase;
1542
1543 /* Check if change in HDMI channel config is allowed */
1544 if (!allow_hdmi_channel_config(adev))
1545 return 0;
1546
1547 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001548 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001549 return 0;
1550 }
1551
1552 platform_set_hdmi_channels(adev->platform, channels);
1553 adev->cur_hdmi_channels = channels;
1554
1555 /*
1556 * Deroute all the playback streams routed to HDMI so that
1557 * the back end is deactivated. Note that backend will not
1558 * be deactivated if any one stream is connected to it.
1559 */
1560 list_for_each(node, &adev->usecase_list) {
1561 usecase = node_to_item(node, struct audio_usecase, list);
1562 if (usecase->type == PCM_PLAYBACK &&
1563 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001564 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001565 }
1566 }
1567
1568 /*
1569 * Enable all the streams disabled above. Now the HDMI backend
1570 * will be activated with new channel configuration
1571 */
1572 list_for_each(node, &adev->usecase_list) {
1573 usecase = node_to_item(node, struct audio_usecase, list);
1574 if (usecase->type == PCM_PLAYBACK &&
1575 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001576 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001577 }
1578 }
1579
1580 return 0;
1581}
1582
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583static int stop_output_stream(struct stream_out *out)
1584{
1585 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586 struct audio_usecase *uc_info;
1587 struct audio_device *adev = out->dev;
1588
Eric Laurent994a6932013-07-17 11:51:42 -07001589 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001590 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001591 uc_info = get_usecase_from_list(adev, out->usecase);
1592 if (uc_info == NULL) {
1593 ALOGE("%s: Could not find the usecase (%d) in the list",
1594 __func__, out->usecase);
1595 return -EINVAL;
1596 }
1597
Haynes Mathew George41f86652014-06-17 14:22:15 -07001598 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1599 if (adev->visualizer_stop_output != NULL)
1600 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1601 if (adev->offload_effects_stop_output != NULL)
1602 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1603 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001604
Eric Laurent150dbfe2013-02-27 14:31:02 -08001605 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001606 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001607
1608 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001609 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001610
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001611 list_remove(&uc_info->list);
1612 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001613
Eric Laurent0499d4f2014-08-25 22:39:29 -05001614 audio_extn_extspk_update(adev->extspk);
1615
Eric Laurent07eeafd2013-10-06 12:52:49 -07001616 /* Must be called after removing the usecase from list */
1617 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1618 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1619
Eric Laurent994a6932013-07-17 11:51:42 -07001620 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621 return ret;
1622}
1623
1624int start_output_stream(struct stream_out *out)
1625{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001627 struct audio_usecase *uc_info;
1628 struct audio_device *adev = out->dev;
1629
Eric Laurent994a6932013-07-17 11:51:42 -07001630 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001631 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001632
1633 if (out->card_status == CARD_STATUS_OFFLINE ||
1634 adev->card_status == CARD_STATUS_OFFLINE) {
1635 ALOGW("out->card_status or adev->card_status offline, try again");
1636 ret = -EAGAIN;
1637 goto error_config;
1638 }
1639
Eric Laurentb23d5282013-05-14 15:27:20 -07001640 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001641 if (out->pcm_device_id < 0) {
1642 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1643 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001644 ret = -EINVAL;
1645 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646 }
1647
1648 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1649 uc_info->id = out->usecase;
1650 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001651 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001652 uc_info->devices = out->devices;
1653 uc_info->in_snd_device = SND_DEVICE_NONE;
1654 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655
Eric Laurent07eeafd2013-10-06 12:52:49 -07001656 /* This must be called before adding this usecase to the list */
1657 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1658 check_and_set_hdmi_channels(adev, out->config.channels);
1659
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001660 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001662 audio_extn_perf_lock_acquire();
1663
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001664 select_devices(adev, out->usecase);
1665
Eric Laurent0499d4f2014-08-25 22:39:29 -05001666 audio_extn_extspk_update(adev->extspk);
1667
Andy Hung31aca912014-03-20 17:14:59 -07001668 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001669 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001670 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001671 unsigned int flags = PCM_OUT;
1672 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001673
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001674 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1675 flags |= PCM_MMAP | PCM_NOIRQ;
1676 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001677 } else if (out->realtime) {
1678 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001679 } else
1680 flags |= PCM_MONOTONIC;
1681
1682 while (1) {
1683 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1684 flags, &out->config);
1685 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1686 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1687 if (out->pcm != NULL) {
1688 pcm_close(out->pcm);
1689 out->pcm = NULL;
1690 }
1691 if (pcm_open_retry_count-- == 0) {
1692 ret = -EIO;
1693 goto error_open;
1694 }
1695 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1696 continue;
1697 }
1698 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001699 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001700 ALOGV("%s: pcm_prepare", __func__);
1701 if (pcm_is_ready(out->pcm)) {
1702 ret = pcm_prepare(out->pcm);
1703 if (ret < 0) {
1704 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1705 pcm_close(out->pcm);
1706 out->pcm = NULL;
1707 goto error_open;
1708 }
1709 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001710 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001711 out->pcm = NULL;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001712 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001713 COMPRESS_IN, &out->compr_config);
1714 if (out->compr && !is_compress_ready(out->compr)) {
1715 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1716 compress_close(out->compr);
1717 out->compr = NULL;
1718 ret = -EIO;
1719 goto error_open;
1720 }
1721 if (out->offload_callback)
1722 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001723
1724 if (adev->visualizer_start_output != NULL)
Haynes Mathew George41f86652014-06-17 14:22:15 -07001725 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1726 if (adev->offload_effects_start_output != NULL)
1727 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001728 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001729 ret = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001730 if (out->realtime) {
1731 ret = pcm_start(out->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001732 if (ret < 0) {
1733 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1734 pcm_close(out->pcm);
1735 out->pcm = NULL;
1736 goto error_open;
1737 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001738 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001739 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001740 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001741 audio_extn_tfa_98xx_enable_speaker();
1742
Eric Laurent994a6932013-07-17 11:51:42 -07001743 ALOGV("%s: exit", __func__);
Haynes Mathew George03c40102016-01-29 17:57:48 -08001744 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001745error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001746 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001748error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001749 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001750}
1751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752static int check_input_parameters(uint32_t sample_rate,
1753 audio_format_t format,
1754 int channel_count)
1755{
vivek mehta4ed66e62016-04-15 23:33:34 -07001756 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001757 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1758 return -EINVAL;
1759 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760
vivek mehtadae44712015-07-27 14:13:18 -07001761 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001762 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001763 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1764 return -EINVAL;
1765 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001766
1767 switch (sample_rate) {
1768 case 8000:
1769 case 11025:
1770 case 12000:
1771 case 16000:
1772 case 22050:
1773 case 24000:
1774 case 32000:
1775 case 44100:
1776 case 48000:
1777 break;
1778 default:
vivek mehtadae44712015-07-27 14:13:18 -07001779 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780 return -EINVAL;
1781 }
1782
1783 return 0;
1784}
1785
1786static size_t get_input_buffer_size(uint32_t sample_rate,
1787 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001788 int channel_count,
1789 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790{
1791 size_t size = 0;
1792
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001793 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1794 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001796 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001797 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001798 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001799
1800 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801
Glenn Kasten4f993392014-05-14 07:30:48 -07001802 /* make sure the size is multiple of 32 bytes
1803 * At 48 kHz mono 16-bit PCM:
1804 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1805 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1806 */
1807 size += 0x1f;
1808 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001809
1810 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811}
1812
1813static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1814{
1815 struct stream_out *out = (struct stream_out *)stream;
1816
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001817 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818}
1819
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001820static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001821{
1822 return -ENOSYS;
1823}
1824
1825static size_t out_get_buffer_size(const struct audio_stream *stream)
1826{
1827 struct stream_out *out = (struct stream_out *)stream;
1828
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001829 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1830 return out->compr_config.fragment_size;
1831 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001832 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001833 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001834}
1835
1836static uint32_t out_get_channels(const struct audio_stream *stream)
1837{
1838 struct stream_out *out = (struct stream_out *)stream;
1839
1840 return out->channel_mask;
1841}
1842
1843static audio_format_t out_get_format(const struct audio_stream *stream)
1844{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001845 struct stream_out *out = (struct stream_out *)stream;
1846
1847 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001848}
1849
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001850static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851{
1852 return -ENOSYS;
1853}
1854
1855static int out_standby(struct audio_stream *stream)
1856{
1857 struct stream_out *out = (struct stream_out *)stream;
1858 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001859
Eric Laurent994a6932013-07-17 11:51:42 -07001860 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001861 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862
Eric Laurenta1478072015-09-21 17:21:52 -07001863 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001865 if (adev->adm_deregister_stream)
1866 adev->adm_deregister_stream(adev->adm_data, out->handle);
1867
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001868 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001870 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1871 if (out->pcm) {
1872 pcm_close(out->pcm);
1873 out->pcm = NULL;
1874 }
1875 } else {
1876 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001877 out->gapless_mdata.encoder_delay = 0;
1878 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001879 if (out->compr != NULL) {
1880 compress_close(out->compr);
1881 out->compr = NULL;
1882 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001883 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001885 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886 }
1887 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001888 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001889 return 0;
1890}
1891
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001892static int out_on_error(struct audio_stream *stream)
1893{
1894 struct stream_out *out = (struct stream_out *)stream;
1895 struct audio_device *adev = out->dev;
1896 bool do_standby = false;
1897
1898 lock_output_stream(out);
1899 if (!out->standby) {
1900 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1901 stop_compressed_output_l(out);
1902 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1903 } else
1904 do_standby = true;
1905 }
1906 pthread_mutex_unlock(&out->lock);
1907
1908 if (do_standby)
1909 return out_standby(&out->stream.common);
1910
1911 return 0;
1912}
1913
Andy Hung7401c7c2016-09-21 12:41:21 -07001914static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001915{
Andy Hung7401c7c2016-09-21 12:41:21 -07001916 struct stream_out *out = (struct stream_out *)stream;
1917
1918 // We try to get the lock for consistency,
1919 // but it isn't necessary for these variables.
1920 // If we're not in standby, we may be blocked on a write.
1921 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1922 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1923 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1924
1925 if (locked) {
1926 log_dump_l(&out->error_log, fd);
1927 pthread_mutex_unlock(&out->lock);
1928 } else {
1929 // We don't have the lock here, copy for safety.
1930 struct error_log log = out->error_log;
1931 log_dump_l(&log, fd);
1932 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001933 return 0;
1934}
1935
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001936static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1937{
1938 int ret = 0;
1939 char value[32];
1940 struct compr_gapless_mdata tmp_mdata;
1941
1942 if (!out || !parms) {
1943 return -EINVAL;
1944 }
1945
1946 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1947 if (ret >= 0) {
1948 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1949 } else {
1950 return -EINVAL;
1951 }
1952
1953 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1954 if (ret >= 0) {
1955 tmp_mdata.encoder_padding = atoi(value);
1956 } else {
1957 return -EINVAL;
1958 }
1959
1960 out->gapless_mdata = tmp_mdata;
1961 out->send_new_metadata = 1;
1962 ALOGV("%s new encoder delay %u and padding %u", __func__,
1963 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1964
1965 return 0;
1966}
1967
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001968static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1969{
1970 return out == adev->primary_output || out == adev->voice_tx_output;
1971}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1974{
1975 struct stream_out *out = (struct stream_out *)stream;
1976 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001977 struct audio_usecase *usecase;
1978 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979 struct str_parms *parms;
1980 char value[32];
1981 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001982 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001983 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984
Eric Laurent2e140aa2016-06-30 17:14:46 -07001985 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001986 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987 parms = str_parms_create_str(kvpairs);
1988 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1989 if (ret >= 0) {
1990 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001991 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001992 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001994 /*
1995 * When HDMI cable is unplugged the music playback is paused and
1996 * the policy manager sends routing=0. But the audioflinger
1997 * continues to write data until standby time (3sec).
1998 * As the HDMI core is turned off, the write gets blocked.
1999 * Avoid this by routing audio to speaker until standby.
2000 */
2001 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2002 val == AUDIO_DEVICE_NONE) {
2003 val = AUDIO_DEVICE_OUT_SPEAKER;
2004 }
2005
2006 /*
2007 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002008 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002009 * the select_devices(). But how do we undo this?
2010 *
2011 * For example, music playback is active on headset (deep-buffer usecase)
2012 * and if we go to ringtones and select a ringtone, low-latency usecase
2013 * will be started on headset+speaker. As we can't enable headset+speaker
2014 * and headset devices at the same time, select_devices() switches the music
2015 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2016 * So when the ringtone playback is completed, how do we undo the same?
2017 *
2018 * We are relying on the out_set_parameters() call on deep-buffer output,
2019 * once the ringtone playback is ended.
2020 * NOTE: We should not check if the current devices are same as new devices.
2021 * Because select_devices() must be called to switch back the music
2022 * playback to headset.
2023 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002024 audio_devices_t new_dev = val;
2025 if (new_dev != AUDIO_DEVICE_NONE) {
2026 bool same_dev = out->devices == new_dev;
2027 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002028
Eric Laurenta7657192014-10-09 21:09:33 -07002029 if (output_drives_call(adev, out)) {
2030 if (!voice_is_in_call(adev)) {
2031 if (adev->mode == AUDIO_MODE_IN_CALL) {
2032 adev->current_call_output = out;
2033 ret = voice_start_call(adev);
2034 }
2035 } else {
2036 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002037 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002038 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002039 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002040
2041 if (!out->standby) {
2042 if (!same_dev) {
2043 ALOGV("update routing change");
2044 out->routing_change = true;
2045 }
2046 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002047 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002048 }
2049
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002050 }
2051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002053 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002054
2055 /*handles device and call state changes*/
2056 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002058
2059 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2060 parse_compress_metadata(out, parms);
2061 }
2062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002064 ALOGV("%s: exit: code(%d)", __func__, status);
2065 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066}
2067
2068static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2069{
2070 struct stream_out *out = (struct stream_out *)stream;
2071 struct str_parms *query = str_parms_create_str(keys);
2072 char *str;
2073 char value[256];
2074 struct str_parms *reply = str_parms_create();
2075 size_t i, j;
2076 int ret;
2077 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002078 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002079 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2080 if (ret >= 0) {
2081 value[0] = '\0';
2082 i = 0;
2083 while (out->supported_channel_masks[i] != 0) {
2084 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2085 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2086 if (!first) {
2087 strcat(value, "|");
2088 }
2089 strcat(value, out_channels_name_to_enum_table[j].name);
2090 first = false;
2091 break;
2092 }
2093 }
2094 i++;
2095 }
2096 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2097 str = str_parms_to_str(reply);
2098 } else {
2099 str = strdup(keys);
2100 }
2101 str_parms_destroy(query);
2102 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002103 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104 return str;
2105}
2106
2107static uint32_t out_get_latency(const struct audio_stream_out *stream)
2108{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002109 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110 struct stream_out *out = (struct stream_out *)stream;
2111
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002112 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2113 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002114 else if (out->realtime) {
2115 // since the buffer won't be filled up faster than realtime,
2116 // return a smaller number
2117 period_ms = (out->af_period_multiplier * out->config.period_size *
2118 1000) / (out->config.rate);
2119 hw_delay = platform_render_latency(out->usecase)/1000;
2120 return period_ms + hw_delay;
2121 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002122
2123 return (out->config.period_count * out->config.period_size * 1000) /
2124 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125}
2126
2127static int out_set_volume(struct audio_stream_out *stream, float left,
2128 float right)
2129{
Eric Laurenta9024de2013-04-04 09:19:12 -07002130 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002131 int volume[2];
2132
Eric Laurenta9024de2013-04-04 09:19:12 -07002133 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2134 /* only take left channel into account: the API is for stereo anyway */
2135 out->muted = (left == 0.0f);
2136 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002137 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2138 const char *mixer_ctl_name = "Compress Playback Volume";
2139 struct audio_device *adev = out->dev;
2140 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002141 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2142 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002143 /* try with the control based on device id */
2144 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2145 PCM_PLAYBACK);
2146 char ctl_name[128] = {0};
2147 snprintf(ctl_name, sizeof(ctl_name),
2148 "Compress Playback %d Volume", pcm_device_id);
2149 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2150 if (!ctl) {
2151 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2152 return -EINVAL;
2153 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002154 }
2155 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2156 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2157 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2158 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002159 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161 return -ENOSYS;
2162}
2163
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002164// note: this call is safe only if the stream_cb is
2165// removed first in close_output_stream (as is done now).
2166static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2167{
2168 if (!stream || !parms)
2169 return;
2170
2171 struct stream_out *out = (struct stream_out *)stream;
2172 struct audio_device *adev = out->dev;
2173
2174 card_status_t status;
2175 int card;
2176 if (parse_snd_card_status(parms, &card, &status) < 0)
2177 return;
2178
2179 pthread_mutex_lock(&adev->lock);
2180 bool valid_cb = (card == adev->snd_card);
2181 pthread_mutex_unlock(&adev->lock);
2182
2183 if (!valid_cb)
2184 return;
2185
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002186 lock_output_stream(out);
2187 if (out->card_status != status)
2188 out->card_status = status;
2189 pthread_mutex_unlock(&out->lock);
2190
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002191 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2192 use_case_table[out->usecase],
2193 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2194
2195 if (status == CARD_STATUS_OFFLINE)
2196 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002197
2198 return;
2199}
2200
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002201#ifdef NO_AUDIO_OUT
2202static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
2203 const void *buffer, size_t bytes)
2204{
2205 struct stream_out *out = (struct stream_out *)stream;
Prashant Malanidc71a442016-12-27 10:55:44 -08002206 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
2207 clock_gettime(CLOCK_MONOTONIC, &t);
2208 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
Eric Laurenta1478072015-09-21 17:21:52 -07002209 lock_output_stream(out);
Prashant Malanidc71a442016-12-27 10:55:44 -08002210 const int64_t elapsed_time_since_last_write = now - out->last_write_time_us;
2211 int64_t sleep_time = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2212 out_get_sample_rate(&stream->common) - elapsed_time_since_last_write;
2213 if (sleep_time > 0) {
2214 usleep(sleep_time);
2215 } else {
2216 // we don't sleep when we exit standby (this is typical for a real alsa buffer).
2217 sleep_time = 0;
2218 }
2219 out->last_write_time_us = now + sleep_time;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002220 pthread_mutex_unlock(&out->lock);
Prashant Malanidc71a442016-12-27 10:55:44 -08002221 // last_write_time_us is an approximation of when the (simulated) alsa
2222 // buffer is believed completely full. The usleep above waits for more space
2223 // in the buffer, but by the end of the sleep the buffer is considered
2224 // topped-off.
2225 //
2226 // On the subsequent out_write(), we measure the elapsed time spent in
2227 // the mixer. This is subtracted from the sleep estimate based on frames,
2228 // thereby accounting for drain in the alsa buffer during mixing.
2229 // This is a crude approximation; we don't handle underruns precisely.
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002230 return bytes;
2231}
2232#endif
2233
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2235 size_t bytes)
2236{
2237 struct stream_out *out = (struct stream_out *)stream;
2238 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002239 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002240 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241
Eric Laurenta1478072015-09-21 17:21:52 -07002242 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002243 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002244 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002245 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002247 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002248 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002250 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002251 goto exit;
2252 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002253
2254 if (last_known_cal_step != -1) {
2255 ALOGD("%s: retry previous failed cal level set", __func__);
2256 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2257 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002260 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002261 ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
2262 if (out->send_new_metadata) {
2263 ALOGVV("send new gapless metadata");
2264 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2265 out->send_new_metadata = 0;
2266 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002267 unsigned int avail;
2268 struct timespec tstamp;
2269 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2270 /* Do not limit write size if the available frames count is unknown */
2271 if (ret != 0) {
2272 avail = bytes;
2273 }
2274 if (avail == 0) {
2275 ret = 0;
2276 } else {
2277 if (avail > bytes) {
2278 avail = bytes;
2279 }
2280 ret = compress_write(out->compr, buffer, avail);
2281 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2282 __func__, avail, ret);
2283 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002284
Eric Laurent6e895242013-09-05 16:10:57 -07002285 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002286 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2287 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002288 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002289 compress_start(out->compr);
2290 out->playback_started = 1;
2291 out->offload_state = OFFLOAD_STATE_PLAYING;
2292 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002293 if (ret < 0) {
2294 log_error_l(&out->error_log, ERROR_CODE_WRITE);
2295 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002296 pthread_mutex_unlock(&out->lock);
2297 return ret;
2298 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002299 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002300 if (out->pcm) {
2301 if (out->muted)
2302 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002303
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002304 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002305
Haynes Mathew George03c40102016-01-29 17:57:48 -08002306 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2307 out->config.rate;
2308 request_out_focus(out, ns);
2309
2310 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2311 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002312 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002313 else
2314 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002315
Haynes Mathew George03c40102016-01-29 17:57:48 -08002316 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002317 } else {
2318 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002319 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320 }
2321
2322exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002323 // For PCM we always consume the buffer and return #bytes regardless of ret.
2324 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2325 out->written += bytes / (out->config.channels * sizeof(short));
2326 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002327 long long sleeptime_us = 0;
2328 if (ret != 0) {
2329 log_error_l(&out->error_log, error_code);
2330 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2331 ALOGE_IF(out->pcm != NULL,
2332 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
2333 sleeptime_us = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2334 out_get_sample_rate(&out->stream.common);
2335 // usleep not guaranteed for values over 1 second but we don't limit here.
2336 }
2337 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002338
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002339 pthread_mutex_unlock(&out->lock);
2340
2341 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002342 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002343 if (sleeptime_us != 0)
2344 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002345 }
2346 return bytes;
2347}
2348
2349static int out_get_render_position(const struct audio_stream_out *stream,
2350 uint32_t *dsp_frames)
2351{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002352 struct stream_out *out = (struct stream_out *)stream;
2353 *dsp_frames = 0;
2354 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002355 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002356 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002357 unsigned long frames = 0;
2358 // TODO: check return value
2359 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2360 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002361 ALOGVV("%s rendered frames %d sample_rate %d",
2362 __func__, *dsp_frames, out->sample_rate);
2363 }
2364 pthread_mutex_unlock(&out->lock);
2365 return 0;
2366 } else
2367 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368}
2369
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002370static int out_add_audio_effect(const struct audio_stream *stream __unused,
2371 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002372{
2373 return 0;
2374}
2375
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002376static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2377 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002378{
2379 return 0;
2380}
2381
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002382static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2383 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002384{
2385 return -EINVAL;
2386}
2387
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002388static int out_get_presentation_position(const struct audio_stream_out *stream,
2389 uint64_t *frames, struct timespec *timestamp)
2390{
2391 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002392 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002393 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002394
Eric Laurenta1478072015-09-21 17:21:52 -07002395 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002396
Eric Laurent949a0892013-09-20 09:20:13 -07002397 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2398 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002399 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002400 compress_get_tstamp(out->compr, &dsp_frames,
2401 &out->sample_rate);
2402 ALOGVV("%s rendered frames %ld sample_rate %d",
2403 __func__, dsp_frames, out->sample_rate);
2404 *frames = dsp_frames;
2405 ret = 0;
2406 /* this is the best we can do */
2407 clock_gettime(CLOCK_MONOTONIC, timestamp);
2408 }
2409 } else {
2410 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002411 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002412 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2413 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002414 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002415 // This adjustment accounts for buffering after app processor.
2416 // It is based on estimated DSP latency per use case, rather than exact.
2417 signed_frames -=
2418 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2419
Eric Laurent949a0892013-09-20 09:20:13 -07002420 // It would be unusual for this value to be negative, but check just in case ...
2421 if (signed_frames >= 0) {
2422 *frames = signed_frames;
2423 ret = 0;
2424 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002425 }
2426 }
2427 }
2428
2429 pthread_mutex_unlock(&out->lock);
2430
2431 return ret;
2432}
2433
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002434static int out_set_callback(struct audio_stream_out *stream,
2435 stream_callback_t callback, void *cookie)
2436{
2437 struct stream_out *out = (struct stream_out *)stream;
2438
2439 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002440 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002441 out->offload_callback = callback;
2442 out->offload_cookie = cookie;
2443 pthread_mutex_unlock(&out->lock);
2444 return 0;
2445}
2446
2447static int out_pause(struct audio_stream_out* stream)
2448{
2449 struct stream_out *out = (struct stream_out *)stream;
2450 int status = -ENOSYS;
2451 ALOGV("%s", __func__);
2452 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002453 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002454 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2455 status = compress_pause(out->compr);
2456 out->offload_state = OFFLOAD_STATE_PAUSED;
2457 }
2458 pthread_mutex_unlock(&out->lock);
2459 }
2460 return status;
2461}
2462
2463static int out_resume(struct audio_stream_out* stream)
2464{
2465 struct stream_out *out = (struct stream_out *)stream;
2466 int status = -ENOSYS;
2467 ALOGV("%s", __func__);
2468 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2469 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002470 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002471 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2472 status = compress_resume(out->compr);
2473 out->offload_state = OFFLOAD_STATE_PLAYING;
2474 }
2475 pthread_mutex_unlock(&out->lock);
2476 }
2477 return status;
2478}
2479
2480static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2481{
2482 struct stream_out *out = (struct stream_out *)stream;
2483 int status = -ENOSYS;
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 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2488 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2489 else
2490 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2491 pthread_mutex_unlock(&out->lock);
2492 }
2493 return status;
2494}
2495
2496static int out_flush(struct audio_stream_out* stream)
2497{
2498 struct stream_out *out = (struct stream_out *)stream;
2499 ALOGV("%s", __func__);
2500 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002501 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002502 stop_compressed_output_l(out);
2503 pthread_mutex_unlock(&out->lock);
2504 return 0;
2505 }
2506 return -ENOSYS;
2507}
2508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509/** audio_stream_in implementation **/
2510static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2511{
2512 struct stream_in *in = (struct stream_in *)stream;
2513
2514 return in->config.rate;
2515}
2516
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002517static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518{
2519 return -ENOSYS;
2520}
2521
2522static size_t in_get_buffer_size(const struct audio_stream *stream)
2523{
2524 struct stream_in *in = (struct stream_in *)stream;
2525
Haynes Mathew George03c40102016-01-29 17:57:48 -08002526 return in->config.period_size * in->af_period_multiplier *
2527 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528}
2529
2530static uint32_t in_get_channels(const struct audio_stream *stream)
2531{
2532 struct stream_in *in = (struct stream_in *)stream;
2533
2534 return in->channel_mask;
2535}
2536
vivek mehta4ed66e62016-04-15 23:33:34 -07002537static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538{
vivek mehta4ed66e62016-04-15 23:33:34 -07002539 struct stream_in *in = (struct stream_in *)stream;
2540 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541}
2542
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002543static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544{
2545 return -ENOSYS;
2546}
2547
2548static int in_standby(struct audio_stream *stream)
2549{
2550 struct stream_in *in = (struct stream_in *)stream;
2551 struct audio_device *adev = in->dev;
2552 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07002553 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002554
2555 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002556
2557 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002558 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002559 audio_extn_sound_trigger_stop_lab(in);
2560 in->standby = true;
2561 }
2562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002564 if (adev->adm_deregister_stream)
2565 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2566
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002567 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002569 if (in->pcm) {
2570 pcm_close(in->pcm);
2571 in->pcm = NULL;
2572 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002573 adev->enable_voicerx = false;
2574 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002576 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 }
2578 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002579 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 return status;
2581}
2582
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002583static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584{
2585 return 0;
2586}
2587
2588static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2589{
2590 struct stream_in *in = (struct stream_in *)stream;
2591 struct audio_device *adev = in->dev;
2592 struct str_parms *parms;
2593 char *str;
2594 char value[32];
2595 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002596 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597
Eric Laurent994a6932013-07-17 11:51:42 -07002598 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 parms = str_parms_create_str(kvpairs);
2600
2601 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2602
Eric Laurenta1478072015-09-21 17:21:52 -07002603 lock_input_stream(in);
2604
Eric Laurent150dbfe2013-02-27 14:31:02 -08002605 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002606 if (ret >= 0) {
2607 val = atoi(value);
2608 /* no audio source uses val == 0 */
2609 if ((in->source != val) && (val != 0)) {
2610 in->source = val;
2611 }
2612 }
2613
2614 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616 if (ret >= 0) {
2617 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002618 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619 in->device = val;
2620 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002621 if (!in->standby) {
2622 ALOGV("update input routing change");
2623 in->routing_change = true;
2624 select_devices(adev, in->usecase);
2625 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626 }
2627 }
2628
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002630 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002631
2632 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002633 ALOGV("%s: exit: status(%d)", __func__, status);
2634 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635}
2636
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002637static char* in_get_parameters(const struct audio_stream *stream __unused,
2638 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639{
2640 return strdup("");
2641}
2642
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002643static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644{
2645 return 0;
2646}
2647
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002648static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2649{
2650 if (!stream || !parms)
2651 return;
2652
2653 struct stream_in *in = (struct stream_in *)stream;
2654 struct audio_device *adev = in->dev;
2655
2656 card_status_t status;
2657 int card;
2658 if (parse_snd_card_status(parms, &card, &status) < 0)
2659 return;
2660
2661 pthread_mutex_lock(&adev->lock);
2662 bool valid_cb = (card == adev->snd_card);
2663 pthread_mutex_unlock(&adev->lock);
2664
2665 if (!valid_cb)
2666 return;
2667
2668 lock_input_stream(in);
2669 if (in->card_status != status)
2670 in->card_status = status;
2671 pthread_mutex_unlock(&in->lock);
2672
2673 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2674 use_case_table[in->usecase],
2675 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2676
2677 // a better solution would be to report error back to AF and let
2678 // it put the stream to standby
2679 if (status == CARD_STATUS_OFFLINE)
2680 in_standby(&in->stream.common);
2681
2682 return;
2683}
2684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2686 size_t bytes)
2687{
2688 struct stream_in *in = (struct stream_in *)stream;
2689 struct audio_device *adev = in->dev;
2690 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002691 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692
Eric Laurenta1478072015-09-21 17:21:52 -07002693 lock_input_stream(in);
2694
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002695 if (in->is_st_session) {
2696 ALOGVV(" %s: reading on st session bytes=%d", __func__, bytes);
2697 /* Read from sound trigger HAL */
2698 audio_extn_sound_trigger_read(in, buffer, bytes);
2699 pthread_mutex_unlock(&in->lock);
2700 return bytes;
2701 }
2702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002704 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002705 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002706 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708 goto exit;
2709 }
2710 in->standby = 0;
2711 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712
Haynes Mathew George03c40102016-01-29 17:57:48 -08002713 //what's the duration requested by the client?
2714 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2715 in->config.rate;
2716 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002717
Haynes Mathew George03c40102016-01-29 17:57:48 -08002718 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002720 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002721 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002722 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002723 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002724 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002725 if (ret < 0) {
2726 ALOGE("Failed to read w/err %s", strerror(errno));
2727 ret = -errno;
2728 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002729 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2730 if (bytes % 4 == 0) {
2731 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2732 int_buf_stream = buffer;
2733 for (size_t itt=0; itt < bytes/4 ; itt++) {
2734 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002735 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002736 } else {
2737 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2738 ret = -EINVAL;
2739 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002740 }
2741 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002742 }
2743
Haynes Mathew George03c40102016-01-29 17:57:48 -08002744 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002745
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002746 /*
2747 * Instead of writing zeroes here, we could trust the hardware
2748 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002749 * 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 -08002750 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002751 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002752 memset(buffer, 0, bytes);
2753
2754exit:
2755 pthread_mutex_unlock(&in->lock);
2756
2757 if (ret != 0) {
2758 in_standby(&in->stream.common);
2759 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002760 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002762 memset(buffer, 0, bytes); // clear return data
2763 }
2764 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002765 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766 }
2767 return bytes;
2768}
2769
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002770static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771{
2772 return 0;
2773}
2774
Andy Hung6ebe5962016-01-15 17:46:57 -08002775static int in_get_capture_position(const struct audio_stream_in *stream,
2776 int64_t *frames, int64_t *time)
2777{
2778 if (stream == NULL || frames == NULL || time == NULL) {
2779 return -EINVAL;
2780 }
2781 struct stream_in *in = (struct stream_in *)stream;
2782 int ret = -ENOSYS;
2783
2784 lock_input_stream(in);
2785 if (in->pcm) {
2786 struct timespec timestamp;
2787 unsigned int avail;
2788 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2789 *frames = in->frames_read + avail;
2790 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2791 ret = 0;
2792 }
2793 }
2794 pthread_mutex_unlock(&in->lock);
2795 return ret;
2796}
2797
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002798static int add_remove_audio_effect(const struct audio_stream *stream,
2799 effect_handle_t effect,
2800 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002801{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002802 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002803 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002804 int status = 0;
2805 effect_descriptor_t desc;
2806
2807 status = (*effect)->get_descriptor(effect, &desc);
2808 if (status != 0)
2809 return status;
2810
Eric Laurenta1478072015-09-21 17:21:52 -07002811 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002812 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002813 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002814 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002815 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002816 in->enable_aec != enable &&
2817 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2818 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002819 if (!enable)
2820 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002821 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2822 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2823 adev->enable_voicerx = enable;
2824 struct audio_usecase *usecase;
2825 struct listnode *node;
2826 list_for_each(node, &adev->usecase_list) {
2827 usecase = node_to_item(node, struct audio_usecase, list);
2828 if (usecase->type == PCM_PLAYBACK) {
2829 select_devices(adev, usecase->id);
2830 break;
2831 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002832 }
2833 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002834 if (!in->standby)
2835 select_devices(in->dev, in->usecase);
2836 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07002837 if (in->enable_ns != enable &&
2838 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2839 in->enable_ns = enable;
2840 if (!in->standby)
2841 select_devices(in->dev, in->usecase);
2842 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002843 pthread_mutex_unlock(&in->dev->lock);
2844 pthread_mutex_unlock(&in->lock);
2845
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002846 return 0;
2847}
2848
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002849static int in_add_audio_effect(const struct audio_stream *stream,
2850 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002851{
Eric Laurent994a6932013-07-17 11:51:42 -07002852 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002853 return add_remove_audio_effect(stream, effect, true);
2854}
2855
2856static int in_remove_audio_effect(const struct audio_stream *stream,
2857 effect_handle_t effect)
2858{
Eric Laurent994a6932013-07-17 11:51:42 -07002859 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002860 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002861}
2862
2863static int adev_open_output_stream(struct audio_hw_device *dev,
2864 audio_io_handle_t handle,
2865 audio_devices_t devices,
2866 audio_output_flags_t flags,
2867 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07002868 struct audio_stream_out **stream_out,
2869 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870{
2871 struct audio_device *adev = (struct audio_device *)dev;
2872 struct stream_out *out;
2873 int i, ret;
2874
Eric Laurent994a6932013-07-17 11:51:42 -07002875 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002876 __func__, config->sample_rate, config->channel_mask, devices, flags);
2877 *stream_out = NULL;
2878 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2879
2880 if (devices == AUDIO_DEVICE_NONE)
2881 devices = AUDIO_DEVICE_OUT_SPEAKER;
2882
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883 out->flags = flags;
2884 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002885 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002886 out->format = config->format;
2887 out->sample_rate = config->sample_rate;
2888 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2889 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002890 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891
2892 /* Init use case and pcm_config */
2893 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07002894 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002895 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002896 pthread_mutex_lock(&adev->lock);
2897 ret = read_hdmi_channel_masks(out);
2898 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002899 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002900 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002901
2902 if (config->sample_rate == 0)
2903 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2904 if (config->channel_mask == 0)
2905 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08002906 if (config->format == AUDIO_FORMAT_DEFAULT)
2907 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002908
2909 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002910 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08002911 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002912 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2913 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002914 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002915 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002916 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002917 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07002918 pthread_mutex_lock(&adev->lock);
2919 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
2920 pthread_mutex_unlock(&adev->lock);
2921
2922 // reject offload during card offline to allow
2923 // fallback to s/w paths
2924 if (offline) {
2925 ret = -ENODEV;
2926 goto error_open;
2927 }
2928
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002929 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2930 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2931 ALOGE("%s: Unsupported Offload information", __func__);
2932 ret = -EINVAL;
2933 goto error_open;
2934 }
2935 if (!is_supported_format(config->offload_info.format)) {
2936 ALOGE("%s: Unsupported audio format", __func__);
2937 ret = -EINVAL;
2938 goto error_open;
2939 }
2940
2941 out->compr_config.codec = (struct snd_codec *)
2942 calloc(1, sizeof(struct snd_codec));
2943
2944 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
2945 if (config->offload_info.channel_mask)
2946 out->channel_mask = config->offload_info.channel_mask;
2947 else if (config->channel_mask)
2948 out->channel_mask = config->channel_mask;
2949 out->format = config->offload_info.format;
2950 out->sample_rate = config->offload_info.sample_rate;
2951
2952 out->stream.set_callback = out_set_callback;
2953 out->stream.pause = out_pause;
2954 out->stream.resume = out_resume;
2955 out->stream.drain = out_drain;
2956 out->stream.flush = out_flush;
2957
2958 out->compr_config.codec->id =
2959 get_snd_codec_id(config->offload_info.format);
2960 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
2961 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07002962 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002963 out->compr_config.codec->bit_rate =
2964 config->offload_info.bit_rate;
2965 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002966 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002967 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
2968
2969 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2970 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002971
2972 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002973 create_offload_callback_thread(out);
2974 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2975 __func__, config->offload_info.version,
2976 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002977 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2978 if (config->sample_rate == 0)
2979 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2980 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2981 config->sample_rate != 8000) {
2982 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2983 ret = -EINVAL;
2984 goto error_open;
2985 }
2986 out->sample_rate = config->sample_rate;
2987 out->config.rate = config->sample_rate;
2988 if (config->format == AUDIO_FORMAT_DEFAULT)
2989 config->format = AUDIO_FORMAT_PCM_16_BIT;
2990 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2991 config->format = AUDIO_FORMAT_PCM_16_BIT;
2992 ret = -EINVAL;
2993 goto error_open;
2994 }
2995 out->format = config->format;
2996 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2997 out->config = pcm_config_afe_proxy_playback;
2998 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003000 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3001 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3002 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003003 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3004 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3005 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003006 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3007 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003008 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
3009 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3010 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003011 } else {
3012 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3013 out->config = pcm_config_low_latency;
3014 }
3015 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3016 if (k_enable_extended_precision
3017 && pcm_params_format_test(adev->use_case_table[out->usecase],
3018 pcm_format_from_audio_format(config->format))) {
3019 out->config.format = pcm_format_from_audio_format(config->format);
3020 /* out->format already set to config->format */
3021 } else {
3022 /* deny the externally proposed config format
3023 * and use the one specified in audio_hw layer configuration.
3024 * Note: out->format is returned by out->stream.common.get_format()
3025 * and is used to set config->format in the code several lines below.
3026 */
3027 out->format = audio_format_from_pcm_format(out->config.format);
3028 }
3029 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003030 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003032 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3033 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003035 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003036 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003037 adev->primary_output = out;
3038 else {
3039 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003040 ret = -EEXIST;
3041 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003042 }
3043 }
3044
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045 /* Check if this usecase is already existing */
3046 pthread_mutex_lock(&adev->lock);
3047 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3048 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003050 ret = -EEXIST;
3051 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052 }
3053 pthread_mutex_unlock(&adev->lock);
3054
3055 out->stream.common.get_sample_rate = out_get_sample_rate;
3056 out->stream.common.set_sample_rate = out_set_sample_rate;
3057 out->stream.common.get_buffer_size = out_get_buffer_size;
3058 out->stream.common.get_channels = out_get_channels;
3059 out->stream.common.get_format = out_get_format;
3060 out->stream.common.set_format = out_set_format;
3061 out->stream.common.standby = out_standby;
3062 out->stream.common.dump = out_dump;
3063 out->stream.common.set_parameters = out_set_parameters;
3064 out->stream.common.get_parameters = out_get_parameters;
3065 out->stream.common.add_audio_effect = out_add_audio_effect;
3066 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3067 out->stream.get_latency = out_get_latency;
3068 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003069#ifdef NO_AUDIO_OUT
3070 out->stream.write = out_write_for_no_output;
3071#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003072 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003073#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074 out->stream.get_render_position = out_get_render_position;
3075 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003076 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077
Haynes Mathew George03c40102016-01-29 17:57:48 -08003078 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003080 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003081 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003083 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003084 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003085 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3086
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003087 config->format = out->stream.common.get_format(&out->stream.common);
3088 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3089 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3090
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003091
3092 /*
3093 By locking output stream before registering, we allow the callback
3094 to update stream's state only after stream's initial state is set to
3095 adev state.
3096 */
3097 lock_output_stream(out);
3098 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3099 pthread_mutex_lock(&adev->lock);
3100 out->card_status = adev->card_status;
3101 pthread_mutex_unlock(&adev->lock);
3102 pthread_mutex_unlock(&out->lock);
3103
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003104 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003105 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003107
3108error_open:
3109 free(out);
3110 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003111 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003112 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113}
3114
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003115static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116 struct audio_stream_out *stream)
3117{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003118 struct stream_out *out = (struct stream_out *)stream;
3119 struct audio_device *adev = out->dev;
3120
Eric Laurent994a6932013-07-17 11:51:42 -07003121 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003122
3123 // must deregister from sndmonitor first to prevent races
3124 // between the callback and close_stream
3125 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003127 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3128 destroy_offload_callback_thread(out);
3129
3130 if (out->compr_config.codec != NULL)
3131 free(out->compr_config.codec);
3132 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003133
3134 if (adev->voice_tx_output == out)
3135 adev->voice_tx_output = NULL;
3136
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003137 pthread_cond_destroy(&out->cond);
3138 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003140 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141}
3142
3143static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3144{
3145 struct audio_device *adev = (struct audio_device *)dev;
3146 struct str_parms *parms;
3147 char *str;
3148 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003149 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003151 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003152
Joe Onorato188b6222016-03-01 11:02:27 -08003153 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003154
3155 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003156
3157 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003158 status = voice_set_parameters(adev, parms);
3159 if (status != 0) {
3160 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161 }
3162
3163 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3164 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003165 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3167 adev->bluetooth_nrec = true;
3168 else
3169 adev->bluetooth_nrec = false;
3170 }
3171
3172 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3173 if (ret >= 0) {
3174 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3175 adev->screen_off = false;
3176 else
3177 adev->screen_off = true;
3178 }
3179
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003180 ret = str_parms_get_int(parms, "rotation", &val);
3181 if (ret >= 0) {
3182 bool reverse_speakers = false;
3183 switch(val) {
3184 // FIXME: note that the code below assumes that the speakers are in the correct placement
3185 // relative to the user when the device is rotated 90deg from its default rotation. This
3186 // assumption is device-specific, not platform-specific like this code.
3187 case 270:
3188 reverse_speakers = true;
3189 break;
3190 case 0:
3191 case 90:
3192 case 180:
3193 break;
3194 default:
3195 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003196 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003197 }
Eric Laurent03f09432014-03-25 18:09:11 -07003198 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003199 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003200 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003201 }
3202
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003203 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3204 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003205 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003206 }
3207
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003208 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003209done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003210 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003211 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003212 ALOGV("%s: exit with code(%d)", __func__, status);
3213 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214}
3215
3216static char* adev_get_parameters(const struct audio_hw_device *dev,
3217 const char *keys)
3218{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003219 struct audio_device *adev = (struct audio_device *)dev;
3220 struct str_parms *reply = str_parms_create();
3221 struct str_parms *query = str_parms_create_str(keys);
3222 char *str;
3223
3224 pthread_mutex_lock(&adev->lock);
3225
3226 voice_get_parameters(adev, query, reply);
3227 str = str_parms_to_str(reply);
3228 str_parms_destroy(query);
3229 str_parms_destroy(reply);
3230
3231 pthread_mutex_unlock(&adev->lock);
3232 ALOGV("%s: exit: returns - %s", __func__, str);
3233 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234}
3235
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003236static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237{
3238 return 0;
3239}
3240
Haynes Mathew George5191a852013-09-11 14:19:36 -07003241static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3242{
3243 int ret;
3244 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003245
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003246 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3247
Haynes Mathew George5191a852013-09-11 14:19:36 -07003248 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003249 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003250 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003251
Haynes Mathew George5191a852013-09-11 14:19:36 -07003252 return ret;
3253}
3254
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003255static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256{
3257 return -ENOSYS;
3258}
3259
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003260static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3261 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262{
3263 return -ENOSYS;
3264}
3265
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003266static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003267{
3268 return -ENOSYS;
3269}
3270
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003271static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272{
3273 return -ENOSYS;
3274}
3275
3276static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3277{
3278 struct audio_device *adev = (struct audio_device *)dev;
3279
3280 pthread_mutex_lock(&adev->lock);
3281 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003282 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003284 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3285 voice_is_in_call(adev)) {
3286 voice_stop_call(adev);
3287 adev->current_call_output = NULL;
3288 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003289 }
3290 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003291
3292 audio_extn_extspk_set_mode(adev->extspk, mode);
3293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003294 return 0;
3295}
3296
3297static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3298{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003299 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003301
Eric Laurent2bafff12016-03-17 12:17:23 -07003302 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003303 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003304 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3305 ret = audio_extn_hfp_set_mic_mute(adev, state);
3306 } else {
3307 ret = voice_set_mic_mute(adev, state);
3308 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003309 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003310 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003311
3312 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313}
3314
3315static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3316{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003317 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318 return 0;
3319}
3320
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003321static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322 const struct audio_config *config)
3323{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003324 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003326 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3327 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328}
3329
3330static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003331 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003332 audio_devices_t devices,
3333 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003334 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003335 audio_input_flags_t flags,
3336 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003337 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338{
3339 struct audio_device *adev = (struct audio_device *)dev;
3340 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003341 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003342 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003343 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344
Eric Laurent994a6932013-07-17 11:51:42 -07003345 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003346 *stream_in = NULL;
3347 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3348 return -EINVAL;
3349
Zheng Zhang6185d572016-12-01 20:35:17 +08003350 if (audio_extn_tfa_98xx_is_supported() && (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003351 return -EINVAL;
3352
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3354
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003355 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003356 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003358 in->stream.common.get_sample_rate = in_get_sample_rate;
3359 in->stream.common.set_sample_rate = in_set_sample_rate;
3360 in->stream.common.get_buffer_size = in_get_buffer_size;
3361 in->stream.common.get_channels = in_get_channels;
3362 in->stream.common.get_format = in_get_format;
3363 in->stream.common.set_format = in_set_format;
3364 in->stream.common.standby = in_standby;
3365 in->stream.common.dump = in_dump;
3366 in->stream.common.set_parameters = in_set_parameters;
3367 in->stream.common.get_parameters = in_get_parameters;
3368 in->stream.common.add_audio_effect = in_add_audio_effect;
3369 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3370 in->stream.set_gain = in_set_gain;
3371 in->stream.read = in_read;
3372 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003373 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374
3375 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003376 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003378 in->standby = 1;
3379 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003380 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003381 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382
vivek mehta57ff9b52016-04-28 14:13:08 -07003383 // restrict 24 bit capture for unprocessed source only
3384 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3385 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003386 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003387 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3388 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3389 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3390 bool ret_error = false;
3391 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3392 from HAL is 8_24
3393 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3394 8_24 return error indicating supported format is 8_24
3395 *> In case of any other source requesting 24 bit or float return error
3396 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003397
vivek mehta57ff9b52016-04-28 14:13:08 -07003398 on error flinger will retry with supported format passed
3399 */
3400 if (source != AUDIO_SOURCE_UNPROCESSED) {
3401 config->format = AUDIO_FORMAT_PCM_16_BIT;
3402 ret_error = true;
3403 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3404 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3405 ret_error = true;
3406 }
3407
3408 if (ret_error) {
3409 ret = -EINVAL;
3410 goto err_open;
3411 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003412 }
3413
vivek mehta57ff9b52016-04-28 14:13:08 -07003414 in->format = config->format;
3415
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003417 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3418 if (config->sample_rate == 0)
3419 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3420 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3421 config->sample_rate != 8000) {
3422 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3423 ret = -EINVAL;
3424 goto err_open;
3425 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003426
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003427 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3428 config->format = AUDIO_FORMAT_PCM_16_BIT;
3429 ret = -EINVAL;
3430 goto err_open;
3431 }
3432
3433 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3434 in->config = pcm_config_afe_proxy_record;
3435 } else {
3436 in->usecase = USECASE_AUDIO_RECORD;
3437 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3438 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3439 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003440#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003441 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003442#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003443 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003444 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003445
Haynes Mathew George03c40102016-01-29 17:57:48 -08003446 in->config = in->realtime ? pcm_config_audio_capture_rt :
3447 pcm_config_audio_capture;
3448
vivek mehta4ed66e62016-04-15 23:33:34 -07003449 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3450 in->config.format = PCM_FORMAT_S24_LE;
3451
Haynes Mathew George03c40102016-01-29 17:57:48 -08003452 if (!in->realtime) {
3453 frame_size = audio_stream_in_frame_size(&in->stream);
3454 buffer_size = get_input_buffer_size(config->sample_rate,
3455 config->format,
3456 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003457 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003458 in->config.period_size = buffer_size / frame_size;
3459 } // period size is left untouched for rt mode playback
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003460 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003461
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003462 in->config.channels = channel_count;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003463 if (in->realtime) {
3464 in->af_period_multiplier = af_period_multiplier;
3465 } else {
3466 in->config.rate = config->sample_rate;
3467 in->af_period_multiplier = 1;
3468 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003470 /* This stream could be for sound trigger lab,
3471 get sound trigger pcm if present */
3472 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003473
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003474 lock_input_stream(in);
3475 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3476 pthread_mutex_lock(&adev->lock);
3477 in->card_status = adev->card_status;
3478 pthread_mutex_unlock(&adev->lock);
3479 pthread_mutex_unlock(&in->lock);
3480
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003481 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003482 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483 return 0;
3484
3485err_open:
3486 free(in);
3487 *stream_in = NULL;
3488 return ret;
3489}
3490
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003491static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003492 struct audio_stream_in *stream)
3493{
Eric Laurent994a6932013-07-17 11:51:42 -07003494 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003495
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003496 // must deregister from sndmonitor first to prevent races
3497 // between the callback and close_stream
3498 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499 in_standby(&stream->common);
3500 free(stream);
3501
3502 return;
3503}
3504
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003505static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506{
3507 return 0;
3508}
3509
Andy Hung31aca912014-03-20 17:14:59 -07003510/* verifies input and output devices and their capabilities.
3511 *
3512 * This verification is required when enabling extended bit-depth or
3513 * sampling rates, as not all qcom products support it.
3514 *
3515 * Suitable for calling only on initialization such as adev_open().
3516 * It fills the audio_device use_case_table[] array.
3517 *
3518 * Has a side-effect that it needs to configure audio routing / devices
3519 * in order to power up the devices and read the device parameters.
3520 * It does not acquire any hw device lock. Should restore the devices
3521 * back to "normal state" upon completion.
3522 */
3523static int adev_verify_devices(struct audio_device *adev)
3524{
3525 /* enumeration is a bit difficult because one really wants to pull
3526 * the use_case, device id, etc from the hidden pcm_device_table[].
3527 * In this case there are the following use cases and device ids.
3528 *
3529 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3530 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3531 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3532 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3533 * [USECASE_AUDIO_RECORD] = {0, 0},
3534 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3535 * [USECASE_VOICE_CALL] = {2, 2},
3536 *
3537 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3538 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3539 */
3540
3541 /* should be the usecases enabled in adev_open_input_stream() */
3542 static const int test_in_usecases[] = {
3543 USECASE_AUDIO_RECORD,
3544 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3545 };
3546 /* should be the usecases enabled in adev_open_output_stream()*/
3547 static const int test_out_usecases[] = {
3548 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3549 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3550 };
3551 static const usecase_type_t usecase_type_by_dir[] = {
3552 PCM_PLAYBACK,
3553 PCM_CAPTURE,
3554 };
3555 static const unsigned flags_by_dir[] = {
3556 PCM_OUT,
3557 PCM_IN,
3558 };
3559
3560 size_t i;
3561 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003562 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003563 char info[512]; /* for possible debug info */
3564
3565 for (dir = 0; dir < 2; ++dir) {
3566 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3567 const unsigned flags_dir = flags_by_dir[dir];
3568 const size_t testsize =
3569 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3570 const int *testcases =
3571 dir ? test_in_usecases : test_out_usecases;
3572 const audio_devices_t audio_device =
3573 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3574
3575 for (i = 0; i < testsize; ++i) {
3576 const audio_usecase_t audio_usecase = testcases[i];
3577 int device_id;
3578 snd_device_t snd_device;
3579 struct pcm_params **pparams;
3580 struct stream_out out;
3581 struct stream_in in;
3582 struct audio_usecase uc_info;
3583 int retval;
3584
3585 pparams = &adev->use_case_table[audio_usecase];
3586 pcm_params_free(*pparams); /* can accept null input */
3587 *pparams = NULL;
3588
3589 /* find the device ID for the use case (signed, for error) */
3590 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3591 if (device_id < 0)
3592 continue;
3593
3594 /* prepare structures for device probing */
3595 memset(&uc_info, 0, sizeof(uc_info));
3596 uc_info.id = audio_usecase;
3597 uc_info.type = usecase_type;
3598 if (dir) {
3599 adev->active_input = &in;
3600 memset(&in, 0, sizeof(in));
3601 in.device = audio_device;
3602 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3603 uc_info.stream.in = &in;
3604 } else {
3605 adev->active_input = NULL;
3606 }
3607 memset(&out, 0, sizeof(out));
3608 out.devices = audio_device; /* only field needed in select_devices */
3609 uc_info.stream.out = &out;
3610 uc_info.devices = audio_device;
3611 uc_info.in_snd_device = SND_DEVICE_NONE;
3612 uc_info.out_snd_device = SND_DEVICE_NONE;
3613 list_add_tail(&adev->usecase_list, &uc_info.list);
3614
3615 /* select device - similar to start_(in/out)put_stream() */
3616 retval = select_devices(adev, audio_usecase);
3617 if (retval >= 0) {
3618 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3619#if LOG_NDEBUG == 0
3620 if (*pparams) {
3621 ALOGV("%s: (%s) card %d device %d", __func__,
3622 dir ? "input" : "output", card_id, device_id);
3623 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07003624 } else {
3625 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3626 }
3627#endif
3628 }
3629
3630 /* deselect device - similar to stop_(in/out)put_stream() */
3631 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07003632 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07003633 /* 2. Disable the rx device */
3634 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07003635 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07003636 list_remove(&uc_info.list);
3637 }
3638 }
3639 adev->active_input = NULL; /* restore adev state */
3640 return 0;
3641}
3642
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003643static int adev_close(hw_device_t *device)
3644{
Andy Hung31aca912014-03-20 17:14:59 -07003645 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003647
3648 if (!adev)
3649 return 0;
3650
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003651 audio_extn_tfa_98xx_deinit();
3652
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003653 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003654 pthread_mutex_lock(&adev_init_lock);
3655
3656 if ((--audio_device_ref_count) == 0) {
3657 audio_route_free(adev->audio_route);
3658 free(adev->snd_dev_ref_cnt);
3659 platform_deinit(adev->platform);
3660 audio_extn_extspk_deinit(adev->extspk);
3661 audio_extn_sound_trigger_deinit(adev);
3662 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3663 pcm_params_free(adev->use_case_table[i]);
3664 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003665 if (adev->adm_deinit)
3666 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003667 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07003668 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07003669
3670 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672 return 0;
3673}
3674
Glenn Kasten4f993392014-05-14 07:30:48 -07003675/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3676 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3677 * just that it _might_ work.
3678 */
3679static int period_size_is_plausible_for_low_latency(int period_size)
3680{
3681 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003682 case 48:
3683 case 96:
3684 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07003685 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003686 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07003687 case 240:
3688 case 320:
3689 case 480:
3690 return 1;
3691 default:
3692 return 0;
3693 }
3694}
3695
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003696static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
3697{
3698 int card;
3699 card_status_t status;
3700
3701 if (!parms)
3702 return;
3703
3704 if (parse_snd_card_status(parms, &card, &status) < 0)
3705 return;
3706
3707 pthread_mutex_lock(&adev->lock);
3708 bool valid_cb = (card == adev->snd_card);
3709 if (valid_cb) {
3710 if (adev->card_status != status) {
3711 adev->card_status = status;
3712 platform_snd_card_update(adev->platform, status);
3713 }
3714 }
3715 pthread_mutex_unlock(&adev->lock);
3716 return;
3717}
3718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719static int adev_open(const hw_module_t *module, const char *name,
3720 hw_device_t **device)
3721{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003722 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723
Eric Laurent2bafff12016-03-17 12:17:23 -07003724 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003726 pthread_mutex_lock(&adev_init_lock);
3727 if (audio_device_ref_count != 0) {
3728 *device = &adev->device.common;
3729 audio_device_ref_count++;
3730 ALOGV("%s: returning existing instance of adev", __func__);
3731 ALOGV("%s: exit", __func__);
3732 pthread_mutex_unlock(&adev_init_lock);
3733 return 0;
3734 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735 adev = calloc(1, sizeof(struct audio_device));
3736
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003737 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3740 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3741 adev->device.common.module = (struct hw_module_t *)module;
3742 adev->device.common.close = adev_close;
3743
3744 adev->device.init_check = adev_init_check;
3745 adev->device.set_voice_volume = adev_set_voice_volume;
3746 adev->device.set_master_volume = adev_set_master_volume;
3747 adev->device.get_master_volume = adev_get_master_volume;
3748 adev->device.set_master_mute = adev_set_master_mute;
3749 adev->device.get_master_mute = adev_get_master_mute;
3750 adev->device.set_mode = adev_set_mode;
3751 adev->device.set_mic_mute = adev_set_mic_mute;
3752 adev->device.get_mic_mute = adev_get_mic_mute;
3753 adev->device.set_parameters = adev_set_parameters;
3754 adev->device.get_parameters = adev_get_parameters;
3755 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3756 adev->device.open_output_stream = adev_open_output_stream;
3757 adev->device.close_output_stream = adev_close_output_stream;
3758 adev->device.open_input_stream = adev_open_input_stream;
3759 adev->device.close_input_stream = adev_close_input_stream;
3760 adev->device.dump = adev_dump;
3761
3762 /* Set the default route before the PCM stream is opened */
3763 pthread_mutex_lock(&adev->lock);
3764 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003765 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003766 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003768 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003769 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003770 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003771 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003772 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773 pthread_mutex_unlock(&adev->lock);
3774
3775 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003776 adev->platform = platform_init(adev);
3777 if (!adev->platform) {
3778 free(adev->snd_dev_ref_cnt);
3779 free(adev);
3780 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3781 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003782 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003783 return -EINVAL;
3784 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05003785 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003786 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003787
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003788 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3789 if (adev->visualizer_lib == NULL) {
3790 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3791 } else {
3792 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3793 adev->visualizer_start_output =
3794 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3795 "visualizer_hal_start_output");
3796 adev->visualizer_stop_output =
3797 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3798 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07003799 }
3800
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003801 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3802 if (adev->offload_effects_lib == NULL) {
3803 ALOGW("%s: DLOPEN failed for %s", __func__,
3804 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3805 } else {
3806 ALOGV("%s: DLOPEN successful for %s", __func__,
3807 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3808 adev->offload_effects_start_output =
3809 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3810 "offload_effects_bundle_hal_start_output");
3811 adev->offload_effects_stop_output =
3812 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3813 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07003814 }
3815
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003816 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3817 if (adev->adm_lib == NULL) {
3818 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3819 } else {
3820 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3821 adev->adm_init = (adm_init_t)
3822 dlsym(adev->adm_lib, "adm_init");
3823 adev->adm_deinit = (adm_deinit_t)
3824 dlsym(adev->adm_lib, "adm_deinit");
3825 adev->adm_register_input_stream = (adm_register_input_stream_t)
3826 dlsym(adev->adm_lib, "adm_register_input_stream");
3827 adev->adm_register_output_stream = (adm_register_output_stream_t)
3828 dlsym(adev->adm_lib, "adm_register_output_stream");
3829 adev->adm_deregister_stream = (adm_deregister_stream_t)
3830 dlsym(adev->adm_lib, "adm_deregister_stream");
3831 adev->adm_request_focus = (adm_request_focus_t)
3832 dlsym(adev->adm_lib, "adm_request_focus");
3833 adev->adm_abandon_focus = (adm_abandon_focus_t)
3834 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08003835 adev->adm_set_config = (adm_set_config_t)
3836 dlsym(adev->adm_lib, "adm_set_config");
3837 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
3838 dlsym(adev->adm_lib, "adm_request_focus_v2");
3839 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
3840 dlsym(adev->adm_lib, "adm_is_noirq_avail");
3841 adev->adm_on_routing_change = (adm_on_routing_change_t)
3842 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003843 }
3844
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003845 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003846 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003849
Andy Hung31aca912014-03-20 17:14:59 -07003850 if (k_enable_extended_precision)
3851 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003852
Glenn Kasten4f993392014-05-14 07:30:48 -07003853 char value[PROPERTY_VALUE_MAX];
3854 int trial;
3855 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3856 trial = atoi(value);
3857 if (period_size_is_plausible_for_low_latency(trial)) {
3858 pcm_config_low_latency.period_size = trial;
3859 pcm_config_low_latency.start_threshold = trial / 4;
3860 pcm_config_low_latency.avail_min = trial / 4;
3861 configured_low_latency_capture_period_size = trial;
3862 }
3863 }
3864 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3865 trial = atoi(value);
3866 if (period_size_is_plausible_for_low_latency(trial)) {
3867 configured_low_latency_capture_period_size = trial;
3868 }
3869 }
3870
Yamit Mehtae3b99562016-09-16 22:44:00 +05303871 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003872 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003873
3874 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
3875 af_period_multiplier = atoi(value);
3876 if (af_period_multiplier < 0) {
3877 af_period_multiplier = 2;
3878 } else if (af_period_multiplier > 4) {
3879 af_period_multiplier = 4;
3880 }
3881 ALOGV("new period_multiplier = %d", af_period_multiplier);
3882 }
3883
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003884 audio_extn_tfa_98xx_init(adev);
3885
vivek mehta1a9b7c02015-06-25 11:49:38 -07003886 pthread_mutex_unlock(&adev_init_lock);
3887
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003888 if (adev->adm_init)
3889 adev->adm_data = adev->adm_init();
3890
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003891 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003892 audio_extn_snd_mon_init();
3893 pthread_mutex_lock(&adev->lock);
3894 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
3895 adev->card_status = CARD_STATUS_ONLINE;
3896 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003897
Eric Laurent2bafff12016-03-17 12:17:23 -07003898 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899 return 0;
3900}
3901
3902static struct hw_module_methods_t hal_module_methods = {
3903 .open = adev_open,
3904};
3905
3906struct audio_module HAL_MODULE_INFO_SYM = {
3907 .common = {
3908 .tag = HARDWARE_MODULE_TAG,
3909 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3910 .hal_api_version = HARDWARE_HAL_API_VERSION,
3911 .id = AUDIO_HARDWARE_MODULE_ID,
3912 .name = "QCOM Audio HAL",
3913 .author = "Code Aurora Forum",
3914 .methods = &hal_module_methods,
3915 },
3916};