blob: 3318cc10720b9153827e19f2d1754b95b0536ade [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
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700804 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
805 uc_info,
806 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700807
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700808 /*
809 * This function is to make sure that all the usecases that are active on
810 * the hardware codec backend are always routed to any one device that is
811 * handled by the hardware codec.
812 * For example, if low-latency and deep-buffer usecases are currently active
813 * on speaker and out_set_parameters(headset) is received on low-latency
814 * output, then we have to make sure deep-buffer is also switched to headset,
815 * because of the limitation that both the devices cannot be enabled
816 * at the same time as they share the same backend.
817 */
818 /* Disable all the usecases on the shared backend other than the
819 specified usecase */
820 for (i = 0; i < AUDIO_USECASE_MAX; i++)
821 switch_device[i] = false;
822
823 list_for_each(node, &adev->usecase_list) {
824 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700825 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
826 continue;
827
828 if (force_routing ||
829 (usecase->out_snd_device != snd_device &&
830 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
831 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700832 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
833 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700834 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700835 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700836 switch_device[usecase->id] = true;
837 num_uc_to_switch++;
838 }
839 }
840
841 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700842 list_for_each(node, &adev->usecase_list) {
843 usecase = node_to_item(node, struct audio_usecase, list);
844 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700845 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900846 }
847 }
848
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700849 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900850 list_for_each(node, &adev->usecase_list) {
851 usecase = node_to_item(node, struct audio_usecase, list);
852 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700853 d_device = derive_playback_snd_device(usecase, uc_info,
854 snd_device);
855 enable_snd_device(adev, d_device);
856 /* Update the out_snd_device before enabling the audio route */
857 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700858 }
859 }
860
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700861 /* Re-route all the usecases on the shared backend other than the
862 specified usecase to new snd devices */
863 list_for_each(node, &adev->usecase_list) {
864 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700865 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700866 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700867 }
868 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869 }
870}
871
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700872static void check_and_route_capture_usecases(struct audio_device *adev,
873 struct audio_usecase *uc_info,
874 snd_device_t snd_device)
875{
876 struct listnode *node;
877 struct audio_usecase *usecase;
878 bool switch_device[AUDIO_USECASE_MAX];
879 int i, num_uc_to_switch = 0;
880
vivek mehta4ed66e62016-04-15 23:33:34 -0700881 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
882
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700883 /*
884 * This function is to make sure that all the active capture usecases
885 * are always routed to the same input sound device.
886 * For example, if audio-record and voice-call usecases are currently
887 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
888 * is received for voice call then we have to make sure that audio-record
889 * usecase is also switched to earpiece i.e. voice-dmic-ef,
890 * because of the limitation that two devices cannot be enabled
891 * at the same time if they share the same backend.
892 */
893 for (i = 0; i < AUDIO_USECASE_MAX; i++)
894 switch_device[i] = false;
895
896 list_for_each(node, &adev->usecase_list) {
897 usecase = node_to_item(node, struct audio_usecase, list);
898 if (usecase->type != PCM_PLAYBACK &&
899 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700900 usecase->in_snd_device != snd_device &&
901 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700902 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
903 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700904 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700905 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700906 switch_device[usecase->id] = true;
907 num_uc_to_switch++;
908 }
909 }
910
911 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700912 list_for_each(node, &adev->usecase_list) {
913 usecase = node_to_item(node, struct audio_usecase, list);
914 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700915 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700916 }
917 }
918
919 list_for_each(node, &adev->usecase_list) {
920 usecase = node_to_item(node, struct audio_usecase, list);
921 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700922 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700923 }
924 }
925
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700926 /* Re-route all the usecases on the shared backend other than the
927 specified usecase to new snd devices */
928 list_for_each(node, &adev->usecase_list) {
929 usecase = node_to_item(node, struct audio_usecase, list);
930 /* Update the in_snd_device only before enabling the audio route */
931 if (switch_device[usecase->id] ) {
932 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700933 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700934 }
935 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700936 }
937}
938
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800939/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700940static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800941{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700942 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700943 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800944
945 switch (channels) {
946 /*
947 * Do not handle stereo output in Multi-channel cases
948 * Stereo case is handled in normal playback path
949 */
950 case 6:
951 ALOGV("%s: HDMI supports 5.1", __func__);
952 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
953 break;
954 case 8:
955 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
956 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
957 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
958 break;
959 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700960 ALOGE("HDMI does not support multi channel playback");
961 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800962 break;
963 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700964 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800965}
966
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800967static int read_usb_sup_sample_rates(struct stream_out *out)
968{
969 uint32_t *sr = out->supported_sample_rates;
970 size_t count = audio_extn_usb_sup_sample_rates(0 /*playback*/,
971 sr,
972 MAX_SUPPORTED_SAMPLE_RATES);
973#if !LOG_NDEBUG
974
975 for (size_t i=0; i<count; i++) {
976 ALOGV("%s %d", __func__, out->supported_sample_rates[i]);
977 }
978#endif
979 return count > 0 ? 0 : -1;
980}
981
982static int read_usb_sup_channel_masks(struct stream_out *out)
983{
984 int channels = audio_extn_usb_get_max_channels();
985 out->supported_channel_masks[0] =
986 channels < 3 ? audio_channel_out_mask_from_count(channels) :
987 audio_channel_mask_for_index_assignment_from_count(channels);
988 return 0;
989}
990
991static int read_usb_sup_formats(struct stream_out *out)
992{
993 int bitwidth = audio_extn_usb_get_max_bit_width();
994 switch (bitwidth) {
995 case 24:
996 // XXX : usb.c returns 24 for s24 and s24_le?
997 out->supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
998 break;
999 case 32:
1000 out->supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1001 break;
1002 case 16:
1003 default :
1004 out->supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1005 break;
1006 }
1007
1008 return 0;
1009}
1010
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001011static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1012{
1013 struct audio_usecase *usecase;
1014 struct listnode *node;
1015
1016 list_for_each(node, &adev->usecase_list) {
1017 usecase = node_to_item(node, struct audio_usecase, list);
1018 if (usecase->type == VOICE_CALL) {
1019 ALOGV("%s: usecase id %d", __func__, usecase->id);
1020 return usecase->id;
1021 }
1022 }
1023 return USECASE_INVALID;
1024}
1025
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001026struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1027 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001028{
1029 struct audio_usecase *usecase;
1030 struct listnode *node;
1031
1032 list_for_each(node, &adev->usecase_list) {
1033 usecase = node_to_item(node, struct audio_usecase, list);
1034 if (usecase->id == uc_id)
1035 return usecase;
1036 }
1037 return NULL;
1038}
1039
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001040int select_devices(struct audio_device *adev,
1041 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001042{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001043 snd_device_t out_snd_device = SND_DEVICE_NONE;
1044 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001045 struct audio_usecase *usecase = NULL;
1046 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001047 struct audio_usecase *hfp_usecase = NULL;
1048 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001049 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001050 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001051
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001052 usecase = get_usecase_from_list(adev, uc_id);
1053 if (usecase == NULL) {
1054 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1055 return -EINVAL;
1056 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001057
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001058 if ((usecase->type == VOICE_CALL) ||
1059 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001060 out_snd_device = platform_get_output_snd_device(adev->platform,
1061 usecase->stream.out->devices);
1062 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001063 usecase->devices = usecase->stream.out->devices;
1064 } else {
1065 /*
1066 * If the voice call is active, use the sound devices of voice call usecase
1067 * so that it would not result any device switch. All the usecases will
1068 * be switched to new device when select_devices() is called for voice call
1069 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001070 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001071 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001072 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001073 vc_usecase = get_usecase_from_list(adev,
1074 get_voice_usecase_id_from_list(adev));
1075 if ((vc_usecase != NULL) &&
1076 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1077 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001078 in_snd_device = vc_usecase->in_snd_device;
1079 out_snd_device = vc_usecase->out_snd_device;
1080 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001081 } else if (audio_extn_hfp_is_active(adev)) {
1082 hfp_ucid = audio_extn_hfp_get_usecase();
1083 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1084 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1085 in_snd_device = hfp_usecase->in_snd_device;
1086 out_snd_device = hfp_usecase->out_snd_device;
1087 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001088 }
1089 if (usecase->type == PCM_PLAYBACK) {
1090 usecase->devices = usecase->stream.out->devices;
1091 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001092 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001093 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001094 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001095 if (usecase->stream.out == adev->primary_output &&
1096 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001097 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1098 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001099 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001100 select_devices(adev, adev->active_input->usecase);
1101 }
1102 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001103 } else if (usecase->type == PCM_CAPTURE) {
1104 usecase->devices = usecase->stream.in->device;
1105 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001106 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001107 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001108 if (adev->active_input &&
1109 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1110 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001111 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001112 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1113 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1114 } else if (adev->primary_output) {
1115 out_device = adev->primary_output->devices;
1116 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001117 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001118 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001119 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001120 }
1121 }
1122
1123 if (out_snd_device == usecase->out_snd_device &&
1124 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001125 return 0;
1126 }
1127
Eric Laurent2bafff12016-03-17 12:17:23 -07001128 if (out_snd_device != SND_DEVICE_NONE &&
1129 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1130 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1131 __func__,
1132 use_case_table[uc_id],
1133 adev->last_logged_snd_device[uc_id][0],
1134 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1135 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1136 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1137 -1,
1138 out_snd_device,
1139 platform_get_snd_device_name(out_snd_device),
1140 platform_get_snd_device_acdb_id(out_snd_device));
1141 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1142 }
1143 if (in_snd_device != SND_DEVICE_NONE &&
1144 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1145 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1146 __func__,
1147 use_case_table[uc_id],
1148 adev->last_logged_snd_device[uc_id][1],
1149 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1150 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1151 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1152 -1,
1153 in_snd_device,
1154 platform_get_snd_device_name(in_snd_device),
1155 platform_get_snd_device_acdb_id(in_snd_device));
1156 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1157 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001158
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001159 /*
1160 * Limitation: While in call, to do a device switch we need to disable
1161 * and enable both RX and TX devices though one of them is same as current
1162 * device.
1163 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001164 if ((usecase->type == VOICE_CALL) &&
1165 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1166 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001167 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001168 /* Disable sidetone only if voice call already exists */
1169 if (voice_is_call_state_active(adev))
1170 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001171 }
1172
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001173 /* Disable current sound devices */
1174 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001175 disable_audio_route(adev, usecase);
1176 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001177 }
1178
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001179 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001180 disable_audio_route(adev, usecase);
1181 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001182 }
1183
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001184 /* Applicable only on the targets that has external modem.
1185 * New device information should be sent to modem before enabling
1186 * the devices to reduce in-call device switch time.
1187 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001188 if ((usecase->type == VOICE_CALL) &&
1189 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1190 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001191 status = platform_switch_voice_call_enable_device_config(adev->platform,
1192 out_snd_device,
1193 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001194 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001195
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001196 /* Enable new sound devices */
1197 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001198 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1199 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001200 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001201 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001202 }
1203
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001204 if (in_snd_device != SND_DEVICE_NONE) {
1205 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001206 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001207 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001208
Eric Laurentb23d5282013-05-14 15:27:20 -07001209 if (usecase->type == VOICE_CALL)
1210 status = platform_switch_voice_call_device_post(adev->platform,
1211 out_snd_device,
1212 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001213
sangwoo170731f2013-06-08 15:36:36 +09001214 usecase->in_snd_device = in_snd_device;
1215 usecase->out_snd_device = out_snd_device;
1216
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001217 audio_extn_tfa_98xx_set_mode();
1218
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001219 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001220
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001221 /* Applicable only on the targets that has external modem.
1222 * Enable device command should be sent to modem only after
1223 * enabling voice call mixer controls
1224 */
vivek mehta765eb642015-08-07 19:46:06 -07001225 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001226 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1227 out_snd_device,
1228 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001229 /* Enable sidetone only if voice call already exists */
1230 if (voice_is_call_state_active(adev))
1231 voice_set_sidetone(adev, out_snd_device, true);
1232 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001233
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001234 return status;
1235}
1236
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001237static int stop_input_stream(struct stream_in *in)
1238{
1239 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001240 struct audio_usecase *uc_info;
1241 struct audio_device *adev = in->dev;
1242
Eric Laurentc8400632013-02-14 19:04:54 -08001243 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001244
Eric Laurent994a6932013-07-17 11:51:42 -07001245 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001246 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001247 uc_info = get_usecase_from_list(adev, in->usecase);
1248 if (uc_info == NULL) {
1249 ALOGE("%s: Could not find the usecase (%d) in the list",
1250 __func__, in->usecase);
1251 return -EINVAL;
1252 }
1253
vivek mehta781065c2017-04-04 12:55:01 -07001254 /* Close in-call recording streams */
1255 voice_check_and_stop_incall_rec_usecase(adev, in);
1256
Eric Laurent150dbfe2013-02-27 14:31:02 -08001257 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001258 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001259
1260 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001261 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001262
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001263 list_remove(&uc_info->list);
1264 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001265
Eric Laurent994a6932013-07-17 11:51:42 -07001266 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001267 return ret;
1268}
1269
1270int start_input_stream(struct stream_in *in)
1271{
1272 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001273 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001274 struct audio_usecase *uc_info;
1275 struct audio_device *adev = in->dev;
1276
Eric Laurent994a6932013-07-17 11:51:42 -07001277 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001278
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001279 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1280 return -EIO;
1281
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001282 if (in->card_status == CARD_STATUS_OFFLINE ||
1283 adev->card_status == CARD_STATUS_OFFLINE) {
1284 ALOGW("in->card_status or adev->card_status offline, try again");
1285 ret = -EAGAIN;
1286 goto error_config;
1287 }
1288
vivek mehta781065c2017-04-04 12:55:01 -07001289 /* Check if source matches incall recording usecase criteria */
1290 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1291 if (ret)
1292 goto error_config;
1293 else
1294 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1295
Eric Laurentb23d5282013-05-14 15:27:20 -07001296 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001297 if (in->pcm_device_id < 0) {
1298 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1299 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001300 ret = -EINVAL;
1301 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001302 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001303
1304 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001305 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1306 uc_info->id = in->usecase;
1307 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001308 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001309 uc_info->devices = in->device;
1310 uc_info->in_snd_device = SND_DEVICE_NONE;
1311 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001312
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001313 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001314
1315 audio_extn_perf_lock_acquire();
1316
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001317 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001318
Eric Laurent0e46adf2016-12-16 12:49:24 -08001319 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001320 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001321 ALOGE("%s: pcm stream not ready", __func__);
1322 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001323 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001324 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001325 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001326 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1327 goto error_open;
1328 }
1329 } else {
1330 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1331 unsigned int pcm_open_retry_count = 0;
1332
1333 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1334 flags |= PCM_MMAP | PCM_NOIRQ;
1335 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1336 } else if (in->realtime) {
1337 flags |= PCM_MMAP | PCM_NOIRQ;
1338 }
1339
1340 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1341 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1342
1343 while (1) {
1344 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1345 flags, &in->config);
1346 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1347 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1348 if (in->pcm != NULL) {
1349 pcm_close(in->pcm);
1350 in->pcm = NULL;
1351 }
1352 if (pcm_open_retry_count-- == 0) {
1353 ret = -EIO;
1354 goto error_open;
1355 }
1356 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1357 continue;
1358 }
1359 break;
1360 }
1361
1362 ALOGV("%s: pcm_prepare", __func__);
1363 ret = pcm_prepare(in->pcm);
1364 if (ret < 0) {
1365 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001366 pcm_close(in->pcm);
1367 in->pcm = NULL;
1368 goto error_open;
1369 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001370 if (in->realtime) {
1371 ret = pcm_start(in->pcm);
1372 if (ret < 0) {
1373 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1374 pcm_close(in->pcm);
1375 in->pcm = NULL;
1376 goto error_open;
1377 }
1378 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001379 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001380 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001381 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001382 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001383
Eric Laurent0e46adf2016-12-16 12:49:24 -08001384 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001385
1386error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001387 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001388 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001389
1390error_config:
1391 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001392 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001393
1394 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001395}
1396
Eric Laurenta1478072015-09-21 17:21:52 -07001397void lock_input_stream(struct stream_in *in)
1398{
1399 pthread_mutex_lock(&in->pre_lock);
1400 pthread_mutex_lock(&in->lock);
1401 pthread_mutex_unlock(&in->pre_lock);
1402}
1403
1404void lock_output_stream(struct stream_out *out)
1405{
1406 pthread_mutex_lock(&out->pre_lock);
1407 pthread_mutex_lock(&out->lock);
1408 pthread_mutex_unlock(&out->pre_lock);
1409}
1410
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001411/* must be called with out->lock locked */
1412static int send_offload_cmd_l(struct stream_out* out, int command)
1413{
1414 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1415
1416 ALOGVV("%s %d", __func__, command);
1417
1418 cmd->cmd = command;
1419 list_add_tail(&out->offload_cmd_list, &cmd->node);
1420 pthread_cond_signal(&out->offload_cond);
1421 return 0;
1422}
1423
1424/* must be called iwth out->lock locked */
1425static void stop_compressed_output_l(struct stream_out *out)
1426{
1427 out->offload_state = OFFLOAD_STATE_IDLE;
1428 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001429 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001430 if (out->compr != NULL) {
1431 compress_stop(out->compr);
1432 while (out->offload_thread_blocked) {
1433 pthread_cond_wait(&out->cond, &out->lock);
1434 }
1435 }
1436}
1437
1438static void *offload_thread_loop(void *context)
1439{
1440 struct stream_out *out = (struct stream_out *) context;
1441 struct listnode *item;
1442
1443 out->offload_state = OFFLOAD_STATE_IDLE;
1444 out->playback_started = 0;
1445
1446 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1447 set_sched_policy(0, SP_FOREGROUND);
1448 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1449
1450 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001451 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001452 for (;;) {
1453 struct offload_cmd *cmd = NULL;
1454 stream_callback_event_t event;
1455 bool send_callback = false;
1456
1457 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1458 __func__, list_empty(&out->offload_cmd_list),
1459 out->offload_state);
1460 if (list_empty(&out->offload_cmd_list)) {
1461 ALOGV("%s SLEEPING", __func__);
1462 pthread_cond_wait(&out->offload_cond, &out->lock);
1463 ALOGV("%s RUNNING", __func__);
1464 continue;
1465 }
1466
1467 item = list_head(&out->offload_cmd_list);
1468 cmd = node_to_item(item, struct offload_cmd, node);
1469 list_remove(item);
1470
1471 ALOGVV("%s STATE %d CMD %d out->compr %p",
1472 __func__, out->offload_state, cmd->cmd, out->compr);
1473
1474 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1475 free(cmd);
1476 break;
1477 }
1478
1479 if (out->compr == NULL) {
1480 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001481 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001482 pthread_cond_signal(&out->cond);
1483 continue;
1484 }
1485 out->offload_thread_blocked = true;
1486 pthread_mutex_unlock(&out->lock);
1487 send_callback = false;
1488 switch(cmd->cmd) {
1489 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1490 compress_wait(out->compr, -1);
1491 send_callback = true;
1492 event = STREAM_CBK_EVENT_WRITE_READY;
1493 break;
1494 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001495 compress_next_track(out->compr);
1496 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001497 send_callback = true;
1498 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001499 /* Resend the metadata for next iteration */
1500 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001501 break;
1502 case OFFLOAD_CMD_DRAIN:
1503 compress_drain(out->compr);
1504 send_callback = true;
1505 event = STREAM_CBK_EVENT_DRAIN_READY;
1506 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001507 case OFFLOAD_CMD_ERROR:
1508 send_callback = true;
1509 event = STREAM_CBK_EVENT_ERROR;
1510 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001511 default:
1512 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1513 break;
1514 }
Eric Laurenta1478072015-09-21 17:21:52 -07001515 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001516 out->offload_thread_blocked = false;
1517 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001518 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001519 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001520 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001521 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001522 free(cmd);
1523 }
1524
1525 pthread_cond_signal(&out->cond);
1526 while (!list_empty(&out->offload_cmd_list)) {
1527 item = list_head(&out->offload_cmd_list);
1528 list_remove(item);
1529 free(node_to_item(item, struct offload_cmd, node));
1530 }
1531 pthread_mutex_unlock(&out->lock);
1532
1533 return NULL;
1534}
1535
1536static int create_offload_callback_thread(struct stream_out *out)
1537{
1538 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1539 list_init(&out->offload_cmd_list);
1540 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1541 offload_thread_loop, out);
1542 return 0;
1543}
1544
1545static int destroy_offload_callback_thread(struct stream_out *out)
1546{
Eric Laurenta1478072015-09-21 17:21:52 -07001547 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001548 stop_compressed_output_l(out);
1549 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1550
1551 pthread_mutex_unlock(&out->lock);
1552 pthread_join(out->offload_thread, (void **) NULL);
1553 pthread_cond_destroy(&out->offload_cond);
1554
1555 return 0;
1556}
1557
Eric Laurent07eeafd2013-10-06 12:52:49 -07001558static bool allow_hdmi_channel_config(struct audio_device *adev)
1559{
1560 struct listnode *node;
1561 struct audio_usecase *usecase;
1562 bool ret = true;
1563
1564 list_for_each(node, &adev->usecase_list) {
1565 usecase = node_to_item(node, struct audio_usecase, list);
1566 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1567 /*
1568 * If voice call is already existing, do not proceed further to avoid
1569 * disabling/enabling both RX and TX devices, CSD calls, etc.
1570 * Once the voice call done, the HDMI channels can be configured to
1571 * max channels of remaining use cases.
1572 */
1573 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001574 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001575 __func__);
1576 ret = false;
1577 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001578 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1579 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001580 "no change in HDMI channels", __func__);
1581 ret = false;
1582 break;
1583 }
1584 }
1585 }
1586 return ret;
1587}
1588
1589static int check_and_set_hdmi_channels(struct audio_device *adev,
1590 unsigned int channels)
1591{
1592 struct listnode *node;
1593 struct audio_usecase *usecase;
1594
1595 /* Check if change in HDMI channel config is allowed */
1596 if (!allow_hdmi_channel_config(adev))
1597 return 0;
1598
1599 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001600 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001601 return 0;
1602 }
1603
1604 platform_set_hdmi_channels(adev->platform, channels);
1605 adev->cur_hdmi_channels = channels;
1606
1607 /*
1608 * Deroute all the playback streams routed to HDMI so that
1609 * the back end is deactivated. Note that backend will not
1610 * be deactivated if any one stream is connected to it.
1611 */
1612 list_for_each(node, &adev->usecase_list) {
1613 usecase = node_to_item(node, struct audio_usecase, list);
1614 if (usecase->type == PCM_PLAYBACK &&
1615 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001616 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001617 }
1618 }
1619
1620 /*
1621 * Enable all the streams disabled above. Now the HDMI backend
1622 * will be activated with new channel configuration
1623 */
1624 list_for_each(node, &adev->usecase_list) {
1625 usecase = node_to_item(node, struct audio_usecase, list);
1626 if (usecase->type == PCM_PLAYBACK &&
1627 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001628 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001629 }
1630 }
1631
1632 return 0;
1633}
1634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001635static int stop_output_stream(struct stream_out *out)
1636{
1637 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638 struct audio_usecase *uc_info;
1639 struct audio_device *adev = out->dev;
1640
Eric Laurent994a6932013-07-17 11:51:42 -07001641 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001642 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001643 uc_info = get_usecase_from_list(adev, out->usecase);
1644 if (uc_info == NULL) {
1645 ALOGE("%s: Could not find the usecase (%d) in the list",
1646 __func__, out->usecase);
1647 return -EINVAL;
1648 }
1649
Haynes Mathew George41f86652014-06-17 14:22:15 -07001650 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1651 if (adev->visualizer_stop_output != NULL)
1652 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1653 if (adev->offload_effects_stop_output != NULL)
1654 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1655 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001656
Eric Laurent150dbfe2013-02-27 14:31:02 -08001657 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001658 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001659
1660 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001661 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001663 list_remove(&uc_info->list);
1664 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001665
Eric Laurent0499d4f2014-08-25 22:39:29 -05001666 audio_extn_extspk_update(adev->extspk);
1667
Eric Laurent07eeafd2013-10-06 12:52:49 -07001668 /* Must be called after removing the usecase from list */
1669 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1670 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1671
Eric Laurent994a6932013-07-17 11:51:42 -07001672 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673 return ret;
1674}
1675
1676int start_output_stream(struct stream_out *out)
1677{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679 struct audio_usecase *uc_info;
1680 struct audio_device *adev = out->dev;
1681
Eric Laurent994a6932013-07-17 11:51:42 -07001682 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001683 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001684
1685 if (out->card_status == CARD_STATUS_OFFLINE ||
1686 adev->card_status == CARD_STATUS_OFFLINE) {
1687 ALOGW("out->card_status or adev->card_status offline, try again");
1688 ret = -EAGAIN;
1689 goto error_config;
1690 }
1691
Eric Laurentb23d5282013-05-14 15:27:20 -07001692 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001693 if (out->pcm_device_id < 0) {
1694 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1695 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001696 ret = -EINVAL;
1697 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698 }
1699
1700 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1701 uc_info->id = out->usecase;
1702 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001703 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001704 uc_info->devices = out->devices;
1705 uc_info->in_snd_device = SND_DEVICE_NONE;
1706 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707
Eric Laurent07eeafd2013-10-06 12:52:49 -07001708 /* This must be called before adding this usecase to the list */
1709 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1710 check_and_set_hdmi_channels(adev, out->config.channels);
1711
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001712 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001714 audio_extn_perf_lock_acquire();
1715
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001716 select_devices(adev, out->usecase);
1717
Eric Laurent0499d4f2014-08-25 22:39:29 -05001718 audio_extn_extspk_update(adev->extspk);
1719
Andy Hung31aca912014-03-20 17:14:59 -07001720 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001721 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001722 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1723 out->pcm = NULL;
1724 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1725 COMPRESS_IN, &out->compr_config);
1726 if (out->compr && !is_compress_ready(out->compr)) {
1727 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1728 compress_close(out->compr);
1729 out->compr = NULL;
1730 ret = -EIO;
1731 goto error_open;
1732 }
1733 if (out->offload_callback)
1734 compress_nonblock(out->compr, out->non_blocking);
1735
1736 if (adev->visualizer_start_output != NULL)
1737 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1738 if (adev->offload_effects_start_output != NULL)
1739 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1740 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001741 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001742 ALOGE("%s: pcm stream not ready", __func__);
1743 goto error_open;
1744 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001745 ret = pcm_start(out->pcm);
1746 if (ret < 0) {
1747 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1748 goto error_open;
1749 }
1750 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001751 unsigned int flags = PCM_OUT;
1752 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001753
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001754 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1755 flags |= PCM_MMAP | PCM_NOIRQ;
1756 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001757 } else if (out->realtime) {
1758 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001759 } else
1760 flags |= PCM_MONOTONIC;
1761
1762 while (1) {
1763 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1764 flags, &out->config);
1765 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1766 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1767 if (out->pcm != NULL) {
1768 pcm_close(out->pcm);
1769 out->pcm = NULL;
1770 }
1771 if (pcm_open_retry_count-- == 0) {
1772 ret = -EIO;
1773 goto error_open;
1774 }
1775 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1776 continue;
1777 }
1778 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001779 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001780 ALOGV("%s: pcm_prepare", __func__);
1781 if (pcm_is_ready(out->pcm)) {
1782 ret = pcm_prepare(out->pcm);
1783 if (ret < 0) {
1784 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1785 pcm_close(out->pcm);
1786 out->pcm = NULL;
1787 goto error_open;
1788 }
1789 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001790 if (out->realtime) {
1791 ret = pcm_start(out->pcm);
1792 if (ret < 0) {
1793 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1794 pcm_close(out->pcm);
1795 out->pcm = NULL;
1796 goto error_open;
1797 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001798 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001799 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001800 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001801 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001802 audio_extn_tfa_98xx_enable_speaker();
1803
Eric Laurent994a6932013-07-17 11:51:42 -07001804 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001805 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001806error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001807 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001808 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001809error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001810 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811}
1812
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813static int check_input_parameters(uint32_t sample_rate,
1814 audio_format_t format,
1815 int channel_count)
1816{
vivek mehta4ed66e62016-04-15 23:33:34 -07001817 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001818 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1819 return -EINVAL;
1820 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001821
vivek mehtadae44712015-07-27 14:13:18 -07001822 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001823 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001824 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1825 return -EINVAL;
1826 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001827
1828 switch (sample_rate) {
1829 case 8000:
1830 case 11025:
1831 case 12000:
1832 case 16000:
1833 case 22050:
1834 case 24000:
1835 case 32000:
1836 case 44100:
1837 case 48000:
1838 break;
1839 default:
vivek mehtadae44712015-07-27 14:13:18 -07001840 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001841 return -EINVAL;
1842 }
1843
1844 return 0;
1845}
1846
1847static size_t get_input_buffer_size(uint32_t sample_rate,
1848 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001849 int channel_count,
1850 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851{
1852 size_t size = 0;
1853
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001854 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1855 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001857 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001858 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001859 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001860
1861 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862
Glenn Kasten4f993392014-05-14 07:30:48 -07001863 /* make sure the size is multiple of 32 bytes
1864 * At 48 kHz mono 16-bit PCM:
1865 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1866 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1867 */
1868 size += 0x1f;
1869 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001870
1871 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001872}
1873
1874static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1875{
1876 struct stream_out *out = (struct stream_out *)stream;
1877
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001878 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879}
1880
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001881static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882{
1883 return -ENOSYS;
1884}
1885
1886static size_t out_get_buffer_size(const struct audio_stream *stream)
1887{
1888 struct stream_out *out = (struct stream_out *)stream;
1889
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001890 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1891 return out->compr_config.fragment_size;
1892 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001893 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001894 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001895}
1896
1897static uint32_t out_get_channels(const struct audio_stream *stream)
1898{
1899 struct stream_out *out = (struct stream_out *)stream;
1900
1901 return out->channel_mask;
1902}
1903
1904static audio_format_t out_get_format(const struct audio_stream *stream)
1905{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001906 struct stream_out *out = (struct stream_out *)stream;
1907
1908 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001909}
1910
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001911static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001912{
1913 return -ENOSYS;
1914}
1915
1916static int out_standby(struct audio_stream *stream)
1917{
1918 struct stream_out *out = (struct stream_out *)stream;
1919 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001920 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001921
Eric Laurent994a6932013-07-17 11:51:42 -07001922 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001923 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001924
Eric Laurenta1478072015-09-21 17:21:52 -07001925 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001927 if (adev->adm_deregister_stream)
1928 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001929 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001931 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1932 if (out->pcm) {
1933 pcm_close(out->pcm);
1934 out->pcm = NULL;
1935 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001936 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001937 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08001938 out->playback_started = false;
1939 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001940 } else {
1941 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001942 out->gapless_mdata.encoder_delay = 0;
1943 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001944 if (out->compr != NULL) {
1945 compress_close(out->compr);
1946 out->compr = NULL;
1947 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001948 }
Phil Burkbc991042017-02-24 08:06:44 -08001949 if (do_stop) {
1950 stop_output_stream(out);
1951 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001952 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953 }
1954 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001955 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956 return 0;
1957}
1958
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001959static int out_on_error(struct audio_stream *stream)
1960{
1961 struct stream_out *out = (struct stream_out *)stream;
1962 struct audio_device *adev = out->dev;
1963 bool do_standby = false;
1964
1965 lock_output_stream(out);
1966 if (!out->standby) {
1967 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1968 stop_compressed_output_l(out);
1969 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1970 } else
1971 do_standby = true;
1972 }
1973 pthread_mutex_unlock(&out->lock);
1974
1975 if (do_standby)
1976 return out_standby(&out->stream.common);
1977
1978 return 0;
1979}
1980
Andy Hung7401c7c2016-09-21 12:41:21 -07001981static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982{
Andy Hung7401c7c2016-09-21 12:41:21 -07001983 struct stream_out *out = (struct stream_out *)stream;
1984
1985 // We try to get the lock for consistency,
1986 // but it isn't necessary for these variables.
1987 // If we're not in standby, we may be blocked on a write.
1988 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1989 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1990 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1991
1992 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07001993 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07001994 }
Andy Hunga452b0a2017-03-15 14:51:15 -07001995
1996 // dump error info
1997 (void)error_log_dump(
1998 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07001999 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07002000 (void)power_log_dump(
2001 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002 return 0;
2003}
2004
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002005static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2006{
2007 int ret = 0;
2008 char value[32];
2009 struct compr_gapless_mdata tmp_mdata;
2010
2011 if (!out || !parms) {
2012 return -EINVAL;
2013 }
2014
2015 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2016 if (ret >= 0) {
2017 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2018 } else {
2019 return -EINVAL;
2020 }
2021
2022 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2023 if (ret >= 0) {
2024 tmp_mdata.encoder_padding = atoi(value);
2025 } else {
2026 return -EINVAL;
2027 }
2028
2029 out->gapless_mdata = tmp_mdata;
2030 out->send_new_metadata = 1;
2031 ALOGV("%s new encoder delay %u and padding %u", __func__,
2032 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2033
2034 return 0;
2035}
2036
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002037static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2038{
2039 return out == adev->primary_output || out == adev->voice_tx_output;
2040}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002041
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2043{
2044 struct stream_out *out = (struct stream_out *)stream;
2045 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002046 struct audio_usecase *usecase;
2047 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048 struct str_parms *parms;
2049 char value[32];
2050 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002051 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002052 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002053
Eric Laurent2e140aa2016-06-30 17:14:46 -07002054 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002055 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056 parms = str_parms_create_str(kvpairs);
2057 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2058 if (ret >= 0) {
2059 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002060 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002061 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002062
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002063 /*
2064 * When HDMI cable is unplugged the music playback is paused and
2065 * the policy manager sends routing=0. But the audioflinger
2066 * continues to write data until standby time (3sec).
2067 * As the HDMI core is turned off, the write gets blocked.
2068 * Avoid this by routing audio to speaker until standby.
2069 */
2070 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2071 val == AUDIO_DEVICE_NONE) {
2072 val = AUDIO_DEVICE_OUT_SPEAKER;
2073 }
2074
2075 /*
2076 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002077 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002078 * the select_devices(). But how do we undo this?
2079 *
2080 * For example, music playback is active on headset (deep-buffer usecase)
2081 * and if we go to ringtones and select a ringtone, low-latency usecase
2082 * will be started on headset+speaker. As we can't enable headset+speaker
2083 * and headset devices at the same time, select_devices() switches the music
2084 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2085 * So when the ringtone playback is completed, how do we undo the same?
2086 *
2087 * We are relying on the out_set_parameters() call on deep-buffer output,
2088 * once the ringtone playback is ended.
2089 * NOTE: We should not check if the current devices are same as new devices.
2090 * Because select_devices() must be called to switch back the music
2091 * playback to headset.
2092 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002093 audio_devices_t new_dev = val;
2094 if (new_dev != AUDIO_DEVICE_NONE) {
2095 bool same_dev = out->devices == new_dev;
2096 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002097
Eric Laurenta7657192014-10-09 21:09:33 -07002098 if (output_drives_call(adev, out)) {
2099 if (!voice_is_in_call(adev)) {
2100 if (adev->mode == AUDIO_MODE_IN_CALL) {
2101 adev->current_call_output = out;
2102 ret = voice_start_call(adev);
2103 }
2104 } else {
2105 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002106 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002107 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002108 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002109
2110 if (!out->standby) {
2111 if (!same_dev) {
2112 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002113 // inform adm before actual routing to prevent glitches.
2114 if (adev->adm_on_routing_change) {
2115 adev->adm_on_routing_change(adev->adm_data,
2116 out->handle);
2117 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002118 }
2119 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002120 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002121 }
2122
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002123 }
2124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002126 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002127
2128 /*handles device and call state changes*/
2129 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002131
2132 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2133 parse_compress_metadata(out, parms);
2134 }
2135
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002136 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002137 ALOGV("%s: exit: code(%d)", __func__, status);
2138 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002139}
2140
2141static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2142{
2143 struct stream_out *out = (struct stream_out *)stream;
2144 struct str_parms *query = str_parms_create_str(keys);
2145 char *str;
2146 char value[256];
2147 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002148 bool replied = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149 size_t i, j;
2150 int ret;
2151 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002152 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2154 if (ret >= 0) {
2155 value[0] = '\0';
2156 i = 0;
2157 while (out->supported_channel_masks[i] != 0) {
2158 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2159 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2160 if (!first) {
2161 strcat(value, "|");
2162 }
2163 strcat(value, out_channels_name_to_enum_table[j].name);
2164 first = false;
2165 break;
2166 }
2167 }
2168 i++;
2169 }
2170 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002171 replied = true;
2172 }
2173
2174 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2175 if (ret >= 0) {
2176 value[0] = '\0';
2177 switch (out->supported_formats[0]) {
2178 case AUDIO_FORMAT_PCM_16_BIT:
2179 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2180 break;
2181 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2182 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2183 break;
2184 case AUDIO_FORMAT_PCM_32_BIT:
2185 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2186 break;
2187 default:
2188 ALOGE("%s: unsupported format %#x", __func__,
2189 out->supported_formats[0]);
2190 break;
2191 }
2192 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2193 replied = true;
2194 }
2195
2196 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2197 value, sizeof(value));
2198 if (ret >= 0) {
2199 value[0] = '\0';
2200 i=0;
2201 int cursor = 0;
2202 while (out->supported_sample_rates[i]) {
2203 int avail = sizeof(value) - cursor;
2204 ret = snprintf(value + cursor, avail, "%s%d",
2205 cursor > 0 ? "|" : "",
2206 out->supported_sample_rates[i]);
2207 if (ret < 0 || ret >= avail) {
2208 // if cursor is at the last element of the array
2209 // overwrite with \0 is duplicate work as
2210 // snprintf already put a \0 in place.
2211 // else
2212 // we had space to write the '|' at value[cursor]
2213 // (which will be overwritten) or no space to fill
2214 // the first element (=> cursor == 0)
2215 value[cursor] = '\0';
2216 break;
2217 }
2218 cursor += ret;
2219 ++i;
2220 }
2221 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2222 value);
2223 replied = true;
2224 }
2225
2226 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227 str = str_parms_to_str(reply);
2228 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002229 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230 }
2231 str_parms_destroy(query);
2232 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002233 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234 return str;
2235}
2236
2237static uint32_t out_get_latency(const struct audio_stream_out *stream)
2238{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002239 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240 struct stream_out *out = (struct stream_out *)stream;
2241
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002242 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2243 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002244 else if ((out->realtime) ||
2245 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002246 // since the buffer won't be filled up faster than realtime,
2247 // return a smaller number
2248 period_ms = (out->af_period_multiplier * out->config.period_size *
2249 1000) / (out->config.rate);
2250 hw_delay = platform_render_latency(out->usecase)/1000;
2251 return period_ms + hw_delay;
2252 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002253
2254 return (out->config.period_count * out->config.period_size * 1000) /
2255 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256}
2257
2258static int out_set_volume(struct audio_stream_out *stream, float left,
2259 float right)
2260{
Eric Laurenta9024de2013-04-04 09:19:12 -07002261 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002262 int volume[2];
2263
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002264 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002265 /* only take left channel into account: the API is for stereo anyway */
2266 out->muted = (left == 0.0f);
2267 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002268 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2269 const char *mixer_ctl_name = "Compress Playback Volume";
2270 struct audio_device *adev = out->dev;
2271 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002272 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2273 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002274 /* try with the control based on device id */
2275 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2276 PCM_PLAYBACK);
2277 char ctl_name[128] = {0};
2278 snprintf(ctl_name, sizeof(ctl_name),
2279 "Compress Playback %d Volume", pcm_device_id);
2280 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2281 if (!ctl) {
2282 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2283 return -EINVAL;
2284 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002285 }
2286 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2287 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2288 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2289 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002290 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002291
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002292 return -ENOSYS;
2293}
2294
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002295// note: this call is safe only if the stream_cb is
2296// removed first in close_output_stream (as is done now).
2297static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2298{
2299 if (!stream || !parms)
2300 return;
2301
2302 struct stream_out *out = (struct stream_out *)stream;
2303 struct audio_device *adev = out->dev;
2304
2305 card_status_t status;
2306 int card;
2307 if (parse_snd_card_status(parms, &card, &status) < 0)
2308 return;
2309
2310 pthread_mutex_lock(&adev->lock);
2311 bool valid_cb = (card == adev->snd_card);
2312 pthread_mutex_unlock(&adev->lock);
2313
2314 if (!valid_cb)
2315 return;
2316
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002317 lock_output_stream(out);
2318 if (out->card_status != status)
2319 out->card_status = status;
2320 pthread_mutex_unlock(&out->lock);
2321
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002322 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2323 use_case_table[out->usecase],
2324 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2325
2326 if (status == CARD_STATUS_OFFLINE)
2327 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002328
2329 return;
2330}
2331
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002332#ifdef NO_AUDIO_OUT
2333static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002334 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002335{
2336 struct stream_out *out = (struct stream_out *)stream;
2337
2338 /* No Output device supported other than BT for playback.
2339 * Sleep for the amount of buffer duration
2340 */
Eric Laurenta1478072015-09-21 17:21:52 -07002341 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002342 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2343 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002344 out_get_sample_rate(&out->stream.common));
2345 pthread_mutex_unlock(&out->lock);
2346 return bytes;
2347}
2348#endif
2349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2351 size_t bytes)
2352{
2353 struct stream_out *out = (struct stream_out *)stream;
2354 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002355 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002356 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002357
Eric Laurenta1478072015-09-21 17:21:52 -07002358 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002359 // this is always nonzero
2360 const int frame_size = audio_stream_out_frame_size(stream);
2361
Eric Laurent0e46adf2016-12-16 12:49:24 -08002362 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2363 error_code = ERROR_CODE_WRITE;
2364 goto exit;
2365 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002366 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002367 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002368 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002369 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002370 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002372 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002373 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374 goto exit;
2375 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002376
2377 if (last_known_cal_step != -1) {
2378 ALOGD("%s: retry previous failed cal level set", __func__);
2379 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2380 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002381 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002383 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002384 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002385 if (out->send_new_metadata) {
2386 ALOGVV("send new gapless metadata");
2387 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2388 out->send_new_metadata = 0;
2389 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002390 unsigned int avail;
2391 struct timespec tstamp;
2392 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2393 /* Do not limit write size if the available frames count is unknown */
2394 if (ret != 0) {
2395 avail = bytes;
2396 }
2397 if (avail == 0) {
2398 ret = 0;
2399 } else {
2400 if (avail > bytes) {
2401 avail = bytes;
2402 }
2403 ret = compress_write(out->compr, buffer, avail);
2404 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2405 __func__, avail, ret);
2406 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002407
Eric Laurent6e895242013-09-05 16:10:57 -07002408 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002409 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2410 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002411 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002412 compress_start(out->compr);
2413 out->playback_started = 1;
2414 out->offload_state = OFFLOAD_STATE_PLAYING;
2415 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002416 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002417 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002418 } else {
2419 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002420 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002421 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002422 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002423 return ret;
2424 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002425 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002426 if (out->pcm) {
2427 if (out->muted)
2428 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002429
Eric Laurent0e46adf2016-12-16 12:49:24 -08002430 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002431
Haynes Mathew George03c40102016-01-29 17:57:48 -08002432 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2433 out->config.rate;
2434 request_out_focus(out, ns);
2435
2436 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2437 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002438 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002439 else
2440 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002441
Haynes Mathew George03c40102016-01-29 17:57:48 -08002442 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002443 } else {
2444 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002445 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002446 }
2447
2448exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002449 // For PCM we always consume the buffer and return #bytes regardless of ret.
2450 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2451 out->written += bytes / (out->config.channels * sizeof(short));
2452 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002453 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002454
2455 // only get time if needed for logging, as it is a system call on 32 bit devices.
2456 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2457 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2458 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002459
Andy Hung7401c7c2016-09-21 12:41:21 -07002460 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002461 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002462 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2463 ALOGE_IF(out->pcm != NULL,
2464 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hungfc044e12017-03-20 09:24:22 -07002465 sleeptime_us = bytes * 1000000LL / frame_size /
Andy Hung7401c7c2016-09-21 12:41:21 -07002466 out_get_sample_rate(&out->stream.common);
2467 // usleep not guaranteed for values over 1 second but we don't limit here.
2468 }
2469 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002470
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002471 pthread_mutex_unlock(&out->lock);
2472
2473 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002474 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002475 if (sleeptime_us != 0)
2476 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002477 } else {
2478 // only log if the data is properly written (out->power_log may be null)
2479 power_log_log(out->power_log, buffer, bytes / frame_size, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480 }
2481 return bytes;
2482}
2483
2484static int out_get_render_position(const struct audio_stream_out *stream,
2485 uint32_t *dsp_frames)
2486{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002487 struct stream_out *out = (struct stream_out *)stream;
2488 *dsp_frames = 0;
2489 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002490 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002491 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002492 unsigned long frames = 0;
2493 // TODO: check return value
2494 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2495 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002496 ALOGVV("%s rendered frames %d sample_rate %d",
2497 __func__, *dsp_frames, out->sample_rate);
2498 }
2499 pthread_mutex_unlock(&out->lock);
2500 return 0;
2501 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002502 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503}
2504
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002505static int out_add_audio_effect(const struct audio_stream *stream __unused,
2506 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507{
2508 return 0;
2509}
2510
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002511static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2512 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513{
2514 return 0;
2515}
2516
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002517static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2518 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002520 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521}
2522
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002523static int out_get_presentation_position(const struct audio_stream_out *stream,
2524 uint64_t *frames, struct timespec *timestamp)
2525{
2526 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002527 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002528 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002529
Eric Laurenta1478072015-09-21 17:21:52 -07002530 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002531
Eric Laurent949a0892013-09-20 09:20:13 -07002532 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2533 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002534 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002535 compress_get_tstamp(out->compr, &dsp_frames,
2536 &out->sample_rate);
2537 ALOGVV("%s rendered frames %ld sample_rate %d",
2538 __func__, dsp_frames, out->sample_rate);
2539 *frames = dsp_frames;
2540 ret = 0;
2541 /* this is the best we can do */
2542 clock_gettime(CLOCK_MONOTONIC, timestamp);
2543 }
2544 } else {
2545 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002546 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002547 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2548 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002549 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002550 // This adjustment accounts for buffering after app processor.
2551 // It is based on estimated DSP latency per use case, rather than exact.
2552 signed_frames -=
2553 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2554
Eric Laurent949a0892013-09-20 09:20:13 -07002555 // It would be unusual for this value to be negative, but check just in case ...
2556 if (signed_frames >= 0) {
2557 *frames = signed_frames;
2558 ret = 0;
2559 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002560 }
2561 }
2562 }
2563
2564 pthread_mutex_unlock(&out->lock);
2565
2566 return ret;
2567}
2568
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002569static int out_set_callback(struct audio_stream_out *stream,
2570 stream_callback_t callback, void *cookie)
2571{
2572 struct stream_out *out = (struct stream_out *)stream;
2573
2574 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002575 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002576 out->offload_callback = callback;
2577 out->offload_cookie = cookie;
2578 pthread_mutex_unlock(&out->lock);
2579 return 0;
2580}
2581
2582static int out_pause(struct audio_stream_out* stream)
2583{
2584 struct stream_out *out = (struct stream_out *)stream;
2585 int status = -ENOSYS;
2586 ALOGV("%s", __func__);
2587 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002588 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002589 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2590 status = compress_pause(out->compr);
2591 out->offload_state = OFFLOAD_STATE_PAUSED;
2592 }
2593 pthread_mutex_unlock(&out->lock);
2594 }
2595 return status;
2596}
2597
2598static int out_resume(struct audio_stream_out* stream)
2599{
2600 struct stream_out *out = (struct stream_out *)stream;
2601 int status = -ENOSYS;
2602 ALOGV("%s", __func__);
2603 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2604 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002605 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002606 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2607 status = compress_resume(out->compr);
2608 out->offload_state = OFFLOAD_STATE_PLAYING;
2609 }
2610 pthread_mutex_unlock(&out->lock);
2611 }
2612 return status;
2613}
2614
2615static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2616{
2617 struct stream_out *out = (struct stream_out *)stream;
2618 int status = -ENOSYS;
2619 ALOGV("%s", __func__);
2620 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002621 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002622 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2623 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2624 else
2625 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2626 pthread_mutex_unlock(&out->lock);
2627 }
2628 return status;
2629}
2630
2631static int out_flush(struct audio_stream_out* stream)
2632{
2633 struct stream_out *out = (struct stream_out *)stream;
2634 ALOGV("%s", __func__);
2635 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002636 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002637 stop_compressed_output_l(out);
2638 pthread_mutex_unlock(&out->lock);
2639 return 0;
2640 }
2641 return -ENOSYS;
2642}
2643
Eric Laurent0e46adf2016-12-16 12:49:24 -08002644static int out_stop(const struct audio_stream_out* stream)
2645{
2646 struct stream_out *out = (struct stream_out *)stream;
2647 struct audio_device *adev = out->dev;
2648 int ret = -ENOSYS;
2649
2650 ALOGV("%s", __func__);
2651 pthread_mutex_lock(&adev->lock);
2652 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2653 out->playback_started && out->pcm != NULL) {
2654 pcm_stop(out->pcm);
2655 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002656 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002657 }
2658 pthread_mutex_unlock(&adev->lock);
2659 return ret;
2660}
2661
2662static int out_start(const struct audio_stream_out* stream)
2663{
2664 struct stream_out *out = (struct stream_out *)stream;
2665 struct audio_device *adev = out->dev;
2666 int ret = -ENOSYS;
2667
2668 ALOGV("%s", __func__);
2669 pthread_mutex_lock(&adev->lock);
2670 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2671 !out->playback_started && out->pcm != NULL) {
2672 ret = start_output_stream(out);
2673 if (ret == 0) {
2674 out->playback_started = true;
2675 }
2676 }
2677 pthread_mutex_unlock(&adev->lock);
2678 return ret;
2679}
2680
Phil Burkbc991042017-02-24 08:06:44 -08002681/*
2682 * Modify config->period_count based on min_size_frames
2683 */
2684static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2685{
2686 int periodCountRequested = (min_size_frames + config->period_size - 1)
2687 / config->period_size;
2688 int periodCount = MMAP_PERIOD_COUNT_MIN;
2689
2690 ALOGV("%s original config.period_size = %d config.period_count = %d",
2691 __func__, config->period_size, config->period_count);
2692
2693 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2694 periodCount *= 2;
2695 }
2696 config->period_count = periodCount;
2697
2698 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2699}
2700
Eric Laurent0e46adf2016-12-16 12:49:24 -08002701static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2702 int32_t min_size_frames,
2703 struct audio_mmap_buffer_info *info)
2704{
2705 struct stream_out *out = (struct stream_out *)stream;
2706 struct audio_device *adev = out->dev;
2707 int ret = 0;
2708 unsigned int offset1;
2709 unsigned int frames1;
2710 const char *step = "";
2711
2712 ALOGV("%s", __func__);
2713 pthread_mutex_lock(&adev->lock);
2714
2715 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002716 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002717 ret = -EINVAL;
2718 goto exit;
2719 }
2720 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002721 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002722 ret = -ENOSYS;
2723 goto exit;
2724 }
2725 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2726 if (out->pcm_device_id < 0) {
2727 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2728 __func__, out->pcm_device_id, out->usecase);
2729 ret = -EINVAL;
2730 goto exit;
2731 }
Phil Burkbc991042017-02-24 08:06:44 -08002732
2733 adjust_mmap_period_count(&out->config, min_size_frames);
2734
Eric Laurent0e46adf2016-12-16 12:49:24 -08002735 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2736 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2737 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2738 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2739 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2740 step = "open";
2741 ret = -ENODEV;
2742 goto exit;
2743 }
2744 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2745 if (ret < 0) {
2746 step = "begin";
2747 goto exit;
2748 }
2749 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2750 info->burst_size_frames = out->config.period_size;
2751 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2752
2753 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2754 info->buffer_size_frames));
2755
2756 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2757 if (ret < 0) {
2758 step = "commit";
2759 goto exit;
2760 }
Phil Burkbc991042017-02-24 08:06:44 -08002761
2762 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002763 ret = 0;
2764
2765 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2766 __func__, info->shared_memory_address, info->buffer_size_frames);
2767
2768exit:
2769 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002770 if (out->pcm == NULL) {
2771 ALOGE("%s: %s - %d", __func__, step, ret);
2772 } else {
2773 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002774 pcm_close(out->pcm);
2775 out->pcm = NULL;
2776 }
2777 }
2778 pthread_mutex_unlock(&adev->lock);
2779 return ret;
2780}
2781
2782static int out_get_mmap_position(const struct audio_stream_out *stream,
2783 struct audio_mmap_position *position)
2784{
2785 struct stream_out *out = (struct stream_out *)stream;
2786 ALOGVV("%s", __func__);
2787 if (position == NULL) {
2788 return -EINVAL;
2789 }
2790 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2791 return -ENOSYS;
2792 }
2793 if (out->pcm == NULL) {
2794 return -ENOSYS;
2795 }
2796
2797 struct timespec ts = { 0, 0 };
2798 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2799 if (ret < 0) {
2800 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2801 return ret;
2802 }
Andy Hungfc044e12017-03-20 09:24:22 -07002803 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002804 return 0;
2805}
2806
2807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808/** audio_stream_in implementation **/
2809static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2810{
2811 struct stream_in *in = (struct stream_in *)stream;
2812
2813 return in->config.rate;
2814}
2815
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002816static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002817{
2818 return -ENOSYS;
2819}
2820
2821static size_t in_get_buffer_size(const struct audio_stream *stream)
2822{
2823 struct stream_in *in = (struct stream_in *)stream;
2824
Haynes Mathew George03c40102016-01-29 17:57:48 -08002825 return in->config.period_size * in->af_period_multiplier *
2826 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827}
2828
2829static uint32_t in_get_channels(const struct audio_stream *stream)
2830{
2831 struct stream_in *in = (struct stream_in *)stream;
2832
2833 return in->channel_mask;
2834}
2835
vivek mehta4ed66e62016-04-15 23:33:34 -07002836static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002837{
vivek mehta4ed66e62016-04-15 23:33:34 -07002838 struct stream_in *in = (struct stream_in *)stream;
2839 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840}
2841
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002842static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002843{
2844 return -ENOSYS;
2845}
2846
2847static int in_standby(struct audio_stream *stream)
2848{
2849 struct stream_in *in = (struct stream_in *)stream;
2850 struct audio_device *adev = in->dev;
2851 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002852 bool do_stop = true;
2853
Eric Laurent994a6932013-07-17 11:51:42 -07002854 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002855
2856 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002857
2858 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002859 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002860 audio_extn_sound_trigger_stop_lab(in);
2861 in->standby = true;
2862 }
2863
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002864 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002865 if (adev->adm_deregister_stream)
2866 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2867
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002868 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002869 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002870 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002871 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002872 in->capture_started = false;
2873 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002874 if (in->pcm) {
2875 pcm_close(in->pcm);
2876 in->pcm = NULL;
2877 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002878 adev->enable_voicerx = false;
2879 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002880 if (do_stop) {
2881 status = stop_input_stream(in);
2882 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002883 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002884 }
2885 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002886 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887 return status;
2888}
2889
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002890static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891{
2892 return 0;
2893}
2894
2895static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2896{
2897 struct stream_in *in = (struct stream_in *)stream;
2898 struct audio_device *adev = in->dev;
2899 struct str_parms *parms;
2900 char *str;
2901 char value[32];
2902 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002903 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002904
Eric Laurent994a6932013-07-17 11:51:42 -07002905 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002906 parms = str_parms_create_str(kvpairs);
2907
2908 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2909
Eric Laurenta1478072015-09-21 17:21:52 -07002910 lock_input_stream(in);
2911
Eric Laurent150dbfe2013-02-27 14:31:02 -08002912 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002913 if (ret >= 0) {
2914 val = atoi(value);
2915 /* no audio source uses val == 0 */
2916 if ((in->source != val) && (val != 0)) {
2917 in->source = val;
2918 }
2919 }
2920
2921 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002922
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002923 if (ret >= 0) {
2924 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002925 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002926 in->device = val;
2927 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002928 if (!in->standby) {
2929 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002930 // inform adm before actual routing to prevent glitches.
2931 if (adev->adm_on_routing_change) {
2932 adev->adm_on_routing_change(adev->adm_data,
2933 in->capture_handle);
2934 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002935 select_devices(adev, in->usecase);
2936 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002937 }
2938 }
2939
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002940 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002941 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942
2943 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002944 ALOGV("%s: exit: status(%d)", __func__, status);
2945 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946}
2947
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002948static char* in_get_parameters(const struct audio_stream *stream __unused,
2949 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002950{
2951 return strdup("");
2952}
2953
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002954static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002955{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002956 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002957}
2958
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002959static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2960{
2961 if (!stream || !parms)
2962 return;
2963
2964 struct stream_in *in = (struct stream_in *)stream;
2965 struct audio_device *adev = in->dev;
2966
2967 card_status_t status;
2968 int card;
2969 if (parse_snd_card_status(parms, &card, &status) < 0)
2970 return;
2971
2972 pthread_mutex_lock(&adev->lock);
2973 bool valid_cb = (card == adev->snd_card);
2974 pthread_mutex_unlock(&adev->lock);
2975
2976 if (!valid_cb)
2977 return;
2978
2979 lock_input_stream(in);
2980 if (in->card_status != status)
2981 in->card_status = status;
2982 pthread_mutex_unlock(&in->lock);
2983
2984 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2985 use_case_table[in->usecase],
2986 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2987
2988 // a better solution would be to report error back to AF and let
2989 // it put the stream to standby
2990 if (status == CARD_STATUS_OFFLINE)
2991 in_standby(&in->stream.common);
2992
2993 return;
2994}
2995
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2997 size_t bytes)
2998{
2999 struct stream_in *in = (struct stream_in *)stream;
3000 struct audio_device *adev = in->dev;
3001 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003002 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003
Eric Laurenta1478072015-09-21 17:21:52 -07003004 lock_input_stream(in);
3005
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003006 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003007 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003008 /* Read from sound trigger HAL */
3009 audio_extn_sound_trigger_read(in, buffer, bytes);
3010 pthread_mutex_unlock(&in->lock);
3011 return bytes;
3012 }
3013
Eric Laurent0e46adf2016-12-16 12:49:24 -08003014 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3015 ret = -ENOSYS;
3016 goto exit;
3017 }
3018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003020 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003022 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024 goto exit;
3025 }
3026 in->standby = 0;
3027 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028
Haynes Mathew George03c40102016-01-29 17:57:48 -08003029 //what's the duration requested by the client?
3030 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3031 in->config.rate;
3032 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003033
Haynes Mathew George03c40102016-01-29 17:57:48 -08003034 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003036 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003037 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003038 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003039 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003040 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003041 if (ret < 0) {
3042 ALOGE("Failed to read w/err %s", strerror(errno));
3043 ret = -errno;
3044 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003045 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3046 if (bytes % 4 == 0) {
3047 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3048 int_buf_stream = buffer;
3049 for (size_t itt=0; itt < bytes/4 ; itt++) {
3050 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003051 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003052 } else {
3053 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3054 ret = -EINVAL;
3055 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003056 }
3057 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058 }
3059
Haynes Mathew George03c40102016-01-29 17:57:48 -08003060 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003061
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062 /*
3063 * Instead of writing zeroes here, we could trust the hardware
3064 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003065 * 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 -08003066 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003067 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068 memset(buffer, 0, bytes);
3069
3070exit:
3071 pthread_mutex_unlock(&in->lock);
3072
3073 if (ret != 0) {
3074 in_standby(&in->stream.common);
3075 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07003076 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003078 memset(buffer, 0, bytes); // clear return data
3079 }
3080 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08003081 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082 }
3083 return bytes;
3084}
3085
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003086static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003087{
3088 return 0;
3089}
3090
Andy Hung6ebe5962016-01-15 17:46:57 -08003091static int in_get_capture_position(const struct audio_stream_in *stream,
3092 int64_t *frames, int64_t *time)
3093{
3094 if (stream == NULL || frames == NULL || time == NULL) {
3095 return -EINVAL;
3096 }
3097 struct stream_in *in = (struct stream_in *)stream;
3098 int ret = -ENOSYS;
3099
3100 lock_input_stream(in);
3101 if (in->pcm) {
3102 struct timespec timestamp;
3103 unsigned int avail;
3104 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3105 *frames = in->frames_read + avail;
3106 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3107 ret = 0;
3108 }
3109 }
3110 pthread_mutex_unlock(&in->lock);
3111 return ret;
3112}
3113
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003114static int add_remove_audio_effect(const struct audio_stream *stream,
3115 effect_handle_t effect,
3116 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003118 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003119 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003120 int status = 0;
3121 effect_descriptor_t desc;
3122
3123 status = (*effect)->get_descriptor(effect, &desc);
3124 if (status != 0)
3125 return status;
3126
Eric Laurenta1478072015-09-21 17:21:52 -07003127 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003128 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003129 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003130 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003131 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003132 in->enable_aec != enable &&
3133 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3134 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003135 if (!enable)
3136 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003137 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3138 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3139 adev->enable_voicerx = enable;
3140 struct audio_usecase *usecase;
3141 struct listnode *node;
3142 list_for_each(node, &adev->usecase_list) {
3143 usecase = node_to_item(node, struct audio_usecase, list);
3144 if (usecase->type == PCM_PLAYBACK) {
3145 select_devices(adev, usecase->id);
3146 break;
3147 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003148 }
3149 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003150 if (!in->standby)
3151 select_devices(in->dev, in->usecase);
3152 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003153 if (in->enable_ns != enable &&
3154 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3155 in->enable_ns = enable;
3156 if (!in->standby)
3157 select_devices(in->dev, in->usecase);
3158 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003159 pthread_mutex_unlock(&in->dev->lock);
3160 pthread_mutex_unlock(&in->lock);
3161
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162 return 0;
3163}
3164
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003165static int in_add_audio_effect(const struct audio_stream *stream,
3166 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003167{
Eric Laurent994a6932013-07-17 11:51:42 -07003168 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003169 return add_remove_audio_effect(stream, effect, true);
3170}
3171
3172static int in_remove_audio_effect(const struct audio_stream *stream,
3173 effect_handle_t effect)
3174{
Eric Laurent994a6932013-07-17 11:51:42 -07003175 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003176 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003177}
3178
Eric Laurent0e46adf2016-12-16 12:49:24 -08003179static int in_stop(const struct audio_stream_in* stream)
3180{
3181 struct stream_in *in = (struct stream_in *)stream;
3182 struct audio_device *adev = in->dev;
3183
3184 int ret = -ENOSYS;
3185 ALOGV("%s", __func__);
3186 pthread_mutex_lock(&adev->lock);
3187 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3188 in->capture_started && in->pcm != NULL) {
3189 pcm_stop(in->pcm);
3190 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003191 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003192 }
3193 pthread_mutex_unlock(&adev->lock);
3194 return ret;
3195}
3196
3197static int in_start(const struct audio_stream_in* stream)
3198{
3199 struct stream_in *in = (struct stream_in *)stream;
3200 struct audio_device *adev = in->dev;
3201 int ret = -ENOSYS;
3202
3203 ALOGV("%s in %p", __func__, in);
3204 pthread_mutex_lock(&adev->lock);
3205 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3206 !in->capture_started && in->pcm != NULL) {
3207 if (!in->capture_started) {
3208 ret = start_input_stream(in);
3209 if (ret == 0) {
3210 in->capture_started = true;
3211 }
3212 }
3213 }
3214 pthread_mutex_unlock(&adev->lock);
3215 return ret;
3216}
3217
3218static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3219 int32_t min_size_frames,
3220 struct audio_mmap_buffer_info *info)
3221{
3222 struct stream_in *in = (struct stream_in *)stream;
3223 struct audio_device *adev = in->dev;
3224 int ret = 0;
3225 unsigned int offset1;
3226 unsigned int frames1;
3227 const char *step = "";
3228
3229 pthread_mutex_lock(&adev->lock);
3230 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003231
Eric Laurent0e46adf2016-12-16 12:49:24 -08003232 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003233 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003234 ret = -EINVAL;
3235 goto exit;
3236 }
3237 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003238 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003239 ALOGV("%s in %p", __func__, in);
3240 ret = -ENOSYS;
3241 goto exit;
3242 }
3243 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3244 if (in->pcm_device_id < 0) {
3245 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3246 __func__, in->pcm_device_id, in->usecase);
3247 ret = -EINVAL;
3248 goto exit;
3249 }
Phil Burkbc991042017-02-24 08:06:44 -08003250
3251 adjust_mmap_period_count(&in->config, min_size_frames);
3252
Eric Laurent0e46adf2016-12-16 12:49:24 -08003253 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3254 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3255 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3256 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3257 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3258 step = "open";
3259 ret = -ENODEV;
3260 goto exit;
3261 }
3262
3263 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3264 if (ret < 0) {
3265 step = "begin";
3266 goto exit;
3267 }
3268 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3269 info->burst_size_frames = in->config.period_size;
3270 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3271
3272 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3273 info->buffer_size_frames));
3274
3275 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3276 if (ret < 0) {
3277 step = "commit";
3278 goto exit;
3279 }
3280
Phil Burkbc991042017-02-24 08:06:44 -08003281 in->standby = false;
3282 ret = 0;
3283
Eric Laurent0e46adf2016-12-16 12:49:24 -08003284 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3285 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003286
3287exit:
3288 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003289 if (in->pcm == NULL) {
3290 ALOGE("%s: %s - %d", __func__, step, ret);
3291 } else {
3292 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003293 pcm_close(in->pcm);
3294 in->pcm = NULL;
3295 }
3296 }
3297 pthread_mutex_unlock(&adev->lock);
3298 return ret;
3299}
3300
3301static int in_get_mmap_position(const struct audio_stream_in *stream,
3302 struct audio_mmap_position *position)
3303{
3304 struct stream_in *in = (struct stream_in *)stream;
3305 ALOGVV("%s", __func__);
3306 if (position == NULL) {
3307 return -EINVAL;
3308 }
3309 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3310 return -ENOSYS;
3311 }
3312 if (in->pcm == NULL) {
3313 return -ENOSYS;
3314 }
3315 struct timespec ts = { 0, 0 };
3316 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3317 if (ret < 0) {
3318 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3319 return ret;
3320 }
Andy Hungfc044e12017-03-20 09:24:22 -07003321 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003322 return 0;
3323}
3324
3325
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003326static int adev_open_output_stream(struct audio_hw_device *dev,
3327 audio_io_handle_t handle,
3328 audio_devices_t devices,
3329 audio_output_flags_t flags,
3330 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003331 struct audio_stream_out **stream_out,
3332 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333{
3334 struct audio_device *adev = (struct audio_device *)dev;
3335 struct stream_out *out;
3336 int i, ret;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003337 const uint32_t direct_dev = (AUDIO_DEVICE_OUT_HDMI|AUDIO_DEVICE_OUT_USB_DEVICE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338
Eric Laurent994a6932013-07-17 11:51:42 -07003339 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340 __func__, config->sample_rate, config->channel_mask, devices, flags);
3341 *stream_out = NULL;
3342 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3343
3344 if (devices == AUDIO_DEVICE_NONE)
3345 devices = AUDIO_DEVICE_OUT_SPEAKER;
3346
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003347 out->flags = flags;
3348 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003349 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003350 out->format = config->format;
3351 out->sample_rate = config->sample_rate;
3352 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3353 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003354 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355
3356 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003357 if (audio_is_linear_pcm(out->format) &&
3358 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
3359 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
3360 (out->devices & direct_dev)) {
3361
3362 bool hdmi = (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL);
3363
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003364 pthread_mutex_lock(&adev->lock);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003365 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3366 ret = read_hdmi_channel_masks(out);
3367 } else if (out->devices & AUDIO_DEVICE_OUT_USB_DEVICE) {
3368 ret = read_usb_sup_formats(out) ||
3369 read_usb_sup_channel_masks(out) ||
3370 read_usb_sup_sample_rates(out);
3371 ALOGV("plugged dev USB ret %d", ret);
3372 } else {
3373 ret = -1;
3374 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003375 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003376 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003377 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003378
Kevin Rocard50eff892017-05-02 16:52:05 -07003379 if (config->sample_rate == 0) {
3380 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3381 } else {
3382 out->sample_rate = config->sample_rate;
3383 }
3384 if (config->channel_mask == 0) {
3385 out->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3386 } else {
3387 out->channel_mask = config->channel_mask;
3388 }
3389 if (config->format == AUDIO_FORMAT_DEFAULT) {
3390 out->format = AUDIO_FORMAT_PCM_16_BIT;
3391 } else {
3392 out->format = config->format;
3393 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003394 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3395 // does this change?
3396 out->config = hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003398 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003400 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003401 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003402 pthread_mutex_lock(&adev->lock);
3403 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3404 pthread_mutex_unlock(&adev->lock);
3405
3406 // reject offload during card offline to allow
3407 // fallback to s/w paths
3408 if (offline) {
3409 ret = -ENODEV;
3410 goto error_open;
3411 }
3412
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003413 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3414 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3415 ALOGE("%s: Unsupported Offload information", __func__);
3416 ret = -EINVAL;
3417 goto error_open;
3418 }
3419 if (!is_supported_format(config->offload_info.format)) {
3420 ALOGE("%s: Unsupported audio format", __func__);
3421 ret = -EINVAL;
3422 goto error_open;
3423 }
3424
3425 out->compr_config.codec = (struct snd_codec *)
3426 calloc(1, sizeof(struct snd_codec));
3427
3428 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3429 if (config->offload_info.channel_mask)
3430 out->channel_mask = config->offload_info.channel_mask;
3431 else if (config->channel_mask)
3432 out->channel_mask = config->channel_mask;
3433 out->format = config->offload_info.format;
3434 out->sample_rate = config->offload_info.sample_rate;
3435
3436 out->stream.set_callback = out_set_callback;
3437 out->stream.pause = out_pause;
3438 out->stream.resume = out_resume;
3439 out->stream.drain = out_drain;
3440 out->stream.flush = out_flush;
3441
3442 out->compr_config.codec->id =
3443 get_snd_codec_id(config->offload_info.format);
3444 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3445 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003446 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003447 out->compr_config.codec->bit_rate =
3448 config->offload_info.bit_rate;
3449 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003450 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003451 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3452
3453 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3454 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003455
3456 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003457 create_offload_callback_thread(out);
3458 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3459 __func__, config->offload_info.version,
3460 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003461 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003462 switch (config->sample_rate) {
3463 case 8000:
3464 case 16000:
3465 case 48000:
3466 out->sample_rate = config->sample_rate;
3467 break;
3468 default:
3469 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003470 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003471 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003472 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3473 out->config = pcm_config_afe_proxy_playback;
3474 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003476 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3477 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3478 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003479 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3480 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3481 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003482 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3483 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003484 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003485 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003486 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3487 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3488 out->config = pcm_config_mmap_playback;
3489 out->stream.start = out_start;
3490 out->stream.stop = out_stop;
3491 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3492 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003493 } else {
3494 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3495 out->config = pcm_config_low_latency;
3496 }
3497 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3498 if (k_enable_extended_precision
3499 && pcm_params_format_test(adev->use_case_table[out->usecase],
3500 pcm_format_from_audio_format(config->format))) {
3501 out->config.format = pcm_format_from_audio_format(config->format);
3502 /* out->format already set to config->format */
3503 } else {
3504 /* deny the externally proposed config format
3505 * and use the one specified in audio_hw layer configuration.
3506 * Note: out->format is returned by out->stream.common.get_format()
3507 * and is used to set config->format in the code several lines below.
3508 */
3509 out->format = audio_format_from_pcm_format(out->config.format);
3510 }
3511 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003512 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003514
3515 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3516 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3517 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3518 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3519 __func__, config->sample_rate, config->format, config->channel_mask);
3520 config->sample_rate = out->sample_rate;
3521 config->format = out->format;
3522 config->channel_mask = out->channel_mask;
3523 ret = -EINVAL;
3524 goto error_open;
3525 }
3526
Andy Hung6fcba9c2014-03-18 11:53:32 -07003527 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3528 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003530 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003531 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003532 adev->primary_output = out;
3533 else {
3534 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003535 ret = -EEXIST;
3536 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003537 }
3538 }
3539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540 /* Check if this usecase is already existing */
3541 pthread_mutex_lock(&adev->lock);
3542 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3543 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003544 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003545 ret = -EEXIST;
3546 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547 }
3548 pthread_mutex_unlock(&adev->lock);
3549
3550 out->stream.common.get_sample_rate = out_get_sample_rate;
3551 out->stream.common.set_sample_rate = out_set_sample_rate;
3552 out->stream.common.get_buffer_size = out_get_buffer_size;
3553 out->stream.common.get_channels = out_get_channels;
3554 out->stream.common.get_format = out_get_format;
3555 out->stream.common.set_format = out_set_format;
3556 out->stream.common.standby = out_standby;
3557 out->stream.common.dump = out_dump;
3558 out->stream.common.set_parameters = out_set_parameters;
3559 out->stream.common.get_parameters = out_get_parameters;
3560 out->stream.common.add_audio_effect = out_add_audio_effect;
3561 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3562 out->stream.get_latency = out_get_latency;
3563 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003564#ifdef NO_AUDIO_OUT
3565 out->stream.write = out_write_for_no_output;
3566#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003568#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569 out->stream.get_render_position = out_get_render_position;
3570 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003571 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572
Eric Laurent0e46adf2016-12-16 12:49:24 -08003573 if (out->realtime)
3574 out->af_period_multiplier = af_period_multiplier;
3575 else
3576 out->af_period_multiplier = 1;
3577
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003579 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003580 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003582 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003583 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003584 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586 config->format = out->stream.common.get_format(&out->stream.common);
3587 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3588 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3589
Andy Hunga452b0a2017-03-15 14:51:15 -07003590 out->error_log = error_log_create(
3591 ERROR_LOG_ENTRIES,
3592 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3593
Andy Hungfc044e12017-03-20 09:24:22 -07003594 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003595 // or not a userdebug or eng build.
3596 if (is_userdebug_or_eng_build()) {
3597 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3598 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3599
3600 out->power_log = power_log_create(
3601 config->sample_rate,
3602 audio_channel_count_from_out_mask(config->channel_mask),
3603 config->format,
3604 POWER_LOG_ENTRIES,
3605 POWER_LOG_FRAMES_PER_ENTRY);
3606 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003607
3608 /*
3609 By locking output stream before registering, we allow the callback
3610 to update stream's state only after stream's initial state is set to
3611 adev state.
3612 */
3613 lock_output_stream(out);
3614 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3615 pthread_mutex_lock(&adev->lock);
3616 out->card_status = adev->card_status;
3617 pthread_mutex_unlock(&adev->lock);
3618 pthread_mutex_unlock(&out->lock);
3619
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003621
Eric Laurent994a6932013-07-17 11:51:42 -07003622 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003624
3625error_open:
3626 free(out);
3627 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003628 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003629 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630}
3631
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003632static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633 struct audio_stream_out *stream)
3634{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003635 struct stream_out *out = (struct stream_out *)stream;
3636 struct audio_device *adev = out->dev;
3637
Eric Laurent994a6932013-07-17 11:51:42 -07003638 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003639
3640 // must deregister from sndmonitor first to prevent races
3641 // between the callback and close_stream
3642 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003643 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003644 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3645 destroy_offload_callback_thread(out);
3646
3647 if (out->compr_config.codec != NULL)
3648 free(out->compr_config.codec);
3649 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003650
3651 if (adev->voice_tx_output == out)
3652 adev->voice_tx_output = NULL;
3653
Andy Hungfc044e12017-03-20 09:24:22 -07003654 power_log_destroy(out->power_log);
3655 out->power_log = NULL;
3656
Andy Hunga452b0a2017-03-15 14:51:15 -07003657 error_log_destroy(out->error_log);
3658 out->error_log = NULL;
3659
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003660 pthread_cond_destroy(&out->cond);
3661 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003663 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664}
3665
3666static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3667{
3668 struct audio_device *adev = (struct audio_device *)dev;
3669 struct str_parms *parms;
3670 char *str;
3671 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003672 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003674 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675
Joe Onorato188b6222016-03-01 11:02:27 -08003676 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003677
3678 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679
3680 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003681 status = voice_set_parameters(adev, parms);
3682 if (status != 0) {
3683 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684 }
3685
3686 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3687 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003688 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3690 adev->bluetooth_nrec = true;
3691 else
3692 adev->bluetooth_nrec = false;
3693 }
3694
3695 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3696 if (ret >= 0) {
3697 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3698 adev->screen_off = false;
3699 else
3700 adev->screen_off = true;
3701 }
3702
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003703 ret = str_parms_get_int(parms, "rotation", &val);
3704 if (ret >= 0) {
3705 bool reverse_speakers = false;
3706 switch(val) {
3707 // FIXME: note that the code below assumes that the speakers are in the correct placement
3708 // relative to the user when the device is rotated 90deg from its default rotation. This
3709 // assumption is device-specific, not platform-specific like this code.
3710 case 270:
3711 reverse_speakers = true;
3712 break;
3713 case 0:
3714 case 90:
3715 case 180:
3716 break;
3717 default:
3718 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003719 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003720 }
Eric Laurent03f09432014-03-25 18:09:11 -07003721 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003722 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003723 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003724 }
3725
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003726 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3727 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003728 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003729 }
3730
David Linee3fe402017-03-13 10:00:42 -07003731 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3732 if (ret >= 0) {
3733 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3734 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3735 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3736 if (ret >= 0) {
3737 const int card = atoi(value);
3738 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3739 }
3740 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3741 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3742 if (ret >= 0) {
3743 const int card = atoi(value);
3744 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3745 }
3746 }
3747 }
3748
3749 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3750 if (ret >= 0) {
3751 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3752 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3753 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3754 if (ret >= 0) {
3755 const int card = atoi(value);
3756
3757 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3758 }
3759 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3760 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3761 if (ret >= 0) {
3762 const int card = atoi(value);
3763 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3764 }
3765 }
3766 }
3767
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003768 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003769done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003771 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003772 ALOGV("%s: exit with code(%d)", __func__, status);
3773 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774}
3775
3776static char* adev_get_parameters(const struct audio_hw_device *dev,
3777 const char *keys)
3778{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003779 struct audio_device *adev = (struct audio_device *)dev;
3780 struct str_parms *reply = str_parms_create();
3781 struct str_parms *query = str_parms_create_str(keys);
3782 char *str;
3783
3784 pthread_mutex_lock(&adev->lock);
3785
3786 voice_get_parameters(adev, query, reply);
3787 str = str_parms_to_str(reply);
3788 str_parms_destroy(query);
3789 str_parms_destroy(reply);
3790
3791 pthread_mutex_unlock(&adev->lock);
3792 ALOGV("%s: exit: returns - %s", __func__, str);
3793 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003794}
3795
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003796static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797{
3798 return 0;
3799}
3800
Haynes Mathew George5191a852013-09-11 14:19:36 -07003801static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3802{
3803 int ret;
3804 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003805
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003806 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3807
Haynes Mathew George5191a852013-09-11 14:19:36 -07003808 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003809 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003810 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003811
Haynes Mathew George5191a852013-09-11 14:19:36 -07003812 return ret;
3813}
3814
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003815static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816{
3817 return -ENOSYS;
3818}
3819
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003820static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3821 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003822{
3823 return -ENOSYS;
3824}
3825
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003826static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003827{
3828 return -ENOSYS;
3829}
3830
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003831static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003832{
3833 return -ENOSYS;
3834}
3835
3836static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3837{
3838 struct audio_device *adev = (struct audio_device *)dev;
3839
3840 pthread_mutex_lock(&adev->lock);
3841 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003842 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003843 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003844 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3845 voice_is_in_call(adev)) {
3846 voice_stop_call(adev);
3847 adev->current_call_output = NULL;
3848 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849 }
3850 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003851
3852 audio_extn_extspk_set_mode(adev->extspk, mode);
3853
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854 return 0;
3855}
3856
3857static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3858{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003859 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003860 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861
Eric Laurent2bafff12016-03-17 12:17:23 -07003862 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003863 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003864 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3865 ret = audio_extn_hfp_set_mic_mute(adev, state);
3866 } else {
3867 ret = voice_set_mic_mute(adev, state);
3868 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003869 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003870 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003871
3872 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003873}
3874
3875static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3876{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003877 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878 return 0;
3879}
3880
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003881static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003882 const struct audio_config *config)
3883{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003884 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003885
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003886 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3887 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888}
3889
3890static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003891 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003892 audio_devices_t devices,
3893 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003894 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003895 audio_input_flags_t flags,
3896 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003897 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898{
3899 struct audio_device *adev = (struct audio_device *)dev;
3900 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003901 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003902 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003903 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003904
Eric Laurent994a6932013-07-17 11:51:42 -07003905 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003906 *stream_in = NULL;
3907 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3908 return -EINVAL;
3909
Zheng Zhang6185d572016-12-01 20:35:17 +08003910 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 -08003911 return -EINVAL;
3912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3914
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003915 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003916 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918 in->stream.common.get_sample_rate = in_get_sample_rate;
3919 in->stream.common.set_sample_rate = in_set_sample_rate;
3920 in->stream.common.get_buffer_size = in_get_buffer_size;
3921 in->stream.common.get_channels = in_get_channels;
3922 in->stream.common.get_format = in_get_format;
3923 in->stream.common.set_format = in_set_format;
3924 in->stream.common.standby = in_standby;
3925 in->stream.common.dump = in_dump;
3926 in->stream.common.set_parameters = in_set_parameters;
3927 in->stream.common.get_parameters = in_get_parameters;
3928 in->stream.common.add_audio_effect = in_add_audio_effect;
3929 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3930 in->stream.set_gain = in_set_gain;
3931 in->stream.read = in_read;
3932 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003933 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003934
3935 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003936 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003937 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003938 in->standby = 1;
3939 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003940 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003941 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942
vivek mehta57ff9b52016-04-28 14:13:08 -07003943 // restrict 24 bit capture for unprocessed source only
3944 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3945 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003946 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003947 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3948 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3949 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3950 bool ret_error = false;
3951 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3952 from HAL is 8_24
3953 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3954 8_24 return error indicating supported format is 8_24
3955 *> In case of any other source requesting 24 bit or float return error
3956 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003957
vivek mehta57ff9b52016-04-28 14:13:08 -07003958 on error flinger will retry with supported format passed
3959 */
3960 if (source != AUDIO_SOURCE_UNPROCESSED) {
3961 config->format = AUDIO_FORMAT_PCM_16_BIT;
3962 ret_error = true;
3963 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3964 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3965 ret_error = true;
3966 }
3967
3968 if (ret_error) {
3969 ret = -EINVAL;
3970 goto err_open;
3971 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003972 }
3973
vivek mehta57ff9b52016-04-28 14:13:08 -07003974 in->format = config->format;
3975
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003976 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003977 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3978 if (config->sample_rate == 0)
3979 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3980 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3981 config->sample_rate != 8000) {
3982 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3983 ret = -EINVAL;
3984 goto err_open;
3985 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003986
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003987 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3988 config->format = AUDIO_FORMAT_PCM_16_BIT;
3989 ret = -EINVAL;
3990 goto err_open;
3991 }
3992
3993 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3994 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07003995 in->af_period_multiplier = 1;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003996 } else {
3997 in->usecase = USECASE_AUDIO_RECORD;
3998 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08003999 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004000 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004001#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004002 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004003#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004004 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004005 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004006 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004007 frame_size = audio_stream_in_frame_size(&in->stream);
4008 buffer_size = get_input_buffer_size(config->sample_rate,
4009 config->format,
4010 channel_count,
4011 is_low_latency);
4012 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004013 in->config.rate = config->sample_rate;
4014 in->af_period_multiplier = 1;
4015 } else {
4016 // period size is left untouched for rt mode playback
4017 in->config = pcm_config_audio_capture_rt;
4018 in->af_period_multiplier = af_period_multiplier;
4019 }
4020 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4021 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
4022 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4023 in->config = pcm_config_mmap_capture;
4024 in->stream.start = in_start;
4025 in->stream.stop = in_stop;
4026 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4027 in->stream.get_mmap_position = in_get_mmap_position;
4028 in->af_period_multiplier = 1;
4029 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
4030 } else {
4031 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004032 frame_size = audio_stream_in_frame_size(&in->stream);
4033 buffer_size = get_input_buffer_size(config->sample_rate,
4034 config->format,
4035 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004036 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004037 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004038 in->config.rate = config->sample_rate;
4039 in->af_period_multiplier = 1;
4040 }
4041 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4042 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004043 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004044
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004045 in->config.channels = channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004047 /* This stream could be for sound trigger lab,
4048 get sound trigger pcm if present */
4049 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004051 lock_input_stream(in);
4052 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4053 pthread_mutex_lock(&adev->lock);
4054 in->card_status = adev->card_status;
4055 pthread_mutex_unlock(&adev->lock);
4056 pthread_mutex_unlock(&in->lock);
4057
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004058 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004059 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060 return 0;
4061
4062err_open:
4063 free(in);
4064 *stream_in = NULL;
4065 return ret;
4066}
4067
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004068static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004069 struct audio_stream_in *stream)
4070{
Eric Laurent994a6932013-07-17 11:51:42 -07004071 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004072
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004073 // must deregister from sndmonitor first to prevent races
4074 // between the callback and close_stream
4075 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004076 in_standby(&stream->common);
4077 free(stream);
4078
4079 return;
4080}
4081
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004082static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004083{
4084 return 0;
4085}
4086
Andy Hung31aca912014-03-20 17:14:59 -07004087/* verifies input and output devices and their capabilities.
4088 *
4089 * This verification is required when enabling extended bit-depth or
4090 * sampling rates, as not all qcom products support it.
4091 *
4092 * Suitable for calling only on initialization such as adev_open().
4093 * It fills the audio_device use_case_table[] array.
4094 *
4095 * Has a side-effect that it needs to configure audio routing / devices
4096 * in order to power up the devices and read the device parameters.
4097 * It does not acquire any hw device lock. Should restore the devices
4098 * back to "normal state" upon completion.
4099 */
4100static int adev_verify_devices(struct audio_device *adev)
4101{
4102 /* enumeration is a bit difficult because one really wants to pull
4103 * the use_case, device id, etc from the hidden pcm_device_table[].
4104 * In this case there are the following use cases and device ids.
4105 *
4106 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4107 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004108 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004109 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4110 * [USECASE_AUDIO_RECORD] = {0, 0},
4111 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4112 * [USECASE_VOICE_CALL] = {2, 2},
4113 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004114 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004115 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4116 */
4117
4118 /* should be the usecases enabled in adev_open_input_stream() */
4119 static const int test_in_usecases[] = {
4120 USECASE_AUDIO_RECORD,
4121 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4122 };
4123 /* should be the usecases enabled in adev_open_output_stream()*/
4124 static const int test_out_usecases[] = {
4125 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4126 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4127 };
4128 static const usecase_type_t usecase_type_by_dir[] = {
4129 PCM_PLAYBACK,
4130 PCM_CAPTURE,
4131 };
4132 static const unsigned flags_by_dir[] = {
4133 PCM_OUT,
4134 PCM_IN,
4135 };
4136
4137 size_t i;
4138 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004139 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004140 char info[512]; /* for possible debug info */
4141
4142 for (dir = 0; dir < 2; ++dir) {
4143 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4144 const unsigned flags_dir = flags_by_dir[dir];
4145 const size_t testsize =
4146 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4147 const int *testcases =
4148 dir ? test_in_usecases : test_out_usecases;
4149 const audio_devices_t audio_device =
4150 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4151
4152 for (i = 0; i < testsize; ++i) {
4153 const audio_usecase_t audio_usecase = testcases[i];
4154 int device_id;
4155 snd_device_t snd_device;
4156 struct pcm_params **pparams;
4157 struct stream_out out;
4158 struct stream_in in;
4159 struct audio_usecase uc_info;
4160 int retval;
4161
4162 pparams = &adev->use_case_table[audio_usecase];
4163 pcm_params_free(*pparams); /* can accept null input */
4164 *pparams = NULL;
4165
4166 /* find the device ID for the use case (signed, for error) */
4167 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4168 if (device_id < 0)
4169 continue;
4170
4171 /* prepare structures for device probing */
4172 memset(&uc_info, 0, sizeof(uc_info));
4173 uc_info.id = audio_usecase;
4174 uc_info.type = usecase_type;
4175 if (dir) {
4176 adev->active_input = &in;
4177 memset(&in, 0, sizeof(in));
4178 in.device = audio_device;
4179 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4180 uc_info.stream.in = &in;
4181 } else {
4182 adev->active_input = NULL;
4183 }
4184 memset(&out, 0, sizeof(out));
4185 out.devices = audio_device; /* only field needed in select_devices */
4186 uc_info.stream.out = &out;
4187 uc_info.devices = audio_device;
4188 uc_info.in_snd_device = SND_DEVICE_NONE;
4189 uc_info.out_snd_device = SND_DEVICE_NONE;
4190 list_add_tail(&adev->usecase_list, &uc_info.list);
4191
4192 /* select device - similar to start_(in/out)put_stream() */
4193 retval = select_devices(adev, audio_usecase);
4194 if (retval >= 0) {
4195 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4196#if LOG_NDEBUG == 0
4197 if (*pparams) {
4198 ALOGV("%s: (%s) card %d device %d", __func__,
4199 dir ? "input" : "output", card_id, device_id);
4200 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004201 } else {
4202 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4203 }
4204#endif
4205 }
4206
4207 /* deselect device - similar to stop_(in/out)put_stream() */
4208 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004209 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004210 /* 2. Disable the rx device */
4211 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004212 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004213 list_remove(&uc_info.list);
4214 }
4215 }
4216 adev->active_input = NULL; /* restore adev state */
4217 return 0;
4218}
4219
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004220static int adev_close(hw_device_t *device)
4221{
Andy Hung31aca912014-03-20 17:14:59 -07004222 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004224
4225 if (!adev)
4226 return 0;
4227
Kevin Rocarda5453442017-05-02 15:09:20 -07004228 audio_extn_snd_mon_unregister_listener(adev);
Kevin Rocard8342c2c2017-04-07 18:50:00 -07004229 audio_extn_snd_mon_deinit();
Kevin Rocarda5453442017-05-02 15:09:20 -07004230
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004231 audio_extn_tfa_98xx_deinit();
4232
vivek mehta1a9b7c02015-06-25 11:49:38 -07004233 pthread_mutex_lock(&adev_init_lock);
4234
4235 if ((--audio_device_ref_count) == 0) {
4236 audio_route_free(adev->audio_route);
4237 free(adev->snd_dev_ref_cnt);
4238 platform_deinit(adev->platform);
4239 audio_extn_extspk_deinit(adev->extspk);
4240 audio_extn_sound_trigger_deinit(adev);
4241 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4242 pcm_params_free(adev->use_case_table[i]);
4243 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004244 if (adev->adm_deinit)
4245 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004246 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004247 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004248
4249 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004250
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004251 return 0;
4252}
4253
Glenn Kasten4f993392014-05-14 07:30:48 -07004254/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4255 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4256 * just that it _might_ work.
4257 */
4258static int period_size_is_plausible_for_low_latency(int period_size)
4259{
4260 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004261 case 48:
4262 case 96:
4263 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004264 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004265 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004266 case 240:
4267 case 320:
4268 case 480:
4269 return 1;
4270 default:
4271 return 0;
4272 }
4273}
4274
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004275static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4276{
4277 int card;
4278 card_status_t status;
4279
4280 if (!parms)
4281 return;
4282
4283 if (parse_snd_card_status(parms, &card, &status) < 0)
4284 return;
4285
4286 pthread_mutex_lock(&adev->lock);
4287 bool valid_cb = (card == adev->snd_card);
4288 if (valid_cb) {
4289 if (adev->card_status != status) {
4290 adev->card_status = status;
4291 platform_snd_card_update(adev->platform, status);
4292 }
4293 }
4294 pthread_mutex_unlock(&adev->lock);
4295 return;
4296}
4297
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004298static int adev_open(const hw_module_t *module, const char *name,
4299 hw_device_t **device)
4300{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004301 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302
Eric Laurent2bafff12016-03-17 12:17:23 -07004303 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004304 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004305 pthread_mutex_lock(&adev_init_lock);
4306 if (audio_device_ref_count != 0) {
4307 *device = &adev->device.common;
4308 audio_device_ref_count++;
4309 ALOGV("%s: returning existing instance of adev", __func__);
4310 ALOGV("%s: exit", __func__);
4311 pthread_mutex_unlock(&adev_init_lock);
4312 return 0;
4313 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004314 adev = calloc(1, sizeof(struct audio_device));
4315
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004316 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4317
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4319 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4320 adev->device.common.module = (struct hw_module_t *)module;
4321 adev->device.common.close = adev_close;
4322
4323 adev->device.init_check = adev_init_check;
4324 adev->device.set_voice_volume = adev_set_voice_volume;
4325 adev->device.set_master_volume = adev_set_master_volume;
4326 adev->device.get_master_volume = adev_get_master_volume;
4327 adev->device.set_master_mute = adev_set_master_mute;
4328 adev->device.get_master_mute = adev_get_master_mute;
4329 adev->device.set_mode = adev_set_mode;
4330 adev->device.set_mic_mute = adev_set_mic_mute;
4331 adev->device.get_mic_mute = adev_get_mic_mute;
4332 adev->device.set_parameters = adev_set_parameters;
4333 adev->device.get_parameters = adev_get_parameters;
4334 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4335 adev->device.open_output_stream = adev_open_output_stream;
4336 adev->device.close_output_stream = adev_close_output_stream;
4337 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004338
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004339 adev->device.close_input_stream = adev_close_input_stream;
4340 adev->device.dump = adev_dump;
4341
4342 /* Set the default route before the PCM stream is opened */
4343 pthread_mutex_lock(&adev->lock);
4344 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004345 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004346 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004347 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004348 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004349 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004350 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004351 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004352 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353 pthread_mutex_unlock(&adev->lock);
4354
4355 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004356 adev->platform = platform_init(adev);
4357 if (!adev->platform) {
4358 free(adev->snd_dev_ref_cnt);
4359 free(adev);
4360 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4361 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004362 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004363 return -EINVAL;
4364 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004365 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004366 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004367
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004368 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4369 if (adev->visualizer_lib == NULL) {
4370 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4371 } else {
4372 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4373 adev->visualizer_start_output =
4374 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4375 "visualizer_hal_start_output");
4376 adev->visualizer_stop_output =
4377 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4378 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004379 }
4380
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004381 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4382 if (adev->offload_effects_lib == NULL) {
4383 ALOGW("%s: DLOPEN failed for %s", __func__,
4384 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4385 } else {
4386 ALOGV("%s: DLOPEN successful for %s", __func__,
4387 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4388 adev->offload_effects_start_output =
4389 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4390 "offload_effects_bundle_hal_start_output");
4391 adev->offload_effects_stop_output =
4392 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4393 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004394 }
4395
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004396 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4397 if (adev->adm_lib == NULL) {
4398 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4399 } else {
4400 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4401 adev->adm_init = (adm_init_t)
4402 dlsym(adev->adm_lib, "adm_init");
4403 adev->adm_deinit = (adm_deinit_t)
4404 dlsym(adev->adm_lib, "adm_deinit");
4405 adev->adm_register_input_stream = (adm_register_input_stream_t)
4406 dlsym(adev->adm_lib, "adm_register_input_stream");
4407 adev->adm_register_output_stream = (adm_register_output_stream_t)
4408 dlsym(adev->adm_lib, "adm_register_output_stream");
4409 adev->adm_deregister_stream = (adm_deregister_stream_t)
4410 dlsym(adev->adm_lib, "adm_deregister_stream");
4411 adev->adm_request_focus = (adm_request_focus_t)
4412 dlsym(adev->adm_lib, "adm_request_focus");
4413 adev->adm_abandon_focus = (adm_abandon_focus_t)
4414 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004415 adev->adm_set_config = (adm_set_config_t)
4416 dlsym(adev->adm_lib, "adm_set_config");
4417 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4418 dlsym(adev->adm_lib, "adm_request_focus_v2");
4419 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4420 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4421 adev->adm_on_routing_change = (adm_on_routing_change_t)
4422 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004423 }
4424
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004425 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004426 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004428 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004429
Andy Hung31aca912014-03-20 17:14:59 -07004430 if (k_enable_extended_precision)
4431 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004432
Glenn Kasten4f993392014-05-14 07:30:48 -07004433 char value[PROPERTY_VALUE_MAX];
4434 int trial;
4435 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4436 trial = atoi(value);
4437 if (period_size_is_plausible_for_low_latency(trial)) {
4438 pcm_config_low_latency.period_size = trial;
4439 pcm_config_low_latency.start_threshold = trial / 4;
4440 pcm_config_low_latency.avail_min = trial / 4;
4441 configured_low_latency_capture_period_size = trial;
4442 }
4443 }
4444 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4445 trial = atoi(value);
4446 if (period_size_is_plausible_for_low_latency(trial)) {
4447 configured_low_latency_capture_period_size = trial;
4448 }
4449 }
4450
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004451 // commented as full set of app type cfg is sent from platform
4452 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004453 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004454
4455 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4456 af_period_multiplier = atoi(value);
4457 if (af_period_multiplier < 0) {
4458 af_period_multiplier = 2;
4459 } else if (af_period_multiplier > 4) {
4460 af_period_multiplier = 4;
4461 }
4462 ALOGV("new period_multiplier = %d", af_period_multiplier);
4463 }
4464
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004465 audio_extn_tfa_98xx_init(adev);
4466
vivek mehta1a9b7c02015-06-25 11:49:38 -07004467 pthread_mutex_unlock(&adev_init_lock);
4468
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004469 if (adev->adm_init)
4470 adev->adm_data = adev->adm_init();
4471
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004472 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004473 audio_extn_snd_mon_init();
4474 pthread_mutex_lock(&adev->lock);
4475 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4476 adev->card_status = CARD_STATUS_ONLINE;
4477 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004478
Eric Laurent2bafff12016-03-17 12:17:23 -07004479 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004480 return 0;
4481}
4482
4483static struct hw_module_methods_t hal_module_methods = {
4484 .open = adev_open,
4485};
4486
4487struct audio_module HAL_MODULE_INFO_SYM = {
4488 .common = {
4489 .tag = HARDWARE_MODULE_TAG,
4490 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4491 .hal_api_version = HARDWARE_HAL_API_VERSION,
4492 .id = AUDIO_HARDWARE_MODULE_ID,
4493 .name = "QCOM Audio HAL",
4494 .author = "Code Aurora Forum",
4495 .methods = &hal_module_methods,
4496 },
4497};