blob: 85216bc4e07591c0b5547606ef48c6359f796963 [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
Eric Laurent0e46adf2016-12-16 12:49:24 -080086
87#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
88#define MMAP_PERIOD_COUNT 512
89
90
Andy Hung31aca912014-03-20 17:14:59 -070091/* This constant enables extended precision handling.
92 * TODO The flag is off until more testing is done.
93 */
94static const bool k_enable_extended_precision = false;
95
Eric Laurentb23d5282013-05-14 15:27:20 -070096struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -070097 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -070098 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
99 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
100 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
101 .format = PCM_FORMAT_S16_LE,
102 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
103 .stop_threshold = INT_MAX,
104 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
105};
106
107struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700108 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700109 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
110 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
111 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
112 .format = PCM_FORMAT_S16_LE,
113 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
114 .stop_threshold = INT_MAX,
115 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
116};
117
Haynes Mathew George03c40102016-01-29 17:57:48 -0800118static int af_period_multiplier = 4;
119struct pcm_config pcm_config_rt = {
120 .channels = DEFAULT_CHANNEL_COUNT,
121 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
122 .period_size = ULL_PERIOD_SIZE, //1 ms
123 .period_count = 512, //=> buffer size is 512ms
124 .format = PCM_FORMAT_S16_LE,
125 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
126 .stop_threshold = INT_MAX,
127 .silence_threshold = 0,
128 .silence_size = 0,
129 .avail_min = ULL_PERIOD_SIZE, //1 ms
130};
131
Eric Laurentb23d5282013-05-14 15:27:20 -0700132struct pcm_config pcm_config_hdmi_multi = {
133 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
134 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
135 .period_size = HDMI_MULTI_PERIOD_SIZE,
136 .period_count = HDMI_MULTI_PERIOD_COUNT,
137 .format = PCM_FORMAT_S16_LE,
138 .start_threshold = 0,
139 .stop_threshold = INT_MAX,
140 .avail_min = 0,
141};
142
Eric Laurent0e46adf2016-12-16 12:49:24 -0800143struct pcm_config pcm_config_mmap_playback = {
144 .channels = DEFAULT_CHANNEL_COUNT,
145 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
146 .period_size = MMAP_PERIOD_SIZE,
147 .period_count = MMAP_PERIOD_COUNT,
148 .format = PCM_FORMAT_S16_LE,
149 .start_threshold = MMAP_PERIOD_SIZE*8,
150 .stop_threshold = INT32_MAX,
151 .silence_threshold = 0,
152 .silence_size = 0,
153 .avail_min = MMAP_PERIOD_SIZE, //1 ms
154};
155
Eric Laurentb23d5282013-05-14 15:27:20 -0700156struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700157 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700158 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700160 .stop_threshold = INT_MAX,
161 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700162};
163
Haynes Mathew George03c40102016-01-29 17:57:48 -0800164struct pcm_config pcm_config_audio_capture_rt = {
165 .channels = DEFAULT_CHANNEL_COUNT,
166 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
167 .period_size = ULL_PERIOD_SIZE,
168 .period_count = 512,
169 .format = PCM_FORMAT_S16_LE,
170 .start_threshold = 0,
171 .stop_threshold = INT_MAX,
172 .silence_threshold = 0,
173 .silence_size = 0,
174 .avail_min = ULL_PERIOD_SIZE, //1 ms
175};
176
Eric Laurent0e46adf2016-12-16 12:49:24 -0800177struct pcm_config pcm_config_mmap_capture = {
178 .channels = DEFAULT_CHANNEL_COUNT,
179 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
180 .period_size = MMAP_PERIOD_SIZE,
181 .period_count = MMAP_PERIOD_COUNT,
182 .format = PCM_FORMAT_S16_LE,
183 .start_threshold = 0,
184 .stop_threshold = INT_MAX,
185 .silence_threshold = 0,
186 .silence_size = 0,
187 .avail_min = MMAP_PERIOD_SIZE, //1 ms
188};
189
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700190#define AFE_PROXY_CHANNEL_COUNT 2
191#define AFE_PROXY_SAMPLING_RATE 48000
192
193#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
194#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
195
196struct pcm_config pcm_config_afe_proxy_playback = {
197 .channels = AFE_PROXY_CHANNEL_COUNT,
198 .rate = AFE_PROXY_SAMPLING_RATE,
199 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
200 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
201 .format = PCM_FORMAT_S16_LE,
202 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
203 .stop_threshold = INT_MAX,
204 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
205};
206
207#define AFE_PROXY_RECORD_PERIOD_SIZE 768
208#define AFE_PROXY_RECORD_PERIOD_COUNT 4
209
210struct pcm_config pcm_config_afe_proxy_record = {
211 .channels = AFE_PROXY_CHANNEL_COUNT,
212 .rate = AFE_PROXY_SAMPLING_RATE,
213 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
214 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
215 .format = PCM_FORMAT_S16_LE,
216 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
217 .stop_threshold = INT_MAX,
218 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
219};
220
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700221const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700222 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
223 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
224 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700225 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700226 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700227 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800228 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700229
Eric Laurentb23d5282013-05-14 15:27:20 -0700230 [USECASE_AUDIO_RECORD] = "audio-record",
231 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800232 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700233
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800234 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
235 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700236
Eric Laurentb23d5282013-05-14 15:27:20 -0700237 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700238 [USECASE_VOICE2_CALL] = "voice2-call",
239 [USECASE_VOLTE_CALL] = "volte-call",
240 [USECASE_QCHAT_CALL] = "qchat-call",
241 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800242 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
243 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700244
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700245 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
246 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
247
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700248 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
249 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700250};
251
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800252
253#define STRING_TO_ENUM(string) { #string, string }
254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800255struct string_to_enum {
256 const char *name;
257 uint32_t value;
258};
259
260static const struct string_to_enum out_channels_name_to_enum_table[] = {
261 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
262 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
263 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
264};
265
Haynes Mathew George5191a852013-09-11 14:19:36 -0700266static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700267static struct audio_device *adev = NULL;
268static pthread_mutex_t adev_init_lock;
269static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700270//cache last MBDRC cal step level
271static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700272
Haynes Mathew George03c40102016-01-29 17:57:48 -0800273static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
274 int flags __unused)
275{
276 int dir = 0;
277 switch (uc_id) {
278 case USECASE_AUDIO_RECORD_LOW_LATENCY:
279 dir = 1;
280 case USECASE_AUDIO_PLAYBACK_ULL:
281 break;
282 default:
283 return false;
284 }
285
286 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
287 PCM_PLAYBACK : PCM_CAPTURE);
288 if (adev->adm_is_noirq_avail)
289 return adev->adm_is_noirq_avail(adev->adm_data,
290 adev->snd_card, dev_id, dir);
291 return false;
292}
293
294static void register_out_stream(struct stream_out *out)
295{
296 struct audio_device *adev = out->dev;
297 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
298 return;
299
300 if (!adev->adm_register_output_stream)
301 return;
302
303 adev->adm_register_output_stream(adev->adm_data,
304 out->handle,
305 out->flags);
306
307 if (!adev->adm_set_config)
308 return;
309
310 if (out->realtime) {
311 adev->adm_set_config(adev->adm_data,
312 out->handle,
313 out->pcm, &out->config);
314 }
315}
316
317static void register_in_stream(struct stream_in *in)
318{
319 struct audio_device *adev = in->dev;
320 if (!adev->adm_register_input_stream)
321 return;
322
323 adev->adm_register_input_stream(adev->adm_data,
324 in->capture_handle,
325 in->flags);
326
327 if (!adev->adm_set_config)
328 return;
329
330 if (in->realtime) {
331 adev->adm_set_config(adev->adm_data,
332 in->capture_handle,
333 in->pcm,
334 &in->config);
335 }
336}
337
338static void request_out_focus(struct stream_out *out, long ns)
339{
340 struct audio_device *adev = out->dev;
341
342 if (out->routing_change) {
343 out->routing_change = false;
344 if (adev->adm_on_routing_change)
345 adev->adm_on_routing_change(adev->adm_data, out->handle);
346 }
347
348 if (adev->adm_request_focus_v2) {
349 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
350 } else if (adev->adm_request_focus) {
351 adev->adm_request_focus(adev->adm_data, out->handle);
352 }
353}
354
355static void request_in_focus(struct stream_in *in, long ns)
356{
357 struct audio_device *adev = in->dev;
358
359 if (in->routing_change) {
360 in->routing_change = false;
361 if (adev->adm_on_routing_change)
362 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
363 }
364
365 if (adev->adm_request_focus_v2) {
366 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
367 } else if (adev->adm_request_focus) {
368 adev->adm_request_focus(adev->adm_data, in->capture_handle);
369 }
370}
371
372static void release_out_focus(struct stream_out *out, long ns __unused)
373{
374 struct audio_device *adev = out->dev;
375
376 if (adev->adm_abandon_focus)
377 adev->adm_abandon_focus(adev->adm_data, out->handle);
378}
379
380static void release_in_focus(struct stream_in *in, long ns __unused)
381{
382 struct audio_device *adev = in->dev;
383 if (adev->adm_abandon_focus)
384 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
385}
386
Andy Hung7401c7c2016-09-21 12:41:21 -0700387// Time string format similar to logcat, buffer_length must be >= 19 chars.
388static void ns2string(int64_t ns, char *buffer, int buffer_length)
389{
390 const int one_second = 1000000000;
391 const time_t sec = ns / one_second;
392 struct tm tm;
393 localtime_r(&sec, &tm);
394 snprintf(buffer, buffer_length, "%02d-%02d %02d:%02d:%02d.%03d",
395 tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range
396 tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
397 (int)(ns % one_second / 1000000));
398}
399
400// Convert timespec to nsec.
401static int64_t ts2ns(const struct timespec *ts)
402{
403 return ts->tv_sec * 1000000000LL + ts->tv_nsec;
404}
405
406// Log errors: consecutive errors with the same code will
407// be aggregated if they occur within one second.
408// A mutual exclusion lock must be held before calling.
409static void log_error_l(struct error_log *log, int code) {
410 ++log->errors;
411
412 struct timespec now_ts = { 0, 0 };
413 (void)clock_gettime(CLOCK_REALTIME, &now_ts);
414 const int64_t now = ts2ns(&now_ts);
415
416 // Within 1 second, cluster the same error codes together.
417 const int one_second = 1000000000;
418 if (code == log->entries[log->idx].code &&
419 now - log->entries[log->idx].last_time < one_second) {
420 log->entries[log->idx].count++;
421 log->entries[log->idx].last_time = now;
422 return;
423 }
424
425 // Add new error entry.
426 if (++log->idx >= ARRAY_SIZE(log->entries)) {
427 log->idx = 0;
428 }
429 log->entries[log->idx].count = 1;
430 log->entries[log->idx].code = code;
431 log->entries[log->idx].first_time = now;
432 log->entries[log->idx].last_time = now;
433}
434
435// Dump information in the error log. A mutual exclusion lock
436// should be held, but if that cannot be obtained, one should
437// make a copy of the error log before calling -- the call is
438// still safe, but there might be some misinterpreted data.
439static void log_dump_l(const struct error_log *log, int fd)
440{
441 dprintf(fd, " Errors: %u\n", log->errors);
442 if (log->errors == 0)
443 return;
444
445 dprintf(fd, " Index Code Freq First time Last time\n");
446 for (size_t i = 0; i < ARRAY_SIZE(log->entries); ++i) {
447 if (log->entries[i].count != 0) {
448 char first_time[32];
449 char last_time[32];
450 ns2string(log->entries[i].first_time, first_time, sizeof(first_time));
451 ns2string(log->entries[i].last_time, last_time, sizeof(last_time));
452 dprintf(fd, " %c%4zu %4d %5d %s %s\n",
453 i == log->idx ? '*' : ' ', // mark head position
454 i, log->entries[i].code, log->entries[i].count,
455 first_time, last_time);
456 }
457 }
458}
459
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700460static int parse_snd_card_status(struct str_parms * parms, int * card,
461 card_status_t * status)
462{
463 char value[32]={0};
464 char state[32]={0};
465
466 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
467
468 if (ret < 0)
469 return -1;
470
471 // sscanf should be okay as value is of max length 32.
472 // same as sizeof state.
473 if (sscanf(value, "%d,%s", card, state) < 2)
474 return -1;
475
476 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
477 CARD_STATUS_OFFLINE;
478 return 0;
479}
480
vivek mehta1a9b7c02015-06-25 11:49:38 -0700481__attribute__ ((visibility ("default")))
482bool audio_hw_send_gain_dep_calibration(int level) {
483 bool ret_val = false;
484 ALOGV("%s: enter ... ", __func__);
485
486 pthread_mutex_lock(&adev_init_lock);
487
488 if (adev != NULL && adev->platform != NULL) {
489 pthread_mutex_lock(&adev->lock);
490 ret_val = platform_send_gain_dep_cal(adev->platform, level);
491 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700492
493 // if cal set fails, cache level info
494 // if cal set succeds, reset known last cal set
495 if (!ret_val)
496 last_known_cal_step = level;
497 else if (last_known_cal_step != -1)
498 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700499 } else {
500 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
501 }
502
503 pthread_mutex_unlock(&adev_init_lock);
504
505 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
506 return ret_val;
507}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700508
vivek mehtaa8d7c922016-05-25 14:40:44 -0700509__attribute__ ((visibility ("default")))
510int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
511 int table_size) {
512 int ret_val = 0;
513 ALOGV("%s: enter ... ", __func__);
514
515 pthread_mutex_lock(&adev_init_lock);
516 if (adev == NULL) {
517 ALOGW("%s: adev is NULL .... ", __func__);
518 goto done;
519 }
520
521 pthread_mutex_lock(&adev->lock);
522 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
523 pthread_mutex_unlock(&adev->lock);
524done:
525 pthread_mutex_unlock(&adev_init_lock);
526 ALOGV("%s: exit ... ", __func__);
527 return ret_val;
528}
529
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700530static bool is_supported_format(audio_format_t format)
531{
Eric Laurent8251ac82014-07-23 11:00:25 -0700532 switch (format) {
533 case AUDIO_FORMAT_MP3:
534 case AUDIO_FORMAT_AAC_LC:
535 case AUDIO_FORMAT_AAC_HE_V1:
536 case AUDIO_FORMAT_AAC_HE_V2:
537 return true;
538 default:
539 break;
540 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700541 return false;
542}
543
Haynes Mathew George03c40102016-01-29 17:57:48 -0800544static inline bool is_mmap_usecase(audio_usecase_t uc_id)
545{
546 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
547 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
548}
549
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700550static int get_snd_codec_id(audio_format_t format)
551{
552 int id = 0;
553
Eric Laurent8251ac82014-07-23 11:00:25 -0700554 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700555 case AUDIO_FORMAT_MP3:
556 id = SND_AUDIOCODEC_MP3;
557 break;
558 case AUDIO_FORMAT_AAC:
559 id = SND_AUDIOCODEC_AAC;
560 break;
561 default:
562 ALOGE("%s: Unsupported audio format", __func__);
563 }
564
565 return id;
566}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800567
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800568static int audio_ssr_status(struct audio_device *adev)
569{
570 int ret = 0;
571 struct mixer_ctl *ctl;
572 const char *mixer_ctl_name = "Audio SSR Status";
573
574 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
575 ret = mixer_ctl_get_value(ctl, 0);
576 ALOGD("%s: value: %d", __func__, ret);
577 return ret;
578}
579
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800580int enable_audio_route(struct audio_device *adev,
581 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800582{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700583 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800584 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800585
586 if (usecase == NULL)
587 return -EINVAL;
588
589 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
590
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800591 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700592 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800593 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700594 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800595
Yamit Mehtae3b99562016-09-16 22:44:00 +0530596 audio_extn_utils_send_app_type_cfg(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800597 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500598 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700599 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700600 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800602 ALOGV("%s: exit", __func__);
603 return 0;
604}
605
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800606int disable_audio_route(struct audio_device *adev,
607 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800608{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700609 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800610 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800611
612 if (usecase == NULL)
613 return -EINVAL;
614
615 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616 if (usecase->type == PCM_CAPTURE)
617 snd_device = usecase->in_snd_device;
618 else
619 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800620 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500621 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700622 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700623 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800624
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800625 ALOGV("%s: exit", __func__);
626 return 0;
627}
628
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800629int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700630 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800631{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700632 int i, num_devices = 0;
633 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800634 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800635 if (snd_device < SND_DEVICE_MIN ||
636 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800637 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800638 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800639 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700640
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700641 platform_send_audio_calibration(adev->platform, snd_device);
642
vivek mehtade4849c2016-03-03 17:23:38 -0800643 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700644 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700645 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800646 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700647 }
648
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700649 /* due to the possibility of calibration overwrite between listen
650 and audio, notify sound trigger hal before audio calibration is sent */
651 audio_extn_sound_trigger_update_device_status(snd_device,
652 ST_EVENT_SND_DEVICE_BUSY);
653
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700654 if (audio_extn_spkr_prot_is_enabled())
655 audio_extn_spkr_prot_calib_cancel(adev);
656
zhaoyang yin4211fad2015-06-04 21:13:25 +0800657 audio_extn_dsm_feedback_enable(adev, snd_device, true);
658
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700659 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
660 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
661 audio_extn_spkr_prot_is_enabled()) {
662 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800663 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700664 }
665 if (audio_extn_spkr_prot_start_processing(snd_device)) {
666 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800667 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700668 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700669 } else if (platform_can_split_snd_device(snd_device,
670 &num_devices,
671 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700672 for (i = 0; i < num_devices; i++) {
673 enable_snd_device(adev, new_snd_devices[i]);
674 }
vivek mehtab6506412015-08-07 16:55:17 -0700675 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700676 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800677 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
678 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
679 ALOGE(" %s: Invalid sound device returned", __func__);
680 goto on_error;
681 }
Ed Tam70b5c142016-03-21 19:14:29 -0700682
Eric Laurent2e140aa2016-06-30 17:14:46 -0700683 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800684 audio_route_apply_and_update_path(adev->audio_route, device_name);
685 }
686on_success:
687 adev->snd_dev_ref_cnt[snd_device]++;
688 ret_val = 0;
689on_error:
690 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800691}
692
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800693int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700694 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800695{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700696 int i, num_devices = 0;
697 snd_device_t new_snd_devices[2];
698
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800699 if (snd_device < SND_DEVICE_MIN ||
700 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800701 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800702 return -EINVAL;
703 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700704 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
705 ALOGE("%s: device ref cnt is already 0", __func__);
706 return -EINVAL;
707 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800708 audio_extn_tfa_98xx_disable_speaker(snd_device);
709
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700710 adev->snd_dev_ref_cnt[snd_device]--;
711 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800712 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700713 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
714 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
715 audio_extn_spkr_prot_is_enabled()) {
716 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700717 } else if (platform_can_split_snd_device(snd_device,
718 &num_devices,
719 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700720 for (i = 0; i < num_devices; i++) {
721 disable_snd_device(adev, new_snd_devices[i]);
722 }
vivek mehtab6506412015-08-07 16:55:17 -0700723 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700724 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800725 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
726 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
727 ALOGE(" %s: Invalid sound device returned", __func__);
728 return -EINVAL;
729 }
730
Eric Laurent2e140aa2016-06-30 17:14:46 -0700731 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800732 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700733 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700734 audio_extn_sound_trigger_update_device_status(snd_device,
735 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700736 }
vivek mehtab6506412015-08-07 16:55:17 -0700737
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800738 return 0;
739}
740
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700741/*
742 legend:
743 uc - existing usecase
744 new_uc - new usecase
745 d1, d11, d2 - SND_DEVICE enums
746 a1, a2 - corresponding ANDROID device enums
747 B, B1, B2 - backend strings
748
749case 1
750 uc->dev d1 (a1) B1
751 new_uc->dev d1 (a1), d2 (a2) B1, B2
752
753 resolution: disable and enable uc->dev on d1
754
755case 2
756 uc->dev d1 (a1) B1
757 new_uc->dev d11 (a1) B1
758
759 resolution: need to switch uc since d1 and d11 are related
760 (e.g. speaker and voice-speaker)
761 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
762
763case 3
764 uc->dev d1 (a1) B1
765 new_uc->dev d2 (a2) B2
766
767 resolution: no need to switch uc
768
769case 4
770 uc->dev d1 (a1) B
771 new_uc->dev d2 (a2) B
772
773 resolution: disable enable uc-dev on d2 since backends match
774 we cannot enable two streams on two different devices if they
775 share the same backend. e.g. if offload is on speaker device using
776 QUAD_MI2S backend and a low-latency stream is started on voice-handset
777 using the same backend, offload must also be switched to voice-handset.
778
779case 5
780 uc->dev d1 (a1) B
781 new_uc->dev d1 (a1), d2 (a2) B
782
783 resolution: disable enable uc-dev on d2 since backends match
784 we cannot enable two streams on two different devices if they
785 share the same backend.
786
787case 6
788 uc->dev d1 a1 B1
789 new_uc->dev d2 a1 B2
790
791 resolution: no need to switch
792
793case 7
794
795 uc->dev d1 (a1), d2 (a2) B1, B2
796 new_uc->dev d1 B1
797
798 resolution: no need to switch
799
800*/
801static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
802 struct audio_usecase *new_uc,
803 snd_device_t new_snd_device)
804{
805 audio_devices_t a1 = uc->stream.out->devices;
806 audio_devices_t a2 = new_uc->stream.out->devices;
807
808 snd_device_t d1 = uc->out_snd_device;
809 snd_device_t d2 = new_snd_device;
810
811 // Treat as a special case when a1 and a2 are not disjoint
812 if ((a1 != a2) && (a1 & a2)) {
813 snd_device_t d3[2];
814 int num_devices = 0;
815 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
816 &num_devices,
817 d3);
818 if (ret < 0) {
819 if (ret != -ENOSYS) {
820 ALOGW("%s failed to split snd_device %d",
821 __func__,
822 popcount(a1) > 1 ? d1 : d2);
823 }
824 goto end;
825 }
826
827 // NB: case 7 is hypothetical and isn't a practical usecase yet.
828 // But if it does happen, we need to give priority to d2 if
829 // the combo devices active on the existing usecase share a backend.
830 // This is because we cannot have a usecase active on a combo device
831 // and a new usecase requests one device in this combo pair.
832 if (platform_check_backends_match(d3[0], d3[1])) {
833 return d2; // case 5
834 } else {
835 return d1; // case 1
836 }
837 } else {
838 if (platform_check_backends_match(d1, d2)) {
839 return d2; // case 2, 4
840 } else {
841 return d1; // case 6, 3
842 }
843 }
844
845end:
846 return d2; // return whatever was calculated before.
847}
848
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700849static void check_and_route_playback_usecases(struct audio_device *adev,
850 struct audio_usecase *uc_info,
851 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700852{
853 struct listnode *node;
854 struct audio_usecase *usecase;
855 bool switch_device[AUDIO_USECASE_MAX];
856 int i, num_uc_to_switch = 0;
857
858 /*
859 * This function is to make sure that all the usecases that are active on
860 * the hardware codec backend are always routed to any one device that is
861 * handled by the hardware codec.
862 * For example, if low-latency and deep-buffer usecases are currently active
863 * on speaker and out_set_parameters(headset) is received on low-latency
864 * output, then we have to make sure deep-buffer is also switched to headset,
865 * because of the limitation that both the devices cannot be enabled
866 * at the same time as they share the same backend.
867 */
868 /* Disable all the usecases on the shared backend other than the
869 specified usecase */
870 for (i = 0; i < AUDIO_USECASE_MAX; i++)
871 switch_device[i] = false;
872
873 list_for_each(node, &adev->usecase_list) {
874 usecase = node_to_item(node, struct audio_usecase, list);
875 if (usecase->type != PCM_CAPTURE &&
876 usecase != uc_info &&
877 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700878 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
879 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700880 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
881 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700882 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700883 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700884 switch_device[usecase->id] = true;
885 num_uc_to_switch++;
886 }
887 }
888
889 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700890 list_for_each(node, &adev->usecase_list) {
891 usecase = node_to_item(node, struct audio_usecase, list);
892 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700893 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900894 }
895 }
896
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700897 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900898 list_for_each(node, &adev->usecase_list) {
899 usecase = node_to_item(node, struct audio_usecase, list);
900 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700901 d_device = derive_playback_snd_device(usecase, uc_info,
902 snd_device);
903 enable_snd_device(adev, d_device);
904 /* Update the out_snd_device before enabling the audio route */
905 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700906 }
907 }
908
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700909 /* Re-route all the usecases on the shared backend other than the
910 specified usecase to new snd devices */
911 list_for_each(node, &adev->usecase_list) {
912 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700913 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700914 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700915 }
916 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700917 }
918}
919
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700920static void check_and_route_capture_usecases(struct audio_device *adev,
921 struct audio_usecase *uc_info,
922 snd_device_t snd_device)
923{
924 struct listnode *node;
925 struct audio_usecase *usecase;
926 bool switch_device[AUDIO_USECASE_MAX];
927 int i, num_uc_to_switch = 0;
928
vivek mehta4ed66e62016-04-15 23:33:34 -0700929 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
930
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700931 /*
932 * This function is to make sure that all the active capture usecases
933 * are always routed to the same input sound device.
934 * For example, if audio-record and voice-call usecases are currently
935 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
936 * is received for voice call then we have to make sure that audio-record
937 * usecase is also switched to earpiece i.e. voice-dmic-ef,
938 * because of the limitation that two devices cannot be enabled
939 * at the same time if they share the same backend.
940 */
941 for (i = 0; i < AUDIO_USECASE_MAX; i++)
942 switch_device[i] = false;
943
944 list_for_each(node, &adev->usecase_list) {
945 usecase = node_to_item(node, struct audio_usecase, list);
946 if (usecase->type != PCM_PLAYBACK &&
947 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700948 usecase->in_snd_device != snd_device &&
949 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700950 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
951 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700952 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700953 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700954 switch_device[usecase->id] = true;
955 num_uc_to_switch++;
956 }
957 }
958
959 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700960 list_for_each(node, &adev->usecase_list) {
961 usecase = node_to_item(node, struct audio_usecase, list);
962 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700963 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700964 }
965 }
966
967 list_for_each(node, &adev->usecase_list) {
968 usecase = node_to_item(node, struct audio_usecase, list);
969 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700970 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700971 }
972 }
973
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700974 /* Re-route all the usecases on the shared backend other than the
975 specified usecase to new snd devices */
976 list_for_each(node, &adev->usecase_list) {
977 usecase = node_to_item(node, struct audio_usecase, list);
978 /* Update the in_snd_device only before enabling the audio route */
979 if (switch_device[usecase->id] ) {
980 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700981 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700982 }
983 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700984 }
985}
986
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800987/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700988static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800989{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700990 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700991 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800992
993 switch (channels) {
994 /*
995 * Do not handle stereo output in Multi-channel cases
996 * Stereo case is handled in normal playback path
997 */
998 case 6:
999 ALOGV("%s: HDMI supports 5.1", __func__);
1000 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1001 break;
1002 case 8:
1003 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1004 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1005 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1006 break;
1007 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001008 ALOGE("HDMI does not support multi channel playback");
1009 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001010 break;
1011 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001012 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001013}
1014
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001015static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1016{
1017 struct audio_usecase *usecase;
1018 struct listnode *node;
1019
1020 list_for_each(node, &adev->usecase_list) {
1021 usecase = node_to_item(node, struct audio_usecase, list);
1022 if (usecase->type == VOICE_CALL) {
1023 ALOGV("%s: usecase id %d", __func__, usecase->id);
1024 return usecase->id;
1025 }
1026 }
1027 return USECASE_INVALID;
1028}
1029
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001030struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1031 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001032{
1033 struct audio_usecase *usecase;
1034 struct listnode *node;
1035
1036 list_for_each(node, &adev->usecase_list) {
1037 usecase = node_to_item(node, struct audio_usecase, list);
1038 if (usecase->id == uc_id)
1039 return usecase;
1040 }
1041 return NULL;
1042}
1043
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001044int select_devices(struct audio_device *adev,
1045 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001047 snd_device_t out_snd_device = SND_DEVICE_NONE;
1048 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049 struct audio_usecase *usecase = NULL;
1050 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001051 struct audio_usecase *hfp_usecase = NULL;
1052 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001053 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001054 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001055
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001056 usecase = get_usecase_from_list(adev, uc_id);
1057 if (usecase == NULL) {
1058 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1059 return -EINVAL;
1060 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001062 if ((usecase->type == VOICE_CALL) ||
1063 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001064 out_snd_device = platform_get_output_snd_device(adev->platform,
1065 usecase->stream.out->devices);
1066 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001067 usecase->devices = usecase->stream.out->devices;
1068 } else {
1069 /*
1070 * If the voice call is active, use the sound devices of voice call usecase
1071 * so that it would not result any device switch. All the usecases will
1072 * be switched to new device when select_devices() is called for voice call
1073 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001074 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001075 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001076 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001077 vc_usecase = get_usecase_from_list(adev,
1078 get_voice_usecase_id_from_list(adev));
1079 if ((vc_usecase != NULL) &&
1080 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1081 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001082 in_snd_device = vc_usecase->in_snd_device;
1083 out_snd_device = vc_usecase->out_snd_device;
1084 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001085 } else if (audio_extn_hfp_is_active(adev)) {
1086 hfp_ucid = audio_extn_hfp_get_usecase();
1087 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1088 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1089 in_snd_device = hfp_usecase->in_snd_device;
1090 out_snd_device = hfp_usecase->out_snd_device;
1091 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001092 }
1093 if (usecase->type == PCM_PLAYBACK) {
1094 usecase->devices = usecase->stream.out->devices;
1095 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001096 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001097 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001098 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001099 if (usecase->stream.out == adev->primary_output &&
1100 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001101 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1102 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001103 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001104 select_devices(adev, adev->active_input->usecase);
1105 }
1106 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001107 } else if (usecase->type == PCM_CAPTURE) {
1108 usecase->devices = usecase->stream.in->device;
1109 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001110 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001111 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001112 if (adev->active_input &&
1113 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1114 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001115 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001116 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1117 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1118 } else if (adev->primary_output) {
1119 out_device = adev->primary_output->devices;
1120 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001121 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001122 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001123 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001124 }
1125 }
1126
1127 if (out_snd_device == usecase->out_snd_device &&
1128 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001129 return 0;
1130 }
1131
Eric Laurent2bafff12016-03-17 12:17:23 -07001132 if (out_snd_device != SND_DEVICE_NONE &&
1133 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1134 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1135 __func__,
1136 use_case_table[uc_id],
1137 adev->last_logged_snd_device[uc_id][0],
1138 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1139 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1140 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1141 -1,
1142 out_snd_device,
1143 platform_get_snd_device_name(out_snd_device),
1144 platform_get_snd_device_acdb_id(out_snd_device));
1145 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1146 }
1147 if (in_snd_device != SND_DEVICE_NONE &&
1148 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1149 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1150 __func__,
1151 use_case_table[uc_id],
1152 adev->last_logged_snd_device[uc_id][1],
1153 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1154 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1155 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1156 -1,
1157 in_snd_device,
1158 platform_get_snd_device_name(in_snd_device),
1159 platform_get_snd_device_acdb_id(in_snd_device));
1160 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1161 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001163 /*
1164 * Limitation: While in call, to do a device switch we need to disable
1165 * and enable both RX and TX devices though one of them is same as current
1166 * device.
1167 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001168 if ((usecase->type == VOICE_CALL) &&
1169 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1170 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001171 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001172 /* Disable sidetone only if voice call already exists */
1173 if (voice_is_call_state_active(adev))
1174 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001175 }
1176
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001177 /* Disable current sound devices */
1178 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001179 disable_audio_route(adev, usecase);
1180 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001181 }
1182
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001183 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001184 disable_audio_route(adev, usecase);
1185 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001186 }
1187
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001188 /* Applicable only on the targets that has external modem.
1189 * New device information should be sent to modem before enabling
1190 * the devices to reduce in-call device switch time.
1191 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001192 if ((usecase->type == VOICE_CALL) &&
1193 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1194 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001195 status = platform_switch_voice_call_enable_device_config(adev->platform,
1196 out_snd_device,
1197 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001198 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001199
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001200 /* Enable new sound devices */
1201 if (out_snd_device != SND_DEVICE_NONE) {
1202 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001203 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001204 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001205 }
1206
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001207 if (in_snd_device != SND_DEVICE_NONE) {
1208 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001209 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001210 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001211
Eric Laurentb23d5282013-05-14 15:27:20 -07001212 if (usecase->type == VOICE_CALL)
1213 status = platform_switch_voice_call_device_post(adev->platform,
1214 out_snd_device,
1215 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001216
sangwoo170731f2013-06-08 15:36:36 +09001217 usecase->in_snd_device = in_snd_device;
1218 usecase->out_snd_device = out_snd_device;
1219
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001220 audio_extn_tfa_98xx_set_mode();
1221
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001222 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001223
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001224 /* Applicable only on the targets that has external modem.
1225 * Enable device command should be sent to modem only after
1226 * enabling voice call mixer controls
1227 */
vivek mehta765eb642015-08-07 19:46:06 -07001228 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001229 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1230 out_snd_device,
1231 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001232 /* Enable sidetone only if voice call already exists */
1233 if (voice_is_call_state_active(adev))
1234 voice_set_sidetone(adev, out_snd_device, true);
1235 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001236
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001237 return status;
1238}
1239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001240static int stop_input_stream(struct stream_in *in)
1241{
1242 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001243 struct audio_usecase *uc_info;
1244 struct audio_device *adev = in->dev;
1245
Eric Laurentc8400632013-02-14 19:04:54 -08001246 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001247
Eric Laurent994a6932013-07-17 11:51:42 -07001248 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001249 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001250 uc_info = get_usecase_from_list(adev, in->usecase);
1251 if (uc_info == NULL) {
1252 ALOGE("%s: Could not find the usecase (%d) in the list",
1253 __func__, in->usecase);
1254 return -EINVAL;
1255 }
1256
Eric Laurent150dbfe2013-02-27 14:31:02 -08001257 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001258 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001259
1260 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001261 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001262
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001263 list_remove(&uc_info->list);
1264 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001265
Eric Laurent994a6932013-07-17 11:51:42 -07001266 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001267 return ret;
1268}
1269
1270int start_input_stream(struct stream_in *in)
1271{
1272 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001273 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001274 struct audio_usecase *uc_info;
1275 struct audio_device *adev = in->dev;
1276
Eric Laurent994a6932013-07-17 11:51:42 -07001277 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001278
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001279 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1280 return -EIO;
1281
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001282 if (in->card_status == CARD_STATUS_OFFLINE ||
1283 adev->card_status == CARD_STATUS_OFFLINE) {
1284 ALOGW("in->card_status or adev->card_status offline, try again");
1285 ret = -EAGAIN;
1286 goto error_config;
1287 }
1288
Eric Laurentb23d5282013-05-14 15:27:20 -07001289 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001290 if (in->pcm_device_id < 0) {
1291 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1292 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001293 ret = -EINVAL;
1294 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001295 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001296
1297 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001298 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1299 uc_info->id = in->usecase;
1300 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001301 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001302 uc_info->devices = in->device;
1303 uc_info->in_snd_device = SND_DEVICE_NONE;
1304 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001305
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001306 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001307
1308 audio_extn_perf_lock_acquire();
1309
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001310 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001311
Eric Laurent0e46adf2016-12-16 12:49:24 -08001312 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
1313 if (!pcm_is_ready(in->pcm)) {
1314 ALOGE("%s: pcm stream not ready", __func__);
1315 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001316 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001317 ret = pcm_prepare(in->pcm);
1318 if (ret < 0) {
1319 ALOGE("%s: MMAP pcm_prepare failed ret %d", __func__, ret);
1320 goto error_open; }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001321 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001322 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001323 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1324 goto error_open;
1325 }
1326 } else {
1327 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1328 unsigned int pcm_open_retry_count = 0;
1329
1330 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1331 flags |= PCM_MMAP | PCM_NOIRQ;
1332 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1333 } else if (in->realtime) {
1334 flags |= PCM_MMAP | PCM_NOIRQ;
1335 }
1336
1337 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1338 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1339
1340 while (1) {
1341 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1342 flags, &in->config);
1343 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1344 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1345 if (in->pcm != NULL) {
1346 pcm_close(in->pcm);
1347 in->pcm = NULL;
1348 }
1349 if (pcm_open_retry_count-- == 0) {
1350 ret = -EIO;
1351 goto error_open;
1352 }
1353 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1354 continue;
1355 }
1356 break;
1357 }
1358
1359 ALOGV("%s: pcm_prepare", __func__);
1360 ret = pcm_prepare(in->pcm);
1361 if (ret < 0) {
1362 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001363 pcm_close(in->pcm);
1364 in->pcm = NULL;
1365 goto error_open;
1366 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001367 if (in->realtime) {
1368 ret = pcm_start(in->pcm);
1369 if (ret < 0) {
1370 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1371 pcm_close(in->pcm);
1372 in->pcm = NULL;
1373 goto error_open;
1374 }
1375 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001376 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001377 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001378 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001379 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001380
Eric Laurent0e46adf2016-12-16 12:49:24 -08001381 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001382
1383error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001384 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001385 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001386
1387error_config:
1388 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001389 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001390
1391 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001392}
1393
Eric Laurenta1478072015-09-21 17:21:52 -07001394void lock_input_stream(struct stream_in *in)
1395{
1396 pthread_mutex_lock(&in->pre_lock);
1397 pthread_mutex_lock(&in->lock);
1398 pthread_mutex_unlock(&in->pre_lock);
1399}
1400
1401void lock_output_stream(struct stream_out *out)
1402{
1403 pthread_mutex_lock(&out->pre_lock);
1404 pthread_mutex_lock(&out->lock);
1405 pthread_mutex_unlock(&out->pre_lock);
1406}
1407
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001408/* must be called with out->lock locked */
1409static int send_offload_cmd_l(struct stream_out* out, int command)
1410{
1411 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1412
1413 ALOGVV("%s %d", __func__, command);
1414
1415 cmd->cmd = command;
1416 list_add_tail(&out->offload_cmd_list, &cmd->node);
1417 pthread_cond_signal(&out->offload_cond);
1418 return 0;
1419}
1420
1421/* must be called iwth out->lock locked */
1422static void stop_compressed_output_l(struct stream_out *out)
1423{
1424 out->offload_state = OFFLOAD_STATE_IDLE;
1425 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001426 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001427 if (out->compr != NULL) {
1428 compress_stop(out->compr);
1429 while (out->offload_thread_blocked) {
1430 pthread_cond_wait(&out->cond, &out->lock);
1431 }
1432 }
1433}
1434
1435static void *offload_thread_loop(void *context)
1436{
1437 struct stream_out *out = (struct stream_out *) context;
1438 struct listnode *item;
1439
1440 out->offload_state = OFFLOAD_STATE_IDLE;
1441 out->playback_started = 0;
1442
1443 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1444 set_sched_policy(0, SP_FOREGROUND);
1445 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1446
1447 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001448 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001449 for (;;) {
1450 struct offload_cmd *cmd = NULL;
1451 stream_callback_event_t event;
1452 bool send_callback = false;
1453
1454 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1455 __func__, list_empty(&out->offload_cmd_list),
1456 out->offload_state);
1457 if (list_empty(&out->offload_cmd_list)) {
1458 ALOGV("%s SLEEPING", __func__);
1459 pthread_cond_wait(&out->offload_cond, &out->lock);
1460 ALOGV("%s RUNNING", __func__);
1461 continue;
1462 }
1463
1464 item = list_head(&out->offload_cmd_list);
1465 cmd = node_to_item(item, struct offload_cmd, node);
1466 list_remove(item);
1467
1468 ALOGVV("%s STATE %d CMD %d out->compr %p",
1469 __func__, out->offload_state, cmd->cmd, out->compr);
1470
1471 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1472 free(cmd);
1473 break;
1474 }
1475
1476 if (out->compr == NULL) {
1477 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001478 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001479 pthread_cond_signal(&out->cond);
1480 continue;
1481 }
1482 out->offload_thread_blocked = true;
1483 pthread_mutex_unlock(&out->lock);
1484 send_callback = false;
1485 switch(cmd->cmd) {
1486 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1487 compress_wait(out->compr, -1);
1488 send_callback = true;
1489 event = STREAM_CBK_EVENT_WRITE_READY;
1490 break;
1491 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001492 compress_next_track(out->compr);
1493 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001494 send_callback = true;
1495 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001496 /* Resend the metadata for next iteration */
1497 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001498 break;
1499 case OFFLOAD_CMD_DRAIN:
1500 compress_drain(out->compr);
1501 send_callback = true;
1502 event = STREAM_CBK_EVENT_DRAIN_READY;
1503 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001504 case OFFLOAD_CMD_ERROR:
1505 send_callback = true;
1506 event = STREAM_CBK_EVENT_ERROR;
1507 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001508 default:
1509 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1510 break;
1511 }
Eric Laurenta1478072015-09-21 17:21:52 -07001512 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001513 out->offload_thread_blocked = false;
1514 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001515 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001516 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001517 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001518 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001519 free(cmd);
1520 }
1521
1522 pthread_cond_signal(&out->cond);
1523 while (!list_empty(&out->offload_cmd_list)) {
1524 item = list_head(&out->offload_cmd_list);
1525 list_remove(item);
1526 free(node_to_item(item, struct offload_cmd, node));
1527 }
1528 pthread_mutex_unlock(&out->lock);
1529
1530 return NULL;
1531}
1532
1533static int create_offload_callback_thread(struct stream_out *out)
1534{
1535 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1536 list_init(&out->offload_cmd_list);
1537 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1538 offload_thread_loop, out);
1539 return 0;
1540}
1541
1542static int destroy_offload_callback_thread(struct stream_out *out)
1543{
Eric Laurenta1478072015-09-21 17:21:52 -07001544 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001545 stop_compressed_output_l(out);
1546 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1547
1548 pthread_mutex_unlock(&out->lock);
1549 pthread_join(out->offload_thread, (void **) NULL);
1550 pthread_cond_destroy(&out->offload_cond);
1551
1552 return 0;
1553}
1554
Eric Laurent07eeafd2013-10-06 12:52:49 -07001555static bool allow_hdmi_channel_config(struct audio_device *adev)
1556{
1557 struct listnode *node;
1558 struct audio_usecase *usecase;
1559 bool ret = true;
1560
1561 list_for_each(node, &adev->usecase_list) {
1562 usecase = node_to_item(node, struct audio_usecase, list);
1563 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1564 /*
1565 * If voice call is already existing, do not proceed further to avoid
1566 * disabling/enabling both RX and TX devices, CSD calls, etc.
1567 * Once the voice call done, the HDMI channels can be configured to
1568 * max channels of remaining use cases.
1569 */
1570 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001571 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001572 __func__);
1573 ret = false;
1574 break;
1575 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001576 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001577 "no change in HDMI channels", __func__);
1578 ret = false;
1579 break;
1580 }
1581 }
1582 }
1583 return ret;
1584}
1585
1586static int check_and_set_hdmi_channels(struct audio_device *adev,
1587 unsigned int channels)
1588{
1589 struct listnode *node;
1590 struct audio_usecase *usecase;
1591
1592 /* Check if change in HDMI channel config is allowed */
1593 if (!allow_hdmi_channel_config(adev))
1594 return 0;
1595
1596 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001597 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001598 return 0;
1599 }
1600
1601 platform_set_hdmi_channels(adev->platform, channels);
1602 adev->cur_hdmi_channels = channels;
1603
1604 /*
1605 * Deroute all the playback streams routed to HDMI so that
1606 * the back end is deactivated. Note that backend will not
1607 * be deactivated if any one stream is connected to it.
1608 */
1609 list_for_each(node, &adev->usecase_list) {
1610 usecase = node_to_item(node, struct audio_usecase, list);
1611 if (usecase->type == PCM_PLAYBACK &&
1612 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001613 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001614 }
1615 }
1616
1617 /*
1618 * Enable all the streams disabled above. Now the HDMI backend
1619 * will be activated with new channel configuration
1620 */
1621 list_for_each(node, &adev->usecase_list) {
1622 usecase = node_to_item(node, struct audio_usecase, list);
1623 if (usecase->type == PCM_PLAYBACK &&
1624 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001625 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001626 }
1627 }
1628
1629 return 0;
1630}
1631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632static int stop_output_stream(struct stream_out *out)
1633{
1634 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001635 struct audio_usecase *uc_info;
1636 struct audio_device *adev = out->dev;
1637
Eric Laurent994a6932013-07-17 11:51:42 -07001638 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001639 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001640 uc_info = get_usecase_from_list(adev, out->usecase);
1641 if (uc_info == NULL) {
1642 ALOGE("%s: Could not find the usecase (%d) in the list",
1643 __func__, out->usecase);
1644 return -EINVAL;
1645 }
1646
Haynes Mathew George41f86652014-06-17 14:22:15 -07001647 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1648 if (adev->visualizer_stop_output != NULL)
1649 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1650 if (adev->offload_effects_stop_output != NULL)
1651 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1652 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001653
Eric Laurent150dbfe2013-02-27 14:31:02 -08001654 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001655 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001656
1657 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001658 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001659
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001660 list_remove(&uc_info->list);
1661 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662
Eric Laurent0499d4f2014-08-25 22:39:29 -05001663 audio_extn_extspk_update(adev->extspk);
1664
Eric Laurent07eeafd2013-10-06 12:52:49 -07001665 /* Must be called after removing the usecase from list */
1666 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1667 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1668
Eric Laurent994a6932013-07-17 11:51:42 -07001669 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001670 return ret;
1671}
1672
1673int start_output_stream(struct stream_out *out)
1674{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001675 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001676 struct audio_usecase *uc_info;
1677 struct audio_device *adev = out->dev;
1678
Eric Laurent994a6932013-07-17 11:51:42 -07001679 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001680 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001681
1682 if (out->card_status == CARD_STATUS_OFFLINE ||
1683 adev->card_status == CARD_STATUS_OFFLINE) {
1684 ALOGW("out->card_status or adev->card_status offline, try again");
1685 ret = -EAGAIN;
1686 goto error_config;
1687 }
1688
Eric Laurentb23d5282013-05-14 15:27:20 -07001689 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001690 if (out->pcm_device_id < 0) {
1691 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1692 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001693 ret = -EINVAL;
1694 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001695 }
1696
1697 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1698 uc_info->id = out->usecase;
1699 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001700 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001701 uc_info->devices = out->devices;
1702 uc_info->in_snd_device = SND_DEVICE_NONE;
1703 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001704
Eric Laurent07eeafd2013-10-06 12:52:49 -07001705 /* This must be called before adding this usecase to the list */
1706 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1707 check_and_set_hdmi_channels(adev, out->config.channels);
1708
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001709 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001710
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001711 audio_extn_perf_lock_acquire();
1712
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001713 select_devices(adev, out->usecase);
1714
Eric Laurent0499d4f2014-08-25 22:39:29 -05001715 audio_extn_extspk_update(adev->extspk);
1716
Andy Hung31aca912014-03-20 17:14:59 -07001717 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001718 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001719 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1720 out->pcm = NULL;
1721 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1722 COMPRESS_IN, &out->compr_config);
1723 if (out->compr && !is_compress_ready(out->compr)) {
1724 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1725 compress_close(out->compr);
1726 out->compr = NULL;
1727 ret = -EIO;
1728 goto error_open;
1729 }
1730 if (out->offload_callback)
1731 compress_nonblock(out->compr, out->non_blocking);
1732
1733 if (adev->visualizer_start_output != NULL)
1734 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1735 if (adev->offload_effects_start_output != NULL)
1736 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1737 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1738 if (!pcm_is_ready(out->pcm)) {
1739 ALOGE("%s: pcm stream not ready", __func__);
1740 goto error_open;
1741 }
1742 ret = pcm_prepare(out->pcm);
1743 if (ret < 0) {
1744 ALOGE("%s: MMAP pcm_prepare failed ret %d", __func__, ret);
1745 goto error_open; }
1746 ret = pcm_start(out->pcm);
1747 if (ret < 0) {
1748 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1749 goto error_open;
1750 }
1751 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001752 unsigned int flags = PCM_OUT;
1753 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001754
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001755 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1756 flags |= PCM_MMAP | PCM_NOIRQ;
1757 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001758 } else if (out->realtime) {
1759 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001760 } else
1761 flags |= PCM_MONOTONIC;
1762
1763 while (1) {
1764 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1765 flags, &out->config);
1766 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1767 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1768 if (out->pcm != NULL) {
1769 pcm_close(out->pcm);
1770 out->pcm = NULL;
1771 }
1772 if (pcm_open_retry_count-- == 0) {
1773 ret = -EIO;
1774 goto error_open;
1775 }
1776 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1777 continue;
1778 }
1779 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001780 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001781 ALOGV("%s: pcm_prepare", __func__);
1782 if (pcm_is_ready(out->pcm)) {
1783 ret = pcm_prepare(out->pcm);
1784 if (ret < 0) {
1785 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1786 pcm_close(out->pcm);
1787 out->pcm = NULL;
1788 goto error_open;
1789 }
1790 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001791 if (out->realtime) {
1792 ret = pcm_start(out->pcm);
1793 if (ret < 0) {
1794 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1795 pcm_close(out->pcm);
1796 out->pcm = NULL;
1797 goto error_open;
1798 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001799 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001800 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001801 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001802 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001803 audio_extn_tfa_98xx_enable_speaker();
1804
Eric Laurent994a6932013-07-17 11:51:42 -07001805 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001806 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001808 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001810error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001811 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812}
1813
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001814static int check_input_parameters(uint32_t sample_rate,
1815 audio_format_t format,
1816 int channel_count)
1817{
vivek mehta4ed66e62016-04-15 23:33:34 -07001818 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001819 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1820 return -EINVAL;
1821 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001822
vivek mehtadae44712015-07-27 14:13:18 -07001823 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001824 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001825 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1826 return -EINVAL;
1827 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001828
1829 switch (sample_rate) {
1830 case 8000:
1831 case 11025:
1832 case 12000:
1833 case 16000:
1834 case 22050:
1835 case 24000:
1836 case 32000:
1837 case 44100:
1838 case 48000:
1839 break;
1840 default:
vivek mehtadae44712015-07-27 14:13:18 -07001841 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001842 return -EINVAL;
1843 }
1844
1845 return 0;
1846}
1847
1848static size_t get_input_buffer_size(uint32_t sample_rate,
1849 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001850 int channel_count,
1851 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852{
1853 size_t size = 0;
1854
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001855 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1856 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001857
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001858 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001859 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001860 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001861
1862 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863
Glenn Kasten4f993392014-05-14 07:30:48 -07001864 /* make sure the size is multiple of 32 bytes
1865 * At 48 kHz mono 16-bit PCM:
1866 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1867 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1868 */
1869 size += 0x1f;
1870 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001871
1872 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001873}
1874
1875static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1876{
1877 struct stream_out *out = (struct stream_out *)stream;
1878
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001879 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880}
1881
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001882static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883{
1884 return -ENOSYS;
1885}
1886
1887static size_t out_get_buffer_size(const struct audio_stream *stream)
1888{
1889 struct stream_out *out = (struct stream_out *)stream;
1890
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001891 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1892 return out->compr_config.fragment_size;
1893 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001894 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001895 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001896}
1897
1898static uint32_t out_get_channels(const struct audio_stream *stream)
1899{
1900 struct stream_out *out = (struct stream_out *)stream;
1901
1902 return out->channel_mask;
1903}
1904
1905static audio_format_t out_get_format(const struct audio_stream *stream)
1906{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001907 struct stream_out *out = (struct stream_out *)stream;
1908
1909 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910}
1911
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001912static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001913{
1914 return -ENOSYS;
1915}
1916
1917static int out_standby(struct audio_stream *stream)
1918{
1919 struct stream_out *out = (struct stream_out *)stream;
1920 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001921
Eric Laurent994a6932013-07-17 11:51:42 -07001922 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001923 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001924
Eric Laurenta1478072015-09-21 17:21:52 -07001925 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001927 if (adev->adm_deregister_stream)
1928 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001929 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001931 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1932 if (out->pcm) {
1933 pcm_close(out->pcm);
1934 out->pcm = NULL;
1935 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001936 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1937 out->playback_started = false;
1938 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001939 } else {
1940 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001941 out->gapless_mdata.encoder_delay = 0;
1942 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001943 if (out->compr != NULL) {
1944 compress_close(out->compr);
1945 out->compr = NULL;
1946 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001947 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001948 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001949 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950 }
1951 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001952 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953 return 0;
1954}
1955
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001956static int out_on_error(struct audio_stream *stream)
1957{
1958 struct stream_out *out = (struct stream_out *)stream;
1959 struct audio_device *adev = out->dev;
1960 bool do_standby = false;
1961
1962 lock_output_stream(out);
1963 if (!out->standby) {
1964 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1965 stop_compressed_output_l(out);
1966 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1967 } else
1968 do_standby = true;
1969 }
1970 pthread_mutex_unlock(&out->lock);
1971
1972 if (do_standby)
1973 return out_standby(&out->stream.common);
1974
1975 return 0;
1976}
1977
Andy Hung7401c7c2016-09-21 12:41:21 -07001978static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979{
Andy Hung7401c7c2016-09-21 12:41:21 -07001980 struct stream_out *out = (struct stream_out *)stream;
1981
1982 // We try to get the lock for consistency,
1983 // but it isn't necessary for these variables.
1984 // If we're not in standby, we may be blocked on a write.
1985 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1986 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1987 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1988
1989 if (locked) {
1990 log_dump_l(&out->error_log, fd);
1991 pthread_mutex_unlock(&out->lock);
1992 } else {
1993 // We don't have the lock here, copy for safety.
1994 struct error_log log = out->error_log;
1995 log_dump_l(&log, fd);
1996 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997 return 0;
1998}
1999
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002000static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2001{
2002 int ret = 0;
2003 char value[32];
2004 struct compr_gapless_mdata tmp_mdata;
2005
2006 if (!out || !parms) {
2007 return -EINVAL;
2008 }
2009
2010 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2011 if (ret >= 0) {
2012 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2013 } else {
2014 return -EINVAL;
2015 }
2016
2017 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2018 if (ret >= 0) {
2019 tmp_mdata.encoder_padding = atoi(value);
2020 } else {
2021 return -EINVAL;
2022 }
2023
2024 out->gapless_mdata = tmp_mdata;
2025 out->send_new_metadata = 1;
2026 ALOGV("%s new encoder delay %u and padding %u", __func__,
2027 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2028
2029 return 0;
2030}
2031
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002032static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2033{
2034 return out == adev->primary_output || out == adev->voice_tx_output;
2035}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2038{
2039 struct stream_out *out = (struct stream_out *)stream;
2040 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002041 struct audio_usecase *usecase;
2042 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043 struct str_parms *parms;
2044 char value[32];
2045 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002046 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002047 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048
Eric Laurent2e140aa2016-06-30 17:14:46 -07002049 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002050 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002051 parms = str_parms_create_str(kvpairs);
2052 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2053 if (ret >= 0) {
2054 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002055 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002056 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002058 /*
2059 * When HDMI cable is unplugged the music playback is paused and
2060 * the policy manager sends routing=0. But the audioflinger
2061 * continues to write data until standby time (3sec).
2062 * As the HDMI core is turned off, the write gets blocked.
2063 * Avoid this by routing audio to speaker until standby.
2064 */
2065 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2066 val == AUDIO_DEVICE_NONE) {
2067 val = AUDIO_DEVICE_OUT_SPEAKER;
2068 }
2069
2070 /*
2071 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002072 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002073 * the select_devices(). But how do we undo this?
2074 *
2075 * For example, music playback is active on headset (deep-buffer usecase)
2076 * and if we go to ringtones and select a ringtone, low-latency usecase
2077 * will be started on headset+speaker. As we can't enable headset+speaker
2078 * and headset devices at the same time, select_devices() switches the music
2079 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2080 * So when the ringtone playback is completed, how do we undo the same?
2081 *
2082 * We are relying on the out_set_parameters() call on deep-buffer output,
2083 * once the ringtone playback is ended.
2084 * NOTE: We should not check if the current devices are same as new devices.
2085 * Because select_devices() must be called to switch back the music
2086 * playback to headset.
2087 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002088 audio_devices_t new_dev = val;
2089 if (new_dev != AUDIO_DEVICE_NONE) {
2090 bool same_dev = out->devices == new_dev;
2091 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002092
Eric Laurenta7657192014-10-09 21:09:33 -07002093 if (output_drives_call(adev, out)) {
2094 if (!voice_is_in_call(adev)) {
2095 if (adev->mode == AUDIO_MODE_IN_CALL) {
2096 adev->current_call_output = out;
2097 ret = voice_start_call(adev);
2098 }
2099 } else {
2100 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002101 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002102 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002103 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002104
2105 if (!out->standby) {
2106 if (!same_dev) {
2107 ALOGV("update routing change");
2108 out->routing_change = true;
2109 }
2110 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002111 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002112 }
2113
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002114 }
2115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002117 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002118
2119 /*handles device and call state changes*/
2120 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002122
2123 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2124 parse_compress_metadata(out, parms);
2125 }
2126
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002127 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002128 ALOGV("%s: exit: code(%d)", __func__, status);
2129 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130}
2131
2132static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2133{
2134 struct stream_out *out = (struct stream_out *)stream;
2135 struct str_parms *query = str_parms_create_str(keys);
2136 char *str;
2137 char value[256];
2138 struct str_parms *reply = str_parms_create();
2139 size_t i, j;
2140 int ret;
2141 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002142 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2144 if (ret >= 0) {
2145 value[0] = '\0';
2146 i = 0;
2147 while (out->supported_channel_masks[i] != 0) {
2148 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2149 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2150 if (!first) {
2151 strcat(value, "|");
2152 }
2153 strcat(value, out_channels_name_to_enum_table[j].name);
2154 first = false;
2155 break;
2156 }
2157 }
2158 i++;
2159 }
2160 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2161 str = str_parms_to_str(reply);
2162 } else {
2163 str = strdup(keys);
2164 }
2165 str_parms_destroy(query);
2166 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002167 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168 return str;
2169}
2170
2171static uint32_t out_get_latency(const struct audio_stream_out *stream)
2172{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002173 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174 struct stream_out *out = (struct stream_out *)stream;
2175
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002176 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2177 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002178 else if ((out->realtime) ||
2179 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002180 // since the buffer won't be filled up faster than realtime,
2181 // return a smaller number
2182 period_ms = (out->af_period_multiplier * out->config.period_size *
2183 1000) / (out->config.rate);
2184 hw_delay = platform_render_latency(out->usecase)/1000;
2185 return period_ms + hw_delay;
2186 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002187
2188 return (out->config.period_count * out->config.period_size * 1000) /
2189 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190}
2191
2192static int out_set_volume(struct audio_stream_out *stream, float left,
2193 float right)
2194{
Eric Laurenta9024de2013-04-04 09:19:12 -07002195 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002196 int volume[2];
2197
Eric Laurenta9024de2013-04-04 09:19:12 -07002198 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2199 /* only take left channel into account: the API is for stereo anyway */
2200 out->muted = (left == 0.0f);
2201 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002202 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2203 const char *mixer_ctl_name = "Compress Playback Volume";
2204 struct audio_device *adev = out->dev;
2205 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002206 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2207 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002208 /* try with the control based on device id */
2209 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2210 PCM_PLAYBACK);
2211 char ctl_name[128] = {0};
2212 snprintf(ctl_name, sizeof(ctl_name),
2213 "Compress Playback %d Volume", pcm_device_id);
2214 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2215 if (!ctl) {
2216 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2217 return -EINVAL;
2218 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002219 }
2220 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2221 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2222 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2223 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002224 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002225
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226 return -ENOSYS;
2227}
2228
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002229// note: this call is safe only if the stream_cb is
2230// removed first in close_output_stream (as is done now).
2231static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2232{
2233 if (!stream || !parms)
2234 return;
2235
2236 struct stream_out *out = (struct stream_out *)stream;
2237 struct audio_device *adev = out->dev;
2238
2239 card_status_t status;
2240 int card;
2241 if (parse_snd_card_status(parms, &card, &status) < 0)
2242 return;
2243
2244 pthread_mutex_lock(&adev->lock);
2245 bool valid_cb = (card == adev->snd_card);
2246 pthread_mutex_unlock(&adev->lock);
2247
2248 if (!valid_cb)
2249 return;
2250
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002251 lock_output_stream(out);
2252 if (out->card_status != status)
2253 out->card_status = status;
2254 pthread_mutex_unlock(&out->lock);
2255
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002256 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2257 use_case_table[out->usecase],
2258 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2259
2260 if (status == CARD_STATUS_OFFLINE)
2261 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002262
2263 return;
2264}
2265
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002266#ifdef NO_AUDIO_OUT
2267static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002268 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002269{
2270 struct stream_out *out = (struct stream_out *)stream;
2271
2272 /* No Output device supported other than BT for playback.
2273 * Sleep for the amount of buffer duration
2274 */
Eric Laurenta1478072015-09-21 17:21:52 -07002275 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002276 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2277 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002278 out_get_sample_rate(&out->stream.common));
2279 pthread_mutex_unlock(&out->lock);
2280 return bytes;
2281}
2282#endif
2283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002284static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2285 size_t bytes)
2286{
2287 struct stream_out *out = (struct stream_out *)stream;
2288 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002289 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002290 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002291
Eric Laurenta1478072015-09-21 17:21:52 -07002292 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002293 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2294 error_code = ERROR_CODE_WRITE;
2295 goto exit;
2296 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002297 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002298 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002299 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002301 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002302 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002303 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002304 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305 goto exit;
2306 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002307
2308 if (last_known_cal_step != -1) {
2309 ALOGD("%s: retry previous failed cal level set", __func__);
2310 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2311 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002312 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002314 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002315 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002316 if (out->send_new_metadata) {
2317 ALOGVV("send new gapless metadata");
2318 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2319 out->send_new_metadata = 0;
2320 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002321 unsigned int avail;
2322 struct timespec tstamp;
2323 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2324 /* Do not limit write size if the available frames count is unknown */
2325 if (ret != 0) {
2326 avail = bytes;
2327 }
2328 if (avail == 0) {
2329 ret = 0;
2330 } else {
2331 if (avail > bytes) {
2332 avail = bytes;
2333 }
2334 ret = compress_write(out->compr, buffer, avail);
2335 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2336 __func__, avail, ret);
2337 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002338
Eric Laurent6e895242013-09-05 16:10:57 -07002339 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002340 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2341 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002342 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 compress_start(out->compr);
2344 out->playback_started = 1;
2345 out->offload_state = OFFLOAD_STATE_PLAYING;
2346 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002347 if (ret < 0) {
2348 log_error_l(&out->error_log, ERROR_CODE_WRITE);
2349 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002350 pthread_mutex_unlock(&out->lock);
2351 return ret;
2352 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002353 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002354 if (out->pcm) {
2355 if (out->muted)
2356 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002357
Eric Laurent0e46adf2016-12-16 12:49:24 -08002358 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002359
Haynes Mathew George03c40102016-01-29 17:57:48 -08002360 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2361 out->config.rate;
2362 request_out_focus(out, ns);
2363
2364 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2365 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002366 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002367 else
2368 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002369
Haynes Mathew George03c40102016-01-29 17:57:48 -08002370 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002371 } else {
2372 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374 }
2375
2376exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002377 // For PCM we always consume the buffer and return #bytes regardless of ret.
2378 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2379 out->written += bytes / (out->config.channels * sizeof(short));
2380 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002381 long long sleeptime_us = 0;
2382 if (ret != 0) {
2383 log_error_l(&out->error_log, error_code);
2384 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2385 ALOGE_IF(out->pcm != NULL,
2386 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
2387 sleeptime_us = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2388 out_get_sample_rate(&out->stream.common);
2389 // usleep not guaranteed for values over 1 second but we don't limit here.
2390 }
2391 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002392
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002393 pthread_mutex_unlock(&out->lock);
2394
2395 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002396 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002397 if (sleeptime_us != 0)
2398 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002399 }
2400 return bytes;
2401}
2402
2403static int out_get_render_position(const struct audio_stream_out *stream,
2404 uint32_t *dsp_frames)
2405{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002406 struct stream_out *out = (struct stream_out *)stream;
2407 *dsp_frames = 0;
2408 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002409 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002410 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002411 unsigned long frames = 0;
2412 // TODO: check return value
2413 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2414 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002415 ALOGVV("%s rendered frames %d sample_rate %d",
2416 __func__, *dsp_frames, out->sample_rate);
2417 }
2418 pthread_mutex_unlock(&out->lock);
2419 return 0;
2420 } else
2421 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002422}
2423
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002424static int out_add_audio_effect(const struct audio_stream *stream __unused,
2425 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426{
2427 return 0;
2428}
2429
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002430static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2431 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432{
2433 return 0;
2434}
2435
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002436static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2437 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438{
2439 return -EINVAL;
2440}
2441
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002442static int out_get_presentation_position(const struct audio_stream_out *stream,
2443 uint64_t *frames, struct timespec *timestamp)
2444{
2445 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002446 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002447 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002448
Eric Laurenta1478072015-09-21 17:21:52 -07002449 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002450
Eric Laurent949a0892013-09-20 09:20:13 -07002451 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2452 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002453 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002454 compress_get_tstamp(out->compr, &dsp_frames,
2455 &out->sample_rate);
2456 ALOGVV("%s rendered frames %ld sample_rate %d",
2457 __func__, dsp_frames, out->sample_rate);
2458 *frames = dsp_frames;
2459 ret = 0;
2460 /* this is the best we can do */
2461 clock_gettime(CLOCK_MONOTONIC, timestamp);
2462 }
2463 } else {
2464 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002465 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002466 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2467 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002468 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002469 // This adjustment accounts for buffering after app processor.
2470 // It is based on estimated DSP latency per use case, rather than exact.
2471 signed_frames -=
2472 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2473
Eric Laurent949a0892013-09-20 09:20:13 -07002474 // It would be unusual for this value to be negative, but check just in case ...
2475 if (signed_frames >= 0) {
2476 *frames = signed_frames;
2477 ret = 0;
2478 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002479 }
2480 }
2481 }
2482
2483 pthread_mutex_unlock(&out->lock);
2484
2485 return ret;
2486}
2487
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002488static int out_set_callback(struct audio_stream_out *stream,
2489 stream_callback_t callback, void *cookie)
2490{
2491 struct stream_out *out = (struct stream_out *)stream;
2492
2493 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002494 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002495 out->offload_callback = callback;
2496 out->offload_cookie = cookie;
2497 pthread_mutex_unlock(&out->lock);
2498 return 0;
2499}
2500
2501static int out_pause(struct audio_stream_out* stream)
2502{
2503 struct stream_out *out = (struct stream_out *)stream;
2504 int status = -ENOSYS;
2505 ALOGV("%s", __func__);
2506 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002507 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002508 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2509 status = compress_pause(out->compr);
2510 out->offload_state = OFFLOAD_STATE_PAUSED;
2511 }
2512 pthread_mutex_unlock(&out->lock);
2513 }
2514 return status;
2515}
2516
2517static int out_resume(struct audio_stream_out* stream)
2518{
2519 struct stream_out *out = (struct stream_out *)stream;
2520 int status = -ENOSYS;
2521 ALOGV("%s", __func__);
2522 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2523 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002524 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002525 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2526 status = compress_resume(out->compr);
2527 out->offload_state = OFFLOAD_STATE_PLAYING;
2528 }
2529 pthread_mutex_unlock(&out->lock);
2530 }
2531 return status;
2532}
2533
2534static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2535{
2536 struct stream_out *out = (struct stream_out *)stream;
2537 int status = -ENOSYS;
2538 ALOGV("%s", __func__);
2539 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002540 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002541 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2542 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2543 else
2544 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2545 pthread_mutex_unlock(&out->lock);
2546 }
2547 return status;
2548}
2549
2550static int out_flush(struct audio_stream_out* stream)
2551{
2552 struct stream_out *out = (struct stream_out *)stream;
2553 ALOGV("%s", __func__);
2554 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002555 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002556 stop_compressed_output_l(out);
2557 pthread_mutex_unlock(&out->lock);
2558 return 0;
2559 }
2560 return -ENOSYS;
2561}
2562
Eric Laurent0e46adf2016-12-16 12:49:24 -08002563static int out_stop(const struct audio_stream_out* stream)
2564{
2565 struct stream_out *out = (struct stream_out *)stream;
2566 struct audio_device *adev = out->dev;
2567 int ret = -ENOSYS;
2568
2569 ALOGV("%s", __func__);
2570 pthread_mutex_lock(&adev->lock);
2571 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2572 out->playback_started && out->pcm != NULL) {
2573 pcm_stop(out->pcm);
2574 ret = stop_output_stream(out);
2575 if (ret == 0) {
2576 out->playback_started = false;
2577 }
2578 }
2579 pthread_mutex_unlock(&adev->lock);
2580 return ret;
2581}
2582
2583static int out_start(const struct audio_stream_out* stream)
2584{
2585 struct stream_out *out = (struct stream_out *)stream;
2586 struct audio_device *adev = out->dev;
2587 int ret = -ENOSYS;
2588
2589 ALOGV("%s", __func__);
2590 pthread_mutex_lock(&adev->lock);
2591 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2592 !out->playback_started && out->pcm != NULL) {
2593 ret = start_output_stream(out);
2594 if (ret == 0) {
2595 out->playback_started = true;
2596 }
2597 }
2598 pthread_mutex_unlock(&adev->lock);
2599 return ret;
2600}
2601
2602static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2603 int32_t min_size_frames,
2604 struct audio_mmap_buffer_info *info)
2605{
2606 struct stream_out *out = (struct stream_out *)stream;
2607 struct audio_device *adev = out->dev;
2608 int ret = 0;
2609 unsigned int offset1;
2610 unsigned int frames1;
2611 const char *step = "";
2612
2613 ALOGV("%s", __func__);
2614 pthread_mutex_lock(&adev->lock);
2615
2616 if (info == NULL || min_size_frames == 0) {
2617 ret = -EINVAL;
2618 goto exit;
2619 }
2620 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
2621 ret = -ENOSYS;
2622 goto exit;
2623 }
2624 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2625 if (out->pcm_device_id < 0) {
2626 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2627 __func__, out->pcm_device_id, out->usecase);
2628 ret = -EINVAL;
2629 goto exit;
2630 }
2631 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2632 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2633 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2634 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2635 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2636 step = "open";
2637 ret = -ENODEV;
2638 goto exit;
2639 }
2640 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2641 if (ret < 0) {
2642 step = "begin";
2643 goto exit;
2644 }
2645 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2646 info->burst_size_frames = out->config.period_size;
2647 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2648
2649 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2650 info->buffer_size_frames));
2651
2652 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2653 if (ret < 0) {
2654 step = "commit";
2655 goto exit;
2656 }
2657 ret = 0;
2658
2659 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2660 __func__, info->shared_memory_address, info->buffer_size_frames);
2661
2662exit:
2663 if (ret != 0) {
2664 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
2665 if (out->pcm != NULL) {
2666 pcm_close(out->pcm);
2667 out->pcm = NULL;
2668 }
2669 }
2670 pthread_mutex_unlock(&adev->lock);
2671 return ret;
2672}
2673
2674static int out_get_mmap_position(const struct audio_stream_out *stream,
2675 struct audio_mmap_position *position)
2676{
2677 struct stream_out *out = (struct stream_out *)stream;
2678 ALOGVV("%s", __func__);
2679 if (position == NULL) {
2680 return -EINVAL;
2681 }
2682 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2683 return -ENOSYS;
2684 }
2685 if (out->pcm == NULL) {
2686 return -ENOSYS;
2687 }
2688
2689 struct timespec ts = { 0, 0 };
2690 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2691 if (ret < 0) {
2692 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2693 return ret;
2694 }
2695 position->time_nanoseconds = ts2ns(&ts);
2696 return 0;
2697}
2698
2699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700/** audio_stream_in implementation **/
2701static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2702{
2703 struct stream_in *in = (struct stream_in *)stream;
2704
2705 return in->config.rate;
2706}
2707
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002708static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709{
2710 return -ENOSYS;
2711}
2712
2713static size_t in_get_buffer_size(const struct audio_stream *stream)
2714{
2715 struct stream_in *in = (struct stream_in *)stream;
2716
Haynes Mathew George03c40102016-01-29 17:57:48 -08002717 return in->config.period_size * in->af_period_multiplier *
2718 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719}
2720
2721static uint32_t in_get_channels(const struct audio_stream *stream)
2722{
2723 struct stream_in *in = (struct stream_in *)stream;
2724
2725 return in->channel_mask;
2726}
2727
vivek mehta4ed66e62016-04-15 23:33:34 -07002728static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729{
vivek mehta4ed66e62016-04-15 23:33:34 -07002730 struct stream_in *in = (struct stream_in *)stream;
2731 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002732}
2733
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002734static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735{
2736 return -ENOSYS;
2737}
2738
2739static int in_standby(struct audio_stream *stream)
2740{
2741 struct stream_in *in = (struct stream_in *)stream;
2742 struct audio_device *adev = in->dev;
2743 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07002744 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002745
2746 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002747
2748 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002749 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002750 audio_extn_sound_trigger_stop_lab(in);
2751 in->standby = true;
2752 }
2753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002755 if (adev->adm_deregister_stream)
2756 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2757
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002758 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002759 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002760 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
2761 in->capture_started = false;
2762 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002763 if (in->pcm) {
2764 pcm_close(in->pcm);
2765 in->pcm = NULL;
2766 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002767 adev->enable_voicerx = false;
2768 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002770 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771 }
2772 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002773 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774 return status;
2775}
2776
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002777static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778{
2779 return 0;
2780}
2781
2782static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2783{
2784 struct stream_in *in = (struct stream_in *)stream;
2785 struct audio_device *adev = in->dev;
2786 struct str_parms *parms;
2787 char *str;
2788 char value[32];
2789 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002790 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791
Eric Laurent994a6932013-07-17 11:51:42 -07002792 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793 parms = str_parms_create_str(kvpairs);
2794
2795 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2796
Eric Laurenta1478072015-09-21 17:21:52 -07002797 lock_input_stream(in);
2798
Eric Laurent150dbfe2013-02-27 14:31:02 -08002799 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002800 if (ret >= 0) {
2801 val = atoi(value);
2802 /* no audio source uses val == 0 */
2803 if ((in->source != val) && (val != 0)) {
2804 in->source = val;
2805 }
2806 }
2807
2808 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002809
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810 if (ret >= 0) {
2811 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002812 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813 in->device = val;
2814 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002815 if (!in->standby) {
2816 ALOGV("update input routing change");
2817 in->routing_change = true;
2818 select_devices(adev, in->usecase);
2819 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002820 }
2821 }
2822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002824 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825
2826 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002827 ALOGV("%s: exit: status(%d)", __func__, status);
2828 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829}
2830
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002831static char* in_get_parameters(const struct audio_stream *stream __unused,
2832 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002833{
2834 return strdup("");
2835}
2836
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002837static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002838{
2839 return 0;
2840}
2841
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002842static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2843{
2844 if (!stream || !parms)
2845 return;
2846
2847 struct stream_in *in = (struct stream_in *)stream;
2848 struct audio_device *adev = in->dev;
2849
2850 card_status_t status;
2851 int card;
2852 if (parse_snd_card_status(parms, &card, &status) < 0)
2853 return;
2854
2855 pthread_mutex_lock(&adev->lock);
2856 bool valid_cb = (card == adev->snd_card);
2857 pthread_mutex_unlock(&adev->lock);
2858
2859 if (!valid_cb)
2860 return;
2861
2862 lock_input_stream(in);
2863 if (in->card_status != status)
2864 in->card_status = status;
2865 pthread_mutex_unlock(&in->lock);
2866
2867 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2868 use_case_table[in->usecase],
2869 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2870
2871 // a better solution would be to report error back to AF and let
2872 // it put the stream to standby
2873 if (status == CARD_STATUS_OFFLINE)
2874 in_standby(&in->stream.common);
2875
2876 return;
2877}
2878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2880 size_t bytes)
2881{
2882 struct stream_in *in = (struct stream_in *)stream;
2883 struct audio_device *adev = in->dev;
2884 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002885 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002886
Eric Laurenta1478072015-09-21 17:21:52 -07002887 lock_input_stream(in);
2888
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002889 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002890 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002891 /* Read from sound trigger HAL */
2892 audio_extn_sound_trigger_read(in, buffer, bytes);
2893 pthread_mutex_unlock(&in->lock);
2894 return bytes;
2895 }
2896
Eric Laurent0e46adf2016-12-16 12:49:24 -08002897 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
2898 ret = -ENOSYS;
2899 goto exit;
2900 }
2901
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002902 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002903 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002904 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002905 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002906 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002907 goto exit;
2908 }
2909 in->standby = 0;
2910 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002911
Haynes Mathew George03c40102016-01-29 17:57:48 -08002912 //what's the duration requested by the client?
2913 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2914 in->config.rate;
2915 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002916
Haynes Mathew George03c40102016-01-29 17:57:48 -08002917 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002918 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002919 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002920 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002921 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002922 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002923 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002924 if (ret < 0) {
2925 ALOGE("Failed to read w/err %s", strerror(errno));
2926 ret = -errno;
2927 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002928 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2929 if (bytes % 4 == 0) {
2930 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2931 int_buf_stream = buffer;
2932 for (size_t itt=0; itt < bytes/4 ; itt++) {
2933 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002934 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002935 } else {
2936 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2937 ret = -EINVAL;
2938 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002939 }
2940 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002941 }
2942
Haynes Mathew George03c40102016-01-29 17:57:48 -08002943 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002944
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002945 /*
2946 * Instead of writing zeroes here, we could trust the hardware
2947 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002948 * 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 -08002949 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002950 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002951 memset(buffer, 0, bytes);
2952
2953exit:
2954 pthread_mutex_unlock(&in->lock);
2955
2956 if (ret != 0) {
2957 in_standby(&in->stream.common);
2958 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002959 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002960 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002961 memset(buffer, 0, bytes); // clear return data
2962 }
2963 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002964 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002965 }
2966 return bytes;
2967}
2968
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002969static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002970{
2971 return 0;
2972}
2973
Andy Hung6ebe5962016-01-15 17:46:57 -08002974static int in_get_capture_position(const struct audio_stream_in *stream,
2975 int64_t *frames, int64_t *time)
2976{
2977 if (stream == NULL || frames == NULL || time == NULL) {
2978 return -EINVAL;
2979 }
2980 struct stream_in *in = (struct stream_in *)stream;
2981 int ret = -ENOSYS;
2982
2983 lock_input_stream(in);
2984 if (in->pcm) {
2985 struct timespec timestamp;
2986 unsigned int avail;
2987 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2988 *frames = in->frames_read + avail;
2989 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2990 ret = 0;
2991 }
2992 }
2993 pthread_mutex_unlock(&in->lock);
2994 return ret;
2995}
2996
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002997static int add_remove_audio_effect(const struct audio_stream *stream,
2998 effect_handle_t effect,
2999 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003001 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003002 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003003 int status = 0;
3004 effect_descriptor_t desc;
3005
3006 status = (*effect)->get_descriptor(effect, &desc);
3007 if (status != 0)
3008 return status;
3009
Eric Laurenta1478072015-09-21 17:21:52 -07003010 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003011 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003012 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003013 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003014 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003015 in->enable_aec != enable &&
3016 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3017 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003018 if (!enable)
3019 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003020 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3021 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3022 adev->enable_voicerx = enable;
3023 struct audio_usecase *usecase;
3024 struct listnode *node;
3025 list_for_each(node, &adev->usecase_list) {
3026 usecase = node_to_item(node, struct audio_usecase, list);
3027 if (usecase->type == PCM_PLAYBACK) {
3028 select_devices(adev, usecase->id);
3029 break;
3030 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003031 }
3032 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003033 if (!in->standby)
3034 select_devices(in->dev, in->usecase);
3035 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003036 if (in->enable_ns != enable &&
3037 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3038 in->enable_ns = enable;
3039 if (!in->standby)
3040 select_devices(in->dev, in->usecase);
3041 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003042 pthread_mutex_unlock(&in->dev->lock);
3043 pthread_mutex_unlock(&in->lock);
3044
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045 return 0;
3046}
3047
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003048static int in_add_audio_effect(const struct audio_stream *stream,
3049 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050{
Eric Laurent994a6932013-07-17 11:51:42 -07003051 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003052 return add_remove_audio_effect(stream, effect, true);
3053}
3054
3055static int in_remove_audio_effect(const struct audio_stream *stream,
3056 effect_handle_t effect)
3057{
Eric Laurent994a6932013-07-17 11:51:42 -07003058 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003059 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060}
3061
Eric Laurent0e46adf2016-12-16 12:49:24 -08003062static int in_stop(const struct audio_stream_in* stream)
3063{
3064 struct stream_in *in = (struct stream_in *)stream;
3065 struct audio_device *adev = in->dev;
3066
3067 int ret = -ENOSYS;
3068 ALOGV("%s", __func__);
3069 pthread_mutex_lock(&adev->lock);
3070 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3071 in->capture_started && in->pcm != NULL) {
3072 pcm_stop(in->pcm);
3073 ret = stop_input_stream(in);
3074 if (ret == 0) {
3075 in->capture_started = false;
3076 }
3077 }
3078 pthread_mutex_unlock(&adev->lock);
3079 return ret;
3080}
3081
3082static int in_start(const struct audio_stream_in* stream)
3083{
3084 struct stream_in *in = (struct stream_in *)stream;
3085 struct audio_device *adev = in->dev;
3086 int ret = -ENOSYS;
3087
3088 ALOGV("%s in %p", __func__, in);
3089 pthread_mutex_lock(&adev->lock);
3090 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3091 !in->capture_started && in->pcm != NULL) {
3092 if (!in->capture_started) {
3093 ret = start_input_stream(in);
3094 if (ret == 0) {
3095 in->capture_started = true;
3096 }
3097 }
3098 }
3099 pthread_mutex_unlock(&adev->lock);
3100 return ret;
3101}
3102
3103static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3104 int32_t min_size_frames,
3105 struct audio_mmap_buffer_info *info)
3106{
3107 struct stream_in *in = (struct stream_in *)stream;
3108 struct audio_device *adev = in->dev;
3109 int ret = 0;
3110 unsigned int offset1;
3111 unsigned int frames1;
3112 const char *step = "";
3113
3114 pthread_mutex_lock(&adev->lock);
3115 ALOGV("%s in %p", __func__, in);
3116 if (info == NULL || min_size_frames == 0) {
3117 ALOGV("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
3118 ret = -EINVAL;
3119 goto exit;
3120 }
3121 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
3122 ALOGV("%s in %p", __func__, in);
3123 ret = -ENOSYS;
3124 goto exit;
3125 }
3126 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3127 if (in->pcm_device_id < 0) {
3128 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3129 __func__, in->pcm_device_id, in->usecase);
3130 ret = -EINVAL;
3131 goto exit;
3132 }
3133 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3134 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3135 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3136 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3137 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3138 step = "open";
3139 ret = -ENODEV;
3140 goto exit;
3141 }
3142
3143 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3144 if (ret < 0) {
3145 step = "begin";
3146 goto exit;
3147 }
3148 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3149 info->burst_size_frames = in->config.period_size;
3150 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3151
3152 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3153 info->buffer_size_frames));
3154
3155 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3156 if (ret < 0) {
3157 step = "commit";
3158 goto exit;
3159 }
3160
3161 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3162 __func__, info->shared_memory_address, info->buffer_size_frames);
3163 ret = 0;
3164
3165exit:
3166 if (ret != 0) {
3167 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
3168 if (in->pcm != NULL) {
3169 pcm_close(in->pcm);
3170 in->pcm = NULL;
3171 }
3172 }
3173 pthread_mutex_unlock(&adev->lock);
3174 return ret;
3175}
3176
3177static int in_get_mmap_position(const struct audio_stream_in *stream,
3178 struct audio_mmap_position *position)
3179{
3180 struct stream_in *in = (struct stream_in *)stream;
3181 ALOGVV("%s", __func__);
3182 if (position == NULL) {
3183 return -EINVAL;
3184 }
3185 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3186 return -ENOSYS;
3187 }
3188 if (in->pcm == NULL) {
3189 return -ENOSYS;
3190 }
3191 struct timespec ts = { 0, 0 };
3192 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3193 if (ret < 0) {
3194 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3195 return ret;
3196 }
3197 position->time_nanoseconds = ts2ns(&ts);
3198 return 0;
3199}
3200
3201
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003202static int adev_open_output_stream(struct audio_hw_device *dev,
3203 audio_io_handle_t handle,
3204 audio_devices_t devices,
3205 audio_output_flags_t flags,
3206 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003207 struct audio_stream_out **stream_out,
3208 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003209{
3210 struct audio_device *adev = (struct audio_device *)dev;
3211 struct stream_out *out;
3212 int i, ret;
3213
Eric Laurent994a6932013-07-17 11:51:42 -07003214 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215 __func__, config->sample_rate, config->channel_mask, devices, flags);
3216 *stream_out = NULL;
3217 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3218
3219 if (devices == AUDIO_DEVICE_NONE)
3220 devices = AUDIO_DEVICE_OUT_SPEAKER;
3221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222 out->flags = flags;
3223 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003224 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003225 out->format = config->format;
3226 out->sample_rate = config->sample_rate;
3227 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3228 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003229 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230
3231 /* Init use case and pcm_config */
3232 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07003233 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003235 pthread_mutex_lock(&adev->lock);
3236 ret = read_hdmi_channel_masks(out);
3237 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003238 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003239 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003240
3241 if (config->sample_rate == 0)
3242 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3243 if (config->channel_mask == 0)
3244 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08003245 if (config->format == AUDIO_FORMAT_DEFAULT)
3246 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003247
3248 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003249 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08003250 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003251 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3252 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003253 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003254 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003255 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003256 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003257 pthread_mutex_lock(&adev->lock);
3258 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3259 pthread_mutex_unlock(&adev->lock);
3260
3261 // reject offload during card offline to allow
3262 // fallback to s/w paths
3263 if (offline) {
3264 ret = -ENODEV;
3265 goto error_open;
3266 }
3267
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003268 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3269 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3270 ALOGE("%s: Unsupported Offload information", __func__);
3271 ret = -EINVAL;
3272 goto error_open;
3273 }
3274 if (!is_supported_format(config->offload_info.format)) {
3275 ALOGE("%s: Unsupported audio format", __func__);
3276 ret = -EINVAL;
3277 goto error_open;
3278 }
3279
3280 out->compr_config.codec = (struct snd_codec *)
3281 calloc(1, sizeof(struct snd_codec));
3282
3283 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3284 if (config->offload_info.channel_mask)
3285 out->channel_mask = config->offload_info.channel_mask;
3286 else if (config->channel_mask)
3287 out->channel_mask = config->channel_mask;
3288 out->format = config->offload_info.format;
3289 out->sample_rate = config->offload_info.sample_rate;
3290
3291 out->stream.set_callback = out_set_callback;
3292 out->stream.pause = out_pause;
3293 out->stream.resume = out_resume;
3294 out->stream.drain = out_drain;
3295 out->stream.flush = out_flush;
3296
3297 out->compr_config.codec->id =
3298 get_snd_codec_id(config->offload_info.format);
3299 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3300 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003301 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003302 out->compr_config.codec->bit_rate =
3303 config->offload_info.bit_rate;
3304 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003305 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003306 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3307
3308 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3309 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003310
3311 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003312 create_offload_callback_thread(out);
3313 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3314 __func__, config->offload_info.version,
3315 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003316 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3317 if (config->sample_rate == 0)
3318 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3319 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3320 config->sample_rate != 8000) {
3321 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3322 ret = -EINVAL;
3323 goto error_open;
3324 }
3325 out->sample_rate = config->sample_rate;
3326 out->config.rate = config->sample_rate;
3327 if (config->format == AUDIO_FORMAT_DEFAULT)
3328 config->format = AUDIO_FORMAT_PCM_16_BIT;
3329 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3330 config->format = AUDIO_FORMAT_PCM_16_BIT;
3331 ret = -EINVAL;
3332 goto error_open;
3333 }
3334 out->format = config->format;
3335 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3336 out->config = pcm_config_afe_proxy_playback;
3337 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003339 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3340 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3341 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003342 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3343 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3344 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003345 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3346 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003347 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003348 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003349 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3350 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3351 out->config = pcm_config_mmap_playback;
3352 out->stream.start = out_start;
3353 out->stream.stop = out_stop;
3354 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3355 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003356 } else {
3357 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3358 out->config = pcm_config_low_latency;
3359 }
3360 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3361 if (k_enable_extended_precision
3362 && pcm_params_format_test(adev->use_case_table[out->usecase],
3363 pcm_format_from_audio_format(config->format))) {
3364 out->config.format = pcm_format_from_audio_format(config->format);
3365 /* out->format already set to config->format */
3366 } else {
3367 /* deny the externally proposed config format
3368 * and use the one specified in audio_hw layer configuration.
3369 * Note: out->format is returned by out->stream.common.get_format()
3370 * and is used to set config->format in the code several lines below.
3371 */
3372 out->format = audio_format_from_pcm_format(out->config.format);
3373 }
3374 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003375 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003377 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3378 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003380 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003381 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003382 adev->primary_output = out;
3383 else {
3384 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003385 ret = -EEXIST;
3386 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003387 }
3388 }
3389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390 /* Check if this usecase is already existing */
3391 pthread_mutex_lock(&adev->lock);
3392 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3393 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003395 ret = -EEXIST;
3396 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397 }
3398 pthread_mutex_unlock(&adev->lock);
3399
3400 out->stream.common.get_sample_rate = out_get_sample_rate;
3401 out->stream.common.set_sample_rate = out_set_sample_rate;
3402 out->stream.common.get_buffer_size = out_get_buffer_size;
3403 out->stream.common.get_channels = out_get_channels;
3404 out->stream.common.get_format = out_get_format;
3405 out->stream.common.set_format = out_set_format;
3406 out->stream.common.standby = out_standby;
3407 out->stream.common.dump = out_dump;
3408 out->stream.common.set_parameters = out_set_parameters;
3409 out->stream.common.get_parameters = out_get_parameters;
3410 out->stream.common.add_audio_effect = out_add_audio_effect;
3411 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3412 out->stream.get_latency = out_get_latency;
3413 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003414#ifdef NO_AUDIO_OUT
3415 out->stream.write = out_write_for_no_output;
3416#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003418#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419 out->stream.get_render_position = out_get_render_position;
3420 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003421 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422
Eric Laurent0e46adf2016-12-16 12:49:24 -08003423 if (out->realtime)
3424 out->af_period_multiplier = af_period_multiplier;
3425 else
3426 out->af_period_multiplier = 1;
3427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003429 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003430 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003432 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003433 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003434 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003436 config->format = out->stream.common.get_format(&out->stream.common);
3437 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3438 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3439
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003440
3441 /*
3442 By locking output stream before registering, we allow the callback
3443 to update stream's state only after stream's initial state is set to
3444 adev state.
3445 */
3446 lock_output_stream(out);
3447 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3448 pthread_mutex_lock(&adev->lock);
3449 out->card_status = adev->card_status;
3450 pthread_mutex_unlock(&adev->lock);
3451 pthread_mutex_unlock(&out->lock);
3452
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003454
Eric Laurent994a6932013-07-17 11:51:42 -07003455 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003457
3458error_open:
3459 free(out);
3460 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003461 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003462 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463}
3464
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003465static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466 struct audio_stream_out *stream)
3467{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003468 struct stream_out *out = (struct stream_out *)stream;
3469 struct audio_device *adev = out->dev;
3470
Eric Laurent994a6932013-07-17 11:51:42 -07003471 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003472
3473 // must deregister from sndmonitor first to prevent races
3474 // between the callback and close_stream
3475 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003477 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3478 destroy_offload_callback_thread(out);
3479
3480 if (out->compr_config.codec != NULL)
3481 free(out->compr_config.codec);
3482 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003483
3484 if (adev->voice_tx_output == out)
3485 adev->voice_tx_output = NULL;
3486
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003487 pthread_cond_destroy(&out->cond);
3488 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003490 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491}
3492
3493static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3494{
3495 struct audio_device *adev = (struct audio_device *)dev;
3496 struct str_parms *parms;
3497 char *str;
3498 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003499 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003500 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003501 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502
Joe Onorato188b6222016-03-01 11:02:27 -08003503 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003504
3505 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506
3507 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003508 status = voice_set_parameters(adev, parms);
3509 if (status != 0) {
3510 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511 }
3512
3513 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3514 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003515 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3517 adev->bluetooth_nrec = true;
3518 else
3519 adev->bluetooth_nrec = false;
3520 }
3521
3522 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3523 if (ret >= 0) {
3524 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3525 adev->screen_off = false;
3526 else
3527 adev->screen_off = true;
3528 }
3529
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003530 ret = str_parms_get_int(parms, "rotation", &val);
3531 if (ret >= 0) {
3532 bool reverse_speakers = false;
3533 switch(val) {
3534 // FIXME: note that the code below assumes that the speakers are in the correct placement
3535 // relative to the user when the device is rotated 90deg from its default rotation. This
3536 // assumption is device-specific, not platform-specific like this code.
3537 case 270:
3538 reverse_speakers = true;
3539 break;
3540 case 0:
3541 case 90:
3542 case 180:
3543 break;
3544 default:
3545 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003546 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003547 }
Eric Laurent03f09432014-03-25 18:09:11 -07003548 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003549 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003550 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003551 }
3552
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003553 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3554 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003555 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003556 }
3557
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003558 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003559done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003561 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003562 ALOGV("%s: exit with code(%d)", __func__, status);
3563 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564}
3565
3566static char* adev_get_parameters(const struct audio_hw_device *dev,
3567 const char *keys)
3568{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003569 struct audio_device *adev = (struct audio_device *)dev;
3570 struct str_parms *reply = str_parms_create();
3571 struct str_parms *query = str_parms_create_str(keys);
3572 char *str;
3573
3574 pthread_mutex_lock(&adev->lock);
3575
3576 voice_get_parameters(adev, query, reply);
3577 str = str_parms_to_str(reply);
3578 str_parms_destroy(query);
3579 str_parms_destroy(reply);
3580
3581 pthread_mutex_unlock(&adev->lock);
3582 ALOGV("%s: exit: returns - %s", __func__, str);
3583 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003584}
3585
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003586static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587{
3588 return 0;
3589}
3590
Haynes Mathew George5191a852013-09-11 14:19:36 -07003591static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3592{
3593 int ret;
3594 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003595
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003596 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3597
Haynes Mathew George5191a852013-09-11 14:19:36 -07003598 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003599 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003600 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003601
Haynes Mathew George5191a852013-09-11 14:19:36 -07003602 return ret;
3603}
3604
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003605static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606{
3607 return -ENOSYS;
3608}
3609
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003610static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3611 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612{
3613 return -ENOSYS;
3614}
3615
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003616static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617{
3618 return -ENOSYS;
3619}
3620
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003621static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622{
3623 return -ENOSYS;
3624}
3625
3626static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3627{
3628 struct audio_device *adev = (struct audio_device *)dev;
3629
3630 pthread_mutex_lock(&adev->lock);
3631 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003632 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003634 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3635 voice_is_in_call(adev)) {
3636 voice_stop_call(adev);
3637 adev->current_call_output = NULL;
3638 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639 }
3640 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003641
3642 audio_extn_extspk_set_mode(adev->extspk, mode);
3643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003644 return 0;
3645}
3646
3647static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3648{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003649 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651
Eric Laurent2bafff12016-03-17 12:17:23 -07003652 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003653 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003654 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3655 ret = audio_extn_hfp_set_mic_mute(adev, state);
3656 } else {
3657 ret = voice_set_mic_mute(adev, state);
3658 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003659 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003660 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003661
3662 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663}
3664
3665static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3666{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003667 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668 return 0;
3669}
3670
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003671static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672 const struct audio_config *config)
3673{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003674 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003676 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3677 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678}
3679
3680static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003681 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682 audio_devices_t devices,
3683 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003684 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003685 audio_input_flags_t flags,
3686 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003687 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688{
3689 struct audio_device *adev = (struct audio_device *)dev;
3690 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003691 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003692 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003693 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694
Eric Laurent994a6932013-07-17 11:51:42 -07003695 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696 *stream_in = NULL;
3697 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3698 return -EINVAL;
3699
Zheng Zhang6185d572016-12-01 20:35:17 +08003700 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 -08003701 return -EINVAL;
3702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3704
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003705 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003706 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003707
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708 in->stream.common.get_sample_rate = in_get_sample_rate;
3709 in->stream.common.set_sample_rate = in_set_sample_rate;
3710 in->stream.common.get_buffer_size = in_get_buffer_size;
3711 in->stream.common.get_channels = in_get_channels;
3712 in->stream.common.get_format = in_get_format;
3713 in->stream.common.set_format = in_set_format;
3714 in->stream.common.standby = in_standby;
3715 in->stream.common.dump = in_dump;
3716 in->stream.common.set_parameters = in_set_parameters;
3717 in->stream.common.get_parameters = in_get_parameters;
3718 in->stream.common.add_audio_effect = in_add_audio_effect;
3719 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3720 in->stream.set_gain = in_set_gain;
3721 in->stream.read = in_read;
3722 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003723 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724
3725 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003726 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003728 in->standby = 1;
3729 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003730 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003731 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732
vivek mehta57ff9b52016-04-28 14:13:08 -07003733 // restrict 24 bit capture for unprocessed source only
3734 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3735 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003736 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003737 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3738 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3739 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3740 bool ret_error = false;
3741 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3742 from HAL is 8_24
3743 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3744 8_24 return error indicating supported format is 8_24
3745 *> In case of any other source requesting 24 bit or float return error
3746 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003747
vivek mehta57ff9b52016-04-28 14:13:08 -07003748 on error flinger will retry with supported format passed
3749 */
3750 if (source != AUDIO_SOURCE_UNPROCESSED) {
3751 config->format = AUDIO_FORMAT_PCM_16_BIT;
3752 ret_error = true;
3753 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3754 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3755 ret_error = true;
3756 }
3757
3758 if (ret_error) {
3759 ret = -EINVAL;
3760 goto err_open;
3761 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003762 }
3763
vivek mehta57ff9b52016-04-28 14:13:08 -07003764 in->format = config->format;
3765
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003767 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3768 if (config->sample_rate == 0)
3769 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3770 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3771 config->sample_rate != 8000) {
3772 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3773 ret = -EINVAL;
3774 goto err_open;
3775 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003776
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003777 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3778 config->format = AUDIO_FORMAT_PCM_16_BIT;
3779 ret = -EINVAL;
3780 goto err_open;
3781 }
3782
3783 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3784 in->config = pcm_config_afe_proxy_record;
3785 } else {
3786 in->usecase = USECASE_AUDIO_RECORD;
3787 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08003788 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003789 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003790#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003791 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003792#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003793 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003794 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08003795 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003796 frame_size = audio_stream_in_frame_size(&in->stream);
3797 buffer_size = get_input_buffer_size(config->sample_rate,
3798 config->format,
3799 channel_count,
3800 is_low_latency);
3801 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003802 in->config.rate = config->sample_rate;
3803 in->af_period_multiplier = 1;
3804 } else {
3805 // period size is left untouched for rt mode playback
3806 in->config = pcm_config_audio_capture_rt;
3807 in->af_period_multiplier = af_period_multiplier;
3808 }
3809 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
3810 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
3811 in->usecase = USECASE_AUDIO_RECORD_MMAP;
3812 in->config = pcm_config_mmap_capture;
3813 in->stream.start = in_start;
3814 in->stream.stop = in_stop;
3815 in->stream.create_mmap_buffer = in_create_mmap_buffer;
3816 in->stream.get_mmap_position = in_get_mmap_position;
3817 in->af_period_multiplier = 1;
3818 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
3819 } else {
3820 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003821 frame_size = audio_stream_in_frame_size(&in->stream);
3822 buffer_size = get_input_buffer_size(config->sample_rate,
3823 config->format,
3824 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003825 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003826 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003827 in->config.rate = config->sample_rate;
3828 in->af_period_multiplier = 1;
3829 }
3830 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3831 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003832 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003833
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003834 in->config.channels = channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003836 /* This stream could be for sound trigger lab,
3837 get sound trigger pcm if present */
3838 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003840 lock_input_stream(in);
3841 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3842 pthread_mutex_lock(&adev->lock);
3843 in->card_status = adev->card_status;
3844 pthread_mutex_unlock(&adev->lock);
3845 pthread_mutex_unlock(&in->lock);
3846
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003847 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003848 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849 return 0;
3850
3851err_open:
3852 free(in);
3853 *stream_in = NULL;
3854 return ret;
3855}
3856
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003857static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003858 struct audio_stream_in *stream)
3859{
Eric Laurent994a6932013-07-17 11:51:42 -07003860 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003861
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003862 // must deregister from sndmonitor first to prevent races
3863 // between the callback and close_stream
3864 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003865 in_standby(&stream->common);
3866 free(stream);
3867
3868 return;
3869}
3870
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003871static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003872{
3873 return 0;
3874}
3875
Andy Hung31aca912014-03-20 17:14:59 -07003876/* verifies input and output devices and their capabilities.
3877 *
3878 * This verification is required when enabling extended bit-depth or
3879 * sampling rates, as not all qcom products support it.
3880 *
3881 * Suitable for calling only on initialization such as adev_open().
3882 * It fills the audio_device use_case_table[] array.
3883 *
3884 * Has a side-effect that it needs to configure audio routing / devices
3885 * in order to power up the devices and read the device parameters.
3886 * It does not acquire any hw device lock. Should restore the devices
3887 * back to "normal state" upon completion.
3888 */
3889static int adev_verify_devices(struct audio_device *adev)
3890{
3891 /* enumeration is a bit difficult because one really wants to pull
3892 * the use_case, device id, etc from the hidden pcm_device_table[].
3893 * In this case there are the following use cases and device ids.
3894 *
3895 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3896 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3897 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3898 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3899 * [USECASE_AUDIO_RECORD] = {0, 0},
3900 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3901 * [USECASE_VOICE_CALL] = {2, 2},
3902 *
3903 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3904 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3905 */
3906
3907 /* should be the usecases enabled in adev_open_input_stream() */
3908 static const int test_in_usecases[] = {
3909 USECASE_AUDIO_RECORD,
3910 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3911 };
3912 /* should be the usecases enabled in adev_open_output_stream()*/
3913 static const int test_out_usecases[] = {
3914 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3915 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3916 };
3917 static const usecase_type_t usecase_type_by_dir[] = {
3918 PCM_PLAYBACK,
3919 PCM_CAPTURE,
3920 };
3921 static const unsigned flags_by_dir[] = {
3922 PCM_OUT,
3923 PCM_IN,
3924 };
3925
3926 size_t i;
3927 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003928 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003929 char info[512]; /* for possible debug info */
3930
3931 for (dir = 0; dir < 2; ++dir) {
3932 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3933 const unsigned flags_dir = flags_by_dir[dir];
3934 const size_t testsize =
3935 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3936 const int *testcases =
3937 dir ? test_in_usecases : test_out_usecases;
3938 const audio_devices_t audio_device =
3939 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3940
3941 for (i = 0; i < testsize; ++i) {
3942 const audio_usecase_t audio_usecase = testcases[i];
3943 int device_id;
3944 snd_device_t snd_device;
3945 struct pcm_params **pparams;
3946 struct stream_out out;
3947 struct stream_in in;
3948 struct audio_usecase uc_info;
3949 int retval;
3950
3951 pparams = &adev->use_case_table[audio_usecase];
3952 pcm_params_free(*pparams); /* can accept null input */
3953 *pparams = NULL;
3954
3955 /* find the device ID for the use case (signed, for error) */
3956 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3957 if (device_id < 0)
3958 continue;
3959
3960 /* prepare structures for device probing */
3961 memset(&uc_info, 0, sizeof(uc_info));
3962 uc_info.id = audio_usecase;
3963 uc_info.type = usecase_type;
3964 if (dir) {
3965 adev->active_input = &in;
3966 memset(&in, 0, sizeof(in));
3967 in.device = audio_device;
3968 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3969 uc_info.stream.in = &in;
3970 } else {
3971 adev->active_input = NULL;
3972 }
3973 memset(&out, 0, sizeof(out));
3974 out.devices = audio_device; /* only field needed in select_devices */
3975 uc_info.stream.out = &out;
3976 uc_info.devices = audio_device;
3977 uc_info.in_snd_device = SND_DEVICE_NONE;
3978 uc_info.out_snd_device = SND_DEVICE_NONE;
3979 list_add_tail(&adev->usecase_list, &uc_info.list);
3980
3981 /* select device - similar to start_(in/out)put_stream() */
3982 retval = select_devices(adev, audio_usecase);
3983 if (retval >= 0) {
3984 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3985#if LOG_NDEBUG == 0
3986 if (*pparams) {
3987 ALOGV("%s: (%s) card %d device %d", __func__,
3988 dir ? "input" : "output", card_id, device_id);
3989 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07003990 } else {
3991 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3992 }
3993#endif
3994 }
3995
3996 /* deselect device - similar to stop_(in/out)put_stream() */
3997 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07003998 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07003999 /* 2. Disable the rx device */
4000 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004001 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004002 list_remove(&uc_info.list);
4003 }
4004 }
4005 adev->active_input = NULL; /* restore adev state */
4006 return 0;
4007}
4008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004009static int adev_close(hw_device_t *device)
4010{
Andy Hung31aca912014-03-20 17:14:59 -07004011 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004012 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004013
4014 if (!adev)
4015 return 0;
4016
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004017 audio_extn_tfa_98xx_deinit();
4018
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004019 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004020 pthread_mutex_lock(&adev_init_lock);
4021
4022 if ((--audio_device_ref_count) == 0) {
4023 audio_route_free(adev->audio_route);
4024 free(adev->snd_dev_ref_cnt);
4025 platform_deinit(adev->platform);
4026 audio_extn_extspk_deinit(adev->extspk);
4027 audio_extn_sound_trigger_deinit(adev);
4028 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4029 pcm_params_free(adev->use_case_table[i]);
4030 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004031 if (adev->adm_deinit)
4032 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004033 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004034 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004035
4036 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004037
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004038 return 0;
4039}
4040
Glenn Kasten4f993392014-05-14 07:30:48 -07004041/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4042 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4043 * just that it _might_ work.
4044 */
4045static int period_size_is_plausible_for_low_latency(int period_size)
4046{
4047 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004048 case 48:
4049 case 96:
4050 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004051 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004052 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004053 case 240:
4054 case 320:
4055 case 480:
4056 return 1;
4057 default:
4058 return 0;
4059 }
4060}
4061
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004062static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4063{
4064 int card;
4065 card_status_t status;
4066
4067 if (!parms)
4068 return;
4069
4070 if (parse_snd_card_status(parms, &card, &status) < 0)
4071 return;
4072
4073 pthread_mutex_lock(&adev->lock);
4074 bool valid_cb = (card == adev->snd_card);
4075 if (valid_cb) {
4076 if (adev->card_status != status) {
4077 adev->card_status = status;
4078 platform_snd_card_update(adev->platform, status);
4079 }
4080 }
4081 pthread_mutex_unlock(&adev->lock);
4082 return;
4083}
4084
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085static int adev_open(const hw_module_t *module, const char *name,
4086 hw_device_t **device)
4087{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004088 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089
Eric Laurent2bafff12016-03-17 12:17:23 -07004090 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004091 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004092 pthread_mutex_lock(&adev_init_lock);
4093 if (audio_device_ref_count != 0) {
4094 *device = &adev->device.common;
4095 audio_device_ref_count++;
4096 ALOGV("%s: returning existing instance of adev", __func__);
4097 ALOGV("%s: exit", __func__);
4098 pthread_mutex_unlock(&adev_init_lock);
4099 return 0;
4100 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004101 adev = calloc(1, sizeof(struct audio_device));
4102
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004103 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004105 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4106 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4107 adev->device.common.module = (struct hw_module_t *)module;
4108 adev->device.common.close = adev_close;
4109
4110 adev->device.init_check = adev_init_check;
4111 adev->device.set_voice_volume = adev_set_voice_volume;
4112 adev->device.set_master_volume = adev_set_master_volume;
4113 adev->device.get_master_volume = adev_get_master_volume;
4114 adev->device.set_master_mute = adev_set_master_mute;
4115 adev->device.get_master_mute = adev_get_master_mute;
4116 adev->device.set_mode = adev_set_mode;
4117 adev->device.set_mic_mute = adev_set_mic_mute;
4118 adev->device.get_mic_mute = adev_get_mic_mute;
4119 adev->device.set_parameters = adev_set_parameters;
4120 adev->device.get_parameters = adev_get_parameters;
4121 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4122 adev->device.open_output_stream = adev_open_output_stream;
4123 adev->device.close_output_stream = adev_close_output_stream;
4124 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004126 adev->device.close_input_stream = adev_close_input_stream;
4127 adev->device.dump = adev_dump;
4128
4129 /* Set the default route before the PCM stream is opened */
4130 pthread_mutex_lock(&adev->lock);
4131 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004132 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004133 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004134 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004135 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004136 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004137 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004138 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004139 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140 pthread_mutex_unlock(&adev->lock);
4141
4142 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004143 adev->platform = platform_init(adev);
4144 if (!adev->platform) {
4145 free(adev->snd_dev_ref_cnt);
4146 free(adev);
4147 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4148 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004149 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004150 return -EINVAL;
4151 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004152 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004153 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004154
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004155 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4156 if (adev->visualizer_lib == NULL) {
4157 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4158 } else {
4159 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4160 adev->visualizer_start_output =
4161 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4162 "visualizer_hal_start_output");
4163 adev->visualizer_stop_output =
4164 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4165 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004166 }
4167
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004168 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4169 if (adev->offload_effects_lib == NULL) {
4170 ALOGW("%s: DLOPEN failed for %s", __func__,
4171 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4172 } else {
4173 ALOGV("%s: DLOPEN successful for %s", __func__,
4174 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4175 adev->offload_effects_start_output =
4176 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4177 "offload_effects_bundle_hal_start_output");
4178 adev->offload_effects_stop_output =
4179 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4180 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004181 }
4182
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004183 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4184 if (adev->adm_lib == NULL) {
4185 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4186 } else {
4187 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4188 adev->adm_init = (adm_init_t)
4189 dlsym(adev->adm_lib, "adm_init");
4190 adev->adm_deinit = (adm_deinit_t)
4191 dlsym(adev->adm_lib, "adm_deinit");
4192 adev->adm_register_input_stream = (adm_register_input_stream_t)
4193 dlsym(adev->adm_lib, "adm_register_input_stream");
4194 adev->adm_register_output_stream = (adm_register_output_stream_t)
4195 dlsym(adev->adm_lib, "adm_register_output_stream");
4196 adev->adm_deregister_stream = (adm_deregister_stream_t)
4197 dlsym(adev->adm_lib, "adm_deregister_stream");
4198 adev->adm_request_focus = (adm_request_focus_t)
4199 dlsym(adev->adm_lib, "adm_request_focus");
4200 adev->adm_abandon_focus = (adm_abandon_focus_t)
4201 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004202 adev->adm_set_config = (adm_set_config_t)
4203 dlsym(adev->adm_lib, "adm_set_config");
4204 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4205 dlsym(adev->adm_lib, "adm_request_focus_v2");
4206 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4207 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4208 adev->adm_on_routing_change = (adm_on_routing_change_t)
4209 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004210 }
4211
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004212 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004213 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004214
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004215 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004216
Andy Hung31aca912014-03-20 17:14:59 -07004217 if (k_enable_extended_precision)
4218 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004219
Glenn Kasten4f993392014-05-14 07:30:48 -07004220 char value[PROPERTY_VALUE_MAX];
4221 int trial;
4222 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4223 trial = atoi(value);
4224 if (period_size_is_plausible_for_low_latency(trial)) {
4225 pcm_config_low_latency.period_size = trial;
4226 pcm_config_low_latency.start_threshold = trial / 4;
4227 pcm_config_low_latency.avail_min = trial / 4;
4228 configured_low_latency_capture_period_size = trial;
4229 }
4230 }
4231 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4232 trial = atoi(value);
4233 if (period_size_is_plausible_for_low_latency(trial)) {
4234 configured_low_latency_capture_period_size = trial;
4235 }
4236 }
4237
Yamit Mehtae3b99562016-09-16 22:44:00 +05304238 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004239 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004240
4241 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4242 af_period_multiplier = atoi(value);
4243 if (af_period_multiplier < 0) {
4244 af_period_multiplier = 2;
4245 } else if (af_period_multiplier > 4) {
4246 af_period_multiplier = 4;
4247 }
4248 ALOGV("new period_multiplier = %d", af_period_multiplier);
4249 }
4250
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004251 audio_extn_tfa_98xx_init(adev);
4252
vivek mehta1a9b7c02015-06-25 11:49:38 -07004253 pthread_mutex_unlock(&adev_init_lock);
4254
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004255 if (adev->adm_init)
4256 adev->adm_data = adev->adm_init();
4257
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004258 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004259 audio_extn_snd_mon_init();
4260 pthread_mutex_lock(&adev->lock);
4261 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4262 adev->card_status = CARD_STATUS_ONLINE;
4263 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004264
Eric Laurent2bafff12016-03-17 12:17:23 -07004265 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004266 return 0;
4267}
4268
4269static struct hw_module_methods_t hal_module_methods = {
4270 .open = adev_open,
4271};
4272
4273struct audio_module HAL_MODULE_INFO_SYM = {
4274 .common = {
4275 .tag = HARDWARE_MODULE_TAG,
4276 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4277 .hal_api_version = HARDWARE_HAL_API_VERSION,
4278 .id = AUDIO_HARDWARE_MODULE_ID,
4279 .name = "QCOM Audio HAL",
4280 .author = "Code Aurora Forum",
4281 .methods = &hal_module_methods,
4282 },
4283};