blob: 4af1e9cfd7eaa0616107096ef6765b9ffb5eb64e [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
David Lin8c03e672017-02-06 20:31:38 -0800858 platform_check_and_set_playback_backend_cfg(adev, uc_info, snd_device);
859
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700860 /*
861 * This function is to make sure that all the usecases that are active on
862 * the hardware codec backend are always routed to any one device that is
863 * handled by the hardware codec.
864 * For example, if low-latency and deep-buffer usecases are currently active
865 * on speaker and out_set_parameters(headset) is received on low-latency
866 * output, then we have to make sure deep-buffer is also switched to headset,
867 * because of the limitation that both the devices cannot be enabled
868 * at the same time as they share the same backend.
869 */
870 /* Disable all the usecases on the shared backend other than the
871 specified usecase */
872 for (i = 0; i < AUDIO_USECASE_MAX; i++)
873 switch_device[i] = false;
874
875 list_for_each(node, &adev->usecase_list) {
876 usecase = node_to_item(node, struct audio_usecase, list);
877 if (usecase->type != PCM_CAPTURE &&
878 usecase != uc_info &&
879 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700880 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
881 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
883 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700884 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700885 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700886 switch_device[usecase->id] = true;
887 num_uc_to_switch++;
888 }
889 }
890
891 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700892 list_for_each(node, &adev->usecase_list) {
893 usecase = node_to_item(node, struct audio_usecase, list);
894 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700895 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900896 }
897 }
898
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700899 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900900 list_for_each(node, &adev->usecase_list) {
901 usecase = node_to_item(node, struct audio_usecase, list);
902 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700903 d_device = derive_playback_snd_device(usecase, uc_info,
904 snd_device);
905 enable_snd_device(adev, d_device);
906 /* Update the out_snd_device before enabling the audio route */
907 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700908 }
909 }
910
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700911 /* Re-route all the usecases on the shared backend other than the
912 specified usecase to new snd devices */
913 list_for_each(node, &adev->usecase_list) {
914 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700915 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700916 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700917 }
918 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700919 }
920}
921
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700922static void check_and_route_capture_usecases(struct audio_device *adev,
923 struct audio_usecase *uc_info,
924 snd_device_t snd_device)
925{
926 struct listnode *node;
927 struct audio_usecase *usecase;
928 bool switch_device[AUDIO_USECASE_MAX];
929 int i, num_uc_to_switch = 0;
930
vivek mehta4ed66e62016-04-15 23:33:34 -0700931 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
932
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700933 /*
934 * This function is to make sure that all the active capture usecases
935 * are always routed to the same input sound device.
936 * For example, if audio-record and voice-call usecases are currently
937 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
938 * is received for voice call then we have to make sure that audio-record
939 * usecase is also switched to earpiece i.e. voice-dmic-ef,
940 * because of the limitation that two devices cannot be enabled
941 * at the same time if they share the same backend.
942 */
943 for (i = 0; i < AUDIO_USECASE_MAX; i++)
944 switch_device[i] = false;
945
946 list_for_each(node, &adev->usecase_list) {
947 usecase = node_to_item(node, struct audio_usecase, list);
948 if (usecase->type != PCM_PLAYBACK &&
949 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700950 usecase->in_snd_device != snd_device &&
951 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700952 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
953 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700954 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700955 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700956 switch_device[usecase->id] = true;
957 num_uc_to_switch++;
958 }
959 }
960
961 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700962 list_for_each(node, &adev->usecase_list) {
963 usecase = node_to_item(node, struct audio_usecase, list);
964 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700965 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700966 }
967 }
968
969 list_for_each(node, &adev->usecase_list) {
970 usecase = node_to_item(node, struct audio_usecase, list);
971 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700972 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700973 }
974 }
975
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700976 /* Re-route all the usecases on the shared backend other than the
977 specified usecase to new snd devices */
978 list_for_each(node, &adev->usecase_list) {
979 usecase = node_to_item(node, struct audio_usecase, list);
980 /* Update the in_snd_device only before enabling the audio route */
981 if (switch_device[usecase->id] ) {
982 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700983 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700984 }
985 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700986 }
987}
988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800989/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700990static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800991{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700992 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700993 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800994
995 switch (channels) {
996 /*
997 * Do not handle stereo output in Multi-channel cases
998 * Stereo case is handled in normal playback path
999 */
1000 case 6:
1001 ALOGV("%s: HDMI supports 5.1", __func__);
1002 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1003 break;
1004 case 8:
1005 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1006 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1007 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1008 break;
1009 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001010 ALOGE("HDMI does not support multi channel playback");
1011 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001012 break;
1013 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001014 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001015}
1016
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001017static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1018{
1019 struct audio_usecase *usecase;
1020 struct listnode *node;
1021
1022 list_for_each(node, &adev->usecase_list) {
1023 usecase = node_to_item(node, struct audio_usecase, list);
1024 if (usecase->type == VOICE_CALL) {
1025 ALOGV("%s: usecase id %d", __func__, usecase->id);
1026 return usecase->id;
1027 }
1028 }
1029 return USECASE_INVALID;
1030}
1031
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001032struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1033 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001034{
1035 struct audio_usecase *usecase;
1036 struct listnode *node;
1037
1038 list_for_each(node, &adev->usecase_list) {
1039 usecase = node_to_item(node, struct audio_usecase, list);
1040 if (usecase->id == uc_id)
1041 return usecase;
1042 }
1043 return NULL;
1044}
1045
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001046int select_devices(struct audio_device *adev,
1047 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001048{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001049 snd_device_t out_snd_device = SND_DEVICE_NONE;
1050 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001051 struct audio_usecase *usecase = NULL;
1052 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001053 struct audio_usecase *hfp_usecase = NULL;
1054 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001055 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001056 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001057
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001058 usecase = get_usecase_from_list(adev, uc_id);
1059 if (usecase == NULL) {
1060 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1061 return -EINVAL;
1062 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001064 if ((usecase->type == VOICE_CALL) ||
1065 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001066 out_snd_device = platform_get_output_snd_device(adev->platform,
1067 usecase->stream.out->devices);
1068 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001069 usecase->devices = usecase->stream.out->devices;
1070 } else {
1071 /*
1072 * If the voice call is active, use the sound devices of voice call usecase
1073 * so that it would not result any device switch. All the usecases will
1074 * be switched to new device when select_devices() is called for voice call
1075 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001076 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001077 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001078 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001079 vc_usecase = get_usecase_from_list(adev,
1080 get_voice_usecase_id_from_list(adev));
1081 if ((vc_usecase != NULL) &&
1082 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1083 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001084 in_snd_device = vc_usecase->in_snd_device;
1085 out_snd_device = vc_usecase->out_snd_device;
1086 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001087 } else if (audio_extn_hfp_is_active(adev)) {
1088 hfp_ucid = audio_extn_hfp_get_usecase();
1089 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1090 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1091 in_snd_device = hfp_usecase->in_snd_device;
1092 out_snd_device = hfp_usecase->out_snd_device;
1093 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001094 }
1095 if (usecase->type == PCM_PLAYBACK) {
1096 usecase->devices = usecase->stream.out->devices;
1097 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001098 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001099 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001100 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001101 if (usecase->stream.out == adev->primary_output &&
1102 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001103 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1104 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001105 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001106 select_devices(adev, adev->active_input->usecase);
1107 }
1108 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001109 } else if (usecase->type == PCM_CAPTURE) {
1110 usecase->devices = usecase->stream.in->device;
1111 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001112 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001113 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001114 if (adev->active_input &&
1115 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1116 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001117 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001118 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1119 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1120 } else if (adev->primary_output) {
1121 out_device = adev->primary_output->devices;
1122 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001123 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001124 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001125 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001126 }
1127 }
1128
1129 if (out_snd_device == usecase->out_snd_device &&
1130 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001131 return 0;
1132 }
1133
Eric Laurent2bafff12016-03-17 12:17:23 -07001134 if (out_snd_device != SND_DEVICE_NONE &&
1135 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1136 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1137 __func__,
1138 use_case_table[uc_id],
1139 adev->last_logged_snd_device[uc_id][0],
1140 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1141 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1142 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1143 -1,
1144 out_snd_device,
1145 platform_get_snd_device_name(out_snd_device),
1146 platform_get_snd_device_acdb_id(out_snd_device));
1147 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1148 }
1149 if (in_snd_device != SND_DEVICE_NONE &&
1150 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1151 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1152 __func__,
1153 use_case_table[uc_id],
1154 adev->last_logged_snd_device[uc_id][1],
1155 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1156 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1157 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1158 -1,
1159 in_snd_device,
1160 platform_get_snd_device_name(in_snd_device),
1161 platform_get_snd_device_acdb_id(in_snd_device));
1162 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1163 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001164
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001165 /*
1166 * Limitation: While in call, to do a device switch we need to disable
1167 * and enable both RX and TX devices though one of them is same as current
1168 * device.
1169 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001170 if ((usecase->type == VOICE_CALL) &&
1171 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1172 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001173 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001174 /* Disable sidetone only if voice call already exists */
1175 if (voice_is_call_state_active(adev))
1176 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001177 }
1178
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001179 /* Disable current sound devices */
1180 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001181 disable_audio_route(adev, usecase);
1182 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001183 }
1184
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001185 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001186 disable_audio_route(adev, usecase);
1187 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001188 }
1189
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001190 /* Applicable only on the targets that has external modem.
1191 * New device information should be sent to modem before enabling
1192 * the devices to reduce in-call device switch time.
1193 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001194 if ((usecase->type == VOICE_CALL) &&
1195 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1196 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001197 status = platform_switch_voice_call_enable_device_config(adev->platform,
1198 out_snd_device,
1199 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001200 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001201
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001202 /* Enable new sound devices */
1203 if (out_snd_device != SND_DEVICE_NONE) {
David Lin8c03e672017-02-06 20:31:38 -08001204 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1205 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001206 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001207 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001208 }
1209
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001210 if (in_snd_device != SND_DEVICE_NONE) {
1211 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001212 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001213 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001214
Eric Laurentb23d5282013-05-14 15:27:20 -07001215 if (usecase->type == VOICE_CALL)
1216 status = platform_switch_voice_call_device_post(adev->platform,
1217 out_snd_device,
1218 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001219
sangwoo170731f2013-06-08 15:36:36 +09001220 usecase->in_snd_device = in_snd_device;
1221 usecase->out_snd_device = out_snd_device;
1222
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001223 audio_extn_tfa_98xx_set_mode();
1224
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001225 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001226
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001227 /* Applicable only on the targets that has external modem.
1228 * Enable device command should be sent to modem only after
1229 * enabling voice call mixer controls
1230 */
vivek mehta765eb642015-08-07 19:46:06 -07001231 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001232 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1233 out_snd_device,
1234 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001235 /* Enable sidetone only if voice call already exists */
1236 if (voice_is_call_state_active(adev))
1237 voice_set_sidetone(adev, out_snd_device, true);
1238 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001240 return status;
1241}
1242
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001243static int stop_input_stream(struct stream_in *in)
1244{
1245 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001246 struct audio_usecase *uc_info;
1247 struct audio_device *adev = in->dev;
1248
Eric Laurentc8400632013-02-14 19:04:54 -08001249 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001250
Eric Laurent994a6932013-07-17 11:51:42 -07001251 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001252 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001253 uc_info = get_usecase_from_list(adev, in->usecase);
1254 if (uc_info == NULL) {
1255 ALOGE("%s: Could not find the usecase (%d) in the list",
1256 __func__, in->usecase);
1257 return -EINVAL;
1258 }
1259
Eric Laurent150dbfe2013-02-27 14:31:02 -08001260 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001261 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001262
1263 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001264 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001265
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001266 list_remove(&uc_info->list);
1267 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001268
Eric Laurent994a6932013-07-17 11:51:42 -07001269 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001270 return ret;
1271}
1272
1273int start_input_stream(struct stream_in *in)
1274{
1275 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001276 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001277 struct audio_usecase *uc_info;
1278 struct audio_device *adev = in->dev;
1279
Eric Laurent994a6932013-07-17 11:51:42 -07001280 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001281
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001282 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1283 return -EIO;
1284
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001285 if (in->card_status == CARD_STATUS_OFFLINE ||
1286 adev->card_status == CARD_STATUS_OFFLINE) {
1287 ALOGW("in->card_status or adev->card_status offline, try again");
1288 ret = -EAGAIN;
1289 goto error_config;
1290 }
1291
Eric Laurentb23d5282013-05-14 15:27:20 -07001292 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001293 if (in->pcm_device_id < 0) {
1294 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1295 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001296 ret = -EINVAL;
1297 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001298 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001299
1300 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001301 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1302 uc_info->id = in->usecase;
1303 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001304 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001305 uc_info->devices = in->device;
1306 uc_info->in_snd_device = SND_DEVICE_NONE;
1307 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001308
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001309 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001310
1311 audio_extn_perf_lock_acquire();
1312
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001313 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001314
Eric Laurent0e46adf2016-12-16 12:49:24 -08001315 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
1316 if (!pcm_is_ready(in->pcm)) {
1317 ALOGE("%s: pcm stream not ready", __func__);
1318 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001319 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001320 ret = pcm_prepare(in->pcm);
1321 if (ret < 0) {
1322 ALOGE("%s: MMAP pcm_prepare failed ret %d", __func__, ret);
1323 goto error_open; }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001324 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001325 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001326 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1327 goto error_open;
1328 }
1329 } else {
1330 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1331 unsigned int pcm_open_retry_count = 0;
1332
1333 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1334 flags |= PCM_MMAP | PCM_NOIRQ;
1335 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1336 } else if (in->realtime) {
1337 flags |= PCM_MMAP | PCM_NOIRQ;
1338 }
1339
1340 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1341 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1342
1343 while (1) {
1344 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1345 flags, &in->config);
1346 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1347 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1348 if (in->pcm != NULL) {
1349 pcm_close(in->pcm);
1350 in->pcm = NULL;
1351 }
1352 if (pcm_open_retry_count-- == 0) {
1353 ret = -EIO;
1354 goto error_open;
1355 }
1356 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1357 continue;
1358 }
1359 break;
1360 }
1361
1362 ALOGV("%s: pcm_prepare", __func__);
1363 ret = pcm_prepare(in->pcm);
1364 if (ret < 0) {
1365 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001366 pcm_close(in->pcm);
1367 in->pcm = NULL;
1368 goto error_open;
1369 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001370 if (in->realtime) {
1371 ret = pcm_start(in->pcm);
1372 if (ret < 0) {
1373 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1374 pcm_close(in->pcm);
1375 in->pcm = NULL;
1376 goto error_open;
1377 }
1378 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001379 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001380 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001381 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001382 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001383
Eric Laurent0e46adf2016-12-16 12:49:24 -08001384 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001385
1386error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001387 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001388 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001389
1390error_config:
1391 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001392 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001393
1394 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001395}
1396
Eric Laurenta1478072015-09-21 17:21:52 -07001397void lock_input_stream(struct stream_in *in)
1398{
1399 pthread_mutex_lock(&in->pre_lock);
1400 pthread_mutex_lock(&in->lock);
1401 pthread_mutex_unlock(&in->pre_lock);
1402}
1403
1404void lock_output_stream(struct stream_out *out)
1405{
1406 pthread_mutex_lock(&out->pre_lock);
1407 pthread_mutex_lock(&out->lock);
1408 pthread_mutex_unlock(&out->pre_lock);
1409}
1410
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001411/* must be called with out->lock locked */
1412static int send_offload_cmd_l(struct stream_out* out, int command)
1413{
1414 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1415
1416 ALOGVV("%s %d", __func__, command);
1417
1418 cmd->cmd = command;
1419 list_add_tail(&out->offload_cmd_list, &cmd->node);
1420 pthread_cond_signal(&out->offload_cond);
1421 return 0;
1422}
1423
1424/* must be called iwth out->lock locked */
1425static void stop_compressed_output_l(struct stream_out *out)
1426{
1427 out->offload_state = OFFLOAD_STATE_IDLE;
1428 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001429 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001430 if (out->compr != NULL) {
1431 compress_stop(out->compr);
1432 while (out->offload_thread_blocked) {
1433 pthread_cond_wait(&out->cond, &out->lock);
1434 }
1435 }
1436}
1437
1438static void *offload_thread_loop(void *context)
1439{
1440 struct stream_out *out = (struct stream_out *) context;
1441 struct listnode *item;
1442
1443 out->offload_state = OFFLOAD_STATE_IDLE;
1444 out->playback_started = 0;
1445
1446 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1447 set_sched_policy(0, SP_FOREGROUND);
1448 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1449
1450 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001451 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001452 for (;;) {
1453 struct offload_cmd *cmd = NULL;
1454 stream_callback_event_t event;
1455 bool send_callback = false;
1456
1457 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1458 __func__, list_empty(&out->offload_cmd_list),
1459 out->offload_state);
1460 if (list_empty(&out->offload_cmd_list)) {
1461 ALOGV("%s SLEEPING", __func__);
1462 pthread_cond_wait(&out->offload_cond, &out->lock);
1463 ALOGV("%s RUNNING", __func__);
1464 continue;
1465 }
1466
1467 item = list_head(&out->offload_cmd_list);
1468 cmd = node_to_item(item, struct offload_cmd, node);
1469 list_remove(item);
1470
1471 ALOGVV("%s STATE %d CMD %d out->compr %p",
1472 __func__, out->offload_state, cmd->cmd, out->compr);
1473
1474 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1475 free(cmd);
1476 break;
1477 }
1478
1479 if (out->compr == NULL) {
1480 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001481 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001482 pthread_cond_signal(&out->cond);
1483 continue;
1484 }
1485 out->offload_thread_blocked = true;
1486 pthread_mutex_unlock(&out->lock);
1487 send_callback = false;
1488 switch(cmd->cmd) {
1489 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1490 compress_wait(out->compr, -1);
1491 send_callback = true;
1492 event = STREAM_CBK_EVENT_WRITE_READY;
1493 break;
1494 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001495 compress_next_track(out->compr);
1496 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001497 send_callback = true;
1498 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001499 /* Resend the metadata for next iteration */
1500 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001501 break;
1502 case OFFLOAD_CMD_DRAIN:
1503 compress_drain(out->compr);
1504 send_callback = true;
1505 event = STREAM_CBK_EVENT_DRAIN_READY;
1506 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001507 case OFFLOAD_CMD_ERROR:
1508 send_callback = true;
1509 event = STREAM_CBK_EVENT_ERROR;
1510 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001511 default:
1512 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1513 break;
1514 }
Eric Laurenta1478072015-09-21 17:21:52 -07001515 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001516 out->offload_thread_blocked = false;
1517 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001518 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001519 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001520 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001521 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001522 free(cmd);
1523 }
1524
1525 pthread_cond_signal(&out->cond);
1526 while (!list_empty(&out->offload_cmd_list)) {
1527 item = list_head(&out->offload_cmd_list);
1528 list_remove(item);
1529 free(node_to_item(item, struct offload_cmd, node));
1530 }
1531 pthread_mutex_unlock(&out->lock);
1532
1533 return NULL;
1534}
1535
1536static int create_offload_callback_thread(struct stream_out *out)
1537{
1538 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1539 list_init(&out->offload_cmd_list);
1540 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1541 offload_thread_loop, out);
1542 return 0;
1543}
1544
1545static int destroy_offload_callback_thread(struct stream_out *out)
1546{
Eric Laurenta1478072015-09-21 17:21:52 -07001547 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001548 stop_compressed_output_l(out);
1549 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1550
1551 pthread_mutex_unlock(&out->lock);
1552 pthread_join(out->offload_thread, (void **) NULL);
1553 pthread_cond_destroy(&out->offload_cond);
1554
1555 return 0;
1556}
1557
Eric Laurent07eeafd2013-10-06 12:52:49 -07001558static bool allow_hdmi_channel_config(struct audio_device *adev)
1559{
1560 struct listnode *node;
1561 struct audio_usecase *usecase;
1562 bool ret = true;
1563
1564 list_for_each(node, &adev->usecase_list) {
1565 usecase = node_to_item(node, struct audio_usecase, list);
1566 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1567 /*
1568 * If voice call is already existing, do not proceed further to avoid
1569 * disabling/enabling both RX and TX devices, CSD calls, etc.
1570 * Once the voice call done, the HDMI channels can be configured to
1571 * max channels of remaining use cases.
1572 */
1573 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001574 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001575 __func__);
1576 ret = false;
1577 break;
1578 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001579 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001580 "no change in HDMI channels", __func__);
1581 ret = false;
1582 break;
1583 }
1584 }
1585 }
1586 return ret;
1587}
1588
1589static int check_and_set_hdmi_channels(struct audio_device *adev,
1590 unsigned int channels)
1591{
1592 struct listnode *node;
1593 struct audio_usecase *usecase;
1594
1595 /* Check if change in HDMI channel config is allowed */
1596 if (!allow_hdmi_channel_config(adev))
1597 return 0;
1598
1599 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001600 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001601 return 0;
1602 }
1603
1604 platform_set_hdmi_channels(adev->platform, channels);
1605 adev->cur_hdmi_channels = channels;
1606
1607 /*
1608 * Deroute all the playback streams routed to HDMI so that
1609 * the back end is deactivated. Note that backend will not
1610 * be deactivated if any one stream is connected to it.
1611 */
1612 list_for_each(node, &adev->usecase_list) {
1613 usecase = node_to_item(node, struct audio_usecase, list);
1614 if (usecase->type == PCM_PLAYBACK &&
1615 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001616 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001617 }
1618 }
1619
1620 /*
1621 * Enable all the streams disabled above. Now the HDMI backend
1622 * will be activated with new channel configuration
1623 */
1624 list_for_each(node, &adev->usecase_list) {
1625 usecase = node_to_item(node, struct audio_usecase, list);
1626 if (usecase->type == PCM_PLAYBACK &&
1627 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001628 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001629 }
1630 }
1631
1632 return 0;
1633}
1634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001635static int stop_output_stream(struct stream_out *out)
1636{
1637 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638 struct audio_usecase *uc_info;
1639 struct audio_device *adev = out->dev;
1640
Eric Laurent994a6932013-07-17 11:51:42 -07001641 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001642 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001643 uc_info = get_usecase_from_list(adev, out->usecase);
1644 if (uc_info == NULL) {
1645 ALOGE("%s: Could not find the usecase (%d) in the list",
1646 __func__, out->usecase);
1647 return -EINVAL;
1648 }
1649
Haynes Mathew George41f86652014-06-17 14:22:15 -07001650 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1651 if (adev->visualizer_stop_output != NULL)
1652 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1653 if (adev->offload_effects_stop_output != NULL)
1654 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1655 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001656
Eric Laurent150dbfe2013-02-27 14:31:02 -08001657 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001658 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001659
1660 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001661 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001663 list_remove(&uc_info->list);
1664 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001665
Eric Laurent0499d4f2014-08-25 22:39:29 -05001666 audio_extn_extspk_update(adev->extspk);
1667
Eric Laurent07eeafd2013-10-06 12:52:49 -07001668 /* Must be called after removing the usecase from list */
1669 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1670 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1671
Eric Laurent994a6932013-07-17 11:51:42 -07001672 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673 return ret;
1674}
1675
1676int start_output_stream(struct stream_out *out)
1677{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679 struct audio_usecase *uc_info;
1680 struct audio_device *adev = out->dev;
1681
Eric Laurent994a6932013-07-17 11:51:42 -07001682 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001683 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001684
1685 if (out->card_status == CARD_STATUS_OFFLINE ||
1686 adev->card_status == CARD_STATUS_OFFLINE) {
1687 ALOGW("out->card_status or adev->card_status offline, try again");
1688 ret = -EAGAIN;
1689 goto error_config;
1690 }
1691
Eric Laurentb23d5282013-05-14 15:27:20 -07001692 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001693 if (out->pcm_device_id < 0) {
1694 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1695 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001696 ret = -EINVAL;
1697 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698 }
1699
1700 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1701 uc_info->id = out->usecase;
1702 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001703 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001704 uc_info->devices = out->devices;
1705 uc_info->in_snd_device = SND_DEVICE_NONE;
1706 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707
Eric Laurent07eeafd2013-10-06 12:52:49 -07001708 /* This must be called before adding this usecase to the list */
1709 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1710 check_and_set_hdmi_channels(adev, out->config.channels);
1711
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001712 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001714 audio_extn_perf_lock_acquire();
1715
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001716 select_devices(adev, out->usecase);
1717
Eric Laurent0499d4f2014-08-25 22:39:29 -05001718 audio_extn_extspk_update(adev->extspk);
1719
Andy Hung31aca912014-03-20 17:14:59 -07001720 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001721 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001722 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1723 out->pcm = NULL;
1724 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1725 COMPRESS_IN, &out->compr_config);
1726 if (out->compr && !is_compress_ready(out->compr)) {
1727 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1728 compress_close(out->compr);
1729 out->compr = NULL;
1730 ret = -EIO;
1731 goto error_open;
1732 }
1733 if (out->offload_callback)
1734 compress_nonblock(out->compr, out->non_blocking);
1735
1736 if (adev->visualizer_start_output != NULL)
1737 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1738 if (adev->offload_effects_start_output != NULL)
1739 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1740 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1741 if (!pcm_is_ready(out->pcm)) {
1742 ALOGE("%s: pcm stream not ready", __func__);
1743 goto error_open;
1744 }
1745 ret = pcm_prepare(out->pcm);
1746 if (ret < 0) {
1747 ALOGE("%s: MMAP pcm_prepare failed ret %d", __func__, ret);
1748 goto error_open; }
1749 ret = pcm_start(out->pcm);
1750 if (ret < 0) {
1751 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1752 goto error_open;
1753 }
1754 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001755 unsigned int flags = PCM_OUT;
1756 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001757
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001758 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1759 flags |= PCM_MMAP | PCM_NOIRQ;
1760 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001761 } else if (out->realtime) {
1762 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001763 } else
1764 flags |= PCM_MONOTONIC;
1765
1766 while (1) {
1767 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1768 flags, &out->config);
1769 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1770 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1771 if (out->pcm != NULL) {
1772 pcm_close(out->pcm);
1773 out->pcm = NULL;
1774 }
1775 if (pcm_open_retry_count-- == 0) {
1776 ret = -EIO;
1777 goto error_open;
1778 }
1779 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1780 continue;
1781 }
1782 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001783 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001784 ALOGV("%s: pcm_prepare", __func__);
1785 if (pcm_is_ready(out->pcm)) {
1786 ret = pcm_prepare(out->pcm);
1787 if (ret < 0) {
1788 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1789 pcm_close(out->pcm);
1790 out->pcm = NULL;
1791 goto error_open;
1792 }
1793 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001794 if (out->realtime) {
1795 ret = pcm_start(out->pcm);
1796 if (ret < 0) {
1797 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1798 pcm_close(out->pcm);
1799 out->pcm = NULL;
1800 goto error_open;
1801 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001802 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001803 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001804 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001805 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001806 audio_extn_tfa_98xx_enable_speaker();
1807
Eric Laurent994a6932013-07-17 11:51:42 -07001808 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001809 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001810error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001811 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001813error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001814 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001815}
1816
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001817static int check_input_parameters(uint32_t sample_rate,
1818 audio_format_t format,
1819 int channel_count)
1820{
vivek mehta4ed66e62016-04-15 23:33:34 -07001821 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001822 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1823 return -EINVAL;
1824 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825
vivek mehtadae44712015-07-27 14:13:18 -07001826 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001827 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001828 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1829 return -EINVAL;
1830 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001831
1832 switch (sample_rate) {
1833 case 8000:
1834 case 11025:
1835 case 12000:
1836 case 16000:
1837 case 22050:
1838 case 24000:
1839 case 32000:
1840 case 44100:
1841 case 48000:
1842 break;
1843 default:
vivek mehtadae44712015-07-27 14:13:18 -07001844 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845 return -EINVAL;
1846 }
1847
1848 return 0;
1849}
1850
1851static size_t get_input_buffer_size(uint32_t sample_rate,
1852 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001853 int channel_count,
1854 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001855{
1856 size_t size = 0;
1857
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001858 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1859 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001860
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001861 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001862 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001863 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001864
1865 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001866
Glenn Kasten4f993392014-05-14 07:30:48 -07001867 /* make sure the size is multiple of 32 bytes
1868 * At 48 kHz mono 16-bit PCM:
1869 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1870 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1871 */
1872 size += 0x1f;
1873 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001874
1875 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001876}
1877
1878static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1879{
1880 struct stream_out *out = (struct stream_out *)stream;
1881
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001882 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883}
1884
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001885static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886{
1887 return -ENOSYS;
1888}
1889
1890static size_t out_get_buffer_size(const struct audio_stream *stream)
1891{
1892 struct stream_out *out = (struct stream_out *)stream;
1893
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001894 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1895 return out->compr_config.fragment_size;
1896 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001897 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001898 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001899}
1900
1901static uint32_t out_get_channels(const struct audio_stream *stream)
1902{
1903 struct stream_out *out = (struct stream_out *)stream;
1904
1905 return out->channel_mask;
1906}
1907
1908static audio_format_t out_get_format(const struct audio_stream *stream)
1909{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001910 struct stream_out *out = (struct stream_out *)stream;
1911
1912 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001913}
1914
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001915static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001916{
1917 return -ENOSYS;
1918}
1919
1920static int out_standby(struct audio_stream *stream)
1921{
1922 struct stream_out *out = (struct stream_out *)stream;
1923 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001924
Eric Laurent994a6932013-07-17 11:51:42 -07001925 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001926 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001927
Eric Laurenta1478072015-09-21 17:21:52 -07001928 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001929 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001930 if (adev->adm_deregister_stream)
1931 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001932 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001933 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001934 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1935 if (out->pcm) {
1936 pcm_close(out->pcm);
1937 out->pcm = NULL;
1938 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001939 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1940 out->playback_started = false;
1941 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001942 } else {
1943 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001944 out->gapless_mdata.encoder_delay = 0;
1945 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001946 if (out->compr != NULL) {
1947 compress_close(out->compr);
1948 out->compr = NULL;
1949 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001950 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001951 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001952 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953 }
1954 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001955 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956 return 0;
1957}
1958
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001959static int out_on_error(struct audio_stream *stream)
1960{
1961 struct stream_out *out = (struct stream_out *)stream;
1962 struct audio_device *adev = out->dev;
1963 bool do_standby = false;
1964
1965 lock_output_stream(out);
1966 if (!out->standby) {
1967 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1968 stop_compressed_output_l(out);
1969 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1970 } else
1971 do_standby = true;
1972 }
1973 pthread_mutex_unlock(&out->lock);
1974
1975 if (do_standby)
1976 return out_standby(&out->stream.common);
1977
1978 return 0;
1979}
1980
Andy Hung7401c7c2016-09-21 12:41:21 -07001981static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982{
Andy Hung7401c7c2016-09-21 12:41:21 -07001983 struct stream_out *out = (struct stream_out *)stream;
1984
1985 // We try to get the lock for consistency,
1986 // but it isn't necessary for these variables.
1987 // If we're not in standby, we may be blocked on a write.
1988 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1989 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1990 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1991
1992 if (locked) {
1993 log_dump_l(&out->error_log, fd);
1994 pthread_mutex_unlock(&out->lock);
1995 } else {
1996 // We don't have the lock here, copy for safety.
1997 struct error_log log = out->error_log;
1998 log_dump_l(&log, fd);
1999 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000 return 0;
2001}
2002
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002003static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2004{
2005 int ret = 0;
2006 char value[32];
2007 struct compr_gapless_mdata tmp_mdata;
2008
2009 if (!out || !parms) {
2010 return -EINVAL;
2011 }
2012
2013 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2014 if (ret >= 0) {
2015 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2016 } else {
2017 return -EINVAL;
2018 }
2019
2020 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2021 if (ret >= 0) {
2022 tmp_mdata.encoder_padding = atoi(value);
2023 } else {
2024 return -EINVAL;
2025 }
2026
2027 out->gapless_mdata = tmp_mdata;
2028 out->send_new_metadata = 1;
2029 ALOGV("%s new encoder delay %u and padding %u", __func__,
2030 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2031
2032 return 0;
2033}
2034
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002035static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2036{
2037 return out == adev->primary_output || out == adev->voice_tx_output;
2038}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002039
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2041{
2042 struct stream_out *out = (struct stream_out *)stream;
2043 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002044 struct audio_usecase *usecase;
2045 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002046 struct str_parms *parms;
2047 char value[32];
2048 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002049 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002050 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002051
Eric Laurent2e140aa2016-06-30 17:14:46 -07002052 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002053 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054 parms = str_parms_create_str(kvpairs);
2055 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2056 if (ret >= 0) {
2057 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002058 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002059 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002061 /*
2062 * When HDMI cable is unplugged the music playback is paused and
2063 * the policy manager sends routing=0. But the audioflinger
2064 * continues to write data until standby time (3sec).
2065 * As the HDMI core is turned off, the write gets blocked.
2066 * Avoid this by routing audio to speaker until standby.
2067 */
2068 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2069 val == AUDIO_DEVICE_NONE) {
2070 val = AUDIO_DEVICE_OUT_SPEAKER;
2071 }
2072
2073 /*
2074 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002075 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002076 * the select_devices(). But how do we undo this?
2077 *
2078 * For example, music playback is active on headset (deep-buffer usecase)
2079 * and if we go to ringtones and select a ringtone, low-latency usecase
2080 * will be started on headset+speaker. As we can't enable headset+speaker
2081 * and headset devices at the same time, select_devices() switches the music
2082 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2083 * So when the ringtone playback is completed, how do we undo the same?
2084 *
2085 * We are relying on the out_set_parameters() call on deep-buffer output,
2086 * once the ringtone playback is ended.
2087 * NOTE: We should not check if the current devices are same as new devices.
2088 * Because select_devices() must be called to switch back the music
2089 * playback to headset.
2090 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002091 audio_devices_t new_dev = val;
2092 if (new_dev != AUDIO_DEVICE_NONE) {
2093 bool same_dev = out->devices == new_dev;
2094 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002095
Eric Laurenta7657192014-10-09 21:09:33 -07002096 if (output_drives_call(adev, out)) {
2097 if (!voice_is_in_call(adev)) {
2098 if (adev->mode == AUDIO_MODE_IN_CALL) {
2099 adev->current_call_output = out;
2100 ret = voice_start_call(adev);
2101 }
2102 } else {
2103 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002104 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002105 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002106 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002107
2108 if (!out->standby) {
2109 if (!same_dev) {
2110 ALOGV("update routing change");
2111 out->routing_change = true;
2112 }
2113 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002114 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002115 }
2116
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002117 }
2118
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002119 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002120 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002121
2122 /*handles device and call state changes*/
2123 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002125
2126 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2127 parse_compress_metadata(out, parms);
2128 }
2129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002131 ALOGV("%s: exit: code(%d)", __func__, status);
2132 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002133}
2134
2135static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2136{
2137 struct stream_out *out = (struct stream_out *)stream;
2138 struct str_parms *query = str_parms_create_str(keys);
2139 char *str;
2140 char value[256];
2141 struct str_parms *reply = str_parms_create();
2142 size_t i, j;
2143 int ret;
2144 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002145 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2147 if (ret >= 0) {
2148 value[0] = '\0';
2149 i = 0;
2150 while (out->supported_channel_masks[i] != 0) {
2151 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2152 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2153 if (!first) {
2154 strcat(value, "|");
2155 }
2156 strcat(value, out_channels_name_to_enum_table[j].name);
2157 first = false;
2158 break;
2159 }
2160 }
2161 i++;
2162 }
2163 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2164 str = str_parms_to_str(reply);
2165 } else {
2166 str = strdup(keys);
2167 }
2168 str_parms_destroy(query);
2169 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002170 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171 return str;
2172}
2173
2174static uint32_t out_get_latency(const struct audio_stream_out *stream)
2175{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002176 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177 struct stream_out *out = (struct stream_out *)stream;
2178
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002179 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2180 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002181 else if ((out->realtime) ||
2182 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002183 // since the buffer won't be filled up faster than realtime,
2184 // return a smaller number
2185 period_ms = (out->af_period_multiplier * out->config.period_size *
2186 1000) / (out->config.rate);
2187 hw_delay = platform_render_latency(out->usecase)/1000;
2188 return period_ms + hw_delay;
2189 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002190
2191 return (out->config.period_count * out->config.period_size * 1000) /
2192 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002193}
2194
2195static int out_set_volume(struct audio_stream_out *stream, float left,
2196 float right)
2197{
Eric Laurenta9024de2013-04-04 09:19:12 -07002198 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002199 int volume[2];
2200
Eric Laurenta9024de2013-04-04 09:19:12 -07002201 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2202 /* only take left channel into account: the API is for stereo anyway */
2203 out->muted = (left == 0.0f);
2204 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002205 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2206 const char *mixer_ctl_name = "Compress Playback Volume";
2207 struct audio_device *adev = out->dev;
2208 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002209 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2210 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002211 /* try with the control based on device id */
2212 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2213 PCM_PLAYBACK);
2214 char ctl_name[128] = {0};
2215 snprintf(ctl_name, sizeof(ctl_name),
2216 "Compress Playback %d Volume", pcm_device_id);
2217 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2218 if (!ctl) {
2219 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2220 return -EINVAL;
2221 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002222 }
2223 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2224 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2225 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2226 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002227 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229 return -ENOSYS;
2230}
2231
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002232// note: this call is safe only if the stream_cb is
2233// removed first in close_output_stream (as is done now).
2234static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2235{
2236 if (!stream || !parms)
2237 return;
2238
2239 struct stream_out *out = (struct stream_out *)stream;
2240 struct audio_device *adev = out->dev;
2241
2242 card_status_t status;
2243 int card;
2244 if (parse_snd_card_status(parms, &card, &status) < 0)
2245 return;
2246
2247 pthread_mutex_lock(&adev->lock);
2248 bool valid_cb = (card == adev->snd_card);
2249 pthread_mutex_unlock(&adev->lock);
2250
2251 if (!valid_cb)
2252 return;
2253
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002254 lock_output_stream(out);
2255 if (out->card_status != status)
2256 out->card_status = status;
2257 pthread_mutex_unlock(&out->lock);
2258
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002259 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2260 use_case_table[out->usecase],
2261 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2262
2263 if (status == CARD_STATUS_OFFLINE)
2264 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002265
2266 return;
2267}
2268
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002269#ifdef NO_AUDIO_OUT
2270static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002271 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002272{
2273 struct stream_out *out = (struct stream_out *)stream;
2274
2275 /* No Output device supported other than BT for playback.
2276 * Sleep for the amount of buffer duration
2277 */
Eric Laurenta1478072015-09-21 17:21:52 -07002278 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002279 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2280 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002281 out_get_sample_rate(&out->stream.common));
2282 pthread_mutex_unlock(&out->lock);
2283 return bytes;
2284}
2285#endif
2286
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002287static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2288 size_t bytes)
2289{
2290 struct stream_out *out = (struct stream_out *)stream;
2291 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002292 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002293 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294
Eric Laurenta1478072015-09-21 17:21:52 -07002295 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002296 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2297 error_code = ERROR_CODE_WRITE;
2298 goto exit;
2299 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002301 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002302 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002303 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002304 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002305 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002306 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002307 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002308 goto exit;
2309 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002310
2311 if (last_known_cal_step != -1) {
2312 ALOGD("%s: retry previous failed cal level set", __func__);
2313 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2314 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002315 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002316
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002317 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002318 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002319 if (out->send_new_metadata) {
2320 ALOGVV("send new gapless metadata");
2321 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2322 out->send_new_metadata = 0;
2323 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002324 unsigned int avail;
2325 struct timespec tstamp;
2326 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2327 /* Do not limit write size if the available frames count is unknown */
2328 if (ret != 0) {
2329 avail = bytes;
2330 }
2331 if (avail == 0) {
2332 ret = 0;
2333 } else {
2334 if (avail > bytes) {
2335 avail = bytes;
2336 }
2337 ret = compress_write(out->compr, buffer, avail);
2338 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2339 __func__, avail, ret);
2340 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002341
Eric Laurent6e895242013-09-05 16:10:57 -07002342 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2344 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002345 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002346 compress_start(out->compr);
2347 out->playback_started = 1;
2348 out->offload_state = OFFLOAD_STATE_PLAYING;
2349 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002350 if (ret < 0) {
2351 log_error_l(&out->error_log, ERROR_CODE_WRITE);
2352 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002353 pthread_mutex_unlock(&out->lock);
2354 return ret;
2355 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002356 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002357 if (out->pcm) {
2358 if (out->muted)
2359 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002360
Eric Laurent0e46adf2016-12-16 12:49:24 -08002361 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002362
Haynes Mathew George03c40102016-01-29 17:57:48 -08002363 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2364 out->config.rate;
2365 request_out_focus(out, ns);
2366
2367 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2368 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002369 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002370 else
2371 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002372
Haynes Mathew George03c40102016-01-29 17:57:48 -08002373 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002374 } else {
2375 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002376 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002377 }
2378
2379exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002380 // For PCM we always consume the buffer and return #bytes regardless of ret.
2381 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2382 out->written += bytes / (out->config.channels * sizeof(short));
2383 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002384 long long sleeptime_us = 0;
2385 if (ret != 0) {
2386 log_error_l(&out->error_log, error_code);
2387 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2388 ALOGE_IF(out->pcm != NULL,
2389 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
2390 sleeptime_us = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2391 out_get_sample_rate(&out->stream.common);
2392 // usleep not guaranteed for values over 1 second but we don't limit here.
2393 }
2394 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002395
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002396 pthread_mutex_unlock(&out->lock);
2397
2398 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002399 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002400 if (sleeptime_us != 0)
2401 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002402 }
2403 return bytes;
2404}
2405
2406static int out_get_render_position(const struct audio_stream_out *stream,
2407 uint32_t *dsp_frames)
2408{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002409 struct stream_out *out = (struct stream_out *)stream;
2410 *dsp_frames = 0;
2411 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002412 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002413 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002414 unsigned long frames = 0;
2415 // TODO: check return value
2416 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2417 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002418 ALOGVV("%s rendered frames %d sample_rate %d",
2419 __func__, *dsp_frames, out->sample_rate);
2420 }
2421 pthread_mutex_unlock(&out->lock);
2422 return 0;
2423 } else
2424 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425}
2426
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002427static int out_add_audio_effect(const struct audio_stream *stream __unused,
2428 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002429{
2430 return 0;
2431}
2432
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002433static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2434 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435{
2436 return 0;
2437}
2438
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002439static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2440 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441{
2442 return -EINVAL;
2443}
2444
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002445static int out_get_presentation_position(const struct audio_stream_out *stream,
2446 uint64_t *frames, struct timespec *timestamp)
2447{
2448 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002449 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002450 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002451
Eric Laurenta1478072015-09-21 17:21:52 -07002452 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002453
Eric Laurent949a0892013-09-20 09:20:13 -07002454 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2455 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002456 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002457 compress_get_tstamp(out->compr, &dsp_frames,
2458 &out->sample_rate);
2459 ALOGVV("%s rendered frames %ld sample_rate %d",
2460 __func__, dsp_frames, out->sample_rate);
2461 *frames = dsp_frames;
2462 ret = 0;
2463 /* this is the best we can do */
2464 clock_gettime(CLOCK_MONOTONIC, timestamp);
2465 }
2466 } else {
2467 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002468 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002469 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2470 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002471 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002472 // This adjustment accounts for buffering after app processor.
2473 // It is based on estimated DSP latency per use case, rather than exact.
2474 signed_frames -=
2475 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2476
Eric Laurent949a0892013-09-20 09:20:13 -07002477 // It would be unusual for this value to be negative, but check just in case ...
2478 if (signed_frames >= 0) {
2479 *frames = signed_frames;
2480 ret = 0;
2481 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002482 }
2483 }
2484 }
2485
2486 pthread_mutex_unlock(&out->lock);
2487
2488 return ret;
2489}
2490
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002491static int out_set_callback(struct audio_stream_out *stream,
2492 stream_callback_t callback, void *cookie)
2493{
2494 struct stream_out *out = (struct stream_out *)stream;
2495
2496 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002497 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002498 out->offload_callback = callback;
2499 out->offload_cookie = cookie;
2500 pthread_mutex_unlock(&out->lock);
2501 return 0;
2502}
2503
2504static int out_pause(struct audio_stream_out* stream)
2505{
2506 struct stream_out *out = (struct stream_out *)stream;
2507 int status = -ENOSYS;
2508 ALOGV("%s", __func__);
2509 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002510 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002511 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2512 status = compress_pause(out->compr);
2513 out->offload_state = OFFLOAD_STATE_PAUSED;
2514 }
2515 pthread_mutex_unlock(&out->lock);
2516 }
2517 return status;
2518}
2519
2520static int out_resume(struct audio_stream_out* stream)
2521{
2522 struct stream_out *out = (struct stream_out *)stream;
2523 int status = -ENOSYS;
2524 ALOGV("%s", __func__);
2525 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2526 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002527 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002528 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2529 status = compress_resume(out->compr);
2530 out->offload_state = OFFLOAD_STATE_PLAYING;
2531 }
2532 pthread_mutex_unlock(&out->lock);
2533 }
2534 return status;
2535}
2536
2537static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2538{
2539 struct stream_out *out = (struct stream_out *)stream;
2540 int status = -ENOSYS;
2541 ALOGV("%s", __func__);
2542 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002543 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002544 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2545 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2546 else
2547 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2548 pthread_mutex_unlock(&out->lock);
2549 }
2550 return status;
2551}
2552
2553static int out_flush(struct audio_stream_out* stream)
2554{
2555 struct stream_out *out = (struct stream_out *)stream;
2556 ALOGV("%s", __func__);
2557 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002558 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002559 stop_compressed_output_l(out);
2560 pthread_mutex_unlock(&out->lock);
2561 return 0;
2562 }
2563 return -ENOSYS;
2564}
2565
Eric Laurent0e46adf2016-12-16 12:49:24 -08002566static int out_stop(const struct audio_stream_out* stream)
2567{
2568 struct stream_out *out = (struct stream_out *)stream;
2569 struct audio_device *adev = out->dev;
2570 int ret = -ENOSYS;
2571
2572 ALOGV("%s", __func__);
2573 pthread_mutex_lock(&adev->lock);
2574 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2575 out->playback_started && out->pcm != NULL) {
2576 pcm_stop(out->pcm);
2577 ret = stop_output_stream(out);
2578 if (ret == 0) {
2579 out->playback_started = false;
2580 }
2581 }
2582 pthread_mutex_unlock(&adev->lock);
2583 return ret;
2584}
2585
2586static int out_start(const struct audio_stream_out* stream)
2587{
2588 struct stream_out *out = (struct stream_out *)stream;
2589 struct audio_device *adev = out->dev;
2590 int ret = -ENOSYS;
2591
2592 ALOGV("%s", __func__);
2593 pthread_mutex_lock(&adev->lock);
2594 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2595 !out->playback_started && out->pcm != NULL) {
2596 ret = start_output_stream(out);
2597 if (ret == 0) {
2598 out->playback_started = true;
2599 }
2600 }
2601 pthread_mutex_unlock(&adev->lock);
2602 return ret;
2603}
2604
2605static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2606 int32_t min_size_frames,
2607 struct audio_mmap_buffer_info *info)
2608{
2609 struct stream_out *out = (struct stream_out *)stream;
2610 struct audio_device *adev = out->dev;
2611 int ret = 0;
2612 unsigned int offset1;
2613 unsigned int frames1;
2614 const char *step = "";
2615
2616 ALOGV("%s", __func__);
2617 pthread_mutex_lock(&adev->lock);
2618
2619 if (info == NULL || min_size_frames == 0) {
2620 ret = -EINVAL;
2621 goto exit;
2622 }
2623 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
2624 ret = -ENOSYS;
2625 goto exit;
2626 }
2627 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2628 if (out->pcm_device_id < 0) {
2629 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2630 __func__, out->pcm_device_id, out->usecase);
2631 ret = -EINVAL;
2632 goto exit;
2633 }
2634 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2635 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2636 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2637 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2638 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2639 step = "open";
2640 ret = -ENODEV;
2641 goto exit;
2642 }
2643 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2644 if (ret < 0) {
2645 step = "begin";
2646 goto exit;
2647 }
2648 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2649 info->burst_size_frames = out->config.period_size;
2650 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2651
2652 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2653 info->buffer_size_frames));
2654
2655 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2656 if (ret < 0) {
2657 step = "commit";
2658 goto exit;
2659 }
2660 ret = 0;
2661
2662 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2663 __func__, info->shared_memory_address, info->buffer_size_frames);
2664
2665exit:
2666 if (ret != 0) {
2667 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
2668 if (out->pcm != NULL) {
2669 pcm_close(out->pcm);
2670 out->pcm = NULL;
2671 }
2672 }
2673 pthread_mutex_unlock(&adev->lock);
2674 return ret;
2675}
2676
2677static int out_get_mmap_position(const struct audio_stream_out *stream,
2678 struct audio_mmap_position *position)
2679{
2680 struct stream_out *out = (struct stream_out *)stream;
2681 ALOGVV("%s", __func__);
2682 if (position == NULL) {
2683 return -EINVAL;
2684 }
2685 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2686 return -ENOSYS;
2687 }
2688 if (out->pcm == NULL) {
2689 return -ENOSYS;
2690 }
2691
2692 struct timespec ts = { 0, 0 };
2693 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2694 if (ret < 0) {
2695 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2696 return ret;
2697 }
2698 position->time_nanoseconds = ts2ns(&ts);
2699 return 0;
2700}
2701
2702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703/** audio_stream_in implementation **/
2704static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2705{
2706 struct stream_in *in = (struct stream_in *)stream;
2707
2708 return in->config.rate;
2709}
2710
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002711static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712{
2713 return -ENOSYS;
2714}
2715
2716static size_t in_get_buffer_size(const struct audio_stream *stream)
2717{
2718 struct stream_in *in = (struct stream_in *)stream;
2719
Haynes Mathew George03c40102016-01-29 17:57:48 -08002720 return in->config.period_size * in->af_period_multiplier *
2721 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722}
2723
2724static uint32_t in_get_channels(const struct audio_stream *stream)
2725{
2726 struct stream_in *in = (struct stream_in *)stream;
2727
2728 return in->channel_mask;
2729}
2730
vivek mehta4ed66e62016-04-15 23:33:34 -07002731static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002732{
vivek mehta4ed66e62016-04-15 23:33:34 -07002733 struct stream_in *in = (struct stream_in *)stream;
2734 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735}
2736
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002737static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738{
2739 return -ENOSYS;
2740}
2741
2742static int in_standby(struct audio_stream *stream)
2743{
2744 struct stream_in *in = (struct stream_in *)stream;
2745 struct audio_device *adev = in->dev;
2746 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07002747 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002748
2749 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002750
2751 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002752 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002753 audio_extn_sound_trigger_stop_lab(in);
2754 in->standby = true;
2755 }
2756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002758 if (adev->adm_deregister_stream)
2759 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2760
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002761 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002763 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
2764 in->capture_started = false;
2765 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002766 if (in->pcm) {
2767 pcm_close(in->pcm);
2768 in->pcm = NULL;
2769 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002770 adev->enable_voicerx = false;
2771 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002773 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774 }
2775 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002776 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002777 return status;
2778}
2779
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002780static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781{
2782 return 0;
2783}
2784
2785static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2786{
2787 struct stream_in *in = (struct stream_in *)stream;
2788 struct audio_device *adev = in->dev;
2789 struct str_parms *parms;
2790 char *str;
2791 char value[32];
2792 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002793 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794
Eric Laurent994a6932013-07-17 11:51:42 -07002795 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796 parms = str_parms_create_str(kvpairs);
2797
2798 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2799
Eric Laurenta1478072015-09-21 17:21:52 -07002800 lock_input_stream(in);
2801
Eric Laurent150dbfe2013-02-27 14:31:02 -08002802 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803 if (ret >= 0) {
2804 val = atoi(value);
2805 /* no audio source uses val == 0 */
2806 if ((in->source != val) && (val != 0)) {
2807 in->source = val;
2808 }
2809 }
2810
2811 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002812
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813 if (ret >= 0) {
2814 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002815 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002816 in->device = val;
2817 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002818 if (!in->standby) {
2819 ALOGV("update input routing change");
2820 in->routing_change = true;
2821 select_devices(adev, in->usecase);
2822 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823 }
2824 }
2825
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002827 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002828
2829 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002830 ALOGV("%s: exit: status(%d)", __func__, status);
2831 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832}
2833
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002834static char* in_get_parameters(const struct audio_stream *stream __unused,
2835 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002836{
2837 return strdup("");
2838}
2839
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002840static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002841{
2842 return 0;
2843}
2844
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002845static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2846{
2847 if (!stream || !parms)
2848 return;
2849
2850 struct stream_in *in = (struct stream_in *)stream;
2851 struct audio_device *adev = in->dev;
2852
2853 card_status_t status;
2854 int card;
2855 if (parse_snd_card_status(parms, &card, &status) < 0)
2856 return;
2857
2858 pthread_mutex_lock(&adev->lock);
2859 bool valid_cb = (card == adev->snd_card);
2860 pthread_mutex_unlock(&adev->lock);
2861
2862 if (!valid_cb)
2863 return;
2864
2865 lock_input_stream(in);
2866 if (in->card_status != status)
2867 in->card_status = status;
2868 pthread_mutex_unlock(&in->lock);
2869
2870 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2871 use_case_table[in->usecase],
2872 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2873
2874 // a better solution would be to report error back to AF and let
2875 // it put the stream to standby
2876 if (status == CARD_STATUS_OFFLINE)
2877 in_standby(&in->stream.common);
2878
2879 return;
2880}
2881
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2883 size_t bytes)
2884{
2885 struct stream_in *in = (struct stream_in *)stream;
2886 struct audio_device *adev = in->dev;
2887 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002888 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002889
Eric Laurenta1478072015-09-21 17:21:52 -07002890 lock_input_stream(in);
2891
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002892 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002893 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002894 /* Read from sound trigger HAL */
2895 audio_extn_sound_trigger_read(in, buffer, bytes);
2896 pthread_mutex_unlock(&in->lock);
2897 return bytes;
2898 }
2899
Eric Laurent0e46adf2016-12-16 12:49:24 -08002900 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
2901 ret = -ENOSYS;
2902 goto exit;
2903 }
2904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002905 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002906 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002907 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002908 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002909 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002910 goto exit;
2911 }
2912 in->standby = 0;
2913 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002914
Haynes Mathew George03c40102016-01-29 17:57:48 -08002915 //what's the duration requested by the client?
2916 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2917 in->config.rate;
2918 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002919
Haynes Mathew George03c40102016-01-29 17:57:48 -08002920 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002921 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002922 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002923 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002924 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002925 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002926 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002927 if (ret < 0) {
2928 ALOGE("Failed to read w/err %s", strerror(errno));
2929 ret = -errno;
2930 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002931 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2932 if (bytes % 4 == 0) {
2933 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2934 int_buf_stream = buffer;
2935 for (size_t itt=0; itt < bytes/4 ; itt++) {
2936 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002937 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002938 } else {
2939 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2940 ret = -EINVAL;
2941 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002942 }
2943 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944 }
2945
Haynes Mathew George03c40102016-01-29 17:57:48 -08002946 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002947
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002948 /*
2949 * Instead of writing zeroes here, we could trust the hardware
2950 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002951 * 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 -08002952 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002953 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002954 memset(buffer, 0, bytes);
2955
2956exit:
2957 pthread_mutex_unlock(&in->lock);
2958
2959 if (ret != 0) {
2960 in_standby(&in->stream.common);
2961 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002962 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002963 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002964 memset(buffer, 0, bytes); // clear return data
2965 }
2966 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002967 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002968 }
2969 return bytes;
2970}
2971
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002972static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002973{
2974 return 0;
2975}
2976
Andy Hung6ebe5962016-01-15 17:46:57 -08002977static int in_get_capture_position(const struct audio_stream_in *stream,
2978 int64_t *frames, int64_t *time)
2979{
2980 if (stream == NULL || frames == NULL || time == NULL) {
2981 return -EINVAL;
2982 }
2983 struct stream_in *in = (struct stream_in *)stream;
2984 int ret = -ENOSYS;
2985
2986 lock_input_stream(in);
2987 if (in->pcm) {
2988 struct timespec timestamp;
2989 unsigned int avail;
2990 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2991 *frames = in->frames_read + avail;
2992 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2993 ret = 0;
2994 }
2995 }
2996 pthread_mutex_unlock(&in->lock);
2997 return ret;
2998}
2999
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003000static int add_remove_audio_effect(const struct audio_stream *stream,
3001 effect_handle_t effect,
3002 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003004 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003005 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003006 int status = 0;
3007 effect_descriptor_t desc;
3008
3009 status = (*effect)->get_descriptor(effect, &desc);
3010 if (status != 0)
3011 return status;
3012
Eric Laurenta1478072015-09-21 17:21:52 -07003013 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003014 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003015 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003016 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003017 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003018 in->enable_aec != enable &&
3019 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3020 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003021 if (!enable)
3022 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003023 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3024 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3025 adev->enable_voicerx = enable;
3026 struct audio_usecase *usecase;
3027 struct listnode *node;
3028 list_for_each(node, &adev->usecase_list) {
3029 usecase = node_to_item(node, struct audio_usecase, list);
3030 if (usecase->type == PCM_PLAYBACK) {
3031 select_devices(adev, usecase->id);
3032 break;
3033 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003034 }
3035 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003036 if (!in->standby)
3037 select_devices(in->dev, in->usecase);
3038 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003039 if (in->enable_ns != enable &&
3040 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3041 in->enable_ns = enable;
3042 if (!in->standby)
3043 select_devices(in->dev, in->usecase);
3044 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003045 pthread_mutex_unlock(&in->dev->lock);
3046 pthread_mutex_unlock(&in->lock);
3047
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048 return 0;
3049}
3050
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003051static int in_add_audio_effect(const struct audio_stream *stream,
3052 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053{
Eric Laurent994a6932013-07-17 11:51:42 -07003054 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003055 return add_remove_audio_effect(stream, effect, true);
3056}
3057
3058static int in_remove_audio_effect(const struct audio_stream *stream,
3059 effect_handle_t effect)
3060{
Eric Laurent994a6932013-07-17 11:51:42 -07003061 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003062 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063}
3064
Eric Laurent0e46adf2016-12-16 12:49:24 -08003065static int in_stop(const struct audio_stream_in* stream)
3066{
3067 struct stream_in *in = (struct stream_in *)stream;
3068 struct audio_device *adev = in->dev;
3069
3070 int ret = -ENOSYS;
3071 ALOGV("%s", __func__);
3072 pthread_mutex_lock(&adev->lock);
3073 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3074 in->capture_started && in->pcm != NULL) {
3075 pcm_stop(in->pcm);
3076 ret = stop_input_stream(in);
3077 if (ret == 0) {
3078 in->capture_started = false;
3079 }
3080 }
3081 pthread_mutex_unlock(&adev->lock);
3082 return ret;
3083}
3084
3085static int in_start(const struct audio_stream_in* stream)
3086{
3087 struct stream_in *in = (struct stream_in *)stream;
3088 struct audio_device *adev = in->dev;
3089 int ret = -ENOSYS;
3090
3091 ALOGV("%s in %p", __func__, in);
3092 pthread_mutex_lock(&adev->lock);
3093 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3094 !in->capture_started && in->pcm != NULL) {
3095 if (!in->capture_started) {
3096 ret = start_input_stream(in);
3097 if (ret == 0) {
3098 in->capture_started = true;
3099 }
3100 }
3101 }
3102 pthread_mutex_unlock(&adev->lock);
3103 return ret;
3104}
3105
3106static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3107 int32_t min_size_frames,
3108 struct audio_mmap_buffer_info *info)
3109{
3110 struct stream_in *in = (struct stream_in *)stream;
3111 struct audio_device *adev = in->dev;
3112 int ret = 0;
3113 unsigned int offset1;
3114 unsigned int frames1;
3115 const char *step = "";
3116
3117 pthread_mutex_lock(&adev->lock);
3118 ALOGV("%s in %p", __func__, in);
3119 if (info == NULL || min_size_frames == 0) {
3120 ALOGV("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
3121 ret = -EINVAL;
3122 goto exit;
3123 }
3124 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
3125 ALOGV("%s in %p", __func__, in);
3126 ret = -ENOSYS;
3127 goto exit;
3128 }
3129 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3130 if (in->pcm_device_id < 0) {
3131 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3132 __func__, in->pcm_device_id, in->usecase);
3133 ret = -EINVAL;
3134 goto exit;
3135 }
3136 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3137 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3138 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3139 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3140 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3141 step = "open";
3142 ret = -ENODEV;
3143 goto exit;
3144 }
3145
3146 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3147 if (ret < 0) {
3148 step = "begin";
3149 goto exit;
3150 }
3151 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3152 info->burst_size_frames = in->config.period_size;
3153 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3154
3155 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3156 info->buffer_size_frames));
3157
3158 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3159 if (ret < 0) {
3160 step = "commit";
3161 goto exit;
3162 }
3163
3164 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3165 __func__, info->shared_memory_address, info->buffer_size_frames);
3166 ret = 0;
3167
3168exit:
3169 if (ret != 0) {
3170 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
3171 if (in->pcm != NULL) {
3172 pcm_close(in->pcm);
3173 in->pcm = NULL;
3174 }
3175 }
3176 pthread_mutex_unlock(&adev->lock);
3177 return ret;
3178}
3179
3180static int in_get_mmap_position(const struct audio_stream_in *stream,
3181 struct audio_mmap_position *position)
3182{
3183 struct stream_in *in = (struct stream_in *)stream;
3184 ALOGVV("%s", __func__);
3185 if (position == NULL) {
3186 return -EINVAL;
3187 }
3188 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3189 return -ENOSYS;
3190 }
3191 if (in->pcm == NULL) {
3192 return -ENOSYS;
3193 }
3194 struct timespec ts = { 0, 0 };
3195 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3196 if (ret < 0) {
3197 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3198 return ret;
3199 }
3200 position->time_nanoseconds = ts2ns(&ts);
3201 return 0;
3202}
3203
3204
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003205static int adev_open_output_stream(struct audio_hw_device *dev,
3206 audio_io_handle_t handle,
3207 audio_devices_t devices,
3208 audio_output_flags_t flags,
3209 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003210 struct audio_stream_out **stream_out,
3211 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212{
3213 struct audio_device *adev = (struct audio_device *)dev;
3214 struct stream_out *out;
3215 int i, ret;
3216
Eric Laurent994a6932013-07-17 11:51:42 -07003217 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218 __func__, config->sample_rate, config->channel_mask, devices, flags);
3219 *stream_out = NULL;
3220 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3221
3222 if (devices == AUDIO_DEVICE_NONE)
3223 devices = AUDIO_DEVICE_OUT_SPEAKER;
3224
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003225 out->flags = flags;
3226 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003227 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003228 out->format = config->format;
3229 out->sample_rate = config->sample_rate;
3230 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3231 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003232 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233
3234 /* Init use case and pcm_config */
3235 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07003236 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003238 pthread_mutex_lock(&adev->lock);
3239 ret = read_hdmi_channel_masks(out);
3240 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003241 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003242 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003243
3244 if (config->sample_rate == 0)
3245 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3246 if (config->channel_mask == 0)
3247 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08003248 if (config->format == AUDIO_FORMAT_DEFAULT)
3249 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003250
3251 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003252 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08003253 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3255 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003257 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003258 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003259 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003260 pthread_mutex_lock(&adev->lock);
3261 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3262 pthread_mutex_unlock(&adev->lock);
3263
3264 // reject offload during card offline to allow
3265 // fallback to s/w paths
3266 if (offline) {
3267 ret = -ENODEV;
3268 goto error_open;
3269 }
3270
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003271 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3272 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3273 ALOGE("%s: Unsupported Offload information", __func__);
3274 ret = -EINVAL;
3275 goto error_open;
3276 }
3277 if (!is_supported_format(config->offload_info.format)) {
3278 ALOGE("%s: Unsupported audio format", __func__);
3279 ret = -EINVAL;
3280 goto error_open;
3281 }
3282
3283 out->compr_config.codec = (struct snd_codec *)
3284 calloc(1, sizeof(struct snd_codec));
3285
3286 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3287 if (config->offload_info.channel_mask)
3288 out->channel_mask = config->offload_info.channel_mask;
3289 else if (config->channel_mask)
3290 out->channel_mask = config->channel_mask;
3291 out->format = config->offload_info.format;
3292 out->sample_rate = config->offload_info.sample_rate;
3293
3294 out->stream.set_callback = out_set_callback;
3295 out->stream.pause = out_pause;
3296 out->stream.resume = out_resume;
3297 out->stream.drain = out_drain;
3298 out->stream.flush = out_flush;
3299
3300 out->compr_config.codec->id =
3301 get_snd_codec_id(config->offload_info.format);
3302 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3303 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003304 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003305 out->compr_config.codec->bit_rate =
3306 config->offload_info.bit_rate;
3307 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003308 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003309 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3310
3311 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3312 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003313
3314 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003315 create_offload_callback_thread(out);
3316 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3317 __func__, config->offload_info.version,
3318 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003319 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3320 if (config->sample_rate == 0)
3321 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3322 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3323 config->sample_rate != 8000) {
3324 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3325 ret = -EINVAL;
3326 goto error_open;
3327 }
3328 out->sample_rate = config->sample_rate;
3329 out->config.rate = config->sample_rate;
3330 if (config->format == AUDIO_FORMAT_DEFAULT)
3331 config->format = AUDIO_FORMAT_PCM_16_BIT;
3332 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3333 config->format = AUDIO_FORMAT_PCM_16_BIT;
3334 ret = -EINVAL;
3335 goto error_open;
3336 }
3337 out->format = config->format;
3338 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3339 out->config = pcm_config_afe_proxy_playback;
3340 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003342 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3343 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3344 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003345 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3346 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3347 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003348 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3349 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003350 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003351 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003352 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3353 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3354 out->config = pcm_config_mmap_playback;
3355 out->stream.start = out_start;
3356 out->stream.stop = out_stop;
3357 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3358 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003359 } else {
3360 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3361 out->config = pcm_config_low_latency;
3362 }
3363 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3364 if (k_enable_extended_precision
3365 && pcm_params_format_test(adev->use_case_table[out->usecase],
3366 pcm_format_from_audio_format(config->format))) {
3367 out->config.format = pcm_format_from_audio_format(config->format);
3368 /* out->format already set to config->format */
3369 } else {
3370 /* deny the externally proposed config format
3371 * and use the one specified in audio_hw layer configuration.
3372 * Note: out->format is returned by out->stream.common.get_format()
3373 * and is used to set config->format in the code several lines below.
3374 */
3375 out->format = audio_format_from_pcm_format(out->config.format);
3376 }
3377 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003378 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003380 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3381 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003383 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003384 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003385 adev->primary_output = out;
3386 else {
3387 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003388 ret = -EEXIST;
3389 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003390 }
3391 }
3392
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393 /* Check if this usecase is already existing */
3394 pthread_mutex_lock(&adev->lock);
3395 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3396 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003398 ret = -EEXIST;
3399 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400 }
3401 pthread_mutex_unlock(&adev->lock);
3402
3403 out->stream.common.get_sample_rate = out_get_sample_rate;
3404 out->stream.common.set_sample_rate = out_set_sample_rate;
3405 out->stream.common.get_buffer_size = out_get_buffer_size;
3406 out->stream.common.get_channels = out_get_channels;
3407 out->stream.common.get_format = out_get_format;
3408 out->stream.common.set_format = out_set_format;
3409 out->stream.common.standby = out_standby;
3410 out->stream.common.dump = out_dump;
3411 out->stream.common.set_parameters = out_set_parameters;
3412 out->stream.common.get_parameters = out_get_parameters;
3413 out->stream.common.add_audio_effect = out_add_audio_effect;
3414 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3415 out->stream.get_latency = out_get_latency;
3416 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003417#ifdef NO_AUDIO_OUT
3418 out->stream.write = out_write_for_no_output;
3419#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003421#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422 out->stream.get_render_position = out_get_render_position;
3423 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003424 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425
Eric Laurent0e46adf2016-12-16 12:49:24 -08003426 if (out->realtime)
3427 out->af_period_multiplier = af_period_multiplier;
3428 else
3429 out->af_period_multiplier = 1;
3430
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003432 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003433 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003435 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003436 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003437 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3438
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439 config->format = out->stream.common.get_format(&out->stream.common);
3440 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3441 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3442
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003443
3444 /*
3445 By locking output stream before registering, we allow the callback
3446 to update stream's state only after stream's initial state is set to
3447 adev state.
3448 */
3449 lock_output_stream(out);
3450 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3451 pthread_mutex_lock(&adev->lock);
3452 out->card_status = adev->card_status;
3453 pthread_mutex_unlock(&adev->lock);
3454 pthread_mutex_unlock(&out->lock);
3455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003457
Eric Laurent994a6932013-07-17 11:51:42 -07003458 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003460
3461error_open:
3462 free(out);
3463 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003464 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003465 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466}
3467
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003468static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469 struct audio_stream_out *stream)
3470{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003471 struct stream_out *out = (struct stream_out *)stream;
3472 struct audio_device *adev = out->dev;
3473
Eric Laurent994a6932013-07-17 11:51:42 -07003474 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003475
3476 // must deregister from sndmonitor first to prevent races
3477 // between the callback and close_stream
3478 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003480 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3481 destroy_offload_callback_thread(out);
3482
3483 if (out->compr_config.codec != NULL)
3484 free(out->compr_config.codec);
3485 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003486
3487 if (adev->voice_tx_output == out)
3488 adev->voice_tx_output = NULL;
3489
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003490 pthread_cond_destroy(&out->cond);
3491 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003492 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003493 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494}
3495
3496static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3497{
3498 struct audio_device *adev = (struct audio_device *)dev;
3499 struct str_parms *parms;
3500 char *str;
3501 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003502 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003504 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505
Joe Onorato188b6222016-03-01 11:02:27 -08003506 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003507
3508 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509
3510 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003511 status = voice_set_parameters(adev, parms);
3512 if (status != 0) {
3513 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514 }
3515
3516 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3517 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003518 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3520 adev->bluetooth_nrec = true;
3521 else
3522 adev->bluetooth_nrec = false;
3523 }
3524
3525 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3526 if (ret >= 0) {
3527 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3528 adev->screen_off = false;
3529 else
3530 adev->screen_off = true;
3531 }
3532
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003533 ret = str_parms_get_int(parms, "rotation", &val);
3534 if (ret >= 0) {
3535 bool reverse_speakers = false;
3536 switch(val) {
3537 // FIXME: note that the code below assumes that the speakers are in the correct placement
3538 // relative to the user when the device is rotated 90deg from its default rotation. This
3539 // assumption is device-specific, not platform-specific like this code.
3540 case 270:
3541 reverse_speakers = true;
3542 break;
3543 case 0:
3544 case 90:
3545 case 180:
3546 break;
3547 default:
3548 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003549 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003550 }
Eric Laurent03f09432014-03-25 18:09:11 -07003551 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003552 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003553 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003554 }
3555
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003556 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3557 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003558 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003559 }
3560
David Lin8c03e672017-02-06 20:31:38 -08003561 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3562 if (ret >= 0) {
3563 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3564 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3565 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3566 if (ret >= 0) {
3567 const int card = atoi(value);
3568 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3569 }
3570 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3571 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3572 if (ret >= 0) {
3573 const int card = atoi(value);
3574 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3575 }
3576 }
3577 }
3578
3579 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3580 if (ret >= 0) {
3581 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3582 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3583 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3584 if (ret >= 0) {
3585 const int card = atoi(value);
3586
3587 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3588 }
3589 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3590 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3591 if (ret >= 0) {
3592 const int card = atoi(value);
3593 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3594 }
3595 }
3596 }
3597
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003598 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003599done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003601 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003602 ALOGV("%s: exit with code(%d)", __func__, status);
3603 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003604}
3605
3606static char* adev_get_parameters(const struct audio_hw_device *dev,
3607 const char *keys)
3608{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003609 struct audio_device *adev = (struct audio_device *)dev;
3610 struct str_parms *reply = str_parms_create();
3611 struct str_parms *query = str_parms_create_str(keys);
3612 char *str;
3613
3614 pthread_mutex_lock(&adev->lock);
3615
3616 voice_get_parameters(adev, query, reply);
3617 str = str_parms_to_str(reply);
3618 str_parms_destroy(query);
3619 str_parms_destroy(reply);
3620
3621 pthread_mutex_unlock(&adev->lock);
3622 ALOGV("%s: exit: returns - %s", __func__, str);
3623 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624}
3625
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003626static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627{
3628 return 0;
3629}
3630
Haynes Mathew George5191a852013-09-11 14:19:36 -07003631static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3632{
3633 int ret;
3634 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003635
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003636 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3637
Haynes Mathew George5191a852013-09-11 14:19:36 -07003638 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003639 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003640 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003641
Haynes Mathew George5191a852013-09-11 14:19:36 -07003642 return ret;
3643}
3644
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003645static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646{
3647 return -ENOSYS;
3648}
3649
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003650static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3651 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652{
3653 return -ENOSYS;
3654}
3655
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003656static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657{
3658 return -ENOSYS;
3659}
3660
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003661static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662{
3663 return -ENOSYS;
3664}
3665
3666static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3667{
3668 struct audio_device *adev = (struct audio_device *)dev;
3669
3670 pthread_mutex_lock(&adev->lock);
3671 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003672 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003674 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3675 voice_is_in_call(adev)) {
3676 voice_stop_call(adev);
3677 adev->current_call_output = NULL;
3678 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679 }
3680 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003681
3682 audio_extn_extspk_set_mode(adev->extspk, mode);
3683
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684 return 0;
3685}
3686
3687static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3688{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003689 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691
Eric Laurent2bafff12016-03-17 12:17:23 -07003692 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003693 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003694 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3695 ret = audio_extn_hfp_set_mic_mute(adev, state);
3696 } else {
3697 ret = voice_set_mic_mute(adev, state);
3698 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003699 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003700 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003701
3702 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703}
3704
3705static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3706{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003707 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708 return 0;
3709}
3710
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003711static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712 const struct audio_config *config)
3713{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003714 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003716 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3717 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003718}
3719
3720static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003721 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003722 audio_devices_t devices,
3723 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003724 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003725 audio_input_flags_t flags,
3726 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003727 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003728{
3729 struct audio_device *adev = (struct audio_device *)dev;
3730 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003731 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003732 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003733 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734
Eric Laurent994a6932013-07-17 11:51:42 -07003735 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 *stream_in = NULL;
3737 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3738 return -EINVAL;
3739
Zheng Zhang6185d572016-12-01 20:35:17 +08003740 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 -08003741 return -EINVAL;
3742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3744
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003745 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003746 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748 in->stream.common.get_sample_rate = in_get_sample_rate;
3749 in->stream.common.set_sample_rate = in_set_sample_rate;
3750 in->stream.common.get_buffer_size = in_get_buffer_size;
3751 in->stream.common.get_channels = in_get_channels;
3752 in->stream.common.get_format = in_get_format;
3753 in->stream.common.set_format = in_set_format;
3754 in->stream.common.standby = in_standby;
3755 in->stream.common.dump = in_dump;
3756 in->stream.common.set_parameters = in_set_parameters;
3757 in->stream.common.get_parameters = in_get_parameters;
3758 in->stream.common.add_audio_effect = in_add_audio_effect;
3759 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3760 in->stream.set_gain = in_set_gain;
3761 in->stream.read = in_read;
3762 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003763 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764
3765 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003766 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768 in->standby = 1;
3769 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003770 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003771 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772
vivek mehta57ff9b52016-04-28 14:13:08 -07003773 // restrict 24 bit capture for unprocessed source only
3774 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3775 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003776 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003777 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3778 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3779 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3780 bool ret_error = false;
3781 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3782 from HAL is 8_24
3783 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3784 8_24 return error indicating supported format is 8_24
3785 *> In case of any other source requesting 24 bit or float return error
3786 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003787
vivek mehta57ff9b52016-04-28 14:13:08 -07003788 on error flinger will retry with supported format passed
3789 */
3790 if (source != AUDIO_SOURCE_UNPROCESSED) {
3791 config->format = AUDIO_FORMAT_PCM_16_BIT;
3792 ret_error = true;
3793 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3794 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3795 ret_error = true;
3796 }
3797
3798 if (ret_error) {
3799 ret = -EINVAL;
3800 goto err_open;
3801 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003802 }
3803
vivek mehta57ff9b52016-04-28 14:13:08 -07003804 in->format = config->format;
3805
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003807 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3808 if (config->sample_rate == 0)
3809 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3810 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3811 config->sample_rate != 8000) {
3812 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3813 ret = -EINVAL;
3814 goto err_open;
3815 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003816
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003817 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3818 config->format = AUDIO_FORMAT_PCM_16_BIT;
3819 ret = -EINVAL;
3820 goto err_open;
3821 }
3822
3823 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3824 in->config = pcm_config_afe_proxy_record;
3825 } else {
3826 in->usecase = USECASE_AUDIO_RECORD;
3827 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08003828 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003829 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003830#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003831 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003832#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003833 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003834 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08003835 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003836 frame_size = audio_stream_in_frame_size(&in->stream);
3837 buffer_size = get_input_buffer_size(config->sample_rate,
3838 config->format,
3839 channel_count,
3840 is_low_latency);
3841 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003842 in->config.rate = config->sample_rate;
3843 in->af_period_multiplier = 1;
3844 } else {
3845 // period size is left untouched for rt mode playback
3846 in->config = pcm_config_audio_capture_rt;
3847 in->af_period_multiplier = af_period_multiplier;
3848 }
3849 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
3850 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
3851 in->usecase = USECASE_AUDIO_RECORD_MMAP;
3852 in->config = pcm_config_mmap_capture;
3853 in->stream.start = in_start;
3854 in->stream.stop = in_stop;
3855 in->stream.create_mmap_buffer = in_create_mmap_buffer;
3856 in->stream.get_mmap_position = in_get_mmap_position;
3857 in->af_period_multiplier = 1;
3858 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
3859 } else {
3860 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003861 frame_size = audio_stream_in_frame_size(&in->stream);
3862 buffer_size = get_input_buffer_size(config->sample_rate,
3863 config->format,
3864 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003865 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003866 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003867 in->config.rate = config->sample_rate;
3868 in->af_period_multiplier = 1;
3869 }
3870 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3871 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003872 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003873
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003874 in->config.channels = channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003875
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003876 /* This stream could be for sound trigger lab,
3877 get sound trigger pcm if present */
3878 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003879
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003880 lock_input_stream(in);
3881 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3882 pthread_mutex_lock(&adev->lock);
3883 in->card_status = adev->card_status;
3884 pthread_mutex_unlock(&adev->lock);
3885 pthread_mutex_unlock(&in->lock);
3886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003888 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889 return 0;
3890
3891err_open:
3892 free(in);
3893 *stream_in = NULL;
3894 return ret;
3895}
3896
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003897static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898 struct audio_stream_in *stream)
3899{
Eric Laurent994a6932013-07-17 11:51:42 -07003900 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003901
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003902 // must deregister from sndmonitor first to prevent races
3903 // between the callback and close_stream
3904 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003905 in_standby(&stream->common);
3906 free(stream);
3907
3908 return;
3909}
3910
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003911static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912{
3913 return 0;
3914}
3915
Andy Hung31aca912014-03-20 17:14:59 -07003916/* verifies input and output devices and their capabilities.
3917 *
3918 * This verification is required when enabling extended bit-depth or
3919 * sampling rates, as not all qcom products support it.
3920 *
3921 * Suitable for calling only on initialization such as adev_open().
3922 * It fills the audio_device use_case_table[] array.
3923 *
3924 * Has a side-effect that it needs to configure audio routing / devices
3925 * in order to power up the devices and read the device parameters.
3926 * It does not acquire any hw device lock. Should restore the devices
3927 * back to "normal state" upon completion.
3928 */
3929static int adev_verify_devices(struct audio_device *adev)
3930{
3931 /* enumeration is a bit difficult because one really wants to pull
3932 * the use_case, device id, etc from the hidden pcm_device_table[].
3933 * In this case there are the following use cases and device ids.
3934 *
3935 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3936 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3937 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3938 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3939 * [USECASE_AUDIO_RECORD] = {0, 0},
3940 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3941 * [USECASE_VOICE_CALL] = {2, 2},
3942 *
3943 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3944 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3945 */
3946
3947 /* should be the usecases enabled in adev_open_input_stream() */
3948 static const int test_in_usecases[] = {
3949 USECASE_AUDIO_RECORD,
3950 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3951 };
3952 /* should be the usecases enabled in adev_open_output_stream()*/
3953 static const int test_out_usecases[] = {
3954 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3955 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3956 };
3957 static const usecase_type_t usecase_type_by_dir[] = {
3958 PCM_PLAYBACK,
3959 PCM_CAPTURE,
3960 };
3961 static const unsigned flags_by_dir[] = {
3962 PCM_OUT,
3963 PCM_IN,
3964 };
3965
3966 size_t i;
3967 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003968 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003969 char info[512]; /* for possible debug info */
3970
3971 for (dir = 0; dir < 2; ++dir) {
3972 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3973 const unsigned flags_dir = flags_by_dir[dir];
3974 const size_t testsize =
3975 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3976 const int *testcases =
3977 dir ? test_in_usecases : test_out_usecases;
3978 const audio_devices_t audio_device =
3979 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3980
3981 for (i = 0; i < testsize; ++i) {
3982 const audio_usecase_t audio_usecase = testcases[i];
3983 int device_id;
3984 snd_device_t snd_device;
3985 struct pcm_params **pparams;
3986 struct stream_out out;
3987 struct stream_in in;
3988 struct audio_usecase uc_info;
3989 int retval;
3990
3991 pparams = &adev->use_case_table[audio_usecase];
3992 pcm_params_free(*pparams); /* can accept null input */
3993 *pparams = NULL;
3994
3995 /* find the device ID for the use case (signed, for error) */
3996 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3997 if (device_id < 0)
3998 continue;
3999
4000 /* prepare structures for device probing */
4001 memset(&uc_info, 0, sizeof(uc_info));
4002 uc_info.id = audio_usecase;
4003 uc_info.type = usecase_type;
4004 if (dir) {
4005 adev->active_input = &in;
4006 memset(&in, 0, sizeof(in));
4007 in.device = audio_device;
4008 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4009 uc_info.stream.in = &in;
4010 } else {
4011 adev->active_input = NULL;
4012 }
4013 memset(&out, 0, sizeof(out));
4014 out.devices = audio_device; /* only field needed in select_devices */
4015 uc_info.stream.out = &out;
4016 uc_info.devices = audio_device;
4017 uc_info.in_snd_device = SND_DEVICE_NONE;
4018 uc_info.out_snd_device = SND_DEVICE_NONE;
4019 list_add_tail(&adev->usecase_list, &uc_info.list);
4020
4021 /* select device - similar to start_(in/out)put_stream() */
4022 retval = select_devices(adev, audio_usecase);
4023 if (retval >= 0) {
4024 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4025#if LOG_NDEBUG == 0
4026 if (*pparams) {
4027 ALOGV("%s: (%s) card %d device %d", __func__,
4028 dir ? "input" : "output", card_id, device_id);
4029 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004030 } else {
4031 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4032 }
4033#endif
4034 }
4035
4036 /* deselect device - similar to stop_(in/out)put_stream() */
4037 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004038 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004039 /* 2. Disable the rx device */
4040 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004041 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004042 list_remove(&uc_info.list);
4043 }
4044 }
4045 adev->active_input = NULL; /* restore adev state */
4046 return 0;
4047}
4048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004049static int adev_close(hw_device_t *device)
4050{
Andy Hung31aca912014-03-20 17:14:59 -07004051 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004052 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004053
4054 if (!adev)
4055 return 0;
4056
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004057 audio_extn_tfa_98xx_deinit();
4058
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004059 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004060 pthread_mutex_lock(&adev_init_lock);
4061
4062 if ((--audio_device_ref_count) == 0) {
4063 audio_route_free(adev->audio_route);
4064 free(adev->snd_dev_ref_cnt);
4065 platform_deinit(adev->platform);
4066 audio_extn_extspk_deinit(adev->extspk);
4067 audio_extn_sound_trigger_deinit(adev);
4068 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4069 pcm_params_free(adev->use_case_table[i]);
4070 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004071 if (adev->adm_deinit)
4072 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004073 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004074 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004075
4076 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004077
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004078 return 0;
4079}
4080
Glenn Kasten4f993392014-05-14 07:30:48 -07004081/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4082 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4083 * just that it _might_ work.
4084 */
4085static int period_size_is_plausible_for_low_latency(int period_size)
4086{
4087 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004088 case 48:
4089 case 96:
4090 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004091 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004092 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004093 case 240:
4094 case 320:
4095 case 480:
4096 return 1;
4097 default:
4098 return 0;
4099 }
4100}
4101
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004102static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4103{
4104 int card;
4105 card_status_t status;
4106
4107 if (!parms)
4108 return;
4109
4110 if (parse_snd_card_status(parms, &card, &status) < 0)
4111 return;
4112
4113 pthread_mutex_lock(&adev->lock);
4114 bool valid_cb = (card == adev->snd_card);
4115 if (valid_cb) {
4116 if (adev->card_status != status) {
4117 adev->card_status = status;
4118 platform_snd_card_update(adev->platform, status);
4119 }
4120 }
4121 pthread_mutex_unlock(&adev->lock);
4122 return;
4123}
4124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004125static int adev_open(const hw_module_t *module, const char *name,
4126 hw_device_t **device)
4127{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004128 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004129
Eric Laurent2bafff12016-03-17 12:17:23 -07004130 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004131 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004132 pthread_mutex_lock(&adev_init_lock);
4133 if (audio_device_ref_count != 0) {
4134 *device = &adev->device.common;
4135 audio_device_ref_count++;
4136 ALOGV("%s: returning existing instance of adev", __func__);
4137 ALOGV("%s: exit", __func__);
4138 pthread_mutex_unlock(&adev_init_lock);
4139 return 0;
4140 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004141 adev = calloc(1, sizeof(struct audio_device));
4142
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004143 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4144
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004145 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4146 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4147 adev->device.common.module = (struct hw_module_t *)module;
4148 adev->device.common.close = adev_close;
4149
4150 adev->device.init_check = adev_init_check;
4151 adev->device.set_voice_volume = adev_set_voice_volume;
4152 adev->device.set_master_volume = adev_set_master_volume;
4153 adev->device.get_master_volume = adev_get_master_volume;
4154 adev->device.set_master_mute = adev_set_master_mute;
4155 adev->device.get_master_mute = adev_get_master_mute;
4156 adev->device.set_mode = adev_set_mode;
4157 adev->device.set_mic_mute = adev_set_mic_mute;
4158 adev->device.get_mic_mute = adev_get_mic_mute;
4159 adev->device.set_parameters = adev_set_parameters;
4160 adev->device.get_parameters = adev_get_parameters;
4161 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4162 adev->device.open_output_stream = adev_open_output_stream;
4163 adev->device.close_output_stream = adev_close_output_stream;
4164 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004165
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004166 adev->device.close_input_stream = adev_close_input_stream;
4167 adev->device.dump = adev_dump;
4168
4169 /* Set the default route before the PCM stream is opened */
4170 pthread_mutex_lock(&adev->lock);
4171 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004172 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004173 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004174 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004175 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004176 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004177 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004178 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004179 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004180 pthread_mutex_unlock(&adev->lock);
4181
4182 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004183 adev->platform = platform_init(adev);
4184 if (!adev->platform) {
4185 free(adev->snd_dev_ref_cnt);
4186 free(adev);
4187 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4188 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004189 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004190 return -EINVAL;
4191 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004192 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004193 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004194
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004195 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4196 if (adev->visualizer_lib == NULL) {
4197 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4198 } else {
4199 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4200 adev->visualizer_start_output =
4201 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4202 "visualizer_hal_start_output");
4203 adev->visualizer_stop_output =
4204 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4205 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004206 }
4207
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004208 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4209 if (adev->offload_effects_lib == NULL) {
4210 ALOGW("%s: DLOPEN failed for %s", __func__,
4211 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4212 } else {
4213 ALOGV("%s: DLOPEN successful for %s", __func__,
4214 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4215 adev->offload_effects_start_output =
4216 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4217 "offload_effects_bundle_hal_start_output");
4218 adev->offload_effects_stop_output =
4219 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4220 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004221 }
4222
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004223 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4224 if (adev->adm_lib == NULL) {
4225 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4226 } else {
4227 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4228 adev->adm_init = (adm_init_t)
4229 dlsym(adev->adm_lib, "adm_init");
4230 adev->adm_deinit = (adm_deinit_t)
4231 dlsym(adev->adm_lib, "adm_deinit");
4232 adev->adm_register_input_stream = (adm_register_input_stream_t)
4233 dlsym(adev->adm_lib, "adm_register_input_stream");
4234 adev->adm_register_output_stream = (adm_register_output_stream_t)
4235 dlsym(adev->adm_lib, "adm_register_output_stream");
4236 adev->adm_deregister_stream = (adm_deregister_stream_t)
4237 dlsym(adev->adm_lib, "adm_deregister_stream");
4238 adev->adm_request_focus = (adm_request_focus_t)
4239 dlsym(adev->adm_lib, "adm_request_focus");
4240 adev->adm_abandon_focus = (adm_abandon_focus_t)
4241 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004242 adev->adm_set_config = (adm_set_config_t)
4243 dlsym(adev->adm_lib, "adm_set_config");
4244 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4245 dlsym(adev->adm_lib, "adm_request_focus_v2");
4246 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4247 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4248 adev->adm_on_routing_change = (adm_on_routing_change_t)
4249 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004250 }
4251
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004252 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004253 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004255 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004256
Andy Hung31aca912014-03-20 17:14:59 -07004257 if (k_enable_extended_precision)
4258 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004259
Glenn Kasten4f993392014-05-14 07:30:48 -07004260 char value[PROPERTY_VALUE_MAX];
4261 int trial;
4262 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4263 trial = atoi(value);
4264 if (period_size_is_plausible_for_low_latency(trial)) {
4265 pcm_config_low_latency.period_size = trial;
4266 pcm_config_low_latency.start_threshold = trial / 4;
4267 pcm_config_low_latency.avail_min = trial / 4;
4268 configured_low_latency_capture_period_size = trial;
4269 }
4270 }
4271 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4272 trial = atoi(value);
4273 if (period_size_is_plausible_for_low_latency(trial)) {
4274 configured_low_latency_capture_period_size = trial;
4275 }
4276 }
4277
Yamit Mehtae3b99562016-09-16 22:44:00 +05304278 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004279 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004280
4281 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4282 af_period_multiplier = atoi(value);
4283 if (af_period_multiplier < 0) {
4284 af_period_multiplier = 2;
4285 } else if (af_period_multiplier > 4) {
4286 af_period_multiplier = 4;
4287 }
4288 ALOGV("new period_multiplier = %d", af_period_multiplier);
4289 }
4290
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004291 audio_extn_tfa_98xx_init(adev);
4292
vivek mehta1a9b7c02015-06-25 11:49:38 -07004293 pthread_mutex_unlock(&adev_init_lock);
4294
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004295 if (adev->adm_init)
4296 adev->adm_data = adev->adm_init();
4297
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004298 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004299 audio_extn_snd_mon_init();
4300 pthread_mutex_lock(&adev->lock);
4301 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4302 adev->card_status = CARD_STATUS_ONLINE;
4303 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004304
Eric Laurent2bafff12016-03-17 12:17:23 -07004305 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004306 return 0;
4307}
4308
4309static struct hw_module_methods_t hal_module_methods = {
4310 .open = adev_open,
4311};
4312
4313struct audio_module HAL_MODULE_INFO_SYM = {
4314 .common = {
4315 .tag = HARDWARE_MODULE_TAG,
4316 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4317 .hal_api_version = HARDWARE_HAL_API_VERSION,
4318 .id = AUDIO_HARDWARE_MODULE_ID,
4319 .name = "QCOM Audio HAL",
4320 .author = "Code Aurora Forum",
4321 .methods = &hal_module_methods,
4322 },
4323};