blob: b90fda05fb17262e9c1931d4c55fff71995a3c9a [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>
Phil Burkbc991042017-02-24 08:06:44 -080047#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070048#include <audio_effects/effect_aec.h>
49#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080050#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080051#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070052#include "platform_api.h"
53#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070054#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080055
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070056#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080057#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070058
Eric Laurent397db572016-05-11 11:31:47 -070059/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
60 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070061#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070062// 2 buffers causes problems with high bitrate files
63#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064/* ToDo: Check and update a proper value in msec */
65#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
66#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
67
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070068#define PROXY_OPEN_RETRY_COUNT 100
69#define PROXY_OPEN_WAIT_TIME 20
70
vivek mehtadae44712015-07-27 14:13:18 -070071#define MIN_CHANNEL_COUNT 1
72#define DEFAULT_CHANNEL_COUNT 2
73
Jean-Michel Trivic0750692015-10-12 12:12:32 -070074#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
75#define MAX_CHANNEL_COUNT 1
76#else
vivek mehtadae44712015-07-27 14:13:18 -070077#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
78#define XSTR(x) STR(x)
79#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070080#endif
vivek mehtadae44712015-07-27 14:13:18 -070081
Haynes Mathew George03c40102016-01-29 17:57:48 -080082#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
83
Glenn Kasten4f993392014-05-14 07:30:48 -070084static unsigned int configured_low_latency_capture_period_size =
85 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
86
Eric Laurent0e46adf2016-12-16 12:49:24 -080087
88#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080089#define MMAP_PERIOD_COUNT_MIN 32
90#define MMAP_PERIOD_COUNT_MAX 512
91#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -080092
93
Andy Hung31aca912014-03-20 17:14:59 -070094/* This constant enables extended precision handling.
95 * TODO The flag is off until more testing is done.
96 */
97static const bool k_enable_extended_precision = false;
98
Eric Laurentb23d5282013-05-14 15:27:20 -070099struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700100 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700101 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
102 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
103 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
104 .format = PCM_FORMAT_S16_LE,
105 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
106 .stop_threshold = INT_MAX,
107 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
108};
109
110struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700111 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700112 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
113 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
114 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
115 .format = PCM_FORMAT_S16_LE,
116 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
117 .stop_threshold = INT_MAX,
118 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
119};
120
Haynes Mathew George03c40102016-01-29 17:57:48 -0800121static int af_period_multiplier = 4;
122struct pcm_config pcm_config_rt = {
123 .channels = DEFAULT_CHANNEL_COUNT,
124 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
125 .period_size = ULL_PERIOD_SIZE, //1 ms
126 .period_count = 512, //=> buffer size is 512ms
127 .format = PCM_FORMAT_S16_LE,
128 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
129 .stop_threshold = INT_MAX,
130 .silence_threshold = 0,
131 .silence_size = 0,
132 .avail_min = ULL_PERIOD_SIZE, //1 ms
133};
134
Eric Laurentb23d5282013-05-14 15:27:20 -0700135struct pcm_config pcm_config_hdmi_multi = {
136 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
137 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
138 .period_size = HDMI_MULTI_PERIOD_SIZE,
139 .period_count = HDMI_MULTI_PERIOD_COUNT,
140 .format = PCM_FORMAT_S16_LE,
141 .start_threshold = 0,
142 .stop_threshold = INT_MAX,
143 .avail_min = 0,
144};
145
Eric Laurent0e46adf2016-12-16 12:49:24 -0800146struct pcm_config pcm_config_mmap_playback = {
147 .channels = DEFAULT_CHANNEL_COUNT,
148 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
149 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800150 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800151 .format = PCM_FORMAT_S16_LE,
152 .start_threshold = MMAP_PERIOD_SIZE*8,
153 .stop_threshold = INT32_MAX,
154 .silence_threshold = 0,
155 .silence_size = 0,
156 .avail_min = MMAP_PERIOD_SIZE, //1 ms
157};
158
Eric Laurentb23d5282013-05-14 15:27:20 -0700159struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700160 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700161 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
162 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700163 .stop_threshold = INT_MAX,
164 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700165};
166
Haynes Mathew George03c40102016-01-29 17:57:48 -0800167struct pcm_config pcm_config_audio_capture_rt = {
168 .channels = DEFAULT_CHANNEL_COUNT,
169 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
170 .period_size = ULL_PERIOD_SIZE,
171 .period_count = 512,
172 .format = PCM_FORMAT_S16_LE,
173 .start_threshold = 0,
174 .stop_threshold = INT_MAX,
175 .silence_threshold = 0,
176 .silence_size = 0,
177 .avail_min = ULL_PERIOD_SIZE, //1 ms
178};
179
Eric Laurent0e46adf2016-12-16 12:49:24 -0800180struct pcm_config pcm_config_mmap_capture = {
181 .channels = DEFAULT_CHANNEL_COUNT,
182 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
183 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800184 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800185 .format = PCM_FORMAT_S16_LE,
186 .start_threshold = 0,
187 .stop_threshold = INT_MAX,
188 .silence_threshold = 0,
189 .silence_size = 0,
190 .avail_min = MMAP_PERIOD_SIZE, //1 ms
191};
192
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700193#define AFE_PROXY_CHANNEL_COUNT 2
194#define AFE_PROXY_SAMPLING_RATE 48000
195
196#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
197#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
198
199struct pcm_config pcm_config_afe_proxy_playback = {
200 .channels = AFE_PROXY_CHANNEL_COUNT,
201 .rate = AFE_PROXY_SAMPLING_RATE,
202 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
203 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
204 .format = PCM_FORMAT_S16_LE,
205 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
206 .stop_threshold = INT_MAX,
207 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
208};
209
210#define AFE_PROXY_RECORD_PERIOD_SIZE 768
211#define AFE_PROXY_RECORD_PERIOD_COUNT 4
212
213struct pcm_config pcm_config_afe_proxy_record = {
214 .channels = AFE_PROXY_CHANNEL_COUNT,
215 .rate = AFE_PROXY_SAMPLING_RATE,
216 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
217 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
218 .format = PCM_FORMAT_S16_LE,
219 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
220 .stop_threshold = INT_MAX,
221 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
222};
223
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700224const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700225 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
226 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
227 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700228 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700229 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700230 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800231 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700232
Eric Laurentb23d5282013-05-14 15:27:20 -0700233 [USECASE_AUDIO_RECORD] = "audio-record",
234 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800235 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700236
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800237 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
238 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700239
Eric Laurentb23d5282013-05-14 15:27:20 -0700240 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700241 [USECASE_VOICE2_CALL] = "voice2-call",
242 [USECASE_VOLTE_CALL] = "volte-call",
243 [USECASE_QCHAT_CALL] = "qchat-call",
244 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800245 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
246 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700247
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700248 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
249 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
250
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700251 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
252 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700253};
254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800255
256#define STRING_TO_ENUM(string) { #string, string }
257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800258struct string_to_enum {
259 const char *name;
260 uint32_t value;
261};
262
263static const struct string_to_enum out_channels_name_to_enum_table[] = {
264 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
265 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
266 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
267};
268
Haynes Mathew George5191a852013-09-11 14:19:36 -0700269static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700270static struct audio_device *adev = NULL;
271static pthread_mutex_t adev_init_lock;
272static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700273//cache last MBDRC cal step level
274static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700275
Haynes Mathew George03c40102016-01-29 17:57:48 -0800276static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
277 int flags __unused)
278{
279 int dir = 0;
280 switch (uc_id) {
281 case USECASE_AUDIO_RECORD_LOW_LATENCY:
282 dir = 1;
283 case USECASE_AUDIO_PLAYBACK_ULL:
284 break;
285 default:
286 return false;
287 }
288
289 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
290 PCM_PLAYBACK : PCM_CAPTURE);
291 if (adev->adm_is_noirq_avail)
292 return adev->adm_is_noirq_avail(adev->adm_data,
293 adev->snd_card, dev_id, dir);
294 return false;
295}
296
297static void register_out_stream(struct stream_out *out)
298{
299 struct audio_device *adev = out->dev;
300 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
301 return;
302
303 if (!adev->adm_register_output_stream)
304 return;
305
306 adev->adm_register_output_stream(adev->adm_data,
307 out->handle,
308 out->flags);
309
310 if (!adev->adm_set_config)
311 return;
312
313 if (out->realtime) {
314 adev->adm_set_config(adev->adm_data,
315 out->handle,
316 out->pcm, &out->config);
317 }
318}
319
320static void register_in_stream(struct stream_in *in)
321{
322 struct audio_device *adev = in->dev;
323 if (!adev->adm_register_input_stream)
324 return;
325
326 adev->adm_register_input_stream(adev->adm_data,
327 in->capture_handle,
328 in->flags);
329
330 if (!adev->adm_set_config)
331 return;
332
333 if (in->realtime) {
334 adev->adm_set_config(adev->adm_data,
335 in->capture_handle,
336 in->pcm,
337 &in->config);
338 }
339}
340
341static void request_out_focus(struct stream_out *out, long ns)
342{
343 struct audio_device *adev = out->dev;
344
345 if (out->routing_change) {
346 out->routing_change = false;
347 if (adev->adm_on_routing_change)
348 adev->adm_on_routing_change(adev->adm_data, out->handle);
349 }
350
351 if (adev->adm_request_focus_v2) {
352 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
353 } else if (adev->adm_request_focus) {
354 adev->adm_request_focus(adev->adm_data, out->handle);
355 }
356}
357
358static void request_in_focus(struct stream_in *in, long ns)
359{
360 struct audio_device *adev = in->dev;
361
362 if (in->routing_change) {
363 in->routing_change = false;
364 if (adev->adm_on_routing_change)
365 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
366 }
367
368 if (adev->adm_request_focus_v2) {
369 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
370 } else if (adev->adm_request_focus) {
371 adev->adm_request_focus(adev->adm_data, in->capture_handle);
372 }
373}
374
375static void release_out_focus(struct stream_out *out, long ns __unused)
376{
377 struct audio_device *adev = out->dev;
378
379 if (adev->adm_abandon_focus)
380 adev->adm_abandon_focus(adev->adm_data, out->handle);
381}
382
383static void release_in_focus(struct stream_in *in, long ns __unused)
384{
385 struct audio_device *adev = in->dev;
386 if (adev->adm_abandon_focus)
387 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
388}
389
Andy Hung7401c7c2016-09-21 12:41:21 -0700390// Time string format similar to logcat, buffer_length must be >= 19 chars.
391static void ns2string(int64_t ns, char *buffer, int buffer_length)
392{
393 const int one_second = 1000000000;
394 const time_t sec = ns / one_second;
395 struct tm tm;
396 localtime_r(&sec, &tm);
397 snprintf(buffer, buffer_length, "%02d-%02d %02d:%02d:%02d.%03d",
398 tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range
399 tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
400 (int)(ns % one_second / 1000000));
401}
402
403// Convert timespec to nsec.
404static int64_t ts2ns(const struct timespec *ts)
405{
406 return ts->tv_sec * 1000000000LL + ts->tv_nsec;
407}
408
409// Log errors: consecutive errors with the same code will
410// be aggregated if they occur within one second.
411// A mutual exclusion lock must be held before calling.
412static void log_error_l(struct error_log *log, int code) {
413 ++log->errors;
414
415 struct timespec now_ts = { 0, 0 };
416 (void)clock_gettime(CLOCK_REALTIME, &now_ts);
417 const int64_t now = ts2ns(&now_ts);
418
419 // Within 1 second, cluster the same error codes together.
420 const int one_second = 1000000000;
421 if (code == log->entries[log->idx].code &&
422 now - log->entries[log->idx].last_time < one_second) {
423 log->entries[log->idx].count++;
424 log->entries[log->idx].last_time = now;
425 return;
426 }
427
428 // Add new error entry.
429 if (++log->idx >= ARRAY_SIZE(log->entries)) {
430 log->idx = 0;
431 }
432 log->entries[log->idx].count = 1;
433 log->entries[log->idx].code = code;
434 log->entries[log->idx].first_time = now;
435 log->entries[log->idx].last_time = now;
436}
437
438// Dump information in the error log. A mutual exclusion lock
439// should be held, but if that cannot be obtained, one should
440// make a copy of the error log before calling -- the call is
441// still safe, but there might be some misinterpreted data.
442static void log_dump_l(const struct error_log *log, int fd)
443{
444 dprintf(fd, " Errors: %u\n", log->errors);
445 if (log->errors == 0)
446 return;
447
448 dprintf(fd, " Index Code Freq First time Last time\n");
449 for (size_t i = 0; i < ARRAY_SIZE(log->entries); ++i) {
450 if (log->entries[i].count != 0) {
451 char first_time[32];
452 char last_time[32];
453 ns2string(log->entries[i].first_time, first_time, sizeof(first_time));
454 ns2string(log->entries[i].last_time, last_time, sizeof(last_time));
455 dprintf(fd, " %c%4zu %4d %5d %s %s\n",
456 i == log->idx ? '*' : ' ', // mark head position
457 i, log->entries[i].code, log->entries[i].count,
458 first_time, last_time);
459 }
460 }
461}
462
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700463static int parse_snd_card_status(struct str_parms * parms, int * card,
464 card_status_t * status)
465{
466 char value[32]={0};
467 char state[32]={0};
468
469 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
470
471 if (ret < 0)
472 return -1;
473
474 // sscanf should be okay as value is of max length 32.
475 // same as sizeof state.
476 if (sscanf(value, "%d,%s", card, state) < 2)
477 return -1;
478
479 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
480 CARD_STATUS_OFFLINE;
481 return 0;
482}
483
vivek mehta1a9b7c02015-06-25 11:49:38 -0700484__attribute__ ((visibility ("default")))
485bool audio_hw_send_gain_dep_calibration(int level) {
486 bool ret_val = false;
487 ALOGV("%s: enter ... ", __func__);
488
489 pthread_mutex_lock(&adev_init_lock);
490
491 if (adev != NULL && adev->platform != NULL) {
492 pthread_mutex_lock(&adev->lock);
493 ret_val = platform_send_gain_dep_cal(adev->platform, level);
494 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700495
496 // if cal set fails, cache level info
497 // if cal set succeds, reset known last cal set
498 if (!ret_val)
499 last_known_cal_step = level;
500 else if (last_known_cal_step != -1)
501 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700502 } else {
503 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
504 }
505
506 pthread_mutex_unlock(&adev_init_lock);
507
508 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
509 return ret_val;
510}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700511
vivek mehtaa8d7c922016-05-25 14:40:44 -0700512__attribute__ ((visibility ("default")))
513int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
514 int table_size) {
515 int ret_val = 0;
516 ALOGV("%s: enter ... ", __func__);
517
518 pthread_mutex_lock(&adev_init_lock);
519 if (adev == NULL) {
520 ALOGW("%s: adev is NULL .... ", __func__);
521 goto done;
522 }
523
524 pthread_mutex_lock(&adev->lock);
525 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
526 pthread_mutex_unlock(&adev->lock);
527done:
528 pthread_mutex_unlock(&adev_init_lock);
529 ALOGV("%s: exit ... ", __func__);
530 return ret_val;
531}
532
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700533static bool is_supported_format(audio_format_t format)
534{
Eric Laurent8251ac82014-07-23 11:00:25 -0700535 switch (format) {
536 case AUDIO_FORMAT_MP3:
537 case AUDIO_FORMAT_AAC_LC:
538 case AUDIO_FORMAT_AAC_HE_V1:
539 case AUDIO_FORMAT_AAC_HE_V2:
540 return true;
541 default:
542 break;
543 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700544 return false;
545}
546
Haynes Mathew George03c40102016-01-29 17:57:48 -0800547static inline bool is_mmap_usecase(audio_usecase_t uc_id)
548{
549 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
550 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
551}
552
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700553static int get_snd_codec_id(audio_format_t format)
554{
555 int id = 0;
556
Eric Laurent8251ac82014-07-23 11:00:25 -0700557 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700558 case AUDIO_FORMAT_MP3:
559 id = SND_AUDIOCODEC_MP3;
560 break;
561 case AUDIO_FORMAT_AAC:
562 id = SND_AUDIOCODEC_AAC;
563 break;
564 default:
565 ALOGE("%s: Unsupported audio format", __func__);
566 }
567
568 return id;
569}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800570
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800571static int audio_ssr_status(struct audio_device *adev)
572{
573 int ret = 0;
574 struct mixer_ctl *ctl;
575 const char *mixer_ctl_name = "Audio SSR Status";
576
577 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
578 ret = mixer_ctl_get_value(ctl, 0);
579 ALOGD("%s: value: %d", __func__, ret);
580 return ret;
581}
582
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800583int enable_audio_route(struct audio_device *adev,
584 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800585{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700586 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800587 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800588
589 if (usecase == NULL)
590 return -EINVAL;
591
592 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
593
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800594 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800596 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700597 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800598
Yamit Mehtae3b99562016-09-16 22:44:00 +0530599 audio_extn_utils_send_app_type_cfg(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800600 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500601 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700602 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700603 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800605 ALOGV("%s: exit", __func__);
606 return 0;
607}
608
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800609int disable_audio_route(struct audio_device *adev,
610 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800611{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700612 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800613 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800614
615 if (usecase == NULL)
616 return -EINVAL;
617
618 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700619 if (usecase->type == PCM_CAPTURE)
620 snd_device = usecase->in_snd_device;
621 else
622 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800623 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500624 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700625 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700626 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800627
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800628 ALOGV("%s: exit", __func__);
629 return 0;
630}
631
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800632int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700633 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800634{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700635 int i, num_devices = 0;
636 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800637 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800638 if (snd_device < SND_DEVICE_MIN ||
639 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800640 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800641 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800642 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700643
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700644 platform_send_audio_calibration(adev->platform, snd_device);
645
vivek mehtade4849c2016-03-03 17:23:38 -0800646 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700647 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700648 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800649 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700650 }
651
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700652 /* due to the possibility of calibration overwrite between listen
653 and audio, notify sound trigger hal before audio calibration is sent */
654 audio_extn_sound_trigger_update_device_status(snd_device,
655 ST_EVENT_SND_DEVICE_BUSY);
656
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700657 if (audio_extn_spkr_prot_is_enabled())
658 audio_extn_spkr_prot_calib_cancel(adev);
659
zhaoyang yin4211fad2015-06-04 21:13:25 +0800660 audio_extn_dsm_feedback_enable(adev, snd_device, true);
661
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700662 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
663 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
664 audio_extn_spkr_prot_is_enabled()) {
665 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800666 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700667 }
668 if (audio_extn_spkr_prot_start_processing(snd_device)) {
669 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800670 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700671 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700672 } else if (platform_can_split_snd_device(snd_device,
673 &num_devices,
674 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700675 for (i = 0; i < num_devices; i++) {
676 enable_snd_device(adev, new_snd_devices[i]);
677 }
vivek mehtab6506412015-08-07 16:55:17 -0700678 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700679 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800680 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
681 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
682 ALOGE(" %s: Invalid sound device returned", __func__);
683 goto on_error;
684 }
Ed Tam70b5c142016-03-21 19:14:29 -0700685
Eric Laurent2e140aa2016-06-30 17:14:46 -0700686 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800687 audio_route_apply_and_update_path(adev->audio_route, device_name);
688 }
689on_success:
690 adev->snd_dev_ref_cnt[snd_device]++;
691 ret_val = 0;
692on_error:
693 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800694}
695
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800696int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700697 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800698{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700699 int i, num_devices = 0;
700 snd_device_t new_snd_devices[2];
701
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800702 if (snd_device < SND_DEVICE_MIN ||
703 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800704 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800705 return -EINVAL;
706 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700707 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
708 ALOGE("%s: device ref cnt is already 0", __func__);
709 return -EINVAL;
710 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800711 audio_extn_tfa_98xx_disable_speaker(snd_device);
712
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 adev->snd_dev_ref_cnt[snd_device]--;
714 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800715 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700716 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
717 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
718 audio_extn_spkr_prot_is_enabled()) {
719 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700720 } else if (platform_can_split_snd_device(snd_device,
721 &num_devices,
722 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700723 for (i = 0; i < num_devices; i++) {
724 disable_snd_device(adev, new_snd_devices[i]);
725 }
vivek mehtab6506412015-08-07 16:55:17 -0700726 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700727 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800728 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
729 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
730 ALOGE(" %s: Invalid sound device returned", __func__);
731 return -EINVAL;
732 }
733
Eric Laurent2e140aa2016-06-30 17:14:46 -0700734 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800735 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700736 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700737 audio_extn_sound_trigger_update_device_status(snd_device,
738 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700739 }
vivek mehtab6506412015-08-07 16:55:17 -0700740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800741 return 0;
742}
743
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700744/*
745 legend:
746 uc - existing usecase
747 new_uc - new usecase
748 d1, d11, d2 - SND_DEVICE enums
749 a1, a2 - corresponding ANDROID device enums
750 B, B1, B2 - backend strings
751
752case 1
753 uc->dev d1 (a1) B1
754 new_uc->dev d1 (a1), d2 (a2) B1, B2
755
756 resolution: disable and enable uc->dev on d1
757
758case 2
759 uc->dev d1 (a1) B1
760 new_uc->dev d11 (a1) B1
761
762 resolution: need to switch uc since d1 and d11 are related
763 (e.g. speaker and voice-speaker)
764 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
765
766case 3
767 uc->dev d1 (a1) B1
768 new_uc->dev d2 (a2) B2
769
770 resolution: no need to switch uc
771
772case 4
773 uc->dev d1 (a1) B
774 new_uc->dev d2 (a2) B
775
776 resolution: disable enable uc-dev on d2 since backends match
777 we cannot enable two streams on two different devices if they
778 share the same backend. e.g. if offload is on speaker device using
779 QUAD_MI2S backend and a low-latency stream is started on voice-handset
780 using the same backend, offload must also be switched to voice-handset.
781
782case 5
783 uc->dev d1 (a1) B
784 new_uc->dev d1 (a1), d2 (a2) B
785
786 resolution: disable enable uc-dev on d2 since backends match
787 we cannot enable two streams on two different devices if they
788 share the same backend.
789
790case 6
791 uc->dev d1 a1 B1
792 new_uc->dev d2 a1 B2
793
794 resolution: no need to switch
795
796case 7
797
798 uc->dev d1 (a1), d2 (a2) B1, B2
799 new_uc->dev d1 B1
800
801 resolution: no need to switch
802
803*/
804static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
805 struct audio_usecase *new_uc,
806 snd_device_t new_snd_device)
807{
808 audio_devices_t a1 = uc->stream.out->devices;
809 audio_devices_t a2 = new_uc->stream.out->devices;
810
811 snd_device_t d1 = uc->out_snd_device;
812 snd_device_t d2 = new_snd_device;
813
814 // Treat as a special case when a1 and a2 are not disjoint
815 if ((a1 != a2) && (a1 & a2)) {
816 snd_device_t d3[2];
817 int num_devices = 0;
818 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
819 &num_devices,
820 d3);
821 if (ret < 0) {
822 if (ret != -ENOSYS) {
823 ALOGW("%s failed to split snd_device %d",
824 __func__,
825 popcount(a1) > 1 ? d1 : d2);
826 }
827 goto end;
828 }
829
830 // NB: case 7 is hypothetical and isn't a practical usecase yet.
831 // But if it does happen, we need to give priority to d2 if
832 // the combo devices active on the existing usecase share a backend.
833 // This is because we cannot have a usecase active on a combo device
834 // and a new usecase requests one device in this combo pair.
835 if (platform_check_backends_match(d3[0], d3[1])) {
836 return d2; // case 5
837 } else {
838 return d1; // case 1
839 }
840 } else {
841 if (platform_check_backends_match(d1, d2)) {
842 return d2; // case 2, 4
843 } else {
844 return d1; // case 6, 3
845 }
846 }
847
848end:
849 return d2; // return whatever was calculated before.
850}
851
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700852static void check_and_route_playback_usecases(struct audio_device *adev,
853 struct audio_usecase *uc_info,
854 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855{
856 struct listnode *node;
857 struct audio_usecase *usecase;
858 bool switch_device[AUDIO_USECASE_MAX];
859 int i, num_uc_to_switch = 0;
860
861 /*
862 * This function is to make sure that all the usecases that are active on
863 * the hardware codec backend are always routed to any one device that is
864 * handled by the hardware codec.
865 * For example, if low-latency and deep-buffer usecases are currently active
866 * on speaker and out_set_parameters(headset) is received on low-latency
867 * output, then we have to make sure deep-buffer is also switched to headset,
868 * because of the limitation that both the devices cannot be enabled
869 * at the same time as they share the same backend.
870 */
871 /* Disable all the usecases on the shared backend other than the
872 specified usecase */
873 for (i = 0; i < AUDIO_USECASE_MAX; i++)
874 switch_device[i] = false;
875
876 list_for_each(node, &adev->usecase_list) {
877 usecase = node_to_item(node, struct audio_usecase, list);
878 if (usecase->type != PCM_CAPTURE &&
879 usecase != uc_info &&
880 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700881 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
882 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700883 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
884 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700885 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700886 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700887 switch_device[usecase->id] = true;
888 num_uc_to_switch++;
889 }
890 }
891
892 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 list_for_each(node, &adev->usecase_list) {
894 usecase = node_to_item(node, struct audio_usecase, list);
895 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700896 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900897 }
898 }
899
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700900 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900901 list_for_each(node, &adev->usecase_list) {
902 usecase = node_to_item(node, struct audio_usecase, list);
903 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700904 d_device = derive_playback_snd_device(usecase, uc_info,
905 snd_device);
906 enable_snd_device(adev, d_device);
907 /* Update the out_snd_device before enabling the audio route */
908 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700909 }
910 }
911
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700912 /* Re-route all the usecases on the shared backend other than the
913 specified usecase to new snd devices */
914 list_for_each(node, &adev->usecase_list) {
915 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700917 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700918 }
919 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700920 }
921}
922
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700923static void check_and_route_capture_usecases(struct audio_device *adev,
924 struct audio_usecase *uc_info,
925 snd_device_t snd_device)
926{
927 struct listnode *node;
928 struct audio_usecase *usecase;
929 bool switch_device[AUDIO_USECASE_MAX];
930 int i, num_uc_to_switch = 0;
931
vivek mehta4ed66e62016-04-15 23:33:34 -0700932 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
933
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700934 /*
935 * This function is to make sure that all the active capture usecases
936 * are always routed to the same input sound device.
937 * For example, if audio-record and voice-call usecases are currently
938 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
939 * is received for voice call then we have to make sure that audio-record
940 * usecase is also switched to earpiece i.e. voice-dmic-ef,
941 * because of the limitation that two devices cannot be enabled
942 * at the same time if they share the same backend.
943 */
944 for (i = 0; i < AUDIO_USECASE_MAX; i++)
945 switch_device[i] = false;
946
947 list_for_each(node, &adev->usecase_list) {
948 usecase = node_to_item(node, struct audio_usecase, list);
949 if (usecase->type != PCM_PLAYBACK &&
950 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700951 usecase->in_snd_device != snd_device &&
952 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700953 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
954 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700955 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700956 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700957 switch_device[usecase->id] = true;
958 num_uc_to_switch++;
959 }
960 }
961
962 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700963 list_for_each(node, &adev->usecase_list) {
964 usecase = node_to_item(node, struct audio_usecase, list);
965 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700966 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700967 }
968 }
969
970 list_for_each(node, &adev->usecase_list) {
971 usecase = node_to_item(node, struct audio_usecase, list);
972 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700973 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700974 }
975 }
976
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700977 /* Re-route all the usecases on the shared backend other than the
978 specified usecase to new snd devices */
979 list_for_each(node, &adev->usecase_list) {
980 usecase = node_to_item(node, struct audio_usecase, list);
981 /* Update the in_snd_device only before enabling the audio route */
982 if (switch_device[usecase->id] ) {
983 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700984 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700985 }
986 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700987 }
988}
989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800990/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700991static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800992{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700993 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700994 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800995
996 switch (channels) {
997 /*
998 * Do not handle stereo output in Multi-channel cases
999 * Stereo case is handled in normal playback path
1000 */
1001 case 6:
1002 ALOGV("%s: HDMI supports 5.1", __func__);
1003 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1004 break;
1005 case 8:
1006 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1007 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1008 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1009 break;
1010 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001011 ALOGE("HDMI does not support multi channel playback");
1012 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001013 break;
1014 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001015 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001016}
1017
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001018static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1019{
1020 struct audio_usecase *usecase;
1021 struct listnode *node;
1022
1023 list_for_each(node, &adev->usecase_list) {
1024 usecase = node_to_item(node, struct audio_usecase, list);
1025 if (usecase->type == VOICE_CALL) {
1026 ALOGV("%s: usecase id %d", __func__, usecase->id);
1027 return usecase->id;
1028 }
1029 }
1030 return USECASE_INVALID;
1031}
1032
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001033struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1034 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001035{
1036 struct audio_usecase *usecase;
1037 struct listnode *node;
1038
1039 list_for_each(node, &adev->usecase_list) {
1040 usecase = node_to_item(node, struct audio_usecase, list);
1041 if (usecase->id == uc_id)
1042 return usecase;
1043 }
1044 return NULL;
1045}
1046
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001047int select_devices(struct audio_device *adev,
1048 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001050 snd_device_t out_snd_device = SND_DEVICE_NONE;
1051 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001052 struct audio_usecase *usecase = NULL;
1053 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001054 struct audio_usecase *hfp_usecase = NULL;
1055 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001056 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001057 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001059 usecase = get_usecase_from_list(adev, uc_id);
1060 if (usecase == NULL) {
1061 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1062 return -EINVAL;
1063 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001064
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001065 if ((usecase->type == VOICE_CALL) ||
1066 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001067 out_snd_device = platform_get_output_snd_device(adev->platform,
1068 usecase->stream.out->devices);
1069 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001070 usecase->devices = usecase->stream.out->devices;
1071 } else {
1072 /*
1073 * If the voice call is active, use the sound devices of voice call usecase
1074 * so that it would not result any device switch. All the usecases will
1075 * be switched to new device when select_devices() is called for voice call
1076 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001077 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001078 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001079 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001080 vc_usecase = get_usecase_from_list(adev,
1081 get_voice_usecase_id_from_list(adev));
1082 if ((vc_usecase != NULL) &&
1083 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1084 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001085 in_snd_device = vc_usecase->in_snd_device;
1086 out_snd_device = vc_usecase->out_snd_device;
1087 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001088 } else if (audio_extn_hfp_is_active(adev)) {
1089 hfp_ucid = audio_extn_hfp_get_usecase();
1090 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1091 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1092 in_snd_device = hfp_usecase->in_snd_device;
1093 out_snd_device = hfp_usecase->out_snd_device;
1094 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001095 }
1096 if (usecase->type == PCM_PLAYBACK) {
1097 usecase->devices = usecase->stream.out->devices;
1098 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001099 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001100 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001101 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001102 if (usecase->stream.out == adev->primary_output &&
1103 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001104 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1105 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001106 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001107 select_devices(adev, adev->active_input->usecase);
1108 }
1109 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001110 } else if (usecase->type == PCM_CAPTURE) {
1111 usecase->devices = usecase->stream.in->device;
1112 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001113 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001114 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001115 if (adev->active_input &&
1116 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1117 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001118 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001119 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1120 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1121 } else if (adev->primary_output) {
1122 out_device = adev->primary_output->devices;
1123 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001124 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001125 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001126 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001127 }
1128 }
1129
1130 if (out_snd_device == usecase->out_snd_device &&
1131 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001132 return 0;
1133 }
1134
Eric Laurent2bafff12016-03-17 12:17:23 -07001135 if (out_snd_device != SND_DEVICE_NONE &&
1136 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1137 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1138 __func__,
1139 use_case_table[uc_id],
1140 adev->last_logged_snd_device[uc_id][0],
1141 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1142 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1143 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1144 -1,
1145 out_snd_device,
1146 platform_get_snd_device_name(out_snd_device),
1147 platform_get_snd_device_acdb_id(out_snd_device));
1148 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1149 }
1150 if (in_snd_device != SND_DEVICE_NONE &&
1151 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1152 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1153 __func__,
1154 use_case_table[uc_id],
1155 adev->last_logged_snd_device[uc_id][1],
1156 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1157 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1158 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1159 -1,
1160 in_snd_device,
1161 platform_get_snd_device_name(in_snd_device),
1162 platform_get_snd_device_acdb_id(in_snd_device));
1163 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1164 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001165
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001166 /*
1167 * Limitation: While in call, to do a device switch we need to disable
1168 * and enable both RX and TX devices though one of them is same as current
1169 * device.
1170 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001171 if ((usecase->type == VOICE_CALL) &&
1172 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1173 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001174 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001175 /* Disable sidetone only if voice call already exists */
1176 if (voice_is_call_state_active(adev))
1177 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001178 }
1179
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001180 /* Disable current sound devices */
1181 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001182 disable_audio_route(adev, usecase);
1183 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001184 }
1185
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001186 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001187 disable_audio_route(adev, usecase);
1188 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001189 }
1190
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001191 /* Applicable only on the targets that has external modem.
1192 * New device information should be sent to modem before enabling
1193 * the devices to reduce in-call device switch time.
1194 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001195 if ((usecase->type == VOICE_CALL) &&
1196 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1197 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001198 status = platform_switch_voice_call_enable_device_config(adev->platform,
1199 out_snd_device,
1200 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001201 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001202
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001203 /* Enable new sound devices */
1204 if (out_snd_device != SND_DEVICE_NONE) {
Mikhail Naganov9d677f42017-03-09 16:57:59 +00001205 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
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) {
Phil Burkbc991042017-02-24 08:06:44 -08001316 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001317 ALOGE("%s: pcm stream not ready", __func__);
1318 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001319 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001320 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001321 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001322 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1323 goto error_open;
1324 }
1325 } else {
1326 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1327 unsigned int pcm_open_retry_count = 0;
1328
1329 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1330 flags |= PCM_MMAP | PCM_NOIRQ;
1331 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1332 } else if (in->realtime) {
1333 flags |= PCM_MMAP | PCM_NOIRQ;
1334 }
1335
1336 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1337 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1338
1339 while (1) {
1340 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1341 flags, &in->config);
1342 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1343 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1344 if (in->pcm != NULL) {
1345 pcm_close(in->pcm);
1346 in->pcm = NULL;
1347 }
1348 if (pcm_open_retry_count-- == 0) {
1349 ret = -EIO;
1350 goto error_open;
1351 }
1352 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1353 continue;
1354 }
1355 break;
1356 }
1357
1358 ALOGV("%s: pcm_prepare", __func__);
1359 ret = pcm_prepare(in->pcm);
1360 if (ret < 0) {
1361 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001362 pcm_close(in->pcm);
1363 in->pcm = NULL;
1364 goto error_open;
1365 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001366 if (in->realtime) {
1367 ret = pcm_start(in->pcm);
1368 if (ret < 0) {
1369 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1370 pcm_close(in->pcm);
1371 in->pcm = NULL;
1372 goto error_open;
1373 }
1374 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001375 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001376 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001377 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001378 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001379
Eric Laurent0e46adf2016-12-16 12:49:24 -08001380 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001381
1382error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001383 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001384 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001385
1386error_config:
1387 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001388 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001389
1390 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001391}
1392
Eric Laurenta1478072015-09-21 17:21:52 -07001393void lock_input_stream(struct stream_in *in)
1394{
1395 pthread_mutex_lock(&in->pre_lock);
1396 pthread_mutex_lock(&in->lock);
1397 pthread_mutex_unlock(&in->pre_lock);
1398}
1399
1400void lock_output_stream(struct stream_out *out)
1401{
1402 pthread_mutex_lock(&out->pre_lock);
1403 pthread_mutex_lock(&out->lock);
1404 pthread_mutex_unlock(&out->pre_lock);
1405}
1406
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001407/* must be called with out->lock locked */
1408static int send_offload_cmd_l(struct stream_out* out, int command)
1409{
1410 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1411
1412 ALOGVV("%s %d", __func__, command);
1413
1414 cmd->cmd = command;
1415 list_add_tail(&out->offload_cmd_list, &cmd->node);
1416 pthread_cond_signal(&out->offload_cond);
1417 return 0;
1418}
1419
1420/* must be called iwth out->lock locked */
1421static void stop_compressed_output_l(struct stream_out *out)
1422{
1423 out->offload_state = OFFLOAD_STATE_IDLE;
1424 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001425 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001426 if (out->compr != NULL) {
1427 compress_stop(out->compr);
1428 while (out->offload_thread_blocked) {
1429 pthread_cond_wait(&out->cond, &out->lock);
1430 }
1431 }
1432}
1433
1434static void *offload_thread_loop(void *context)
1435{
1436 struct stream_out *out = (struct stream_out *) context;
1437 struct listnode *item;
1438
1439 out->offload_state = OFFLOAD_STATE_IDLE;
1440 out->playback_started = 0;
1441
1442 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1443 set_sched_policy(0, SP_FOREGROUND);
1444 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1445
1446 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001447 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001448 for (;;) {
1449 struct offload_cmd *cmd = NULL;
1450 stream_callback_event_t event;
1451 bool send_callback = false;
1452
1453 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1454 __func__, list_empty(&out->offload_cmd_list),
1455 out->offload_state);
1456 if (list_empty(&out->offload_cmd_list)) {
1457 ALOGV("%s SLEEPING", __func__);
1458 pthread_cond_wait(&out->offload_cond, &out->lock);
1459 ALOGV("%s RUNNING", __func__);
1460 continue;
1461 }
1462
1463 item = list_head(&out->offload_cmd_list);
1464 cmd = node_to_item(item, struct offload_cmd, node);
1465 list_remove(item);
1466
1467 ALOGVV("%s STATE %d CMD %d out->compr %p",
1468 __func__, out->offload_state, cmd->cmd, out->compr);
1469
1470 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1471 free(cmd);
1472 break;
1473 }
1474
1475 if (out->compr == NULL) {
1476 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001477 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001478 pthread_cond_signal(&out->cond);
1479 continue;
1480 }
1481 out->offload_thread_blocked = true;
1482 pthread_mutex_unlock(&out->lock);
1483 send_callback = false;
1484 switch(cmd->cmd) {
1485 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1486 compress_wait(out->compr, -1);
1487 send_callback = true;
1488 event = STREAM_CBK_EVENT_WRITE_READY;
1489 break;
1490 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001491 compress_next_track(out->compr);
1492 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001493 send_callback = true;
1494 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001495 /* Resend the metadata for next iteration */
1496 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001497 break;
1498 case OFFLOAD_CMD_DRAIN:
1499 compress_drain(out->compr);
1500 send_callback = true;
1501 event = STREAM_CBK_EVENT_DRAIN_READY;
1502 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001503 case OFFLOAD_CMD_ERROR:
1504 send_callback = true;
1505 event = STREAM_CBK_EVENT_ERROR;
1506 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001507 default:
1508 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1509 break;
1510 }
Eric Laurenta1478072015-09-21 17:21:52 -07001511 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001512 out->offload_thread_blocked = false;
1513 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001514 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001515 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001516 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001517 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001518 free(cmd);
1519 }
1520
1521 pthread_cond_signal(&out->cond);
1522 while (!list_empty(&out->offload_cmd_list)) {
1523 item = list_head(&out->offload_cmd_list);
1524 list_remove(item);
1525 free(node_to_item(item, struct offload_cmd, node));
1526 }
1527 pthread_mutex_unlock(&out->lock);
1528
1529 return NULL;
1530}
1531
1532static int create_offload_callback_thread(struct stream_out *out)
1533{
1534 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1535 list_init(&out->offload_cmd_list);
1536 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1537 offload_thread_loop, out);
1538 return 0;
1539}
1540
1541static int destroy_offload_callback_thread(struct stream_out *out)
1542{
Eric Laurenta1478072015-09-21 17:21:52 -07001543 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001544 stop_compressed_output_l(out);
1545 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1546
1547 pthread_mutex_unlock(&out->lock);
1548 pthread_join(out->offload_thread, (void **) NULL);
1549 pthread_cond_destroy(&out->offload_cond);
1550
1551 return 0;
1552}
1553
Eric Laurent07eeafd2013-10-06 12:52:49 -07001554static bool allow_hdmi_channel_config(struct audio_device *adev)
1555{
1556 struct listnode *node;
1557 struct audio_usecase *usecase;
1558 bool ret = true;
1559
1560 list_for_each(node, &adev->usecase_list) {
1561 usecase = node_to_item(node, struct audio_usecase, list);
1562 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1563 /*
1564 * If voice call is already existing, do not proceed further to avoid
1565 * disabling/enabling both RX and TX devices, CSD calls, etc.
1566 * Once the voice call done, the HDMI channels can be configured to
1567 * max channels of remaining use cases.
1568 */
1569 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001570 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001571 __func__);
1572 ret = false;
1573 break;
1574 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001575 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001576 "no change in HDMI channels", __func__);
1577 ret = false;
1578 break;
1579 }
1580 }
1581 }
1582 return ret;
1583}
1584
1585static int check_and_set_hdmi_channels(struct audio_device *adev,
1586 unsigned int channels)
1587{
1588 struct listnode *node;
1589 struct audio_usecase *usecase;
1590
1591 /* Check if change in HDMI channel config is allowed */
1592 if (!allow_hdmi_channel_config(adev))
1593 return 0;
1594
1595 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001596 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001597 return 0;
1598 }
1599
1600 platform_set_hdmi_channels(adev->platform, channels);
1601 adev->cur_hdmi_channels = channels;
1602
1603 /*
1604 * Deroute all the playback streams routed to HDMI so that
1605 * the back end is deactivated. Note that backend will not
1606 * be deactivated if any one stream is connected to it.
1607 */
1608 list_for_each(node, &adev->usecase_list) {
1609 usecase = node_to_item(node, struct audio_usecase, list);
1610 if (usecase->type == PCM_PLAYBACK &&
1611 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001612 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001613 }
1614 }
1615
1616 /*
1617 * Enable all the streams disabled above. Now the HDMI backend
1618 * will be activated with new channel configuration
1619 */
1620 list_for_each(node, &adev->usecase_list) {
1621 usecase = node_to_item(node, struct audio_usecase, list);
1622 if (usecase->type == PCM_PLAYBACK &&
1623 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001624 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001625 }
1626 }
1627
1628 return 0;
1629}
1630
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001631static int stop_output_stream(struct stream_out *out)
1632{
1633 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001634 struct audio_usecase *uc_info;
1635 struct audio_device *adev = out->dev;
1636
Eric Laurent994a6932013-07-17 11:51:42 -07001637 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001638 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001639 uc_info = get_usecase_from_list(adev, out->usecase);
1640 if (uc_info == NULL) {
1641 ALOGE("%s: Could not find the usecase (%d) in the list",
1642 __func__, out->usecase);
1643 return -EINVAL;
1644 }
1645
Haynes Mathew George41f86652014-06-17 14:22:15 -07001646 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1647 if (adev->visualizer_stop_output != NULL)
1648 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1649 if (adev->offload_effects_stop_output != NULL)
1650 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1651 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001652
Eric Laurent150dbfe2013-02-27 14:31:02 -08001653 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001654 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001655
1656 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001657 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001659 list_remove(&uc_info->list);
1660 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661
Eric Laurent0499d4f2014-08-25 22:39:29 -05001662 audio_extn_extspk_update(adev->extspk);
1663
Eric Laurent07eeafd2013-10-06 12:52:49 -07001664 /* Must be called after removing the usecase from list */
1665 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1666 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1667
Eric Laurent994a6932013-07-17 11:51:42 -07001668 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001669 return ret;
1670}
1671
1672int start_output_stream(struct stream_out *out)
1673{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001675 struct audio_usecase *uc_info;
1676 struct audio_device *adev = out->dev;
1677
Eric Laurent994a6932013-07-17 11:51:42 -07001678 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001679 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001680
1681 if (out->card_status == CARD_STATUS_OFFLINE ||
1682 adev->card_status == CARD_STATUS_OFFLINE) {
1683 ALOGW("out->card_status or adev->card_status offline, try again");
1684 ret = -EAGAIN;
1685 goto error_config;
1686 }
1687
Eric Laurentb23d5282013-05-14 15:27:20 -07001688 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689 if (out->pcm_device_id < 0) {
1690 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1691 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001692 ret = -EINVAL;
1693 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001694 }
1695
1696 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1697 uc_info->id = out->usecase;
1698 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001699 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001700 uc_info->devices = out->devices;
1701 uc_info->in_snd_device = SND_DEVICE_NONE;
1702 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703
Eric Laurent07eeafd2013-10-06 12:52:49 -07001704 /* This must be called before adding this usecase to the list */
1705 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1706 check_and_set_hdmi_channels(adev, out->config.channels);
1707
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001708 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001710 audio_extn_perf_lock_acquire();
1711
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001712 select_devices(adev, out->usecase);
1713
Eric Laurent0499d4f2014-08-25 22:39:29 -05001714 audio_extn_extspk_update(adev->extspk);
1715
Andy Hung31aca912014-03-20 17:14:59 -07001716 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001717 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001718 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1719 out->pcm = NULL;
1720 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1721 COMPRESS_IN, &out->compr_config);
1722 if (out->compr && !is_compress_ready(out->compr)) {
1723 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1724 compress_close(out->compr);
1725 out->compr = NULL;
1726 ret = -EIO;
1727 goto error_open;
1728 }
1729 if (out->offload_callback)
1730 compress_nonblock(out->compr, out->non_blocking);
1731
1732 if (adev->visualizer_start_output != NULL)
1733 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1734 if (adev->offload_effects_start_output != NULL)
1735 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1736 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001737 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001738 ALOGE("%s: pcm stream not ready", __func__);
1739 goto error_open;
1740 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001741 ret = pcm_start(out->pcm);
1742 if (ret < 0) {
1743 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1744 goto error_open;
1745 }
1746 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001747 unsigned int flags = PCM_OUT;
1748 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001749
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001750 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1751 flags |= PCM_MMAP | PCM_NOIRQ;
1752 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001753 } else if (out->realtime) {
1754 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001755 } else
1756 flags |= PCM_MONOTONIC;
1757
1758 while (1) {
1759 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1760 flags, &out->config);
1761 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1762 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1763 if (out->pcm != NULL) {
1764 pcm_close(out->pcm);
1765 out->pcm = NULL;
1766 }
1767 if (pcm_open_retry_count-- == 0) {
1768 ret = -EIO;
1769 goto error_open;
1770 }
1771 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1772 continue;
1773 }
1774 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001775 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001776 ALOGV("%s: pcm_prepare", __func__);
1777 if (pcm_is_ready(out->pcm)) {
1778 ret = pcm_prepare(out->pcm);
1779 if (ret < 0) {
1780 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1781 pcm_close(out->pcm);
1782 out->pcm = NULL;
1783 goto error_open;
1784 }
1785 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001786 if (out->realtime) {
1787 ret = pcm_start(out->pcm);
1788 if (ret < 0) {
1789 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1790 pcm_close(out->pcm);
1791 out->pcm = NULL;
1792 goto error_open;
1793 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001794 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001795 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001796 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001797 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001798 audio_extn_tfa_98xx_enable_speaker();
1799
Eric Laurent994a6932013-07-17 11:51:42 -07001800 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001801 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001802error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001803 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001805error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001806 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807}
1808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809static int check_input_parameters(uint32_t sample_rate,
1810 audio_format_t format,
1811 int channel_count)
1812{
vivek mehta4ed66e62016-04-15 23:33:34 -07001813 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001814 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1815 return -EINVAL;
1816 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001817
vivek mehtadae44712015-07-27 14:13:18 -07001818 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001819 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001820 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1821 return -EINVAL;
1822 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823
1824 switch (sample_rate) {
1825 case 8000:
1826 case 11025:
1827 case 12000:
1828 case 16000:
1829 case 22050:
1830 case 24000:
1831 case 32000:
1832 case 44100:
1833 case 48000:
1834 break;
1835 default:
vivek mehtadae44712015-07-27 14:13:18 -07001836 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837 return -EINVAL;
1838 }
1839
1840 return 0;
1841}
1842
1843static size_t get_input_buffer_size(uint32_t sample_rate,
1844 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001845 int channel_count,
1846 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847{
1848 size_t size = 0;
1849
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001850 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1851 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001853 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001854 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001855 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001856
1857 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858
Glenn Kasten4f993392014-05-14 07:30:48 -07001859 /* make sure the size is multiple of 32 bytes
1860 * At 48 kHz mono 16-bit PCM:
1861 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1862 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1863 */
1864 size += 0x1f;
1865 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001866
1867 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001868}
1869
1870static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1871{
1872 struct stream_out *out = (struct stream_out *)stream;
1873
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001874 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001875}
1876
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001877static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001878{
1879 return -ENOSYS;
1880}
1881
1882static size_t out_get_buffer_size(const struct audio_stream *stream)
1883{
1884 struct stream_out *out = (struct stream_out *)stream;
1885
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001886 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1887 return out->compr_config.fragment_size;
1888 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001889 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001890 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891}
1892
1893static uint32_t out_get_channels(const struct audio_stream *stream)
1894{
1895 struct stream_out *out = (struct stream_out *)stream;
1896
1897 return out->channel_mask;
1898}
1899
1900static audio_format_t out_get_format(const struct audio_stream *stream)
1901{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001902 struct stream_out *out = (struct stream_out *)stream;
1903
1904 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001905}
1906
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001907static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001908{
1909 return -ENOSYS;
1910}
1911
1912static int out_standby(struct audio_stream *stream)
1913{
1914 struct stream_out *out = (struct stream_out *)stream;
1915 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001916 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001917
Eric Laurent994a6932013-07-17 11:51:42 -07001918 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001919 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001920
Eric Laurenta1478072015-09-21 17:21:52 -07001921 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001922 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001923 if (adev->adm_deregister_stream)
1924 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001925 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001927 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1928 if (out->pcm) {
1929 pcm_close(out->pcm);
1930 out->pcm = NULL;
1931 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001932 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001933 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08001934 out->playback_started = false;
1935 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001936 } else {
1937 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001938 out->gapless_mdata.encoder_delay = 0;
1939 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001940 if (out->compr != NULL) {
1941 compress_close(out->compr);
1942 out->compr = NULL;
1943 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001944 }
Phil Burkbc991042017-02-24 08:06:44 -08001945 if (do_stop) {
1946 stop_output_stream(out);
1947 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001948 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949 }
1950 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001951 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001952 return 0;
1953}
1954
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001955static int out_on_error(struct audio_stream *stream)
1956{
1957 struct stream_out *out = (struct stream_out *)stream;
1958 struct audio_device *adev = out->dev;
1959 bool do_standby = false;
1960
1961 lock_output_stream(out);
1962 if (!out->standby) {
1963 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1964 stop_compressed_output_l(out);
1965 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1966 } else
1967 do_standby = true;
1968 }
1969 pthread_mutex_unlock(&out->lock);
1970
1971 if (do_standby)
1972 return out_standby(&out->stream.common);
1973
1974 return 0;
1975}
1976
Andy Hung7401c7c2016-09-21 12:41:21 -07001977static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978{
Andy Hung7401c7c2016-09-21 12:41:21 -07001979 struct stream_out *out = (struct stream_out *)stream;
1980
1981 // We try to get the lock for consistency,
1982 // but it isn't necessary for these variables.
1983 // If we're not in standby, we may be blocked on a write.
1984 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1985 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1986 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1987
1988 if (locked) {
1989 log_dump_l(&out->error_log, fd);
1990 pthread_mutex_unlock(&out->lock);
1991 } else {
1992 // We don't have the lock here, copy for safety.
1993 struct error_log log = out->error_log;
1994 log_dump_l(&log, fd);
1995 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996 return 0;
1997}
1998
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001999static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2000{
2001 int ret = 0;
2002 char value[32];
2003 struct compr_gapless_mdata tmp_mdata;
2004
2005 if (!out || !parms) {
2006 return -EINVAL;
2007 }
2008
2009 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2010 if (ret >= 0) {
2011 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2012 } else {
2013 return -EINVAL;
2014 }
2015
2016 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2017 if (ret >= 0) {
2018 tmp_mdata.encoder_padding = atoi(value);
2019 } else {
2020 return -EINVAL;
2021 }
2022
2023 out->gapless_mdata = tmp_mdata;
2024 out->send_new_metadata = 1;
2025 ALOGV("%s new encoder delay %u and padding %u", __func__,
2026 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2027
2028 return 0;
2029}
2030
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002031static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2032{
2033 return out == adev->primary_output || out == adev->voice_tx_output;
2034}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002035
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002036static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2037{
2038 struct stream_out *out = (struct stream_out *)stream;
2039 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002040 struct audio_usecase *usecase;
2041 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042 struct str_parms *parms;
2043 char value[32];
2044 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002045 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002046 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047
Eric Laurent2e140aa2016-06-30 17:14:46 -07002048 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002049 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050 parms = str_parms_create_str(kvpairs);
2051 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2052 if (ret >= 0) {
2053 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002054 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002055 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002057 /*
2058 * When HDMI cable is unplugged the music playback is paused and
2059 * the policy manager sends routing=0. But the audioflinger
2060 * continues to write data until standby time (3sec).
2061 * As the HDMI core is turned off, the write gets blocked.
2062 * Avoid this by routing audio to speaker until standby.
2063 */
2064 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2065 val == AUDIO_DEVICE_NONE) {
2066 val = AUDIO_DEVICE_OUT_SPEAKER;
2067 }
2068
2069 /*
2070 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002071 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002072 * the select_devices(). But how do we undo this?
2073 *
2074 * For example, music playback is active on headset (deep-buffer usecase)
2075 * and if we go to ringtones and select a ringtone, low-latency usecase
2076 * will be started on headset+speaker. As we can't enable headset+speaker
2077 * and headset devices at the same time, select_devices() switches the music
2078 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2079 * So when the ringtone playback is completed, how do we undo the same?
2080 *
2081 * We are relying on the out_set_parameters() call on deep-buffer output,
2082 * once the ringtone playback is ended.
2083 * NOTE: We should not check if the current devices are same as new devices.
2084 * Because select_devices() must be called to switch back the music
2085 * playback to headset.
2086 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002087 audio_devices_t new_dev = val;
2088 if (new_dev != AUDIO_DEVICE_NONE) {
2089 bool same_dev = out->devices == new_dev;
2090 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002091
Eric Laurenta7657192014-10-09 21:09:33 -07002092 if (output_drives_call(adev, out)) {
2093 if (!voice_is_in_call(adev)) {
2094 if (adev->mode == AUDIO_MODE_IN_CALL) {
2095 adev->current_call_output = out;
2096 ret = voice_start_call(adev);
2097 }
2098 } else {
2099 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002100 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002101 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002102 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002103
2104 if (!out->standby) {
2105 if (!same_dev) {
2106 ALOGV("update routing change");
2107 out->routing_change = true;
2108 }
2109 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002110 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002111 }
2112
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002113 }
2114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002116 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002117
2118 /*handles device and call state changes*/
2119 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002121
2122 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2123 parse_compress_metadata(out, parms);
2124 }
2125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002126 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002127 ALOGV("%s: exit: code(%d)", __func__, status);
2128 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002129}
2130
2131static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2132{
2133 struct stream_out *out = (struct stream_out *)stream;
2134 struct str_parms *query = str_parms_create_str(keys);
2135 char *str;
2136 char value[256];
2137 struct str_parms *reply = str_parms_create();
2138 size_t i, j;
2139 int ret;
2140 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002141 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002142 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2143 if (ret >= 0) {
2144 value[0] = '\0';
2145 i = 0;
2146 while (out->supported_channel_masks[i] != 0) {
2147 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2148 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2149 if (!first) {
2150 strcat(value, "|");
2151 }
2152 strcat(value, out_channels_name_to_enum_table[j].name);
2153 first = false;
2154 break;
2155 }
2156 }
2157 i++;
2158 }
2159 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2160 str = str_parms_to_str(reply);
2161 } else {
2162 str = strdup(keys);
2163 }
2164 str_parms_destroy(query);
2165 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002166 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167 return str;
2168}
2169
2170static uint32_t out_get_latency(const struct audio_stream_out *stream)
2171{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002172 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002173 struct stream_out *out = (struct stream_out *)stream;
2174
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002175 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2176 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002177 else if ((out->realtime) ||
2178 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002179 // since the buffer won't be filled up faster than realtime,
2180 // return a smaller number
2181 period_ms = (out->af_period_multiplier * out->config.period_size *
2182 1000) / (out->config.rate);
2183 hw_delay = platform_render_latency(out->usecase)/1000;
2184 return period_ms + hw_delay;
2185 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002186
2187 return (out->config.period_count * out->config.period_size * 1000) /
2188 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189}
2190
2191static int out_set_volume(struct audio_stream_out *stream, float left,
2192 float right)
2193{
Eric Laurenta9024de2013-04-04 09:19:12 -07002194 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002195 int volume[2];
2196
Eric Laurenta9024de2013-04-04 09:19:12 -07002197 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2198 /* only take left channel into account: the API is for stereo anyway */
2199 out->muted = (left == 0.0f);
2200 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002201 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2202 const char *mixer_ctl_name = "Compress Playback Volume";
2203 struct audio_device *adev = out->dev;
2204 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002205 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2206 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002207 /* try with the control based on device id */
2208 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2209 PCM_PLAYBACK);
2210 char ctl_name[128] = {0};
2211 snprintf(ctl_name, sizeof(ctl_name),
2212 "Compress Playback %d Volume", pcm_device_id);
2213 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2214 if (!ctl) {
2215 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2216 return -EINVAL;
2217 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002218 }
2219 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2220 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2221 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2222 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002223 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002224
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225 return -ENOSYS;
2226}
2227
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002228// note: this call is safe only if the stream_cb is
2229// removed first in close_output_stream (as is done now).
2230static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2231{
2232 if (!stream || !parms)
2233 return;
2234
2235 struct stream_out *out = (struct stream_out *)stream;
2236 struct audio_device *adev = out->dev;
2237
2238 card_status_t status;
2239 int card;
2240 if (parse_snd_card_status(parms, &card, &status) < 0)
2241 return;
2242
2243 pthread_mutex_lock(&adev->lock);
2244 bool valid_cb = (card == adev->snd_card);
2245 pthread_mutex_unlock(&adev->lock);
2246
2247 if (!valid_cb)
2248 return;
2249
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002250 lock_output_stream(out);
2251 if (out->card_status != status)
2252 out->card_status = status;
2253 pthread_mutex_unlock(&out->lock);
2254
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002255 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2256 use_case_table[out->usecase],
2257 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2258
2259 if (status == CARD_STATUS_OFFLINE)
2260 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002261
2262 return;
2263}
2264
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002265#ifdef NO_AUDIO_OUT
2266static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002267 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002268{
2269 struct stream_out *out = (struct stream_out *)stream;
2270
2271 /* No Output device supported other than BT for playback.
2272 * Sleep for the amount of buffer duration
2273 */
Eric Laurenta1478072015-09-21 17:21:52 -07002274 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002275 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2276 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002277 out_get_sample_rate(&out->stream.common));
2278 pthread_mutex_unlock(&out->lock);
2279 return bytes;
2280}
2281#endif
2282
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002283static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2284 size_t bytes)
2285{
2286 struct stream_out *out = (struct stream_out *)stream;
2287 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002288 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002289 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002290
Eric Laurenta1478072015-09-21 17:21:52 -07002291 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002292 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2293 error_code = ERROR_CODE_WRITE;
2294 goto exit;
2295 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002296 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002297 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002298 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002299 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002300 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002301 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002302 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002303 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002304 goto exit;
2305 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002306
2307 if (last_known_cal_step != -1) {
2308 ALOGD("%s: retry previous failed cal level set", __func__);
2309 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2310 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002311 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002312
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002313 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002314 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002315 if (out->send_new_metadata) {
2316 ALOGVV("send new gapless metadata");
2317 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2318 out->send_new_metadata = 0;
2319 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002320 unsigned int avail;
2321 struct timespec tstamp;
2322 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2323 /* Do not limit write size if the available frames count is unknown */
2324 if (ret != 0) {
2325 avail = bytes;
2326 }
2327 if (avail == 0) {
2328 ret = 0;
2329 } else {
2330 if (avail > bytes) {
2331 avail = bytes;
2332 }
2333 ret = compress_write(out->compr, buffer, avail);
2334 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2335 __func__, avail, ret);
2336 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002337
Eric Laurent6e895242013-09-05 16:10:57 -07002338 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002339 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2340 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002341 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002342 compress_start(out->compr);
2343 out->playback_started = 1;
2344 out->offload_state = OFFLOAD_STATE_PLAYING;
2345 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002346 if (ret < 0) {
2347 log_error_l(&out->error_log, ERROR_CODE_WRITE);
2348 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002349 pthread_mutex_unlock(&out->lock);
2350 return ret;
2351 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002352 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002353 if (out->pcm) {
2354 if (out->muted)
2355 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002356
Eric Laurent0e46adf2016-12-16 12:49:24 -08002357 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002358
Haynes Mathew George03c40102016-01-29 17:57:48 -08002359 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2360 out->config.rate;
2361 request_out_focus(out, ns);
2362
2363 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2364 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002365 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002366 else
2367 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002368
Haynes Mathew George03c40102016-01-29 17:57:48 -08002369 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002370 } else {
2371 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002372 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002373 }
2374
2375exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002376 // For PCM we always consume the buffer and return #bytes regardless of ret.
2377 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2378 out->written += bytes / (out->config.channels * sizeof(short));
2379 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002380 long long sleeptime_us = 0;
2381 if (ret != 0) {
2382 log_error_l(&out->error_log, error_code);
2383 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2384 ALOGE_IF(out->pcm != NULL,
2385 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
2386 sleeptime_us = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2387 out_get_sample_rate(&out->stream.common);
2388 // usleep not guaranteed for values over 1 second but we don't limit here.
2389 }
2390 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002392 pthread_mutex_unlock(&out->lock);
2393
2394 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002395 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002396 if (sleeptime_us != 0)
2397 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002398 }
2399 return bytes;
2400}
2401
2402static int out_get_render_position(const struct audio_stream_out *stream,
2403 uint32_t *dsp_frames)
2404{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002405 struct stream_out *out = (struct stream_out *)stream;
2406 *dsp_frames = 0;
2407 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002408 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002409 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002410 unsigned long frames = 0;
2411 // TODO: check return value
2412 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2413 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002414 ALOGVV("%s rendered frames %d sample_rate %d",
2415 __func__, *dsp_frames, out->sample_rate);
2416 }
2417 pthread_mutex_unlock(&out->lock);
2418 return 0;
2419 } else
2420 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002421}
2422
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002423static int out_add_audio_effect(const struct audio_stream *stream __unused,
2424 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425{
2426 return 0;
2427}
2428
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002429static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2430 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002431{
2432 return 0;
2433}
2434
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002435static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2436 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437{
2438 return -EINVAL;
2439}
2440
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002441static int out_get_presentation_position(const struct audio_stream_out *stream,
2442 uint64_t *frames, struct timespec *timestamp)
2443{
2444 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002445 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002446 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002447
Eric Laurenta1478072015-09-21 17:21:52 -07002448 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002449
Eric Laurent949a0892013-09-20 09:20:13 -07002450 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2451 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002452 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002453 compress_get_tstamp(out->compr, &dsp_frames,
2454 &out->sample_rate);
2455 ALOGVV("%s rendered frames %ld sample_rate %d",
2456 __func__, dsp_frames, out->sample_rate);
2457 *frames = dsp_frames;
2458 ret = 0;
2459 /* this is the best we can do */
2460 clock_gettime(CLOCK_MONOTONIC, timestamp);
2461 }
2462 } else {
2463 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002464 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002465 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2466 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002467 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002468 // This adjustment accounts for buffering after app processor.
2469 // It is based on estimated DSP latency per use case, rather than exact.
2470 signed_frames -=
2471 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2472
Eric Laurent949a0892013-09-20 09:20:13 -07002473 // It would be unusual for this value to be negative, but check just in case ...
2474 if (signed_frames >= 0) {
2475 *frames = signed_frames;
2476 ret = 0;
2477 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002478 }
2479 }
2480 }
2481
2482 pthread_mutex_unlock(&out->lock);
2483
2484 return ret;
2485}
2486
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002487static int out_set_callback(struct audio_stream_out *stream,
2488 stream_callback_t callback, void *cookie)
2489{
2490 struct stream_out *out = (struct stream_out *)stream;
2491
2492 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002493 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002494 out->offload_callback = callback;
2495 out->offload_cookie = cookie;
2496 pthread_mutex_unlock(&out->lock);
2497 return 0;
2498}
2499
2500static int out_pause(struct audio_stream_out* stream)
2501{
2502 struct stream_out *out = (struct stream_out *)stream;
2503 int status = -ENOSYS;
2504 ALOGV("%s", __func__);
2505 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002506 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002507 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2508 status = compress_pause(out->compr);
2509 out->offload_state = OFFLOAD_STATE_PAUSED;
2510 }
2511 pthread_mutex_unlock(&out->lock);
2512 }
2513 return status;
2514}
2515
2516static int out_resume(struct audio_stream_out* stream)
2517{
2518 struct stream_out *out = (struct stream_out *)stream;
2519 int status = -ENOSYS;
2520 ALOGV("%s", __func__);
2521 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2522 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002523 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002524 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2525 status = compress_resume(out->compr);
2526 out->offload_state = OFFLOAD_STATE_PLAYING;
2527 }
2528 pthread_mutex_unlock(&out->lock);
2529 }
2530 return status;
2531}
2532
2533static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2534{
2535 struct stream_out *out = (struct stream_out *)stream;
2536 int status = -ENOSYS;
2537 ALOGV("%s", __func__);
2538 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002539 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002540 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2541 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2542 else
2543 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2544 pthread_mutex_unlock(&out->lock);
2545 }
2546 return status;
2547}
2548
2549static int out_flush(struct audio_stream_out* stream)
2550{
2551 struct stream_out *out = (struct stream_out *)stream;
2552 ALOGV("%s", __func__);
2553 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002554 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002555 stop_compressed_output_l(out);
2556 pthread_mutex_unlock(&out->lock);
2557 return 0;
2558 }
2559 return -ENOSYS;
2560}
2561
Eric Laurent0e46adf2016-12-16 12:49:24 -08002562static int out_stop(const struct audio_stream_out* stream)
2563{
2564 struct stream_out *out = (struct stream_out *)stream;
2565 struct audio_device *adev = out->dev;
2566 int ret = -ENOSYS;
2567
2568 ALOGV("%s", __func__);
2569 pthread_mutex_lock(&adev->lock);
2570 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2571 out->playback_started && out->pcm != NULL) {
2572 pcm_stop(out->pcm);
2573 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002574 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002575 }
2576 pthread_mutex_unlock(&adev->lock);
2577 return ret;
2578}
2579
2580static int out_start(const struct audio_stream_out* stream)
2581{
2582 struct stream_out *out = (struct stream_out *)stream;
2583 struct audio_device *adev = out->dev;
2584 int ret = -ENOSYS;
2585
2586 ALOGV("%s", __func__);
2587 pthread_mutex_lock(&adev->lock);
2588 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2589 !out->playback_started && out->pcm != NULL) {
2590 ret = start_output_stream(out);
2591 if (ret == 0) {
2592 out->playback_started = true;
2593 }
2594 }
2595 pthread_mutex_unlock(&adev->lock);
2596 return ret;
2597}
2598
Phil Burkbc991042017-02-24 08:06:44 -08002599/*
2600 * Modify config->period_count based on min_size_frames
2601 */
2602static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2603{
2604 int periodCountRequested = (min_size_frames + config->period_size - 1)
2605 / config->period_size;
2606 int periodCount = MMAP_PERIOD_COUNT_MIN;
2607
2608 ALOGV("%s original config.period_size = %d config.period_count = %d",
2609 __func__, config->period_size, config->period_count);
2610
2611 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2612 periodCount *= 2;
2613 }
2614 config->period_count = periodCount;
2615
2616 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2617}
2618
Eric Laurent0e46adf2016-12-16 12:49:24 -08002619static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2620 int32_t min_size_frames,
2621 struct audio_mmap_buffer_info *info)
2622{
2623 struct stream_out *out = (struct stream_out *)stream;
2624 struct audio_device *adev = out->dev;
2625 int ret = 0;
2626 unsigned int offset1;
2627 unsigned int frames1;
2628 const char *step = "";
2629
2630 ALOGV("%s", __func__);
2631 pthread_mutex_lock(&adev->lock);
2632
2633 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002634 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002635 ret = -EINVAL;
2636 goto exit;
2637 }
2638 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002639 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002640 ret = -ENOSYS;
2641 goto exit;
2642 }
2643 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2644 if (out->pcm_device_id < 0) {
2645 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2646 __func__, out->pcm_device_id, out->usecase);
2647 ret = -EINVAL;
2648 goto exit;
2649 }
Phil Burkbc991042017-02-24 08:06:44 -08002650
2651 adjust_mmap_period_count(&out->config, min_size_frames);
2652
Eric Laurent0e46adf2016-12-16 12:49:24 -08002653 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2654 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2655 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2656 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2657 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2658 step = "open";
2659 ret = -ENODEV;
2660 goto exit;
2661 }
2662 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2663 if (ret < 0) {
2664 step = "begin";
2665 goto exit;
2666 }
2667 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2668 info->burst_size_frames = out->config.period_size;
2669 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2670
2671 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2672 info->buffer_size_frames));
2673
2674 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2675 if (ret < 0) {
2676 step = "commit";
2677 goto exit;
2678 }
Phil Burkbc991042017-02-24 08:06:44 -08002679
2680 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002681 ret = 0;
2682
2683 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2684 __func__, info->shared_memory_address, info->buffer_size_frames);
2685
2686exit:
2687 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002688 if (out->pcm == NULL) {
2689 ALOGE("%s: %s - %d", __func__, step, ret);
2690 } else {
2691 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002692 pcm_close(out->pcm);
2693 out->pcm = NULL;
2694 }
2695 }
2696 pthread_mutex_unlock(&adev->lock);
2697 return ret;
2698}
2699
2700static int out_get_mmap_position(const struct audio_stream_out *stream,
2701 struct audio_mmap_position *position)
2702{
2703 struct stream_out *out = (struct stream_out *)stream;
2704 ALOGVV("%s", __func__);
2705 if (position == NULL) {
2706 return -EINVAL;
2707 }
2708 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2709 return -ENOSYS;
2710 }
2711 if (out->pcm == NULL) {
2712 return -ENOSYS;
2713 }
2714
2715 struct timespec ts = { 0, 0 };
2716 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2717 if (ret < 0) {
2718 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2719 return ret;
2720 }
2721 position->time_nanoseconds = ts2ns(&ts);
2722 return 0;
2723}
2724
2725
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726/** audio_stream_in implementation **/
2727static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2728{
2729 struct stream_in *in = (struct stream_in *)stream;
2730
2731 return in->config.rate;
2732}
2733
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002734static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735{
2736 return -ENOSYS;
2737}
2738
2739static size_t in_get_buffer_size(const struct audio_stream *stream)
2740{
2741 struct stream_in *in = (struct stream_in *)stream;
2742
Haynes Mathew George03c40102016-01-29 17:57:48 -08002743 return in->config.period_size * in->af_period_multiplier *
2744 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745}
2746
2747static uint32_t in_get_channels(const struct audio_stream *stream)
2748{
2749 struct stream_in *in = (struct stream_in *)stream;
2750
2751 return in->channel_mask;
2752}
2753
vivek mehta4ed66e62016-04-15 23:33:34 -07002754static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755{
vivek mehta4ed66e62016-04-15 23:33:34 -07002756 struct stream_in *in = (struct stream_in *)stream;
2757 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758}
2759
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002760static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761{
2762 return -ENOSYS;
2763}
2764
2765static int in_standby(struct audio_stream *stream)
2766{
2767 struct stream_in *in = (struct stream_in *)stream;
2768 struct audio_device *adev = in->dev;
2769 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002770 bool do_stop = true;
2771
Eric Laurent994a6932013-07-17 11:51:42 -07002772 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002773
2774 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002775
2776 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002777 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002778 audio_extn_sound_trigger_stop_lab(in);
2779 in->standby = true;
2780 }
2781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002783 if (adev->adm_deregister_stream)
2784 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2785
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002786 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002788 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002789 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002790 in->capture_started = false;
2791 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002792 if (in->pcm) {
2793 pcm_close(in->pcm);
2794 in->pcm = NULL;
2795 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002796 adev->enable_voicerx = false;
2797 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002798 if (do_stop) {
2799 status = stop_input_stream(in);
2800 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002801 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802 }
2803 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002804 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002805 return status;
2806}
2807
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002808static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809{
2810 return 0;
2811}
2812
2813static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2814{
2815 struct stream_in *in = (struct stream_in *)stream;
2816 struct audio_device *adev = in->dev;
2817 struct str_parms *parms;
2818 char *str;
2819 char value[32];
2820 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002821 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822
Eric Laurent994a6932013-07-17 11:51:42 -07002823 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824 parms = str_parms_create_str(kvpairs);
2825
2826 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2827
Eric Laurenta1478072015-09-21 17:21:52 -07002828 lock_input_stream(in);
2829
Eric Laurent150dbfe2013-02-27 14:31:02 -08002830 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 if (ret >= 0) {
2832 val = atoi(value);
2833 /* no audio source uses val == 0 */
2834 if ((in->source != val) && (val != 0)) {
2835 in->source = val;
2836 }
2837 }
2838
2839 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002840
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002841 if (ret >= 0) {
2842 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002843 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002844 in->device = val;
2845 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002846 if (!in->standby) {
2847 ALOGV("update input routing change");
2848 in->routing_change = true;
2849 select_devices(adev, in->usecase);
2850 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002851 }
2852 }
2853
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002854 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002855 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002856
2857 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002858 ALOGV("%s: exit: status(%d)", __func__, status);
2859 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860}
2861
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002862static char* in_get_parameters(const struct audio_stream *stream __unused,
2863 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002864{
2865 return strdup("");
2866}
2867
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002868static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002869{
2870 return 0;
2871}
2872
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002873static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2874{
2875 if (!stream || !parms)
2876 return;
2877
2878 struct stream_in *in = (struct stream_in *)stream;
2879 struct audio_device *adev = in->dev;
2880
2881 card_status_t status;
2882 int card;
2883 if (parse_snd_card_status(parms, &card, &status) < 0)
2884 return;
2885
2886 pthread_mutex_lock(&adev->lock);
2887 bool valid_cb = (card == adev->snd_card);
2888 pthread_mutex_unlock(&adev->lock);
2889
2890 if (!valid_cb)
2891 return;
2892
2893 lock_input_stream(in);
2894 if (in->card_status != status)
2895 in->card_status = status;
2896 pthread_mutex_unlock(&in->lock);
2897
2898 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2899 use_case_table[in->usecase],
2900 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2901
2902 // a better solution would be to report error back to AF and let
2903 // it put the stream to standby
2904 if (status == CARD_STATUS_OFFLINE)
2905 in_standby(&in->stream.common);
2906
2907 return;
2908}
2909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002910static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2911 size_t bytes)
2912{
2913 struct stream_in *in = (struct stream_in *)stream;
2914 struct audio_device *adev = in->dev;
2915 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002916 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917
Eric Laurenta1478072015-09-21 17:21:52 -07002918 lock_input_stream(in);
2919
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002920 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002921 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002922 /* Read from sound trigger HAL */
2923 audio_extn_sound_trigger_read(in, buffer, bytes);
2924 pthread_mutex_unlock(&in->lock);
2925 return bytes;
2926 }
2927
Eric Laurent0e46adf2016-12-16 12:49:24 -08002928 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
2929 ret = -ENOSYS;
2930 goto exit;
2931 }
2932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002933 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002934 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002935 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002936 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002937 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938 goto exit;
2939 }
2940 in->standby = 0;
2941 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942
Haynes Mathew George03c40102016-01-29 17:57:48 -08002943 //what's the duration requested by the client?
2944 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2945 in->config.rate;
2946 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002947
Haynes Mathew George03c40102016-01-29 17:57:48 -08002948 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002949 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002950 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002951 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002952 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002953 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002954 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002955 if (ret < 0) {
2956 ALOGE("Failed to read w/err %s", strerror(errno));
2957 ret = -errno;
2958 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002959 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2960 if (bytes % 4 == 0) {
2961 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2962 int_buf_stream = buffer;
2963 for (size_t itt=0; itt < bytes/4 ; itt++) {
2964 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002965 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002966 } else {
2967 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2968 ret = -EINVAL;
2969 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002970 }
2971 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972 }
2973
Haynes Mathew George03c40102016-01-29 17:57:48 -08002974 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002975
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976 /*
2977 * Instead of writing zeroes here, we could trust the hardware
2978 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002979 * 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 -08002980 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002981 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982 memset(buffer, 0, bytes);
2983
2984exit:
2985 pthread_mutex_unlock(&in->lock);
2986
2987 if (ret != 0) {
2988 in_standby(&in->stream.common);
2989 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002990 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002991 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002992 memset(buffer, 0, bytes); // clear return data
2993 }
2994 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002995 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996 }
2997 return bytes;
2998}
2999
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003000static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001{
3002 return 0;
3003}
3004
Andy Hung6ebe5962016-01-15 17:46:57 -08003005static int in_get_capture_position(const struct audio_stream_in *stream,
3006 int64_t *frames, int64_t *time)
3007{
3008 if (stream == NULL || frames == NULL || time == NULL) {
3009 return -EINVAL;
3010 }
3011 struct stream_in *in = (struct stream_in *)stream;
3012 int ret = -ENOSYS;
3013
3014 lock_input_stream(in);
3015 if (in->pcm) {
3016 struct timespec timestamp;
3017 unsigned int avail;
3018 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3019 *frames = in->frames_read + avail;
3020 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3021 ret = 0;
3022 }
3023 }
3024 pthread_mutex_unlock(&in->lock);
3025 return ret;
3026}
3027
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003028static int add_remove_audio_effect(const struct audio_stream *stream,
3029 effect_handle_t effect,
3030 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003032 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003033 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003034 int status = 0;
3035 effect_descriptor_t desc;
3036
3037 status = (*effect)->get_descriptor(effect, &desc);
3038 if (status != 0)
3039 return status;
3040
Eric Laurenta1478072015-09-21 17:21:52 -07003041 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003042 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003043 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003044 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003045 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003046 in->enable_aec != enable &&
3047 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3048 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003049 if (!enable)
3050 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003051 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3052 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3053 adev->enable_voicerx = enable;
3054 struct audio_usecase *usecase;
3055 struct listnode *node;
3056 list_for_each(node, &adev->usecase_list) {
3057 usecase = node_to_item(node, struct audio_usecase, list);
3058 if (usecase->type == PCM_PLAYBACK) {
3059 select_devices(adev, usecase->id);
3060 break;
3061 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003062 }
3063 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003064 if (!in->standby)
3065 select_devices(in->dev, in->usecase);
3066 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003067 if (in->enable_ns != enable &&
3068 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3069 in->enable_ns = enable;
3070 if (!in->standby)
3071 select_devices(in->dev, in->usecase);
3072 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003073 pthread_mutex_unlock(&in->dev->lock);
3074 pthread_mutex_unlock(&in->lock);
3075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076 return 0;
3077}
3078
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003079static int in_add_audio_effect(const struct audio_stream *stream,
3080 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081{
Eric Laurent994a6932013-07-17 11:51:42 -07003082 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003083 return add_remove_audio_effect(stream, effect, true);
3084}
3085
3086static int in_remove_audio_effect(const struct audio_stream *stream,
3087 effect_handle_t effect)
3088{
Eric Laurent994a6932013-07-17 11:51:42 -07003089 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003090 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003091}
3092
Eric Laurent0e46adf2016-12-16 12:49:24 -08003093static int in_stop(const struct audio_stream_in* stream)
3094{
3095 struct stream_in *in = (struct stream_in *)stream;
3096 struct audio_device *adev = in->dev;
3097
3098 int ret = -ENOSYS;
3099 ALOGV("%s", __func__);
3100 pthread_mutex_lock(&adev->lock);
3101 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3102 in->capture_started && in->pcm != NULL) {
3103 pcm_stop(in->pcm);
3104 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003105 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003106 }
3107 pthread_mutex_unlock(&adev->lock);
3108 return ret;
3109}
3110
3111static int in_start(const struct audio_stream_in* stream)
3112{
3113 struct stream_in *in = (struct stream_in *)stream;
3114 struct audio_device *adev = in->dev;
3115 int ret = -ENOSYS;
3116
3117 ALOGV("%s in %p", __func__, in);
3118 pthread_mutex_lock(&adev->lock);
3119 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3120 !in->capture_started && in->pcm != NULL) {
3121 if (!in->capture_started) {
3122 ret = start_input_stream(in);
3123 if (ret == 0) {
3124 in->capture_started = true;
3125 }
3126 }
3127 }
3128 pthread_mutex_unlock(&adev->lock);
3129 return ret;
3130}
3131
3132static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3133 int32_t min_size_frames,
3134 struct audio_mmap_buffer_info *info)
3135{
3136 struct stream_in *in = (struct stream_in *)stream;
3137 struct audio_device *adev = in->dev;
3138 int ret = 0;
3139 unsigned int offset1;
3140 unsigned int frames1;
3141 const char *step = "";
3142
3143 pthread_mutex_lock(&adev->lock);
3144 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003145
Eric Laurent0e46adf2016-12-16 12:49:24 -08003146 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003147 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003148 ret = -EINVAL;
3149 goto exit;
3150 }
3151 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003152 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003153 ALOGV("%s in %p", __func__, in);
3154 ret = -ENOSYS;
3155 goto exit;
3156 }
3157 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3158 if (in->pcm_device_id < 0) {
3159 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3160 __func__, in->pcm_device_id, in->usecase);
3161 ret = -EINVAL;
3162 goto exit;
3163 }
Phil Burkbc991042017-02-24 08:06:44 -08003164
3165 adjust_mmap_period_count(&in->config, min_size_frames);
3166
Eric Laurent0e46adf2016-12-16 12:49:24 -08003167 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3168 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3169 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3170 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3171 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3172 step = "open";
3173 ret = -ENODEV;
3174 goto exit;
3175 }
3176
3177 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3178 if (ret < 0) {
3179 step = "begin";
3180 goto exit;
3181 }
3182 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3183 info->burst_size_frames = in->config.period_size;
3184 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3185
3186 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3187 info->buffer_size_frames));
3188
3189 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3190 if (ret < 0) {
3191 step = "commit";
3192 goto exit;
3193 }
3194
Phil Burkbc991042017-02-24 08:06:44 -08003195 in->standby = false;
3196 ret = 0;
3197
Eric Laurent0e46adf2016-12-16 12:49:24 -08003198 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3199 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003200
3201exit:
3202 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003203 if (in->pcm == NULL) {
3204 ALOGE("%s: %s - %d", __func__, step, ret);
3205 } else {
3206 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003207 pcm_close(in->pcm);
3208 in->pcm = NULL;
3209 }
3210 }
3211 pthread_mutex_unlock(&adev->lock);
3212 return ret;
3213}
3214
3215static int in_get_mmap_position(const struct audio_stream_in *stream,
3216 struct audio_mmap_position *position)
3217{
3218 struct stream_in *in = (struct stream_in *)stream;
3219 ALOGVV("%s", __func__);
3220 if (position == NULL) {
3221 return -EINVAL;
3222 }
3223 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3224 return -ENOSYS;
3225 }
3226 if (in->pcm == NULL) {
3227 return -ENOSYS;
3228 }
3229 struct timespec ts = { 0, 0 };
3230 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3231 if (ret < 0) {
3232 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3233 return ret;
3234 }
3235 position->time_nanoseconds = ts2ns(&ts);
3236 return 0;
3237}
3238
3239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240static int adev_open_output_stream(struct audio_hw_device *dev,
3241 audio_io_handle_t handle,
3242 audio_devices_t devices,
3243 audio_output_flags_t flags,
3244 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003245 struct audio_stream_out **stream_out,
3246 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247{
3248 struct audio_device *adev = (struct audio_device *)dev;
3249 struct stream_out *out;
3250 int i, ret;
3251
Eric Laurent994a6932013-07-17 11:51:42 -07003252 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003253 __func__, config->sample_rate, config->channel_mask, devices, flags);
3254 *stream_out = NULL;
3255 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3256
3257 if (devices == AUDIO_DEVICE_NONE)
3258 devices = AUDIO_DEVICE_OUT_SPEAKER;
3259
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260 out->flags = flags;
3261 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003262 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003263 out->format = config->format;
3264 out->sample_rate = config->sample_rate;
3265 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3266 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003267 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268
3269 /* Init use case and pcm_config */
3270 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07003271 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003273 pthread_mutex_lock(&adev->lock);
3274 ret = read_hdmi_channel_masks(out);
3275 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003276 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003277 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003278
3279 if (config->sample_rate == 0)
3280 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3281 if (config->channel_mask == 0)
3282 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08003283 if (config->format == AUDIO_FORMAT_DEFAULT)
3284 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003285
3286 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003287 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08003288 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003289 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3290 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003291 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003292 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003294 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003295 pthread_mutex_lock(&adev->lock);
3296 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3297 pthread_mutex_unlock(&adev->lock);
3298
3299 // reject offload during card offline to allow
3300 // fallback to s/w paths
3301 if (offline) {
3302 ret = -ENODEV;
3303 goto error_open;
3304 }
3305
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003306 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3307 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3308 ALOGE("%s: Unsupported Offload information", __func__);
3309 ret = -EINVAL;
3310 goto error_open;
3311 }
3312 if (!is_supported_format(config->offload_info.format)) {
3313 ALOGE("%s: Unsupported audio format", __func__);
3314 ret = -EINVAL;
3315 goto error_open;
3316 }
3317
3318 out->compr_config.codec = (struct snd_codec *)
3319 calloc(1, sizeof(struct snd_codec));
3320
3321 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3322 if (config->offload_info.channel_mask)
3323 out->channel_mask = config->offload_info.channel_mask;
3324 else if (config->channel_mask)
3325 out->channel_mask = config->channel_mask;
3326 out->format = config->offload_info.format;
3327 out->sample_rate = config->offload_info.sample_rate;
3328
3329 out->stream.set_callback = out_set_callback;
3330 out->stream.pause = out_pause;
3331 out->stream.resume = out_resume;
3332 out->stream.drain = out_drain;
3333 out->stream.flush = out_flush;
3334
3335 out->compr_config.codec->id =
3336 get_snd_codec_id(config->offload_info.format);
3337 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3338 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003339 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003340 out->compr_config.codec->bit_rate =
3341 config->offload_info.bit_rate;
3342 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003343 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003344 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3345
3346 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3347 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003348
3349 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003350 create_offload_callback_thread(out);
3351 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3352 __func__, config->offload_info.version,
3353 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003354 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3355 if (config->sample_rate == 0)
3356 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3357 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3358 config->sample_rate != 8000) {
3359 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3360 ret = -EINVAL;
3361 goto error_open;
3362 }
3363 out->sample_rate = config->sample_rate;
3364 out->config.rate = config->sample_rate;
3365 if (config->format == AUDIO_FORMAT_DEFAULT)
3366 config->format = AUDIO_FORMAT_PCM_16_BIT;
3367 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3368 config->format = AUDIO_FORMAT_PCM_16_BIT;
3369 ret = -EINVAL;
3370 goto error_open;
3371 }
3372 out->format = config->format;
3373 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3374 out->config = pcm_config_afe_proxy_playback;
3375 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003377 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3378 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3379 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003380 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3381 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3382 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003383 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3384 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003385 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003386 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003387 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3388 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3389 out->config = pcm_config_mmap_playback;
3390 out->stream.start = out_start;
3391 out->stream.stop = out_stop;
3392 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3393 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003394 } else {
3395 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3396 out->config = pcm_config_low_latency;
3397 }
3398 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3399 if (k_enable_extended_precision
3400 && pcm_params_format_test(adev->use_case_table[out->usecase],
3401 pcm_format_from_audio_format(config->format))) {
3402 out->config.format = pcm_format_from_audio_format(config->format);
3403 /* out->format already set to config->format */
3404 } else {
3405 /* deny the externally proposed config format
3406 * and use the one specified in audio_hw layer configuration.
3407 * Note: out->format is returned by out->stream.common.get_format()
3408 * and is used to set config->format in the code several lines below.
3409 */
3410 out->format = audio_format_from_pcm_format(out->config.format);
3411 }
3412 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003413 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003415 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3416 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003418 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003419 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003420 adev->primary_output = out;
3421 else {
3422 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003423 ret = -EEXIST;
3424 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003425 }
3426 }
3427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428 /* Check if this usecase is already existing */
3429 pthread_mutex_lock(&adev->lock);
3430 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3431 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003432 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003433 ret = -EEXIST;
3434 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435 }
3436 pthread_mutex_unlock(&adev->lock);
3437
3438 out->stream.common.get_sample_rate = out_get_sample_rate;
3439 out->stream.common.set_sample_rate = out_set_sample_rate;
3440 out->stream.common.get_buffer_size = out_get_buffer_size;
3441 out->stream.common.get_channels = out_get_channels;
3442 out->stream.common.get_format = out_get_format;
3443 out->stream.common.set_format = out_set_format;
3444 out->stream.common.standby = out_standby;
3445 out->stream.common.dump = out_dump;
3446 out->stream.common.set_parameters = out_set_parameters;
3447 out->stream.common.get_parameters = out_get_parameters;
3448 out->stream.common.add_audio_effect = out_add_audio_effect;
3449 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3450 out->stream.get_latency = out_get_latency;
3451 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003452#ifdef NO_AUDIO_OUT
3453 out->stream.write = out_write_for_no_output;
3454#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003456#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457 out->stream.get_render_position = out_get_render_position;
3458 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003459 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460
Eric Laurent0e46adf2016-12-16 12:49:24 -08003461 if (out->realtime)
3462 out->af_period_multiplier = af_period_multiplier;
3463 else
3464 out->af_period_multiplier = 1;
3465
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003467 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003468 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003470 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003471 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003472 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003474 config->format = out->stream.common.get_format(&out->stream.common);
3475 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3476 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3477
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003478
3479 /*
3480 By locking output stream before registering, we allow the callback
3481 to update stream's state only after stream's initial state is set to
3482 adev state.
3483 */
3484 lock_output_stream(out);
3485 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3486 pthread_mutex_lock(&adev->lock);
3487 out->card_status = adev->card_status;
3488 pthread_mutex_unlock(&adev->lock);
3489 pthread_mutex_unlock(&out->lock);
3490
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003492
Eric Laurent994a6932013-07-17 11:51:42 -07003493 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003495
3496error_open:
3497 free(out);
3498 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003499 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003500 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501}
3502
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003503static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504 struct audio_stream_out *stream)
3505{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003506 struct stream_out *out = (struct stream_out *)stream;
3507 struct audio_device *adev = out->dev;
3508
Eric Laurent994a6932013-07-17 11:51:42 -07003509 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003510
3511 // must deregister from sndmonitor first to prevent races
3512 // between the callback and close_stream
3513 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003515 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3516 destroy_offload_callback_thread(out);
3517
3518 if (out->compr_config.codec != NULL)
3519 free(out->compr_config.codec);
3520 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003521
3522 if (adev->voice_tx_output == out)
3523 adev->voice_tx_output = NULL;
3524
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003525 pthread_cond_destroy(&out->cond);
3526 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003528 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529}
3530
3531static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3532{
3533 struct audio_device *adev = (struct audio_device *)dev;
3534 struct str_parms *parms;
3535 char *str;
3536 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003537 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003539 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540
Joe Onorato188b6222016-03-01 11:02:27 -08003541 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003542
3543 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003544
3545 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003546 status = voice_set_parameters(adev, parms);
3547 if (status != 0) {
3548 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549 }
3550
3551 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3552 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003553 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3555 adev->bluetooth_nrec = true;
3556 else
3557 adev->bluetooth_nrec = false;
3558 }
3559
3560 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3561 if (ret >= 0) {
3562 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3563 adev->screen_off = false;
3564 else
3565 adev->screen_off = true;
3566 }
3567
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003568 ret = str_parms_get_int(parms, "rotation", &val);
3569 if (ret >= 0) {
3570 bool reverse_speakers = false;
3571 switch(val) {
3572 // FIXME: note that the code below assumes that the speakers are in the correct placement
3573 // relative to the user when the device is rotated 90deg from its default rotation. This
3574 // assumption is device-specific, not platform-specific like this code.
3575 case 270:
3576 reverse_speakers = true;
3577 break;
3578 case 0:
3579 case 90:
3580 case 180:
3581 break;
3582 default:
3583 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003584 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003585 }
Eric Laurent03f09432014-03-25 18:09:11 -07003586 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003587 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003588 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003589 }
3590
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003591 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3592 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003593 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003594 }
3595
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003596 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003597done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003598 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003599 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003600 ALOGV("%s: exit with code(%d)", __func__, status);
3601 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003602}
3603
3604static char* adev_get_parameters(const struct audio_hw_device *dev,
3605 const char *keys)
3606{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003607 struct audio_device *adev = (struct audio_device *)dev;
3608 struct str_parms *reply = str_parms_create();
3609 struct str_parms *query = str_parms_create_str(keys);
3610 char *str;
3611
3612 pthread_mutex_lock(&adev->lock);
3613
3614 voice_get_parameters(adev, query, reply);
3615 str = str_parms_to_str(reply);
3616 str_parms_destroy(query);
3617 str_parms_destroy(reply);
3618
3619 pthread_mutex_unlock(&adev->lock);
3620 ALOGV("%s: exit: returns - %s", __func__, str);
3621 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622}
3623
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003624static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625{
3626 return 0;
3627}
3628
Haynes Mathew George5191a852013-09-11 14:19:36 -07003629static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3630{
3631 int ret;
3632 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003633
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003634 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3635
Haynes Mathew George5191a852013-09-11 14:19:36 -07003636 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003637 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003638 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003639
Haynes Mathew George5191a852013-09-11 14:19:36 -07003640 return ret;
3641}
3642
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003643static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003644{
3645 return -ENOSYS;
3646}
3647
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003648static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3649 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650{
3651 return -ENOSYS;
3652}
3653
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003654static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655{
3656 return -ENOSYS;
3657}
3658
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003659static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660{
3661 return -ENOSYS;
3662}
3663
3664static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3665{
3666 struct audio_device *adev = (struct audio_device *)dev;
3667
3668 pthread_mutex_lock(&adev->lock);
3669 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003670 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003672 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3673 voice_is_in_call(adev)) {
3674 voice_stop_call(adev);
3675 adev->current_call_output = NULL;
3676 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677 }
3678 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003679
3680 audio_extn_extspk_set_mode(adev->extspk, mode);
3681
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682 return 0;
3683}
3684
3685static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3686{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003687 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689
Eric Laurent2bafff12016-03-17 12:17:23 -07003690 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003691 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003692 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3693 ret = audio_extn_hfp_set_mic_mute(adev, state);
3694 } else {
3695 ret = voice_set_mic_mute(adev, state);
3696 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003697 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003698 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003699
3700 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003701}
3702
3703static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3704{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003705 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706 return 0;
3707}
3708
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003709static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003710 const struct audio_config *config)
3711{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003712 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003714 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3715 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716}
3717
3718static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003719 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720 audio_devices_t devices,
3721 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003722 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003723 audio_input_flags_t flags,
3724 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003725 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726{
3727 struct audio_device *adev = (struct audio_device *)dev;
3728 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003729 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003730 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003731 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732
Eric Laurent994a6932013-07-17 11:51:42 -07003733 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734 *stream_in = NULL;
3735 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3736 return -EINVAL;
3737
Zheng Zhang6185d572016-12-01 20:35:17 +08003738 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 -08003739 return -EINVAL;
3740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3742
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003743 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003744 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003745
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003746 in->stream.common.get_sample_rate = in_get_sample_rate;
3747 in->stream.common.set_sample_rate = in_set_sample_rate;
3748 in->stream.common.get_buffer_size = in_get_buffer_size;
3749 in->stream.common.get_channels = in_get_channels;
3750 in->stream.common.get_format = in_get_format;
3751 in->stream.common.set_format = in_set_format;
3752 in->stream.common.standby = in_standby;
3753 in->stream.common.dump = in_dump;
3754 in->stream.common.set_parameters = in_set_parameters;
3755 in->stream.common.get_parameters = in_get_parameters;
3756 in->stream.common.add_audio_effect = in_add_audio_effect;
3757 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3758 in->stream.set_gain = in_set_gain;
3759 in->stream.read = in_read;
3760 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003761 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003762
3763 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003764 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766 in->standby = 1;
3767 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003768 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003769 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770
vivek mehta57ff9b52016-04-28 14:13:08 -07003771 // restrict 24 bit capture for unprocessed source only
3772 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3773 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003774 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003775 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3776 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3777 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3778 bool ret_error = false;
3779 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3780 from HAL is 8_24
3781 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3782 8_24 return error indicating supported format is 8_24
3783 *> In case of any other source requesting 24 bit or float return error
3784 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003785
vivek mehta57ff9b52016-04-28 14:13:08 -07003786 on error flinger will retry with supported format passed
3787 */
3788 if (source != AUDIO_SOURCE_UNPROCESSED) {
3789 config->format = AUDIO_FORMAT_PCM_16_BIT;
3790 ret_error = true;
3791 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3792 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3793 ret_error = true;
3794 }
3795
3796 if (ret_error) {
3797 ret = -EINVAL;
3798 goto err_open;
3799 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003800 }
3801
vivek mehta57ff9b52016-04-28 14:13:08 -07003802 in->format = config->format;
3803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003805 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3806 if (config->sample_rate == 0)
3807 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3808 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3809 config->sample_rate != 8000) {
3810 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3811 ret = -EINVAL;
3812 goto err_open;
3813 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003814
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003815 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3816 config->format = AUDIO_FORMAT_PCM_16_BIT;
3817 ret = -EINVAL;
3818 goto err_open;
3819 }
3820
3821 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3822 in->config = pcm_config_afe_proxy_record;
3823 } else {
3824 in->usecase = USECASE_AUDIO_RECORD;
3825 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08003826 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003827 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003828#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003829 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003830#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003831 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003832 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08003833 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003834 frame_size = audio_stream_in_frame_size(&in->stream);
3835 buffer_size = get_input_buffer_size(config->sample_rate,
3836 config->format,
3837 channel_count,
3838 is_low_latency);
3839 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003840 in->config.rate = config->sample_rate;
3841 in->af_period_multiplier = 1;
3842 } else {
3843 // period size is left untouched for rt mode playback
3844 in->config = pcm_config_audio_capture_rt;
3845 in->af_period_multiplier = af_period_multiplier;
3846 }
3847 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
3848 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
3849 in->usecase = USECASE_AUDIO_RECORD_MMAP;
3850 in->config = pcm_config_mmap_capture;
3851 in->stream.start = in_start;
3852 in->stream.stop = in_stop;
3853 in->stream.create_mmap_buffer = in_create_mmap_buffer;
3854 in->stream.get_mmap_position = in_get_mmap_position;
3855 in->af_period_multiplier = 1;
3856 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
3857 } else {
3858 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003859 frame_size = audio_stream_in_frame_size(&in->stream);
3860 buffer_size = get_input_buffer_size(config->sample_rate,
3861 config->format,
3862 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003863 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003864 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003865 in->config.rate = config->sample_rate;
3866 in->af_period_multiplier = 1;
3867 }
3868 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3869 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003870 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003871
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003872 in->config.channels = channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003873
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003874 /* This stream could be for sound trigger lab,
3875 get sound trigger pcm if present */
3876 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003877
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003878 lock_input_stream(in);
3879 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3880 pthread_mutex_lock(&adev->lock);
3881 in->card_status = adev->card_status;
3882 pthread_mutex_unlock(&adev->lock);
3883 pthread_mutex_unlock(&in->lock);
3884
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003885 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003886 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887 return 0;
3888
3889err_open:
3890 free(in);
3891 *stream_in = NULL;
3892 return ret;
3893}
3894
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003895static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003896 struct audio_stream_in *stream)
3897{
Eric Laurent994a6932013-07-17 11:51:42 -07003898 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003899
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003900 // must deregister from sndmonitor first to prevent races
3901 // between the callback and close_stream
3902 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903 in_standby(&stream->common);
3904 free(stream);
3905
3906 return;
3907}
3908
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003909static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003910{
3911 return 0;
3912}
3913
Andy Hung31aca912014-03-20 17:14:59 -07003914/* verifies input and output devices and their capabilities.
3915 *
3916 * This verification is required when enabling extended bit-depth or
3917 * sampling rates, as not all qcom products support it.
3918 *
3919 * Suitable for calling only on initialization such as adev_open().
3920 * It fills the audio_device use_case_table[] array.
3921 *
3922 * Has a side-effect that it needs to configure audio routing / devices
3923 * in order to power up the devices and read the device parameters.
3924 * It does not acquire any hw device lock. Should restore the devices
3925 * back to "normal state" upon completion.
3926 */
3927static int adev_verify_devices(struct audio_device *adev)
3928{
3929 /* enumeration is a bit difficult because one really wants to pull
3930 * the use_case, device id, etc from the hidden pcm_device_table[].
3931 * In this case there are the following use cases and device ids.
3932 *
3933 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3934 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3935 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3936 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3937 * [USECASE_AUDIO_RECORD] = {0, 0},
3938 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3939 * [USECASE_VOICE_CALL] = {2, 2},
3940 *
3941 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3942 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3943 */
3944
3945 /* should be the usecases enabled in adev_open_input_stream() */
3946 static const int test_in_usecases[] = {
3947 USECASE_AUDIO_RECORD,
3948 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3949 };
3950 /* should be the usecases enabled in adev_open_output_stream()*/
3951 static const int test_out_usecases[] = {
3952 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3953 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3954 };
3955 static const usecase_type_t usecase_type_by_dir[] = {
3956 PCM_PLAYBACK,
3957 PCM_CAPTURE,
3958 };
3959 static const unsigned flags_by_dir[] = {
3960 PCM_OUT,
3961 PCM_IN,
3962 };
3963
3964 size_t i;
3965 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003966 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003967 char info[512]; /* for possible debug info */
3968
3969 for (dir = 0; dir < 2; ++dir) {
3970 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3971 const unsigned flags_dir = flags_by_dir[dir];
3972 const size_t testsize =
3973 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3974 const int *testcases =
3975 dir ? test_in_usecases : test_out_usecases;
3976 const audio_devices_t audio_device =
3977 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3978
3979 for (i = 0; i < testsize; ++i) {
3980 const audio_usecase_t audio_usecase = testcases[i];
3981 int device_id;
3982 snd_device_t snd_device;
3983 struct pcm_params **pparams;
3984 struct stream_out out;
3985 struct stream_in in;
3986 struct audio_usecase uc_info;
3987 int retval;
3988
3989 pparams = &adev->use_case_table[audio_usecase];
3990 pcm_params_free(*pparams); /* can accept null input */
3991 *pparams = NULL;
3992
3993 /* find the device ID for the use case (signed, for error) */
3994 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3995 if (device_id < 0)
3996 continue;
3997
3998 /* prepare structures for device probing */
3999 memset(&uc_info, 0, sizeof(uc_info));
4000 uc_info.id = audio_usecase;
4001 uc_info.type = usecase_type;
4002 if (dir) {
4003 adev->active_input = &in;
4004 memset(&in, 0, sizeof(in));
4005 in.device = audio_device;
4006 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4007 uc_info.stream.in = &in;
4008 } else {
4009 adev->active_input = NULL;
4010 }
4011 memset(&out, 0, sizeof(out));
4012 out.devices = audio_device; /* only field needed in select_devices */
4013 uc_info.stream.out = &out;
4014 uc_info.devices = audio_device;
4015 uc_info.in_snd_device = SND_DEVICE_NONE;
4016 uc_info.out_snd_device = SND_DEVICE_NONE;
4017 list_add_tail(&adev->usecase_list, &uc_info.list);
4018
4019 /* select device - similar to start_(in/out)put_stream() */
4020 retval = select_devices(adev, audio_usecase);
4021 if (retval >= 0) {
4022 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4023#if LOG_NDEBUG == 0
4024 if (*pparams) {
4025 ALOGV("%s: (%s) card %d device %d", __func__,
4026 dir ? "input" : "output", card_id, device_id);
4027 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004028 } else {
4029 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4030 }
4031#endif
4032 }
4033
4034 /* deselect device - similar to stop_(in/out)put_stream() */
4035 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004036 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004037 /* 2. Disable the rx device */
4038 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004039 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004040 list_remove(&uc_info.list);
4041 }
4042 }
4043 adev->active_input = NULL; /* restore adev state */
4044 return 0;
4045}
4046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004047static int adev_close(hw_device_t *device)
4048{
Andy Hung31aca912014-03-20 17:14:59 -07004049 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004051
4052 if (!adev)
4053 return 0;
4054
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004055 audio_extn_tfa_98xx_deinit();
4056
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004057 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004058 pthread_mutex_lock(&adev_init_lock);
4059
4060 if ((--audio_device_ref_count) == 0) {
4061 audio_route_free(adev->audio_route);
4062 free(adev->snd_dev_ref_cnt);
4063 platform_deinit(adev->platform);
4064 audio_extn_extspk_deinit(adev->extspk);
4065 audio_extn_sound_trigger_deinit(adev);
4066 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4067 pcm_params_free(adev->use_case_table[i]);
4068 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004069 if (adev->adm_deinit)
4070 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004071 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004072 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004073
4074 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004076 return 0;
4077}
4078
Glenn Kasten4f993392014-05-14 07:30:48 -07004079/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4080 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4081 * just that it _might_ work.
4082 */
4083static int period_size_is_plausible_for_low_latency(int period_size)
4084{
4085 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004086 case 48:
4087 case 96:
4088 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004089 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004090 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004091 case 240:
4092 case 320:
4093 case 480:
4094 return 1;
4095 default:
4096 return 0;
4097 }
4098}
4099
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004100static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4101{
4102 int card;
4103 card_status_t status;
4104
4105 if (!parms)
4106 return;
4107
4108 if (parse_snd_card_status(parms, &card, &status) < 0)
4109 return;
4110
4111 pthread_mutex_lock(&adev->lock);
4112 bool valid_cb = (card == adev->snd_card);
4113 if (valid_cb) {
4114 if (adev->card_status != status) {
4115 adev->card_status = status;
4116 platform_snd_card_update(adev->platform, status);
4117 }
4118 }
4119 pthread_mutex_unlock(&adev->lock);
4120 return;
4121}
4122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004123static int adev_open(const hw_module_t *module, const char *name,
4124 hw_device_t **device)
4125{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004126 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004127
Eric Laurent2bafff12016-03-17 12:17:23 -07004128 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004129 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004130 pthread_mutex_lock(&adev_init_lock);
4131 if (audio_device_ref_count != 0) {
4132 *device = &adev->device.common;
4133 audio_device_ref_count++;
4134 ALOGV("%s: returning existing instance of adev", __func__);
4135 ALOGV("%s: exit", __func__);
4136 pthread_mutex_unlock(&adev_init_lock);
4137 return 0;
4138 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004139 adev = calloc(1, sizeof(struct audio_device));
4140
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004141 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4142
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004143 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4144 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4145 adev->device.common.module = (struct hw_module_t *)module;
4146 adev->device.common.close = adev_close;
4147
4148 adev->device.init_check = adev_init_check;
4149 adev->device.set_voice_volume = adev_set_voice_volume;
4150 adev->device.set_master_volume = adev_set_master_volume;
4151 adev->device.get_master_volume = adev_get_master_volume;
4152 adev->device.set_master_mute = adev_set_master_mute;
4153 adev->device.get_master_mute = adev_get_master_mute;
4154 adev->device.set_mode = adev_set_mode;
4155 adev->device.set_mic_mute = adev_set_mic_mute;
4156 adev->device.get_mic_mute = adev_get_mic_mute;
4157 adev->device.set_parameters = adev_set_parameters;
4158 adev->device.get_parameters = adev_get_parameters;
4159 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4160 adev->device.open_output_stream = adev_open_output_stream;
4161 adev->device.close_output_stream = adev_close_output_stream;
4162 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004163
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004164 adev->device.close_input_stream = adev_close_input_stream;
4165 adev->device.dump = adev_dump;
4166
4167 /* Set the default route before the PCM stream is opened */
4168 pthread_mutex_lock(&adev->lock);
4169 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004170 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004171 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004172 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004173 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004174 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004175 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004176 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004177 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004178 pthread_mutex_unlock(&adev->lock);
4179
4180 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004181 adev->platform = platform_init(adev);
4182 if (!adev->platform) {
4183 free(adev->snd_dev_ref_cnt);
4184 free(adev);
4185 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4186 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004187 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004188 return -EINVAL;
4189 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004190 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004191 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004192
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004193 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4194 if (adev->visualizer_lib == NULL) {
4195 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4196 } else {
4197 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4198 adev->visualizer_start_output =
4199 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4200 "visualizer_hal_start_output");
4201 adev->visualizer_stop_output =
4202 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4203 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004204 }
4205
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004206 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4207 if (adev->offload_effects_lib == NULL) {
4208 ALOGW("%s: DLOPEN failed for %s", __func__,
4209 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4210 } else {
4211 ALOGV("%s: DLOPEN successful for %s", __func__,
4212 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4213 adev->offload_effects_start_output =
4214 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4215 "offload_effects_bundle_hal_start_output");
4216 adev->offload_effects_stop_output =
4217 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4218 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004219 }
4220
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004221 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4222 if (adev->adm_lib == NULL) {
4223 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4224 } else {
4225 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4226 adev->adm_init = (adm_init_t)
4227 dlsym(adev->adm_lib, "adm_init");
4228 adev->adm_deinit = (adm_deinit_t)
4229 dlsym(adev->adm_lib, "adm_deinit");
4230 adev->adm_register_input_stream = (adm_register_input_stream_t)
4231 dlsym(adev->adm_lib, "adm_register_input_stream");
4232 adev->adm_register_output_stream = (adm_register_output_stream_t)
4233 dlsym(adev->adm_lib, "adm_register_output_stream");
4234 adev->adm_deregister_stream = (adm_deregister_stream_t)
4235 dlsym(adev->adm_lib, "adm_deregister_stream");
4236 adev->adm_request_focus = (adm_request_focus_t)
4237 dlsym(adev->adm_lib, "adm_request_focus");
4238 adev->adm_abandon_focus = (adm_abandon_focus_t)
4239 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004240 adev->adm_set_config = (adm_set_config_t)
4241 dlsym(adev->adm_lib, "adm_set_config");
4242 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4243 dlsym(adev->adm_lib, "adm_request_focus_v2");
4244 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4245 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4246 adev->adm_on_routing_change = (adm_on_routing_change_t)
4247 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004248 }
4249
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004250 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004251 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004252
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004253 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004254
Andy Hung31aca912014-03-20 17:14:59 -07004255 if (k_enable_extended_precision)
4256 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004257
Glenn Kasten4f993392014-05-14 07:30:48 -07004258 char value[PROPERTY_VALUE_MAX];
4259 int trial;
4260 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4261 trial = atoi(value);
4262 if (period_size_is_plausible_for_low_latency(trial)) {
4263 pcm_config_low_latency.period_size = trial;
4264 pcm_config_low_latency.start_threshold = trial / 4;
4265 pcm_config_low_latency.avail_min = trial / 4;
4266 configured_low_latency_capture_period_size = trial;
4267 }
4268 }
4269 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4270 trial = atoi(value);
4271 if (period_size_is_plausible_for_low_latency(trial)) {
4272 configured_low_latency_capture_period_size = trial;
4273 }
4274 }
4275
Yamit Mehtae3b99562016-09-16 22:44:00 +05304276 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004277 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004278
4279 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4280 af_period_multiplier = atoi(value);
4281 if (af_period_multiplier < 0) {
4282 af_period_multiplier = 2;
4283 } else if (af_period_multiplier > 4) {
4284 af_period_multiplier = 4;
4285 }
4286 ALOGV("new period_multiplier = %d", af_period_multiplier);
4287 }
4288
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004289 audio_extn_tfa_98xx_init(adev);
4290
vivek mehta1a9b7c02015-06-25 11:49:38 -07004291 pthread_mutex_unlock(&adev_init_lock);
4292
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004293 if (adev->adm_init)
4294 adev->adm_data = adev->adm_init();
4295
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004296 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004297 audio_extn_snd_mon_init();
4298 pthread_mutex_lock(&adev->lock);
4299 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4300 adev->card_status = CARD_STATUS_ONLINE;
4301 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004302
Eric Laurent2bafff12016-03-17 12:17:23 -07004303 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004304 return 0;
4305}
4306
4307static struct hw_module_methods_t hal_module_methods = {
4308 .open = adev_open,
4309};
4310
4311struct audio_module HAL_MODULE_INFO_SYM = {
4312 .common = {
4313 .tag = HARDWARE_MODULE_TAG,
4314 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4315 .hal_api_version = HARDWARE_HAL_API_VERSION,
4316 .id = AUDIO_HARDWARE_MODULE_ID,
4317 .name = "QCOM Audio HAL",
4318 .author = "Code Aurora Forum",
4319 .methods = &hal_module_methods,
4320 },
4321};