blob: cdd10b3b230c89919d643c14c7bf68024c636815 [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
Haynes Mathew Georgee6e2d442018-02-22 18:51:56 -080038#include <log/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>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080053#include "audio_extn.h"
Wei Wangf4837d52017-11-21 14:51:20 -080054#include "audio_perf.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
vivek mehta4a824772017-06-08 19:05:49 -070069/* treat as unsigned Q1.13 */
70#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070071#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070072
73/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070074#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070075
Eric Laurent51f3c662018-04-10 18:21:34 -070076#define RECORD_GAIN_MIN 0.0f
77#define RECORD_GAIN_MAX 1.0f
78#define RECORD_VOLUME_CTL_MAX 0x2000
79
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070080#define PROXY_OPEN_RETRY_COUNT 100
81#define PROXY_OPEN_WAIT_TIME 20
82
vivek mehtadae44712015-07-27 14:13:18 -070083#define MIN_CHANNEL_COUNT 1
84#define DEFAULT_CHANNEL_COUNT 2
85
Jean-Michel Trivic0750692015-10-12 12:12:32 -070086#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
87#define MAX_CHANNEL_COUNT 1
88#else
vivek mehtadae44712015-07-27 14:13:18 -070089#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
90#define XSTR(x) STR(x)
91#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070092#endif
Eric Laurent74b55762017-07-09 17:04:53 -070093#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070094
Haynes Mathew George03c40102016-01-29 17:57:48 -080095#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
96
Glenn Kasten4f993392014-05-14 07:30:48 -070097static unsigned int configured_low_latency_capture_period_size =
98 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
99
Eric Laurent0e46adf2016-12-16 12:49:24 -0800100
101#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -0800102#define MMAP_PERIOD_COUNT_MIN 32
103#define MMAP_PERIOD_COUNT_MAX 512
104#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800105
Andy Hung31aca912014-03-20 17:14:59 -0700106/* This constant enables extended precision handling.
107 * TODO The flag is off until more testing is done.
108 */
109static const bool k_enable_extended_precision = false;
110
Eric Laurentb23d5282013-05-14 15:27:20 -0700111struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700112 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700113 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
114 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
115 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
116 .format = PCM_FORMAT_S16_LE,
117 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
118 .stop_threshold = INT_MAX,
119 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
120};
121
122struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700123 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700124 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
125 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
126 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
127 .format = PCM_FORMAT_S16_LE,
128 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
129 .stop_threshold = INT_MAX,
130 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
131};
132
Haynes Mathew George03c40102016-01-29 17:57:48 -0800133static int af_period_multiplier = 4;
134struct pcm_config pcm_config_rt = {
135 .channels = DEFAULT_CHANNEL_COUNT,
136 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
137 .period_size = ULL_PERIOD_SIZE, //1 ms
138 .period_count = 512, //=> buffer size is 512ms
139 .format = PCM_FORMAT_S16_LE,
140 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
141 .stop_threshold = INT_MAX,
142 .silence_threshold = 0,
143 .silence_size = 0,
144 .avail_min = ULL_PERIOD_SIZE, //1 ms
145};
146
Eric Laurentb23d5282013-05-14 15:27:20 -0700147struct pcm_config pcm_config_hdmi_multi = {
148 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
149 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
150 .period_size = HDMI_MULTI_PERIOD_SIZE,
151 .period_count = HDMI_MULTI_PERIOD_COUNT,
152 .format = PCM_FORMAT_S16_LE,
153 .start_threshold = 0,
154 .stop_threshold = INT_MAX,
155 .avail_min = 0,
156};
157
Eric Laurent0e46adf2016-12-16 12:49:24 -0800158struct pcm_config pcm_config_mmap_playback = {
159 .channels = DEFAULT_CHANNEL_COUNT,
160 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
161 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800162 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800163 .format = PCM_FORMAT_S16_LE,
164 .start_threshold = MMAP_PERIOD_SIZE*8,
165 .stop_threshold = INT32_MAX,
166 .silence_threshold = 0,
167 .silence_size = 0,
168 .avail_min = MMAP_PERIOD_SIZE, //1 ms
169};
170
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800171struct pcm_config pcm_config_hifi = {
172 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
173 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
174 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
175 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
176 .format = PCM_FORMAT_S24_3LE,
177 .start_threshold = 0,
178 .stop_threshold = INT_MAX,
179 .avail_min = 0,
180};
181
Eric Laurentb23d5282013-05-14 15:27:20 -0700182struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700183 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700184 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
185 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700186 .stop_threshold = INT_MAX,
187 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700188};
189
Haynes Mathew George03c40102016-01-29 17:57:48 -0800190struct pcm_config pcm_config_audio_capture_rt = {
191 .channels = DEFAULT_CHANNEL_COUNT,
192 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
193 .period_size = ULL_PERIOD_SIZE,
194 .period_count = 512,
195 .format = PCM_FORMAT_S16_LE,
196 .start_threshold = 0,
197 .stop_threshold = INT_MAX,
198 .silence_threshold = 0,
199 .silence_size = 0,
200 .avail_min = ULL_PERIOD_SIZE, //1 ms
201};
202
Eric Laurent0e46adf2016-12-16 12:49:24 -0800203struct pcm_config pcm_config_mmap_capture = {
204 .channels = DEFAULT_CHANNEL_COUNT,
205 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
206 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800207 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800208 .format = PCM_FORMAT_S16_LE,
209 .start_threshold = 0,
210 .stop_threshold = INT_MAX,
211 .silence_threshold = 0,
212 .silence_size = 0,
213 .avail_min = MMAP_PERIOD_SIZE, //1 ms
214};
215
vivek mehtaa68fea62017-06-08 19:04:02 -0700216struct pcm_config pcm_config_voip = {
217 .channels = 1,
218 .period_count = 2,
219 .format = PCM_FORMAT_S16_LE,
220 .stop_threshold = INT_MAX,
221 .avail_min = 0,
222};
223
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700224#define AFE_PROXY_CHANNEL_COUNT 2
225#define AFE_PROXY_SAMPLING_RATE 48000
226
227#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
228#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
229
230struct pcm_config pcm_config_afe_proxy_playback = {
231 .channels = AFE_PROXY_CHANNEL_COUNT,
232 .rate = AFE_PROXY_SAMPLING_RATE,
233 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
234 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
235 .format = PCM_FORMAT_S16_LE,
236 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
237 .stop_threshold = INT_MAX,
238 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
239};
240
241#define AFE_PROXY_RECORD_PERIOD_SIZE 768
242#define AFE_PROXY_RECORD_PERIOD_COUNT 4
243
244struct pcm_config pcm_config_afe_proxy_record = {
245 .channels = AFE_PROXY_CHANNEL_COUNT,
246 .rate = AFE_PROXY_SAMPLING_RATE,
247 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
248 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
249 .format = PCM_FORMAT_S16_LE,
250 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
251 .stop_threshold = INT_MAX,
252 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
253};
254
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700255const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700256 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
257 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800258 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700259 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700260 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700261 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800262 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700263
Eric Laurentb23d5282013-05-14 15:27:20 -0700264 [USECASE_AUDIO_RECORD] = "audio-record",
265 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800266 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700267 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700268
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800269 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
270 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700271
Eric Laurentb23d5282013-05-14 15:27:20 -0700272 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700273 [USECASE_VOICE2_CALL] = "voice2-call",
274 [USECASE_VOLTE_CALL] = "volte-call",
275 [USECASE_QCHAT_CALL] = "qchat-call",
276 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800277 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
278 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700279
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700280 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
281 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
282
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700283 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
284 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700285
286 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
287 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
288 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
289
vivek mehtaa68fea62017-06-08 19:04:02 -0700290 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
291 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200292
293 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700294
295 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700296};
297
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800298
299#define STRING_TO_ENUM(string) { #string, string }
300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800301struct string_to_enum {
302 const char *name;
303 uint32_t value;
304};
305
Haynes Mathew George569b7482017-05-08 14:44:27 -0700306static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800307 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
308 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
309 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700310 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700311 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700312 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
313 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
314 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
315 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
316 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
317 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
318 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
319 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
320 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800321};
322
Haynes Mathew George5191a852013-09-11 14:19:36 -0700323static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700324static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700325static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700326static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700327//cache last MBDRC cal step level
328static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700329
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800330static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
331static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
332
Haynes Mathew George03c40102016-01-29 17:57:48 -0800333static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
334 int flags __unused)
335{
336 int dir = 0;
337 switch (uc_id) {
338 case USECASE_AUDIO_RECORD_LOW_LATENCY:
339 dir = 1;
340 case USECASE_AUDIO_PLAYBACK_ULL:
341 break;
342 default:
343 return false;
344 }
345
346 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
347 PCM_PLAYBACK : PCM_CAPTURE);
348 if (adev->adm_is_noirq_avail)
349 return adev->adm_is_noirq_avail(adev->adm_data,
350 adev->snd_card, dev_id, dir);
351 return false;
352}
353
354static void register_out_stream(struct stream_out *out)
355{
356 struct audio_device *adev = out->dev;
357 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
358 return;
359
360 if (!adev->adm_register_output_stream)
361 return;
362
363 adev->adm_register_output_stream(adev->adm_data,
364 out->handle,
365 out->flags);
366
367 if (!adev->adm_set_config)
368 return;
369
370 if (out->realtime) {
371 adev->adm_set_config(adev->adm_data,
372 out->handle,
373 out->pcm, &out->config);
374 }
375}
376
377static void register_in_stream(struct stream_in *in)
378{
379 struct audio_device *adev = in->dev;
380 if (!adev->adm_register_input_stream)
381 return;
382
383 adev->adm_register_input_stream(adev->adm_data,
384 in->capture_handle,
385 in->flags);
386
387 if (!adev->adm_set_config)
388 return;
389
390 if (in->realtime) {
391 adev->adm_set_config(adev->adm_data,
392 in->capture_handle,
393 in->pcm,
394 &in->config);
395 }
396}
397
398static void request_out_focus(struct stream_out *out, long ns)
399{
400 struct audio_device *adev = out->dev;
401
Haynes Mathew George03c40102016-01-29 17:57:48 -0800402 if (adev->adm_request_focus_v2) {
403 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
404 } else if (adev->adm_request_focus) {
405 adev->adm_request_focus(adev->adm_data, out->handle);
406 }
407}
408
409static void request_in_focus(struct stream_in *in, long ns)
410{
411 struct audio_device *adev = in->dev;
412
Haynes Mathew George03c40102016-01-29 17:57:48 -0800413 if (adev->adm_request_focus_v2) {
414 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
415 } else if (adev->adm_request_focus) {
416 adev->adm_request_focus(adev->adm_data, in->capture_handle);
417 }
418}
419
420static void release_out_focus(struct stream_out *out, long ns __unused)
421{
422 struct audio_device *adev = out->dev;
423
424 if (adev->adm_abandon_focus)
425 adev->adm_abandon_focus(adev->adm_data, out->handle);
426}
427
428static void release_in_focus(struct stream_in *in, long ns __unused)
429{
430 struct audio_device *adev = in->dev;
431 if (adev->adm_abandon_focus)
432 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
433}
434
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700435static int parse_snd_card_status(struct str_parms * parms, int * card,
436 card_status_t * status)
437{
438 char value[32]={0};
439 char state[32]={0};
440
441 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
442
443 if (ret < 0)
444 return -1;
445
446 // sscanf should be okay as value is of max length 32.
447 // same as sizeof state.
448 if (sscanf(value, "%d,%s", card, state) < 2)
449 return -1;
450
451 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
452 CARD_STATUS_OFFLINE;
453 return 0;
454}
455
vivek mehta40125092017-08-21 18:48:51 -0700456// always call with adev lock held
457void send_gain_dep_calibration_l() {
458 if (last_known_cal_step >= 0)
459 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
460}
461
vivek mehta1a9b7c02015-06-25 11:49:38 -0700462__attribute__ ((visibility ("default")))
463bool audio_hw_send_gain_dep_calibration(int level) {
464 bool ret_val = false;
465 ALOGV("%s: enter ... ", __func__);
466
467 pthread_mutex_lock(&adev_init_lock);
468
469 if (adev != NULL && adev->platform != NULL) {
470 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700471 last_known_cal_step = level;
472 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700473 pthread_mutex_unlock(&adev->lock);
474 } else {
475 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
476 }
477
478 pthread_mutex_unlock(&adev_init_lock);
479
480 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
481 return ret_val;
482}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700483
vivek mehtaa8d7c922016-05-25 14:40:44 -0700484__attribute__ ((visibility ("default")))
485int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
486 int table_size) {
487 int ret_val = 0;
488 ALOGV("%s: enter ... ", __func__);
489
490 pthread_mutex_lock(&adev_init_lock);
491 if (adev == NULL) {
492 ALOGW("%s: adev is NULL .... ", __func__);
493 goto done;
494 }
495
496 pthread_mutex_lock(&adev->lock);
497 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
498 pthread_mutex_unlock(&adev->lock);
499done:
500 pthread_mutex_unlock(&adev_init_lock);
501 ALOGV("%s: exit ... ", __func__);
502 return ret_val;
503}
504
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700505static bool is_supported_format(audio_format_t format)
506{
Eric Laurent8251ac82014-07-23 11:00:25 -0700507 switch (format) {
508 case AUDIO_FORMAT_MP3:
509 case AUDIO_FORMAT_AAC_LC:
510 case AUDIO_FORMAT_AAC_HE_V1:
511 case AUDIO_FORMAT_AAC_HE_V2:
512 return true;
513 default:
514 break;
515 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700516 return false;
517}
518
Haynes Mathew George03c40102016-01-29 17:57:48 -0800519static inline bool is_mmap_usecase(audio_usecase_t uc_id)
520{
521 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
522 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
523}
524
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700525static int get_snd_codec_id(audio_format_t format)
526{
527 int id = 0;
528
Eric Laurent8251ac82014-07-23 11:00:25 -0700529 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700530 case AUDIO_FORMAT_MP3:
531 id = SND_AUDIOCODEC_MP3;
532 break;
533 case AUDIO_FORMAT_AAC:
534 id = SND_AUDIOCODEC_AAC;
535 break;
536 default:
537 ALOGE("%s: Unsupported audio format", __func__);
538 }
539
540 return id;
541}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800542
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800543static int audio_ssr_status(struct audio_device *adev)
544{
545 int ret = 0;
546 struct mixer_ctl *ctl;
547 const char *mixer_ctl_name = "Audio SSR Status";
548
549 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
550 ret = mixer_ctl_get_value(ctl, 0);
551 ALOGD("%s: value: %d", __func__, ret);
552 return ret;
553}
554
vivek mehta4a824772017-06-08 19:05:49 -0700555static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
556{
557 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
558}
559
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800560static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
561{
562 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
563 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
564 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
565 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
566 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
567 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
568
569}
570
571static bool is_a2dp_device(snd_device_t out_snd_device)
572{
573 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
574}
575
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800576int enable_audio_route(struct audio_device *adev,
577 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800578{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700579 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800580 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800581
582 if (usecase == NULL)
583 return -EINVAL;
584
585 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
586
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800587 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700588 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800589 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700590 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530591 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800592 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800593 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500594 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000595 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700596 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700597 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800599 ALOGV("%s: exit", __func__);
600 return 0;
601}
602
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800603int disable_audio_route(struct audio_device *adev,
604 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800605{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700606 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800607 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800608
609 if (usecase == NULL)
610 return -EINVAL;
611
612 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700613 if (usecase->type == PCM_CAPTURE)
614 snd_device = usecase->in_snd_device;
615 else
616 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800617 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500618 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700619 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700620 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000621 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800623 ALOGV("%s: exit", __func__);
624 return 0;
625}
626
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800627int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700628 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800629{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700630 int i, num_devices = 0;
631 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800632 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800633 if (snd_device < SND_DEVICE_MIN ||
634 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800635 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800636 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800637 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700638
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700639 platform_send_audio_calibration(adev->platform, snd_device);
640
vivek mehtade4849c2016-03-03 17:23:38 -0800641 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700642 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700643 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800644 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700645 }
646
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700647 /* due to the possibility of calibration overwrite between listen
648 and audio, notify sound trigger hal before audio calibration is sent */
649 audio_extn_sound_trigger_update_device_status(snd_device,
650 ST_EVENT_SND_DEVICE_BUSY);
651
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700652 if (audio_extn_spkr_prot_is_enabled())
653 audio_extn_spkr_prot_calib_cancel(adev);
654
zhaoyang yin4211fad2015-06-04 21:13:25 +0800655 audio_extn_dsm_feedback_enable(adev, snd_device, true);
656
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800657 if (is_a2dp_device(snd_device) &&
658 (audio_extn_a2dp_start_playback() < 0)) {
659 ALOGE("%s: failed to configure A2DP control path", __func__);
660 goto on_error;
661 }
662
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700663 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800664 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800665 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700666 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
667 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700668 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800669 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700670 }
671 if (audio_extn_spkr_prot_start_processing(snd_device)) {
672 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800673 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700674 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700675 } else if (platform_can_split_snd_device(snd_device,
676 &num_devices,
677 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700678 for (i = 0; i < num_devices; i++) {
679 enable_snd_device(adev, new_snd_devices[i]);
680 }
vivek mehtab6506412015-08-07 16:55:17 -0700681 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700682 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800683 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
684 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
685 ALOGE(" %s: Invalid sound device returned", __func__);
686 goto on_error;
687 }
Ed Tam70b5c142016-03-21 19:14:29 -0700688
Eric Laurent2e140aa2016-06-30 17:14:46 -0700689 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800690 audio_route_apply_and_update_path(adev->audio_route, device_name);
691 }
692on_success:
693 adev->snd_dev_ref_cnt[snd_device]++;
694 ret_val = 0;
695on_error:
696 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800697}
698
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800699int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700700 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800701{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700702 int i, num_devices = 0;
703 snd_device_t new_snd_devices[2];
704
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800705 if (snd_device < SND_DEVICE_MIN ||
706 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800707 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800708 return -EINVAL;
709 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700710 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
711 ALOGE("%s: device ref cnt is already 0", __func__);
712 return -EINVAL;
713 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800714 audio_extn_tfa_98xx_disable_speaker(snd_device);
715
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700716 adev->snd_dev_ref_cnt[snd_device]--;
717 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800718 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800719
720 if (is_a2dp_device(snd_device))
721 audio_extn_a2dp_stop_playback();
722
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700723 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800724 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700725 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700726 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
727 audio_extn_spkr_prot_is_enabled()) {
728 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700729
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700730 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
731 // and does not use speaker swap. As this code causes a problem with device enable ref
732 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700733 // when speaker device is disabled, reset swap.
734 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700735 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700736
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700737 } else if (platform_can_split_snd_device(snd_device,
738 &num_devices,
739 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700740 for (i = 0; i < num_devices; i++) {
741 disable_snd_device(adev, new_snd_devices[i]);
742 }
vivek mehtab6506412015-08-07 16:55:17 -0700743 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700744 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800745 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
746 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
747 ALOGE(" %s: Invalid sound device returned", __func__);
748 return -EINVAL;
749 }
750
Eric Laurent2e140aa2016-06-30 17:14:46 -0700751 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800752 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700753 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700754 audio_extn_sound_trigger_update_device_status(snd_device,
755 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700756 }
vivek mehtab6506412015-08-07 16:55:17 -0700757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800758 return 0;
759}
760
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700761/*
762 legend:
763 uc - existing usecase
764 new_uc - new usecase
765 d1, d11, d2 - SND_DEVICE enums
766 a1, a2 - corresponding ANDROID device enums
767 B, B1, B2 - backend strings
768
769case 1
770 uc->dev d1 (a1) B1
771 new_uc->dev d1 (a1), d2 (a2) B1, B2
772
773 resolution: disable and enable uc->dev on d1
774
775case 2
776 uc->dev d1 (a1) B1
777 new_uc->dev d11 (a1) B1
778
779 resolution: need to switch uc since d1 and d11 are related
780 (e.g. speaker and voice-speaker)
781 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
782
783case 3
784 uc->dev d1 (a1) B1
785 new_uc->dev d2 (a2) B2
786
787 resolution: no need to switch uc
788
789case 4
790 uc->dev d1 (a1) B
791 new_uc->dev d2 (a2) B
792
793 resolution: disable enable uc-dev on d2 since backends match
794 we cannot enable two streams on two different devices if they
795 share the same backend. e.g. if offload is on speaker device using
796 QUAD_MI2S backend and a low-latency stream is started on voice-handset
797 using the same backend, offload must also be switched to voice-handset.
798
799case 5
800 uc->dev d1 (a1) B
801 new_uc->dev d1 (a1), d2 (a2) B
802
803 resolution: disable enable uc-dev on d2 since backends match
804 we cannot enable two streams on two different devices if they
805 share the same backend.
806
807case 6
808 uc->dev d1 a1 B1
809 new_uc->dev d2 a1 B2
810
811 resolution: no need to switch
812
813case 7
814
815 uc->dev d1 (a1), d2 (a2) B1, B2
816 new_uc->dev d1 B1
817
818 resolution: no need to switch
819
820*/
821static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
822 struct audio_usecase *new_uc,
823 snd_device_t new_snd_device)
824{
825 audio_devices_t a1 = uc->stream.out->devices;
826 audio_devices_t a2 = new_uc->stream.out->devices;
827
828 snd_device_t d1 = uc->out_snd_device;
829 snd_device_t d2 = new_snd_device;
830
831 // Treat as a special case when a1 and a2 are not disjoint
832 if ((a1 != a2) && (a1 & a2)) {
833 snd_device_t d3[2];
834 int num_devices = 0;
835 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
836 &num_devices,
837 d3);
838 if (ret < 0) {
839 if (ret != -ENOSYS) {
840 ALOGW("%s failed to split snd_device %d",
841 __func__,
842 popcount(a1) > 1 ? d1 : d2);
843 }
844 goto end;
845 }
846
847 // NB: case 7 is hypothetical and isn't a practical usecase yet.
848 // But if it does happen, we need to give priority to d2 if
849 // the combo devices active on the existing usecase share a backend.
850 // This is because we cannot have a usecase active on a combo device
851 // and a new usecase requests one device in this combo pair.
852 if (platform_check_backends_match(d3[0], d3[1])) {
853 return d2; // case 5
854 } else {
855 return d1; // case 1
856 }
857 } else {
858 if (platform_check_backends_match(d1, d2)) {
859 return d2; // case 2, 4
860 } else {
861 return d1; // case 6, 3
862 }
863 }
864
865end:
866 return d2; // return whatever was calculated before.
867}
868
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700869static void check_and_route_playback_usecases(struct audio_device *adev,
870 struct audio_usecase *uc_info,
871 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700872{
873 struct listnode *node;
874 struct audio_usecase *usecase;
875 bool switch_device[AUDIO_USECASE_MAX];
876 int i, num_uc_to_switch = 0;
877
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700878 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
879 uc_info,
880 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700881
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800882 /* For a2dp device reconfigure all active sessions
883 * with new AFE encoder format based on a2dp state
884 */
885 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
886 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
887 audio_extn_a2dp_is_force_device_switch()) {
888 force_routing = true;
889 }
890
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700891 /*
892 * This function is to make sure that all the usecases that are active on
893 * the hardware codec backend are always routed to any one device that is
894 * handled by the hardware codec.
895 * For example, if low-latency and deep-buffer usecases are currently active
896 * on speaker and out_set_parameters(headset) is received on low-latency
897 * output, then we have to make sure deep-buffer is also switched to headset,
898 * because of the limitation that both the devices cannot be enabled
899 * at the same time as they share the same backend.
900 */
901 /* Disable all the usecases on the shared backend other than the
902 specified usecase */
903 for (i = 0; i < AUDIO_USECASE_MAX; i++)
904 switch_device[i] = false;
905
906 list_for_each(node, &adev->usecase_list) {
907 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700908 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
909 continue;
910
911 if (force_routing ||
912 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700913 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
914 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700915 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
917 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700918 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700919 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700920 switch_device[usecase->id] = true;
921 num_uc_to_switch++;
922 }
923 }
924
925 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700926 list_for_each(node, &adev->usecase_list) {
927 usecase = node_to_item(node, struct audio_usecase, list);
928 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700929 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900930 }
931 }
932
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700933 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900934 list_for_each(node, &adev->usecase_list) {
935 usecase = node_to_item(node, struct audio_usecase, list);
936 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700937 d_device = derive_playback_snd_device(usecase, uc_info,
938 snd_device);
939 enable_snd_device(adev, d_device);
940 /* Update the out_snd_device before enabling the audio route */
941 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 }
943 }
944
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700945 /* Re-route all the usecases on the shared backend other than the
946 specified usecase to new snd devices */
947 list_for_each(node, &adev->usecase_list) {
948 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700949 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700950 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700951 }
952 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700953 }
954}
955
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700956static void check_and_route_capture_usecases(struct audio_device *adev,
957 struct audio_usecase *uc_info,
958 snd_device_t snd_device)
959{
960 struct listnode *node;
961 struct audio_usecase *usecase;
962 bool switch_device[AUDIO_USECASE_MAX];
963 int i, num_uc_to_switch = 0;
964
vivek mehta4ed66e62016-04-15 23:33:34 -0700965 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
966
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700967 /*
968 * This function is to make sure that all the active capture usecases
969 * are always routed to the same input sound device.
970 * For example, if audio-record and voice-call usecases are currently
971 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
972 * is received for voice call then we have to make sure that audio-record
973 * usecase is also switched to earpiece i.e. voice-dmic-ef,
974 * because of the limitation that two devices cannot be enabled
975 * at the same time if they share the same backend.
976 */
977 for (i = 0; i < AUDIO_USECASE_MAX; i++)
978 switch_device[i] = false;
979
980 list_for_each(node, &adev->usecase_list) {
981 usecase = node_to_item(node, struct audio_usecase, list);
982 if (usecase->type != PCM_PLAYBACK &&
983 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700984 usecase->in_snd_device != snd_device &&
985 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700986 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
987 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700988 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700989 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700990 switch_device[usecase->id] = true;
991 num_uc_to_switch++;
992 }
993 }
994
995 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700996 list_for_each(node, &adev->usecase_list) {
997 usecase = node_to_item(node, struct audio_usecase, list);
998 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700999 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001000 }
1001 }
1002
1003 list_for_each(node, &adev->usecase_list) {
1004 usecase = node_to_item(node, struct audio_usecase, list);
1005 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001006 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001007 }
1008 }
1009
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001010 /* Re-route all the usecases on the shared backend other than the
1011 specified usecase to new snd devices */
1012 list_for_each(node, &adev->usecase_list) {
1013 usecase = node_to_item(node, struct audio_usecase, list);
1014 /* Update the in_snd_device only before enabling the audio route */
1015 if (switch_device[usecase->id] ) {
1016 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001017 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001018 }
1019 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001020 }
1021}
1022
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001023/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001024static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001026 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001027 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028
1029 switch (channels) {
1030 /*
1031 * Do not handle stereo output in Multi-channel cases
1032 * Stereo case is handled in normal playback path
1033 */
1034 case 6:
1035 ALOGV("%s: HDMI supports 5.1", __func__);
1036 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1037 break;
1038 case 8:
1039 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1040 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1041 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1042 break;
1043 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001044 ALOGE("HDMI does not support multi channel playback");
1045 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046 break;
1047 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001048 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049}
1050
Andy Hung18859412017-08-09 11:47:21 -07001051static ssize_t read_usb_sup_sample_rates(bool is_playback,
1052 uint32_t *supported_sample_rates,
1053 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001054{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001055 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1056 supported_sample_rates,
1057 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001058#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001059 for (ssize_t i=0; i<count; i++) {
1060 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1061 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001062 }
1063#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001064 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001065}
1066
Haynes Mathew George569b7482017-05-08 14:44:27 -07001067static int read_usb_sup_channel_masks(bool is_playback,
1068 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001069 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001070{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001071 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001072 int channel_count;
1073 uint32_t num_masks = 0;
1074 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1075 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001076 }
Eric Laurent74b55762017-07-09 17:04:53 -07001077 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001078 // start from 2 channels as framework currently doesn't support mono.
1079 // TODO: consider only supporting channel index masks beyond stereo here.
1080 for (channel_count = FCC_2;
1081 channel_count <= channels && num_masks < max_masks;
1082 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001083 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1084 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001085 for (channel_count = FCC_2;
1086 channel_count <= channels && num_masks < max_masks;
1087 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001088 supported_channel_masks[num_masks++] =
1089 audio_channel_mask_for_index_assignment_from_count(channel_count);
1090 }
1091 } else {
1092 // For capture we report all supported channel masks from 1 channel up.
1093 channel_count = MIN_CHANNEL_COUNT;
1094 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1095 // indexed mask
1096 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1097 supported_channel_masks[num_masks++] =
1098 audio_channel_in_mask_from_count(channel_count);
1099 }
1100 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001101#ifdef NDEBUG
1102 for (size_t i = 0; i < num_masks; ++i) {
1103 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1104 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1105 }
1106#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001107 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001108}
1109
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001110static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001111 audio_format_t *supported_formats,
1112 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001113{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001114 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001115 switch (bitwidth) {
1116 case 24:
1117 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001118 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001119 break;
1120 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001121 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001122 break;
1123 case 16:
1124 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001125 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001126 break;
1127 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001128 ALOGV("%s: %s supported format %d", __func__,
1129 is_playback ? "P" : "C", bitwidth);
1130 return 1;
1131}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001132
Haynes Mathew George569b7482017-05-08 14:44:27 -07001133static int read_usb_sup_params_and_compare(bool is_playback,
1134 audio_format_t *format,
1135 audio_format_t *supported_formats,
1136 uint32_t max_formats,
1137 audio_channel_mask_t *mask,
1138 audio_channel_mask_t *supported_channel_masks,
1139 uint32_t max_masks,
1140 uint32_t *rate,
1141 uint32_t *supported_sample_rates,
1142 uint32_t max_rates) {
1143 int ret = 0;
1144 int num_formats;
1145 int num_masks;
1146 int num_rates;
1147 int i;
1148
1149 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1150 max_formats);
1151 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1152 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001153
Haynes Mathew George569b7482017-05-08 14:44:27 -07001154 num_rates = read_usb_sup_sample_rates(is_playback,
1155 supported_sample_rates, max_rates);
1156
1157#define LUT(table, len, what, dflt) \
1158 for (i=0; i<len && (table[i] != what); i++); \
1159 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1160
1161 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1162 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1163 LUT(supported_sample_rates, num_rates, *rate, 0);
1164
1165#undef LUT
1166 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001167}
1168
Andy Hungd9653bd2017-08-01 19:31:39 -07001169static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1170{
1171 // Check if usb is ready.
1172 // The usb device may have been removed quickly after insertion and hence
1173 // no longer available. This will show up as empty channel masks, or rates.
1174
1175 pthread_mutex_lock(&adev->lock);
1176 uint32_t supported_sample_rate;
1177
1178 // we consider usb ready if we can fetch at least one sample rate.
1179 const bool ready = read_usb_sup_sample_rates(
1180 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1181 pthread_mutex_unlock(&adev->lock);
1182 return ready;
1183}
1184
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001185static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1186{
1187 struct audio_usecase *usecase;
1188 struct listnode *node;
1189
1190 list_for_each(node, &adev->usecase_list) {
1191 usecase = node_to_item(node, struct audio_usecase, list);
1192 if (usecase->type == VOICE_CALL) {
1193 ALOGV("%s: usecase id %d", __func__, usecase->id);
1194 return usecase->id;
1195 }
1196 }
1197 return USECASE_INVALID;
1198}
1199
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001200struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1201 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001202{
1203 struct audio_usecase *usecase;
1204 struct listnode *node;
1205
1206 list_for_each(node, &adev->usecase_list) {
1207 usecase = node_to_item(node, struct audio_usecase, list);
1208 if (usecase->id == uc_id)
1209 return usecase;
1210 }
1211 return NULL;
1212}
1213
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001214static bool force_device_switch(struct audio_usecase *usecase)
1215{
1216 if (usecase->stream.out == NULL) {
1217 ALOGE("%s: stream.out is NULL", __func__);
1218 return false;
1219 }
1220
1221 // Force all A2DP output devices to reconfigure for proper AFE encode format
1222 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1223 // in suspended state, hence try to trigger a retry when we again get a routing request.
1224 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1225 audio_extn_a2dp_is_force_device_switch()) {
1226 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1227 return true;
1228 }
1229
1230 return false;
1231}
1232
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001233int select_devices(struct audio_device *adev,
1234 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001235{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001236 snd_device_t out_snd_device = SND_DEVICE_NONE;
1237 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001238 struct audio_usecase *usecase = NULL;
1239 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001240 struct audio_usecase *hfp_usecase = NULL;
1241 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001242 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001243 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001244 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1245 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001246
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001247 usecase = get_usecase_from_list(adev, uc_id);
1248 if (usecase == NULL) {
1249 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1250 return -EINVAL;
1251 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001252
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001253 if ((usecase->type == VOICE_CALL) ||
1254 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001255 out_snd_device = platform_get_output_snd_device(adev->platform,
1256 usecase->stream.out->devices);
1257 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001258 usecase->devices = usecase->stream.out->devices;
1259 } else {
1260 /*
1261 * If the voice call is active, use the sound devices of voice call usecase
1262 * so that it would not result any device switch. All the usecases will
1263 * be switched to new device when select_devices() is called for voice call
1264 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001265 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001266 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001267 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001268 vc_usecase = get_usecase_from_list(adev,
1269 get_voice_usecase_id_from_list(adev));
1270 if ((vc_usecase != NULL) &&
1271 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1272 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001273 in_snd_device = vc_usecase->in_snd_device;
1274 out_snd_device = vc_usecase->out_snd_device;
1275 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001276 } else if (audio_extn_hfp_is_active(adev)) {
1277 hfp_ucid = audio_extn_hfp_get_usecase();
1278 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1279 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1280 in_snd_device = hfp_usecase->in_snd_device;
1281 out_snd_device = hfp_usecase->out_snd_device;
1282 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001283 }
1284 if (usecase->type == PCM_PLAYBACK) {
1285 usecase->devices = usecase->stream.out->devices;
1286 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001287 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001288 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001289
Eric Laurentb23d5282013-05-14 15:27:20 -07001290 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001291 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001292
1293 if (voip_usecase)
1294 voip_out = voip_usecase->stream.out;
1295
1296 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001297 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001298 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001299 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001300 select_devices(adev, adev->active_input->usecase);
1301 }
1302 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001303 } else if (usecase->type == PCM_CAPTURE) {
1304 usecase->devices = usecase->stream.in->device;
1305 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001306 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001307 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001308 if (adev->active_input &&
1309 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1310 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001311
1312 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1313 USECASE_AUDIO_PLAYBACK_VOIP);
1314
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001315 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001316 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1317 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001318 } else if (voip_usecase) {
1319 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001320 } else if (adev->primary_output) {
1321 out_device = adev->primary_output->devices;
1322 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001323 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001324 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001325 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001326 }
1327 }
1328
1329 if (out_snd_device == usecase->out_snd_device &&
1330 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001331 if (!force_device_switch(usecase))
1332 return 0;
1333 }
1334
1335 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1336 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1337 return 0;
1338 }
1339
1340 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
1341 (!audio_extn_a2dp_is_ready())) {
1342 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
1343 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344 }
1345
Eric Laurent2bafff12016-03-17 12:17:23 -07001346 if (out_snd_device != SND_DEVICE_NONE &&
1347 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1348 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1349 __func__,
1350 use_case_table[uc_id],
1351 adev->last_logged_snd_device[uc_id][0],
1352 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1353 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1354 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1355 -1,
1356 out_snd_device,
1357 platform_get_snd_device_name(out_snd_device),
1358 platform_get_snd_device_acdb_id(out_snd_device));
1359 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1360 }
1361 if (in_snd_device != SND_DEVICE_NONE &&
1362 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1363 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1364 __func__,
1365 use_case_table[uc_id],
1366 adev->last_logged_snd_device[uc_id][1],
1367 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1368 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1369 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1370 -1,
1371 in_snd_device,
1372 platform_get_snd_device_name(in_snd_device),
1373 platform_get_snd_device_acdb_id(in_snd_device));
1374 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1375 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001377 /*
1378 * Limitation: While in call, to do a device switch we need to disable
1379 * and enable both RX and TX devices though one of them is same as current
1380 * device.
1381 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001382 if ((usecase->type == VOICE_CALL) &&
1383 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1384 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001385 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001386 /* Disable sidetone only if voice call already exists */
1387 if (voice_is_call_state_active(adev))
1388 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001389 }
1390
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001391 /* Disable current sound devices */
1392 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001393 disable_audio_route(adev, usecase);
1394 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001395 }
1396
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001397 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001398 disable_audio_route(adev, usecase);
1399 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001400 }
1401
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001402 /* Applicable only on the targets that has external modem.
1403 * New device information should be sent to modem before enabling
1404 * the devices to reduce in-call device switch time.
1405 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001406 if ((usecase->type == VOICE_CALL) &&
1407 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1408 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001409 status = platform_switch_voice_call_enable_device_config(adev->platform,
1410 out_snd_device,
1411 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001412 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001413
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001414 /* Enable new sound devices */
1415 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001416 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001417 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1418 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001419 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001420 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001421 }
1422
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001423 if (in_snd_device != SND_DEVICE_NONE) {
1424 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001425 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001426 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001427
Eric Laurentb23d5282013-05-14 15:27:20 -07001428 if (usecase->type == VOICE_CALL)
1429 status = platform_switch_voice_call_device_post(adev->platform,
1430 out_snd_device,
1431 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001432
sangwoo170731f2013-06-08 15:36:36 +09001433 usecase->in_snd_device = in_snd_device;
1434 usecase->out_snd_device = out_snd_device;
1435
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001436 audio_extn_tfa_98xx_set_mode();
1437
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001438 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001439
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001440 /* Applicable only on the targets that has external modem.
1441 * Enable device command should be sent to modem only after
1442 * enabling voice call mixer controls
1443 */
vivek mehta765eb642015-08-07 19:46:06 -07001444 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001445 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1446 out_snd_device,
1447 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001448 /* Enable sidetone only if voice call already exists */
1449 if (voice_is_call_state_active(adev))
1450 voice_set_sidetone(adev, out_snd_device, true);
1451 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001452
Eric Laurentf4520b02017-09-20 18:31:58 -07001453 if (usecase == voip_usecase) {
1454 struct stream_out *voip_out = voip_usecase->stream.out;
1455 audio_extn_utils_send_app_type_gain(adev,
1456 voip_out->app_type_cfg.app_type,
1457 &voip_out->app_type_cfg.gain[0]);
1458 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001459 return status;
1460}
1461
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001462static int stop_input_stream(struct stream_in *in)
1463{
1464 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001465 struct audio_usecase *uc_info;
1466 struct audio_device *adev = in->dev;
1467
Eric Laurent994a6932013-07-17 11:51:42 -07001468 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001469 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001470
1471 if (adev->active_input) {
1472 if (adev->active_input->usecase == in->usecase) {
1473 adev->active_input = NULL;
1474 } else {
1475 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1476 __func__,
1477 use_case_table[adev->active_input->usecase],
1478 use_case_table[in->usecase]);
1479 }
1480 }
1481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001482 uc_info = get_usecase_from_list(adev, in->usecase);
1483 if (uc_info == NULL) {
1484 ALOGE("%s: Could not find the usecase (%d) in the list",
1485 __func__, in->usecase);
1486 return -EINVAL;
1487 }
1488
vivek mehta781065c2017-04-04 12:55:01 -07001489 /* Close in-call recording streams */
1490 voice_check_and_stop_incall_rec_usecase(adev, in);
1491
Eric Laurent150dbfe2013-02-27 14:31:02 -08001492 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001493 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001494
1495 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001496 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001498 list_remove(&uc_info->list);
1499 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001500
Eric Laurent994a6932013-07-17 11:51:42 -07001501 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001502 return ret;
1503}
1504
1505int start_input_stream(struct stream_in *in)
1506{
1507 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001508 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001509 struct audio_usecase *uc_info;
1510 struct audio_device *adev = in->dev;
1511
Eric Laurent994a6932013-07-17 11:51:42 -07001512 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001513
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001514 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1515 return -EIO;
1516
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001517 if (in->card_status == CARD_STATUS_OFFLINE ||
1518 adev->card_status == CARD_STATUS_OFFLINE) {
1519 ALOGW("in->card_status or adev->card_status offline, try again");
1520 ret = -EAGAIN;
1521 goto error_config;
1522 }
1523
vivek mehta781065c2017-04-04 12:55:01 -07001524 /* Check if source matches incall recording usecase criteria */
1525 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1526 if (ret)
1527 goto error_config;
1528 else
1529 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1530
Eric Laurentb23d5282013-05-14 15:27:20 -07001531 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532 if (in->pcm_device_id < 0) {
1533 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1534 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001535 ret = -EINVAL;
1536 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001538
1539 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001540 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1541 uc_info->id = in->usecase;
1542 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001543 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001544 uc_info->devices = in->device;
1545 uc_info->in_snd_device = SND_DEVICE_NONE;
1546 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001547
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001548 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001549
Wei Wangf4837d52017-11-21 14:51:20 -08001550 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001551 audio_extn_perf_lock_acquire();
1552
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001553 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001554
Eric Laurent0e46adf2016-12-16 12:49:24 -08001555 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001556 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001557 ALOGE("%s: pcm stream not ready", __func__);
1558 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001559 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001560 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001561 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001562 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1563 goto error_open;
1564 }
1565 } else {
1566 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1567 unsigned int pcm_open_retry_count = 0;
1568
1569 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1570 flags |= PCM_MMAP | PCM_NOIRQ;
1571 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1572 } else if (in->realtime) {
1573 flags |= PCM_MMAP | PCM_NOIRQ;
1574 }
1575
1576 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1577 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1578
1579 while (1) {
1580 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1581 flags, &in->config);
1582 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1583 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1584 if (in->pcm != NULL) {
1585 pcm_close(in->pcm);
1586 in->pcm = NULL;
1587 }
1588 if (pcm_open_retry_count-- == 0) {
1589 ret = -EIO;
1590 goto error_open;
1591 }
1592 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1593 continue;
1594 }
1595 break;
1596 }
1597
1598 ALOGV("%s: pcm_prepare", __func__);
1599 ret = pcm_prepare(in->pcm);
1600 if (ret < 0) {
1601 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001602 pcm_close(in->pcm);
1603 in->pcm = NULL;
1604 goto error_open;
1605 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001606 if (in->realtime) {
1607 ret = pcm_start(in->pcm);
1608 if (ret < 0) {
1609 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1610 pcm_close(in->pcm);
1611 in->pcm = NULL;
1612 goto error_open;
1613 }
1614 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001615 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001616 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001617 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001618 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001619 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001620
Eric Laurent0e46adf2016-12-16 12:49:24 -08001621 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001622
1623error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001625 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001626 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001627
1628error_config:
1629 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001630 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001631 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632}
1633
Eric Laurenta1478072015-09-21 17:21:52 -07001634void lock_input_stream(struct stream_in *in)
1635{
1636 pthread_mutex_lock(&in->pre_lock);
1637 pthread_mutex_lock(&in->lock);
1638 pthread_mutex_unlock(&in->pre_lock);
1639}
1640
1641void lock_output_stream(struct stream_out *out)
1642{
1643 pthread_mutex_lock(&out->pre_lock);
1644 pthread_mutex_lock(&out->lock);
1645 pthread_mutex_unlock(&out->pre_lock);
1646}
1647
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001648/* must be called with out->lock locked */
1649static int send_offload_cmd_l(struct stream_out* out, int command)
1650{
1651 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1652
1653 ALOGVV("%s %d", __func__, command);
1654
1655 cmd->cmd = command;
1656 list_add_tail(&out->offload_cmd_list, &cmd->node);
1657 pthread_cond_signal(&out->offload_cond);
1658 return 0;
1659}
1660
1661/* must be called iwth out->lock locked */
1662static void stop_compressed_output_l(struct stream_out *out)
1663{
1664 out->offload_state = OFFLOAD_STATE_IDLE;
1665 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001666 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001667 if (out->compr != NULL) {
1668 compress_stop(out->compr);
1669 while (out->offload_thread_blocked) {
1670 pthread_cond_wait(&out->cond, &out->lock);
1671 }
1672 }
1673}
1674
1675static void *offload_thread_loop(void *context)
1676{
1677 struct stream_out *out = (struct stream_out *) context;
1678 struct listnode *item;
1679
1680 out->offload_state = OFFLOAD_STATE_IDLE;
1681 out->playback_started = 0;
1682
1683 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1684 set_sched_policy(0, SP_FOREGROUND);
1685 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1686
1687 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001688 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001689 for (;;) {
1690 struct offload_cmd *cmd = NULL;
1691 stream_callback_event_t event;
1692 bool send_callback = false;
1693
1694 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1695 __func__, list_empty(&out->offload_cmd_list),
1696 out->offload_state);
1697 if (list_empty(&out->offload_cmd_list)) {
1698 ALOGV("%s SLEEPING", __func__);
1699 pthread_cond_wait(&out->offload_cond, &out->lock);
1700 ALOGV("%s RUNNING", __func__);
1701 continue;
1702 }
1703
1704 item = list_head(&out->offload_cmd_list);
1705 cmd = node_to_item(item, struct offload_cmd, node);
1706 list_remove(item);
1707
1708 ALOGVV("%s STATE %d CMD %d out->compr %p",
1709 __func__, out->offload_state, cmd->cmd, out->compr);
1710
1711 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1712 free(cmd);
1713 break;
1714 }
1715
1716 if (out->compr == NULL) {
1717 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001718 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001719 pthread_cond_signal(&out->cond);
1720 continue;
1721 }
1722 out->offload_thread_blocked = true;
1723 pthread_mutex_unlock(&out->lock);
1724 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001725 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001726 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1727 compress_wait(out->compr, -1);
1728 send_callback = true;
1729 event = STREAM_CBK_EVENT_WRITE_READY;
1730 break;
1731 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001732 compress_next_track(out->compr);
1733 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001734 send_callback = true;
1735 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001736 /* Resend the metadata for next iteration */
1737 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001738 break;
1739 case OFFLOAD_CMD_DRAIN:
1740 compress_drain(out->compr);
1741 send_callback = true;
1742 event = STREAM_CBK_EVENT_DRAIN_READY;
1743 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001744 case OFFLOAD_CMD_ERROR:
1745 send_callback = true;
1746 event = STREAM_CBK_EVENT_ERROR;
1747 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001748 default:
1749 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1750 break;
1751 }
Eric Laurenta1478072015-09-21 17:21:52 -07001752 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001753 out->offload_thread_blocked = false;
1754 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001755 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001756 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001757 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001758 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001759 free(cmd);
1760 }
1761
1762 pthread_cond_signal(&out->cond);
1763 while (!list_empty(&out->offload_cmd_list)) {
1764 item = list_head(&out->offload_cmd_list);
1765 list_remove(item);
1766 free(node_to_item(item, struct offload_cmd, node));
1767 }
1768 pthread_mutex_unlock(&out->lock);
1769
1770 return NULL;
1771}
1772
1773static int create_offload_callback_thread(struct stream_out *out)
1774{
1775 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1776 list_init(&out->offload_cmd_list);
1777 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1778 offload_thread_loop, out);
1779 return 0;
1780}
1781
1782static int destroy_offload_callback_thread(struct stream_out *out)
1783{
Eric Laurenta1478072015-09-21 17:21:52 -07001784 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001785 stop_compressed_output_l(out);
1786 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1787
1788 pthread_mutex_unlock(&out->lock);
1789 pthread_join(out->offload_thread, (void **) NULL);
1790 pthread_cond_destroy(&out->offload_cond);
1791
1792 return 0;
1793}
1794
Eric Laurent07eeafd2013-10-06 12:52:49 -07001795static bool allow_hdmi_channel_config(struct audio_device *adev)
1796{
1797 struct listnode *node;
1798 struct audio_usecase *usecase;
1799 bool ret = true;
1800
1801 list_for_each(node, &adev->usecase_list) {
1802 usecase = node_to_item(node, struct audio_usecase, list);
1803 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1804 /*
1805 * If voice call is already existing, do not proceed further to avoid
1806 * disabling/enabling both RX and TX devices, CSD calls, etc.
1807 * Once the voice call done, the HDMI channels can be configured to
1808 * max channels of remaining use cases.
1809 */
1810 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001811 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001812 __func__);
1813 ret = false;
1814 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001815 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1816 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001817 "no change in HDMI channels", __func__);
1818 ret = false;
1819 break;
1820 }
1821 }
1822 }
1823 return ret;
1824}
1825
1826static int check_and_set_hdmi_channels(struct audio_device *adev,
1827 unsigned int channels)
1828{
1829 struct listnode *node;
1830 struct audio_usecase *usecase;
1831
1832 /* Check if change in HDMI channel config is allowed */
1833 if (!allow_hdmi_channel_config(adev))
1834 return 0;
1835
1836 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001837 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001838 return 0;
1839 }
1840
1841 platform_set_hdmi_channels(adev->platform, channels);
1842 adev->cur_hdmi_channels = channels;
1843
1844 /*
1845 * Deroute all the playback streams routed to HDMI so that
1846 * the back end is deactivated. Note that backend will not
1847 * be deactivated if any one stream is connected to it.
1848 */
1849 list_for_each(node, &adev->usecase_list) {
1850 usecase = node_to_item(node, struct audio_usecase, list);
1851 if (usecase->type == PCM_PLAYBACK &&
1852 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001853 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001854 }
1855 }
1856
1857 /*
1858 * Enable all the streams disabled above. Now the HDMI backend
1859 * will be activated with new channel configuration
1860 */
1861 list_for_each(node, &adev->usecase_list) {
1862 usecase = node_to_item(node, struct audio_usecase, list);
1863 if (usecase->type == PCM_PLAYBACK &&
1864 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001865 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001866 }
1867 }
1868
1869 return 0;
1870}
1871
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001872static int check_and_set_usb_service_interval(struct audio_device *adev,
1873 struct audio_usecase *uc_info,
1874 bool min)
1875{
1876 struct listnode *node;
1877 struct audio_usecase *usecase;
1878 bool switch_usecases = false;
1879 bool reconfig = false;
1880
1881 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
1882 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
1883 return -1;
1884
1885 /* set if the valid usecase do not already exist */
1886 list_for_each(node, &adev->usecase_list) {
1887 usecase = node_to_item(node, struct audio_usecase, list);
1888 if (usecase->type == PCM_PLAYBACK &&
1889 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
1890 switch (usecase->id) {
1891 case USECASE_AUDIO_PLAYBACK_MMAP:
1892 case USECASE_AUDIO_PLAYBACK_ULL:
1893 // cannot reconfig while mmap/ull is present.
1894 return -1;
1895 default:
1896 switch_usecases = true;
1897 break;
1898 }
1899 }
1900 if (switch_usecases)
1901 break;
1902 }
1903 /*
1904 * client can try to set service interval in start_output_stream
1905 * to min or to 0 (i.e reset) in stop_output_stream .
1906 */
1907 unsigned long service_interval =
1908 audio_extn_usb_find_service_interval(min, true /*playback*/);
1909 int ret = platform_set_usb_service_interval(adev->platform,
1910 true /*playback*/,
1911 service_interval,
1912 &reconfig);
1913 /* no change or not supported or no active usecases */
1914 if (ret || !reconfig || !switch_usecases)
1915 return -1;
1916 return 0;
1917#undef VALID_USECASE
1918}
1919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001920static int stop_output_stream(struct stream_out *out)
1921{
1922 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001923 struct audio_usecase *uc_info;
1924 struct audio_device *adev = out->dev;
1925
Eric Laurent994a6932013-07-17 11:51:42 -07001926 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001927 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928 uc_info = get_usecase_from_list(adev, out->usecase);
1929 if (uc_info == NULL) {
1930 ALOGE("%s: Could not find the usecase (%d) in the list",
1931 __func__, out->usecase);
1932 return -EINVAL;
1933 }
1934
Haynes Mathew George41f86652014-06-17 14:22:15 -07001935 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1936 if (adev->visualizer_stop_output != NULL)
1937 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1938 if (adev->offload_effects_stop_output != NULL)
1939 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001940 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1941 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1942 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001943 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001944
Eric Laurent150dbfe2013-02-27 14:31:02 -08001945 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001946 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001947
1948 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001949 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001951 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001952
Eric Laurent0499d4f2014-08-25 22:39:29 -05001953 audio_extn_extspk_update(adev->extspk);
1954
Eric Laurent07eeafd2013-10-06 12:52:49 -07001955 /* Must be called after removing the usecase from list */
1956 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1957 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001958 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1959 struct listnode *node;
1960 struct audio_usecase *usecase;
1961 list_for_each(node, &adev->usecase_list) {
1962 usecase = node_to_item(node, struct audio_usecase, list);
1963 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1964 select_devices(adev, usecase->id);
1965 }
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001966 } else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
1967 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
1968 if (ret == 0) {
1969 /* default service interval was successfully updated,
1970 reopen USB backend with new service interval */
1971 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
1972 }
1973 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001974 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001975
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001976 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07001977 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978 return ret;
1979}
1980
1981int start_output_stream(struct stream_out *out)
1982{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984 struct audio_usecase *uc_info;
1985 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001986 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987
Eric Laurent994a6932013-07-17 11:51:42 -07001988 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001989 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001990
1991 if (out->card_status == CARD_STATUS_OFFLINE ||
1992 adev->card_status == CARD_STATUS_OFFLINE) {
1993 ALOGW("out->card_status or adev->card_status offline, try again");
1994 ret = -EAGAIN;
1995 goto error_config;
1996 }
1997
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001998 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
1999 if (!audio_extn_a2dp_is_ready()) {
2000 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2001 a2dp_combo = true;
2002 } else {
2003 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2004 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2005 ret = -EAGAIN;
2006 goto error_config;
2007 }
2008 }
2009 }
2010 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002011 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002012 if (out->pcm_device_id < 0) {
2013 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2014 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002015 ret = -EINVAL;
2016 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017 }
2018
2019 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2020 uc_info->id = out->usecase;
2021 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002022 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002023 uc_info->devices = out->devices;
2024 uc_info->in_snd_device = SND_DEVICE_NONE;
2025 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002026
Eric Laurent07eeafd2013-10-06 12:52:49 -07002027 /* This must be called before adding this usecase to the list */
2028 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2029 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002030 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2031 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2032 /* USB backend is not reopened immediately.
2033 This is eventually done as part of select_devices */
2034 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002035
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002036 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037
Wei Wangf4837d52017-11-21 14:51:20 -08002038 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002039 audio_extn_perf_lock_acquire();
2040
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002041 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2042 (!audio_extn_a2dp_is_ready())) {
2043 if (!a2dp_combo) {
2044 check_a2dp_restore_l(adev, out, false);
2045 } else {
2046 audio_devices_t dev = out->devices;
2047 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2048 select_devices(adev, out->usecase);
2049 out->devices = dev;
2050 }
2051 } else {
2052 select_devices(adev, out->usecase);
2053 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002054
Eric Laurent0499d4f2014-08-25 22:39:29 -05002055 audio_extn_extspk_update(adev->extspk);
2056
Andy Hung31aca912014-03-20 17:14:59 -07002057 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002058 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002059 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2060 out->pcm = NULL;
2061 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2062 COMPRESS_IN, &out->compr_config);
2063 if (out->compr && !is_compress_ready(out->compr)) {
2064 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2065 compress_close(out->compr);
2066 out->compr = NULL;
2067 ret = -EIO;
2068 goto error_open;
2069 }
2070 if (out->offload_callback)
2071 compress_nonblock(out->compr, out->non_blocking);
2072
2073 if (adev->visualizer_start_output != NULL)
2074 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2075 if (adev->offload_effects_start_output != NULL)
2076 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2077 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002078 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002079 ALOGE("%s: pcm stream not ready", __func__);
2080 goto error_open;
2081 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002082 ret = pcm_start(out->pcm);
2083 if (ret < 0) {
2084 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2085 goto error_open;
2086 }
2087 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002088 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002089 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002090
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002091 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2092 flags |= PCM_MMAP | PCM_NOIRQ;
2093 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002094 } else if (out->realtime) {
2095 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002096 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002097
2098 while (1) {
2099 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2100 flags, &out->config);
2101 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2102 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2103 if (out->pcm != NULL) {
2104 pcm_close(out->pcm);
2105 out->pcm = NULL;
2106 }
2107 if (pcm_open_retry_count-- == 0) {
2108 ret = -EIO;
2109 goto error_open;
2110 }
2111 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2112 continue;
2113 }
2114 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002115 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002116 ALOGV("%s: pcm_prepare", __func__);
2117 if (pcm_is_ready(out->pcm)) {
2118 ret = pcm_prepare(out->pcm);
2119 if (ret < 0) {
2120 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2121 pcm_close(out->pcm);
2122 out->pcm = NULL;
2123 goto error_open;
2124 }
2125 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002126 if (out->realtime) {
2127 ret = pcm_start(out->pcm);
2128 if (ret < 0) {
2129 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2130 pcm_close(out->pcm);
2131 out->pcm = NULL;
2132 goto error_open;
2133 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002134 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002135 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002136 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002137 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002138 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002139 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002140
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002141 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2142 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2143 audio_low_latency_hint_start();
2144 }
2145
vivek mehtae59cfb22017-06-16 15:57:11 -07002146 // consider a scenario where on pause lower layers are tear down.
2147 // so on resume, swap mixer control need to be sent only when
2148 // backend is active, hence rather than sending from enable device
2149 // sending it from start of streamtream
2150
2151 platform_set_swap_channels(adev, true);
2152
Eric Laurent994a6932013-07-17 11:51:42 -07002153 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002154 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002155error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002156 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002157 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002158 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002159error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002160 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161}
2162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163static int check_input_parameters(uint32_t sample_rate,
2164 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002165 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002167 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2168 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002169 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2170 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002171 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2172 return -EINVAL;
2173 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174
Eric Laurent74b55762017-07-09 17:04:53 -07002175 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2176 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002177 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002178 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002179 return -EINVAL;
2180 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002181
2182 switch (sample_rate) {
2183 case 8000:
2184 case 11025:
2185 case 12000:
2186 case 16000:
2187 case 22050:
2188 case 24000:
2189 case 32000:
2190 case 44100:
2191 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002192 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002193 break;
2194 default:
vivek mehtadae44712015-07-27 14:13:18 -07002195 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196 return -EINVAL;
2197 }
2198
2199 return 0;
2200}
2201
Kevin Rocarda325aa22018-04-03 09:15:52 -07002202/** Add a value in a list if not already present.
2203 * @return true if value was successfully inserted or already present,
2204 * false if the list is full and does not contain the value.
2205 */
2206static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2207 for (size_t i = 0; i < list_length; i++) {
2208 if (list[i] == value) return true; // value is already present
2209 if (list[i] == 0) { // no values in this slot
2210 list[i] = value;
2211 return true; // value inserted
2212 }
2213 }
2214 return false; // could not insert value
2215}
2216
2217/** Add channel_mask in supported_channel_masks if not already present.
2218 * @return true if channel_mask was successfully inserted or already present,
2219 * false if supported_channel_masks is full and does not contain channel_mask.
2220 */
2221static void register_channel_mask(audio_channel_mask_t channel_mask,
2222 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2223 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2224 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2225}
2226
2227/** Add format in supported_formats if not already present.
2228 * @return true if format was successfully inserted or already present,
2229 * false if supported_formats is full and does not contain format.
2230 */
2231static void register_format(audio_format_t format,
2232 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2233 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2234 "%s: stream can not declare supporting its format %x", __func__, format);
2235}
2236/** Add sample_rate in supported_sample_rates if not already present.
2237 * @return true if sample_rate was successfully inserted or already present,
2238 * false if supported_sample_rates is full and does not contain sample_rate.
2239 */
2240static void register_sample_rate(uint32_t sample_rate,
2241 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2242 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2243 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2244}
2245
vivek mehtaa68fea62017-06-08 19:04:02 -07002246static size_t get_stream_buffer_size(size_t duration_ms,
2247 uint32_t sample_rate,
2248 audio_format_t format,
2249 int channel_count,
2250 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002251{
2252 size_t size = 0;
2253
vivek mehtaa68fea62017-06-08 19:04:02 -07002254 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002255 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002256 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002257
2258 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259
Glenn Kasten4f993392014-05-14 07:30:48 -07002260 /* make sure the size is multiple of 32 bytes
2261 * At 48 kHz mono 16-bit PCM:
2262 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2263 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2264 */
2265 size += 0x1f;
2266 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002267
2268 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002269}
2270
2271static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2272{
2273 struct stream_out *out = (struct stream_out *)stream;
2274
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002275 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002276}
2277
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002278static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279{
2280 return -ENOSYS;
2281}
2282
2283static size_t out_get_buffer_size(const struct audio_stream *stream)
2284{
2285 struct stream_out *out = (struct stream_out *)stream;
2286
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002287 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2288 return out->compr_config.fragment_size;
2289 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002290 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002291 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002292}
2293
2294static uint32_t out_get_channels(const struct audio_stream *stream)
2295{
2296 struct stream_out *out = (struct stream_out *)stream;
2297
2298 return out->channel_mask;
2299}
2300
2301static audio_format_t out_get_format(const struct audio_stream *stream)
2302{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002303 struct stream_out *out = (struct stream_out *)stream;
2304
2305 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002306}
2307
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002308static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002309{
2310 return -ENOSYS;
2311}
2312
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002313/* must be called with out->lock locked */
2314static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002315{
2316 struct stream_out *out = (struct stream_out *)stream;
2317 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002318 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002321 if (adev->adm_deregister_stream)
2322 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002323 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002324 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002325 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2326 if (out->pcm) {
2327 pcm_close(out->pcm);
2328 out->pcm = NULL;
2329 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002330 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002331 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002332 out->playback_started = false;
2333 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002334 } else {
2335 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002336 out->gapless_mdata.encoder_delay = 0;
2337 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002338 if (out->compr != NULL) {
2339 compress_close(out->compr);
2340 out->compr = NULL;
2341 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002342 }
Phil Burkbc991042017-02-24 08:06:44 -08002343 if (do_stop) {
2344 stop_output_stream(out);
2345 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002346 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002348 return 0;
2349}
2350
2351static int out_standby(struct audio_stream *stream)
2352{
2353 struct stream_out *out = (struct stream_out *)stream;
2354
2355 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2356 out->usecase, use_case_table[out->usecase]);
2357
2358 lock_output_stream(out);
2359 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002361 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362 return 0;
2363}
2364
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002365static int out_on_error(struct audio_stream *stream)
2366{
2367 struct stream_out *out = (struct stream_out *)stream;
2368 struct audio_device *adev = out->dev;
2369 bool do_standby = false;
2370
2371 lock_output_stream(out);
2372 if (!out->standby) {
2373 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2374 stop_compressed_output_l(out);
2375 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2376 } else
2377 do_standby = true;
2378 }
2379 pthread_mutex_unlock(&out->lock);
2380
2381 if (do_standby)
2382 return out_standby(&out->stream.common);
2383
2384 return 0;
2385}
2386
Andy Hung7401c7c2016-09-21 12:41:21 -07002387static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388{
Andy Hung7401c7c2016-09-21 12:41:21 -07002389 struct stream_out *out = (struct stream_out *)stream;
2390
2391 // We try to get the lock for consistency,
2392 // but it isn't necessary for these variables.
2393 // If we're not in standby, we may be blocked on a write.
2394 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2395 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2396 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2397
2398 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002399 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002400 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002401
2402 // dump error info
2403 (void)error_log_dump(
2404 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002405
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002406 return 0;
2407}
2408
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002409static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2410{
2411 int ret = 0;
2412 char value[32];
2413 struct compr_gapless_mdata tmp_mdata;
2414
2415 if (!out || !parms) {
2416 return -EINVAL;
2417 }
2418
2419 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2420 if (ret >= 0) {
2421 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2422 } else {
2423 return -EINVAL;
2424 }
2425
2426 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2427 if (ret >= 0) {
2428 tmp_mdata.encoder_padding = atoi(value);
2429 } else {
2430 return -EINVAL;
2431 }
2432
2433 out->gapless_mdata = tmp_mdata;
2434 out->send_new_metadata = 1;
2435 ALOGV("%s new encoder delay %u and padding %u", __func__,
2436 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2437
2438 return 0;
2439}
2440
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002441static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2442{
2443 return out == adev->primary_output || out == adev->voice_tx_output;
2444}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002445
Kevin Rocard1e02c882017-08-09 15:26:07 -07002446static int get_alive_usb_card(struct str_parms* parms) {
2447 int card;
2448 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2449 !audio_extn_usb_alive(card)) {
2450 return card;
2451 }
2452 return -ENODEV;
2453}
2454
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2456{
2457 struct stream_out *out = (struct stream_out *)stream;
2458 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002459 struct audio_usecase *usecase;
2460 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461 struct str_parms *parms;
2462 char value[32];
2463 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002464 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002465 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002466 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002467
Eric Laurent2e140aa2016-06-30 17:14:46 -07002468 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002469 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470 parms = str_parms_create_str(kvpairs);
2471 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2472 if (ret >= 0) {
2473 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002474
Eric Laurenta1478072015-09-21 17:21:52 -07002475 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002476
2477 // The usb driver needs to be closed after usb device disconnection
2478 // otherwise audio is no longer played on the new usb devices.
2479 // By forcing the stream in standby, the usb stack refcount drops to 0
2480 // and the driver is closed.
2481 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2482 audio_is_usb_out_device(out->devices)) {
2483 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2484 out_standby_l(&out->stream.common);
2485 }
2486
Eric Laurent150dbfe2013-02-27 14:31:02 -08002487 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002489 /*
2490 * When HDMI cable is unplugged the music playback is paused and
2491 * the policy manager sends routing=0. But the audioflinger
2492 * continues to write data until standby time (3sec).
2493 * As the HDMI core is turned off, the write gets blocked.
2494 * Avoid this by routing audio to speaker until standby.
2495 */
2496 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2497 val == AUDIO_DEVICE_NONE) {
2498 val = AUDIO_DEVICE_OUT_SPEAKER;
2499 }
2500
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002501 /*
2502 * When A2DP is disconnected the
2503 * music playback is paused and the policy manager sends routing=0
2504 * But the audioflingercontinues to write data until standby time
2505 * (3sec). As BT is turned off, the write gets blocked.
2506 * Avoid this by routing audio to speaker until standby.
2507 */
2508 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2509 (val == AUDIO_DEVICE_NONE) &&
2510 !audio_extn_a2dp_is_ready()) {
2511 val = AUDIO_DEVICE_OUT_SPEAKER;
2512 }
2513
2514 /* To avoid a2dp to sco overlapping / BT device improper state
2515 * check with BT lib about a2dp streaming support before routing
2516 */
2517 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2518 if (!audio_extn_a2dp_is_ready()) {
2519 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2520 //combo usecase just by pass a2dp
2521 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2522 bypass_a2dp = true;
2523 } else {
2524 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2525 /* update device to a2dp and don't route as BT returned error
2526 * However it is still possible a2dp routing called because
2527 * of current active device disconnection (like wired headset)
2528 */
2529 out->devices = val;
2530 pthread_mutex_unlock(&out->lock);
2531 pthread_mutex_unlock(&adev->lock);
2532 status = -ENOSYS;
2533 goto routing_fail;
2534 }
2535 }
2536 }
2537
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002538 audio_devices_t new_dev = val;
2539
2540 // Workaround: If routing to an non existing usb device, fail gracefully
2541 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002542 int card;
2543 if (audio_is_usb_out_device(new_dev) &&
2544 (card = get_alive_usb_card(parms)) >= 0) {
2545
2546 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002547 pthread_mutex_unlock(&adev->lock);
2548 pthread_mutex_unlock(&out->lock);
2549 status = -ENOSYS;
2550 goto routing_fail;
2551 }
2552
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002553 /*
2554 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002555 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002556 * the select_devices(). But how do we undo this?
2557 *
2558 * For example, music playback is active on headset (deep-buffer usecase)
2559 * and if we go to ringtones and select a ringtone, low-latency usecase
2560 * will be started on headset+speaker. As we can't enable headset+speaker
2561 * and headset devices at the same time, select_devices() switches the music
2562 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2563 * So when the ringtone playback is completed, how do we undo the same?
2564 *
2565 * We are relying on the out_set_parameters() call on deep-buffer output,
2566 * once the ringtone playback is ended.
2567 * NOTE: We should not check if the current devices are same as new devices.
2568 * Because select_devices() must be called to switch back the music
2569 * playback to headset.
2570 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002571 if (new_dev != AUDIO_DEVICE_NONE) {
2572 bool same_dev = out->devices == new_dev;
2573 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002574
Eric Laurenta7657192014-10-09 21:09:33 -07002575 if (output_drives_call(adev, out)) {
2576 if (!voice_is_in_call(adev)) {
2577 if (adev->mode == AUDIO_MODE_IN_CALL) {
2578 adev->current_call_output = out;
2579 ret = voice_start_call(adev);
2580 }
2581 } else {
2582 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002583 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002584 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002585 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002586
2587 if (!out->standby) {
2588 if (!same_dev) {
2589 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002590 // inform adm before actual routing to prevent glitches.
2591 if (adev->adm_on_routing_change) {
2592 adev->adm_on_routing_change(adev->adm_data,
2593 out->handle);
2594 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002595 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002596 if (!bypass_a2dp) {
2597 select_devices(adev, out->usecase);
2598 } else {
2599 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2600 select_devices(adev, out->usecase);
2601 out->devices = new_dev;
2602 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002603 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002604
2605 // on device switch force swap, lower functions will make sure
2606 // to check if swap is allowed or not.
2607
2608 if (!same_dev)
2609 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002610
2611 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2612 out->a2dp_compress_mute &&
2613 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2614 pthread_mutex_lock(&out->compr_mute_lock);
2615 out->a2dp_compress_mute = false;
2616 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2617 pthread_mutex_unlock(&out->compr_mute_lock);
2618 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002619 }
2620
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002621 }
2622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002623 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002624 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002625
2626 /*handles device and call state changes*/
2627 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002629 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002630
2631 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2632 parse_compress_metadata(out, parms);
2633 }
2634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002636 ALOGV("%s: exit: code(%d)", __func__, status);
2637 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002638}
2639
Haynes Mathew George569b7482017-05-08 14:44:27 -07002640static bool stream_get_parameter_channels(struct str_parms *query,
2641 struct str_parms *reply,
2642 audio_channel_mask_t *supported_channel_masks) {
2643 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002646 size_t i, j;
2647
2648 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2649 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650 value[0] = '\0';
2651 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002652 while (supported_channel_masks[i] != 0) {
2653 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2654 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 if (!first) {
2656 strcat(value, "|");
2657 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002658 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659 first = false;
2660 break;
2661 }
2662 }
2663 i++;
2664 }
2665 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002666 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002667 return ret >= 0;
2668}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002669
Haynes Mathew George569b7482017-05-08 14:44:27 -07002670static bool stream_get_parameter_formats(struct str_parms *query,
2671 struct str_parms *reply,
2672 audio_format_t *supported_formats) {
2673 int ret = -1;
2674 char value[256];
2675 int i;
2676
2677 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2678 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002679 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002680 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002681 case AUDIO_FORMAT_PCM_16_BIT:
2682 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2683 break;
2684 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2685 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2686 break;
2687 case AUDIO_FORMAT_PCM_32_BIT:
2688 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2689 break;
2690 default:
2691 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002692 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002693 break;
2694 }
2695 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002696 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002697 return ret >= 0;
2698}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002699
Haynes Mathew George569b7482017-05-08 14:44:27 -07002700static bool stream_get_parameter_rates(struct str_parms *query,
2701 struct str_parms *reply,
2702 uint32_t *supported_sample_rates) {
2703
2704 int i;
2705 char value[256];
2706 int ret = -1;
2707 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2708 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002709 value[0] = '\0';
2710 i=0;
2711 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002712 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002713 int avail = sizeof(value) - cursor;
2714 ret = snprintf(value + cursor, avail, "%s%d",
2715 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002716 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002717 if (ret < 0 || ret >= avail) {
2718 // if cursor is at the last element of the array
2719 // overwrite with \0 is duplicate work as
2720 // snprintf already put a \0 in place.
2721 // else
2722 // we had space to write the '|' at value[cursor]
2723 // (which will be overwritten) or no space to fill
2724 // the first element (=> cursor == 0)
2725 value[cursor] = '\0';
2726 break;
2727 }
2728 cursor += ret;
2729 ++i;
2730 }
2731 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2732 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002733 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002734 return ret >= 0;
2735}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002736
Haynes Mathew George569b7482017-05-08 14:44:27 -07002737static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2738{
2739 struct stream_out *out = (struct stream_out *)stream;
2740 struct str_parms *query = str_parms_create_str(keys);
2741 char *str;
2742 struct str_parms *reply = str_parms_create();
2743 bool replied = false;
2744 ALOGV("%s: enter: keys - %s", __func__, keys);
2745
2746 replied |= stream_get_parameter_channels(query, reply,
2747 &out->supported_channel_masks[0]);
2748 replied |= stream_get_parameter_formats(query, reply,
2749 &out->supported_formats[0]);
2750 replied |= stream_get_parameter_rates(query, reply,
2751 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002752 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002753 str = str_parms_to_str(reply);
2754 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002755 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002756 }
2757 str_parms_destroy(query);
2758 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002759 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760 return str;
2761}
2762
2763static uint32_t out_get_latency(const struct audio_stream_out *stream)
2764{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002765 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002767 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002768
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002769 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2770 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002771 else if ((out->realtime) ||
2772 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002773 // since the buffer won't be filled up faster than realtime,
2774 // return a smaller number
2775 period_ms = (out->af_period_multiplier * out->config.period_size *
2776 1000) / (out->config.rate);
2777 hw_delay = platform_render_latency(out->usecase)/1000;
2778 return period_ms + hw_delay;
2779 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002780
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002781 latency = (out->config.period_count * out->config.period_size * 1000) /
2782 (out->config.rate);
2783
2784 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2785 latency += audio_extn_a2dp_get_encoder_latency();
2786
2787 return latency;
2788}
2789
2790static int set_compr_volume(struct audio_stream_out *stream, float left,
2791 float right)
2792{
2793 struct stream_out *out = (struct stream_out *)stream;
2794 int volume[2];
2795 char mixer_ctl_name[128];
2796 struct audio_device *adev = out->dev;
2797 struct mixer_ctl *ctl;
2798 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2799 PCM_PLAYBACK);
2800
2801 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2802 "Compress Playback %d Volume", pcm_device_id);
2803 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2804 if (!ctl) {
2805 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2806 __func__, mixer_ctl_name);
2807 return -EINVAL;
2808 }
2809 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2810 __func__, mixer_ctl_name, left, right);
2811 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2812 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2813 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2814
2815 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002816}
2817
2818static int out_set_volume(struct audio_stream_out *stream, float left,
2819 float right)
2820{
Eric Laurenta9024de2013-04-04 09:19:12 -07002821 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002822 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002823
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002824 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002825 /* only take left channel into account: the API is for stereo anyway */
2826 out->muted = (left == 0.0f);
2827 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002828 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002829 pthread_mutex_lock(&out->compr_mute_lock);
2830 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2831 if (!out->a2dp_compress_mute)
2832 ret = set_compr_volume(stream, left, right);
2833 out->volume_l = left;
2834 out->volume_r = right;
2835 pthread_mutex_unlock(&out->compr_mute_lock);
2836 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002837 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002838 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2839 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2840 if (!out->standby) {
2841 // if in standby, cached volume will be sent after stream is opened
2842 audio_extn_utils_send_app_type_gain(out->dev,
2843 out->app_type_cfg.app_type,
2844 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002845 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002846 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002847 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849 return -ENOSYS;
2850}
2851
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002852// note: this call is safe only if the stream_cb is
2853// removed first in close_output_stream (as is done now).
2854static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2855{
2856 if (!stream || !parms)
2857 return;
2858
2859 struct stream_out *out = (struct stream_out *)stream;
2860 struct audio_device *adev = out->dev;
2861
2862 card_status_t status;
2863 int card;
2864 if (parse_snd_card_status(parms, &card, &status) < 0)
2865 return;
2866
2867 pthread_mutex_lock(&adev->lock);
2868 bool valid_cb = (card == adev->snd_card);
2869 pthread_mutex_unlock(&adev->lock);
2870
2871 if (!valid_cb)
2872 return;
2873
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002874 lock_output_stream(out);
2875 if (out->card_status != status)
2876 out->card_status = status;
2877 pthread_mutex_unlock(&out->lock);
2878
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002879 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2880 use_case_table[out->usecase],
2881 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2882
2883 if (status == CARD_STATUS_OFFLINE)
2884 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002885
2886 return;
2887}
2888
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002889#ifdef NO_AUDIO_OUT
2890static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002891 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002892{
2893 struct stream_out *out = (struct stream_out *)stream;
2894
2895 /* No Output device supported other than BT for playback.
2896 * Sleep for the amount of buffer duration
2897 */
Eric Laurenta1478072015-09-21 17:21:52 -07002898 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002899 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2900 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002901 out_get_sample_rate(&out->stream.common));
2902 pthread_mutex_unlock(&out->lock);
2903 return bytes;
2904}
2905#endif
2906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002907static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2908 size_t bytes)
2909{
2910 struct stream_out *out = (struct stream_out *)stream;
2911 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002912 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002913 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002914
Eric Laurenta1478072015-09-21 17:21:52 -07002915 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002916 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002917 const size_t frame_size = audio_stream_out_frame_size(stream);
2918 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002919
Eric Laurent0e46adf2016-12-16 12:49:24 -08002920 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2921 error_code = ERROR_CODE_WRITE;
2922 goto exit;
2923 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002924
2925 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2926 (audio_extn_a2dp_is_suspended())) {
2927 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2928 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2929 ret = -EIO;
2930 goto exit;
2931 }
2932 }
2933 }
2934
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002935 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002936 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002937 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002939
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002940 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002941 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002942 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002943 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944 goto exit;
2945 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002946
vivek mehta40125092017-08-21 18:48:51 -07002947 // after standby always force set last known cal step
2948 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2949 ALOGD("%s: retry previous failed cal level set", __func__);
2950 send_gain_dep_calibration_l();
2951 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002952 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002953
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002954 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002955 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002956 if (out->send_new_metadata) {
2957 ALOGVV("send new gapless metadata");
2958 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2959 out->send_new_metadata = 0;
2960 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002961 unsigned int avail;
2962 struct timespec tstamp;
2963 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2964 /* Do not limit write size if the available frames count is unknown */
2965 if (ret != 0) {
2966 avail = bytes;
2967 }
2968 if (avail == 0) {
2969 ret = 0;
2970 } else {
2971 if (avail > bytes) {
2972 avail = bytes;
2973 }
2974 ret = compress_write(out->compr, buffer, avail);
2975 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2976 __func__, avail, ret);
2977 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002978
Eric Laurent6e895242013-09-05 16:10:57 -07002979 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002980 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2981 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002982 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002983 compress_start(out->compr);
2984 out->playback_started = 1;
2985 out->offload_state = OFFLOAD_STATE_PLAYING;
2986 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002987 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002988 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002989 } else {
2990 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002991 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002992 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002993 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002994 return ret;
2995 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002996 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002997 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002998 size_t bytes_to_write = bytes;
2999
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003000 if (out->muted)
3001 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003002 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003003 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003004 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3005 int16_t *src = (int16_t *)buffer;
3006 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003007
Eric Laurentad2dde92017-09-20 18:27:31 -07003008 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3009 out->format != AUDIO_FORMAT_PCM_16_BIT,
3010 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003011
Eric Laurentad2dde92017-09-20 18:27:31 -07003012 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3013 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3014 }
3015 bytes_to_write /= 2;
3016 }
3017 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3018
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003019 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003020 request_out_focus(out, ns);
3021
3022 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3023 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003024 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003025 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003026 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003027
Haynes Mathew George03c40102016-01-29 17:57:48 -08003028 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003029 } else {
3030 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003031 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032 }
3033
3034exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003035 // For PCM we always consume the buffer and return #bytes regardless of ret.
3036 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003037 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003038 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003039 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003040
Andy Hung7401c7c2016-09-21 12:41:21 -07003041 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003042 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003043 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3044 ALOGE_IF(out->pcm != NULL,
3045 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003046 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003047 // usleep not guaranteed for values over 1 second but we don't limit here.
3048 }
3049 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003050
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051 pthread_mutex_unlock(&out->lock);
3052
3053 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003054 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003055 if (sleeptime_us != 0)
3056 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057 }
3058 return bytes;
3059}
3060
3061static int out_get_render_position(const struct audio_stream_out *stream,
3062 uint32_t *dsp_frames)
3063{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003064 struct stream_out *out = (struct stream_out *)stream;
3065 *dsp_frames = 0;
3066 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003067 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003068 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003069 unsigned long frames = 0;
3070 // TODO: check return value
3071 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3072 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073 ALOGVV("%s rendered frames %d sample_rate %d",
3074 __func__, *dsp_frames, out->sample_rate);
3075 }
3076 pthread_mutex_unlock(&out->lock);
3077 return 0;
3078 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003079 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080}
3081
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003082static int out_add_audio_effect(const struct audio_stream *stream __unused,
3083 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084{
3085 return 0;
3086}
3087
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003088static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3089 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090{
3091 return 0;
3092}
3093
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003094static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3095 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003097 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098}
3099
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003100static int out_get_presentation_position(const struct audio_stream_out *stream,
3101 uint64_t *frames, struct timespec *timestamp)
3102{
3103 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003104 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003105 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003106
Eric Laurenta1478072015-09-21 17:21:52 -07003107 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003108
Eric Laurent949a0892013-09-20 09:20:13 -07003109 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3110 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003111 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003112 compress_get_tstamp(out->compr, &dsp_frames,
3113 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003114 // Adjustment accounts for A2DP encoder latency with offload usecases
3115 // Note: Encoder latency is returned in ms.
3116 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3117 unsigned long offset =
3118 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3119 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3120 }
Eric Laurent949a0892013-09-20 09:20:13 -07003121 ALOGVV("%s rendered frames %ld sample_rate %d",
3122 __func__, dsp_frames, out->sample_rate);
3123 *frames = dsp_frames;
3124 ret = 0;
3125 /* this is the best we can do */
3126 clock_gettime(CLOCK_MONOTONIC, timestamp);
3127 }
3128 } else {
3129 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003130 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003131 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3132 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003133 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003134 // This adjustment accounts for buffering after app processor.
3135 // It is based on estimated DSP latency per use case, rather than exact.
3136 signed_frames -=
3137 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3138
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003139 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3140 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3141 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3142 signed_frames -=
3143 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3144 }
3145
Eric Laurent949a0892013-09-20 09:20:13 -07003146 // It would be unusual for this value to be negative, but check just in case ...
3147 if (signed_frames >= 0) {
3148 *frames = signed_frames;
3149 ret = 0;
3150 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003151 }
3152 }
3153 }
3154
3155 pthread_mutex_unlock(&out->lock);
3156
3157 return ret;
3158}
3159
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003160static int out_set_callback(struct audio_stream_out *stream,
3161 stream_callback_t callback, void *cookie)
3162{
3163 struct stream_out *out = (struct stream_out *)stream;
3164
3165 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003166 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003167 out->offload_callback = callback;
3168 out->offload_cookie = cookie;
3169 pthread_mutex_unlock(&out->lock);
3170 return 0;
3171}
3172
3173static int out_pause(struct audio_stream_out* stream)
3174{
3175 struct stream_out *out = (struct stream_out *)stream;
3176 int status = -ENOSYS;
3177 ALOGV("%s", __func__);
3178 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003179 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003180 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3181 status = compress_pause(out->compr);
3182 out->offload_state = OFFLOAD_STATE_PAUSED;
3183 }
3184 pthread_mutex_unlock(&out->lock);
3185 }
3186 return status;
3187}
3188
3189static int out_resume(struct audio_stream_out* stream)
3190{
3191 struct stream_out *out = (struct stream_out *)stream;
3192 int status = -ENOSYS;
3193 ALOGV("%s", __func__);
3194 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3195 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003196 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003197 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3198 status = compress_resume(out->compr);
3199 out->offload_state = OFFLOAD_STATE_PLAYING;
3200 }
3201 pthread_mutex_unlock(&out->lock);
3202 }
3203 return status;
3204}
3205
3206static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3207{
3208 struct stream_out *out = (struct stream_out *)stream;
3209 int status = -ENOSYS;
3210 ALOGV("%s", __func__);
3211 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003212 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003213 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3214 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3215 else
3216 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3217 pthread_mutex_unlock(&out->lock);
3218 }
3219 return status;
3220}
3221
3222static int out_flush(struct audio_stream_out* stream)
3223{
3224 struct stream_out *out = (struct stream_out *)stream;
3225 ALOGV("%s", __func__);
3226 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003227 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003228 stop_compressed_output_l(out);
3229 pthread_mutex_unlock(&out->lock);
3230 return 0;
3231 }
3232 return -ENOSYS;
3233}
3234
Eric Laurent0e46adf2016-12-16 12:49:24 -08003235static int out_stop(const struct audio_stream_out* stream)
3236{
3237 struct stream_out *out = (struct stream_out *)stream;
3238 struct audio_device *adev = out->dev;
3239 int ret = -ENOSYS;
3240
3241 ALOGV("%s", __func__);
3242 pthread_mutex_lock(&adev->lock);
3243 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3244 out->playback_started && out->pcm != NULL) {
3245 pcm_stop(out->pcm);
3246 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003247 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003248 }
3249 pthread_mutex_unlock(&adev->lock);
3250 return ret;
3251}
3252
3253static int out_start(const struct audio_stream_out* stream)
3254{
3255 struct stream_out *out = (struct stream_out *)stream;
3256 struct audio_device *adev = out->dev;
3257 int ret = -ENOSYS;
3258
3259 ALOGV("%s", __func__);
3260 pthread_mutex_lock(&adev->lock);
3261 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3262 !out->playback_started && out->pcm != NULL) {
3263 ret = start_output_stream(out);
3264 if (ret == 0) {
3265 out->playback_started = true;
3266 }
3267 }
3268 pthread_mutex_unlock(&adev->lock);
3269 return ret;
3270}
3271
Phil Burkbc991042017-02-24 08:06:44 -08003272/*
3273 * Modify config->period_count based on min_size_frames
3274 */
3275static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3276{
3277 int periodCountRequested = (min_size_frames + config->period_size - 1)
3278 / config->period_size;
3279 int periodCount = MMAP_PERIOD_COUNT_MIN;
3280
3281 ALOGV("%s original config.period_size = %d config.period_count = %d",
3282 __func__, config->period_size, config->period_count);
3283
3284 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3285 periodCount *= 2;
3286 }
3287 config->period_count = periodCount;
3288
3289 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3290}
3291
Eric Laurent0e46adf2016-12-16 12:49:24 -08003292static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3293 int32_t min_size_frames,
3294 struct audio_mmap_buffer_info *info)
3295{
3296 struct stream_out *out = (struct stream_out *)stream;
3297 struct audio_device *adev = out->dev;
3298 int ret = 0;
3299 unsigned int offset1;
3300 unsigned int frames1;
3301 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003302 uint32_t mmap_size;
3303 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003304
3305 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003306 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003307 pthread_mutex_lock(&adev->lock);
3308
3309 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003310 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003311 ret = -EINVAL;
3312 goto exit;
3313 }
3314 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003315 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003316 ret = -ENOSYS;
3317 goto exit;
3318 }
3319 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3320 if (out->pcm_device_id < 0) {
3321 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3322 __func__, out->pcm_device_id, out->usecase);
3323 ret = -EINVAL;
3324 goto exit;
3325 }
Phil Burkbc991042017-02-24 08:06:44 -08003326
3327 adjust_mmap_period_count(&out->config, min_size_frames);
3328
Eric Laurent0e46adf2016-12-16 12:49:24 -08003329 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3330 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3331 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3332 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3333 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3334 step = "open";
3335 ret = -ENODEV;
3336 goto exit;
3337 }
3338 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3339 if (ret < 0) {
3340 step = "begin";
3341 goto exit;
3342 }
3343 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003344 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003345 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003346 ret = platform_get_mmap_data_fd(adev->platform,
3347 out->pcm_device_id, 0 /*playback*/,
3348 &info->shared_memory_fd,
3349 &mmap_size);
3350 if (ret < 0) {
3351 // Fall back to non exclusive mode
3352 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3353 } else {
3354 if (mmap_size < buffer_size) {
3355 step = "mmap";
3356 goto exit;
3357 }
3358 // FIXME: indicate exclusive mode support by returning a negative buffer size
3359 info->buffer_size_frames *= -1;
3360 }
3361 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003362
3363 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3364 if (ret < 0) {
3365 step = "commit";
3366 goto exit;
3367 }
Phil Burkbc991042017-02-24 08:06:44 -08003368
3369 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003370 ret = 0;
3371
3372 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3373 __func__, info->shared_memory_address, info->buffer_size_frames);
3374
3375exit:
3376 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003377 if (out->pcm == NULL) {
3378 ALOGE("%s: %s - %d", __func__, step, ret);
3379 } else {
3380 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003381 pcm_close(out->pcm);
3382 out->pcm = NULL;
3383 }
3384 }
3385 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003386 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003387 return ret;
3388}
3389
3390static int out_get_mmap_position(const struct audio_stream_out *stream,
3391 struct audio_mmap_position *position)
3392{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003393 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003394 struct stream_out *out = (struct stream_out *)stream;
3395 ALOGVV("%s", __func__);
3396 if (position == NULL) {
3397 return -EINVAL;
3398 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003399 lock_output_stream(out);
3400 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3401 out->pcm == NULL) {
3402 ret = -ENOSYS;
3403 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003404 }
3405
3406 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003407 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003408 if (ret < 0) {
3409 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003410 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003411 }
Andy Hungfc044e12017-03-20 09:24:22 -07003412 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003413exit:
3414 pthread_mutex_unlock(&out->lock);
3415 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003416}
3417
3418
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419/** audio_stream_in implementation **/
3420static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3421{
3422 struct stream_in *in = (struct stream_in *)stream;
3423
3424 return in->config.rate;
3425}
3426
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003427static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428{
3429 return -ENOSYS;
3430}
3431
3432static size_t in_get_buffer_size(const struct audio_stream *stream)
3433{
3434 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003435 return in->config.period_size * in->af_period_multiplier *
3436 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003437}
3438
3439static uint32_t in_get_channels(const struct audio_stream *stream)
3440{
3441 struct stream_in *in = (struct stream_in *)stream;
3442
3443 return in->channel_mask;
3444}
3445
vivek mehta4ed66e62016-04-15 23:33:34 -07003446static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447{
vivek mehta4ed66e62016-04-15 23:33:34 -07003448 struct stream_in *in = (struct stream_in *)stream;
3449 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450}
3451
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003452static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453{
3454 return -ENOSYS;
3455}
3456
3457static int in_standby(struct audio_stream *stream)
3458{
3459 struct stream_in *in = (struct stream_in *)stream;
3460 struct audio_device *adev = in->dev;
3461 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003462 bool do_stop = true;
3463
Eric Laurent994a6932013-07-17 11:51:42 -07003464 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003465
3466 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003467
3468 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003469 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003470 audio_extn_sound_trigger_stop_lab(in);
3471 in->standby = true;
3472 }
3473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003474 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003475 if (adev->adm_deregister_stream)
3476 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3477
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003478 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003480 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003481 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003482 in->capture_started = false;
3483 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003484 if (in->pcm) {
3485 pcm_close(in->pcm);
3486 in->pcm = NULL;
3487 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003488 adev->enable_voicerx = false;
3489 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003490 if (do_stop) {
3491 status = stop_input_stream(in);
3492 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003493 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494 }
3495 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003496 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497 return status;
3498}
3499
Andy Hungd13f0d32017-06-12 13:58:37 -07003500static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501{
Andy Hungd13f0d32017-06-12 13:58:37 -07003502 struct stream_in *in = (struct stream_in *)stream;
3503
3504 // We try to get the lock for consistency,
3505 // but it isn't necessary for these variables.
3506 // If we're not in standby, we may be blocked on a read.
3507 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3508 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3509 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3510 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3511
3512 if (locked) {
3513 pthread_mutex_unlock(&in->lock);
3514 }
3515
3516 // dump error info
3517 (void)error_log_dump(
3518 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519 return 0;
3520}
3521
3522static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3523{
3524 struct stream_in *in = (struct stream_in *)stream;
3525 struct audio_device *adev = in->dev;
3526 struct str_parms *parms;
3527 char *str;
3528 char value[32];
3529 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003530 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531
Eric Laurent994a6932013-07-17 11:51:42 -07003532 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533 parms = str_parms_create_str(kvpairs);
3534
3535 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3536
Eric Laurenta1478072015-09-21 17:21:52 -07003537 lock_input_stream(in);
3538
Eric Laurent150dbfe2013-02-27 14:31:02 -08003539 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540 if (ret >= 0) {
3541 val = atoi(value);
3542 /* no audio source uses val == 0 */
3543 if ((in->source != val) && (val != 0)) {
3544 in->source = val;
3545 }
3546 }
3547
3548 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550 if (ret >= 0) {
3551 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003552 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003553
3554 // Workaround: If routing to an non existing usb device, fail gracefully
3555 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003556 int card;
3557 if (audio_is_usb_in_device(val) &&
3558 (card = get_alive_usb_card(parms)) >= 0) {
3559
3560 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003561 status = -ENOSYS;
3562 } else {
3563
3564 in->device = val;
3565 /* If recording is in progress, change the tx device to new device */
3566 if (!in->standby) {
3567 ALOGV("update input routing change");
3568 // inform adm before actual routing to prevent glitches.
3569 if (adev->adm_on_routing_change) {
3570 adev->adm_on_routing_change(adev->adm_data,
3571 in->capture_handle);
3572 }
3573 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003574 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003575 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576 }
3577 }
3578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003580 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581
3582 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003583 ALOGV("%s: exit: status(%d)", __func__, status);
3584 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003585}
3586
Haynes Mathew George569b7482017-05-08 14:44:27 -07003587static char* in_get_parameters(const struct audio_stream *stream,
3588 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003590 struct stream_in *in = (struct stream_in *)stream;
3591 struct str_parms *query = str_parms_create_str(keys);
3592 char *str;
3593 struct str_parms *reply = str_parms_create();
3594 bool replied = false;
3595
3596 ALOGV("%s: enter: keys - %s", __func__, keys);
3597 replied |= stream_get_parameter_channels(query, reply,
3598 &in->supported_channel_masks[0]);
3599 replied |= stream_get_parameter_formats(query, reply,
3600 &in->supported_formats[0]);
3601 replied |= stream_get_parameter_rates(query, reply,
3602 &in->supported_sample_rates[0]);
3603 if (replied) {
3604 str = str_parms_to_str(reply);
3605 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003606 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003607 }
3608 str_parms_destroy(query);
3609 str_parms_destroy(reply);
3610 ALOGV("%s: exit: returns - %s", __func__, str);
3611 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612}
3613
Eric Laurent51f3c662018-04-10 18:21:34 -07003614static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615{
Eric Laurent51f3c662018-04-10 18:21:34 -07003616 struct stream_in *in = (struct stream_in *)stream;
3617 char mixer_ctl_name[128];
3618 struct mixer_ctl *ctl;
3619 int ctl_value;
3620
3621 ALOGV("%s: gain %f", __func__, gain);
3622
3623 if (stream == NULL)
3624 return -EINVAL;
3625
3626 /* in_set_gain() only used to silence MMAP capture for now */
3627 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3628 return -ENOSYS;
3629
3630 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3631
3632 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3633 if (!ctl) {
3634 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3635 __func__, mixer_ctl_name);
3636 return -ENOSYS;
3637 }
3638
3639 if (gain < RECORD_GAIN_MIN)
3640 gain = RECORD_GAIN_MIN;
3641 else if (gain > RECORD_GAIN_MAX)
3642 gain = RECORD_GAIN_MAX;
3643 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3644
3645 mixer_ctl_set_value(ctl, 0, ctl_value);
3646 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003647}
3648
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003649static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3650{
3651 if (!stream || !parms)
3652 return;
3653
3654 struct stream_in *in = (struct stream_in *)stream;
3655 struct audio_device *adev = in->dev;
3656
3657 card_status_t status;
3658 int card;
3659 if (parse_snd_card_status(parms, &card, &status) < 0)
3660 return;
3661
3662 pthread_mutex_lock(&adev->lock);
3663 bool valid_cb = (card == adev->snd_card);
3664 pthread_mutex_unlock(&adev->lock);
3665
3666 if (!valid_cb)
3667 return;
3668
3669 lock_input_stream(in);
3670 if (in->card_status != status)
3671 in->card_status = status;
3672 pthread_mutex_unlock(&in->lock);
3673
3674 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3675 use_case_table[in->usecase],
3676 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3677
3678 // a better solution would be to report error back to AF and let
3679 // it put the stream to standby
3680 if (status == CARD_STATUS_OFFLINE)
3681 in_standby(&in->stream.common);
3682
3683 return;
3684}
3685
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3687 size_t bytes)
3688{
3689 struct stream_in *in = (struct stream_in *)stream;
3690 struct audio_device *adev = in->dev;
3691 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003692 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003693 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694
Eric Laurenta1478072015-09-21 17:21:52 -07003695 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003696 const size_t frame_size = audio_stream_in_frame_size(stream);
3697 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003698
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003699 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003700 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003701 /* Read from sound trigger HAL */
3702 audio_extn_sound_trigger_read(in, buffer, bytes);
3703 pthread_mutex_unlock(&in->lock);
3704 return bytes;
3705 }
3706
Eric Laurent0e46adf2016-12-16 12:49:24 -08003707 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3708 ret = -ENOSYS;
3709 goto exit;
3710 }
3711
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003713 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003715 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717 goto exit;
3718 }
3719 in->standby = 0;
3720 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721
Andy Hungd13f0d32017-06-12 13:58:37 -07003722 // errors that occur here are read errors.
3723 error_code = ERROR_CODE_READ;
3724
Haynes Mathew George03c40102016-01-29 17:57:48 -08003725 //what's the duration requested by the client?
3726 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3727 in->config.rate;
3728 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003729
Haynes Mathew George03c40102016-01-29 17:57:48 -08003730 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003731 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003732 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003733 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003734 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003735 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003736 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003737 if (ret < 0) {
3738 ALOGE("Failed to read w/err %s", strerror(errno));
3739 ret = -errno;
3740 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003741 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3742 if (bytes % 4 == 0) {
3743 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3744 int_buf_stream = buffer;
3745 for (size_t itt=0; itt < bytes/4 ; itt++) {
3746 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003747 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003748 } else {
3749 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3750 ret = -EINVAL;
3751 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003752 }
3753 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003754 }
3755
Haynes Mathew George03c40102016-01-29 17:57:48 -08003756 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003758 /*
3759 * Instead of writing zeroes here, we could trust the hardware
3760 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003761 * 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 -08003762 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003763 if (ret == 0 && adev->mic_muted &&
3764 !voice_is_in_call_rec_stream(in) &&
3765 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003767 in->frames_muted += frames;
3768 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769
3770exit:
3771 pthread_mutex_unlock(&in->lock);
3772
3773 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003774 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003775 in_standby(&in->stream.common);
3776 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003777 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003778 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003779 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003780 }
3781 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003782 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783 }
3784 return bytes;
3785}
3786
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003787static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788{
3789 return 0;
3790}
3791
Andy Hung6ebe5962016-01-15 17:46:57 -08003792static int in_get_capture_position(const struct audio_stream_in *stream,
3793 int64_t *frames, int64_t *time)
3794{
3795 if (stream == NULL || frames == NULL || time == NULL) {
3796 return -EINVAL;
3797 }
3798 struct stream_in *in = (struct stream_in *)stream;
3799 int ret = -ENOSYS;
3800
3801 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003802 // note: ST sessions do not close the alsa pcm driver synchronously
3803 // on standby. Therefore, we may return an error even though the
3804 // pcm stream is still opened.
3805 if (in->standby) {
3806 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3807 "%s stream in standby but pcm not NULL for non ST session", __func__);
3808 goto exit;
3809 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003810 if (in->pcm) {
3811 struct timespec timestamp;
3812 unsigned int avail;
3813 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3814 *frames = in->frames_read + avail;
3815 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3816 ret = 0;
3817 }
3818 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003819exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003820 pthread_mutex_unlock(&in->lock);
3821 return ret;
3822}
3823
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003824static int add_remove_audio_effect(const struct audio_stream *stream,
3825 effect_handle_t effect,
3826 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003827{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003828 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003829 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003830 int status = 0;
3831 effect_descriptor_t desc;
3832
3833 status = (*effect)->get_descriptor(effect, &desc);
3834 if (status != 0)
3835 return status;
3836
Eric Laurenta1478072015-09-21 17:21:52 -07003837 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003838 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003839 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003840 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003841 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003842 in->enable_aec != enable &&
3843 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3844 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003845 if (!enable)
3846 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003847 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3848 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3849 adev->enable_voicerx = enable;
3850 struct audio_usecase *usecase;
3851 struct listnode *node;
3852 list_for_each(node, &adev->usecase_list) {
3853 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003854 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003855 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003856 }
3857 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003858 if (!in->standby)
3859 select_devices(in->dev, in->usecase);
3860 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003861 if (in->enable_ns != enable &&
3862 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3863 in->enable_ns = enable;
3864 if (!in->standby)
3865 select_devices(in->dev, in->usecase);
3866 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003867 pthread_mutex_unlock(&in->dev->lock);
3868 pthread_mutex_unlock(&in->lock);
3869
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870 return 0;
3871}
3872
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003873static int in_add_audio_effect(const struct audio_stream *stream,
3874 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003875{
Eric Laurent994a6932013-07-17 11:51:42 -07003876 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003877 return add_remove_audio_effect(stream, effect, true);
3878}
3879
3880static int in_remove_audio_effect(const struct audio_stream *stream,
3881 effect_handle_t effect)
3882{
Eric Laurent994a6932013-07-17 11:51:42 -07003883 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003884 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003885}
3886
Eric Laurent0e46adf2016-12-16 12:49:24 -08003887static int in_stop(const struct audio_stream_in* stream)
3888{
3889 struct stream_in *in = (struct stream_in *)stream;
3890 struct audio_device *adev = in->dev;
3891
3892 int ret = -ENOSYS;
3893 ALOGV("%s", __func__);
3894 pthread_mutex_lock(&adev->lock);
3895 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3896 in->capture_started && in->pcm != NULL) {
3897 pcm_stop(in->pcm);
3898 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003899 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003900 }
3901 pthread_mutex_unlock(&adev->lock);
3902 return ret;
3903}
3904
3905static int in_start(const struct audio_stream_in* stream)
3906{
3907 struct stream_in *in = (struct stream_in *)stream;
3908 struct audio_device *adev = in->dev;
3909 int ret = -ENOSYS;
3910
3911 ALOGV("%s in %p", __func__, in);
3912 pthread_mutex_lock(&adev->lock);
3913 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3914 !in->capture_started && in->pcm != NULL) {
3915 if (!in->capture_started) {
3916 ret = start_input_stream(in);
3917 if (ret == 0) {
3918 in->capture_started = true;
3919 }
3920 }
3921 }
3922 pthread_mutex_unlock(&adev->lock);
3923 return ret;
3924}
3925
3926static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3927 int32_t min_size_frames,
3928 struct audio_mmap_buffer_info *info)
3929{
3930 struct stream_in *in = (struct stream_in *)stream;
3931 struct audio_device *adev = in->dev;
3932 int ret = 0;
3933 unsigned int offset1;
3934 unsigned int frames1;
3935 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003936 uint32_t mmap_size;
3937 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003938
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003939 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003940 pthread_mutex_lock(&adev->lock);
3941 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003942
Eric Laurent0e46adf2016-12-16 12:49:24 -08003943 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003944 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003945 ret = -EINVAL;
3946 goto exit;
3947 }
3948 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003949 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003950 ALOGV("%s in %p", __func__, in);
3951 ret = -ENOSYS;
3952 goto exit;
3953 }
3954 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3955 if (in->pcm_device_id < 0) {
3956 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3957 __func__, in->pcm_device_id, in->usecase);
3958 ret = -EINVAL;
3959 goto exit;
3960 }
Phil Burkbc991042017-02-24 08:06:44 -08003961
3962 adjust_mmap_period_count(&in->config, min_size_frames);
3963
Eric Laurent0e46adf2016-12-16 12:49:24 -08003964 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3965 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3966 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3967 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3968 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3969 step = "open";
3970 ret = -ENODEV;
3971 goto exit;
3972 }
3973
3974 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3975 if (ret < 0) {
3976 step = "begin";
3977 goto exit;
3978 }
3979 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003980 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003981 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003982 ret = platform_get_mmap_data_fd(adev->platform,
3983 in->pcm_device_id, 1 /*capture*/,
3984 &info->shared_memory_fd,
3985 &mmap_size);
3986 if (ret < 0) {
3987 // Fall back to non exclusive mode
3988 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3989 } else {
3990 if (mmap_size < buffer_size) {
3991 step = "mmap";
3992 goto exit;
3993 }
3994 // FIXME: indicate exclusive mode support by returning a negative buffer size
3995 info->buffer_size_frames *= -1;
3996 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003997
Haynes Mathew George96483a22017-03-28 14:52:47 -07003998 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003999
4000 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4001 if (ret < 0) {
4002 step = "commit";
4003 goto exit;
4004 }
4005
Phil Burkbc991042017-02-24 08:06:44 -08004006 in->standby = false;
4007 ret = 0;
4008
Eric Laurent0e46adf2016-12-16 12:49:24 -08004009 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4010 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004011
4012exit:
4013 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004014 if (in->pcm == NULL) {
4015 ALOGE("%s: %s - %d", __func__, step, ret);
4016 } else {
4017 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004018 pcm_close(in->pcm);
4019 in->pcm = NULL;
4020 }
4021 }
4022 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004023 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004024 return ret;
4025}
4026
4027static int in_get_mmap_position(const struct audio_stream_in *stream,
4028 struct audio_mmap_position *position)
4029{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004030 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004031 struct stream_in *in = (struct stream_in *)stream;
4032 ALOGVV("%s", __func__);
4033 if (position == NULL) {
4034 return -EINVAL;
4035 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004036 lock_input_stream(in);
4037 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4038 in->pcm == NULL) {
4039 ret = -ENOSYS;
4040 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004041 }
4042 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004043 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004044 if (ret < 0) {
4045 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004046 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004047 }
Andy Hungfc044e12017-03-20 09:24:22 -07004048 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004049exit:
4050 pthread_mutex_unlock(&in->lock);
4051 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004052}
4053
jiabin8962a4d2018-03-19 18:21:24 -07004054static int in_get_active_microphones(const struct audio_stream_in *stream,
4055 struct audio_microphone_characteristic_t *mic_array,
4056 size_t *mic_count) {
4057 struct stream_in *in = (struct stream_in *)stream;
4058 struct audio_device *adev = in->dev;
4059 ALOGVV("%s", __func__);
4060
4061 lock_input_stream(in);
4062 pthread_mutex_lock(&adev->lock);
4063 int ret = platform_get_active_microphones(adev->platform, in->device,
4064 audio_channel_count_from_in_mask(in->channel_mask),
4065 in->source, in->usecase, mic_array, mic_count);
4066 pthread_mutex_unlock(&adev->lock);
4067 pthread_mutex_unlock(&in->lock);
4068
4069 return ret;
4070}
4071
4072static int adev_get_microphones(const struct audio_hw_device *dev,
4073 struct audio_microphone_characteristic_t *mic_array,
4074 size_t *mic_count) {
4075 struct audio_device *adev = (struct audio_device *)dev;
4076 ALOGVV("%s", __func__);
4077
4078 pthread_mutex_lock(&adev->lock);
4079 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4080 pthread_mutex_unlock(&adev->lock);
4081
4082 return ret;
4083}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004084
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085static int adev_open_output_stream(struct audio_hw_device *dev,
4086 audio_io_handle_t handle,
4087 audio_devices_t devices,
4088 audio_output_flags_t flags,
4089 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004090 struct audio_stream_out **stream_out,
4091 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004092{
4093 struct audio_device *adev = (struct audio_device *)dev;
4094 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004095 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004096 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4097 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4098 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004099
Andy Hungd9653bd2017-08-01 19:31:39 -07004100 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4101 return -ENOSYS;
4102 }
4103
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004104 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4105 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004106 *stream_out = NULL;
4107 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4108
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004109 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004111 if (devices == AUDIO_DEVICE_NONE)
4112 devices = AUDIO_DEVICE_OUT_SPEAKER;
4113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004114 out->flags = flags;
4115 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004116 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004117 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004118 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004119
4120 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004121 if ((is_hdmi || is_usb_dev) &&
4122 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4123 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4124 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004125 audio_format_t req_format = config->format;
4126 audio_channel_mask_t req_channel_mask = config->channel_mask;
4127 uint32_t req_sample_rate = config->sample_rate;
4128
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004129 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004130 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004131 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004132 if (config->sample_rate == 0)
4133 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004134 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004135 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4136 if (config->format == AUDIO_FORMAT_DEFAULT)
4137 config->format = AUDIO_FORMAT_PCM_16_BIT;
4138 } else if (is_usb_dev) {
4139 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4140 &config->format,
4141 &out->supported_formats[0],
4142 MAX_SUPPORTED_FORMATS,
4143 &config->channel_mask,
4144 &out->supported_channel_masks[0],
4145 MAX_SUPPORTED_CHANNEL_MASKS,
4146 &config->sample_rate,
4147 &out->supported_sample_rates[0],
4148 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004149 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004150 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004151 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004152 if (ret != 0) {
4153 // For MMAP NO IRQ, allow conversions in ADSP
4154 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4155 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004156
Eric Laurentab805ee2018-03-30 12:20:38 -07004157 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4158 config->sample_rate = req_sample_rate;
4159 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4160 config->channel_mask = req_channel_mask;
4161 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4162 config->format = req_format;
4163 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004164
Haynes Mathew George569b7482017-05-08 14:44:27 -07004165 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004166 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004167 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004168 if (is_hdmi) {
4169 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4170 out->config = pcm_config_hdmi_multi;
4171 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4172 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4173 out->config = pcm_config_mmap_playback;
4174 out->stream.start = out_start;
4175 out->stream.stop = out_stop;
4176 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4177 out->stream.get_mmap_position = out_get_mmap_position;
4178 } else {
4179 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4180 out->config = pcm_config_hifi;
4181 }
4182
4183 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004184 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004185 if (is_hdmi) {
4186 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4187 audio_bytes_per_sample(out->format));
4188 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004189 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004190 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004191 pthread_mutex_lock(&adev->lock);
4192 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4193 pthread_mutex_unlock(&adev->lock);
4194
4195 // reject offload during card offline to allow
4196 // fallback to s/w paths
4197 if (offline) {
4198 ret = -ENODEV;
4199 goto error_open;
4200 }
4201
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004202 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4203 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4204 ALOGE("%s: Unsupported Offload information", __func__);
4205 ret = -EINVAL;
4206 goto error_open;
4207 }
4208 if (!is_supported_format(config->offload_info.format)) {
4209 ALOGE("%s: Unsupported audio format", __func__);
4210 ret = -EINVAL;
4211 goto error_open;
4212 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004213 out->sample_rate = config->offload_info.sample_rate;
4214 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4215 out->channel_mask = config->offload_info.channel_mask;
4216 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4217 out->channel_mask = config->channel_mask;
4218 else
4219 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4220
4221 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004222
4223 out->compr_config.codec = (struct snd_codec *)
4224 calloc(1, sizeof(struct snd_codec));
4225
4226 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004227
4228 out->stream.set_callback = out_set_callback;
4229 out->stream.pause = out_pause;
4230 out->stream.resume = out_resume;
4231 out->stream.drain = out_drain;
4232 out->stream.flush = out_flush;
4233
4234 out->compr_config.codec->id =
4235 get_snd_codec_id(config->offload_info.format);
4236 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4237 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004238 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004239 out->compr_config.codec->bit_rate =
4240 config->offload_info.bit_rate;
4241 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004242 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004243 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4244
4245 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4246 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004247
4248 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004249 create_offload_callback_thread(out);
4250 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4251 __func__, config->offload_info.version,
4252 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004253 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4254 switch (config->sample_rate) {
4255 case 0:
4256 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4257 break;
4258 case 8000:
4259 case 16000:
4260 case 48000:
4261 out->sample_rate = config->sample_rate;
4262 break;
4263 default:
4264 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4265 config->sample_rate);
4266 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4267 ret = -EINVAL;
4268 goto error_open;
4269 }
4270 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4271 switch (config->channel_mask) {
4272 case AUDIO_CHANNEL_NONE:
4273 case AUDIO_CHANNEL_OUT_STEREO:
4274 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4275 break;
4276 default:
4277 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4278 config->channel_mask);
4279 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4280 ret = -EINVAL;
4281 goto error_open;
4282 }
4283 switch (config->format) {
4284 case AUDIO_FORMAT_DEFAULT:
4285 case AUDIO_FORMAT_PCM_16_BIT:
4286 out->format = AUDIO_FORMAT_PCM_16_BIT;
4287 break;
4288 default:
4289 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4290 config->format);
4291 config->format = AUDIO_FORMAT_PCM_16_BIT;
4292 ret = -EINVAL;
4293 goto error_open;
4294 }
4295
4296 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004297 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004298 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004299 case 0:
4300 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4301 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004302 case 8000:
4303 case 16000:
4304 case 48000:
4305 out->sample_rate = config->sample_rate;
4306 break;
4307 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004308 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4309 config->sample_rate);
4310 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4311 ret = -EINVAL;
4312 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004313 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004314 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4315 switch (config->channel_mask) {
4316 case AUDIO_CHANNEL_NONE:
4317 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4318 break;
4319 case AUDIO_CHANNEL_OUT_STEREO:
4320 out->channel_mask = config->channel_mask;
4321 break;
4322 default:
4323 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4324 config->channel_mask);
4325 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4326 ret = -EINVAL;
4327 break;
4328 }
4329 switch (config->format) {
4330 case AUDIO_FORMAT_DEFAULT:
4331 out->format = AUDIO_FORMAT_PCM_16_BIT;
4332 break;
4333 case AUDIO_FORMAT_PCM_16_BIT:
4334 out->format = config->format;
4335 break;
4336 default:
4337 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4338 config->format);
4339 config->format = AUDIO_FORMAT_PCM_16_BIT;
4340 ret = -EINVAL;
4341 break;
4342 }
4343 if (ret != 0)
4344 goto error_open;
4345
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004346 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4347 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004348 out->config.rate = out->sample_rate;
4349 out->config.channels =
4350 audio_channel_count_from_out_mask(out->channel_mask);
4351 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004352 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004353 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4354 switch (config->sample_rate) {
4355 case 0:
4356 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4357 break;
4358 case 8000:
4359 case 16000:
4360 case 32000:
4361 case 48000:
4362 out->sample_rate = config->sample_rate;
4363 break;
4364 default:
4365 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4366 config->sample_rate);
4367 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4368 ret = -EINVAL;
4369 break;
4370 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004371 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004372 switch (config->channel_mask) {
4373 case AUDIO_CHANNEL_NONE:
4374 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4375 break;
4376 case AUDIO_CHANNEL_OUT_STEREO:
4377 out->channel_mask = config->channel_mask;
4378 break;
4379 default:
4380 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4381 config->channel_mask);
4382 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4383 ret = -EINVAL;
4384 break;
4385 }
4386 switch (config->format) {
4387 case AUDIO_FORMAT_DEFAULT:
4388 out->format = AUDIO_FORMAT_PCM_16_BIT;
4389 break;
4390 case AUDIO_FORMAT_PCM_16_BIT:
4391 out->format = config->format;
4392 break;
4393 default:
4394 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4395 config->format);
4396 config->format = AUDIO_FORMAT_PCM_16_BIT;
4397 ret = -EINVAL;
4398 break;
4399 }
4400 if (ret != 0)
4401 goto error_open;
4402
vivek mehtaa68fea62017-06-08 19:04:02 -07004403 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004404 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4405 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004406 out->config.rate = out->sample_rate;
4407 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004408 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004409 out->sample_rate,
4410 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004411 out->config.channels,
4412 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004413 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004414 out->config.period_size = buffer_size / frame_size;
4415 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4416 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004417 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004418 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004419 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4420 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004421 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004422 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4423 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004424 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004425 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004426 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004427 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004428 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004429 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4430 out->config = pcm_config_mmap_playback;
4431 out->stream.start = out_start;
4432 out->stream.stop = out_stop;
4433 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4434 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004435 } else {
4436 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4437 out->config = pcm_config_low_latency;
4438 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004439
4440 if (config->sample_rate == 0) {
4441 out->sample_rate = out->config.rate;
4442 } else {
4443 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004444 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004445 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4446 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4447 } else {
4448 out->channel_mask = config->channel_mask;
4449 }
4450 if (config->format == AUDIO_FORMAT_DEFAULT)
4451 out->format = audio_format_from_pcm_format(out->config.format);
4452 else if (!audio_is_linear_pcm(config->format)) {
4453 config->format = AUDIO_FORMAT_PCM_16_BIT;
4454 ret = -EINVAL;
4455 goto error_open;
4456 } else {
4457 out->format = config->format;
4458 }
4459
4460 out->config.rate = out->sample_rate;
4461 out->config.channels =
4462 audio_channel_count_from_out_mask(out->channel_mask);
4463 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4464 out->config.format = pcm_format_from_audio_format(out->format);
4465 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004466 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004467
4468 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4469 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004470 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004471 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4472 __func__, config->sample_rate, config->format, config->channel_mask);
4473 config->sample_rate = out->sample_rate;
4474 config->format = out->format;
4475 config->channel_mask = out->channel_mask;
4476 ret = -EINVAL;
4477 goto error_open;
4478 }
4479
Andy Hung6fcba9c2014-03-18 11:53:32 -07004480 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4481 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004482
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004483 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004484 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004485 adev->primary_output = out;
4486 else {
4487 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004488 ret = -EEXIST;
4489 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004490 }
4491 }
4492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004493 /* Check if this usecase is already existing */
4494 pthread_mutex_lock(&adev->lock);
4495 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4496 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004497 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004498 ret = -EEXIST;
4499 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500 }
4501 pthread_mutex_unlock(&adev->lock);
4502
4503 out->stream.common.get_sample_rate = out_get_sample_rate;
4504 out->stream.common.set_sample_rate = out_set_sample_rate;
4505 out->stream.common.get_buffer_size = out_get_buffer_size;
4506 out->stream.common.get_channels = out_get_channels;
4507 out->stream.common.get_format = out_get_format;
4508 out->stream.common.set_format = out_set_format;
4509 out->stream.common.standby = out_standby;
4510 out->stream.common.dump = out_dump;
4511 out->stream.common.set_parameters = out_set_parameters;
4512 out->stream.common.get_parameters = out_get_parameters;
4513 out->stream.common.add_audio_effect = out_add_audio_effect;
4514 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4515 out->stream.get_latency = out_get_latency;
4516 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004517#ifdef NO_AUDIO_OUT
4518 out->stream.write = out_write_for_no_output;
4519#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004521#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004522 out->stream.get_render_position = out_get_render_position;
4523 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004524 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004525
Eric Laurent0e46adf2016-12-16 12:49:24 -08004526 if (out->realtime)
4527 out->af_period_multiplier = af_period_multiplier;
4528 else
4529 out->af_period_multiplier = 1;
4530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004531 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004532 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004533 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004534
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004535 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004536 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004537 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4538
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004539 config->format = out->stream.common.get_format(&out->stream.common);
4540 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4541 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4542
Kevin Rocarda325aa22018-04-03 09:15:52 -07004543 register_format(out->format, out->supported_formats);
4544 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4545 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4546
Andy Hunga452b0a2017-03-15 14:51:15 -07004547 out->error_log = error_log_create(
4548 ERROR_LOG_ENTRIES,
4549 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4550
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004551 /*
4552 By locking output stream before registering, we allow the callback
4553 to update stream's state only after stream's initial state is set to
4554 adev state.
4555 */
4556 lock_output_stream(out);
4557 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4558 pthread_mutex_lock(&adev->lock);
4559 out->card_status = adev->card_status;
4560 pthread_mutex_unlock(&adev->lock);
4561 pthread_mutex_unlock(&out->lock);
4562
vivek mehta4a824772017-06-08 19:05:49 -07004563 stream_app_type_cfg_init(&out->app_type_cfg);
4564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004565 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004566
Eric Laurent994a6932013-07-17 11:51:42 -07004567 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004568 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004569
4570error_open:
4571 free(out);
4572 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004573 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004574 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004575}
4576
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004577static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004578 struct audio_stream_out *stream)
4579{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004580 struct stream_out *out = (struct stream_out *)stream;
4581 struct audio_device *adev = out->dev;
4582
Eric Laurent994a6932013-07-17 11:51:42 -07004583 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004584
4585 // must deregister from sndmonitor first to prevent races
4586 // between the callback and close_stream
4587 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004589 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4590 destroy_offload_callback_thread(out);
4591
4592 if (out->compr_config.codec != NULL)
4593 free(out->compr_config.codec);
4594 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004595
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004596 out->a2dp_compress_mute = false;
4597
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004598 if (adev->voice_tx_output == out)
4599 adev->voice_tx_output = NULL;
4600
Andy Hunga452b0a2017-03-15 14:51:15 -07004601 error_log_destroy(out->error_log);
4602 out->error_log = NULL;
4603
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004604 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004605 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004606 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004607 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004608 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004609}
4610
4611static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4612{
4613 struct audio_device *adev = (struct audio_device *)dev;
4614 struct str_parms *parms;
4615 char *str;
4616 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004617 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004618 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004619 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004620
Joe Onorato188b6222016-03-01 11:02:27 -08004621 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004622
4623 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004624
4625 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004626 status = voice_set_parameters(adev, parms);
4627 if (status != 0) {
4628 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004629 }
4630
4631 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4632 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004633 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004634 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4635 adev->bluetooth_nrec = true;
4636 else
4637 adev->bluetooth_nrec = false;
4638 }
4639
4640 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4641 if (ret >= 0) {
4642 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4643 adev->screen_off = false;
4644 else
4645 adev->screen_off = true;
4646 }
4647
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004648 ret = str_parms_get_int(parms, "rotation", &val);
4649 if (ret >= 0) {
4650 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004651 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004652 // FIXME: note that the code below assumes that the speakers are in the correct placement
4653 // relative to the user when the device is rotated 90deg from its default rotation. This
4654 // assumption is device-specific, not platform-specific like this code.
4655 case 270:
4656 reverse_speakers = true;
4657 break;
4658 case 0:
4659 case 90:
4660 case 180:
4661 break;
4662 default:
4663 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004664 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004665 }
Eric Laurent03f09432014-03-25 18:09:11 -07004666 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004667 // check and set swap
4668 // - check if orientation changed and speaker active
4669 // - set rotation and cache the rotation value
4670 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004671 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004672 }
4673
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004674 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4675 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004676 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004677 }
4678
David Linee3fe402017-03-13 10:00:42 -07004679 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4680 if (ret >= 0) {
4681 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004682 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004683 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4684 if (ret >= 0) {
4685 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004686 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004687 }
Eric Laurent99dab492017-06-17 15:19:08 -07004688 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004689 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4690 if (ret >= 0) {
4691 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004692 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004693 }
4694 }
4695 }
4696
4697 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4698 if (ret >= 0) {
4699 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004700 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004701 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4702 if (ret >= 0) {
4703 const int card = atoi(value);
4704
Eric Laurent99dab492017-06-17 15:19:08 -07004705 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004706 }
Eric Laurent99dab492017-06-17 15:19:08 -07004707 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004708 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4709 if (ret >= 0) {
4710 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004711 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004712 }
4713 }
4714 }
4715
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004716 audio_extn_hfp_set_parameters(adev, parms);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004717 audio_extn_a2dp_set_parameters(parms);
4718 // reconfigure should be done only after updating A2DP state in audio extension
4719 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4720 if (ret >= 0) {
4721 struct audio_usecase *usecase;
4722 struct listnode *node;
4723 list_for_each(node, &adev->usecase_list) {
4724 usecase = node_to_item(node, struct audio_usecase, list);
4725 if ((usecase->type == PCM_PLAYBACK) &&
4726 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)) {
4727 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4728
4729 pthread_mutex_unlock(&adev->lock);
4730 lock_output_stream(usecase->stream.out);
4731 pthread_mutex_lock(&adev->lock);
4732 audio_extn_a2dp_set_handoff_mode(true);
4733 // force device switch to reconfigure encoder
4734 select_devices(adev, usecase->id);
4735 audio_extn_a2dp_set_handoff_mode(false);
4736 pthread_mutex_unlock(&usecase->stream.out->lock);
4737 break;
4738 }
4739 }
4740 }
4741
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004742done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004743 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004744 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004745 ALOGV("%s: exit with code(%d)", __func__, status);
4746 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004747}
4748
4749static char* adev_get_parameters(const struct audio_hw_device *dev,
4750 const char *keys)
4751{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004752 struct audio_device *adev = (struct audio_device *)dev;
4753 struct str_parms *reply = str_parms_create();
4754 struct str_parms *query = str_parms_create_str(keys);
4755 char *str;
4756
4757 pthread_mutex_lock(&adev->lock);
4758
4759 voice_get_parameters(adev, query, reply);
4760 str = str_parms_to_str(reply);
4761 str_parms_destroy(query);
4762 str_parms_destroy(reply);
4763
4764 pthread_mutex_unlock(&adev->lock);
4765 ALOGV("%s: exit: returns - %s", __func__, str);
4766 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004767}
4768
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004769static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004770{
4771 return 0;
4772}
4773
Haynes Mathew George5191a852013-09-11 14:19:36 -07004774static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4775{
4776 int ret;
4777 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004778
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004779 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4780
Haynes Mathew George5191a852013-09-11 14:19:36 -07004781 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004782 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004783 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004784
Haynes Mathew George5191a852013-09-11 14:19:36 -07004785 return ret;
4786}
4787
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004788static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004789{
4790 return -ENOSYS;
4791}
4792
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004793static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4794 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004795{
4796 return -ENOSYS;
4797}
4798
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004799static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004800{
4801 return -ENOSYS;
4802}
4803
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004804static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004805{
4806 return -ENOSYS;
4807}
4808
4809static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4810{
4811 struct audio_device *adev = (struct audio_device *)dev;
4812
4813 pthread_mutex_lock(&adev->lock);
4814 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004815 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004816 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004817 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4818 voice_is_in_call(adev)) {
4819 voice_stop_call(adev);
4820 adev->current_call_output = NULL;
4821 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004822 }
4823 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004824
4825 audio_extn_extspk_set_mode(adev->extspk, mode);
4826
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004827 return 0;
4828}
4829
4830static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4831{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004832 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004833 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004834
Eric Laurent2bafff12016-03-17 12:17:23 -07004835 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004836 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004837 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4838 ret = audio_extn_hfp_set_mic_mute(adev, state);
4839 } else {
4840 ret = voice_set_mic_mute(adev, state);
4841 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004842 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004843 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004844
4845 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004846}
4847
4848static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4849{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004850 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004851 return 0;
4852}
4853
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004854static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004855 const struct audio_config *config)
4856{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004857 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004858
Eric Laurent74b55762017-07-09 17:04:53 -07004859 /* Don't know if USB HIFI in this context so use true to be conservative */
4860 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4861 true /*is_usb_hifi */) != 0)
4862 return 0;
4863
vivek mehtaa68fea62017-06-08 19:04:02 -07004864 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4865 config->sample_rate, config->format,
4866 channel_count,
4867 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004868}
4869
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004870static bool adev_input_allow_hifi_record(struct audio_device *adev,
4871 audio_devices_t devices,
4872 audio_input_flags_t flags,
4873 audio_source_t source) {
4874 const bool allowed = true;
4875
4876 if (!audio_is_usb_in_device(devices))
4877 return !allowed;
4878
4879 switch (flags) {
4880 case AUDIO_INPUT_FLAG_NONE:
4881 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4882 break;
4883 default:
4884 return !allowed;
4885 }
4886
4887 switch (source) {
4888 case AUDIO_SOURCE_DEFAULT:
4889 case AUDIO_SOURCE_MIC:
4890 case AUDIO_SOURCE_UNPROCESSED:
4891 break;
4892 default:
4893 return !allowed;
4894 }
4895
4896 switch (adev->mode) {
4897 case 0:
4898 break;
4899 default:
4900 return !allowed;
4901 }
4902
4903 return allowed;
4904}
4905
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004906static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004907 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004908 audio_devices_t devices,
4909 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004910 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004911 audio_input_flags_t flags,
4912 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004913 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004914{
4915 struct audio_device *adev = (struct audio_device *)dev;
4916 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004917 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004918 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004919 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004920 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004921 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4922 devices,
4923 flags,
4924 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004925 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004926 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004927
Andy Hungd9653bd2017-08-01 19:31:39 -07004928 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4929 return -ENOSYS;
4930 }
4931
Eric Laurent74b55762017-07-09 17:04:53 -07004932 if (!(is_usb_dev && may_use_hifi_record)) {
4933 if (config->sample_rate == 0)
4934 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4935 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4936 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4937 if (config->format == AUDIO_FORMAT_DEFAULT)
4938 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004939
Eric Laurent74b55762017-07-09 17:04:53 -07004940 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4941
4942 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4943 return -EINVAL;
4944 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004945
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004946 if (audio_extn_tfa_98xx_is_supported() &&
4947 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004948 return -EINVAL;
4949
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004950 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4951
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004952 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004953 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004954
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004955 in->stream.common.get_sample_rate = in_get_sample_rate;
4956 in->stream.common.set_sample_rate = in_set_sample_rate;
4957 in->stream.common.get_buffer_size = in_get_buffer_size;
4958 in->stream.common.get_channels = in_get_channels;
4959 in->stream.common.get_format = in_get_format;
4960 in->stream.common.set_format = in_set_format;
4961 in->stream.common.standby = in_standby;
4962 in->stream.common.dump = in_dump;
4963 in->stream.common.set_parameters = in_set_parameters;
4964 in->stream.common.get_parameters = in_get_parameters;
4965 in->stream.common.add_audio_effect = in_add_audio_effect;
4966 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4967 in->stream.set_gain = in_set_gain;
4968 in->stream.read = in_read;
4969 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004970 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07004971 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004972
4973 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004974 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004975 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004976 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004977 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004978 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004979
Haynes Mathew George569b7482017-05-08 14:44:27 -07004980 if (is_usb_dev && may_use_hifi_record) {
4981 /* HiFi record selects an appropriate format, channel, rate combo
4982 depending on sink capabilities*/
4983 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4984 &config->format,
4985 &in->supported_formats[0],
4986 MAX_SUPPORTED_FORMATS,
4987 &config->channel_mask,
4988 &in->supported_channel_masks[0],
4989 MAX_SUPPORTED_CHANNEL_MASKS,
4990 &config->sample_rate,
4991 &in->supported_sample_rates[0],
4992 MAX_SUPPORTED_SAMPLE_RATES);
4993 if (ret != 0) {
4994 ret = -EINVAL;
4995 goto err_open;
4996 }
Eric Laurent74b55762017-07-09 17:04:53 -07004997 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004998 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004999 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005000 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5001 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5002 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5003 bool ret_error = false;
5004 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5005 from HAL is 8_24
5006 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5007 8_24 return error indicating supported format is 8_24
5008 *> In case of any other source requesting 24 bit or float return error
5009 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005010
vivek mehta57ff9b52016-04-28 14:13:08 -07005011 on error flinger will retry with supported format passed
5012 */
5013 if (source != AUDIO_SOURCE_UNPROCESSED) {
5014 config->format = AUDIO_FORMAT_PCM_16_BIT;
5015 ret_error = true;
5016 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5017 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5018 ret_error = true;
5019 }
5020
5021 if (ret_error) {
5022 ret = -EINVAL;
5023 goto err_open;
5024 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005025 }
5026
vivek mehta57ff9b52016-04-28 14:13:08 -07005027 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005028 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005030 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005031 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5032 if (config->sample_rate == 0)
5033 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5034 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5035 config->sample_rate != 8000) {
5036 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5037 ret = -EINVAL;
5038 goto err_open;
5039 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005040
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005041 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5042 config->format = AUDIO_FORMAT_PCM_16_BIT;
5043 ret = -EINVAL;
5044 goto err_open;
5045 }
5046
5047 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5048 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005049 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005050 } else if (is_usb_dev && may_use_hifi_record) {
5051 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5052 in->config = pcm_config_audio_capture;
5053 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005054 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5055 config->sample_rate,
5056 config->format,
5057 channel_count,
5058 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005059 in->config.period_size = buffer_size / frame_size;
5060 in->config.rate = config->sample_rate;
5061 in->af_period_multiplier = 1;
5062 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005063 } else {
5064 in->usecase = USECASE_AUDIO_RECORD;
5065 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005066 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005067 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005068#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005069 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005070#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005071 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005072 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005073 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005074 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005075 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5076 config->sample_rate,
5077 config->format,
5078 channel_count,
5079 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005080 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005081 in->config.rate = config->sample_rate;
5082 in->af_period_multiplier = 1;
5083 } else {
5084 // period size is left untouched for rt mode playback
5085 in->config = pcm_config_audio_capture_rt;
5086 in->af_period_multiplier = af_period_multiplier;
5087 }
5088 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5089 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005090 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005091 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5092 in->config = pcm_config_mmap_capture;
5093 in->stream.start = in_start;
5094 in->stream.stop = in_stop;
5095 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5096 in->stream.get_mmap_position = in_get_mmap_position;
5097 in->af_period_multiplier = 1;
5098 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005099 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005100 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005101 (config->sample_rate == 8000 ||
5102 config->sample_rate == 16000 ||
5103 config->sample_rate == 32000 ||
5104 config->sample_rate == 48000) &&
5105 channel_count == 1) {
5106 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5107 in->config = pcm_config_audio_capture;
5108 frame_size = audio_stream_in_frame_size(&in->stream);
5109 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5110 config->sample_rate,
5111 config->format,
5112 channel_count, false /*is_low_latency*/);
5113 in->config.period_size = buffer_size / frame_size;
5114 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5115 in->config.rate = config->sample_rate;
5116 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005117 } else {
5118 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005119 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005120 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5121 config->sample_rate,
5122 config->format,
5123 channel_count,
5124 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005125 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005126 in->config.rate = config->sample_rate;
5127 in->af_period_multiplier = 1;
5128 }
5129 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5130 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005131 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005132
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005133 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005134 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005135
Kevin Rocarda325aa22018-04-03 09:15:52 -07005136
5137 register_format(in->format, in->supported_formats);
5138 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5139 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5140
Andy Hungd13f0d32017-06-12 13:58:37 -07005141 in->error_log = error_log_create(
5142 ERROR_LOG_ENTRIES,
5143 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5144
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005145 /* This stream could be for sound trigger lab,
5146 get sound trigger pcm if present */
5147 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005148
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005149 lock_input_stream(in);
5150 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5151 pthread_mutex_lock(&adev->lock);
5152 in->card_status = adev->card_status;
5153 pthread_mutex_unlock(&adev->lock);
5154 pthread_mutex_unlock(&in->lock);
5155
vivek mehta4a824772017-06-08 19:05:49 -07005156 stream_app_type_cfg_init(&in->app_type_cfg);
5157
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005158 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005159 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005160 return 0;
5161
5162err_open:
5163 free(in);
5164 *stream_in = NULL;
5165 return ret;
5166}
5167
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005168static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005169 struct audio_stream_in *stream)
5170{
Andy Hungd13f0d32017-06-12 13:58:37 -07005171 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005172 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005173
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005174 // must deregister from sndmonitor first to prevent races
5175 // between the callback and close_stream
5176 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005177 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005178
5179 error_log_destroy(in->error_log);
5180 in->error_log = NULL;
5181
Andy Hung0dbb52b2017-08-09 13:51:38 -07005182 pthread_mutex_destroy(&in->pre_lock);
5183 pthread_mutex_destroy(&in->lock);
5184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005185 free(stream);
5186
5187 return;
5188}
5189
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005190static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005191{
5192 return 0;
5193}
5194
Andy Hung31aca912014-03-20 17:14:59 -07005195/* verifies input and output devices and their capabilities.
5196 *
5197 * This verification is required when enabling extended bit-depth or
5198 * sampling rates, as not all qcom products support it.
5199 *
5200 * Suitable for calling only on initialization such as adev_open().
5201 * It fills the audio_device use_case_table[] array.
5202 *
5203 * Has a side-effect that it needs to configure audio routing / devices
5204 * in order to power up the devices and read the device parameters.
5205 * It does not acquire any hw device lock. Should restore the devices
5206 * back to "normal state" upon completion.
5207 */
5208static int adev_verify_devices(struct audio_device *adev)
5209{
5210 /* enumeration is a bit difficult because one really wants to pull
5211 * the use_case, device id, etc from the hidden pcm_device_table[].
5212 * In this case there are the following use cases and device ids.
5213 *
5214 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5215 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005216 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005217 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5218 * [USECASE_AUDIO_RECORD] = {0, 0},
5219 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5220 * [USECASE_VOICE_CALL] = {2, 2},
5221 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005222 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005223 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5224 */
5225
5226 /* should be the usecases enabled in adev_open_input_stream() */
5227 static const int test_in_usecases[] = {
5228 USECASE_AUDIO_RECORD,
5229 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5230 };
5231 /* should be the usecases enabled in adev_open_output_stream()*/
5232 static const int test_out_usecases[] = {
5233 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5234 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5235 };
5236 static const usecase_type_t usecase_type_by_dir[] = {
5237 PCM_PLAYBACK,
5238 PCM_CAPTURE,
5239 };
5240 static const unsigned flags_by_dir[] = {
5241 PCM_OUT,
5242 PCM_IN,
5243 };
5244
5245 size_t i;
5246 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005247 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005248 char info[512]; /* for possible debug info */
5249
5250 for (dir = 0; dir < 2; ++dir) {
5251 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5252 const unsigned flags_dir = flags_by_dir[dir];
5253 const size_t testsize =
5254 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5255 const int *testcases =
5256 dir ? test_in_usecases : test_out_usecases;
5257 const audio_devices_t audio_device =
5258 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5259
5260 for (i = 0; i < testsize; ++i) {
5261 const audio_usecase_t audio_usecase = testcases[i];
5262 int device_id;
5263 snd_device_t snd_device;
5264 struct pcm_params **pparams;
5265 struct stream_out out;
5266 struct stream_in in;
5267 struct audio_usecase uc_info;
5268 int retval;
5269
5270 pparams = &adev->use_case_table[audio_usecase];
5271 pcm_params_free(*pparams); /* can accept null input */
5272 *pparams = NULL;
5273
5274 /* find the device ID for the use case (signed, for error) */
5275 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5276 if (device_id < 0)
5277 continue;
5278
5279 /* prepare structures for device probing */
5280 memset(&uc_info, 0, sizeof(uc_info));
5281 uc_info.id = audio_usecase;
5282 uc_info.type = usecase_type;
5283 if (dir) {
5284 adev->active_input = &in;
5285 memset(&in, 0, sizeof(in));
5286 in.device = audio_device;
5287 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5288 uc_info.stream.in = &in;
5289 } else {
5290 adev->active_input = NULL;
5291 }
5292 memset(&out, 0, sizeof(out));
5293 out.devices = audio_device; /* only field needed in select_devices */
5294 uc_info.stream.out = &out;
5295 uc_info.devices = audio_device;
5296 uc_info.in_snd_device = SND_DEVICE_NONE;
5297 uc_info.out_snd_device = SND_DEVICE_NONE;
5298 list_add_tail(&adev->usecase_list, &uc_info.list);
5299
5300 /* select device - similar to start_(in/out)put_stream() */
5301 retval = select_devices(adev, audio_usecase);
5302 if (retval >= 0) {
5303 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5304#if LOG_NDEBUG == 0
5305 if (*pparams) {
5306 ALOGV("%s: (%s) card %d device %d", __func__,
5307 dir ? "input" : "output", card_id, device_id);
5308 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005309 } else {
5310 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5311 }
5312#endif
5313 }
5314
5315 /* deselect device - similar to stop_(in/out)put_stream() */
5316 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005317 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005318 /* 2. Disable the rx device */
5319 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005320 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005321 list_remove(&uc_info.list);
5322 }
5323 }
5324 adev->active_input = NULL; /* restore adev state */
5325 return 0;
5326}
5327
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005328static int adev_close(hw_device_t *device)
5329{
Andy Hung31aca912014-03-20 17:14:59 -07005330 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005331 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005332
5333 if (!adev)
5334 return 0;
5335
5336 pthread_mutex_lock(&adev_init_lock);
5337
5338 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005339 audio_extn_snd_mon_unregister_listener(adev);
5340 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005341 audio_route_free(adev->audio_route);
5342 free(adev->snd_dev_ref_cnt);
5343 platform_deinit(adev->platform);
5344 audio_extn_extspk_deinit(adev->extspk);
5345 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005346 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005347 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5348 pcm_params_free(adev->use_case_table[i]);
5349 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005350 if (adev->adm_deinit)
5351 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005352 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005353 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005354 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005355
5356 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005358 return 0;
5359}
5360
Glenn Kasten4f993392014-05-14 07:30:48 -07005361/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5362 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5363 * just that it _might_ work.
5364 */
5365static int period_size_is_plausible_for_low_latency(int period_size)
5366{
5367 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005368 case 48:
5369 case 96:
5370 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005371 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005372 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005373 case 240:
5374 case 320:
5375 case 480:
5376 return 1;
5377 default:
5378 return 0;
5379 }
5380}
5381
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005382static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5383{
5384 int card;
5385 card_status_t status;
5386
5387 if (!parms)
5388 return;
5389
5390 if (parse_snd_card_status(parms, &card, &status) < 0)
5391 return;
5392
5393 pthread_mutex_lock(&adev->lock);
5394 bool valid_cb = (card == adev->snd_card);
5395 if (valid_cb) {
5396 if (adev->card_status != status) {
5397 adev->card_status = status;
5398 platform_snd_card_update(adev->platform, status);
5399 }
5400 }
5401 pthread_mutex_unlock(&adev->lock);
5402 return;
5403}
5404
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005405/* out and adev lock held */
5406static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5407{
5408 struct audio_usecase *uc_info;
5409 float left_p;
5410 float right_p;
5411 audio_devices_t devices;
5412
5413 uc_info = get_usecase_from_list(adev, out->usecase);
5414 if (uc_info == NULL) {
5415 ALOGE("%s: Could not find the usecase (%d) in the list",
5416 __func__, out->usecase);
5417 return -EINVAL;
5418 }
5419
5420 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5421 out->usecase, use_case_table[out->usecase]);
5422
5423 if (restore) {
5424 // restore A2DP device for active usecases and unmute if required
5425 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5426 !is_a2dp_device(uc_info->out_snd_device)) {
5427 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5428 select_devices(adev, uc_info->id);
5429 pthread_mutex_lock(&out->compr_mute_lock);
5430 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5431 (out->a2dp_compress_mute)) {
5432 out->a2dp_compress_mute = false;
5433 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5434 }
5435 pthread_mutex_unlock(&out->compr_mute_lock);
5436 }
5437 } else {
5438 // mute compress stream if suspended
5439 pthread_mutex_lock(&out->compr_mute_lock);
5440 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5441 (!out->a2dp_compress_mute)) {
5442 if (!out->standby) {
5443 ALOGD("%s: selecting speaker and muting stream", __func__);
5444 devices = out->devices;
5445 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5446 left_p = out->volume_l;
5447 right_p = out->volume_r;
5448 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5449 compress_pause(out->compr);
5450 set_compr_volume(&out->stream, 0.0f, 0.0f);
5451 out->a2dp_compress_mute = true;
5452 select_devices(adev, out->usecase);
5453 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5454 compress_resume(out->compr);
5455 out->devices = devices;
5456 out->volume_l = left_p;
5457 out->volume_r = right_p;
5458 }
5459 }
5460 pthread_mutex_unlock(&out->compr_mute_lock);
5461 }
5462 ALOGV("%s: exit", __func__);
5463 return 0;
5464}
5465
5466int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5467{
5468 int ret = 0;
5469
5470 lock_output_stream(out);
5471 pthread_mutex_lock(&adev->lock);
5472
5473 ret = check_a2dp_restore_l(adev, out, restore);
5474
5475 pthread_mutex_unlock(&adev->lock);
5476 pthread_mutex_unlock(&out->lock);
5477 return ret;
5478}
5479
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005480static int adev_open(const hw_module_t *module, const char *name,
5481 hw_device_t **device)
5482{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005483 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005484
Eric Laurent2bafff12016-03-17 12:17:23 -07005485 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005486 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005487 pthread_mutex_lock(&adev_init_lock);
5488 if (audio_device_ref_count != 0) {
5489 *device = &adev->device.common;
5490 audio_device_ref_count++;
5491 ALOGV("%s: returning existing instance of adev", __func__);
5492 ALOGV("%s: exit", __func__);
5493 pthread_mutex_unlock(&adev_init_lock);
5494 return 0;
5495 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005496 adev = calloc(1, sizeof(struct audio_device));
5497
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005498 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005500 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5501 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5502 adev->device.common.module = (struct hw_module_t *)module;
5503 adev->device.common.close = adev_close;
5504
5505 adev->device.init_check = adev_init_check;
5506 adev->device.set_voice_volume = adev_set_voice_volume;
5507 adev->device.set_master_volume = adev_set_master_volume;
5508 adev->device.get_master_volume = adev_get_master_volume;
5509 adev->device.set_master_mute = adev_set_master_mute;
5510 adev->device.get_master_mute = adev_get_master_mute;
5511 adev->device.set_mode = adev_set_mode;
5512 adev->device.set_mic_mute = adev_set_mic_mute;
5513 adev->device.get_mic_mute = adev_get_mic_mute;
5514 adev->device.set_parameters = adev_set_parameters;
5515 adev->device.get_parameters = adev_get_parameters;
5516 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5517 adev->device.open_output_stream = adev_open_output_stream;
5518 adev->device.close_output_stream = adev_close_output_stream;
5519 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005520
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005521 adev->device.close_input_stream = adev_close_input_stream;
5522 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005523 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005524
5525 /* Set the default route before the PCM stream is opened */
5526 pthread_mutex_lock(&adev->lock);
5527 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005528 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005529 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005530 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005531 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005532 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005533 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005534 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005535 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005536 pthread_mutex_unlock(&adev->lock);
5537
5538 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005539 adev->platform = platform_init(adev);
5540 if (!adev->platform) {
5541 free(adev->snd_dev_ref_cnt);
5542 free(adev);
5543 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5544 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005545 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005546 return -EINVAL;
5547 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005548 adev->extspk = audio_extn_extspk_init(adev);
5549
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005550 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5551 if (adev->visualizer_lib == NULL) {
5552 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5553 } else {
5554 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5555 adev->visualizer_start_output =
5556 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5557 "visualizer_hal_start_output");
5558 adev->visualizer_stop_output =
5559 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5560 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005561 }
5562
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005563 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5564 if (adev->offload_effects_lib == NULL) {
5565 ALOGW("%s: DLOPEN failed for %s", __func__,
5566 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5567 } else {
5568 ALOGV("%s: DLOPEN successful for %s", __func__,
5569 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5570 adev->offload_effects_start_output =
5571 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5572 "offload_effects_bundle_hal_start_output");
5573 adev->offload_effects_stop_output =
5574 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5575 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005576 }
5577
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005578 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5579 if (adev->adm_lib == NULL) {
5580 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5581 } else {
5582 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5583 adev->adm_init = (adm_init_t)
5584 dlsym(adev->adm_lib, "adm_init");
5585 adev->adm_deinit = (adm_deinit_t)
5586 dlsym(adev->adm_lib, "adm_deinit");
5587 adev->adm_register_input_stream = (adm_register_input_stream_t)
5588 dlsym(adev->adm_lib, "adm_register_input_stream");
5589 adev->adm_register_output_stream = (adm_register_output_stream_t)
5590 dlsym(adev->adm_lib, "adm_register_output_stream");
5591 adev->adm_deregister_stream = (adm_deregister_stream_t)
5592 dlsym(adev->adm_lib, "adm_deregister_stream");
5593 adev->adm_request_focus = (adm_request_focus_t)
5594 dlsym(adev->adm_lib, "adm_request_focus");
5595 adev->adm_abandon_focus = (adm_abandon_focus_t)
5596 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005597 adev->adm_set_config = (adm_set_config_t)
5598 dlsym(adev->adm_lib, "adm_set_config");
5599 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5600 dlsym(adev->adm_lib, "adm_request_focus_v2");
5601 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5602 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5603 adev->adm_on_routing_change = (adm_on_routing_change_t)
5604 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005605 }
5606
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005607 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005608 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005609
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005610 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005611
Andy Hung31aca912014-03-20 17:14:59 -07005612 if (k_enable_extended_precision)
5613 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005614
Glenn Kasten4f993392014-05-14 07:30:48 -07005615 char value[PROPERTY_VALUE_MAX];
5616 int trial;
5617 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5618 trial = atoi(value);
5619 if (period_size_is_plausible_for_low_latency(trial)) {
5620 pcm_config_low_latency.period_size = trial;
5621 pcm_config_low_latency.start_threshold = trial / 4;
5622 pcm_config_low_latency.avail_min = trial / 4;
5623 configured_low_latency_capture_period_size = trial;
5624 }
5625 }
5626 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5627 trial = atoi(value);
5628 if (period_size_is_plausible_for_low_latency(trial)) {
5629 configured_low_latency_capture_period_size = trial;
5630 }
5631 }
5632
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005633 // commented as full set of app type cfg is sent from platform
5634 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005635 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005636
5637 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5638 af_period_multiplier = atoi(value);
5639 if (af_period_multiplier < 0) {
5640 af_period_multiplier = 2;
5641 } else if (af_period_multiplier > 4) {
5642 af_period_multiplier = 4;
5643 }
5644 ALOGV("new period_multiplier = %d", af_period_multiplier);
5645 }
5646
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005647 audio_extn_tfa_98xx_init(adev);
5648
vivek mehta1a9b7c02015-06-25 11:49:38 -07005649 pthread_mutex_unlock(&adev_init_lock);
5650
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005651 if (adev->adm_init)
5652 adev->adm_data = adev->adm_init();
5653
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005654 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005655 audio_extn_snd_mon_init();
5656 pthread_mutex_lock(&adev->lock);
5657 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5658 adev->card_status = CARD_STATUS_ONLINE;
5659 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005660 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005661
Eric Laurent2bafff12016-03-17 12:17:23 -07005662 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005663 return 0;
5664}
5665
5666static struct hw_module_methods_t hal_module_methods = {
5667 .open = adev_open,
5668};
5669
5670struct audio_module HAL_MODULE_INFO_SYM = {
5671 .common = {
5672 .tag = HARDWARE_MODULE_TAG,
5673 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5674 .hal_api_version = HARDWARE_HAL_API_VERSION,
5675 .id = AUDIO_HARDWARE_MODULE_ID,
5676 .name = "QCOM Audio HAL",
5677 .author = "Code Aurora Forum",
5678 .methods = &hal_module_methods,
5679 },
5680};