blob: 9fad3fdb8e4e79c363bb3fb8cd519f3cb6516260 [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>
Kevin Rocardb5c28192017-05-02 15:30:20 -070036#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
38#include <cutils/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
52#include <audio_utils/power.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080054#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070061
Eric Laurent397db572016-05-11 11:31:47 -070062/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
63 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070064#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070065// 2 buffers causes problems with high bitrate files
66#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067/* ToDo: Check and update a proper value in msec */
68#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
69#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
70
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070071#define PROXY_OPEN_RETRY_COUNT 100
72#define PROXY_OPEN_WAIT_TIME 20
73
vivek mehtadae44712015-07-27 14:13:18 -070074#define MIN_CHANNEL_COUNT 1
75#define DEFAULT_CHANNEL_COUNT 2
76
Jean-Michel Trivic0750692015-10-12 12:12:32 -070077#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
78#define MAX_CHANNEL_COUNT 1
79#else
vivek mehtadae44712015-07-27 14:13:18 -070080#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
81#define XSTR(x) STR(x)
82#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070083#endif
vivek mehtadae44712015-07-27 14:13:18 -070084
Haynes Mathew George03c40102016-01-29 17:57:48 -080085#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
86
Glenn Kasten4f993392014-05-14 07:30:48 -070087static unsigned int configured_low_latency_capture_period_size =
88 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
89
Eric Laurent0e46adf2016-12-16 12:49:24 -080090
91#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080092#define MMAP_PERIOD_COUNT_MIN 32
93#define MMAP_PERIOD_COUNT_MAX 512
94#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -080095
96
Andy Hung31aca912014-03-20 17:14:59 -070097/* This constant enables extended precision handling.
98 * TODO The flag is off until more testing is done.
99 */
100static const bool k_enable_extended_precision = false;
101
Eric Laurentb23d5282013-05-14 15:27:20 -0700102struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700103 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700104 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
105 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
106 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
107 .format = PCM_FORMAT_S16_LE,
108 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
109 .stop_threshold = INT_MAX,
110 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
111};
112
113struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700114 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700115 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
116 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
117 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
118 .format = PCM_FORMAT_S16_LE,
119 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
120 .stop_threshold = INT_MAX,
121 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
122};
123
Haynes Mathew George03c40102016-01-29 17:57:48 -0800124static int af_period_multiplier = 4;
125struct pcm_config pcm_config_rt = {
126 .channels = DEFAULT_CHANNEL_COUNT,
127 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
128 .period_size = ULL_PERIOD_SIZE, //1 ms
129 .period_count = 512, //=> buffer size is 512ms
130 .format = PCM_FORMAT_S16_LE,
131 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
132 .stop_threshold = INT_MAX,
133 .silence_threshold = 0,
134 .silence_size = 0,
135 .avail_min = ULL_PERIOD_SIZE, //1 ms
136};
137
Eric Laurentb23d5282013-05-14 15:27:20 -0700138struct pcm_config pcm_config_hdmi_multi = {
139 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
140 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
141 .period_size = HDMI_MULTI_PERIOD_SIZE,
142 .period_count = HDMI_MULTI_PERIOD_COUNT,
143 .format = PCM_FORMAT_S16_LE,
144 .start_threshold = 0,
145 .stop_threshold = INT_MAX,
146 .avail_min = 0,
147};
148
Eric Laurent0e46adf2016-12-16 12:49:24 -0800149struct pcm_config pcm_config_mmap_playback = {
150 .channels = DEFAULT_CHANNEL_COUNT,
151 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
152 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800153 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800154 .format = PCM_FORMAT_S16_LE,
155 .start_threshold = MMAP_PERIOD_SIZE*8,
156 .stop_threshold = INT32_MAX,
157 .silence_threshold = 0,
158 .silence_size = 0,
159 .avail_min = MMAP_PERIOD_SIZE, //1 ms
160};
161
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800162struct pcm_config pcm_config_hifi = {
163 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
164 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
165 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
166 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
167 .format = PCM_FORMAT_S24_3LE,
168 .start_threshold = 0,
169 .stop_threshold = INT_MAX,
170 .avail_min = 0,
171};
172
Eric Laurentb23d5282013-05-14 15:27:20 -0700173struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700174 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700175 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
176 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700177 .stop_threshold = INT_MAX,
178 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700179};
180
Haynes Mathew George03c40102016-01-29 17:57:48 -0800181struct pcm_config pcm_config_audio_capture_rt = {
182 .channels = DEFAULT_CHANNEL_COUNT,
183 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
184 .period_size = ULL_PERIOD_SIZE,
185 .period_count = 512,
186 .format = PCM_FORMAT_S16_LE,
187 .start_threshold = 0,
188 .stop_threshold = INT_MAX,
189 .silence_threshold = 0,
190 .silence_size = 0,
191 .avail_min = ULL_PERIOD_SIZE, //1 ms
192};
193
Eric Laurent0e46adf2016-12-16 12:49:24 -0800194struct pcm_config pcm_config_mmap_capture = {
195 .channels = DEFAULT_CHANNEL_COUNT,
196 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
197 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800198 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800199 .format = PCM_FORMAT_S16_LE,
200 .start_threshold = 0,
201 .stop_threshold = INT_MAX,
202 .silence_threshold = 0,
203 .silence_size = 0,
204 .avail_min = MMAP_PERIOD_SIZE, //1 ms
205};
206
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700207#define AFE_PROXY_CHANNEL_COUNT 2
208#define AFE_PROXY_SAMPLING_RATE 48000
209
210#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
211#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
212
213struct pcm_config pcm_config_afe_proxy_playback = {
214 .channels = AFE_PROXY_CHANNEL_COUNT,
215 .rate = AFE_PROXY_SAMPLING_RATE,
216 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
217 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
218 .format = PCM_FORMAT_S16_LE,
219 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
220 .stop_threshold = INT_MAX,
221 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
222};
223
224#define AFE_PROXY_RECORD_PERIOD_SIZE 768
225#define AFE_PROXY_RECORD_PERIOD_COUNT 4
226
227struct pcm_config pcm_config_afe_proxy_record = {
228 .channels = AFE_PROXY_CHANNEL_COUNT,
229 .rate = AFE_PROXY_SAMPLING_RATE,
230 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
231 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
232 .format = PCM_FORMAT_S16_LE,
233 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
234 .stop_threshold = INT_MAX,
235 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
236};
237
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700238const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700239 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
240 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800241 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700242 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700243 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700244 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800245 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700246
Eric Laurentb23d5282013-05-14 15:27:20 -0700247 [USECASE_AUDIO_RECORD] = "audio-record",
248 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800249 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700250
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800251 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
252 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700253
Eric Laurentb23d5282013-05-14 15:27:20 -0700254 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700255 [USECASE_VOICE2_CALL] = "voice2-call",
256 [USECASE_VOLTE_CALL] = "volte-call",
257 [USECASE_QCHAT_CALL] = "qchat-call",
258 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800259 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
260 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700261
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700262 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
263 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
264
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700265 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
266 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700267
268 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
269 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
270 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
271
Eric Laurentb23d5282013-05-14 15:27:20 -0700272};
273
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800274
275#define STRING_TO_ENUM(string) { #string, string }
276
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800277struct string_to_enum {
278 const char *name;
279 uint32_t value;
280};
281
282static const struct string_to_enum out_channels_name_to_enum_table[] = {
283 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
286};
287
Haynes Mathew George5191a852013-09-11 14:19:36 -0700288static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700289static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700290static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700291static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700292//cache last MBDRC cal step level
293static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700294
Andy Hung9e737de2017-05-22 10:51:22 -0700295// TODO: Consider moving this to a pthread_once() if we have more
296// static initialization required.
297static bool is_userdebug_or_eng_build() {
298 char value[PROPERTY_VALUE_MAX];
299 (void)property_get("ro.build.type", value, "unknown"); // ignore actual length
300 return strcmp(value, "userdebug") == 0 || strcmp(value, "eng") == 0;
301}
302
Haynes Mathew George03c40102016-01-29 17:57:48 -0800303static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
304 int flags __unused)
305{
306 int dir = 0;
307 switch (uc_id) {
308 case USECASE_AUDIO_RECORD_LOW_LATENCY:
309 dir = 1;
310 case USECASE_AUDIO_PLAYBACK_ULL:
311 break;
312 default:
313 return false;
314 }
315
316 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
317 PCM_PLAYBACK : PCM_CAPTURE);
318 if (adev->adm_is_noirq_avail)
319 return adev->adm_is_noirq_avail(adev->adm_data,
320 adev->snd_card, dev_id, dir);
321 return false;
322}
323
324static void register_out_stream(struct stream_out *out)
325{
326 struct audio_device *adev = out->dev;
327 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
328 return;
329
330 if (!adev->adm_register_output_stream)
331 return;
332
333 adev->adm_register_output_stream(adev->adm_data,
334 out->handle,
335 out->flags);
336
337 if (!adev->adm_set_config)
338 return;
339
340 if (out->realtime) {
341 adev->adm_set_config(adev->adm_data,
342 out->handle,
343 out->pcm, &out->config);
344 }
345}
346
347static void register_in_stream(struct stream_in *in)
348{
349 struct audio_device *adev = in->dev;
350 if (!adev->adm_register_input_stream)
351 return;
352
353 adev->adm_register_input_stream(adev->adm_data,
354 in->capture_handle,
355 in->flags);
356
357 if (!adev->adm_set_config)
358 return;
359
360 if (in->realtime) {
361 adev->adm_set_config(adev->adm_data,
362 in->capture_handle,
363 in->pcm,
364 &in->config);
365 }
366}
367
368static void request_out_focus(struct stream_out *out, long ns)
369{
370 struct audio_device *adev = out->dev;
371
Haynes Mathew George03c40102016-01-29 17:57:48 -0800372 if (adev->adm_request_focus_v2) {
373 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
374 } else if (adev->adm_request_focus) {
375 adev->adm_request_focus(adev->adm_data, out->handle);
376 }
377}
378
379static void request_in_focus(struct stream_in *in, long ns)
380{
381 struct audio_device *adev = in->dev;
382
Haynes Mathew George03c40102016-01-29 17:57:48 -0800383 if (adev->adm_request_focus_v2) {
384 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
385 } else if (adev->adm_request_focus) {
386 adev->adm_request_focus(adev->adm_data, in->capture_handle);
387 }
388}
389
390static void release_out_focus(struct stream_out *out, long ns __unused)
391{
392 struct audio_device *adev = out->dev;
393
394 if (adev->adm_abandon_focus)
395 adev->adm_abandon_focus(adev->adm_data, out->handle);
396}
397
398static void release_in_focus(struct stream_in *in, long ns __unused)
399{
400 struct audio_device *adev = in->dev;
401 if (adev->adm_abandon_focus)
402 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
403}
404
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700405static int parse_snd_card_status(struct str_parms * parms, int * card,
406 card_status_t * status)
407{
408 char value[32]={0};
409 char state[32]={0};
410
411 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
412
413 if (ret < 0)
414 return -1;
415
416 // sscanf should be okay as value is of max length 32.
417 // same as sizeof state.
418 if (sscanf(value, "%d,%s", card, state) < 2)
419 return -1;
420
421 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
422 CARD_STATUS_OFFLINE;
423 return 0;
424}
425
vivek mehta1a9b7c02015-06-25 11:49:38 -0700426__attribute__ ((visibility ("default")))
427bool audio_hw_send_gain_dep_calibration(int level) {
428 bool ret_val = false;
429 ALOGV("%s: enter ... ", __func__);
430
431 pthread_mutex_lock(&adev_init_lock);
432
433 if (adev != NULL && adev->platform != NULL) {
434 pthread_mutex_lock(&adev->lock);
435 ret_val = platform_send_gain_dep_cal(adev->platform, level);
436 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700437
438 // if cal set fails, cache level info
439 // if cal set succeds, reset known last cal set
440 if (!ret_val)
441 last_known_cal_step = level;
442 else if (last_known_cal_step != -1)
443 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700444 } else {
445 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
446 }
447
448 pthread_mutex_unlock(&adev_init_lock);
449
450 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
451 return ret_val;
452}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700453
vivek mehtaa8d7c922016-05-25 14:40:44 -0700454__attribute__ ((visibility ("default")))
455int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
456 int table_size) {
457 int ret_val = 0;
458 ALOGV("%s: enter ... ", __func__);
459
460 pthread_mutex_lock(&adev_init_lock);
461 if (adev == NULL) {
462 ALOGW("%s: adev is NULL .... ", __func__);
463 goto done;
464 }
465
466 pthread_mutex_lock(&adev->lock);
467 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
468 pthread_mutex_unlock(&adev->lock);
469done:
470 pthread_mutex_unlock(&adev_init_lock);
471 ALOGV("%s: exit ... ", __func__);
472 return ret_val;
473}
474
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700475static bool is_supported_format(audio_format_t format)
476{
Eric Laurent8251ac82014-07-23 11:00:25 -0700477 switch (format) {
478 case AUDIO_FORMAT_MP3:
479 case AUDIO_FORMAT_AAC_LC:
480 case AUDIO_FORMAT_AAC_HE_V1:
481 case AUDIO_FORMAT_AAC_HE_V2:
482 return true;
483 default:
484 break;
485 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700486 return false;
487}
488
Haynes Mathew George03c40102016-01-29 17:57:48 -0800489static inline bool is_mmap_usecase(audio_usecase_t uc_id)
490{
491 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
492 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
493}
494
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700495static int get_snd_codec_id(audio_format_t format)
496{
497 int id = 0;
498
Eric Laurent8251ac82014-07-23 11:00:25 -0700499 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700500 case AUDIO_FORMAT_MP3:
501 id = SND_AUDIOCODEC_MP3;
502 break;
503 case AUDIO_FORMAT_AAC:
504 id = SND_AUDIOCODEC_AAC;
505 break;
506 default:
507 ALOGE("%s: Unsupported audio format", __func__);
508 }
509
510 return id;
511}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800512
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800513static int audio_ssr_status(struct audio_device *adev)
514{
515 int ret = 0;
516 struct mixer_ctl *ctl;
517 const char *mixer_ctl_name = "Audio SSR Status";
518
519 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
520 ret = mixer_ctl_get_value(ctl, 0);
521 ALOGD("%s: value: %d", __func__, ret);
522 return ret;
523}
524
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800525int enable_audio_route(struct audio_device *adev,
526 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800527{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700528 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800529 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800530
531 if (usecase == NULL)
532 return -EINVAL;
533
534 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
535
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800536 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700537 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800538 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700539 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800540
Yamit Mehtae3b99562016-09-16 22:44:00 +0530541 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800542 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800543 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500544 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700545 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700546 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800548 ALOGV("%s: exit", __func__);
549 return 0;
550}
551
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800552int disable_audio_route(struct audio_device *adev,
553 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800554{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700555 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800556 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800557
558 if (usecase == NULL)
559 return -EINVAL;
560
561 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700562 if (usecase->type == PCM_CAPTURE)
563 snd_device = usecase->in_snd_device;
564 else
565 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800566 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500567 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700568 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700569 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800570
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800571 ALOGV("%s: exit", __func__);
572 return 0;
573}
574
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800575int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700576 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800577{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700578 int i, num_devices = 0;
579 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800580 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800581 if (snd_device < SND_DEVICE_MIN ||
582 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800583 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800584 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800585 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700586
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700587 platform_send_audio_calibration(adev->platform, snd_device);
588
vivek mehtade4849c2016-03-03 17:23:38 -0800589 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700590 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700591 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800592 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700593 }
594
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700595 /* due to the possibility of calibration overwrite between listen
596 and audio, notify sound trigger hal before audio calibration is sent */
597 audio_extn_sound_trigger_update_device_status(snd_device,
598 ST_EVENT_SND_DEVICE_BUSY);
599
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700600 if (audio_extn_spkr_prot_is_enabled())
601 audio_extn_spkr_prot_calib_cancel(adev);
602
zhaoyang yin4211fad2015-06-04 21:13:25 +0800603 audio_extn_dsm_feedback_enable(adev, snd_device, true);
604
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700605 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
606 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
607 audio_extn_spkr_prot_is_enabled()) {
608 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800609 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700610 }
611 if (audio_extn_spkr_prot_start_processing(snd_device)) {
612 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800613 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700614 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700615 } else if (platform_can_split_snd_device(snd_device,
616 &num_devices,
617 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700618 for (i = 0; i < num_devices; i++) {
619 enable_snd_device(adev, new_snd_devices[i]);
620 }
vivek mehtab6506412015-08-07 16:55:17 -0700621 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700622 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800623 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
624 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
625 ALOGE(" %s: Invalid sound device returned", __func__);
626 goto on_error;
627 }
Ed Tam70b5c142016-03-21 19:14:29 -0700628
Eric Laurent2e140aa2016-06-30 17:14:46 -0700629 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800630 audio_route_apply_and_update_path(adev->audio_route, device_name);
631 }
632on_success:
633 adev->snd_dev_ref_cnt[snd_device]++;
634 ret_val = 0;
635on_error:
636 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800637}
638
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800639int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700640 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800641{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700642 int i, num_devices = 0;
643 snd_device_t new_snd_devices[2];
644
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800645 if (snd_device < SND_DEVICE_MIN ||
646 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800647 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800648 return -EINVAL;
649 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700650 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
651 ALOGE("%s: device ref cnt is already 0", __func__);
652 return -EINVAL;
653 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800654 audio_extn_tfa_98xx_disable_speaker(snd_device);
655
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700656 adev->snd_dev_ref_cnt[snd_device]--;
657 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800658 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700659 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
660 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
661 audio_extn_spkr_prot_is_enabled()) {
662 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700663 } else if (platform_can_split_snd_device(snd_device,
664 &num_devices,
665 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700666 for (i = 0; i < num_devices; i++) {
667 disable_snd_device(adev, new_snd_devices[i]);
668 }
vivek mehtab6506412015-08-07 16:55:17 -0700669 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700670 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800671 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
672 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
673 ALOGE(" %s: Invalid sound device returned", __func__);
674 return -EINVAL;
675 }
676
Eric Laurent2e140aa2016-06-30 17:14:46 -0700677 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800678 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700679 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700680 audio_extn_sound_trigger_update_device_status(snd_device,
681 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700682 }
vivek mehtab6506412015-08-07 16:55:17 -0700683
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800684 return 0;
685}
686
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700687/*
688 legend:
689 uc - existing usecase
690 new_uc - new usecase
691 d1, d11, d2 - SND_DEVICE enums
692 a1, a2 - corresponding ANDROID device enums
693 B, B1, B2 - backend strings
694
695case 1
696 uc->dev d1 (a1) B1
697 new_uc->dev d1 (a1), d2 (a2) B1, B2
698
699 resolution: disable and enable uc->dev on d1
700
701case 2
702 uc->dev d1 (a1) B1
703 new_uc->dev d11 (a1) B1
704
705 resolution: need to switch uc since d1 and d11 are related
706 (e.g. speaker and voice-speaker)
707 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
708
709case 3
710 uc->dev d1 (a1) B1
711 new_uc->dev d2 (a2) B2
712
713 resolution: no need to switch uc
714
715case 4
716 uc->dev d1 (a1) B
717 new_uc->dev d2 (a2) B
718
719 resolution: disable enable uc-dev on d2 since backends match
720 we cannot enable two streams on two different devices if they
721 share the same backend. e.g. if offload is on speaker device using
722 QUAD_MI2S backend and a low-latency stream is started on voice-handset
723 using the same backend, offload must also be switched to voice-handset.
724
725case 5
726 uc->dev d1 (a1) B
727 new_uc->dev d1 (a1), d2 (a2) B
728
729 resolution: disable enable uc-dev on d2 since backends match
730 we cannot enable two streams on two different devices if they
731 share the same backend.
732
733case 6
734 uc->dev d1 a1 B1
735 new_uc->dev d2 a1 B2
736
737 resolution: no need to switch
738
739case 7
740
741 uc->dev d1 (a1), d2 (a2) B1, B2
742 new_uc->dev d1 B1
743
744 resolution: no need to switch
745
746*/
747static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
748 struct audio_usecase *new_uc,
749 snd_device_t new_snd_device)
750{
751 audio_devices_t a1 = uc->stream.out->devices;
752 audio_devices_t a2 = new_uc->stream.out->devices;
753
754 snd_device_t d1 = uc->out_snd_device;
755 snd_device_t d2 = new_snd_device;
756
757 // Treat as a special case when a1 and a2 are not disjoint
758 if ((a1 != a2) && (a1 & a2)) {
759 snd_device_t d3[2];
760 int num_devices = 0;
761 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
762 &num_devices,
763 d3);
764 if (ret < 0) {
765 if (ret != -ENOSYS) {
766 ALOGW("%s failed to split snd_device %d",
767 __func__,
768 popcount(a1) > 1 ? d1 : d2);
769 }
770 goto end;
771 }
772
773 // NB: case 7 is hypothetical and isn't a practical usecase yet.
774 // But if it does happen, we need to give priority to d2 if
775 // the combo devices active on the existing usecase share a backend.
776 // This is because we cannot have a usecase active on a combo device
777 // and a new usecase requests one device in this combo pair.
778 if (platform_check_backends_match(d3[0], d3[1])) {
779 return d2; // case 5
780 } else {
781 return d1; // case 1
782 }
783 } else {
784 if (platform_check_backends_match(d1, d2)) {
785 return d2; // case 2, 4
786 } else {
787 return d1; // case 6, 3
788 }
789 }
790
791end:
792 return d2; // return whatever was calculated before.
793}
794
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700795static void check_and_route_playback_usecases(struct audio_device *adev,
796 struct audio_usecase *uc_info,
797 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700798{
799 struct listnode *node;
800 struct audio_usecase *usecase;
801 bool switch_device[AUDIO_USECASE_MAX];
802 int i, num_uc_to_switch = 0;
803
David Linee3fe402017-03-13 10:00:42 -0700804 platform_check_and_set_playback_backend_cfg(adev, uc_info, snd_device);
805
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700806 /*
807 * This function is to make sure that all the usecases that are active on
808 * the hardware codec backend are always routed to any one device that is
809 * handled by the hardware codec.
810 * For example, if low-latency and deep-buffer usecases are currently active
811 * on speaker and out_set_parameters(headset) is received on low-latency
812 * output, then we have to make sure deep-buffer is also switched to headset,
813 * because of the limitation that both the devices cannot be enabled
814 * at the same time as they share the same backend.
815 */
816 /* Disable all the usecases on the shared backend other than the
817 specified usecase */
818 for (i = 0; i < AUDIO_USECASE_MAX; i++)
819 switch_device[i] = false;
820
821 list_for_each(node, &adev->usecase_list) {
822 usecase = node_to_item(node, struct audio_usecase, list);
823 if (usecase->type != PCM_CAPTURE &&
824 usecase != uc_info &&
825 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700826 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
827 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700828 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
829 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700830 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700831 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700832 switch_device[usecase->id] = true;
833 num_uc_to_switch++;
834 }
835 }
836
837 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700838 list_for_each(node, &adev->usecase_list) {
839 usecase = node_to_item(node, struct audio_usecase, list);
840 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700841 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900842 }
843 }
844
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700845 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900846 list_for_each(node, &adev->usecase_list) {
847 usecase = node_to_item(node, struct audio_usecase, list);
848 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700849 d_device = derive_playback_snd_device(usecase, uc_info,
850 snd_device);
851 enable_snd_device(adev, d_device);
852 /* Update the out_snd_device before enabling the audio route */
853 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700854 }
855 }
856
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 /* Re-route all the usecases on the shared backend other than the
858 specified usecase to new snd devices */
859 list_for_each(node, &adev->usecase_list) {
860 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700861 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700862 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700863 }
864 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700865 }
866}
867
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700868static void check_and_route_capture_usecases(struct audio_device *adev,
869 struct audio_usecase *uc_info,
870 snd_device_t snd_device)
871{
872 struct listnode *node;
873 struct audio_usecase *usecase;
874 bool switch_device[AUDIO_USECASE_MAX];
875 int i, num_uc_to_switch = 0;
876
vivek mehta4ed66e62016-04-15 23:33:34 -0700877 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
878
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700879 /*
880 * This function is to make sure that all the active capture usecases
881 * are always routed to the same input sound device.
882 * For example, if audio-record and voice-call usecases are currently
883 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
884 * is received for voice call then we have to make sure that audio-record
885 * usecase is also switched to earpiece i.e. voice-dmic-ef,
886 * because of the limitation that two devices cannot be enabled
887 * at the same time if they share the same backend.
888 */
889 for (i = 0; i < AUDIO_USECASE_MAX; i++)
890 switch_device[i] = false;
891
892 list_for_each(node, &adev->usecase_list) {
893 usecase = node_to_item(node, struct audio_usecase, list);
894 if (usecase->type != PCM_PLAYBACK &&
895 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700896 usecase->in_snd_device != snd_device &&
897 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700898 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
899 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700900 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700901 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700902 switch_device[usecase->id] = true;
903 num_uc_to_switch++;
904 }
905 }
906
907 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700908 list_for_each(node, &adev->usecase_list) {
909 usecase = node_to_item(node, struct audio_usecase, list);
910 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700911 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700912 }
913 }
914
915 list_for_each(node, &adev->usecase_list) {
916 usecase = node_to_item(node, struct audio_usecase, list);
917 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700918 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700919 }
920 }
921
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700922 /* Re-route all the usecases on the shared backend other than the
923 specified usecase to new snd devices */
924 list_for_each(node, &adev->usecase_list) {
925 usecase = node_to_item(node, struct audio_usecase, list);
926 /* Update the in_snd_device only before enabling the audio route */
927 if (switch_device[usecase->id] ) {
928 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700929 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700930 }
931 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700932 }
933}
934
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800935/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700936static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800937{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700938 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700939 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800940
941 switch (channels) {
942 /*
943 * Do not handle stereo output in Multi-channel cases
944 * Stereo case is handled in normal playback path
945 */
946 case 6:
947 ALOGV("%s: HDMI supports 5.1", __func__);
948 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
949 break;
950 case 8:
951 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
952 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
953 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
954 break;
955 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700956 ALOGE("HDMI does not support multi channel playback");
957 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800958 break;
959 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700960 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800961}
962
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800963static int read_usb_sup_sample_rates(struct stream_out *out)
964{
965 uint32_t *sr = out->supported_sample_rates;
966 size_t count = audio_extn_usb_sup_sample_rates(0 /*playback*/,
967 sr,
968 MAX_SUPPORTED_SAMPLE_RATES);
969#if !LOG_NDEBUG
970
971 for (size_t i=0; i<count; i++) {
972 ALOGV("%s %d", __func__, out->supported_sample_rates[i]);
973 }
974#endif
975 return count > 0 ? 0 : -1;
976}
977
978static int read_usb_sup_channel_masks(struct stream_out *out)
979{
980 int channels = audio_extn_usb_get_max_channels();
981 out->supported_channel_masks[0] =
982 channels < 3 ? audio_channel_out_mask_from_count(channels) :
983 audio_channel_mask_for_index_assignment_from_count(channels);
984 return 0;
985}
986
987static int read_usb_sup_formats(struct stream_out *out)
988{
989 int bitwidth = audio_extn_usb_get_max_bit_width();
990 switch (bitwidth) {
991 case 24:
992 // XXX : usb.c returns 24 for s24 and s24_le?
993 out->supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
994 break;
995 case 32:
996 out->supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
997 break;
998 case 16:
999 default :
1000 out->supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1001 break;
1002 }
1003
1004 return 0;
1005}
1006
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001007static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1008{
1009 struct audio_usecase *usecase;
1010 struct listnode *node;
1011
1012 list_for_each(node, &adev->usecase_list) {
1013 usecase = node_to_item(node, struct audio_usecase, list);
1014 if (usecase->type == VOICE_CALL) {
1015 ALOGV("%s: usecase id %d", __func__, usecase->id);
1016 return usecase->id;
1017 }
1018 }
1019 return USECASE_INVALID;
1020}
1021
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001022struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1023 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001024{
1025 struct audio_usecase *usecase;
1026 struct listnode *node;
1027
1028 list_for_each(node, &adev->usecase_list) {
1029 usecase = node_to_item(node, struct audio_usecase, list);
1030 if (usecase->id == uc_id)
1031 return usecase;
1032 }
1033 return NULL;
1034}
1035
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001036int select_devices(struct audio_device *adev,
1037 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001038{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001039 snd_device_t out_snd_device = SND_DEVICE_NONE;
1040 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001041 struct audio_usecase *usecase = NULL;
1042 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001043 struct audio_usecase *hfp_usecase = NULL;
1044 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001045 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001046 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001047
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001048 usecase = get_usecase_from_list(adev, uc_id);
1049 if (usecase == NULL) {
1050 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1051 return -EINVAL;
1052 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001053
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001054 if ((usecase->type == VOICE_CALL) ||
1055 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001056 out_snd_device = platform_get_output_snd_device(adev->platform,
1057 usecase->stream.out->devices);
1058 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001059 usecase->devices = usecase->stream.out->devices;
1060 } else {
1061 /*
1062 * If the voice call is active, use the sound devices of voice call usecase
1063 * so that it would not result any device switch. All the usecases will
1064 * be switched to new device when select_devices() is called for voice call
1065 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001066 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001067 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001068 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001069 vc_usecase = get_usecase_from_list(adev,
1070 get_voice_usecase_id_from_list(adev));
1071 if ((vc_usecase != NULL) &&
1072 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1073 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001074 in_snd_device = vc_usecase->in_snd_device;
1075 out_snd_device = vc_usecase->out_snd_device;
1076 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001077 } else if (audio_extn_hfp_is_active(adev)) {
1078 hfp_ucid = audio_extn_hfp_get_usecase();
1079 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1080 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1081 in_snd_device = hfp_usecase->in_snd_device;
1082 out_snd_device = hfp_usecase->out_snd_device;
1083 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001084 }
1085 if (usecase->type == PCM_PLAYBACK) {
1086 usecase->devices = usecase->stream.out->devices;
1087 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001088 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001089 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001090 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001091 if (usecase->stream.out == adev->primary_output &&
1092 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001093 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1094 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001095 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001096 select_devices(adev, adev->active_input->usecase);
1097 }
1098 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001099 } else if (usecase->type == PCM_CAPTURE) {
1100 usecase->devices = usecase->stream.in->device;
1101 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001102 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001103 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001104 if (adev->active_input &&
1105 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1106 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001107 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001108 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1109 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1110 } else if (adev->primary_output) {
1111 out_device = adev->primary_output->devices;
1112 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001113 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001114 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001115 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001116 }
1117 }
1118
1119 if (out_snd_device == usecase->out_snd_device &&
1120 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001121 return 0;
1122 }
1123
Eric Laurent2bafff12016-03-17 12:17:23 -07001124 if (out_snd_device != SND_DEVICE_NONE &&
1125 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1126 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1127 __func__,
1128 use_case_table[uc_id],
1129 adev->last_logged_snd_device[uc_id][0],
1130 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1131 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1132 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1133 -1,
1134 out_snd_device,
1135 platform_get_snd_device_name(out_snd_device),
1136 platform_get_snd_device_acdb_id(out_snd_device));
1137 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1138 }
1139 if (in_snd_device != SND_DEVICE_NONE &&
1140 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1141 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1142 __func__,
1143 use_case_table[uc_id],
1144 adev->last_logged_snd_device[uc_id][1],
1145 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1146 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1147 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1148 -1,
1149 in_snd_device,
1150 platform_get_snd_device_name(in_snd_device),
1151 platform_get_snd_device_acdb_id(in_snd_device));
1152 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1153 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001154
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001155 /*
1156 * Limitation: While in call, to do a device switch we need to disable
1157 * and enable both RX and TX devices though one of them is same as current
1158 * device.
1159 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001160 if ((usecase->type == VOICE_CALL) &&
1161 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1162 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001163 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001164 /* Disable sidetone only if voice call already exists */
1165 if (voice_is_call_state_active(adev))
1166 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001167 }
1168
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001169 /* Disable current sound devices */
1170 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001171 disable_audio_route(adev, usecase);
1172 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001173 }
1174
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001175 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001176 disable_audio_route(adev, usecase);
1177 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001178 }
1179
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001180 /* Applicable only on the targets that has external modem.
1181 * New device information should be sent to modem before enabling
1182 * the devices to reduce in-call device switch time.
1183 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001184 if ((usecase->type == VOICE_CALL) &&
1185 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1186 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001187 status = platform_switch_voice_call_enable_device_config(adev->platform,
1188 out_snd_device,
1189 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001190 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001191
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001192 /* Enable new sound devices */
1193 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001194 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1195 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001196 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001197 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001198 }
1199
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001200 if (in_snd_device != SND_DEVICE_NONE) {
1201 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001202 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001203 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001204
Eric Laurentb23d5282013-05-14 15:27:20 -07001205 if (usecase->type == VOICE_CALL)
1206 status = platform_switch_voice_call_device_post(adev->platform,
1207 out_snd_device,
1208 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001209
sangwoo170731f2013-06-08 15:36:36 +09001210 usecase->in_snd_device = in_snd_device;
1211 usecase->out_snd_device = out_snd_device;
1212
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001213 audio_extn_tfa_98xx_set_mode();
1214
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001215 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001216
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001217 /* Applicable only on the targets that has external modem.
1218 * Enable device command should be sent to modem only after
1219 * enabling voice call mixer controls
1220 */
vivek mehta765eb642015-08-07 19:46:06 -07001221 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001222 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1223 out_snd_device,
1224 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001225 /* Enable sidetone only if voice call already exists */
1226 if (voice_is_call_state_active(adev))
1227 voice_set_sidetone(adev, out_snd_device, true);
1228 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001230 return status;
1231}
1232
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001233static int stop_input_stream(struct stream_in *in)
1234{
1235 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001236 struct audio_usecase *uc_info;
1237 struct audio_device *adev = in->dev;
1238
Eric Laurentc8400632013-02-14 19:04:54 -08001239 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001240
Eric Laurent994a6932013-07-17 11:51:42 -07001241 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001242 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001243 uc_info = get_usecase_from_list(adev, in->usecase);
1244 if (uc_info == NULL) {
1245 ALOGE("%s: Could not find the usecase (%d) in the list",
1246 __func__, in->usecase);
1247 return -EINVAL;
1248 }
1249
vivek mehta781065c2017-04-04 12:55:01 -07001250 /* Close in-call recording streams */
1251 voice_check_and_stop_incall_rec_usecase(adev, in);
1252
Eric Laurent150dbfe2013-02-27 14:31:02 -08001253 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001254 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001255
1256 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001257 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001258
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001259 list_remove(&uc_info->list);
1260 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001261
Eric Laurent994a6932013-07-17 11:51:42 -07001262 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001263 return ret;
1264}
1265
1266int start_input_stream(struct stream_in *in)
1267{
1268 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001269 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001270 struct audio_usecase *uc_info;
1271 struct audio_device *adev = in->dev;
1272
Eric Laurent994a6932013-07-17 11:51:42 -07001273 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001274
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001275 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1276 return -EIO;
1277
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001278 if (in->card_status == CARD_STATUS_OFFLINE ||
1279 adev->card_status == CARD_STATUS_OFFLINE) {
1280 ALOGW("in->card_status or adev->card_status offline, try again");
1281 ret = -EAGAIN;
1282 goto error_config;
1283 }
1284
vivek mehta781065c2017-04-04 12:55:01 -07001285 /* Check if source matches incall recording usecase criteria */
1286 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1287 if (ret)
1288 goto error_config;
1289 else
1290 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1291
Eric Laurentb23d5282013-05-14 15:27:20 -07001292 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001293 if (in->pcm_device_id < 0) {
1294 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1295 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001296 ret = -EINVAL;
1297 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001298 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001299
1300 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001301 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1302 uc_info->id = in->usecase;
1303 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001304 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001305 uc_info->devices = in->device;
1306 uc_info->in_snd_device = SND_DEVICE_NONE;
1307 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001308
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001309 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001310
1311 audio_extn_perf_lock_acquire();
1312
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001313 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001314
Eric Laurent0e46adf2016-12-16 12:49:24 -08001315 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001316 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001317 ALOGE("%s: pcm stream not ready", __func__);
1318 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001319 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001320 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001321 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001322 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1323 goto error_open;
1324 }
1325 } else {
1326 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1327 unsigned int pcm_open_retry_count = 0;
1328
1329 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1330 flags |= PCM_MMAP | PCM_NOIRQ;
1331 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1332 } else if (in->realtime) {
1333 flags |= PCM_MMAP | PCM_NOIRQ;
1334 }
1335
1336 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1337 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1338
1339 while (1) {
1340 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1341 flags, &in->config);
1342 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1343 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1344 if (in->pcm != NULL) {
1345 pcm_close(in->pcm);
1346 in->pcm = NULL;
1347 }
1348 if (pcm_open_retry_count-- == 0) {
1349 ret = -EIO;
1350 goto error_open;
1351 }
1352 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1353 continue;
1354 }
1355 break;
1356 }
1357
1358 ALOGV("%s: pcm_prepare", __func__);
1359 ret = pcm_prepare(in->pcm);
1360 if (ret < 0) {
1361 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001362 pcm_close(in->pcm);
1363 in->pcm = NULL;
1364 goto error_open;
1365 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001366 if (in->realtime) {
1367 ret = pcm_start(in->pcm);
1368 if (ret < 0) {
1369 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1370 pcm_close(in->pcm);
1371 in->pcm = NULL;
1372 goto error_open;
1373 }
1374 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001375 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001376 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001377 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001378 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001379
Eric Laurent0e46adf2016-12-16 12:49:24 -08001380 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001381
1382error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001383 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001384 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001385
1386error_config:
1387 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001388 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001389
1390 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001391}
1392
Eric Laurenta1478072015-09-21 17:21:52 -07001393void lock_input_stream(struct stream_in *in)
1394{
1395 pthread_mutex_lock(&in->pre_lock);
1396 pthread_mutex_lock(&in->lock);
1397 pthread_mutex_unlock(&in->pre_lock);
1398}
1399
1400void lock_output_stream(struct stream_out *out)
1401{
1402 pthread_mutex_lock(&out->pre_lock);
1403 pthread_mutex_lock(&out->lock);
1404 pthread_mutex_unlock(&out->pre_lock);
1405}
1406
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001407/* must be called with out->lock locked */
1408static int send_offload_cmd_l(struct stream_out* out, int command)
1409{
1410 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1411
1412 ALOGVV("%s %d", __func__, command);
1413
1414 cmd->cmd = command;
1415 list_add_tail(&out->offload_cmd_list, &cmd->node);
1416 pthread_cond_signal(&out->offload_cond);
1417 return 0;
1418}
1419
1420/* must be called iwth out->lock locked */
1421static void stop_compressed_output_l(struct stream_out *out)
1422{
1423 out->offload_state = OFFLOAD_STATE_IDLE;
1424 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001425 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001426 if (out->compr != NULL) {
1427 compress_stop(out->compr);
1428 while (out->offload_thread_blocked) {
1429 pthread_cond_wait(&out->cond, &out->lock);
1430 }
1431 }
1432}
1433
1434static void *offload_thread_loop(void *context)
1435{
1436 struct stream_out *out = (struct stream_out *) context;
1437 struct listnode *item;
1438
1439 out->offload_state = OFFLOAD_STATE_IDLE;
1440 out->playback_started = 0;
1441
1442 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1443 set_sched_policy(0, SP_FOREGROUND);
1444 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1445
1446 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001447 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001448 for (;;) {
1449 struct offload_cmd *cmd = NULL;
1450 stream_callback_event_t event;
1451 bool send_callback = false;
1452
1453 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1454 __func__, list_empty(&out->offload_cmd_list),
1455 out->offload_state);
1456 if (list_empty(&out->offload_cmd_list)) {
1457 ALOGV("%s SLEEPING", __func__);
1458 pthread_cond_wait(&out->offload_cond, &out->lock);
1459 ALOGV("%s RUNNING", __func__);
1460 continue;
1461 }
1462
1463 item = list_head(&out->offload_cmd_list);
1464 cmd = node_to_item(item, struct offload_cmd, node);
1465 list_remove(item);
1466
1467 ALOGVV("%s STATE %d CMD %d out->compr %p",
1468 __func__, out->offload_state, cmd->cmd, out->compr);
1469
1470 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1471 free(cmd);
1472 break;
1473 }
1474
1475 if (out->compr == NULL) {
1476 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001477 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001478 pthread_cond_signal(&out->cond);
1479 continue;
1480 }
1481 out->offload_thread_blocked = true;
1482 pthread_mutex_unlock(&out->lock);
1483 send_callback = false;
1484 switch(cmd->cmd) {
1485 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1486 compress_wait(out->compr, -1);
1487 send_callback = true;
1488 event = STREAM_CBK_EVENT_WRITE_READY;
1489 break;
1490 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001491 compress_next_track(out->compr);
1492 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001493 send_callback = true;
1494 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001495 /* Resend the metadata for next iteration */
1496 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001497 break;
1498 case OFFLOAD_CMD_DRAIN:
1499 compress_drain(out->compr);
1500 send_callback = true;
1501 event = STREAM_CBK_EVENT_DRAIN_READY;
1502 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001503 case OFFLOAD_CMD_ERROR:
1504 send_callback = true;
1505 event = STREAM_CBK_EVENT_ERROR;
1506 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001507 default:
1508 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1509 break;
1510 }
Eric Laurenta1478072015-09-21 17:21:52 -07001511 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001512 out->offload_thread_blocked = false;
1513 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001514 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001515 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001516 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001517 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001518 free(cmd);
1519 }
1520
1521 pthread_cond_signal(&out->cond);
1522 while (!list_empty(&out->offload_cmd_list)) {
1523 item = list_head(&out->offload_cmd_list);
1524 list_remove(item);
1525 free(node_to_item(item, struct offload_cmd, node));
1526 }
1527 pthread_mutex_unlock(&out->lock);
1528
1529 return NULL;
1530}
1531
1532static int create_offload_callback_thread(struct stream_out *out)
1533{
1534 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1535 list_init(&out->offload_cmd_list);
1536 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1537 offload_thread_loop, out);
1538 return 0;
1539}
1540
1541static int destroy_offload_callback_thread(struct stream_out *out)
1542{
Eric Laurenta1478072015-09-21 17:21:52 -07001543 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001544 stop_compressed_output_l(out);
1545 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1546
1547 pthread_mutex_unlock(&out->lock);
1548 pthread_join(out->offload_thread, (void **) NULL);
1549 pthread_cond_destroy(&out->offload_cond);
1550
1551 return 0;
1552}
1553
Eric Laurent07eeafd2013-10-06 12:52:49 -07001554static bool allow_hdmi_channel_config(struct audio_device *adev)
1555{
1556 struct listnode *node;
1557 struct audio_usecase *usecase;
1558 bool ret = true;
1559
1560 list_for_each(node, &adev->usecase_list) {
1561 usecase = node_to_item(node, struct audio_usecase, list);
1562 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1563 /*
1564 * If voice call is already existing, do not proceed further to avoid
1565 * disabling/enabling both RX and TX devices, CSD calls, etc.
1566 * Once the voice call done, the HDMI channels can be configured to
1567 * max channels of remaining use cases.
1568 */
1569 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001570 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001571 __func__);
1572 ret = false;
1573 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001574 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1575 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001576 "no change in HDMI channels", __func__);
1577 ret = false;
1578 break;
1579 }
1580 }
1581 }
1582 return ret;
1583}
1584
1585static int check_and_set_hdmi_channels(struct audio_device *adev,
1586 unsigned int channels)
1587{
1588 struct listnode *node;
1589 struct audio_usecase *usecase;
1590
1591 /* Check if change in HDMI channel config is allowed */
1592 if (!allow_hdmi_channel_config(adev))
1593 return 0;
1594
1595 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001596 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001597 return 0;
1598 }
1599
1600 platform_set_hdmi_channels(adev->platform, channels);
1601 adev->cur_hdmi_channels = channels;
1602
1603 /*
1604 * Deroute all the playback streams routed to HDMI so that
1605 * the back end is deactivated. Note that backend will not
1606 * be deactivated if any one stream is connected to it.
1607 */
1608 list_for_each(node, &adev->usecase_list) {
1609 usecase = node_to_item(node, struct audio_usecase, list);
1610 if (usecase->type == PCM_PLAYBACK &&
1611 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001612 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001613 }
1614 }
1615
1616 /*
1617 * Enable all the streams disabled above. Now the HDMI backend
1618 * will be activated with new channel configuration
1619 */
1620 list_for_each(node, &adev->usecase_list) {
1621 usecase = node_to_item(node, struct audio_usecase, list);
1622 if (usecase->type == PCM_PLAYBACK &&
1623 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001624 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001625 }
1626 }
1627
1628 return 0;
1629}
1630
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001631static int stop_output_stream(struct stream_out *out)
1632{
1633 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001634 struct audio_usecase *uc_info;
1635 struct audio_device *adev = out->dev;
1636
Eric Laurent994a6932013-07-17 11:51:42 -07001637 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001638 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001639 uc_info = get_usecase_from_list(adev, out->usecase);
1640 if (uc_info == NULL) {
1641 ALOGE("%s: Could not find the usecase (%d) in the list",
1642 __func__, out->usecase);
1643 return -EINVAL;
1644 }
1645
Haynes Mathew George41f86652014-06-17 14:22:15 -07001646 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1647 if (adev->visualizer_stop_output != NULL)
1648 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1649 if (adev->offload_effects_stop_output != NULL)
1650 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1651 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001652
Eric Laurent150dbfe2013-02-27 14:31:02 -08001653 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001654 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001655
1656 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001657 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001659 list_remove(&uc_info->list);
1660 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661
Eric Laurent0499d4f2014-08-25 22:39:29 -05001662 audio_extn_extspk_update(adev->extspk);
1663
Eric Laurent07eeafd2013-10-06 12:52:49 -07001664 /* Must be called after removing the usecase from list */
1665 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1666 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1667
Eric Laurent994a6932013-07-17 11:51:42 -07001668 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001669 return ret;
1670}
1671
1672int start_output_stream(struct stream_out *out)
1673{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001675 struct audio_usecase *uc_info;
1676 struct audio_device *adev = out->dev;
1677
Eric Laurent994a6932013-07-17 11:51:42 -07001678 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001679 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001680
1681 if (out->card_status == CARD_STATUS_OFFLINE ||
1682 adev->card_status == CARD_STATUS_OFFLINE) {
1683 ALOGW("out->card_status or adev->card_status offline, try again");
1684 ret = -EAGAIN;
1685 goto error_config;
1686 }
1687
Eric Laurentb23d5282013-05-14 15:27:20 -07001688 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689 if (out->pcm_device_id < 0) {
1690 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1691 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001692 ret = -EINVAL;
1693 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001694 }
1695
1696 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1697 uc_info->id = out->usecase;
1698 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001699 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001700 uc_info->devices = out->devices;
1701 uc_info->in_snd_device = SND_DEVICE_NONE;
1702 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703
Eric Laurent07eeafd2013-10-06 12:52:49 -07001704 /* This must be called before adding this usecase to the list */
1705 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1706 check_and_set_hdmi_channels(adev, out->config.channels);
1707
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001708 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001710 audio_extn_perf_lock_acquire();
1711
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001712 select_devices(adev, out->usecase);
1713
Eric Laurent0499d4f2014-08-25 22:39:29 -05001714 audio_extn_extspk_update(adev->extspk);
1715
Andy Hung31aca912014-03-20 17:14:59 -07001716 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001717 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001718 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1719 out->pcm = NULL;
1720 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1721 COMPRESS_IN, &out->compr_config);
1722 if (out->compr && !is_compress_ready(out->compr)) {
1723 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1724 compress_close(out->compr);
1725 out->compr = NULL;
1726 ret = -EIO;
1727 goto error_open;
1728 }
1729 if (out->offload_callback)
1730 compress_nonblock(out->compr, out->non_blocking);
1731
1732 if (adev->visualizer_start_output != NULL)
1733 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1734 if (adev->offload_effects_start_output != NULL)
1735 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1736 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001737 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001738 ALOGE("%s: pcm stream not ready", __func__);
1739 goto error_open;
1740 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001741 ret = pcm_start(out->pcm);
1742 if (ret < 0) {
1743 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1744 goto error_open;
1745 }
1746 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001747 unsigned int flags = PCM_OUT;
1748 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001749
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001750 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1751 flags |= PCM_MMAP | PCM_NOIRQ;
1752 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001753 } else if (out->realtime) {
1754 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001755 } else
1756 flags |= PCM_MONOTONIC;
1757
1758 while (1) {
1759 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1760 flags, &out->config);
1761 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1762 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1763 if (out->pcm != NULL) {
1764 pcm_close(out->pcm);
1765 out->pcm = NULL;
1766 }
1767 if (pcm_open_retry_count-- == 0) {
1768 ret = -EIO;
1769 goto error_open;
1770 }
1771 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1772 continue;
1773 }
1774 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001775 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001776 ALOGV("%s: pcm_prepare", __func__);
1777 if (pcm_is_ready(out->pcm)) {
1778 ret = pcm_prepare(out->pcm);
1779 if (ret < 0) {
1780 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1781 pcm_close(out->pcm);
1782 out->pcm = NULL;
1783 goto error_open;
1784 }
1785 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001786 if (out->realtime) {
1787 ret = pcm_start(out->pcm);
1788 if (ret < 0) {
1789 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1790 pcm_close(out->pcm);
1791 out->pcm = NULL;
1792 goto error_open;
1793 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001794 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001795 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001796 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001797 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001798 audio_extn_tfa_98xx_enable_speaker();
1799
Eric Laurent994a6932013-07-17 11:51:42 -07001800 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001801 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001802error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001803 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001805error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001806 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807}
1808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809static int check_input_parameters(uint32_t sample_rate,
1810 audio_format_t format,
1811 int channel_count)
1812{
vivek mehta4ed66e62016-04-15 23:33:34 -07001813 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001814 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1815 return -EINVAL;
1816 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001817
vivek mehtadae44712015-07-27 14:13:18 -07001818 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001819 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001820 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1821 return -EINVAL;
1822 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823
1824 switch (sample_rate) {
1825 case 8000:
1826 case 11025:
1827 case 12000:
1828 case 16000:
1829 case 22050:
1830 case 24000:
1831 case 32000:
1832 case 44100:
1833 case 48000:
1834 break;
1835 default:
vivek mehtadae44712015-07-27 14:13:18 -07001836 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837 return -EINVAL;
1838 }
1839
1840 return 0;
1841}
1842
1843static size_t get_input_buffer_size(uint32_t sample_rate,
1844 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001845 int channel_count,
1846 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847{
1848 size_t size = 0;
1849
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001850 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1851 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001853 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001854 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001855 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001856
1857 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858
Glenn Kasten4f993392014-05-14 07:30:48 -07001859 /* make sure the size is multiple of 32 bytes
1860 * At 48 kHz mono 16-bit PCM:
1861 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1862 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1863 */
1864 size += 0x1f;
1865 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001866
1867 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001868}
1869
1870static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1871{
1872 struct stream_out *out = (struct stream_out *)stream;
1873
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001874 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001875}
1876
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001877static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001878{
1879 return -ENOSYS;
1880}
1881
1882static size_t out_get_buffer_size(const struct audio_stream *stream)
1883{
1884 struct stream_out *out = (struct stream_out *)stream;
1885
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001886 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1887 return out->compr_config.fragment_size;
1888 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001889 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001890 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891}
1892
1893static uint32_t out_get_channels(const struct audio_stream *stream)
1894{
1895 struct stream_out *out = (struct stream_out *)stream;
1896
1897 return out->channel_mask;
1898}
1899
1900static audio_format_t out_get_format(const struct audio_stream *stream)
1901{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001902 struct stream_out *out = (struct stream_out *)stream;
1903
1904 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001905}
1906
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001907static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001908{
1909 return -ENOSYS;
1910}
1911
1912static int out_standby(struct audio_stream *stream)
1913{
1914 struct stream_out *out = (struct stream_out *)stream;
1915 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001916 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001917
Eric Laurent994a6932013-07-17 11:51:42 -07001918 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001919 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001920
Eric Laurenta1478072015-09-21 17:21:52 -07001921 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001922 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001923 if (adev->adm_deregister_stream)
1924 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001925 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001927 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1928 if (out->pcm) {
1929 pcm_close(out->pcm);
1930 out->pcm = NULL;
1931 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001932 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001933 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08001934 out->playback_started = false;
1935 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001936 } else {
1937 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001938 out->gapless_mdata.encoder_delay = 0;
1939 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001940 if (out->compr != NULL) {
1941 compress_close(out->compr);
1942 out->compr = NULL;
1943 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001944 }
Phil Burkbc991042017-02-24 08:06:44 -08001945 if (do_stop) {
1946 stop_output_stream(out);
1947 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001948 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949 }
1950 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001951 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001952 return 0;
1953}
1954
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001955static int out_on_error(struct audio_stream *stream)
1956{
1957 struct stream_out *out = (struct stream_out *)stream;
1958 struct audio_device *adev = out->dev;
1959 bool do_standby = false;
1960
1961 lock_output_stream(out);
1962 if (!out->standby) {
1963 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1964 stop_compressed_output_l(out);
1965 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1966 } else
1967 do_standby = true;
1968 }
1969 pthread_mutex_unlock(&out->lock);
1970
1971 if (do_standby)
1972 return out_standby(&out->stream.common);
1973
1974 return 0;
1975}
1976
Andy Hung7401c7c2016-09-21 12:41:21 -07001977static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978{
Andy Hung7401c7c2016-09-21 12:41:21 -07001979 struct stream_out *out = (struct stream_out *)stream;
1980
1981 // We try to get the lock for consistency,
1982 // but it isn't necessary for these variables.
1983 // If we're not in standby, we may be blocked on a write.
1984 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1985 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1986 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1987
1988 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07001989 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07001990 }
Andy Hunga452b0a2017-03-15 14:51:15 -07001991
1992 // dump error info
1993 (void)error_log_dump(
1994 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07001995 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07001996 (void)power_log_dump(
1997 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001998 return 0;
1999}
2000
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002001static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2002{
2003 int ret = 0;
2004 char value[32];
2005 struct compr_gapless_mdata tmp_mdata;
2006
2007 if (!out || !parms) {
2008 return -EINVAL;
2009 }
2010
2011 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2012 if (ret >= 0) {
2013 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2014 } else {
2015 return -EINVAL;
2016 }
2017
2018 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2019 if (ret >= 0) {
2020 tmp_mdata.encoder_padding = atoi(value);
2021 } else {
2022 return -EINVAL;
2023 }
2024
2025 out->gapless_mdata = tmp_mdata;
2026 out->send_new_metadata = 1;
2027 ALOGV("%s new encoder delay %u and padding %u", __func__,
2028 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2029
2030 return 0;
2031}
2032
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002033static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2034{
2035 return out == adev->primary_output || out == adev->voice_tx_output;
2036}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002037
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2039{
2040 struct stream_out *out = (struct stream_out *)stream;
2041 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002042 struct audio_usecase *usecase;
2043 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044 struct str_parms *parms;
2045 char value[32];
2046 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002047 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002048 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049
Eric Laurent2e140aa2016-06-30 17:14:46 -07002050 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002051 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052 parms = str_parms_create_str(kvpairs);
2053 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2054 if (ret >= 0) {
2055 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002056 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002057 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002059 /*
2060 * When HDMI cable is unplugged the music playback is paused and
2061 * the policy manager sends routing=0. But the audioflinger
2062 * continues to write data until standby time (3sec).
2063 * As the HDMI core is turned off, the write gets blocked.
2064 * Avoid this by routing audio to speaker until standby.
2065 */
2066 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2067 val == AUDIO_DEVICE_NONE) {
2068 val = AUDIO_DEVICE_OUT_SPEAKER;
2069 }
2070
2071 /*
2072 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002073 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002074 * the select_devices(). But how do we undo this?
2075 *
2076 * For example, music playback is active on headset (deep-buffer usecase)
2077 * and if we go to ringtones and select a ringtone, low-latency usecase
2078 * will be started on headset+speaker. As we can't enable headset+speaker
2079 * and headset devices at the same time, select_devices() switches the music
2080 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2081 * So when the ringtone playback is completed, how do we undo the same?
2082 *
2083 * We are relying on the out_set_parameters() call on deep-buffer output,
2084 * once the ringtone playback is ended.
2085 * NOTE: We should not check if the current devices are same as new devices.
2086 * Because select_devices() must be called to switch back the music
2087 * playback to headset.
2088 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002089 audio_devices_t new_dev = val;
2090 if (new_dev != AUDIO_DEVICE_NONE) {
2091 bool same_dev = out->devices == new_dev;
2092 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002093
Eric Laurenta7657192014-10-09 21:09:33 -07002094 if (output_drives_call(adev, out)) {
2095 if (!voice_is_in_call(adev)) {
2096 if (adev->mode == AUDIO_MODE_IN_CALL) {
2097 adev->current_call_output = out;
2098 ret = voice_start_call(adev);
2099 }
2100 } else {
2101 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002102 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002103 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002104 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002105
2106 if (!out->standby) {
2107 if (!same_dev) {
2108 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002109 // inform adm before actual routing to prevent glitches.
2110 if (adev->adm_on_routing_change) {
2111 adev->adm_on_routing_change(adev->adm_data,
2112 out->handle);
2113 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002114 }
2115 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002116 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002117 }
2118
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002119 }
2120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002122 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002123
2124 /*handles device and call state changes*/
2125 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002126 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002127
2128 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2129 parse_compress_metadata(out, parms);
2130 }
2131
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002132 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002133 ALOGV("%s: exit: code(%d)", __func__, status);
2134 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002135}
2136
2137static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2138{
2139 struct stream_out *out = (struct stream_out *)stream;
2140 struct str_parms *query = str_parms_create_str(keys);
2141 char *str;
2142 char value[256];
2143 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002144 bool replied = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002145 size_t i, j;
2146 int ret;
2147 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002148 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2150 if (ret >= 0) {
2151 value[0] = '\0';
2152 i = 0;
2153 while (out->supported_channel_masks[i] != 0) {
2154 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2155 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2156 if (!first) {
2157 strcat(value, "|");
2158 }
2159 strcat(value, out_channels_name_to_enum_table[j].name);
2160 first = false;
2161 break;
2162 }
2163 }
2164 i++;
2165 }
2166 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002167 replied = true;
2168 }
2169
2170 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2171 if (ret >= 0) {
2172 value[0] = '\0';
2173 switch (out->supported_formats[0]) {
2174 case AUDIO_FORMAT_PCM_16_BIT:
2175 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2176 break;
2177 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2178 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2179 break;
2180 case AUDIO_FORMAT_PCM_32_BIT:
2181 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2182 break;
2183 default:
2184 ALOGE("%s: unsupported format %#x", __func__,
2185 out->supported_formats[0]);
2186 break;
2187 }
2188 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2189 replied = true;
2190 }
2191
2192 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2193 value, sizeof(value));
2194 if (ret >= 0) {
2195 value[0] = '\0';
2196 i=0;
2197 int cursor = 0;
2198 while (out->supported_sample_rates[i]) {
2199 int avail = sizeof(value) - cursor;
2200 ret = snprintf(value + cursor, avail, "%s%d",
2201 cursor > 0 ? "|" : "",
2202 out->supported_sample_rates[i]);
2203 if (ret < 0 || ret >= avail) {
2204 // if cursor is at the last element of the array
2205 // overwrite with \0 is duplicate work as
2206 // snprintf already put a \0 in place.
2207 // else
2208 // we had space to write the '|' at value[cursor]
2209 // (which will be overwritten) or no space to fill
2210 // the first element (=> cursor == 0)
2211 value[cursor] = '\0';
2212 break;
2213 }
2214 cursor += ret;
2215 ++i;
2216 }
2217 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2218 value);
2219 replied = true;
2220 }
2221
2222 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223 str = str_parms_to_str(reply);
2224 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002225 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226 }
2227 str_parms_destroy(query);
2228 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002229 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230 return str;
2231}
2232
2233static uint32_t out_get_latency(const struct audio_stream_out *stream)
2234{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002235 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236 struct stream_out *out = (struct stream_out *)stream;
2237
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002238 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2239 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002240 else if ((out->realtime) ||
2241 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002242 // since the buffer won't be filled up faster than realtime,
2243 // return a smaller number
2244 period_ms = (out->af_period_multiplier * out->config.period_size *
2245 1000) / (out->config.rate);
2246 hw_delay = platform_render_latency(out->usecase)/1000;
2247 return period_ms + hw_delay;
2248 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002249
2250 return (out->config.period_count * out->config.period_size * 1000) /
2251 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002252}
2253
2254static int out_set_volume(struct audio_stream_out *stream, float left,
2255 float right)
2256{
Eric Laurenta9024de2013-04-04 09:19:12 -07002257 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002258 int volume[2];
2259
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002260 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002261 /* only take left channel into account: the API is for stereo anyway */
2262 out->muted = (left == 0.0f);
2263 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002264 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2265 const char *mixer_ctl_name = "Compress Playback Volume";
2266 struct audio_device *adev = out->dev;
2267 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002268 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2269 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002270 /* try with the control based on device id */
2271 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2272 PCM_PLAYBACK);
2273 char ctl_name[128] = {0};
2274 snprintf(ctl_name, sizeof(ctl_name),
2275 "Compress Playback %d Volume", pcm_device_id);
2276 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2277 if (!ctl) {
2278 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2279 return -EINVAL;
2280 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002281 }
2282 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2283 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2284 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2285 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002286 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002287
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002288 return -ENOSYS;
2289}
2290
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002291// note: this call is safe only if the stream_cb is
2292// removed first in close_output_stream (as is done now).
2293static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2294{
2295 if (!stream || !parms)
2296 return;
2297
2298 struct stream_out *out = (struct stream_out *)stream;
2299 struct audio_device *adev = out->dev;
2300
2301 card_status_t status;
2302 int card;
2303 if (parse_snd_card_status(parms, &card, &status) < 0)
2304 return;
2305
2306 pthread_mutex_lock(&adev->lock);
2307 bool valid_cb = (card == adev->snd_card);
2308 pthread_mutex_unlock(&adev->lock);
2309
2310 if (!valid_cb)
2311 return;
2312
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002313 lock_output_stream(out);
2314 if (out->card_status != status)
2315 out->card_status = status;
2316 pthread_mutex_unlock(&out->lock);
2317
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002318 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2319 use_case_table[out->usecase],
2320 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2321
2322 if (status == CARD_STATUS_OFFLINE)
2323 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002324
2325 return;
2326}
2327
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002328#ifdef NO_AUDIO_OUT
2329static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002330 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002331{
2332 struct stream_out *out = (struct stream_out *)stream;
2333
2334 /* No Output device supported other than BT for playback.
2335 * Sleep for the amount of buffer duration
2336 */
Eric Laurenta1478072015-09-21 17:21:52 -07002337 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002338 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2339 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002340 out_get_sample_rate(&out->stream.common));
2341 pthread_mutex_unlock(&out->lock);
2342 return bytes;
2343}
2344#endif
2345
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2347 size_t bytes)
2348{
2349 struct stream_out *out = (struct stream_out *)stream;
2350 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002351 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002352 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353
Eric Laurenta1478072015-09-21 17:21:52 -07002354 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002355 // this is always nonzero
2356 const int frame_size = audio_stream_out_frame_size(stream);
2357
Eric Laurent0e46adf2016-12-16 12:49:24 -08002358 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2359 error_code = ERROR_CODE_WRITE;
2360 goto exit;
2361 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002363 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002364 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002365 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002366 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002367 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002369 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002370 goto exit;
2371 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002372
2373 if (last_known_cal_step != -1) {
2374 ALOGD("%s: retry previous failed cal level set", __func__);
2375 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2376 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002377 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002378
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002380 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002381 if (out->send_new_metadata) {
2382 ALOGVV("send new gapless metadata");
2383 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2384 out->send_new_metadata = 0;
2385 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002386 unsigned int avail;
2387 struct timespec tstamp;
2388 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2389 /* Do not limit write size if the available frames count is unknown */
2390 if (ret != 0) {
2391 avail = bytes;
2392 }
2393 if (avail == 0) {
2394 ret = 0;
2395 } else {
2396 if (avail > bytes) {
2397 avail = bytes;
2398 }
2399 ret = compress_write(out->compr, buffer, avail);
2400 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2401 __func__, avail, ret);
2402 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002403
Eric Laurent6e895242013-09-05 16:10:57 -07002404 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002405 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2406 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002407 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002408 compress_start(out->compr);
2409 out->playback_started = 1;
2410 out->offload_state = OFFLOAD_STATE_PLAYING;
2411 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002412 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002413 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002414 } else {
2415 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002416 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002417 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002418 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002419 return ret;
2420 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002421 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002422 if (out->pcm) {
2423 if (out->muted)
2424 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002425
Eric Laurent0e46adf2016-12-16 12:49:24 -08002426 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002427
Haynes Mathew George03c40102016-01-29 17:57:48 -08002428 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2429 out->config.rate;
2430 request_out_focus(out, ns);
2431
2432 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2433 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002434 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002435 else
2436 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002437
Haynes Mathew George03c40102016-01-29 17:57:48 -08002438 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002439 } else {
2440 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002441 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002442 }
2443
2444exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002445 // For PCM we always consume the buffer and return #bytes regardless of ret.
2446 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2447 out->written += bytes / (out->config.channels * sizeof(short));
2448 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002449 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002450
2451 // only get time if needed for logging, as it is a system call on 32 bit devices.
2452 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2453 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2454 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002455
Andy Hung7401c7c2016-09-21 12:41:21 -07002456 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002457 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002458 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2459 ALOGE_IF(out->pcm != NULL,
2460 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hungfc044e12017-03-20 09:24:22 -07002461 sleeptime_us = bytes * 1000000LL / frame_size /
Andy Hung7401c7c2016-09-21 12:41:21 -07002462 out_get_sample_rate(&out->stream.common);
2463 // usleep not guaranteed for values over 1 second but we don't limit here.
2464 }
2465 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002466
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002467 pthread_mutex_unlock(&out->lock);
2468
2469 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002470 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002471 if (sleeptime_us != 0)
2472 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002473 } else {
2474 // only log if the data is properly written (out->power_log may be null)
2475 power_log_log(out->power_log, buffer, bytes / frame_size, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476 }
2477 return bytes;
2478}
2479
2480static int out_get_render_position(const struct audio_stream_out *stream,
2481 uint32_t *dsp_frames)
2482{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002483 struct stream_out *out = (struct stream_out *)stream;
2484 *dsp_frames = 0;
2485 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002486 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002487 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002488 unsigned long frames = 0;
2489 // TODO: check return value
2490 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2491 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002492 ALOGVV("%s rendered frames %d sample_rate %d",
2493 __func__, *dsp_frames, out->sample_rate);
2494 }
2495 pthread_mutex_unlock(&out->lock);
2496 return 0;
2497 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002498 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499}
2500
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002501static int out_add_audio_effect(const struct audio_stream *stream __unused,
2502 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503{
2504 return 0;
2505}
2506
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002507static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2508 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509{
2510 return 0;
2511}
2512
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002513static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2514 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002516 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517}
2518
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002519static int out_get_presentation_position(const struct audio_stream_out *stream,
2520 uint64_t *frames, struct timespec *timestamp)
2521{
2522 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002523 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002524 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002525
Eric Laurenta1478072015-09-21 17:21:52 -07002526 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002527
Eric Laurent949a0892013-09-20 09:20:13 -07002528 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2529 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002530 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002531 compress_get_tstamp(out->compr, &dsp_frames,
2532 &out->sample_rate);
2533 ALOGVV("%s rendered frames %ld sample_rate %d",
2534 __func__, dsp_frames, out->sample_rate);
2535 *frames = dsp_frames;
2536 ret = 0;
2537 /* this is the best we can do */
2538 clock_gettime(CLOCK_MONOTONIC, timestamp);
2539 }
2540 } else {
2541 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002542 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002543 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2544 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002545 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002546 // This adjustment accounts for buffering after app processor.
2547 // It is based on estimated DSP latency per use case, rather than exact.
2548 signed_frames -=
2549 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2550
Eric Laurent949a0892013-09-20 09:20:13 -07002551 // It would be unusual for this value to be negative, but check just in case ...
2552 if (signed_frames >= 0) {
2553 *frames = signed_frames;
2554 ret = 0;
2555 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002556 }
2557 }
2558 }
2559
2560 pthread_mutex_unlock(&out->lock);
2561
2562 return ret;
2563}
2564
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002565static int out_set_callback(struct audio_stream_out *stream,
2566 stream_callback_t callback, void *cookie)
2567{
2568 struct stream_out *out = (struct stream_out *)stream;
2569
2570 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002571 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002572 out->offload_callback = callback;
2573 out->offload_cookie = cookie;
2574 pthread_mutex_unlock(&out->lock);
2575 return 0;
2576}
2577
2578static int out_pause(struct audio_stream_out* stream)
2579{
2580 struct stream_out *out = (struct stream_out *)stream;
2581 int status = -ENOSYS;
2582 ALOGV("%s", __func__);
2583 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002584 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002585 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2586 status = compress_pause(out->compr);
2587 out->offload_state = OFFLOAD_STATE_PAUSED;
2588 }
2589 pthread_mutex_unlock(&out->lock);
2590 }
2591 return status;
2592}
2593
2594static int out_resume(struct audio_stream_out* stream)
2595{
2596 struct stream_out *out = (struct stream_out *)stream;
2597 int status = -ENOSYS;
2598 ALOGV("%s", __func__);
2599 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2600 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002601 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002602 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2603 status = compress_resume(out->compr);
2604 out->offload_state = OFFLOAD_STATE_PLAYING;
2605 }
2606 pthread_mutex_unlock(&out->lock);
2607 }
2608 return status;
2609}
2610
2611static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2612{
2613 struct stream_out *out = (struct stream_out *)stream;
2614 int status = -ENOSYS;
2615 ALOGV("%s", __func__);
2616 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002617 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002618 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2619 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2620 else
2621 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2622 pthread_mutex_unlock(&out->lock);
2623 }
2624 return status;
2625}
2626
2627static int out_flush(struct audio_stream_out* stream)
2628{
2629 struct stream_out *out = (struct stream_out *)stream;
2630 ALOGV("%s", __func__);
2631 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002632 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002633 stop_compressed_output_l(out);
2634 pthread_mutex_unlock(&out->lock);
2635 return 0;
2636 }
2637 return -ENOSYS;
2638}
2639
Eric Laurent0e46adf2016-12-16 12:49:24 -08002640static int out_stop(const struct audio_stream_out* stream)
2641{
2642 struct stream_out *out = (struct stream_out *)stream;
2643 struct audio_device *adev = out->dev;
2644 int ret = -ENOSYS;
2645
2646 ALOGV("%s", __func__);
2647 pthread_mutex_lock(&adev->lock);
2648 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2649 out->playback_started && out->pcm != NULL) {
2650 pcm_stop(out->pcm);
2651 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002652 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002653 }
2654 pthread_mutex_unlock(&adev->lock);
2655 return ret;
2656}
2657
2658static int out_start(const struct audio_stream_out* stream)
2659{
2660 struct stream_out *out = (struct stream_out *)stream;
2661 struct audio_device *adev = out->dev;
2662 int ret = -ENOSYS;
2663
2664 ALOGV("%s", __func__);
2665 pthread_mutex_lock(&adev->lock);
2666 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2667 !out->playback_started && out->pcm != NULL) {
2668 ret = start_output_stream(out);
2669 if (ret == 0) {
2670 out->playback_started = true;
2671 }
2672 }
2673 pthread_mutex_unlock(&adev->lock);
2674 return ret;
2675}
2676
Phil Burkbc991042017-02-24 08:06:44 -08002677/*
2678 * Modify config->period_count based on min_size_frames
2679 */
2680static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2681{
2682 int periodCountRequested = (min_size_frames + config->period_size - 1)
2683 / config->period_size;
2684 int periodCount = MMAP_PERIOD_COUNT_MIN;
2685
2686 ALOGV("%s original config.period_size = %d config.period_count = %d",
2687 __func__, config->period_size, config->period_count);
2688
2689 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2690 periodCount *= 2;
2691 }
2692 config->period_count = periodCount;
2693
2694 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2695}
2696
Eric Laurent0e46adf2016-12-16 12:49:24 -08002697static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2698 int32_t min_size_frames,
2699 struct audio_mmap_buffer_info *info)
2700{
2701 struct stream_out *out = (struct stream_out *)stream;
2702 struct audio_device *adev = out->dev;
2703 int ret = 0;
2704 unsigned int offset1;
2705 unsigned int frames1;
2706 const char *step = "";
2707
2708 ALOGV("%s", __func__);
2709 pthread_mutex_lock(&adev->lock);
2710
2711 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002712 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002713 ret = -EINVAL;
2714 goto exit;
2715 }
2716 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002717 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002718 ret = -ENOSYS;
2719 goto exit;
2720 }
2721 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2722 if (out->pcm_device_id < 0) {
2723 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2724 __func__, out->pcm_device_id, out->usecase);
2725 ret = -EINVAL;
2726 goto exit;
2727 }
Phil Burkbc991042017-02-24 08:06:44 -08002728
2729 adjust_mmap_period_count(&out->config, min_size_frames);
2730
Eric Laurent0e46adf2016-12-16 12:49:24 -08002731 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2732 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2733 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2734 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2735 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2736 step = "open";
2737 ret = -ENODEV;
2738 goto exit;
2739 }
2740 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2741 if (ret < 0) {
2742 step = "begin";
2743 goto exit;
2744 }
2745 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2746 info->burst_size_frames = out->config.period_size;
2747 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2748
2749 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2750 info->buffer_size_frames));
2751
2752 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2753 if (ret < 0) {
2754 step = "commit";
2755 goto exit;
2756 }
Phil Burkbc991042017-02-24 08:06:44 -08002757
2758 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002759 ret = 0;
2760
2761 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2762 __func__, info->shared_memory_address, info->buffer_size_frames);
2763
2764exit:
2765 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002766 if (out->pcm == NULL) {
2767 ALOGE("%s: %s - %d", __func__, step, ret);
2768 } else {
2769 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002770 pcm_close(out->pcm);
2771 out->pcm = NULL;
2772 }
2773 }
2774 pthread_mutex_unlock(&adev->lock);
2775 return ret;
2776}
2777
2778static int out_get_mmap_position(const struct audio_stream_out *stream,
2779 struct audio_mmap_position *position)
2780{
2781 struct stream_out *out = (struct stream_out *)stream;
2782 ALOGVV("%s", __func__);
2783 if (position == NULL) {
2784 return -EINVAL;
2785 }
2786 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2787 return -ENOSYS;
2788 }
2789 if (out->pcm == NULL) {
2790 return -ENOSYS;
2791 }
2792
2793 struct timespec ts = { 0, 0 };
2794 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2795 if (ret < 0) {
2796 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2797 return ret;
2798 }
Andy Hungfc044e12017-03-20 09:24:22 -07002799 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002800 return 0;
2801}
2802
2803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804/** audio_stream_in implementation **/
2805static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2806{
2807 struct stream_in *in = (struct stream_in *)stream;
2808
2809 return in->config.rate;
2810}
2811
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002812static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813{
2814 return -ENOSYS;
2815}
2816
2817static size_t in_get_buffer_size(const struct audio_stream *stream)
2818{
2819 struct stream_in *in = (struct stream_in *)stream;
2820
Haynes Mathew George03c40102016-01-29 17:57:48 -08002821 return in->config.period_size * in->af_period_multiplier *
2822 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823}
2824
2825static uint32_t in_get_channels(const struct audio_stream *stream)
2826{
2827 struct stream_in *in = (struct stream_in *)stream;
2828
2829 return in->channel_mask;
2830}
2831
vivek mehta4ed66e62016-04-15 23:33:34 -07002832static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002833{
vivek mehta4ed66e62016-04-15 23:33:34 -07002834 struct stream_in *in = (struct stream_in *)stream;
2835 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002836}
2837
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002838static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839{
2840 return -ENOSYS;
2841}
2842
2843static int in_standby(struct audio_stream *stream)
2844{
2845 struct stream_in *in = (struct stream_in *)stream;
2846 struct audio_device *adev = in->dev;
2847 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002848 bool do_stop = true;
2849
Eric Laurent994a6932013-07-17 11:51:42 -07002850 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002851
2852 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002853
2854 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002855 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002856 audio_extn_sound_trigger_stop_lab(in);
2857 in->standby = true;
2858 }
2859
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002861 if (adev->adm_deregister_stream)
2862 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2863
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002864 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002865 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002866 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002867 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002868 in->capture_started = false;
2869 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002870 if (in->pcm) {
2871 pcm_close(in->pcm);
2872 in->pcm = NULL;
2873 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002874 adev->enable_voicerx = false;
2875 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002876 if (do_stop) {
2877 status = stop_input_stream(in);
2878 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002879 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880 }
2881 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002882 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883 return status;
2884}
2885
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002886static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887{
2888 return 0;
2889}
2890
2891static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2892{
2893 struct stream_in *in = (struct stream_in *)stream;
2894 struct audio_device *adev = in->dev;
2895 struct str_parms *parms;
2896 char *str;
2897 char value[32];
2898 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002899 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002900
Eric Laurent994a6932013-07-17 11:51:42 -07002901 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002902 parms = str_parms_create_str(kvpairs);
2903
2904 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2905
Eric Laurenta1478072015-09-21 17:21:52 -07002906 lock_input_stream(in);
2907
Eric Laurent150dbfe2013-02-27 14:31:02 -08002908 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002909 if (ret >= 0) {
2910 val = atoi(value);
2911 /* no audio source uses val == 0 */
2912 if ((in->source != val) && (val != 0)) {
2913 in->source = val;
2914 }
2915 }
2916
2917 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002918
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002919 if (ret >= 0) {
2920 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002921 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922 in->device = val;
2923 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002924 if (!in->standby) {
2925 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002926 // inform adm before actual routing to prevent glitches.
2927 if (adev->adm_on_routing_change) {
2928 adev->adm_on_routing_change(adev->adm_data,
2929 in->capture_handle);
2930 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002931 select_devices(adev, in->usecase);
2932 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002933 }
2934 }
2935
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002936 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002937 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938
2939 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002940 ALOGV("%s: exit: status(%d)", __func__, status);
2941 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942}
2943
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002944static char* in_get_parameters(const struct audio_stream *stream __unused,
2945 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946{
2947 return strdup("");
2948}
2949
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002950static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002951{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002952 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002953}
2954
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002955static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2956{
2957 if (!stream || !parms)
2958 return;
2959
2960 struct stream_in *in = (struct stream_in *)stream;
2961 struct audio_device *adev = in->dev;
2962
2963 card_status_t status;
2964 int card;
2965 if (parse_snd_card_status(parms, &card, &status) < 0)
2966 return;
2967
2968 pthread_mutex_lock(&adev->lock);
2969 bool valid_cb = (card == adev->snd_card);
2970 pthread_mutex_unlock(&adev->lock);
2971
2972 if (!valid_cb)
2973 return;
2974
2975 lock_input_stream(in);
2976 if (in->card_status != status)
2977 in->card_status = status;
2978 pthread_mutex_unlock(&in->lock);
2979
2980 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2981 use_case_table[in->usecase],
2982 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2983
2984 // a better solution would be to report error back to AF and let
2985 // it put the stream to standby
2986 if (status == CARD_STATUS_OFFLINE)
2987 in_standby(&in->stream.common);
2988
2989 return;
2990}
2991
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2993 size_t bytes)
2994{
2995 struct stream_in *in = (struct stream_in *)stream;
2996 struct audio_device *adev = in->dev;
2997 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002998 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999
Eric Laurenta1478072015-09-21 17:21:52 -07003000 lock_input_stream(in);
3001
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003002 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003003 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003004 /* Read from sound trigger HAL */
3005 audio_extn_sound_trigger_read(in, buffer, bytes);
3006 pthread_mutex_unlock(&in->lock);
3007 return bytes;
3008 }
3009
Eric Laurent0e46adf2016-12-16 12:49:24 -08003010 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3011 ret = -ENOSYS;
3012 goto exit;
3013 }
3014
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003016 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003017 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003018 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020 goto exit;
3021 }
3022 in->standby = 0;
3023 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024
Haynes Mathew George03c40102016-01-29 17:57:48 -08003025 //what's the duration requested by the client?
3026 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3027 in->config.rate;
3028 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003029
Haynes Mathew George03c40102016-01-29 17:57:48 -08003030 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003032 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003033 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003034 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003035 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003036 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003037 if (ret < 0) {
3038 ALOGE("Failed to read w/err %s", strerror(errno));
3039 ret = -errno;
3040 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003041 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3042 if (bytes % 4 == 0) {
3043 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3044 int_buf_stream = buffer;
3045 for (size_t itt=0; itt < bytes/4 ; itt++) {
3046 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003047 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003048 } else {
3049 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3050 ret = -EINVAL;
3051 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003052 }
3053 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003054 }
3055
Haynes Mathew George03c40102016-01-29 17:57:48 -08003056 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003057
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058 /*
3059 * Instead of writing zeroes here, we could trust the hardware
3060 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003061 * 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 -08003062 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003063 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003064 memset(buffer, 0, bytes);
3065
3066exit:
3067 pthread_mutex_unlock(&in->lock);
3068
3069 if (ret != 0) {
3070 in_standby(&in->stream.common);
3071 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07003072 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003074 memset(buffer, 0, bytes); // clear return data
3075 }
3076 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08003077 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078 }
3079 return bytes;
3080}
3081
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003082static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083{
3084 return 0;
3085}
3086
Andy Hung6ebe5962016-01-15 17:46:57 -08003087static int in_get_capture_position(const struct audio_stream_in *stream,
3088 int64_t *frames, int64_t *time)
3089{
3090 if (stream == NULL || frames == NULL || time == NULL) {
3091 return -EINVAL;
3092 }
3093 struct stream_in *in = (struct stream_in *)stream;
3094 int ret = -ENOSYS;
3095
3096 lock_input_stream(in);
3097 if (in->pcm) {
3098 struct timespec timestamp;
3099 unsigned int avail;
3100 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3101 *frames = in->frames_read + avail;
3102 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3103 ret = 0;
3104 }
3105 }
3106 pthread_mutex_unlock(&in->lock);
3107 return ret;
3108}
3109
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003110static int add_remove_audio_effect(const struct audio_stream *stream,
3111 effect_handle_t effect,
3112 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003114 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003115 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003116 int status = 0;
3117 effect_descriptor_t desc;
3118
3119 status = (*effect)->get_descriptor(effect, &desc);
3120 if (status != 0)
3121 return status;
3122
Eric Laurenta1478072015-09-21 17:21:52 -07003123 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003124 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003125 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003126 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003127 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003128 in->enable_aec != enable &&
3129 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3130 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003131 if (!enable)
3132 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003133 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3134 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3135 adev->enable_voicerx = enable;
3136 struct audio_usecase *usecase;
3137 struct listnode *node;
3138 list_for_each(node, &adev->usecase_list) {
3139 usecase = node_to_item(node, struct audio_usecase, list);
3140 if (usecase->type == PCM_PLAYBACK) {
3141 select_devices(adev, usecase->id);
3142 break;
3143 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003144 }
3145 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003146 if (!in->standby)
3147 select_devices(in->dev, in->usecase);
3148 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003149 if (in->enable_ns != enable &&
3150 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3151 in->enable_ns = enable;
3152 if (!in->standby)
3153 select_devices(in->dev, in->usecase);
3154 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003155 pthread_mutex_unlock(&in->dev->lock);
3156 pthread_mutex_unlock(&in->lock);
3157
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 return 0;
3159}
3160
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003161static int in_add_audio_effect(const struct audio_stream *stream,
3162 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003163{
Eric Laurent994a6932013-07-17 11:51:42 -07003164 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003165 return add_remove_audio_effect(stream, effect, true);
3166}
3167
3168static int in_remove_audio_effect(const struct audio_stream *stream,
3169 effect_handle_t effect)
3170{
Eric Laurent994a6932013-07-17 11:51:42 -07003171 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003172 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003173}
3174
Eric Laurent0e46adf2016-12-16 12:49:24 -08003175static int in_stop(const struct audio_stream_in* stream)
3176{
3177 struct stream_in *in = (struct stream_in *)stream;
3178 struct audio_device *adev = in->dev;
3179
3180 int ret = -ENOSYS;
3181 ALOGV("%s", __func__);
3182 pthread_mutex_lock(&adev->lock);
3183 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3184 in->capture_started && in->pcm != NULL) {
3185 pcm_stop(in->pcm);
3186 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003187 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003188 }
3189 pthread_mutex_unlock(&adev->lock);
3190 return ret;
3191}
3192
3193static int in_start(const struct audio_stream_in* stream)
3194{
3195 struct stream_in *in = (struct stream_in *)stream;
3196 struct audio_device *adev = in->dev;
3197 int ret = -ENOSYS;
3198
3199 ALOGV("%s in %p", __func__, in);
3200 pthread_mutex_lock(&adev->lock);
3201 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3202 !in->capture_started && in->pcm != NULL) {
3203 if (!in->capture_started) {
3204 ret = start_input_stream(in);
3205 if (ret == 0) {
3206 in->capture_started = true;
3207 }
3208 }
3209 }
3210 pthread_mutex_unlock(&adev->lock);
3211 return ret;
3212}
3213
3214static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3215 int32_t min_size_frames,
3216 struct audio_mmap_buffer_info *info)
3217{
3218 struct stream_in *in = (struct stream_in *)stream;
3219 struct audio_device *adev = in->dev;
3220 int ret = 0;
3221 unsigned int offset1;
3222 unsigned int frames1;
3223 const char *step = "";
3224
3225 pthread_mutex_lock(&adev->lock);
3226 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003227
Eric Laurent0e46adf2016-12-16 12:49:24 -08003228 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003229 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003230 ret = -EINVAL;
3231 goto exit;
3232 }
3233 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003234 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003235 ALOGV("%s in %p", __func__, in);
3236 ret = -ENOSYS;
3237 goto exit;
3238 }
3239 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3240 if (in->pcm_device_id < 0) {
3241 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3242 __func__, in->pcm_device_id, in->usecase);
3243 ret = -EINVAL;
3244 goto exit;
3245 }
Phil Burkbc991042017-02-24 08:06:44 -08003246
3247 adjust_mmap_period_count(&in->config, min_size_frames);
3248
Eric Laurent0e46adf2016-12-16 12:49:24 -08003249 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3250 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3251 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3252 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3253 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3254 step = "open";
3255 ret = -ENODEV;
3256 goto exit;
3257 }
3258
3259 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3260 if (ret < 0) {
3261 step = "begin";
3262 goto exit;
3263 }
3264 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3265 info->burst_size_frames = in->config.period_size;
3266 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3267
3268 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3269 info->buffer_size_frames));
3270
3271 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3272 if (ret < 0) {
3273 step = "commit";
3274 goto exit;
3275 }
3276
Phil Burkbc991042017-02-24 08:06:44 -08003277 in->standby = false;
3278 ret = 0;
3279
Eric Laurent0e46adf2016-12-16 12:49:24 -08003280 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3281 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003282
3283exit:
3284 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003285 if (in->pcm == NULL) {
3286 ALOGE("%s: %s - %d", __func__, step, ret);
3287 } else {
3288 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003289 pcm_close(in->pcm);
3290 in->pcm = NULL;
3291 }
3292 }
3293 pthread_mutex_unlock(&adev->lock);
3294 return ret;
3295}
3296
3297static int in_get_mmap_position(const struct audio_stream_in *stream,
3298 struct audio_mmap_position *position)
3299{
3300 struct stream_in *in = (struct stream_in *)stream;
3301 ALOGVV("%s", __func__);
3302 if (position == NULL) {
3303 return -EINVAL;
3304 }
3305 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3306 return -ENOSYS;
3307 }
3308 if (in->pcm == NULL) {
3309 return -ENOSYS;
3310 }
3311 struct timespec ts = { 0, 0 };
3312 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3313 if (ret < 0) {
3314 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3315 return ret;
3316 }
Andy Hungfc044e12017-03-20 09:24:22 -07003317 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003318 return 0;
3319}
3320
3321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322static int adev_open_output_stream(struct audio_hw_device *dev,
3323 audio_io_handle_t handle,
3324 audio_devices_t devices,
3325 audio_output_flags_t flags,
3326 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003327 struct audio_stream_out **stream_out,
3328 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329{
3330 struct audio_device *adev = (struct audio_device *)dev;
3331 struct stream_out *out;
3332 int i, ret;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003333 const uint32_t direct_dev = (AUDIO_DEVICE_OUT_HDMI|AUDIO_DEVICE_OUT_USB_DEVICE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334
Eric Laurent994a6932013-07-17 11:51:42 -07003335 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336 __func__, config->sample_rate, config->channel_mask, devices, flags);
3337 *stream_out = NULL;
3338 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3339
3340 if (devices == AUDIO_DEVICE_NONE)
3341 devices = AUDIO_DEVICE_OUT_SPEAKER;
3342
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343 out->flags = flags;
3344 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003345 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003346 out->format = config->format;
3347 out->sample_rate = config->sample_rate;
3348 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3349 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003350 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351
3352 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003353 if (audio_is_linear_pcm(out->format) &&
3354 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
3355 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
3356 (out->devices & direct_dev)) {
3357
3358 bool hdmi = (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL);
3359
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003360 pthread_mutex_lock(&adev->lock);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003361 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3362 ret = read_hdmi_channel_masks(out);
3363 } else if (out->devices & AUDIO_DEVICE_OUT_USB_DEVICE) {
3364 ret = read_usb_sup_formats(out) ||
3365 read_usb_sup_channel_masks(out) ||
3366 read_usb_sup_sample_rates(out);
3367 ALOGV("plugged dev USB ret %d", ret);
3368 } else {
3369 ret = -1;
3370 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003371 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003372 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003373 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003374
Kevin Rocard50eff892017-05-02 16:52:05 -07003375 if (config->sample_rate == 0) {
3376 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3377 } else {
3378 out->sample_rate = config->sample_rate;
3379 }
3380 if (config->channel_mask == 0) {
3381 out->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3382 } else {
3383 out->channel_mask = config->channel_mask;
3384 }
3385 if (config->format == AUDIO_FORMAT_DEFAULT) {
3386 out->format = AUDIO_FORMAT_PCM_16_BIT;
3387 } else {
3388 out->format = config->format;
3389 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003390 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3391 // does this change?
3392 out->config = hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003394 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003396 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003397 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003398 pthread_mutex_lock(&adev->lock);
3399 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3400 pthread_mutex_unlock(&adev->lock);
3401
3402 // reject offload during card offline to allow
3403 // fallback to s/w paths
3404 if (offline) {
3405 ret = -ENODEV;
3406 goto error_open;
3407 }
3408
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003409 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3410 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3411 ALOGE("%s: Unsupported Offload information", __func__);
3412 ret = -EINVAL;
3413 goto error_open;
3414 }
3415 if (!is_supported_format(config->offload_info.format)) {
3416 ALOGE("%s: Unsupported audio format", __func__);
3417 ret = -EINVAL;
3418 goto error_open;
3419 }
3420
3421 out->compr_config.codec = (struct snd_codec *)
3422 calloc(1, sizeof(struct snd_codec));
3423
3424 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3425 if (config->offload_info.channel_mask)
3426 out->channel_mask = config->offload_info.channel_mask;
3427 else if (config->channel_mask)
3428 out->channel_mask = config->channel_mask;
3429 out->format = config->offload_info.format;
3430 out->sample_rate = config->offload_info.sample_rate;
3431
3432 out->stream.set_callback = out_set_callback;
3433 out->stream.pause = out_pause;
3434 out->stream.resume = out_resume;
3435 out->stream.drain = out_drain;
3436 out->stream.flush = out_flush;
3437
3438 out->compr_config.codec->id =
3439 get_snd_codec_id(config->offload_info.format);
3440 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3441 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003442 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003443 out->compr_config.codec->bit_rate =
3444 config->offload_info.bit_rate;
3445 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003446 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003447 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3448
3449 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3450 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003451
3452 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003453 create_offload_callback_thread(out);
3454 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3455 __func__, config->offload_info.version,
3456 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003457 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003458 switch (config->sample_rate) {
3459 case 8000:
3460 case 16000:
3461 case 48000:
3462 out->sample_rate = config->sample_rate;
3463 break;
3464 default:
3465 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003466 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003467 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003468 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3469 out->config = pcm_config_afe_proxy_playback;
3470 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003472 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3473 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3474 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003475 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3476 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3477 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003478 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3479 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003480 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003481 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003482 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3483 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3484 out->config = pcm_config_mmap_playback;
3485 out->stream.start = out_start;
3486 out->stream.stop = out_stop;
3487 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3488 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003489 } else {
3490 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3491 out->config = pcm_config_low_latency;
3492 }
3493 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3494 if (k_enable_extended_precision
3495 && pcm_params_format_test(adev->use_case_table[out->usecase],
3496 pcm_format_from_audio_format(config->format))) {
3497 out->config.format = pcm_format_from_audio_format(config->format);
3498 /* out->format already set to config->format */
3499 } else {
3500 /* deny the externally proposed config format
3501 * and use the one specified in audio_hw layer configuration.
3502 * Note: out->format is returned by out->stream.common.get_format()
3503 * and is used to set config->format in the code several lines below.
3504 */
3505 out->format = audio_format_from_pcm_format(out->config.format);
3506 }
3507 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003508 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003510
3511 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3512 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3513 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3514 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3515 __func__, config->sample_rate, config->format, config->channel_mask);
3516 config->sample_rate = out->sample_rate;
3517 config->format = out->format;
3518 config->channel_mask = out->channel_mask;
3519 ret = -EINVAL;
3520 goto error_open;
3521 }
3522
Andy Hung6fcba9c2014-03-18 11:53:32 -07003523 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3524 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003526 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003527 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003528 adev->primary_output = out;
3529 else {
3530 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003531 ret = -EEXIST;
3532 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003533 }
3534 }
3535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536 /* Check if this usecase is already existing */
3537 pthread_mutex_lock(&adev->lock);
3538 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3539 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003541 ret = -EEXIST;
3542 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003543 }
3544 pthread_mutex_unlock(&adev->lock);
3545
3546 out->stream.common.get_sample_rate = out_get_sample_rate;
3547 out->stream.common.set_sample_rate = out_set_sample_rate;
3548 out->stream.common.get_buffer_size = out_get_buffer_size;
3549 out->stream.common.get_channels = out_get_channels;
3550 out->stream.common.get_format = out_get_format;
3551 out->stream.common.set_format = out_set_format;
3552 out->stream.common.standby = out_standby;
3553 out->stream.common.dump = out_dump;
3554 out->stream.common.set_parameters = out_set_parameters;
3555 out->stream.common.get_parameters = out_get_parameters;
3556 out->stream.common.add_audio_effect = out_add_audio_effect;
3557 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3558 out->stream.get_latency = out_get_latency;
3559 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003560#ifdef NO_AUDIO_OUT
3561 out->stream.write = out_write_for_no_output;
3562#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003564#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565 out->stream.get_render_position = out_get_render_position;
3566 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003567 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003568
Eric Laurent0e46adf2016-12-16 12:49:24 -08003569 if (out->realtime)
3570 out->af_period_multiplier = af_period_multiplier;
3571 else
3572 out->af_period_multiplier = 1;
3573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003575 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003576 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003578 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003579 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003580 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582 config->format = out->stream.common.get_format(&out->stream.common);
3583 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3584 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3585
Andy Hunga452b0a2017-03-15 14:51:15 -07003586 out->error_log = error_log_create(
3587 ERROR_LOG_ENTRIES,
3588 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3589
Andy Hungfc044e12017-03-20 09:24:22 -07003590 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003591 // or not a userdebug or eng build.
3592 if (is_userdebug_or_eng_build()) {
3593 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3594 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3595
3596 out->power_log = power_log_create(
3597 config->sample_rate,
3598 audio_channel_count_from_out_mask(config->channel_mask),
3599 config->format,
3600 POWER_LOG_ENTRIES,
3601 POWER_LOG_FRAMES_PER_ENTRY);
3602 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003603
3604 /*
3605 By locking output stream before registering, we allow the callback
3606 to update stream's state only after stream's initial state is set to
3607 adev state.
3608 */
3609 lock_output_stream(out);
3610 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3611 pthread_mutex_lock(&adev->lock);
3612 out->card_status = adev->card_status;
3613 pthread_mutex_unlock(&adev->lock);
3614 pthread_mutex_unlock(&out->lock);
3615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003617
Eric Laurent994a6932013-07-17 11:51:42 -07003618 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003620
3621error_open:
3622 free(out);
3623 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003624 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003625 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626}
3627
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003628static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629 struct audio_stream_out *stream)
3630{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003631 struct stream_out *out = (struct stream_out *)stream;
3632 struct audio_device *adev = out->dev;
3633
Eric Laurent994a6932013-07-17 11:51:42 -07003634 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003635
3636 // must deregister from sndmonitor first to prevent races
3637 // between the callback and close_stream
3638 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003640 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3641 destroy_offload_callback_thread(out);
3642
3643 if (out->compr_config.codec != NULL)
3644 free(out->compr_config.codec);
3645 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003646
3647 if (adev->voice_tx_output == out)
3648 adev->voice_tx_output = NULL;
3649
Andy Hungfc044e12017-03-20 09:24:22 -07003650 power_log_destroy(out->power_log);
3651 out->power_log = NULL;
3652
Andy Hunga452b0a2017-03-15 14:51:15 -07003653 error_log_destroy(out->error_log);
3654 out->error_log = NULL;
3655
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003656 pthread_cond_destroy(&out->cond);
3657 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003659 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660}
3661
3662static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3663{
3664 struct audio_device *adev = (struct audio_device *)dev;
3665 struct str_parms *parms;
3666 char *str;
3667 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003668 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003670 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671
Joe Onorato188b6222016-03-01 11:02:27 -08003672 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003673
3674 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675
3676 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003677 status = voice_set_parameters(adev, parms);
3678 if (status != 0) {
3679 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003680 }
3681
3682 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3683 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003684 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3686 adev->bluetooth_nrec = true;
3687 else
3688 adev->bluetooth_nrec = false;
3689 }
3690
3691 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3692 if (ret >= 0) {
3693 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3694 adev->screen_off = false;
3695 else
3696 adev->screen_off = true;
3697 }
3698
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003699 ret = str_parms_get_int(parms, "rotation", &val);
3700 if (ret >= 0) {
3701 bool reverse_speakers = false;
3702 switch(val) {
3703 // FIXME: note that the code below assumes that the speakers are in the correct placement
3704 // relative to the user when the device is rotated 90deg from its default rotation. This
3705 // assumption is device-specific, not platform-specific like this code.
3706 case 270:
3707 reverse_speakers = true;
3708 break;
3709 case 0:
3710 case 90:
3711 case 180:
3712 break;
3713 default:
3714 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003715 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003716 }
Eric Laurent03f09432014-03-25 18:09:11 -07003717 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003718 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003719 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003720 }
3721
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003722 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3723 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003724 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003725 }
3726
David Linee3fe402017-03-13 10:00:42 -07003727 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3728 if (ret >= 0) {
3729 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3730 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3731 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3732 if (ret >= 0) {
3733 const int card = atoi(value);
3734 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3735 }
3736 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3737 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3738 if (ret >= 0) {
3739 const int card = atoi(value);
3740 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3741 }
3742 }
3743 }
3744
3745 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3746 if (ret >= 0) {
3747 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3748 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3749 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3750 if (ret >= 0) {
3751 const int card = atoi(value);
3752
3753 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3754 }
3755 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3756 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3757 if (ret >= 0) {
3758 const int card = atoi(value);
3759 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3760 }
3761 }
3762 }
3763
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003764 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003765done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003767 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003768 ALOGV("%s: exit with code(%d)", __func__, status);
3769 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770}
3771
3772static char* adev_get_parameters(const struct audio_hw_device *dev,
3773 const char *keys)
3774{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003775 struct audio_device *adev = (struct audio_device *)dev;
3776 struct str_parms *reply = str_parms_create();
3777 struct str_parms *query = str_parms_create_str(keys);
3778 char *str;
3779
3780 pthread_mutex_lock(&adev->lock);
3781
3782 voice_get_parameters(adev, query, reply);
3783 str = str_parms_to_str(reply);
3784 str_parms_destroy(query);
3785 str_parms_destroy(reply);
3786
3787 pthread_mutex_unlock(&adev->lock);
3788 ALOGV("%s: exit: returns - %s", __func__, str);
3789 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003790}
3791
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003792static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793{
3794 return 0;
3795}
3796
Haynes Mathew George5191a852013-09-11 14:19:36 -07003797static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3798{
3799 int ret;
3800 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003801
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003802 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3803
Haynes Mathew George5191a852013-09-11 14:19:36 -07003804 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003805 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003806 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003807
Haynes Mathew George5191a852013-09-11 14:19:36 -07003808 return ret;
3809}
3810
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003811static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812{
3813 return -ENOSYS;
3814}
3815
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003816static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3817 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003818{
3819 return -ENOSYS;
3820}
3821
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003822static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003823{
3824 return -ENOSYS;
3825}
3826
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003827static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003828{
3829 return -ENOSYS;
3830}
3831
3832static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3833{
3834 struct audio_device *adev = (struct audio_device *)dev;
3835
3836 pthread_mutex_lock(&adev->lock);
3837 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003838 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003840 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3841 voice_is_in_call(adev)) {
3842 voice_stop_call(adev);
3843 adev->current_call_output = NULL;
3844 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003845 }
3846 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003847
3848 audio_extn_extspk_set_mode(adev->extspk, mode);
3849
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003850 return 0;
3851}
3852
3853static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3854{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003855 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003856 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003857
Eric Laurent2bafff12016-03-17 12:17:23 -07003858 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003859 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003860 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3861 ret = audio_extn_hfp_set_mic_mute(adev, state);
3862 } else {
3863 ret = voice_set_mic_mute(adev, state);
3864 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003865 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003866 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003867
3868 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003869}
3870
3871static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3872{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003873 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003874 return 0;
3875}
3876
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003877static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878 const struct audio_config *config)
3879{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003880 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003881
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003882 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3883 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003884}
3885
3886static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003887 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888 audio_devices_t devices,
3889 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003890 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003891 audio_input_flags_t flags,
3892 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003893 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003894{
3895 struct audio_device *adev = (struct audio_device *)dev;
3896 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003897 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003898 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003899 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900
Eric Laurent994a6932013-07-17 11:51:42 -07003901 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003902 *stream_in = NULL;
3903 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3904 return -EINVAL;
3905
Zheng Zhang6185d572016-12-01 20:35:17 +08003906 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 -08003907 return -EINVAL;
3908
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003909 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3910
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003911 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003912 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003913
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914 in->stream.common.get_sample_rate = in_get_sample_rate;
3915 in->stream.common.set_sample_rate = in_set_sample_rate;
3916 in->stream.common.get_buffer_size = in_get_buffer_size;
3917 in->stream.common.get_channels = in_get_channels;
3918 in->stream.common.get_format = in_get_format;
3919 in->stream.common.set_format = in_set_format;
3920 in->stream.common.standby = in_standby;
3921 in->stream.common.dump = in_dump;
3922 in->stream.common.set_parameters = in_set_parameters;
3923 in->stream.common.get_parameters = in_get_parameters;
3924 in->stream.common.add_audio_effect = in_add_audio_effect;
3925 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3926 in->stream.set_gain = in_set_gain;
3927 in->stream.read = in_read;
3928 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003929 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930
3931 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003932 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003933 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003934 in->standby = 1;
3935 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003936 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003937 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003938
vivek mehta57ff9b52016-04-28 14:13:08 -07003939 // restrict 24 bit capture for unprocessed source only
3940 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3941 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003942 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003943 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3944 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3945 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3946 bool ret_error = false;
3947 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3948 from HAL is 8_24
3949 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3950 8_24 return error indicating supported format is 8_24
3951 *> In case of any other source requesting 24 bit or float return error
3952 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003953
vivek mehta57ff9b52016-04-28 14:13:08 -07003954 on error flinger will retry with supported format passed
3955 */
3956 if (source != AUDIO_SOURCE_UNPROCESSED) {
3957 config->format = AUDIO_FORMAT_PCM_16_BIT;
3958 ret_error = true;
3959 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3960 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3961 ret_error = true;
3962 }
3963
3964 if (ret_error) {
3965 ret = -EINVAL;
3966 goto err_open;
3967 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003968 }
3969
vivek mehta57ff9b52016-04-28 14:13:08 -07003970 in->format = config->format;
3971
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003972 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003973 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3974 if (config->sample_rate == 0)
3975 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3976 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3977 config->sample_rate != 8000) {
3978 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3979 ret = -EINVAL;
3980 goto err_open;
3981 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003982
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003983 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3984 config->format = AUDIO_FORMAT_PCM_16_BIT;
3985 ret = -EINVAL;
3986 goto err_open;
3987 }
3988
3989 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3990 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07003991 in->af_period_multiplier = 1;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003992 } else {
3993 in->usecase = USECASE_AUDIO_RECORD;
3994 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08003995 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003996 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003997#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003998 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003999#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004000 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004001 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004002 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004003 frame_size = audio_stream_in_frame_size(&in->stream);
4004 buffer_size = get_input_buffer_size(config->sample_rate,
4005 config->format,
4006 channel_count,
4007 is_low_latency);
4008 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004009 in->config.rate = config->sample_rate;
4010 in->af_period_multiplier = 1;
4011 } else {
4012 // period size is left untouched for rt mode playback
4013 in->config = pcm_config_audio_capture_rt;
4014 in->af_period_multiplier = af_period_multiplier;
4015 }
4016 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4017 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
4018 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4019 in->config = pcm_config_mmap_capture;
4020 in->stream.start = in_start;
4021 in->stream.stop = in_stop;
4022 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4023 in->stream.get_mmap_position = in_get_mmap_position;
4024 in->af_period_multiplier = 1;
4025 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
4026 } else {
4027 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004028 frame_size = audio_stream_in_frame_size(&in->stream);
4029 buffer_size = get_input_buffer_size(config->sample_rate,
4030 config->format,
4031 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004032 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004033 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004034 in->config.rate = config->sample_rate;
4035 in->af_period_multiplier = 1;
4036 }
4037 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4038 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004039 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004040
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004041 in->config.channels = channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004042
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004043 /* This stream could be for sound trigger lab,
4044 get sound trigger pcm if present */
4045 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004047 lock_input_stream(in);
4048 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4049 pthread_mutex_lock(&adev->lock);
4050 in->card_status = adev->card_status;
4051 pthread_mutex_unlock(&adev->lock);
4052 pthread_mutex_unlock(&in->lock);
4053
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004054 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004055 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004056 return 0;
4057
4058err_open:
4059 free(in);
4060 *stream_in = NULL;
4061 return ret;
4062}
4063
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004064static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004065 struct audio_stream_in *stream)
4066{
Eric Laurent994a6932013-07-17 11:51:42 -07004067 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004068
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004069 // must deregister from sndmonitor first to prevent races
4070 // between the callback and close_stream
4071 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004072 in_standby(&stream->common);
4073 free(stream);
4074
4075 return;
4076}
4077
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004078static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004079{
4080 return 0;
4081}
4082
Andy Hung31aca912014-03-20 17:14:59 -07004083/* verifies input and output devices and their capabilities.
4084 *
4085 * This verification is required when enabling extended bit-depth or
4086 * sampling rates, as not all qcom products support it.
4087 *
4088 * Suitable for calling only on initialization such as adev_open().
4089 * It fills the audio_device use_case_table[] array.
4090 *
4091 * Has a side-effect that it needs to configure audio routing / devices
4092 * in order to power up the devices and read the device parameters.
4093 * It does not acquire any hw device lock. Should restore the devices
4094 * back to "normal state" upon completion.
4095 */
4096static int adev_verify_devices(struct audio_device *adev)
4097{
4098 /* enumeration is a bit difficult because one really wants to pull
4099 * the use_case, device id, etc from the hidden pcm_device_table[].
4100 * In this case there are the following use cases and device ids.
4101 *
4102 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4103 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004104 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004105 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4106 * [USECASE_AUDIO_RECORD] = {0, 0},
4107 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4108 * [USECASE_VOICE_CALL] = {2, 2},
4109 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004110 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004111 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4112 */
4113
4114 /* should be the usecases enabled in adev_open_input_stream() */
4115 static const int test_in_usecases[] = {
4116 USECASE_AUDIO_RECORD,
4117 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4118 };
4119 /* should be the usecases enabled in adev_open_output_stream()*/
4120 static const int test_out_usecases[] = {
4121 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4122 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4123 };
4124 static const usecase_type_t usecase_type_by_dir[] = {
4125 PCM_PLAYBACK,
4126 PCM_CAPTURE,
4127 };
4128 static const unsigned flags_by_dir[] = {
4129 PCM_OUT,
4130 PCM_IN,
4131 };
4132
4133 size_t i;
4134 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004135 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004136 char info[512]; /* for possible debug info */
4137
4138 for (dir = 0; dir < 2; ++dir) {
4139 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4140 const unsigned flags_dir = flags_by_dir[dir];
4141 const size_t testsize =
4142 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4143 const int *testcases =
4144 dir ? test_in_usecases : test_out_usecases;
4145 const audio_devices_t audio_device =
4146 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4147
4148 for (i = 0; i < testsize; ++i) {
4149 const audio_usecase_t audio_usecase = testcases[i];
4150 int device_id;
4151 snd_device_t snd_device;
4152 struct pcm_params **pparams;
4153 struct stream_out out;
4154 struct stream_in in;
4155 struct audio_usecase uc_info;
4156 int retval;
4157
4158 pparams = &adev->use_case_table[audio_usecase];
4159 pcm_params_free(*pparams); /* can accept null input */
4160 *pparams = NULL;
4161
4162 /* find the device ID for the use case (signed, for error) */
4163 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4164 if (device_id < 0)
4165 continue;
4166
4167 /* prepare structures for device probing */
4168 memset(&uc_info, 0, sizeof(uc_info));
4169 uc_info.id = audio_usecase;
4170 uc_info.type = usecase_type;
4171 if (dir) {
4172 adev->active_input = &in;
4173 memset(&in, 0, sizeof(in));
4174 in.device = audio_device;
4175 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4176 uc_info.stream.in = &in;
4177 } else {
4178 adev->active_input = NULL;
4179 }
4180 memset(&out, 0, sizeof(out));
4181 out.devices = audio_device; /* only field needed in select_devices */
4182 uc_info.stream.out = &out;
4183 uc_info.devices = audio_device;
4184 uc_info.in_snd_device = SND_DEVICE_NONE;
4185 uc_info.out_snd_device = SND_DEVICE_NONE;
4186 list_add_tail(&adev->usecase_list, &uc_info.list);
4187
4188 /* select device - similar to start_(in/out)put_stream() */
4189 retval = select_devices(adev, audio_usecase);
4190 if (retval >= 0) {
4191 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4192#if LOG_NDEBUG == 0
4193 if (*pparams) {
4194 ALOGV("%s: (%s) card %d device %d", __func__,
4195 dir ? "input" : "output", card_id, device_id);
4196 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004197 } else {
4198 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4199 }
4200#endif
4201 }
4202
4203 /* deselect device - similar to stop_(in/out)put_stream() */
4204 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004205 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004206 /* 2. Disable the rx device */
4207 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004208 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004209 list_remove(&uc_info.list);
4210 }
4211 }
4212 adev->active_input = NULL; /* restore adev state */
4213 return 0;
4214}
4215
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004216static int adev_close(hw_device_t *device)
4217{
Andy Hung31aca912014-03-20 17:14:59 -07004218 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004219 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004220
4221 if (!adev)
4222 return 0;
4223
Kevin Rocarda5453442017-05-02 15:09:20 -07004224 audio_extn_snd_mon_unregister_listener(adev);
Kevin Rocard8342c2c2017-04-07 18:50:00 -07004225 audio_extn_snd_mon_deinit();
Kevin Rocarda5453442017-05-02 15:09:20 -07004226
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004227 audio_extn_tfa_98xx_deinit();
4228
vivek mehta1a9b7c02015-06-25 11:49:38 -07004229 pthread_mutex_lock(&adev_init_lock);
4230
4231 if ((--audio_device_ref_count) == 0) {
4232 audio_route_free(adev->audio_route);
4233 free(adev->snd_dev_ref_cnt);
4234 platform_deinit(adev->platform);
4235 audio_extn_extspk_deinit(adev->extspk);
4236 audio_extn_sound_trigger_deinit(adev);
4237 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4238 pcm_params_free(adev->use_case_table[i]);
4239 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004240 if (adev->adm_deinit)
4241 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004242 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004243 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004244
4245 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247 return 0;
4248}
4249
Glenn Kasten4f993392014-05-14 07:30:48 -07004250/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4251 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4252 * just that it _might_ work.
4253 */
4254static int period_size_is_plausible_for_low_latency(int period_size)
4255{
4256 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004257 case 48:
4258 case 96:
4259 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004260 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004261 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004262 case 240:
4263 case 320:
4264 case 480:
4265 return 1;
4266 default:
4267 return 0;
4268 }
4269}
4270
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004271static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4272{
4273 int card;
4274 card_status_t status;
4275
4276 if (!parms)
4277 return;
4278
4279 if (parse_snd_card_status(parms, &card, &status) < 0)
4280 return;
4281
4282 pthread_mutex_lock(&adev->lock);
4283 bool valid_cb = (card == adev->snd_card);
4284 if (valid_cb) {
4285 if (adev->card_status != status) {
4286 adev->card_status = status;
4287 platform_snd_card_update(adev->platform, status);
4288 }
4289 }
4290 pthread_mutex_unlock(&adev->lock);
4291 return;
4292}
4293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004294static int adev_open(const hw_module_t *module, const char *name,
4295 hw_device_t **device)
4296{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004297 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004298
Eric Laurent2bafff12016-03-17 12:17:23 -07004299 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004300 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004301 pthread_mutex_lock(&adev_init_lock);
4302 if (audio_device_ref_count != 0) {
4303 *device = &adev->device.common;
4304 audio_device_ref_count++;
4305 ALOGV("%s: returning existing instance of adev", __func__);
4306 ALOGV("%s: exit", __func__);
4307 pthread_mutex_unlock(&adev_init_lock);
4308 return 0;
4309 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310 adev = calloc(1, sizeof(struct audio_device));
4311
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004312 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4313
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004314 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4315 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4316 adev->device.common.module = (struct hw_module_t *)module;
4317 adev->device.common.close = adev_close;
4318
4319 adev->device.init_check = adev_init_check;
4320 adev->device.set_voice_volume = adev_set_voice_volume;
4321 adev->device.set_master_volume = adev_set_master_volume;
4322 adev->device.get_master_volume = adev_get_master_volume;
4323 adev->device.set_master_mute = adev_set_master_mute;
4324 adev->device.get_master_mute = adev_get_master_mute;
4325 adev->device.set_mode = adev_set_mode;
4326 adev->device.set_mic_mute = adev_set_mic_mute;
4327 adev->device.get_mic_mute = adev_get_mic_mute;
4328 adev->device.set_parameters = adev_set_parameters;
4329 adev->device.get_parameters = adev_get_parameters;
4330 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4331 adev->device.open_output_stream = adev_open_output_stream;
4332 adev->device.close_output_stream = adev_close_output_stream;
4333 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004334
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004335 adev->device.close_input_stream = adev_close_input_stream;
4336 adev->device.dump = adev_dump;
4337
4338 /* Set the default route before the PCM stream is opened */
4339 pthread_mutex_lock(&adev->lock);
4340 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004341 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004342 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004343 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004344 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004345 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004346 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004347 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004348 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004349 pthread_mutex_unlock(&adev->lock);
4350
4351 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004352 adev->platform = platform_init(adev);
4353 if (!adev->platform) {
4354 free(adev->snd_dev_ref_cnt);
4355 free(adev);
4356 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4357 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004358 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004359 return -EINVAL;
4360 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004361 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004362 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004363
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004364 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4365 if (adev->visualizer_lib == NULL) {
4366 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4367 } else {
4368 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4369 adev->visualizer_start_output =
4370 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4371 "visualizer_hal_start_output");
4372 adev->visualizer_stop_output =
4373 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4374 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004375 }
4376
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004377 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4378 if (adev->offload_effects_lib == NULL) {
4379 ALOGW("%s: DLOPEN failed for %s", __func__,
4380 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4381 } else {
4382 ALOGV("%s: DLOPEN successful for %s", __func__,
4383 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4384 adev->offload_effects_start_output =
4385 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4386 "offload_effects_bundle_hal_start_output");
4387 adev->offload_effects_stop_output =
4388 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4389 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004390 }
4391
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004392 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4393 if (adev->adm_lib == NULL) {
4394 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4395 } else {
4396 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4397 adev->adm_init = (adm_init_t)
4398 dlsym(adev->adm_lib, "adm_init");
4399 adev->adm_deinit = (adm_deinit_t)
4400 dlsym(adev->adm_lib, "adm_deinit");
4401 adev->adm_register_input_stream = (adm_register_input_stream_t)
4402 dlsym(adev->adm_lib, "adm_register_input_stream");
4403 adev->adm_register_output_stream = (adm_register_output_stream_t)
4404 dlsym(adev->adm_lib, "adm_register_output_stream");
4405 adev->adm_deregister_stream = (adm_deregister_stream_t)
4406 dlsym(adev->adm_lib, "adm_deregister_stream");
4407 adev->adm_request_focus = (adm_request_focus_t)
4408 dlsym(adev->adm_lib, "adm_request_focus");
4409 adev->adm_abandon_focus = (adm_abandon_focus_t)
4410 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004411 adev->adm_set_config = (adm_set_config_t)
4412 dlsym(adev->adm_lib, "adm_set_config");
4413 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4414 dlsym(adev->adm_lib, "adm_request_focus_v2");
4415 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4416 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4417 adev->adm_on_routing_change = (adm_on_routing_change_t)
4418 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004419 }
4420
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004421 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004422 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004423
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004424 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004425
Andy Hung31aca912014-03-20 17:14:59 -07004426 if (k_enable_extended_precision)
4427 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004428
Glenn Kasten4f993392014-05-14 07:30:48 -07004429 char value[PROPERTY_VALUE_MAX];
4430 int trial;
4431 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4432 trial = atoi(value);
4433 if (period_size_is_plausible_for_low_latency(trial)) {
4434 pcm_config_low_latency.period_size = trial;
4435 pcm_config_low_latency.start_threshold = trial / 4;
4436 pcm_config_low_latency.avail_min = trial / 4;
4437 configured_low_latency_capture_period_size = trial;
4438 }
4439 }
4440 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4441 trial = atoi(value);
4442 if (period_size_is_plausible_for_low_latency(trial)) {
4443 configured_low_latency_capture_period_size = trial;
4444 }
4445 }
4446
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004447 // commented as full set of app type cfg is sent from platform
4448 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004449 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004450
4451 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4452 af_period_multiplier = atoi(value);
4453 if (af_period_multiplier < 0) {
4454 af_period_multiplier = 2;
4455 } else if (af_period_multiplier > 4) {
4456 af_period_multiplier = 4;
4457 }
4458 ALOGV("new period_multiplier = %d", af_period_multiplier);
4459 }
4460
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004461 audio_extn_tfa_98xx_init(adev);
4462
vivek mehta1a9b7c02015-06-25 11:49:38 -07004463 pthread_mutex_unlock(&adev_init_lock);
4464
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004465 if (adev->adm_init)
4466 adev->adm_data = adev->adm_init();
4467
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004468 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004469 audio_extn_snd_mon_init();
4470 pthread_mutex_lock(&adev->lock);
4471 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4472 adev->card_status = CARD_STATUS_ONLINE;
4473 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004474
Eric Laurent2bafff12016-03-17 12:17:23 -07004475 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004476 return 0;
4477}
4478
4479static struct hw_module_methods_t hal_module_methods = {
4480 .open = adev_open,
4481};
4482
4483struct audio_module HAL_MODULE_INFO_SYM = {
4484 .common = {
4485 .tag = HARDWARE_MODULE_TAG,
4486 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4487 .hal_api_version = HARDWARE_HAL_API_VERSION,
4488 .id = AUDIO_HARDWARE_MODULE_ID,
4489 .name = "QCOM Audio HAL",
4490 .author = "Code Aurora Forum",
4491 .methods = &hal_module_methods,
4492 },
4493};