blob: 7a019ba356ef558a81ff6f0fbec3327d485b21af [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
David Lin8c03e672017-02-06 20:31:38 -0800861 platform_check_and_set_playback_backend_cfg(adev, uc_info, snd_device);
862
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700863 /*
864 * This function is to make sure that all the usecases that are active on
865 * the hardware codec backend are always routed to any one device that is
866 * handled by the hardware codec.
867 * For example, if low-latency and deep-buffer usecases are currently active
868 * on speaker and out_set_parameters(headset) is received on low-latency
869 * output, then we have to make sure deep-buffer is also switched to headset,
870 * because of the limitation that both the devices cannot be enabled
871 * at the same time as they share the same backend.
872 */
873 /* Disable all the usecases on the shared backend other than the
874 specified usecase */
875 for (i = 0; i < AUDIO_USECASE_MAX; i++)
876 switch_device[i] = false;
877
878 list_for_each(node, &adev->usecase_list) {
879 usecase = node_to_item(node, struct audio_usecase, list);
880 if (usecase->type != PCM_CAPTURE &&
881 usecase != uc_info &&
882 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700883 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
884 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700885 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
886 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700887 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700888 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700889 switch_device[usecase->id] = true;
890 num_uc_to_switch++;
891 }
892 }
893
894 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700895 list_for_each(node, &adev->usecase_list) {
896 usecase = node_to_item(node, struct audio_usecase, list);
897 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700898 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900899 }
900 }
901
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700902 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900903 list_for_each(node, &adev->usecase_list) {
904 usecase = node_to_item(node, struct audio_usecase, list);
905 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700906 d_device = derive_playback_snd_device(usecase, uc_info,
907 snd_device);
908 enable_snd_device(adev, d_device);
909 /* Update the out_snd_device before enabling the audio route */
910 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700911 }
912 }
913
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700914 /* Re-route all the usecases on the shared backend other than the
915 specified usecase to new snd devices */
916 list_for_each(node, &adev->usecase_list) {
917 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700918 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700919 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700920 }
921 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700922 }
923}
924
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700925static void check_and_route_capture_usecases(struct audio_device *adev,
926 struct audio_usecase *uc_info,
927 snd_device_t snd_device)
928{
929 struct listnode *node;
930 struct audio_usecase *usecase;
931 bool switch_device[AUDIO_USECASE_MAX];
932 int i, num_uc_to_switch = 0;
933
vivek mehta4ed66e62016-04-15 23:33:34 -0700934 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
935
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700936 /*
937 * This function is to make sure that all the active capture usecases
938 * are always routed to the same input sound device.
939 * For example, if audio-record and voice-call usecases are currently
940 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
941 * is received for voice call then we have to make sure that audio-record
942 * usecase is also switched to earpiece i.e. voice-dmic-ef,
943 * because of the limitation that two devices cannot be enabled
944 * at the same time if they share the same backend.
945 */
946 for (i = 0; i < AUDIO_USECASE_MAX; i++)
947 switch_device[i] = false;
948
949 list_for_each(node, &adev->usecase_list) {
950 usecase = node_to_item(node, struct audio_usecase, list);
951 if (usecase->type != PCM_PLAYBACK &&
952 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700953 usecase->in_snd_device != snd_device &&
954 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700955 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
956 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700957 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700958 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700959 switch_device[usecase->id] = true;
960 num_uc_to_switch++;
961 }
962 }
963
964 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700965 list_for_each(node, &adev->usecase_list) {
966 usecase = node_to_item(node, struct audio_usecase, list);
967 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700968 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700969 }
970 }
971
972 list_for_each(node, &adev->usecase_list) {
973 usecase = node_to_item(node, struct audio_usecase, list);
974 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700975 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700976 }
977 }
978
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700979 /* Re-route all the usecases on the shared backend other than the
980 specified usecase to new snd devices */
981 list_for_each(node, &adev->usecase_list) {
982 usecase = node_to_item(node, struct audio_usecase, list);
983 /* Update the in_snd_device only before enabling the audio route */
984 if (switch_device[usecase->id] ) {
985 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700986 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700987 }
988 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700989 }
990}
991
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800992/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700993static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800994{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700995 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700996 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800997
998 switch (channels) {
999 /*
1000 * Do not handle stereo output in Multi-channel cases
1001 * Stereo case is handled in normal playback path
1002 */
1003 case 6:
1004 ALOGV("%s: HDMI supports 5.1", __func__);
1005 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1006 break;
1007 case 8:
1008 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1009 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1010 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1011 break;
1012 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001013 ALOGE("HDMI does not support multi channel playback");
1014 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001015 break;
1016 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001017 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018}
1019
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001020static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1021{
1022 struct audio_usecase *usecase;
1023 struct listnode *node;
1024
1025 list_for_each(node, &adev->usecase_list) {
1026 usecase = node_to_item(node, struct audio_usecase, list);
1027 if (usecase->type == VOICE_CALL) {
1028 ALOGV("%s: usecase id %d", __func__, usecase->id);
1029 return usecase->id;
1030 }
1031 }
1032 return USECASE_INVALID;
1033}
1034
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001035struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1036 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001037{
1038 struct audio_usecase *usecase;
1039 struct listnode *node;
1040
1041 list_for_each(node, &adev->usecase_list) {
1042 usecase = node_to_item(node, struct audio_usecase, list);
1043 if (usecase->id == uc_id)
1044 return usecase;
1045 }
1046 return NULL;
1047}
1048
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001049int select_devices(struct audio_device *adev,
1050 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001051{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001052 snd_device_t out_snd_device = SND_DEVICE_NONE;
1053 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001054 struct audio_usecase *usecase = NULL;
1055 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001056 struct audio_usecase *hfp_usecase = NULL;
1057 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001058 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001059 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001060
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001061 usecase = get_usecase_from_list(adev, uc_id);
1062 if (usecase == NULL) {
1063 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1064 return -EINVAL;
1065 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001066
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001067 if ((usecase->type == VOICE_CALL) ||
1068 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001069 out_snd_device = platform_get_output_snd_device(adev->platform,
1070 usecase->stream.out->devices);
1071 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001072 usecase->devices = usecase->stream.out->devices;
1073 } else {
1074 /*
1075 * If the voice call is active, use the sound devices of voice call usecase
1076 * so that it would not result any device switch. All the usecases will
1077 * be switched to new device when select_devices() is called for voice call
1078 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001079 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001080 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001081 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001082 vc_usecase = get_usecase_from_list(adev,
1083 get_voice_usecase_id_from_list(adev));
1084 if ((vc_usecase != NULL) &&
1085 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1086 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001087 in_snd_device = vc_usecase->in_snd_device;
1088 out_snd_device = vc_usecase->out_snd_device;
1089 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001090 } else if (audio_extn_hfp_is_active(adev)) {
1091 hfp_ucid = audio_extn_hfp_get_usecase();
1092 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1093 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1094 in_snd_device = hfp_usecase->in_snd_device;
1095 out_snd_device = hfp_usecase->out_snd_device;
1096 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001097 }
1098 if (usecase->type == PCM_PLAYBACK) {
1099 usecase->devices = usecase->stream.out->devices;
1100 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001101 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001102 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001103 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001104 if (usecase->stream.out == adev->primary_output &&
1105 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001106 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1107 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001108 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001109 select_devices(adev, adev->active_input->usecase);
1110 }
1111 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001112 } else if (usecase->type == PCM_CAPTURE) {
1113 usecase->devices = usecase->stream.in->device;
1114 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001115 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001116 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001117 if (adev->active_input &&
1118 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1119 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001120 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001121 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1122 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1123 } else if (adev->primary_output) {
1124 out_device = adev->primary_output->devices;
1125 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001126 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001127 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001128 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001129 }
1130 }
1131
1132 if (out_snd_device == usecase->out_snd_device &&
1133 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001134 return 0;
1135 }
1136
Eric Laurent2bafff12016-03-17 12:17:23 -07001137 if (out_snd_device != SND_DEVICE_NONE &&
1138 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1139 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1140 __func__,
1141 use_case_table[uc_id],
1142 adev->last_logged_snd_device[uc_id][0],
1143 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1144 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1145 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1146 -1,
1147 out_snd_device,
1148 platform_get_snd_device_name(out_snd_device),
1149 platform_get_snd_device_acdb_id(out_snd_device));
1150 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1151 }
1152 if (in_snd_device != SND_DEVICE_NONE &&
1153 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1154 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1155 __func__,
1156 use_case_table[uc_id],
1157 adev->last_logged_snd_device[uc_id][1],
1158 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1159 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1160 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1161 -1,
1162 in_snd_device,
1163 platform_get_snd_device_name(in_snd_device),
1164 platform_get_snd_device_acdb_id(in_snd_device));
1165 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1166 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001167
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001168 /*
1169 * Limitation: While in call, to do a device switch we need to disable
1170 * and enable both RX and TX devices though one of them is same as current
1171 * device.
1172 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001173 if ((usecase->type == VOICE_CALL) &&
1174 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1175 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001176 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001177 /* Disable sidetone only if voice call already exists */
1178 if (voice_is_call_state_active(adev))
1179 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001180 }
1181
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001182 /* Disable current sound devices */
1183 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001184 disable_audio_route(adev, usecase);
1185 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001186 }
1187
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001188 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001189 disable_audio_route(adev, usecase);
1190 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001191 }
1192
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001193 /* Applicable only on the targets that has external modem.
1194 * New device information should be sent to modem before enabling
1195 * the devices to reduce in-call device switch time.
1196 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001197 if ((usecase->type == VOICE_CALL) &&
1198 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1199 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001200 status = platform_switch_voice_call_enable_device_config(adev->platform,
1201 out_snd_device,
1202 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001203 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001204
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001205 /* Enable new sound devices */
1206 if (out_snd_device != SND_DEVICE_NONE) {
David Lin8c03e672017-02-06 20:31:38 -08001207 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1208 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001209 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001210 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001211 }
1212
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001213 if (in_snd_device != SND_DEVICE_NONE) {
1214 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001215 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001216 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001217
Eric Laurentb23d5282013-05-14 15:27:20 -07001218 if (usecase->type == VOICE_CALL)
1219 status = platform_switch_voice_call_device_post(adev->platform,
1220 out_snd_device,
1221 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001222
sangwoo170731f2013-06-08 15:36:36 +09001223 usecase->in_snd_device = in_snd_device;
1224 usecase->out_snd_device = out_snd_device;
1225
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001226 audio_extn_tfa_98xx_set_mode();
1227
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001228 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001229
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001230 /* Applicable only on the targets that has external modem.
1231 * Enable device command should be sent to modem only after
1232 * enabling voice call mixer controls
1233 */
vivek mehta765eb642015-08-07 19:46:06 -07001234 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001235 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1236 out_snd_device,
1237 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001238 /* Enable sidetone only if voice call already exists */
1239 if (voice_is_call_state_active(adev))
1240 voice_set_sidetone(adev, out_snd_device, true);
1241 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001242
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001243 return status;
1244}
1245
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001246static int stop_input_stream(struct stream_in *in)
1247{
1248 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001249 struct audio_usecase *uc_info;
1250 struct audio_device *adev = in->dev;
1251
Eric Laurentc8400632013-02-14 19:04:54 -08001252 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001253
Eric Laurent994a6932013-07-17 11:51:42 -07001254 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001255 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001256 uc_info = get_usecase_from_list(adev, in->usecase);
1257 if (uc_info == NULL) {
1258 ALOGE("%s: Could not find the usecase (%d) in the list",
1259 __func__, in->usecase);
1260 return -EINVAL;
1261 }
1262
Eric Laurent150dbfe2013-02-27 14:31:02 -08001263 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001264 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001265
1266 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001267 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001268
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001269 list_remove(&uc_info->list);
1270 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001271
Eric Laurent994a6932013-07-17 11:51:42 -07001272 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001273 return ret;
1274}
1275
1276int start_input_stream(struct stream_in *in)
1277{
1278 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001279 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001280 struct audio_usecase *uc_info;
1281 struct audio_device *adev = in->dev;
1282
Eric Laurent994a6932013-07-17 11:51:42 -07001283 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001284
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001285 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1286 return -EIO;
1287
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001288 if (in->card_status == CARD_STATUS_OFFLINE ||
1289 adev->card_status == CARD_STATUS_OFFLINE) {
1290 ALOGW("in->card_status or adev->card_status offline, try again");
1291 ret = -EAGAIN;
1292 goto error_config;
1293 }
1294
Eric Laurentb23d5282013-05-14 15:27:20 -07001295 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001296 if (in->pcm_device_id < 0) {
1297 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1298 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001299 ret = -EINVAL;
1300 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001301 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001302
1303 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001304 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1305 uc_info->id = in->usecase;
1306 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001307 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001308 uc_info->devices = in->device;
1309 uc_info->in_snd_device = SND_DEVICE_NONE;
1310 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001311
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001312 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001313
1314 audio_extn_perf_lock_acquire();
1315
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001316 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001317
Eric Laurent0e46adf2016-12-16 12:49:24 -08001318 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001319 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001320 ALOGE("%s: pcm stream not ready", __func__);
1321 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001322 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001323 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001324 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001325 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1326 goto error_open;
1327 }
1328 } else {
1329 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1330 unsigned int pcm_open_retry_count = 0;
1331
1332 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1333 flags |= PCM_MMAP | PCM_NOIRQ;
1334 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1335 } else if (in->realtime) {
1336 flags |= PCM_MMAP | PCM_NOIRQ;
1337 }
1338
1339 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1340 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1341
1342 while (1) {
1343 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1344 flags, &in->config);
1345 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1346 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1347 if (in->pcm != NULL) {
1348 pcm_close(in->pcm);
1349 in->pcm = NULL;
1350 }
1351 if (pcm_open_retry_count-- == 0) {
1352 ret = -EIO;
1353 goto error_open;
1354 }
1355 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1356 continue;
1357 }
1358 break;
1359 }
1360
1361 ALOGV("%s: pcm_prepare", __func__);
1362 ret = pcm_prepare(in->pcm);
1363 if (ret < 0) {
1364 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001365 pcm_close(in->pcm);
1366 in->pcm = NULL;
1367 goto error_open;
1368 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001369 if (in->realtime) {
1370 ret = pcm_start(in->pcm);
1371 if (ret < 0) {
1372 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1373 pcm_close(in->pcm);
1374 in->pcm = NULL;
1375 goto error_open;
1376 }
1377 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001378 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001379 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001380 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001381 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001382
Eric Laurent0e46adf2016-12-16 12:49:24 -08001383 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001384
1385error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001386 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001387 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001388
1389error_config:
1390 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001391 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001392
1393 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001394}
1395
Eric Laurenta1478072015-09-21 17:21:52 -07001396void lock_input_stream(struct stream_in *in)
1397{
1398 pthread_mutex_lock(&in->pre_lock);
1399 pthread_mutex_lock(&in->lock);
1400 pthread_mutex_unlock(&in->pre_lock);
1401}
1402
1403void lock_output_stream(struct stream_out *out)
1404{
1405 pthread_mutex_lock(&out->pre_lock);
1406 pthread_mutex_lock(&out->lock);
1407 pthread_mutex_unlock(&out->pre_lock);
1408}
1409
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001410/* must be called with out->lock locked */
1411static int send_offload_cmd_l(struct stream_out* out, int command)
1412{
1413 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1414
1415 ALOGVV("%s %d", __func__, command);
1416
1417 cmd->cmd = command;
1418 list_add_tail(&out->offload_cmd_list, &cmd->node);
1419 pthread_cond_signal(&out->offload_cond);
1420 return 0;
1421}
1422
1423/* must be called iwth out->lock locked */
1424static void stop_compressed_output_l(struct stream_out *out)
1425{
1426 out->offload_state = OFFLOAD_STATE_IDLE;
1427 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001428 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001429 if (out->compr != NULL) {
1430 compress_stop(out->compr);
1431 while (out->offload_thread_blocked) {
1432 pthread_cond_wait(&out->cond, &out->lock);
1433 }
1434 }
1435}
1436
1437static void *offload_thread_loop(void *context)
1438{
1439 struct stream_out *out = (struct stream_out *) context;
1440 struct listnode *item;
1441
1442 out->offload_state = OFFLOAD_STATE_IDLE;
1443 out->playback_started = 0;
1444
1445 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1446 set_sched_policy(0, SP_FOREGROUND);
1447 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1448
1449 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001450 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001451 for (;;) {
1452 struct offload_cmd *cmd = NULL;
1453 stream_callback_event_t event;
1454 bool send_callback = false;
1455
1456 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1457 __func__, list_empty(&out->offload_cmd_list),
1458 out->offload_state);
1459 if (list_empty(&out->offload_cmd_list)) {
1460 ALOGV("%s SLEEPING", __func__);
1461 pthread_cond_wait(&out->offload_cond, &out->lock);
1462 ALOGV("%s RUNNING", __func__);
1463 continue;
1464 }
1465
1466 item = list_head(&out->offload_cmd_list);
1467 cmd = node_to_item(item, struct offload_cmd, node);
1468 list_remove(item);
1469
1470 ALOGVV("%s STATE %d CMD %d out->compr %p",
1471 __func__, out->offload_state, cmd->cmd, out->compr);
1472
1473 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1474 free(cmd);
1475 break;
1476 }
1477
1478 if (out->compr == NULL) {
1479 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001480 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001481 pthread_cond_signal(&out->cond);
1482 continue;
1483 }
1484 out->offload_thread_blocked = true;
1485 pthread_mutex_unlock(&out->lock);
1486 send_callback = false;
1487 switch(cmd->cmd) {
1488 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1489 compress_wait(out->compr, -1);
1490 send_callback = true;
1491 event = STREAM_CBK_EVENT_WRITE_READY;
1492 break;
1493 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001494 compress_next_track(out->compr);
1495 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001496 send_callback = true;
1497 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001498 /* Resend the metadata for next iteration */
1499 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001500 break;
1501 case OFFLOAD_CMD_DRAIN:
1502 compress_drain(out->compr);
1503 send_callback = true;
1504 event = STREAM_CBK_EVENT_DRAIN_READY;
1505 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001506 case OFFLOAD_CMD_ERROR:
1507 send_callback = true;
1508 event = STREAM_CBK_EVENT_ERROR;
1509 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001510 default:
1511 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1512 break;
1513 }
Eric Laurenta1478072015-09-21 17:21:52 -07001514 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001515 out->offload_thread_blocked = false;
1516 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001517 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001518 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001519 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001520 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001521 free(cmd);
1522 }
1523
1524 pthread_cond_signal(&out->cond);
1525 while (!list_empty(&out->offload_cmd_list)) {
1526 item = list_head(&out->offload_cmd_list);
1527 list_remove(item);
1528 free(node_to_item(item, struct offload_cmd, node));
1529 }
1530 pthread_mutex_unlock(&out->lock);
1531
1532 return NULL;
1533}
1534
1535static int create_offload_callback_thread(struct stream_out *out)
1536{
1537 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1538 list_init(&out->offload_cmd_list);
1539 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1540 offload_thread_loop, out);
1541 return 0;
1542}
1543
1544static int destroy_offload_callback_thread(struct stream_out *out)
1545{
Eric Laurenta1478072015-09-21 17:21:52 -07001546 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001547 stop_compressed_output_l(out);
1548 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1549
1550 pthread_mutex_unlock(&out->lock);
1551 pthread_join(out->offload_thread, (void **) NULL);
1552 pthread_cond_destroy(&out->offload_cond);
1553
1554 return 0;
1555}
1556
Eric Laurent07eeafd2013-10-06 12:52:49 -07001557static bool allow_hdmi_channel_config(struct audio_device *adev)
1558{
1559 struct listnode *node;
1560 struct audio_usecase *usecase;
1561 bool ret = true;
1562
1563 list_for_each(node, &adev->usecase_list) {
1564 usecase = node_to_item(node, struct audio_usecase, list);
1565 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1566 /*
1567 * If voice call is already existing, do not proceed further to avoid
1568 * disabling/enabling both RX and TX devices, CSD calls, etc.
1569 * Once the voice call done, the HDMI channels can be configured to
1570 * max channels of remaining use cases.
1571 */
1572 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001573 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001574 __func__);
1575 ret = false;
1576 break;
1577 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001578 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001579 "no change in HDMI channels", __func__);
1580 ret = false;
1581 break;
1582 }
1583 }
1584 }
1585 return ret;
1586}
1587
1588static int check_and_set_hdmi_channels(struct audio_device *adev,
1589 unsigned int channels)
1590{
1591 struct listnode *node;
1592 struct audio_usecase *usecase;
1593
1594 /* Check if change in HDMI channel config is allowed */
1595 if (!allow_hdmi_channel_config(adev))
1596 return 0;
1597
1598 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001599 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001600 return 0;
1601 }
1602
1603 platform_set_hdmi_channels(adev->platform, channels);
1604 adev->cur_hdmi_channels = channels;
1605
1606 /*
1607 * Deroute all the playback streams routed to HDMI so that
1608 * the back end is deactivated. Note that backend will not
1609 * be deactivated if any one stream is connected to it.
1610 */
1611 list_for_each(node, &adev->usecase_list) {
1612 usecase = node_to_item(node, struct audio_usecase, list);
1613 if (usecase->type == PCM_PLAYBACK &&
1614 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001615 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001616 }
1617 }
1618
1619 /*
1620 * Enable all the streams disabled above. Now the HDMI backend
1621 * will be activated with new channel configuration
1622 */
1623 list_for_each(node, &adev->usecase_list) {
1624 usecase = node_to_item(node, struct audio_usecase, list);
1625 if (usecase->type == PCM_PLAYBACK &&
1626 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001627 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001628 }
1629 }
1630
1631 return 0;
1632}
1633
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001634static int stop_output_stream(struct stream_out *out)
1635{
1636 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001637 struct audio_usecase *uc_info;
1638 struct audio_device *adev = out->dev;
1639
Eric Laurent994a6932013-07-17 11:51:42 -07001640 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001641 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001642 uc_info = get_usecase_from_list(adev, out->usecase);
1643 if (uc_info == NULL) {
1644 ALOGE("%s: Could not find the usecase (%d) in the list",
1645 __func__, out->usecase);
1646 return -EINVAL;
1647 }
1648
Haynes Mathew George41f86652014-06-17 14:22:15 -07001649 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1650 if (adev->visualizer_stop_output != NULL)
1651 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1652 if (adev->offload_effects_stop_output != NULL)
1653 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1654 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001655
Eric Laurent150dbfe2013-02-27 14:31:02 -08001656 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001657 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001658
1659 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001660 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001662 list_remove(&uc_info->list);
1663 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664
Eric Laurent0499d4f2014-08-25 22:39:29 -05001665 audio_extn_extspk_update(adev->extspk);
1666
Eric Laurent07eeafd2013-10-06 12:52:49 -07001667 /* Must be called after removing the usecase from list */
1668 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1669 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1670
Eric Laurent994a6932013-07-17 11:51:42 -07001671 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672 return ret;
1673}
1674
1675int start_output_stream(struct stream_out *out)
1676{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001677 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678 struct audio_usecase *uc_info;
1679 struct audio_device *adev = out->dev;
1680
Eric Laurent994a6932013-07-17 11:51:42 -07001681 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001682 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001683
1684 if (out->card_status == CARD_STATUS_OFFLINE ||
1685 adev->card_status == CARD_STATUS_OFFLINE) {
1686 ALOGW("out->card_status or adev->card_status offline, try again");
1687 ret = -EAGAIN;
1688 goto error_config;
1689 }
1690
Eric Laurentb23d5282013-05-14 15:27:20 -07001691 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001692 if (out->pcm_device_id < 0) {
1693 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1694 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001695 ret = -EINVAL;
1696 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697 }
1698
1699 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1700 uc_info->id = out->usecase;
1701 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001702 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001703 uc_info->devices = out->devices;
1704 uc_info->in_snd_device = SND_DEVICE_NONE;
1705 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001706
Eric Laurent07eeafd2013-10-06 12:52:49 -07001707 /* This must be called before adding this usecase to the list */
1708 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1709 check_and_set_hdmi_channels(adev, out->config.channels);
1710
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001711 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001712
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001713 audio_extn_perf_lock_acquire();
1714
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001715 select_devices(adev, out->usecase);
1716
Eric Laurent0499d4f2014-08-25 22:39:29 -05001717 audio_extn_extspk_update(adev->extspk);
1718
Andy Hung31aca912014-03-20 17:14:59 -07001719 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001720 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001721 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1722 out->pcm = NULL;
1723 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1724 COMPRESS_IN, &out->compr_config);
1725 if (out->compr && !is_compress_ready(out->compr)) {
1726 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1727 compress_close(out->compr);
1728 out->compr = NULL;
1729 ret = -EIO;
1730 goto error_open;
1731 }
1732 if (out->offload_callback)
1733 compress_nonblock(out->compr, out->non_blocking);
1734
1735 if (adev->visualizer_start_output != NULL)
1736 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1737 if (adev->offload_effects_start_output != NULL)
1738 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1739 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001740 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001741 ALOGE("%s: pcm stream not ready", __func__);
1742 goto error_open;
1743 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001744 ret = pcm_start(out->pcm);
1745 if (ret < 0) {
1746 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1747 goto error_open;
1748 }
1749 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001750 unsigned int flags = PCM_OUT;
1751 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001752
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001753 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1754 flags |= PCM_MMAP | PCM_NOIRQ;
1755 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001756 } else if (out->realtime) {
1757 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001758 } else
1759 flags |= PCM_MONOTONIC;
1760
1761 while (1) {
1762 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1763 flags, &out->config);
1764 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1765 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1766 if (out->pcm != NULL) {
1767 pcm_close(out->pcm);
1768 out->pcm = NULL;
1769 }
1770 if (pcm_open_retry_count-- == 0) {
1771 ret = -EIO;
1772 goto error_open;
1773 }
1774 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1775 continue;
1776 }
1777 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001778 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001779 ALOGV("%s: pcm_prepare", __func__);
1780 if (pcm_is_ready(out->pcm)) {
1781 ret = pcm_prepare(out->pcm);
1782 if (ret < 0) {
1783 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1784 pcm_close(out->pcm);
1785 out->pcm = NULL;
1786 goto error_open;
1787 }
1788 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001789 if (out->realtime) {
1790 ret = pcm_start(out->pcm);
1791 if (ret < 0) {
1792 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1793 pcm_close(out->pcm);
1794 out->pcm = NULL;
1795 goto error_open;
1796 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001797 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001798 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001799 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001800 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001801 audio_extn_tfa_98xx_enable_speaker();
1802
Eric Laurent994a6932013-07-17 11:51:42 -07001803 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001804 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001805error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001806 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001808error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001809 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001810}
1811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812static int check_input_parameters(uint32_t sample_rate,
1813 audio_format_t format,
1814 int channel_count)
1815{
vivek mehta4ed66e62016-04-15 23:33:34 -07001816 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001817 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1818 return -EINVAL;
1819 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001820
vivek mehtadae44712015-07-27 14:13:18 -07001821 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001822 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001823 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1824 return -EINVAL;
1825 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826
1827 switch (sample_rate) {
1828 case 8000:
1829 case 11025:
1830 case 12000:
1831 case 16000:
1832 case 22050:
1833 case 24000:
1834 case 32000:
1835 case 44100:
1836 case 48000:
1837 break;
1838 default:
vivek mehtadae44712015-07-27 14:13:18 -07001839 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840 return -EINVAL;
1841 }
1842
1843 return 0;
1844}
1845
1846static size_t get_input_buffer_size(uint32_t sample_rate,
1847 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001848 int channel_count,
1849 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850{
1851 size_t size = 0;
1852
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001853 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1854 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001855
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001856 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001857 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001858 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001859
1860 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861
Glenn Kasten4f993392014-05-14 07:30:48 -07001862 /* make sure the size is multiple of 32 bytes
1863 * At 48 kHz mono 16-bit PCM:
1864 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1865 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1866 */
1867 size += 0x1f;
1868 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001869
1870 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001871}
1872
1873static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1874{
1875 struct stream_out *out = (struct stream_out *)stream;
1876
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001877 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001878}
1879
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001880static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881{
1882 return -ENOSYS;
1883}
1884
1885static size_t out_get_buffer_size(const struct audio_stream *stream)
1886{
1887 struct stream_out *out = (struct stream_out *)stream;
1888
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001889 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1890 return out->compr_config.fragment_size;
1891 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001892 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001893 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001894}
1895
1896static uint32_t out_get_channels(const struct audio_stream *stream)
1897{
1898 struct stream_out *out = (struct stream_out *)stream;
1899
1900 return out->channel_mask;
1901}
1902
1903static audio_format_t out_get_format(const struct audio_stream *stream)
1904{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001905 struct stream_out *out = (struct stream_out *)stream;
1906
1907 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001908}
1909
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001910static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001911{
1912 return -ENOSYS;
1913}
1914
1915static int out_standby(struct audio_stream *stream)
1916{
1917 struct stream_out *out = (struct stream_out *)stream;
1918 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001919 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001920
Eric Laurent994a6932013-07-17 11:51:42 -07001921 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001922 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001923
Eric Laurenta1478072015-09-21 17:21:52 -07001924 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001925 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001926 if (adev->adm_deregister_stream)
1927 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001928 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001929 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001930 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1931 if (out->pcm) {
1932 pcm_close(out->pcm);
1933 out->pcm = NULL;
1934 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001935 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001936 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08001937 out->playback_started = false;
1938 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001939 } else {
1940 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001941 out->gapless_mdata.encoder_delay = 0;
1942 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001943 if (out->compr != NULL) {
1944 compress_close(out->compr);
1945 out->compr = NULL;
1946 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001947 }
Phil Burkbc991042017-02-24 08:06:44 -08001948 if (do_stop) {
1949 stop_output_stream(out);
1950 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001951 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001952 }
1953 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001954 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001955 return 0;
1956}
1957
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001958static int out_on_error(struct audio_stream *stream)
1959{
1960 struct stream_out *out = (struct stream_out *)stream;
1961 struct audio_device *adev = out->dev;
1962 bool do_standby = false;
1963
1964 lock_output_stream(out);
1965 if (!out->standby) {
1966 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1967 stop_compressed_output_l(out);
1968 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1969 } else
1970 do_standby = true;
1971 }
1972 pthread_mutex_unlock(&out->lock);
1973
1974 if (do_standby)
1975 return out_standby(&out->stream.common);
1976
1977 return 0;
1978}
1979
Andy Hung7401c7c2016-09-21 12:41:21 -07001980static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001981{
Andy Hung7401c7c2016-09-21 12:41:21 -07001982 struct stream_out *out = (struct stream_out *)stream;
1983
1984 // We try to get the lock for consistency,
1985 // but it isn't necessary for these variables.
1986 // If we're not in standby, we may be blocked on a write.
1987 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1988 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1989 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1990
1991 if (locked) {
1992 log_dump_l(&out->error_log, fd);
1993 pthread_mutex_unlock(&out->lock);
1994 } else {
1995 // We don't have the lock here, copy for safety.
1996 struct error_log log = out->error_log;
1997 log_dump_l(&log, fd);
1998 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999 return 0;
2000}
2001
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002002static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2003{
2004 int ret = 0;
2005 char value[32];
2006 struct compr_gapless_mdata tmp_mdata;
2007
2008 if (!out || !parms) {
2009 return -EINVAL;
2010 }
2011
2012 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2013 if (ret >= 0) {
2014 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2015 } else {
2016 return -EINVAL;
2017 }
2018
2019 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2020 if (ret >= 0) {
2021 tmp_mdata.encoder_padding = atoi(value);
2022 } else {
2023 return -EINVAL;
2024 }
2025
2026 out->gapless_mdata = tmp_mdata;
2027 out->send_new_metadata = 1;
2028 ALOGV("%s new encoder delay %u and padding %u", __func__,
2029 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2030
2031 return 0;
2032}
2033
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002034static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2035{
2036 return out == adev->primary_output || out == adev->voice_tx_output;
2037}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002038
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002039static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2040{
2041 struct stream_out *out = (struct stream_out *)stream;
2042 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002043 struct audio_usecase *usecase;
2044 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045 struct str_parms *parms;
2046 char value[32];
2047 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002048 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002049 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050
Eric Laurent2e140aa2016-06-30 17:14:46 -07002051 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002052 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002053 parms = str_parms_create_str(kvpairs);
2054 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2055 if (ret >= 0) {
2056 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002057 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002058 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002060 /*
2061 * When HDMI cable is unplugged the music playback is paused and
2062 * the policy manager sends routing=0. But the audioflinger
2063 * continues to write data until standby time (3sec).
2064 * As the HDMI core is turned off, the write gets blocked.
2065 * Avoid this by routing audio to speaker until standby.
2066 */
2067 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2068 val == AUDIO_DEVICE_NONE) {
2069 val = AUDIO_DEVICE_OUT_SPEAKER;
2070 }
2071
2072 /*
2073 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002074 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002075 * the select_devices(). But how do we undo this?
2076 *
2077 * For example, music playback is active on headset (deep-buffer usecase)
2078 * and if we go to ringtones and select a ringtone, low-latency usecase
2079 * will be started on headset+speaker. As we can't enable headset+speaker
2080 * and headset devices at the same time, select_devices() switches the music
2081 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2082 * So when the ringtone playback is completed, how do we undo the same?
2083 *
2084 * We are relying on the out_set_parameters() call on deep-buffer output,
2085 * once the ringtone playback is ended.
2086 * NOTE: We should not check if the current devices are same as new devices.
2087 * Because select_devices() must be called to switch back the music
2088 * playback to headset.
2089 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002090 audio_devices_t new_dev = val;
2091 if (new_dev != AUDIO_DEVICE_NONE) {
2092 bool same_dev = out->devices == new_dev;
2093 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002094
Eric Laurenta7657192014-10-09 21:09:33 -07002095 if (output_drives_call(adev, out)) {
2096 if (!voice_is_in_call(adev)) {
2097 if (adev->mode == AUDIO_MODE_IN_CALL) {
2098 adev->current_call_output = out;
2099 ret = voice_start_call(adev);
2100 }
2101 } else {
2102 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002103 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002104 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002105 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002106
2107 if (!out->standby) {
2108 if (!same_dev) {
2109 ALOGV("update routing change");
2110 out->routing_change = true;
2111 }
2112 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002113 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002114 }
2115
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002116 }
2117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002119 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002120
2121 /*handles device and call state changes*/
2122 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002124
2125 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2126 parse_compress_metadata(out, parms);
2127 }
2128
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002129 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002130 ALOGV("%s: exit: code(%d)", __func__, status);
2131 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002132}
2133
2134static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2135{
2136 struct stream_out *out = (struct stream_out *)stream;
2137 struct str_parms *query = str_parms_create_str(keys);
2138 char *str;
2139 char value[256];
2140 struct str_parms *reply = str_parms_create();
2141 size_t i, j;
2142 int ret;
2143 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002144 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002145 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2146 if (ret >= 0) {
2147 value[0] = '\0';
2148 i = 0;
2149 while (out->supported_channel_masks[i] != 0) {
2150 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2151 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2152 if (!first) {
2153 strcat(value, "|");
2154 }
2155 strcat(value, out_channels_name_to_enum_table[j].name);
2156 first = false;
2157 break;
2158 }
2159 }
2160 i++;
2161 }
2162 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2163 str = str_parms_to_str(reply);
2164 } else {
2165 str = strdup(keys);
2166 }
2167 str_parms_destroy(query);
2168 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002169 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002170 return str;
2171}
2172
2173static uint32_t out_get_latency(const struct audio_stream_out *stream)
2174{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002175 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002176 struct stream_out *out = (struct stream_out *)stream;
2177
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002178 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2179 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002180 else if ((out->realtime) ||
2181 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002182 // since the buffer won't be filled up faster than realtime,
2183 // return a smaller number
2184 period_ms = (out->af_period_multiplier * out->config.period_size *
2185 1000) / (out->config.rate);
2186 hw_delay = platform_render_latency(out->usecase)/1000;
2187 return period_ms + hw_delay;
2188 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002189
2190 return (out->config.period_count * out->config.period_size * 1000) /
2191 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192}
2193
2194static int out_set_volume(struct audio_stream_out *stream, float left,
2195 float right)
2196{
Eric Laurenta9024de2013-04-04 09:19:12 -07002197 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002198 int volume[2];
2199
Eric Laurenta9024de2013-04-04 09:19:12 -07002200 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2201 /* only take left channel into account: the API is for stereo anyway */
2202 out->muted = (left == 0.0f);
2203 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002204 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2205 const char *mixer_ctl_name = "Compress Playback Volume";
2206 struct audio_device *adev = out->dev;
2207 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002208 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2209 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002210 /* try with the control based on device id */
2211 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2212 PCM_PLAYBACK);
2213 char ctl_name[128] = {0};
2214 snprintf(ctl_name, sizeof(ctl_name),
2215 "Compress Playback %d Volume", pcm_device_id);
2216 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2217 if (!ctl) {
2218 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2219 return -EINVAL;
2220 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002221 }
2222 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2223 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2224 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2225 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002226 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228 return -ENOSYS;
2229}
2230
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002231// note: this call is safe only if the stream_cb is
2232// removed first in close_output_stream (as is done now).
2233static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2234{
2235 if (!stream || !parms)
2236 return;
2237
2238 struct stream_out *out = (struct stream_out *)stream;
2239 struct audio_device *adev = out->dev;
2240
2241 card_status_t status;
2242 int card;
2243 if (parse_snd_card_status(parms, &card, &status) < 0)
2244 return;
2245
2246 pthread_mutex_lock(&adev->lock);
2247 bool valid_cb = (card == adev->snd_card);
2248 pthread_mutex_unlock(&adev->lock);
2249
2250 if (!valid_cb)
2251 return;
2252
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002253 lock_output_stream(out);
2254 if (out->card_status != status)
2255 out->card_status = status;
2256 pthread_mutex_unlock(&out->lock);
2257
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002258 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2259 use_case_table[out->usecase],
2260 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2261
2262 if (status == CARD_STATUS_OFFLINE)
2263 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002264
2265 return;
2266}
2267
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002268#ifdef NO_AUDIO_OUT
2269static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002270 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002271{
2272 struct stream_out *out = (struct stream_out *)stream;
2273
2274 /* No Output device supported other than BT for playback.
2275 * Sleep for the amount of buffer duration
2276 */
Eric Laurenta1478072015-09-21 17:21:52 -07002277 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002278 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2279 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002280 out_get_sample_rate(&out->stream.common));
2281 pthread_mutex_unlock(&out->lock);
2282 return bytes;
2283}
2284#endif
2285
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2287 size_t bytes)
2288{
2289 struct stream_out *out = (struct stream_out *)stream;
2290 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002291 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002292 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002293
Eric Laurenta1478072015-09-21 17:21:52 -07002294 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002295 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2296 error_code = ERROR_CODE_WRITE;
2297 goto exit;
2298 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002299 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002300 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002301 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002302 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002303 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002304 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002306 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002307 goto exit;
2308 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002309
2310 if (last_known_cal_step != -1) {
2311 ALOGD("%s: retry previous failed cal level set", __func__);
2312 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2313 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002315
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002316 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002317 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002318 if (out->send_new_metadata) {
2319 ALOGVV("send new gapless metadata");
2320 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2321 out->send_new_metadata = 0;
2322 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002323 unsigned int avail;
2324 struct timespec tstamp;
2325 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2326 /* Do not limit write size if the available frames count is unknown */
2327 if (ret != 0) {
2328 avail = bytes;
2329 }
2330 if (avail == 0) {
2331 ret = 0;
2332 } else {
2333 if (avail > bytes) {
2334 avail = bytes;
2335 }
2336 ret = compress_write(out->compr, buffer, avail);
2337 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2338 __func__, avail, ret);
2339 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002340
Eric Laurent6e895242013-09-05 16:10:57 -07002341 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002342 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2343 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002344 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002345 compress_start(out->compr);
2346 out->playback_started = 1;
2347 out->offload_state = OFFLOAD_STATE_PLAYING;
2348 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002349 if (ret < 0) {
2350 log_error_l(&out->error_log, ERROR_CODE_WRITE);
2351 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002352 pthread_mutex_unlock(&out->lock);
2353 return ret;
2354 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002355 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002356 if (out->pcm) {
2357 if (out->muted)
2358 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002359
Eric Laurent0e46adf2016-12-16 12:49:24 -08002360 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002361
Haynes Mathew George03c40102016-01-29 17:57:48 -08002362 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2363 out->config.rate;
2364 request_out_focus(out, ns);
2365
2366 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2367 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002368 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002369 else
2370 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002371
Haynes Mathew George03c40102016-01-29 17:57:48 -08002372 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002373 } else {
2374 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002375 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376 }
2377
2378exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002379 // For PCM we always consume the buffer and return #bytes regardless of ret.
2380 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2381 out->written += bytes / (out->config.channels * sizeof(short));
2382 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002383 long long sleeptime_us = 0;
2384 if (ret != 0) {
2385 log_error_l(&out->error_log, error_code);
2386 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2387 ALOGE_IF(out->pcm != NULL,
2388 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
2389 sleeptime_us = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2390 out_get_sample_rate(&out->stream.common);
2391 // usleep not guaranteed for values over 1 second but we don't limit here.
2392 }
2393 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002394
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002395 pthread_mutex_unlock(&out->lock);
2396
2397 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002398 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002399 if (sleeptime_us != 0)
2400 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002401 }
2402 return bytes;
2403}
2404
2405static int out_get_render_position(const struct audio_stream_out *stream,
2406 uint32_t *dsp_frames)
2407{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002408 struct stream_out *out = (struct stream_out *)stream;
2409 *dsp_frames = 0;
2410 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002411 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002412 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002413 unsigned long frames = 0;
2414 // TODO: check return value
2415 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2416 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002417 ALOGVV("%s rendered frames %d sample_rate %d",
2418 __func__, *dsp_frames, out->sample_rate);
2419 }
2420 pthread_mutex_unlock(&out->lock);
2421 return 0;
2422 } else
2423 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002424}
2425
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002426static int out_add_audio_effect(const struct audio_stream *stream __unused,
2427 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002428{
2429 return 0;
2430}
2431
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002432static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2433 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002434{
2435 return 0;
2436}
2437
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002438static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2439 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440{
2441 return -EINVAL;
2442}
2443
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002444static int out_get_presentation_position(const struct audio_stream_out *stream,
2445 uint64_t *frames, struct timespec *timestamp)
2446{
2447 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002448 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002449 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002450
Eric Laurenta1478072015-09-21 17:21:52 -07002451 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002452
Eric Laurent949a0892013-09-20 09:20:13 -07002453 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2454 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002455 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002456 compress_get_tstamp(out->compr, &dsp_frames,
2457 &out->sample_rate);
2458 ALOGVV("%s rendered frames %ld sample_rate %d",
2459 __func__, dsp_frames, out->sample_rate);
2460 *frames = dsp_frames;
2461 ret = 0;
2462 /* this is the best we can do */
2463 clock_gettime(CLOCK_MONOTONIC, timestamp);
2464 }
2465 } else {
2466 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002467 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002468 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2469 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002470 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002471 // This adjustment accounts for buffering after app processor.
2472 // It is based on estimated DSP latency per use case, rather than exact.
2473 signed_frames -=
2474 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2475
Eric Laurent949a0892013-09-20 09:20:13 -07002476 // It would be unusual for this value to be negative, but check just in case ...
2477 if (signed_frames >= 0) {
2478 *frames = signed_frames;
2479 ret = 0;
2480 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002481 }
2482 }
2483 }
2484
2485 pthread_mutex_unlock(&out->lock);
2486
2487 return ret;
2488}
2489
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002490static int out_set_callback(struct audio_stream_out *stream,
2491 stream_callback_t callback, void *cookie)
2492{
2493 struct stream_out *out = (struct stream_out *)stream;
2494
2495 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002496 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002497 out->offload_callback = callback;
2498 out->offload_cookie = cookie;
2499 pthread_mutex_unlock(&out->lock);
2500 return 0;
2501}
2502
2503static int out_pause(struct audio_stream_out* stream)
2504{
2505 struct stream_out *out = (struct stream_out *)stream;
2506 int status = -ENOSYS;
2507 ALOGV("%s", __func__);
2508 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002509 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002510 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2511 status = compress_pause(out->compr);
2512 out->offload_state = OFFLOAD_STATE_PAUSED;
2513 }
2514 pthread_mutex_unlock(&out->lock);
2515 }
2516 return status;
2517}
2518
2519static int out_resume(struct audio_stream_out* stream)
2520{
2521 struct stream_out *out = (struct stream_out *)stream;
2522 int status = -ENOSYS;
2523 ALOGV("%s", __func__);
2524 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2525 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002526 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002527 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2528 status = compress_resume(out->compr);
2529 out->offload_state = OFFLOAD_STATE_PLAYING;
2530 }
2531 pthread_mutex_unlock(&out->lock);
2532 }
2533 return status;
2534}
2535
2536static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2537{
2538 struct stream_out *out = (struct stream_out *)stream;
2539 int status = -ENOSYS;
2540 ALOGV("%s", __func__);
2541 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002542 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002543 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2544 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2545 else
2546 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2547 pthread_mutex_unlock(&out->lock);
2548 }
2549 return status;
2550}
2551
2552static int out_flush(struct audio_stream_out* stream)
2553{
2554 struct stream_out *out = (struct stream_out *)stream;
2555 ALOGV("%s", __func__);
2556 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002557 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002558 stop_compressed_output_l(out);
2559 pthread_mutex_unlock(&out->lock);
2560 return 0;
2561 }
2562 return -ENOSYS;
2563}
2564
Eric Laurent0e46adf2016-12-16 12:49:24 -08002565static int out_stop(const struct audio_stream_out* stream)
2566{
2567 struct stream_out *out = (struct stream_out *)stream;
2568 struct audio_device *adev = out->dev;
2569 int ret = -ENOSYS;
2570
2571 ALOGV("%s", __func__);
2572 pthread_mutex_lock(&adev->lock);
2573 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2574 out->playback_started && out->pcm != NULL) {
2575 pcm_stop(out->pcm);
2576 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002577 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002578 }
2579 pthread_mutex_unlock(&adev->lock);
2580 return ret;
2581}
2582
2583static int out_start(const struct audio_stream_out* stream)
2584{
2585 struct stream_out *out = (struct stream_out *)stream;
2586 struct audio_device *adev = out->dev;
2587 int ret = -ENOSYS;
2588
2589 ALOGV("%s", __func__);
2590 pthread_mutex_lock(&adev->lock);
2591 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2592 !out->playback_started && out->pcm != NULL) {
2593 ret = start_output_stream(out);
2594 if (ret == 0) {
2595 out->playback_started = true;
2596 }
2597 }
2598 pthread_mutex_unlock(&adev->lock);
2599 return ret;
2600}
2601
Phil Burkbc991042017-02-24 08:06:44 -08002602/*
2603 * Modify config->period_count based on min_size_frames
2604 */
2605static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2606{
2607 int periodCountRequested = (min_size_frames + config->period_size - 1)
2608 / config->period_size;
2609 int periodCount = MMAP_PERIOD_COUNT_MIN;
2610
2611 ALOGV("%s original config.period_size = %d config.period_count = %d",
2612 __func__, config->period_size, config->period_count);
2613
2614 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2615 periodCount *= 2;
2616 }
2617 config->period_count = periodCount;
2618
2619 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2620}
2621
Eric Laurent0e46adf2016-12-16 12:49:24 -08002622static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2623 int32_t min_size_frames,
2624 struct audio_mmap_buffer_info *info)
2625{
2626 struct stream_out *out = (struct stream_out *)stream;
2627 struct audio_device *adev = out->dev;
2628 int ret = 0;
2629 unsigned int offset1;
2630 unsigned int frames1;
2631 const char *step = "";
2632
2633 ALOGV("%s", __func__);
2634 pthread_mutex_lock(&adev->lock);
2635
2636 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002637 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002638 ret = -EINVAL;
2639 goto exit;
2640 }
2641 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002642 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002643 ret = -ENOSYS;
2644 goto exit;
2645 }
2646 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2647 if (out->pcm_device_id < 0) {
2648 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2649 __func__, out->pcm_device_id, out->usecase);
2650 ret = -EINVAL;
2651 goto exit;
2652 }
Phil Burkbc991042017-02-24 08:06:44 -08002653
2654 adjust_mmap_period_count(&out->config, min_size_frames);
2655
Eric Laurent0e46adf2016-12-16 12:49:24 -08002656 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2657 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2658 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2659 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2660 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2661 step = "open";
2662 ret = -ENODEV;
2663 goto exit;
2664 }
2665 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2666 if (ret < 0) {
2667 step = "begin";
2668 goto exit;
2669 }
2670 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2671 info->burst_size_frames = out->config.period_size;
2672 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2673
2674 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2675 info->buffer_size_frames));
2676
2677 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2678 if (ret < 0) {
2679 step = "commit";
2680 goto exit;
2681 }
Phil Burkbc991042017-02-24 08:06:44 -08002682
2683 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002684 ret = 0;
2685
2686 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2687 __func__, info->shared_memory_address, info->buffer_size_frames);
2688
2689exit:
2690 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002691 if (out->pcm == NULL) {
2692 ALOGE("%s: %s - %d", __func__, step, ret);
2693 } else {
2694 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002695 pcm_close(out->pcm);
2696 out->pcm = NULL;
2697 }
2698 }
2699 pthread_mutex_unlock(&adev->lock);
2700 return ret;
2701}
2702
2703static int out_get_mmap_position(const struct audio_stream_out *stream,
2704 struct audio_mmap_position *position)
2705{
2706 struct stream_out *out = (struct stream_out *)stream;
2707 ALOGVV("%s", __func__);
2708 if (position == NULL) {
2709 return -EINVAL;
2710 }
2711 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2712 return -ENOSYS;
2713 }
2714 if (out->pcm == NULL) {
2715 return -ENOSYS;
2716 }
2717
2718 struct timespec ts = { 0, 0 };
2719 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2720 if (ret < 0) {
2721 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2722 return ret;
2723 }
2724 position->time_nanoseconds = ts2ns(&ts);
2725 return 0;
2726}
2727
2728
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729/** audio_stream_in implementation **/
2730static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2731{
2732 struct stream_in *in = (struct stream_in *)stream;
2733
2734 return in->config.rate;
2735}
2736
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002737static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738{
2739 return -ENOSYS;
2740}
2741
2742static size_t in_get_buffer_size(const struct audio_stream *stream)
2743{
2744 struct stream_in *in = (struct stream_in *)stream;
2745
Haynes Mathew George03c40102016-01-29 17:57:48 -08002746 return in->config.period_size * in->af_period_multiplier *
2747 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748}
2749
2750static uint32_t in_get_channels(const struct audio_stream *stream)
2751{
2752 struct stream_in *in = (struct stream_in *)stream;
2753
2754 return in->channel_mask;
2755}
2756
vivek mehta4ed66e62016-04-15 23:33:34 -07002757static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758{
vivek mehta4ed66e62016-04-15 23:33:34 -07002759 struct stream_in *in = (struct stream_in *)stream;
2760 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761}
2762
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002763static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764{
2765 return -ENOSYS;
2766}
2767
2768static int in_standby(struct audio_stream *stream)
2769{
2770 struct stream_in *in = (struct stream_in *)stream;
2771 struct audio_device *adev = in->dev;
2772 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002773 bool do_stop = true;
2774
Eric Laurent994a6932013-07-17 11:51:42 -07002775 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002776
2777 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002778
2779 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002780 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002781 audio_extn_sound_trigger_stop_lab(in);
2782 in->standby = true;
2783 }
2784
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002785 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002786 if (adev->adm_deregister_stream)
2787 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2788
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002789 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002790 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002791 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002792 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002793 in->capture_started = false;
2794 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002795 if (in->pcm) {
2796 pcm_close(in->pcm);
2797 in->pcm = NULL;
2798 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002799 adev->enable_voicerx = false;
2800 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002801 if (do_stop) {
2802 status = stop_input_stream(in);
2803 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002804 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002805 }
2806 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002807 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808 return status;
2809}
2810
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002811static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812{
2813 return 0;
2814}
2815
2816static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2817{
2818 struct stream_in *in = (struct stream_in *)stream;
2819 struct audio_device *adev = in->dev;
2820 struct str_parms *parms;
2821 char *str;
2822 char value[32];
2823 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002824 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825
Eric Laurent994a6932013-07-17 11:51:42 -07002826 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827 parms = str_parms_create_str(kvpairs);
2828
2829 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2830
Eric Laurenta1478072015-09-21 17:21:52 -07002831 lock_input_stream(in);
2832
Eric Laurent150dbfe2013-02-27 14:31:02 -08002833 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834 if (ret >= 0) {
2835 val = atoi(value);
2836 /* no audio source uses val == 0 */
2837 if ((in->source != val) && (val != 0)) {
2838 in->source = val;
2839 }
2840 }
2841
2842 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002844 if (ret >= 0) {
2845 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002846 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847 in->device = val;
2848 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002849 if (!in->standby) {
2850 ALOGV("update input routing change");
2851 in->routing_change = true;
2852 select_devices(adev, in->usecase);
2853 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002854 }
2855 }
2856
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002858 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002859
2860 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002861 ALOGV("%s: exit: status(%d)", __func__, status);
2862 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863}
2864
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002865static char* in_get_parameters(const struct audio_stream *stream __unused,
2866 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002867{
2868 return strdup("");
2869}
2870
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002871static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002872{
2873 return 0;
2874}
2875
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002876static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2877{
2878 if (!stream || !parms)
2879 return;
2880
2881 struct stream_in *in = (struct stream_in *)stream;
2882 struct audio_device *adev = in->dev;
2883
2884 card_status_t status;
2885 int card;
2886 if (parse_snd_card_status(parms, &card, &status) < 0)
2887 return;
2888
2889 pthread_mutex_lock(&adev->lock);
2890 bool valid_cb = (card == adev->snd_card);
2891 pthread_mutex_unlock(&adev->lock);
2892
2893 if (!valid_cb)
2894 return;
2895
2896 lock_input_stream(in);
2897 if (in->card_status != status)
2898 in->card_status = status;
2899 pthread_mutex_unlock(&in->lock);
2900
2901 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2902 use_case_table[in->usecase],
2903 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2904
2905 // a better solution would be to report error back to AF and let
2906 // it put the stream to standby
2907 if (status == CARD_STATUS_OFFLINE)
2908 in_standby(&in->stream.common);
2909
2910 return;
2911}
2912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002913static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2914 size_t bytes)
2915{
2916 struct stream_in *in = (struct stream_in *)stream;
2917 struct audio_device *adev = in->dev;
2918 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002919 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002920
Eric Laurenta1478072015-09-21 17:21:52 -07002921 lock_input_stream(in);
2922
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002923 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002924 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002925 /* Read from sound trigger HAL */
2926 audio_extn_sound_trigger_read(in, buffer, bytes);
2927 pthread_mutex_unlock(&in->lock);
2928 return bytes;
2929 }
2930
Eric Laurent0e46adf2016-12-16 12:49:24 -08002931 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
2932 ret = -ENOSYS;
2933 goto exit;
2934 }
2935
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002936 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002937 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002939 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002940 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002941 goto exit;
2942 }
2943 in->standby = 0;
2944 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002945
Haynes Mathew George03c40102016-01-29 17:57:48 -08002946 //what's the duration requested by the client?
2947 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2948 in->config.rate;
2949 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002950
Haynes Mathew George03c40102016-01-29 17:57:48 -08002951 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002952 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002953 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002954 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002955 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002956 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002957 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002958 if (ret < 0) {
2959 ALOGE("Failed to read w/err %s", strerror(errno));
2960 ret = -errno;
2961 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002962 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2963 if (bytes % 4 == 0) {
2964 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2965 int_buf_stream = buffer;
2966 for (size_t itt=0; itt < bytes/4 ; itt++) {
2967 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002968 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002969 } else {
2970 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2971 ret = -EINVAL;
2972 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002973 }
2974 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002975 }
2976
Haynes Mathew George03c40102016-01-29 17:57:48 -08002977 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002978
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002979 /*
2980 * Instead of writing zeroes here, we could trust the hardware
2981 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002982 * 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 -08002983 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002984 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985 memset(buffer, 0, bytes);
2986
2987exit:
2988 pthread_mutex_unlock(&in->lock);
2989
2990 if (ret != 0) {
2991 in_standby(&in->stream.common);
2992 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002993 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002995 memset(buffer, 0, bytes); // clear return data
2996 }
2997 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002998 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999 }
3000 return bytes;
3001}
3002
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003003static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003004{
3005 return 0;
3006}
3007
Andy Hung6ebe5962016-01-15 17:46:57 -08003008static int in_get_capture_position(const struct audio_stream_in *stream,
3009 int64_t *frames, int64_t *time)
3010{
3011 if (stream == NULL || frames == NULL || time == NULL) {
3012 return -EINVAL;
3013 }
3014 struct stream_in *in = (struct stream_in *)stream;
3015 int ret = -ENOSYS;
3016
3017 lock_input_stream(in);
3018 if (in->pcm) {
3019 struct timespec timestamp;
3020 unsigned int avail;
3021 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3022 *frames = in->frames_read + avail;
3023 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3024 ret = 0;
3025 }
3026 }
3027 pthread_mutex_unlock(&in->lock);
3028 return ret;
3029}
3030
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003031static int add_remove_audio_effect(const struct audio_stream *stream,
3032 effect_handle_t effect,
3033 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003035 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003036 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003037 int status = 0;
3038 effect_descriptor_t desc;
3039
3040 status = (*effect)->get_descriptor(effect, &desc);
3041 if (status != 0)
3042 return status;
3043
Eric Laurenta1478072015-09-21 17:21:52 -07003044 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003045 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003046 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003047 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003048 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003049 in->enable_aec != enable &&
3050 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3051 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003052 if (!enable)
3053 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003054 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3055 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3056 adev->enable_voicerx = enable;
3057 struct audio_usecase *usecase;
3058 struct listnode *node;
3059 list_for_each(node, &adev->usecase_list) {
3060 usecase = node_to_item(node, struct audio_usecase, list);
3061 if (usecase->type == PCM_PLAYBACK) {
3062 select_devices(adev, usecase->id);
3063 break;
3064 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003065 }
3066 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003067 if (!in->standby)
3068 select_devices(in->dev, in->usecase);
3069 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003070 if (in->enable_ns != enable &&
3071 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3072 in->enable_ns = enable;
3073 if (!in->standby)
3074 select_devices(in->dev, in->usecase);
3075 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003076 pthread_mutex_unlock(&in->dev->lock);
3077 pthread_mutex_unlock(&in->lock);
3078
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079 return 0;
3080}
3081
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003082static int in_add_audio_effect(const struct audio_stream *stream,
3083 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084{
Eric Laurent994a6932013-07-17 11:51:42 -07003085 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003086 return add_remove_audio_effect(stream, effect, true);
3087}
3088
3089static int in_remove_audio_effect(const struct audio_stream *stream,
3090 effect_handle_t effect)
3091{
Eric Laurent994a6932013-07-17 11:51:42 -07003092 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003093 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003094}
3095
Eric Laurent0e46adf2016-12-16 12:49:24 -08003096static int in_stop(const struct audio_stream_in* stream)
3097{
3098 struct stream_in *in = (struct stream_in *)stream;
3099 struct audio_device *adev = in->dev;
3100
3101 int ret = -ENOSYS;
3102 ALOGV("%s", __func__);
3103 pthread_mutex_lock(&adev->lock);
3104 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3105 in->capture_started && in->pcm != NULL) {
3106 pcm_stop(in->pcm);
3107 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003108 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003109 }
3110 pthread_mutex_unlock(&adev->lock);
3111 return ret;
3112}
3113
3114static int in_start(const struct audio_stream_in* stream)
3115{
3116 struct stream_in *in = (struct stream_in *)stream;
3117 struct audio_device *adev = in->dev;
3118 int ret = -ENOSYS;
3119
3120 ALOGV("%s in %p", __func__, in);
3121 pthread_mutex_lock(&adev->lock);
3122 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3123 !in->capture_started && in->pcm != NULL) {
3124 if (!in->capture_started) {
3125 ret = start_input_stream(in);
3126 if (ret == 0) {
3127 in->capture_started = true;
3128 }
3129 }
3130 }
3131 pthread_mutex_unlock(&adev->lock);
3132 return ret;
3133}
3134
3135static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3136 int32_t min_size_frames,
3137 struct audio_mmap_buffer_info *info)
3138{
3139 struct stream_in *in = (struct stream_in *)stream;
3140 struct audio_device *adev = in->dev;
3141 int ret = 0;
3142 unsigned int offset1;
3143 unsigned int frames1;
3144 const char *step = "";
3145
3146 pthread_mutex_lock(&adev->lock);
3147 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003148
Eric Laurent0e46adf2016-12-16 12:49:24 -08003149 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003150 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003151 ret = -EINVAL;
3152 goto exit;
3153 }
3154 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003155 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003156 ALOGV("%s in %p", __func__, in);
3157 ret = -ENOSYS;
3158 goto exit;
3159 }
3160 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3161 if (in->pcm_device_id < 0) {
3162 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3163 __func__, in->pcm_device_id, in->usecase);
3164 ret = -EINVAL;
3165 goto exit;
3166 }
Phil Burkbc991042017-02-24 08:06:44 -08003167
3168 adjust_mmap_period_count(&in->config, min_size_frames);
3169
Eric Laurent0e46adf2016-12-16 12:49:24 -08003170 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3171 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3172 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3173 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3174 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3175 step = "open";
3176 ret = -ENODEV;
3177 goto exit;
3178 }
3179
3180 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3181 if (ret < 0) {
3182 step = "begin";
3183 goto exit;
3184 }
3185 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3186 info->burst_size_frames = in->config.period_size;
3187 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3188
3189 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3190 info->buffer_size_frames));
3191
3192 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3193 if (ret < 0) {
3194 step = "commit";
3195 goto exit;
3196 }
3197
Phil Burkbc991042017-02-24 08:06:44 -08003198 in->standby = false;
3199 ret = 0;
3200
Eric Laurent0e46adf2016-12-16 12:49:24 -08003201 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3202 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003203
3204exit:
3205 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003206 if (in->pcm == NULL) {
3207 ALOGE("%s: %s - %d", __func__, step, ret);
3208 } else {
3209 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003210 pcm_close(in->pcm);
3211 in->pcm = NULL;
3212 }
3213 }
3214 pthread_mutex_unlock(&adev->lock);
3215 return ret;
3216}
3217
3218static int in_get_mmap_position(const struct audio_stream_in *stream,
3219 struct audio_mmap_position *position)
3220{
3221 struct stream_in *in = (struct stream_in *)stream;
3222 ALOGVV("%s", __func__);
3223 if (position == NULL) {
3224 return -EINVAL;
3225 }
3226 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3227 return -ENOSYS;
3228 }
3229 if (in->pcm == NULL) {
3230 return -ENOSYS;
3231 }
3232 struct timespec ts = { 0, 0 };
3233 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3234 if (ret < 0) {
3235 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3236 return ret;
3237 }
3238 position->time_nanoseconds = ts2ns(&ts);
3239 return 0;
3240}
3241
3242
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003243static int adev_open_output_stream(struct audio_hw_device *dev,
3244 audio_io_handle_t handle,
3245 audio_devices_t devices,
3246 audio_output_flags_t flags,
3247 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003248 struct audio_stream_out **stream_out,
3249 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250{
3251 struct audio_device *adev = (struct audio_device *)dev;
3252 struct stream_out *out;
3253 int i, ret;
3254
Eric Laurent994a6932013-07-17 11:51:42 -07003255 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256 __func__, config->sample_rate, config->channel_mask, devices, flags);
3257 *stream_out = NULL;
3258 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3259
3260 if (devices == AUDIO_DEVICE_NONE)
3261 devices = AUDIO_DEVICE_OUT_SPEAKER;
3262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263 out->flags = flags;
3264 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003265 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003266 out->format = config->format;
3267 out->sample_rate = config->sample_rate;
3268 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3269 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003270 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271
3272 /* Init use case and pcm_config */
3273 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07003274 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003276 pthread_mutex_lock(&adev->lock);
3277 ret = read_hdmi_channel_masks(out);
3278 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003279 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003280 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003281
3282 if (config->sample_rate == 0)
3283 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3284 if (config->channel_mask == 0)
3285 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08003286 if (config->format == AUDIO_FORMAT_DEFAULT)
3287 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003288
3289 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003290 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08003291 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3293 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003294 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003295 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003297 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003298 pthread_mutex_lock(&adev->lock);
3299 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3300 pthread_mutex_unlock(&adev->lock);
3301
3302 // reject offload during card offline to allow
3303 // fallback to s/w paths
3304 if (offline) {
3305 ret = -ENODEV;
3306 goto error_open;
3307 }
3308
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003309 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3310 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3311 ALOGE("%s: Unsupported Offload information", __func__);
3312 ret = -EINVAL;
3313 goto error_open;
3314 }
3315 if (!is_supported_format(config->offload_info.format)) {
3316 ALOGE("%s: Unsupported audio format", __func__);
3317 ret = -EINVAL;
3318 goto error_open;
3319 }
3320
3321 out->compr_config.codec = (struct snd_codec *)
3322 calloc(1, sizeof(struct snd_codec));
3323
3324 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3325 if (config->offload_info.channel_mask)
3326 out->channel_mask = config->offload_info.channel_mask;
3327 else if (config->channel_mask)
3328 out->channel_mask = config->channel_mask;
3329 out->format = config->offload_info.format;
3330 out->sample_rate = config->offload_info.sample_rate;
3331
3332 out->stream.set_callback = out_set_callback;
3333 out->stream.pause = out_pause;
3334 out->stream.resume = out_resume;
3335 out->stream.drain = out_drain;
3336 out->stream.flush = out_flush;
3337
3338 out->compr_config.codec->id =
3339 get_snd_codec_id(config->offload_info.format);
3340 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3341 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003342 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003343 out->compr_config.codec->bit_rate =
3344 config->offload_info.bit_rate;
3345 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003346 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003347 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3348
3349 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3350 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003351
3352 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003353 create_offload_callback_thread(out);
3354 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3355 __func__, config->offload_info.version,
3356 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003357 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3358 if (config->sample_rate == 0)
3359 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3360 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3361 config->sample_rate != 8000) {
3362 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3363 ret = -EINVAL;
3364 goto error_open;
3365 }
3366 out->sample_rate = config->sample_rate;
3367 out->config.rate = config->sample_rate;
3368 if (config->format == AUDIO_FORMAT_DEFAULT)
3369 config->format = AUDIO_FORMAT_PCM_16_BIT;
3370 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3371 config->format = AUDIO_FORMAT_PCM_16_BIT;
3372 ret = -EINVAL;
3373 goto error_open;
3374 }
3375 out->format = config->format;
3376 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3377 out->config = pcm_config_afe_proxy_playback;
3378 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003380 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3381 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3382 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003383 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3384 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3385 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003386 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3387 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003388 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003389 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003390 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3391 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3392 out->config = pcm_config_mmap_playback;
3393 out->stream.start = out_start;
3394 out->stream.stop = out_stop;
3395 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3396 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003397 } else {
3398 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3399 out->config = pcm_config_low_latency;
3400 }
3401 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3402 if (k_enable_extended_precision
3403 && pcm_params_format_test(adev->use_case_table[out->usecase],
3404 pcm_format_from_audio_format(config->format))) {
3405 out->config.format = pcm_format_from_audio_format(config->format);
3406 /* out->format already set to config->format */
3407 } else {
3408 /* deny the externally proposed config format
3409 * and use the one specified in audio_hw layer configuration.
3410 * Note: out->format is returned by out->stream.common.get_format()
3411 * and is used to set config->format in the code several lines below.
3412 */
3413 out->format = audio_format_from_pcm_format(out->config.format);
3414 }
3415 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003416 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003418 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3419 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003421 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003422 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003423 adev->primary_output = out;
3424 else {
3425 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003426 ret = -EEXIST;
3427 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003428 }
3429 }
3430
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431 /* Check if this usecase is already existing */
3432 pthread_mutex_lock(&adev->lock);
3433 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3434 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003436 ret = -EEXIST;
3437 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438 }
3439 pthread_mutex_unlock(&adev->lock);
3440
3441 out->stream.common.get_sample_rate = out_get_sample_rate;
3442 out->stream.common.set_sample_rate = out_set_sample_rate;
3443 out->stream.common.get_buffer_size = out_get_buffer_size;
3444 out->stream.common.get_channels = out_get_channels;
3445 out->stream.common.get_format = out_get_format;
3446 out->stream.common.set_format = out_set_format;
3447 out->stream.common.standby = out_standby;
3448 out->stream.common.dump = out_dump;
3449 out->stream.common.set_parameters = out_set_parameters;
3450 out->stream.common.get_parameters = out_get_parameters;
3451 out->stream.common.add_audio_effect = out_add_audio_effect;
3452 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3453 out->stream.get_latency = out_get_latency;
3454 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003455#ifdef NO_AUDIO_OUT
3456 out->stream.write = out_write_for_no_output;
3457#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003458 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003459#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460 out->stream.get_render_position = out_get_render_position;
3461 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003462 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463
Eric Laurent0e46adf2016-12-16 12:49:24 -08003464 if (out->realtime)
3465 out->af_period_multiplier = af_period_multiplier;
3466 else
3467 out->af_period_multiplier = 1;
3468
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003470 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003471 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003473 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003474 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003475 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477 config->format = out->stream.common.get_format(&out->stream.common);
3478 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3479 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3480
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003481
3482 /*
3483 By locking output stream before registering, we allow the callback
3484 to update stream's state only after stream's initial state is set to
3485 adev state.
3486 */
3487 lock_output_stream(out);
3488 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3489 pthread_mutex_lock(&adev->lock);
3490 out->card_status = adev->card_status;
3491 pthread_mutex_unlock(&adev->lock);
3492 pthread_mutex_unlock(&out->lock);
3493
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003495
Eric Laurent994a6932013-07-17 11:51:42 -07003496 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003498
3499error_open:
3500 free(out);
3501 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003502 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003503 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504}
3505
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003506static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507 struct audio_stream_out *stream)
3508{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003509 struct stream_out *out = (struct stream_out *)stream;
3510 struct audio_device *adev = out->dev;
3511
Eric Laurent994a6932013-07-17 11:51:42 -07003512 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003513
3514 // must deregister from sndmonitor first to prevent races
3515 // between the callback and close_stream
3516 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003518 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3519 destroy_offload_callback_thread(out);
3520
3521 if (out->compr_config.codec != NULL)
3522 free(out->compr_config.codec);
3523 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003524
3525 if (adev->voice_tx_output == out)
3526 adev->voice_tx_output = NULL;
3527
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003528 pthread_cond_destroy(&out->cond);
3529 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003531 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003532}
3533
3534static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3535{
3536 struct audio_device *adev = (struct audio_device *)dev;
3537 struct str_parms *parms;
3538 char *str;
3539 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003540 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003541 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003542 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003543
Joe Onorato188b6222016-03-01 11:02:27 -08003544 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003545
3546 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547
3548 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003549 status = voice_set_parameters(adev, parms);
3550 if (status != 0) {
3551 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003552 }
3553
3554 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3555 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003556 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3558 adev->bluetooth_nrec = true;
3559 else
3560 adev->bluetooth_nrec = false;
3561 }
3562
3563 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3564 if (ret >= 0) {
3565 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3566 adev->screen_off = false;
3567 else
3568 adev->screen_off = true;
3569 }
3570
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003571 ret = str_parms_get_int(parms, "rotation", &val);
3572 if (ret >= 0) {
3573 bool reverse_speakers = false;
3574 switch(val) {
3575 // FIXME: note that the code below assumes that the speakers are in the correct placement
3576 // relative to the user when the device is rotated 90deg from its default rotation. This
3577 // assumption is device-specific, not platform-specific like this code.
3578 case 270:
3579 reverse_speakers = true;
3580 break;
3581 case 0:
3582 case 90:
3583 case 180:
3584 break;
3585 default:
3586 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003587 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003588 }
Eric Laurent03f09432014-03-25 18:09:11 -07003589 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003590 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003591 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003592 }
3593
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003594 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3595 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003596 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003597 }
3598
David Lin8c03e672017-02-06 20:31:38 -08003599 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3600 if (ret >= 0) {
3601 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3602 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3603 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3604 if (ret >= 0) {
3605 const int card = atoi(value);
3606 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3607 }
3608 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3609 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3610 if (ret >= 0) {
3611 const int card = atoi(value);
3612 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3613 }
3614 }
3615 }
3616
3617 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3618 if (ret >= 0) {
3619 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3620 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3621 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3622 if (ret >= 0) {
3623 const int card = atoi(value);
3624
3625 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3626 }
3627 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3628 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3629 if (ret >= 0) {
3630 const int card = atoi(value);
3631 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3632 }
3633 }
3634 }
3635
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003636 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003637done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003638 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003639 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003640 ALOGV("%s: exit with code(%d)", __func__, status);
3641 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642}
3643
3644static char* adev_get_parameters(const struct audio_hw_device *dev,
3645 const char *keys)
3646{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003647 struct audio_device *adev = (struct audio_device *)dev;
3648 struct str_parms *reply = str_parms_create();
3649 struct str_parms *query = str_parms_create_str(keys);
3650 char *str;
3651
3652 pthread_mutex_lock(&adev->lock);
3653
3654 voice_get_parameters(adev, query, reply);
3655 str = str_parms_to_str(reply);
3656 str_parms_destroy(query);
3657 str_parms_destroy(reply);
3658
3659 pthread_mutex_unlock(&adev->lock);
3660 ALOGV("%s: exit: returns - %s", __func__, str);
3661 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662}
3663
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003664static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003665{
3666 return 0;
3667}
3668
Haynes Mathew George5191a852013-09-11 14:19:36 -07003669static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3670{
3671 int ret;
3672 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003673
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003674 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3675
Haynes Mathew George5191a852013-09-11 14:19:36 -07003676 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003677 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003678 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003679
Haynes Mathew George5191a852013-09-11 14:19:36 -07003680 return ret;
3681}
3682
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003683static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684{
3685 return -ENOSYS;
3686}
3687
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003688static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3689 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690{
3691 return -ENOSYS;
3692}
3693
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003694static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003695{
3696 return -ENOSYS;
3697}
3698
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003699static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700{
3701 return -ENOSYS;
3702}
3703
3704static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3705{
3706 struct audio_device *adev = (struct audio_device *)dev;
3707
3708 pthread_mutex_lock(&adev->lock);
3709 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003710 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003712 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3713 voice_is_in_call(adev)) {
3714 voice_stop_call(adev);
3715 adev->current_call_output = NULL;
3716 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717 }
3718 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003719
3720 audio_extn_extspk_set_mode(adev->extspk, mode);
3721
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003722 return 0;
3723}
3724
3725static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3726{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003727 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003728 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729
Eric Laurent2bafff12016-03-17 12:17:23 -07003730 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003731 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003732 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3733 ret = audio_extn_hfp_set_mic_mute(adev, state);
3734 } else {
3735 ret = voice_set_mic_mute(adev, state);
3736 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003737 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003738 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003739
3740 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741}
3742
3743static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3744{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003745 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003746 return 0;
3747}
3748
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003749static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750 const struct audio_config *config)
3751{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003752 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003753
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003754 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3755 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756}
3757
3758static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003759 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760 audio_devices_t devices,
3761 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003762 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003763 audio_input_flags_t flags,
3764 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003765 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766{
3767 struct audio_device *adev = (struct audio_device *)dev;
3768 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003769 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003770 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003771 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772
Eric Laurent994a6932013-07-17 11:51:42 -07003773 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774 *stream_in = NULL;
3775 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3776 return -EINVAL;
3777
Zheng Zhang6185d572016-12-01 20:35:17 +08003778 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 -08003779 return -EINVAL;
3780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3782
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003783 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003784 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003785
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003786 in->stream.common.get_sample_rate = in_get_sample_rate;
3787 in->stream.common.set_sample_rate = in_set_sample_rate;
3788 in->stream.common.get_buffer_size = in_get_buffer_size;
3789 in->stream.common.get_channels = in_get_channels;
3790 in->stream.common.get_format = in_get_format;
3791 in->stream.common.set_format = in_set_format;
3792 in->stream.common.standby = in_standby;
3793 in->stream.common.dump = in_dump;
3794 in->stream.common.set_parameters = in_set_parameters;
3795 in->stream.common.get_parameters = in_get_parameters;
3796 in->stream.common.add_audio_effect = in_add_audio_effect;
3797 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3798 in->stream.set_gain = in_set_gain;
3799 in->stream.read = in_read;
3800 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003801 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802
3803 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003804 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806 in->standby = 1;
3807 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003808 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003809 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810
vivek mehta57ff9b52016-04-28 14:13:08 -07003811 // restrict 24 bit capture for unprocessed source only
3812 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3813 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003814 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003815 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3816 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3817 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3818 bool ret_error = false;
3819 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3820 from HAL is 8_24
3821 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3822 8_24 return error indicating supported format is 8_24
3823 *> In case of any other source requesting 24 bit or float return error
3824 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003825
vivek mehta57ff9b52016-04-28 14:13:08 -07003826 on error flinger will retry with supported format passed
3827 */
3828 if (source != AUDIO_SOURCE_UNPROCESSED) {
3829 config->format = AUDIO_FORMAT_PCM_16_BIT;
3830 ret_error = true;
3831 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3832 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3833 ret_error = true;
3834 }
3835
3836 if (ret_error) {
3837 ret = -EINVAL;
3838 goto err_open;
3839 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003840 }
3841
vivek mehta57ff9b52016-04-28 14:13:08 -07003842 in->format = config->format;
3843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003844 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003845 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3846 if (config->sample_rate == 0)
3847 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3848 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3849 config->sample_rate != 8000) {
3850 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3851 ret = -EINVAL;
3852 goto err_open;
3853 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003854
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003855 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3856 config->format = AUDIO_FORMAT_PCM_16_BIT;
3857 ret = -EINVAL;
3858 goto err_open;
3859 }
3860
3861 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3862 in->config = pcm_config_afe_proxy_record;
3863 } else {
3864 in->usecase = USECASE_AUDIO_RECORD;
3865 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08003866 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003867 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003868#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003869 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003870#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003871 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003872 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08003873 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003874 frame_size = audio_stream_in_frame_size(&in->stream);
3875 buffer_size = get_input_buffer_size(config->sample_rate,
3876 config->format,
3877 channel_count,
3878 is_low_latency);
3879 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003880 in->config.rate = config->sample_rate;
3881 in->af_period_multiplier = 1;
3882 } else {
3883 // period size is left untouched for rt mode playback
3884 in->config = pcm_config_audio_capture_rt;
3885 in->af_period_multiplier = af_period_multiplier;
3886 }
3887 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
3888 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
3889 in->usecase = USECASE_AUDIO_RECORD_MMAP;
3890 in->config = pcm_config_mmap_capture;
3891 in->stream.start = in_start;
3892 in->stream.stop = in_stop;
3893 in->stream.create_mmap_buffer = in_create_mmap_buffer;
3894 in->stream.get_mmap_position = in_get_mmap_position;
3895 in->af_period_multiplier = 1;
3896 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
3897 } else {
3898 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003899 frame_size = audio_stream_in_frame_size(&in->stream);
3900 buffer_size = get_input_buffer_size(config->sample_rate,
3901 config->format,
3902 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003903 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003904 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003905 in->config.rate = config->sample_rate;
3906 in->af_period_multiplier = 1;
3907 }
3908 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3909 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003910 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912 in->config.channels = channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003914 /* This stream could be for sound trigger lab,
3915 get sound trigger pcm if present */
3916 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003918 lock_input_stream(in);
3919 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3920 pthread_mutex_lock(&adev->lock);
3921 in->card_status = adev->card_status;
3922 pthread_mutex_unlock(&adev->lock);
3923 pthread_mutex_unlock(&in->lock);
3924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003925 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003926 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003927 return 0;
3928
3929err_open:
3930 free(in);
3931 *stream_in = NULL;
3932 return ret;
3933}
3934
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003935static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936 struct audio_stream_in *stream)
3937{
Eric Laurent994a6932013-07-17 11:51:42 -07003938 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003939
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003940 // must deregister from sndmonitor first to prevent races
3941 // between the callback and close_stream
3942 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003943 in_standby(&stream->common);
3944 free(stream);
3945
3946 return;
3947}
3948
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003949static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003950{
3951 return 0;
3952}
3953
Andy Hung31aca912014-03-20 17:14:59 -07003954/* verifies input and output devices and their capabilities.
3955 *
3956 * This verification is required when enabling extended bit-depth or
3957 * sampling rates, as not all qcom products support it.
3958 *
3959 * Suitable for calling only on initialization such as adev_open().
3960 * It fills the audio_device use_case_table[] array.
3961 *
3962 * Has a side-effect that it needs to configure audio routing / devices
3963 * in order to power up the devices and read the device parameters.
3964 * It does not acquire any hw device lock. Should restore the devices
3965 * back to "normal state" upon completion.
3966 */
3967static int adev_verify_devices(struct audio_device *adev)
3968{
3969 /* enumeration is a bit difficult because one really wants to pull
3970 * the use_case, device id, etc from the hidden pcm_device_table[].
3971 * In this case there are the following use cases and device ids.
3972 *
3973 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3974 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3975 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3976 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3977 * [USECASE_AUDIO_RECORD] = {0, 0},
3978 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3979 * [USECASE_VOICE_CALL] = {2, 2},
3980 *
3981 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3982 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3983 */
3984
3985 /* should be the usecases enabled in adev_open_input_stream() */
3986 static const int test_in_usecases[] = {
3987 USECASE_AUDIO_RECORD,
3988 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3989 };
3990 /* should be the usecases enabled in adev_open_output_stream()*/
3991 static const int test_out_usecases[] = {
3992 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3993 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3994 };
3995 static const usecase_type_t usecase_type_by_dir[] = {
3996 PCM_PLAYBACK,
3997 PCM_CAPTURE,
3998 };
3999 static const unsigned flags_by_dir[] = {
4000 PCM_OUT,
4001 PCM_IN,
4002 };
4003
4004 size_t i;
4005 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004006 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004007 char info[512]; /* for possible debug info */
4008
4009 for (dir = 0; dir < 2; ++dir) {
4010 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4011 const unsigned flags_dir = flags_by_dir[dir];
4012 const size_t testsize =
4013 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4014 const int *testcases =
4015 dir ? test_in_usecases : test_out_usecases;
4016 const audio_devices_t audio_device =
4017 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4018
4019 for (i = 0; i < testsize; ++i) {
4020 const audio_usecase_t audio_usecase = testcases[i];
4021 int device_id;
4022 snd_device_t snd_device;
4023 struct pcm_params **pparams;
4024 struct stream_out out;
4025 struct stream_in in;
4026 struct audio_usecase uc_info;
4027 int retval;
4028
4029 pparams = &adev->use_case_table[audio_usecase];
4030 pcm_params_free(*pparams); /* can accept null input */
4031 *pparams = NULL;
4032
4033 /* find the device ID for the use case (signed, for error) */
4034 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4035 if (device_id < 0)
4036 continue;
4037
4038 /* prepare structures for device probing */
4039 memset(&uc_info, 0, sizeof(uc_info));
4040 uc_info.id = audio_usecase;
4041 uc_info.type = usecase_type;
4042 if (dir) {
4043 adev->active_input = &in;
4044 memset(&in, 0, sizeof(in));
4045 in.device = audio_device;
4046 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4047 uc_info.stream.in = &in;
4048 } else {
4049 adev->active_input = NULL;
4050 }
4051 memset(&out, 0, sizeof(out));
4052 out.devices = audio_device; /* only field needed in select_devices */
4053 uc_info.stream.out = &out;
4054 uc_info.devices = audio_device;
4055 uc_info.in_snd_device = SND_DEVICE_NONE;
4056 uc_info.out_snd_device = SND_DEVICE_NONE;
4057 list_add_tail(&adev->usecase_list, &uc_info.list);
4058
4059 /* select device - similar to start_(in/out)put_stream() */
4060 retval = select_devices(adev, audio_usecase);
4061 if (retval >= 0) {
4062 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4063#if LOG_NDEBUG == 0
4064 if (*pparams) {
4065 ALOGV("%s: (%s) card %d device %d", __func__,
4066 dir ? "input" : "output", card_id, device_id);
4067 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004068 } else {
4069 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4070 }
4071#endif
4072 }
4073
4074 /* deselect device - similar to stop_(in/out)put_stream() */
4075 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004076 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004077 /* 2. Disable the rx device */
4078 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004079 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004080 list_remove(&uc_info.list);
4081 }
4082 }
4083 adev->active_input = NULL; /* restore adev state */
4084 return 0;
4085}
4086
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087static int adev_close(hw_device_t *device)
4088{
Andy Hung31aca912014-03-20 17:14:59 -07004089 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004090 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004091
4092 if (!adev)
4093 return 0;
4094
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004095 audio_extn_tfa_98xx_deinit();
4096
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004097 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004098 pthread_mutex_lock(&adev_init_lock);
4099
4100 if ((--audio_device_ref_count) == 0) {
4101 audio_route_free(adev->audio_route);
4102 free(adev->snd_dev_ref_cnt);
4103 platform_deinit(adev->platform);
4104 audio_extn_extspk_deinit(adev->extspk);
4105 audio_extn_sound_trigger_deinit(adev);
4106 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4107 pcm_params_free(adev->use_case_table[i]);
4108 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004109 if (adev->adm_deinit)
4110 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004111 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004112 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004113
4114 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004116 return 0;
4117}
4118
Glenn Kasten4f993392014-05-14 07:30:48 -07004119/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4120 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4121 * just that it _might_ work.
4122 */
4123static int period_size_is_plausible_for_low_latency(int period_size)
4124{
4125 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004126 case 48:
4127 case 96:
4128 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004129 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004130 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004131 case 240:
4132 case 320:
4133 case 480:
4134 return 1;
4135 default:
4136 return 0;
4137 }
4138}
4139
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004140static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4141{
4142 int card;
4143 card_status_t status;
4144
4145 if (!parms)
4146 return;
4147
4148 if (parse_snd_card_status(parms, &card, &status) < 0)
4149 return;
4150
4151 pthread_mutex_lock(&adev->lock);
4152 bool valid_cb = (card == adev->snd_card);
4153 if (valid_cb) {
4154 if (adev->card_status != status) {
4155 adev->card_status = status;
4156 platform_snd_card_update(adev->platform, status);
4157 }
4158 }
4159 pthread_mutex_unlock(&adev->lock);
4160 return;
4161}
4162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163static int adev_open(const hw_module_t *module, const char *name,
4164 hw_device_t **device)
4165{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004166 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167
Eric Laurent2bafff12016-03-17 12:17:23 -07004168 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004169 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004170 pthread_mutex_lock(&adev_init_lock);
4171 if (audio_device_ref_count != 0) {
4172 *device = &adev->device.common;
4173 audio_device_ref_count++;
4174 ALOGV("%s: returning existing instance of adev", __func__);
4175 ALOGV("%s: exit", __func__);
4176 pthread_mutex_unlock(&adev_init_lock);
4177 return 0;
4178 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004179 adev = calloc(1, sizeof(struct audio_device));
4180
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004181 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4182
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004183 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4184 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4185 adev->device.common.module = (struct hw_module_t *)module;
4186 adev->device.common.close = adev_close;
4187
4188 adev->device.init_check = adev_init_check;
4189 adev->device.set_voice_volume = adev_set_voice_volume;
4190 adev->device.set_master_volume = adev_set_master_volume;
4191 adev->device.get_master_volume = adev_get_master_volume;
4192 adev->device.set_master_mute = adev_set_master_mute;
4193 adev->device.get_master_mute = adev_get_master_mute;
4194 adev->device.set_mode = adev_set_mode;
4195 adev->device.set_mic_mute = adev_set_mic_mute;
4196 adev->device.get_mic_mute = adev_get_mic_mute;
4197 adev->device.set_parameters = adev_set_parameters;
4198 adev->device.get_parameters = adev_get_parameters;
4199 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4200 adev->device.open_output_stream = adev_open_output_stream;
4201 adev->device.close_output_stream = adev_close_output_stream;
4202 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004204 adev->device.close_input_stream = adev_close_input_stream;
4205 adev->device.dump = adev_dump;
4206
4207 /* Set the default route before the PCM stream is opened */
4208 pthread_mutex_lock(&adev->lock);
4209 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004210 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004211 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004213 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004214 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004215 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004216 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004217 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004218 pthread_mutex_unlock(&adev->lock);
4219
4220 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004221 adev->platform = platform_init(adev);
4222 if (!adev->platform) {
4223 free(adev->snd_dev_ref_cnt);
4224 free(adev);
4225 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4226 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004227 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004228 return -EINVAL;
4229 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004230 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004231 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004232
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004233 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4234 if (adev->visualizer_lib == NULL) {
4235 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4236 } else {
4237 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4238 adev->visualizer_start_output =
4239 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4240 "visualizer_hal_start_output");
4241 adev->visualizer_stop_output =
4242 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4243 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004244 }
4245
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004246 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4247 if (adev->offload_effects_lib == NULL) {
4248 ALOGW("%s: DLOPEN failed for %s", __func__,
4249 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4250 } else {
4251 ALOGV("%s: DLOPEN successful for %s", __func__,
4252 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4253 adev->offload_effects_start_output =
4254 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4255 "offload_effects_bundle_hal_start_output");
4256 adev->offload_effects_stop_output =
4257 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4258 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004259 }
4260
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004261 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4262 if (adev->adm_lib == NULL) {
4263 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4264 } else {
4265 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4266 adev->adm_init = (adm_init_t)
4267 dlsym(adev->adm_lib, "adm_init");
4268 adev->adm_deinit = (adm_deinit_t)
4269 dlsym(adev->adm_lib, "adm_deinit");
4270 adev->adm_register_input_stream = (adm_register_input_stream_t)
4271 dlsym(adev->adm_lib, "adm_register_input_stream");
4272 adev->adm_register_output_stream = (adm_register_output_stream_t)
4273 dlsym(adev->adm_lib, "adm_register_output_stream");
4274 adev->adm_deregister_stream = (adm_deregister_stream_t)
4275 dlsym(adev->adm_lib, "adm_deregister_stream");
4276 adev->adm_request_focus = (adm_request_focus_t)
4277 dlsym(adev->adm_lib, "adm_request_focus");
4278 adev->adm_abandon_focus = (adm_abandon_focus_t)
4279 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004280 adev->adm_set_config = (adm_set_config_t)
4281 dlsym(adev->adm_lib, "adm_set_config");
4282 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4283 dlsym(adev->adm_lib, "adm_request_focus_v2");
4284 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4285 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4286 adev->adm_on_routing_change = (adm_on_routing_change_t)
4287 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004288 }
4289
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004290 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004291 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004292
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004293 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004294
Andy Hung31aca912014-03-20 17:14:59 -07004295 if (k_enable_extended_precision)
4296 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004297
Glenn Kasten4f993392014-05-14 07:30:48 -07004298 char value[PROPERTY_VALUE_MAX];
4299 int trial;
4300 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4301 trial = atoi(value);
4302 if (period_size_is_plausible_for_low_latency(trial)) {
4303 pcm_config_low_latency.period_size = trial;
4304 pcm_config_low_latency.start_threshold = trial / 4;
4305 pcm_config_low_latency.avail_min = trial / 4;
4306 configured_low_latency_capture_period_size = trial;
4307 }
4308 }
4309 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4310 trial = atoi(value);
4311 if (period_size_is_plausible_for_low_latency(trial)) {
4312 configured_low_latency_capture_period_size = trial;
4313 }
4314 }
4315
Yamit Mehtae3b99562016-09-16 22:44:00 +05304316 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004317 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004318
4319 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4320 af_period_multiplier = atoi(value);
4321 if (af_period_multiplier < 0) {
4322 af_period_multiplier = 2;
4323 } else if (af_period_multiplier > 4) {
4324 af_period_multiplier = 4;
4325 }
4326 ALOGV("new period_multiplier = %d", af_period_multiplier);
4327 }
4328
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004329 audio_extn_tfa_98xx_init(adev);
4330
vivek mehta1a9b7c02015-06-25 11:49:38 -07004331 pthread_mutex_unlock(&adev_init_lock);
4332
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004333 if (adev->adm_init)
4334 adev->adm_data = adev->adm_init();
4335
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004336 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004337 audio_extn_snd_mon_init();
4338 pthread_mutex_lock(&adev->lock);
4339 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4340 adev->card_status = CARD_STATUS_ONLINE;
4341 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004342
Eric Laurent2bafff12016-03-17 12:17:23 -07004343 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004344 return 0;
4345}
4346
4347static struct hw_module_methods_t hal_module_methods = {
4348 .open = adev_open,
4349};
4350
4351struct audio_module HAL_MODULE_INFO_SYM = {
4352 .common = {
4353 .tag = HARDWARE_MODULE_TAG,
4354 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4355 .hal_api_version = HARDWARE_HAL_API_VERSION,
4356 .id = AUDIO_HARDWARE_MODULE_ID,
4357 .name = "QCOM Audio HAL",
4358 .author = "Code Aurora Forum",
4359 .methods = &hal_module_methods,
4360 },
4361};