blob: 7235ad3da01586cd62db06f7eedbd37dd6ea7374 [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>
Andy Hung572633e2019-02-19 11:58:24 -080043#include <utils/Timers.h> // systemTime
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>
Suren Baghdasaryan7f924c22018-12-21 15:07:18 -080047#include <processgroup/sched_policy.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070048#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080049#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070050#include <audio_effects/effect_aec.h>
51#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070052#include <audio_utils/clock.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080054#include "audio_extn.h"
Wei Wangf4837d52017-11-21 14:51:20 -080055#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070056#include "platform_api.h"
57#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070058#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080059
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080061#include "audio_extn/tfa_98xx.h"
jasmine cha270b7762018-03-30 15:41:33 +080062#include "audio_extn/maxxaudio.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070063
Eric Laurent397db572016-05-11 11:31:47 -070064/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
65 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070066#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070067// 2 buffers causes problems with high bitrate files
68#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070069/* ToDo: Check and update a proper value in msec */
70#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070071/* treat as unsigned Q1.13 */
72#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070074
75/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070076#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070077
Eric Laurent51f3c662018-04-10 18:21:34 -070078#define RECORD_GAIN_MIN 0.0f
79#define RECORD_GAIN_MAX 1.0f
80#define RECORD_VOLUME_CTL_MAX 0x2000
81
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070082#define PROXY_OPEN_RETRY_COUNT 100
83#define PROXY_OPEN_WAIT_TIME 20
84
vivek mehtadae44712015-07-27 14:13:18 -070085#define MIN_CHANNEL_COUNT 1
86#define DEFAULT_CHANNEL_COUNT 2
87
Jean-Michel Trivic0750692015-10-12 12:12:32 -070088#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
89#define MAX_CHANNEL_COUNT 1
90#else
vivek mehtadae44712015-07-27 14:13:18 -070091#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
92#define XSTR(x) STR(x)
93#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070094#endif
Eric Laurent74b55762017-07-09 17:04:53 -070095#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070096
Haynes Mathew George03c40102016-01-29 17:57:48 -080097#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
98
Glenn Kasten4f993392014-05-14 07:30:48 -070099static unsigned int configured_low_latency_capture_period_size =
100 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
101
Eric Laurent0e46adf2016-12-16 12:49:24 -0800102
103#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -0800104#define MMAP_PERIOD_COUNT_MIN 32
105#define MMAP_PERIOD_COUNT_MAX 512
106#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800107
Andy Hung31aca912014-03-20 17:14:59 -0700108/* This constant enables extended precision handling.
109 * TODO The flag is off until more testing is done.
110 */
111static const bool k_enable_extended_precision = false;
112
Eric Laurentb23d5282013-05-14 15:27:20 -0700113struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700114 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700115 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
116 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
117 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
118 .format = PCM_FORMAT_S16_LE,
119 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
120 .stop_threshold = INT_MAX,
121 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
122};
123
124struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700125 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700126 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
127 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
128 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
129 .format = PCM_FORMAT_S16_LE,
130 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
131 .stop_threshold = INT_MAX,
132 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
133};
134
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -0800135struct pcm_config pcm_config_haptics_audio = {
136 .channels = 1,
137 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
138 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
139 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
140 .format = PCM_FORMAT_S16_LE,
141 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
142 .stop_threshold = INT_MAX,
143 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
144};
145
146struct pcm_config pcm_config_haptics = {
147 .channels = 1,
148 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
149 .period_count = 2,
150 .format = PCM_FORMAT_S16_LE,
151 .stop_threshold = INT_MAX,
152 .avail_min = 0,
153};
154
Haynes Mathew George03c40102016-01-29 17:57:48 -0800155static int af_period_multiplier = 4;
156struct pcm_config pcm_config_rt = {
157 .channels = DEFAULT_CHANNEL_COUNT,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE, //1 ms
160 .period_count = 512, //=> buffer size is 512ms
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Eric Laurentb23d5282013-05-14 15:27:20 -0700169struct pcm_config pcm_config_hdmi_multi = {
170 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
171 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
172 .period_size = HDMI_MULTI_PERIOD_SIZE,
173 .period_count = HDMI_MULTI_PERIOD_COUNT,
174 .format = PCM_FORMAT_S16_LE,
175 .start_threshold = 0,
176 .stop_threshold = INT_MAX,
177 .avail_min = 0,
178};
179
Eric Laurent0e46adf2016-12-16 12:49:24 -0800180struct pcm_config pcm_config_mmap_playback = {
181 .channels = DEFAULT_CHANNEL_COUNT,
182 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
183 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800184 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800185 .format = PCM_FORMAT_S16_LE,
186 .start_threshold = MMAP_PERIOD_SIZE*8,
187 .stop_threshold = INT32_MAX,
188 .silence_threshold = 0,
189 .silence_size = 0,
190 .avail_min = MMAP_PERIOD_SIZE, //1 ms
191};
192
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800193struct pcm_config pcm_config_hifi = {
194 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
195 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
196 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
197 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
198 .format = PCM_FORMAT_S24_3LE,
199 .start_threshold = 0,
200 .stop_threshold = INT_MAX,
201 .avail_min = 0,
202};
203
Eric Laurentb23d5282013-05-14 15:27:20 -0700204struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700205 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700206 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
207 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700208 .stop_threshold = INT_MAX,
209 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700210};
211
Haynes Mathew George03c40102016-01-29 17:57:48 -0800212struct pcm_config pcm_config_audio_capture_rt = {
213 .channels = DEFAULT_CHANNEL_COUNT,
214 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
215 .period_size = ULL_PERIOD_SIZE,
216 .period_count = 512,
217 .format = PCM_FORMAT_S16_LE,
218 .start_threshold = 0,
219 .stop_threshold = INT_MAX,
220 .silence_threshold = 0,
221 .silence_size = 0,
222 .avail_min = ULL_PERIOD_SIZE, //1 ms
223};
224
Eric Laurent0e46adf2016-12-16 12:49:24 -0800225struct pcm_config pcm_config_mmap_capture = {
226 .channels = DEFAULT_CHANNEL_COUNT,
227 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
228 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800229 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800230 .format = PCM_FORMAT_S16_LE,
231 .start_threshold = 0,
232 .stop_threshold = INT_MAX,
233 .silence_threshold = 0,
234 .silence_size = 0,
235 .avail_min = MMAP_PERIOD_SIZE, //1 ms
236};
237
vivek mehtaa68fea62017-06-08 19:04:02 -0700238struct pcm_config pcm_config_voip = {
239 .channels = 1,
240 .period_count = 2,
241 .format = PCM_FORMAT_S16_LE,
242 .stop_threshold = INT_MAX,
243 .avail_min = 0,
244};
245
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700246#define AFE_PROXY_CHANNEL_COUNT 2
247#define AFE_PROXY_SAMPLING_RATE 48000
248
jiabinad481a72018-07-23 12:03:17 -0700249#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700250#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
251
252struct pcm_config pcm_config_afe_proxy_playback = {
253 .channels = AFE_PROXY_CHANNEL_COUNT,
254 .rate = AFE_PROXY_SAMPLING_RATE,
255 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
256 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
257 .format = PCM_FORMAT_S16_LE,
258 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
259 .stop_threshold = INT_MAX,
260 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
261};
262
jiabinad481a72018-07-23 12:03:17 -0700263#define AFE_PROXY_RECORD_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700264#define AFE_PROXY_RECORD_PERIOD_COUNT 4
265
266struct pcm_config pcm_config_afe_proxy_record = {
267 .channels = AFE_PROXY_CHANNEL_COUNT,
268 .rate = AFE_PROXY_SAMPLING_RATE,
269 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
270 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
271 .format = PCM_FORMAT_S16_LE,
272 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
jiabin5d0261e2018-05-25 09:43:59 -0700273 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700274 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
275};
276
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700277const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700278 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
279 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -0800280 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800281 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700282 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700283 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700284 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800285 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700286
Eric Laurentb23d5282013-05-14 15:27:20 -0700287 [USECASE_AUDIO_RECORD] = "audio-record",
288 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800289 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700290 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700291
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800292 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
293 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700294
Eric Laurentb23d5282013-05-14 15:27:20 -0700295 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700296 [USECASE_VOICE2_CALL] = "voice2-call",
297 [USECASE_VOLTE_CALL] = "volte-call",
298 [USECASE_QCHAT_CALL] = "qchat-call",
299 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800300 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
301 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700302
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700303 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
304 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
305
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700306 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
307 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700308
309 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
310 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
311 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
312
vivek mehtaa68fea62017-06-08 19:04:02 -0700313 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
314 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200315
316 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700317
318 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700319};
320
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800321
322#define STRING_TO_ENUM(string) { #string, string }
323
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800324struct string_to_enum {
325 const char *name;
326 uint32_t value;
327};
328
Haynes Mathew George569b7482017-05-08 14:44:27 -0700329static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800330 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
331 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
332 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700333 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700334 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700335 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
336 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
337 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
338 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
339 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
340 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
341 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
342 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
343 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800344};
345
Haynes Mathew George5191a852013-09-11 14:19:36 -0700346static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700347static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700348static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700349static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700350//cache last MBDRC cal step level
351static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700352
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800353static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
354static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
355
Haynes Mathew George03c40102016-01-29 17:57:48 -0800356static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
357 int flags __unused)
358{
359 int dir = 0;
360 switch (uc_id) {
361 case USECASE_AUDIO_RECORD_LOW_LATENCY:
362 dir = 1;
363 case USECASE_AUDIO_PLAYBACK_ULL:
364 break;
365 default:
366 return false;
367 }
368
369 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
370 PCM_PLAYBACK : PCM_CAPTURE);
371 if (adev->adm_is_noirq_avail)
372 return adev->adm_is_noirq_avail(adev->adm_data,
373 adev->snd_card, dev_id, dir);
374 return false;
375}
376
377static void register_out_stream(struct stream_out *out)
378{
379 struct audio_device *adev = out->dev;
380 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
381 return;
382
383 if (!adev->adm_register_output_stream)
384 return;
385
386 adev->adm_register_output_stream(adev->adm_data,
387 out->handle,
388 out->flags);
389
390 if (!adev->adm_set_config)
391 return;
392
393 if (out->realtime) {
394 adev->adm_set_config(adev->adm_data,
395 out->handle,
396 out->pcm, &out->config);
397 }
398}
399
400static void register_in_stream(struct stream_in *in)
401{
402 struct audio_device *adev = in->dev;
403 if (!adev->adm_register_input_stream)
404 return;
405
406 adev->adm_register_input_stream(adev->adm_data,
407 in->capture_handle,
408 in->flags);
409
410 if (!adev->adm_set_config)
411 return;
412
413 if (in->realtime) {
414 adev->adm_set_config(adev->adm_data,
415 in->capture_handle,
416 in->pcm,
417 &in->config);
418 }
419}
420
421static void request_out_focus(struct stream_out *out, long ns)
422{
423 struct audio_device *adev = out->dev;
424
Haynes Mathew George03c40102016-01-29 17:57:48 -0800425 if (adev->adm_request_focus_v2) {
426 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
427 } else if (adev->adm_request_focus) {
428 adev->adm_request_focus(adev->adm_data, out->handle);
429 }
430}
431
432static void request_in_focus(struct stream_in *in, long ns)
433{
434 struct audio_device *adev = in->dev;
435
Haynes Mathew George03c40102016-01-29 17:57:48 -0800436 if (adev->adm_request_focus_v2) {
437 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
438 } else if (adev->adm_request_focus) {
439 adev->adm_request_focus(adev->adm_data, in->capture_handle);
440 }
441}
442
443static void release_out_focus(struct stream_out *out, long ns __unused)
444{
445 struct audio_device *adev = out->dev;
446
447 if (adev->adm_abandon_focus)
448 adev->adm_abandon_focus(adev->adm_data, out->handle);
449}
450
451static void release_in_focus(struct stream_in *in, long ns __unused)
452{
453 struct audio_device *adev = in->dev;
454 if (adev->adm_abandon_focus)
455 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
456}
457
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700458static int parse_snd_card_status(struct str_parms * parms, int * card,
459 card_status_t * status)
460{
461 char value[32]={0};
462 char state[32]={0};
463
464 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
465
466 if (ret < 0)
467 return -1;
468
469 // sscanf should be okay as value is of max length 32.
470 // same as sizeof state.
471 if (sscanf(value, "%d,%s", card, state) < 2)
472 return -1;
473
474 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
475 CARD_STATUS_OFFLINE;
476 return 0;
477}
478
vivek mehta40125092017-08-21 18:48:51 -0700479// always call with adev lock held
480void send_gain_dep_calibration_l() {
481 if (last_known_cal_step >= 0)
482 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
483}
484
vivek mehta1a9b7c02015-06-25 11:49:38 -0700485__attribute__ ((visibility ("default")))
486bool audio_hw_send_gain_dep_calibration(int level) {
487 bool ret_val = false;
488 ALOGV("%s: enter ... ", __func__);
489
490 pthread_mutex_lock(&adev_init_lock);
491
492 if (adev != NULL && adev->platform != NULL) {
493 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700494 last_known_cal_step = level;
495 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700496 pthread_mutex_unlock(&adev->lock);
497 } else {
498 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
499 }
500
501 pthread_mutex_unlock(&adev_init_lock);
502
503 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
504 return ret_val;
505}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700506
jasmine cha270b7762018-03-30 15:41:33 +0800507#ifdef MAXXAUDIO_QDSP_ENABLED
508bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
509{
510 bool ret = false;
511 ALOGV("%s: enter ...", __func__);
512
513 pthread_mutex_lock(&adev_init_lock);
514
515 if (adev != NULL && adev->platform != NULL) {
516 pthread_mutex_lock(&adev->lock);
517 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
518 pthread_mutex_unlock(&adev->lock);
519 }
520
521 pthread_mutex_unlock(&adev_init_lock);
522
523 ALOGV("%s: exit with ret %d", __func__, ret);
524 return ret;
525}
526#else
527#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
528#endif
529
vivek mehtaa8d7c922016-05-25 14:40:44 -0700530__attribute__ ((visibility ("default")))
531int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
532 int table_size) {
533 int ret_val = 0;
534 ALOGV("%s: enter ... ", __func__);
535
536 pthread_mutex_lock(&adev_init_lock);
537 if (adev == NULL) {
538 ALOGW("%s: adev is NULL .... ", __func__);
539 goto done;
540 }
541
542 pthread_mutex_lock(&adev->lock);
543 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
544 pthread_mutex_unlock(&adev->lock);
545done:
546 pthread_mutex_unlock(&adev_init_lock);
547 ALOGV("%s: exit ... ", __func__);
548 return ret_val;
549}
550
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700551static bool is_supported_format(audio_format_t format)
552{
Eric Laurent8251ac82014-07-23 11:00:25 -0700553 switch (format) {
554 case AUDIO_FORMAT_MP3:
555 case AUDIO_FORMAT_AAC_LC:
556 case AUDIO_FORMAT_AAC_HE_V1:
557 case AUDIO_FORMAT_AAC_HE_V2:
558 return true;
559 default:
560 break;
561 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700562 return false;
563}
564
juyuchenbe5c67e2018-08-29 17:19:20 +0800565static bool is_supported_24bits_audiosource(audio_source_t source)
566{
567 switch (source) {
568 case AUDIO_SOURCE_UNPROCESSED:
569#ifdef ENABLED_24BITS_CAMCORDER
570 case AUDIO_SOURCE_CAMCORDER:
571#endif
572 return true;
573 default:
574 break;
575 }
576 return false;
577}
578
Haynes Mathew George03c40102016-01-29 17:57:48 -0800579static inline bool is_mmap_usecase(audio_usecase_t uc_id)
580{
581 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
582 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
583}
584
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700585static int get_snd_codec_id(audio_format_t format)
586{
587 int id = 0;
588
Eric Laurent8251ac82014-07-23 11:00:25 -0700589 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700590 case AUDIO_FORMAT_MP3:
591 id = SND_AUDIOCODEC_MP3;
592 break;
593 case AUDIO_FORMAT_AAC:
594 id = SND_AUDIOCODEC_AAC;
595 break;
596 default:
597 ALOGE("%s: Unsupported audio format", __func__);
598 }
599
600 return id;
601}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800602
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800603static int audio_ssr_status(struct audio_device *adev)
604{
605 int ret = 0;
606 struct mixer_ctl *ctl;
607 const char *mixer_ctl_name = "Audio SSR Status";
608
609 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
610 ret = mixer_ctl_get_value(ctl, 0);
611 ALOGD("%s: value: %d", __func__, ret);
612 return ret;
613}
614
vivek mehta4a824772017-06-08 19:05:49 -0700615static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
616{
617 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
618}
619
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800620static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
621{
622 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
623 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
624 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
625 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
626 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
627 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
628
629}
630
631static bool is_a2dp_device(snd_device_t out_snd_device)
632{
633 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
634}
635
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800636int enable_audio_route(struct audio_device *adev,
637 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800638{
yixuanjiang509f0a72018-09-06 18:37:23 +0800639 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700640 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800641
642 if (usecase == NULL)
643 return -EINVAL;
644
645 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
646
yixuanjiang509f0a72018-09-06 18:37:23 +0800647 if (usecase->type == PCM_CAPTURE)
648 snd_device = usecase->in_snd_device;
649 else
650 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530651 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Chafb2ea2c2019-03-04 18:12:47 +0800652 audio_extn_ma_set_device(usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800653 audio_extn_utils_send_audio_calibration(adev, usecase);
Andy Hung11f10e22018-10-19 17:47:12 -0700654
655 // we shouldn't truncate mixer_path
656 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
657 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
658 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800659 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Andy Hung11f10e22018-10-19 17:47:12 -0700660
yixuanjiang509f0a72018-09-06 18:37:23 +0800661 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700662 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700663 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800665 ALOGV("%s: exit", __func__);
666 return 0;
667}
668
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800669int disable_audio_route(struct audio_device *adev,
670 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800671{
yixuanjiang509f0a72018-09-06 18:37:23 +0800672 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700673 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800674
675 if (usecase == NULL)
676 return -EINVAL;
677
678 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800679 if (usecase->type == PCM_CAPTURE)
680 snd_device = usecase->in_snd_device;
681 else
682 snd_device = usecase->out_snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700683
684 // we shouldn't truncate mixer_path
685 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
686 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
687 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800688 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700689 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Andy Hung11f10e22018-10-19 17:47:12 -0700690
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700691 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000692 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800693
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800694 ALOGV("%s: exit", __func__);
695 return 0;
696}
697
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800698int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700699 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800700{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700701 int i, num_devices = 0;
702 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800703 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800704 if (snd_device < SND_DEVICE_MIN ||
705 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800706 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800707 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800708 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700709
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700710 platform_send_audio_calibration(adev->platform, snd_device);
711
vivek mehtade4849c2016-03-03 17:23:38 -0800712 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700713 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700714 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800715 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700716 }
717
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700718 /* due to the possibility of calibration overwrite between listen
719 and audio, notify sound trigger hal before audio calibration is sent */
720 audio_extn_sound_trigger_update_device_status(snd_device,
721 ST_EVENT_SND_DEVICE_BUSY);
722
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700723 if (audio_extn_spkr_prot_is_enabled())
724 audio_extn_spkr_prot_calib_cancel(adev);
725
zhaoyang yin4211fad2015-06-04 21:13:25 +0800726 audio_extn_dsm_feedback_enable(adev, snd_device, true);
727
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700728 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800729 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800730 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700731 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
732 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700733 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800734 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700735 }
736 if (audio_extn_spkr_prot_start_processing(snd_device)) {
737 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800738 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700739 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700740 } else if (platform_can_split_snd_device(snd_device,
741 &num_devices,
742 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700743 for (i = 0; i < num_devices; i++) {
744 enable_snd_device(adev, new_snd_devices[i]);
745 }
vivek mehtab6506412015-08-07 16:55:17 -0700746 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700747 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800748 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
749 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
750 ALOGE(" %s: Invalid sound device returned", __func__);
751 goto on_error;
752 }
Ed Tam70b5c142016-03-21 19:14:29 -0700753
Eric Laurent2e140aa2016-06-30 17:14:46 -0700754 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700755
756 if (is_a2dp_device(snd_device) &&
757 (audio_extn_a2dp_start_playback() < 0)) {
758 ALOGE("%s: failed to configure A2DP control path", __func__);
759 goto on_error;
760 }
761
vivek mehtade4849c2016-03-03 17:23:38 -0800762 audio_route_apply_and_update_path(adev->audio_route, device_name);
763 }
764on_success:
765 adev->snd_dev_ref_cnt[snd_device]++;
766 ret_val = 0;
767on_error:
768 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800769}
770
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800771int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700772 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800773{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700774 int i, num_devices = 0;
775 snd_device_t new_snd_devices[2];
776
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800777 if (snd_device < SND_DEVICE_MIN ||
778 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800779 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800780 return -EINVAL;
781 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700782 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
783 ALOGE("%s: device ref cnt is already 0", __func__);
784 return -EINVAL;
785 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800786 audio_extn_tfa_98xx_disable_speaker(snd_device);
787
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700788 adev->snd_dev_ref_cnt[snd_device]--;
789 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800790 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800791
792 if (is_a2dp_device(snd_device))
793 audio_extn_a2dp_stop_playback();
794
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700795 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800796 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700797 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700798 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
799 audio_extn_spkr_prot_is_enabled()) {
800 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700801
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700802 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
803 // and does not use speaker swap. As this code causes a problem with device enable ref
804 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700805 // when speaker device is disabled, reset swap.
806 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700807 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700808
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700809 } else if (platform_can_split_snd_device(snd_device,
810 &num_devices,
811 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700812 for (i = 0; i < num_devices; i++) {
813 disable_snd_device(adev, new_snd_devices[i]);
814 }
vivek mehtab6506412015-08-07 16:55:17 -0700815 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700816 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800817 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
818 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
819 ALOGE(" %s: Invalid sound device returned", __func__);
820 return -EINVAL;
821 }
822
Eric Laurent2e140aa2016-06-30 17:14:46 -0700823 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800824 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700825 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700826 audio_extn_sound_trigger_update_device_status(snd_device,
827 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700828 }
vivek mehtab6506412015-08-07 16:55:17 -0700829
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800830 return 0;
831}
832
Vignesh Kulothungan64698822018-01-23 11:25:18 -0800833#ifdef DYNAMIC_ECNS_ENABLED
834static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
835 struct stream_in *in,
836 struct audio_effect_config effect_config,
837 unsigned int param_value)
838{
839 char mixer_ctl_name[] = "Audio Effect";
840 long set_values[6];
841
842 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
843 if (!ctl) {
844 ALOGE("%s: Could not get mixer ctl - %s",
845 __func__, mixer_ctl_name);
846 return -EINVAL;
847 }
848
849 set_values[0] = 1; //0:Rx 1:Tx
850 set_values[1] = in->app_type_cfg.app_type;
851 set_values[2] = (long)effect_config.module_id;
852 set_values[3] = (long)effect_config.instance_id;
853 set_values[4] = (long)effect_config.param_id;
854 set_values[5] = param_value;
855
856 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
857
858 return 0;
859
860}
861
862static int update_effect_param_ecns(struct audio_usecase *usecase,
863 unsigned int module_id, int effect_type,
864 unsigned int *param_value)
865{
866 int ret = 0;
867 struct audio_effect_config other_effect_config;
868 struct stream_in *in = NULL;
869
870 if (!usecase)
871 return -EINVAL;
872
873 in = usecase->stream.in;
874
875 /* Get the effect config data of the other effect */
876 ret = platform_get_effect_config_data(usecase->in_snd_device,
877 &other_effect_config,
878 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
879 if (ret < 0) {
880 ALOGE("%s Failed to get effect params %d", __func__, ret);
881 return ret;
882 }
883
884 if (module_id == other_effect_config.module_id) {
885 //Same module id for AEC/NS. Values need to be combined
886 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
887 ((effect_type == EFFECT_NS) && (in->enable_aec)))
888 *param_value |= other_effect_config.param_value;
889 }
890
891 return ret;
892}
893
894static int enable_disable_effect(struct audio_device *adev, struct stream_in *in,
895 int effect_type, bool enable)
896{
897 struct audio_effect_config effect_config;
898 struct audio_usecase *usecase = NULL;
899 int ret = 0;
900 unsigned int param_value = 0;
901
902 if (!in) {
903 ALOGE("%s: Invalid input stream", __func__);
904 return -EINVAL;
905 }
906
907 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
908
909 usecase = get_usecase_from_list(adev, in->usecase);
910
911 ret = platform_get_effect_config_data(usecase->in_snd_device,
912 &effect_config, effect_type);
913 if (ret < 0) {
914 ALOGE("%s Failed to get module id %d", __func__, ret);
915 return ret;
916 }
917 ALOGV("%s: module %d app_type %d usecase->id:%d usecase->in_snd_device:%d",
918 __func__, effect_config.module_id, in->app_type_cfg.app_type,
919 usecase->id, usecase->in_snd_device);
920
921 if (enable)
922 param_value = effect_config.param_value;
923
924 /*Special handling for AEC & NS effects Param values need to be
925 updated if module ids are same*/
926
927 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
928 ret = update_effect_param_ecns(usecase, effect_config.module_id,
929 effect_type, &param_value);
930 if (ret < 0)
931 return ret;
932 }
933
934 ret = send_effect_enable_disable_mixer_ctl(adev, in,
935 effect_config, param_value);
936
937 return ret;
938}
939
940static int check_and_enable_effect(struct audio_device *adev)
941{
942 int ret = 0;
943
944 struct listnode *node;
945 struct stream_in *in = NULL;
946
947 list_for_each(node, &adev->usecase_list)
948 {
949 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
950 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
951 in = usecase->stream.in;
952
953 if (in->standby)
954 continue;
955
956 if (in->enable_aec) {
957 ret = enable_disable_effect(adev, in, EFFECT_AEC, true);
958 }
959
960 if (in->enable_ns &&
961 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
962 ret = enable_disable_effect(adev, in, EFFECT_NS, true);
963 }
964 }
965 }
966
967 return ret;
968}
969#else
970#define enable_disable_effect(w, x, y, z) -ENOSYS
971#define check_and_enable_effect(x) -ENOSYS
972#endif
973
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700974/*
975 legend:
976 uc - existing usecase
977 new_uc - new usecase
978 d1, d11, d2 - SND_DEVICE enums
979 a1, a2 - corresponding ANDROID device enums
980 B, B1, B2 - backend strings
981
982case 1
983 uc->dev d1 (a1) B1
984 new_uc->dev d1 (a1), d2 (a2) B1, B2
985
986 resolution: disable and enable uc->dev on d1
987
988case 2
989 uc->dev d1 (a1) B1
990 new_uc->dev d11 (a1) B1
991
992 resolution: need to switch uc since d1 and d11 are related
993 (e.g. speaker and voice-speaker)
994 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
995
996case 3
997 uc->dev d1 (a1) B1
998 new_uc->dev d2 (a2) B2
999
1000 resolution: no need to switch uc
1001
1002case 4
1003 uc->dev d1 (a1) B
1004 new_uc->dev d2 (a2) B
1005
1006 resolution: disable enable uc-dev on d2 since backends match
1007 we cannot enable two streams on two different devices if they
1008 share the same backend. e.g. if offload is on speaker device using
1009 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1010 using the same backend, offload must also be switched to voice-handset.
1011
1012case 5
1013 uc->dev d1 (a1) B
1014 new_uc->dev d1 (a1), d2 (a2) B
1015
1016 resolution: disable enable uc-dev on d2 since backends match
1017 we cannot enable two streams on two different devices if they
1018 share the same backend.
1019
1020case 6
1021 uc->dev d1 a1 B1
1022 new_uc->dev d2 a1 B2
1023
1024 resolution: no need to switch
1025
1026case 7
1027
1028 uc->dev d1 (a1), d2 (a2) B1, B2
1029 new_uc->dev d1 B1
1030
1031 resolution: no need to switch
1032
1033*/
1034static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
1035 struct audio_usecase *new_uc,
1036 snd_device_t new_snd_device)
1037{
1038 audio_devices_t a1 = uc->stream.out->devices;
1039 audio_devices_t a2 = new_uc->stream.out->devices;
1040
1041 snd_device_t d1 = uc->out_snd_device;
1042 snd_device_t d2 = new_snd_device;
1043
1044 // Treat as a special case when a1 and a2 are not disjoint
1045 if ((a1 != a2) && (a1 & a2)) {
1046 snd_device_t d3[2];
1047 int num_devices = 0;
1048 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
1049 &num_devices,
1050 d3);
1051 if (ret < 0) {
1052 if (ret != -ENOSYS) {
1053 ALOGW("%s failed to split snd_device %d",
1054 __func__,
1055 popcount(a1) > 1 ? d1 : d2);
1056 }
1057 goto end;
1058 }
1059
1060 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1061 // But if it does happen, we need to give priority to d2 if
1062 // the combo devices active on the existing usecase share a backend.
1063 // This is because we cannot have a usecase active on a combo device
1064 // and a new usecase requests one device in this combo pair.
1065 if (platform_check_backends_match(d3[0], d3[1])) {
1066 return d2; // case 5
1067 } else {
1068 return d1; // case 1
1069 }
1070 } else {
1071 if (platform_check_backends_match(d1, d2)) {
1072 return d2; // case 2, 4
1073 } else {
1074 return d1; // case 6, 3
1075 }
1076 }
1077
1078end:
1079 return d2; // return whatever was calculated before.
1080}
1081
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001082static void check_and_route_playback_usecases(struct audio_device *adev,
1083 struct audio_usecase *uc_info,
1084 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001085{
1086 struct listnode *node;
1087 struct audio_usecase *usecase;
1088 bool switch_device[AUDIO_USECASE_MAX];
1089 int i, num_uc_to_switch = 0;
1090
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001091 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
1092 uc_info,
1093 snd_device);
David Linee3fe402017-03-13 10:00:42 -07001094
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001095 /* For a2dp device reconfigure all active sessions
1096 * with new AFE encoder format based on a2dp state
1097 */
1098 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001099 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1100 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001101 audio_extn_a2dp_is_force_device_switch()) {
1102 force_routing = true;
1103 }
1104
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001105 /*
1106 * This function is to make sure that all the usecases that are active on
1107 * the hardware codec backend are always routed to any one device that is
1108 * handled by the hardware codec.
1109 * For example, if low-latency and deep-buffer usecases are currently active
1110 * on speaker and out_set_parameters(headset) is received on low-latency
1111 * output, then we have to make sure deep-buffer is also switched to headset,
1112 * because of the limitation that both the devices cannot be enabled
1113 * at the same time as they share the same backend.
1114 */
1115 /* Disable all the usecases on the shared backend other than the
1116 specified usecase */
1117 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1118 switch_device[i] = false;
1119
1120 list_for_each(node, &adev->usecase_list) {
1121 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001122 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
1123 continue;
1124
1125 if (force_routing ||
1126 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -07001127 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
1128 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001129 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001130 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1131 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -07001132 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001133 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 switch_device[usecase->id] = true;
1135 num_uc_to_switch++;
1136 }
1137 }
1138
1139 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001140 list_for_each(node, &adev->usecase_list) {
1141 usecase = node_to_item(node, struct audio_usecase, list);
1142 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001143 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001144 }
1145 }
1146
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001147 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001148 list_for_each(node, &adev->usecase_list) {
1149 usecase = node_to_item(node, struct audio_usecase, list);
1150 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001151 d_device = derive_playback_snd_device(usecase, uc_info,
1152 snd_device);
1153 enable_snd_device(adev, d_device);
1154 /* Update the out_snd_device before enabling the audio route */
1155 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001156 }
1157 }
1158
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001159 /* Re-route all the usecases on the shared backend other than the
1160 specified usecase to new snd devices */
1161 list_for_each(node, &adev->usecase_list) {
1162 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001163 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001164 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001165 }
1166 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001167 }
1168}
1169
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001170static void check_and_route_capture_usecases(struct audio_device *adev,
1171 struct audio_usecase *uc_info,
1172 snd_device_t snd_device)
1173{
1174 struct listnode *node;
1175 struct audio_usecase *usecase;
1176 bool switch_device[AUDIO_USECASE_MAX];
1177 int i, num_uc_to_switch = 0;
1178
vivek mehta4ed66e62016-04-15 23:33:34 -07001179 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1180
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001181 /*
1182 * This function is to make sure that all the active capture usecases
1183 * are always routed to the same input sound device.
1184 * For example, if audio-record and voice-call usecases are currently
1185 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1186 * is received for voice call then we have to make sure that audio-record
1187 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1188 * because of the limitation that two devices cannot be enabled
1189 * at the same time if they share the same backend.
1190 */
1191 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1192 switch_device[i] = false;
1193
1194 list_for_each(node, &adev->usecase_list) {
1195 usecase = node_to_item(node, struct audio_usecase, list);
1196 if (usecase->type != PCM_PLAYBACK &&
1197 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001198 usecase->in_snd_device != snd_device &&
Carter Hsu0a1160c2018-10-04 09:24:36 +08001199 ((uc_info->type == VOICE_CALL &&
1200 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1201 platform_check_backends_match(snd_device,\
1202 usecase->in_snd_device)) &&
Anish Kumarff864712015-06-03 13:35:11 -07001203 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001204 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1205 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001206 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001207 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001208 switch_device[usecase->id] = true;
1209 num_uc_to_switch++;
1210 }
1211 }
1212
1213 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001214 list_for_each(node, &adev->usecase_list) {
1215 usecase = node_to_item(node, struct audio_usecase, list);
1216 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001217 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001218 }
1219 }
1220
1221 list_for_each(node, &adev->usecase_list) {
1222 usecase = node_to_item(node, struct audio_usecase, list);
1223 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001224 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001225 }
1226 }
1227
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001228 /* Re-route all the usecases on the shared backend other than the
1229 specified usecase to new snd devices */
1230 list_for_each(node, &adev->usecase_list) {
1231 usecase = node_to_item(node, struct audio_usecase, list);
1232 /* Update the in_snd_device only before enabling the audio route */
1233 if (switch_device[usecase->id] ) {
1234 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001235 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001236 }
1237 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001238 }
1239}
1240
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001241/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001242static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001243{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001244 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001245 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001246
1247 switch (channels) {
1248 /*
1249 * Do not handle stereo output in Multi-channel cases
1250 * Stereo case is handled in normal playback path
1251 */
1252 case 6:
1253 ALOGV("%s: HDMI supports 5.1", __func__);
1254 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1255 break;
1256 case 8:
1257 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1258 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1259 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1260 break;
1261 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001262 ALOGE("HDMI does not support multi channel playback");
1263 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001264 break;
1265 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001266 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001267}
1268
Andy Hung18859412017-08-09 11:47:21 -07001269static ssize_t read_usb_sup_sample_rates(bool is_playback,
1270 uint32_t *supported_sample_rates,
1271 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001272{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001273 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1274 supported_sample_rates,
1275 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001276#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001277 for (ssize_t i=0; i<count; i++) {
1278 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1279 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001280 }
1281#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001282 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001283}
1284
Haynes Mathew George569b7482017-05-08 14:44:27 -07001285static int read_usb_sup_channel_masks(bool is_playback,
1286 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001287 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001288{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001289 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001290 int channel_count;
1291 uint32_t num_masks = 0;
1292 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1293 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001294 }
Eric Laurent74b55762017-07-09 17:04:53 -07001295 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001296 // start from 2 channels as framework currently doesn't support mono.
1297 // TODO: consider only supporting channel index masks beyond stereo here.
1298 for (channel_count = FCC_2;
1299 channel_count <= channels && num_masks < max_masks;
1300 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001301 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1302 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001303 for (channel_count = FCC_2;
1304 channel_count <= channels && num_masks < max_masks;
1305 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001306 supported_channel_masks[num_masks++] =
1307 audio_channel_mask_for_index_assignment_from_count(channel_count);
1308 }
1309 } else {
1310 // For capture we report all supported channel masks from 1 channel up.
1311 channel_count = MIN_CHANNEL_COUNT;
1312 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1313 // indexed mask
1314 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
Andy Hung88ce1d92018-10-29 18:31:12 -07001315 const audio_channel_mask_t mask =
Eric Laurent74b55762017-07-09 17:04:53 -07001316 audio_channel_in_mask_from_count(channel_count);
Andy Hung88ce1d92018-10-29 18:31:12 -07001317 supported_channel_masks[num_masks++] = mask;
1318 const audio_channel_mask_t index_mask =
1319 audio_channel_mask_for_index_assignment_from_count(channel_count);
1320 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1321 supported_channel_masks[num_masks++] = index_mask;
1322 }
Eric Laurent74b55762017-07-09 17:04:53 -07001323 }
1324 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001325#ifdef NDEBUG
1326 for (size_t i = 0; i < num_masks; ++i) {
1327 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1328 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1329 }
1330#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001331 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001332}
1333
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001334static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001335 audio_format_t *supported_formats,
1336 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001337{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001338 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001339 switch (bitwidth) {
1340 case 24:
1341 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001342 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001343 break;
1344 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001345 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001346 break;
1347 case 16:
1348 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001349 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001350 break;
1351 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001352 ALOGV("%s: %s supported format %d", __func__,
1353 is_playback ? "P" : "C", bitwidth);
1354 return 1;
1355}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001356
Haynes Mathew George569b7482017-05-08 14:44:27 -07001357static int read_usb_sup_params_and_compare(bool is_playback,
1358 audio_format_t *format,
1359 audio_format_t *supported_formats,
1360 uint32_t max_formats,
1361 audio_channel_mask_t *mask,
1362 audio_channel_mask_t *supported_channel_masks,
1363 uint32_t max_masks,
1364 uint32_t *rate,
1365 uint32_t *supported_sample_rates,
1366 uint32_t max_rates) {
1367 int ret = 0;
1368 int num_formats;
1369 int num_masks;
1370 int num_rates;
1371 int i;
1372
1373 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1374 max_formats);
1375 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1376 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001377
Haynes Mathew George569b7482017-05-08 14:44:27 -07001378 num_rates = read_usb_sup_sample_rates(is_playback,
1379 supported_sample_rates, max_rates);
1380
1381#define LUT(table, len, what, dflt) \
1382 for (i=0; i<len && (table[i] != what); i++); \
1383 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1384
1385 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1386 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1387 LUT(supported_sample_rates, num_rates, *rate, 0);
1388
1389#undef LUT
1390 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001391}
1392
Andy Hungd9653bd2017-08-01 19:31:39 -07001393static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1394{
1395 // Check if usb is ready.
1396 // The usb device may have been removed quickly after insertion and hence
1397 // no longer available. This will show up as empty channel masks, or rates.
1398
1399 pthread_mutex_lock(&adev->lock);
1400 uint32_t supported_sample_rate;
1401
1402 // we consider usb ready if we can fetch at least one sample rate.
1403 const bool ready = read_usb_sup_sample_rates(
1404 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1405 pthread_mutex_unlock(&adev->lock);
1406 return ready;
1407}
1408
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001409static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1410{
1411 struct audio_usecase *usecase;
1412 struct listnode *node;
1413
1414 list_for_each(node, &adev->usecase_list) {
1415 usecase = node_to_item(node, struct audio_usecase, list);
1416 if (usecase->type == VOICE_CALL) {
1417 ALOGV("%s: usecase id %d", __func__, usecase->id);
1418 return usecase->id;
1419 }
1420 }
1421 return USECASE_INVALID;
1422}
1423
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001424struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1425 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001426{
1427 struct audio_usecase *usecase;
1428 struct listnode *node;
1429
1430 list_for_each(node, &adev->usecase_list) {
1431 usecase = node_to_item(node, struct audio_usecase, list);
1432 if (usecase->id == uc_id)
1433 return usecase;
1434 }
1435 return NULL;
1436}
1437
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001438static bool force_device_switch(struct audio_usecase *usecase)
1439{
1440 if (usecase->stream.out == NULL) {
1441 ALOGE("%s: stream.out is NULL", __func__);
1442 return false;
1443 }
1444
1445 // Force all A2DP output devices to reconfigure for proper AFE encode format
1446 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1447 // in suspended state, hence try to trigger a retry when we again get a routing request.
1448 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1449 audio_extn_a2dp_is_force_device_switch()) {
1450 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1451 return true;
1452 }
1453
1454 return false;
1455}
1456
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001457struct stream_in *adev_get_active_input(const struct audio_device *adev)
1458{
1459 struct listnode *node;
1460 struct stream_in *last_active_in = NULL;
1461
1462 /* Get last added active input.
1463 * TODO: We may use a priority mechanism to pick highest priority active source */
1464 list_for_each(node, &adev->usecase_list)
1465 {
1466 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1467 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
1468 last_active_in = usecase->stream.in;
1469 }
1470 }
1471
1472 return last_active_in;
1473}
1474
1475struct stream_in *get_voice_communication_input(const struct audio_device *adev)
1476{
1477 struct listnode *node;
1478
1479 /* First check active inputs with voice communication source and then
1480 * any input if audio mode is in communication */
1481 list_for_each(node, &adev->usecase_list)
1482 {
1483 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1484 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
1485 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1486 return usecase->stream.in;
1487 }
1488 }
1489 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
1490 return adev_get_active_input(adev);
1491 }
1492 return NULL;
1493}
1494
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001495int select_devices(struct audio_device *adev,
1496 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001498 snd_device_t out_snd_device = SND_DEVICE_NONE;
1499 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001500 struct audio_usecase *usecase = NULL;
1501 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001502 struct audio_usecase *hfp_usecase = NULL;
1503 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001504 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001505 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001506 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1507 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001509 usecase = get_usecase_from_list(adev, uc_id);
1510 if (usecase == NULL) {
1511 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1512 return -EINVAL;
1513 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001514
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001515 if ((usecase->type == VOICE_CALL) ||
1516 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001517 out_snd_device = platform_get_output_snd_device(adev->platform,
1518 usecase->stream.out->devices);
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001519 in_snd_device = platform_get_input_snd_device(adev->platform,
1520 NULL,
1521 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001522 usecase->devices = usecase->stream.out->devices;
1523 } else {
1524 /*
1525 * If the voice call is active, use the sound devices of voice call usecase
1526 * so that it would not result any device switch. All the usecases will
1527 * be switched to new device when select_devices() is called for voice call
1528 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001529 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001530 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001531 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001532 vc_usecase = get_usecase_from_list(adev,
1533 get_voice_usecase_id_from_list(adev));
1534 if ((vc_usecase != NULL) &&
1535 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
juyuchend194b432018-11-16 14:15:16 +08001536 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
1537 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001538 in_snd_device = vc_usecase->in_snd_device;
1539 out_snd_device = vc_usecase->out_snd_device;
1540 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001541 } else if (audio_extn_hfp_is_active(adev)) {
1542 hfp_ucid = audio_extn_hfp_get_usecase();
1543 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1544 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1545 in_snd_device = hfp_usecase->in_snd_device;
1546 out_snd_device = hfp_usecase->out_snd_device;
1547 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001548 }
1549 if (usecase->type == PCM_PLAYBACK) {
1550 usecase->devices = usecase->stream.out->devices;
1551 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001552 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001553 struct stream_out *voip_out = adev->primary_output;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001554 struct stream_in *voip_in = get_voice_communication_input(adev);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001555
Eric Laurentb23d5282013-05-14 15:27:20 -07001556 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001557 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001558
1559 if (voip_usecase)
1560 voip_out = voip_usecase->stream.out;
1561
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001562 if (usecase->stream.out == voip_out && voip_in != NULL) {
1563 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001564 }
1565 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001566 } else if (usecase->type == PCM_CAPTURE) {
1567 usecase->devices = usecase->stream.in->device;
1568 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001569 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001570 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001571 struct stream_in *voip_in = get_voice_communication_input(adev);
1572
1573 if (voip_in != NULL) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001574
1575 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1576 USECASE_AUDIO_PLAYBACK_VOIP);
1577
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001578 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001579 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1580 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001581 } else if (voip_usecase) {
1582 out_device = voip_usecase->stream.out->devices;
juyuchend194b432018-11-16 14:15:16 +08001583 } else if (adev->primary_output &&
1584 !adev->primary_output->standby) {
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001585 out_device = adev->primary_output->devices;
juyuchend194b432018-11-16 14:15:16 +08001586 } else {
1587 /* forcing speaker o/p device to get matching i/p pair
1588 in case o/p is not routed from same primary HAL */
1589 out_device = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001590 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001591 }
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001592 in_snd_device = platform_get_input_snd_device(adev->platform,
1593 usecase->stream.in,
1594 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001595 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001596 }
1597 }
1598
1599 if (out_snd_device == usecase->out_snd_device &&
1600 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001601 if (!force_device_switch(usecase))
1602 return 0;
1603 }
1604
1605 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1606 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1607 return 0;
1608 }
1609
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001610 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1611 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001612 (!audio_extn_a2dp_is_ready())) {
1613 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001614 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1615 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1616 else
1617 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001618 }
1619
juyuchen66c4ecf2018-08-06 15:39:34 +08001620 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1621 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1622 }
1623
Eric Laurent2bafff12016-03-17 12:17:23 -07001624 if (out_snd_device != SND_DEVICE_NONE &&
1625 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1626 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1627 __func__,
1628 use_case_table[uc_id],
1629 adev->last_logged_snd_device[uc_id][0],
1630 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1631 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1632 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1633 -1,
1634 out_snd_device,
1635 platform_get_snd_device_name(out_snd_device),
1636 platform_get_snd_device_acdb_id(out_snd_device));
1637 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1638 }
1639 if (in_snd_device != SND_DEVICE_NONE &&
1640 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1641 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1642 __func__,
1643 use_case_table[uc_id],
1644 adev->last_logged_snd_device[uc_id][1],
1645 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1646 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1647 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1648 -1,
1649 in_snd_device,
1650 platform_get_snd_device_name(in_snd_device),
1651 platform_get_snd_device_acdb_id(in_snd_device));
1652 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1653 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001654
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655 /*
1656 * Limitation: While in call, to do a device switch we need to disable
1657 * and enable both RX and TX devices though one of them is same as current
1658 * device.
1659 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001660 if ((usecase->type == VOICE_CALL) &&
1661 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1662 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001663 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001664 /* Disable sidetone only if voice call already exists */
1665 if (voice_is_call_state_active(adev))
1666 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001667 }
1668
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001669 /* Disable current sound devices */
1670 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001671 disable_audio_route(adev, usecase);
1672 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673 }
1674
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001675 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001676 disable_audio_route(adev, usecase);
1677 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678 }
1679
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001680 /* Applicable only on the targets that has external modem.
1681 * New device information should be sent to modem before enabling
1682 * the devices to reduce in-call device switch time.
1683 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001684 if ((usecase->type == VOICE_CALL) &&
1685 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1686 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001687 status = platform_switch_voice_call_enable_device_config(adev->platform,
1688 out_snd_device,
1689 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001690 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001691
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001692 /* Enable new sound devices */
1693 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001694 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001695 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1696 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001697 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001698 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001699 }
1700
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001701 if (in_snd_device != SND_DEVICE_NONE) {
1702 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001703 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001704 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001705
Eric Laurentb23d5282013-05-14 15:27:20 -07001706 if (usecase->type == VOICE_CALL)
1707 status = platform_switch_voice_call_device_post(adev->platform,
1708 out_snd_device,
1709 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001710
sangwoo170731f2013-06-08 15:36:36 +09001711 usecase->in_snd_device = in_snd_device;
1712 usecase->out_snd_device = out_snd_device;
1713
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001714 audio_extn_tfa_98xx_set_mode();
1715
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001716 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001717
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001718 /* If input stream is already running the effect needs to be
1719 applied on the new input device that's being enabled here. */
1720 if (in_snd_device != SND_DEVICE_NONE)
1721 check_and_enable_effect(adev);
1722
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001723 /* Applicable only on the targets that has external modem.
1724 * Enable device command should be sent to modem only after
1725 * enabling voice call mixer controls
1726 */
vivek mehta765eb642015-08-07 19:46:06 -07001727 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001728 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1729 out_snd_device,
1730 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001731 /* Enable sidetone only if voice call already exists */
1732 if (voice_is_call_state_active(adev))
1733 voice_set_sidetone(adev, out_snd_device, true);
1734 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001735
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001736 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001737 struct stream_out *voip_out = voip_usecase->stream.out;
1738 audio_extn_utils_send_app_type_gain(adev,
1739 voip_out->app_type_cfg.app_type,
1740 &voip_out->app_type_cfg.gain[0]);
1741 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742 return status;
1743}
1744
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745static int stop_input_stream(struct stream_in *in)
1746{
1747 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748 struct audio_usecase *uc_info;
1749 struct audio_device *adev = in->dev;
1750
Eric Laurent994a6932013-07-17 11:51:42 -07001751 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001752 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754 uc_info = get_usecase_from_list(adev, in->usecase);
1755 if (uc_info == NULL) {
1756 ALOGE("%s: Could not find the usecase (%d) in the list",
1757 __func__, in->usecase);
1758 return -EINVAL;
1759 }
1760
vivek mehta781065c2017-04-04 12:55:01 -07001761 /* Close in-call recording streams */
1762 voice_check_and_stop_incall_rec_usecase(adev, in);
1763
Eric Laurent150dbfe2013-02-27 14:31:02 -08001764 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001765 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001766
1767 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001768 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001770 list_remove(&uc_info->list);
1771 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001772
Eric Laurent994a6932013-07-17 11:51:42 -07001773 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774 return ret;
1775}
1776
1777int start_input_stream(struct stream_in *in)
1778{
1779 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001780 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781 struct audio_usecase *uc_info;
1782 struct audio_device *adev = in->dev;
1783
Eric Laurent994a6932013-07-17 11:51:42 -07001784 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001785
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001786 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1787 return -EIO;
1788
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001789 if (in->card_status == CARD_STATUS_OFFLINE ||
1790 adev->card_status == CARD_STATUS_OFFLINE) {
1791 ALOGW("in->card_status or adev->card_status offline, try again");
1792 ret = -EAGAIN;
1793 goto error_config;
1794 }
1795
vivek mehta781065c2017-04-04 12:55:01 -07001796 /* Check if source matches incall recording usecase criteria */
1797 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1798 if (ret)
1799 goto error_config;
1800 else
1801 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1802
Eric Laurentb23d5282013-05-14 15:27:20 -07001803 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804 if (in->pcm_device_id < 0) {
1805 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1806 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001807 ret = -EINVAL;
1808 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001810
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1812 uc_info->id = in->usecase;
1813 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001814 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001815 uc_info->devices = in->device;
1816 uc_info->in_snd_device = SND_DEVICE_NONE;
1817 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001819 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001820
Wei Wangf4837d52017-11-21 14:51:20 -08001821 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001822 audio_extn_perf_lock_acquire();
1823
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001824 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825
Eric Laurent0e46adf2016-12-16 12:49:24 -08001826 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001827 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001828 ALOGE("%s: pcm stream not ready", __func__);
1829 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001830 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001831 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001832 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001833 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1834 goto error_open;
1835 }
1836 } else {
1837 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1838 unsigned int pcm_open_retry_count = 0;
1839
1840 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1841 flags |= PCM_MMAP | PCM_NOIRQ;
1842 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1843 } else if (in->realtime) {
1844 flags |= PCM_MMAP | PCM_NOIRQ;
1845 }
1846
1847 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1848 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1849
1850 while (1) {
1851 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1852 flags, &in->config);
1853 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1854 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1855 if (in->pcm != NULL) {
1856 pcm_close(in->pcm);
1857 in->pcm = NULL;
1858 }
1859 if (pcm_open_retry_count-- == 0) {
1860 ret = -EIO;
1861 goto error_open;
1862 }
1863 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1864 continue;
1865 }
1866 break;
1867 }
1868
1869 ALOGV("%s: pcm_prepare", __func__);
1870 ret = pcm_prepare(in->pcm);
1871 if (ret < 0) {
1872 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001873 pcm_close(in->pcm);
1874 in->pcm = NULL;
1875 goto error_open;
1876 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001877 if (in->realtime) {
1878 ret = pcm_start(in->pcm);
1879 if (ret < 0) {
1880 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1881 pcm_close(in->pcm);
1882 in->pcm = NULL;
1883 goto error_open;
1884 }
1885 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001886 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001887 register_in_stream(in);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001888 check_and_enable_effect(adev);
Wei Wangf4837d52017-11-21 14:51:20 -08001889 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001890 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001891 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001892
Eric Laurent0e46adf2016-12-16 12:49:24 -08001893 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001894
1895error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001896 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001897 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001898 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001899
1900error_config:
Eric Laurent2bafff12016-03-17 12:17:23 -07001901 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001902 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001903}
1904
Eric Laurenta1478072015-09-21 17:21:52 -07001905void lock_input_stream(struct stream_in *in)
1906{
1907 pthread_mutex_lock(&in->pre_lock);
1908 pthread_mutex_lock(&in->lock);
1909 pthread_mutex_unlock(&in->pre_lock);
1910}
1911
1912void lock_output_stream(struct stream_out *out)
1913{
1914 pthread_mutex_lock(&out->pre_lock);
1915 pthread_mutex_lock(&out->lock);
1916 pthread_mutex_unlock(&out->pre_lock);
1917}
1918
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001919/* must be called with out->lock locked */
1920static int send_offload_cmd_l(struct stream_out* out, int command)
1921{
1922 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1923
1924 ALOGVV("%s %d", __func__, command);
1925
1926 cmd->cmd = command;
1927 list_add_tail(&out->offload_cmd_list, &cmd->node);
1928 pthread_cond_signal(&out->offload_cond);
1929 return 0;
1930}
1931
1932/* must be called iwth out->lock locked */
1933static void stop_compressed_output_l(struct stream_out *out)
1934{
1935 out->offload_state = OFFLOAD_STATE_IDLE;
1936 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001937 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001938 if (out->compr != NULL) {
1939 compress_stop(out->compr);
1940 while (out->offload_thread_blocked) {
1941 pthread_cond_wait(&out->cond, &out->lock);
1942 }
1943 }
1944}
1945
1946static void *offload_thread_loop(void *context)
1947{
1948 struct stream_out *out = (struct stream_out *) context;
1949 struct listnode *item;
1950
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001951 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1952 set_sched_policy(0, SP_FOREGROUND);
1953 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1954
1955 ALOGV("%s", __func__);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001956
Eric Laurenta1478072015-09-21 17:21:52 -07001957 lock_output_stream(out);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001958 out->offload_state = OFFLOAD_STATE_IDLE;
1959 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001960 for (;;) {
1961 struct offload_cmd *cmd = NULL;
1962 stream_callback_event_t event;
1963 bool send_callback = false;
1964
1965 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1966 __func__, list_empty(&out->offload_cmd_list),
1967 out->offload_state);
1968 if (list_empty(&out->offload_cmd_list)) {
1969 ALOGV("%s SLEEPING", __func__);
1970 pthread_cond_wait(&out->offload_cond, &out->lock);
1971 ALOGV("%s RUNNING", __func__);
1972 continue;
1973 }
1974
1975 item = list_head(&out->offload_cmd_list);
1976 cmd = node_to_item(item, struct offload_cmd, node);
1977 list_remove(item);
1978
1979 ALOGVV("%s STATE %d CMD %d out->compr %p",
1980 __func__, out->offload_state, cmd->cmd, out->compr);
1981
1982 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1983 free(cmd);
1984 break;
1985 }
1986
1987 if (out->compr == NULL) {
1988 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001989 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001990 pthread_cond_signal(&out->cond);
1991 continue;
1992 }
1993 out->offload_thread_blocked = true;
1994 pthread_mutex_unlock(&out->lock);
1995 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001996 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001997 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1998 compress_wait(out->compr, -1);
1999 send_callback = true;
2000 event = STREAM_CBK_EVENT_WRITE_READY;
2001 break;
2002 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002003 compress_next_track(out->compr);
2004 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002005 send_callback = true;
2006 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002007 /* Resend the metadata for next iteration */
2008 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002009 break;
2010 case OFFLOAD_CMD_DRAIN:
2011 compress_drain(out->compr);
2012 send_callback = true;
2013 event = STREAM_CBK_EVENT_DRAIN_READY;
2014 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002015 case OFFLOAD_CMD_ERROR:
2016 send_callback = true;
2017 event = STREAM_CBK_EVENT_ERROR;
2018 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002019 default:
2020 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2021 break;
2022 }
Eric Laurenta1478072015-09-21 17:21:52 -07002023 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002024 out->offload_thread_blocked = false;
2025 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07002026 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002027 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002028 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002029 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002030 free(cmd);
2031 }
2032
2033 pthread_cond_signal(&out->cond);
2034 while (!list_empty(&out->offload_cmd_list)) {
2035 item = list_head(&out->offload_cmd_list);
2036 list_remove(item);
2037 free(node_to_item(item, struct offload_cmd, node));
2038 }
2039 pthread_mutex_unlock(&out->lock);
2040
2041 return NULL;
2042}
2043
2044static int create_offload_callback_thread(struct stream_out *out)
2045{
2046 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2047 list_init(&out->offload_cmd_list);
2048 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2049 offload_thread_loop, out);
2050 return 0;
2051}
2052
2053static int destroy_offload_callback_thread(struct stream_out *out)
2054{
Eric Laurenta1478072015-09-21 17:21:52 -07002055 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002056 stop_compressed_output_l(out);
2057 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2058
2059 pthread_mutex_unlock(&out->lock);
2060 pthread_join(out->offload_thread, (void **) NULL);
2061 pthread_cond_destroy(&out->offload_cond);
2062
2063 return 0;
2064}
2065
Eric Laurent07eeafd2013-10-06 12:52:49 -07002066static bool allow_hdmi_channel_config(struct audio_device *adev)
2067{
2068 struct listnode *node;
2069 struct audio_usecase *usecase;
2070 bool ret = true;
2071
2072 list_for_each(node, &adev->usecase_list) {
2073 usecase = node_to_item(node, struct audio_usecase, list);
2074 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2075 /*
2076 * If voice call is already existing, do not proceed further to avoid
2077 * disabling/enabling both RX and TX devices, CSD calls, etc.
2078 * Once the voice call done, the HDMI channels can be configured to
2079 * max channels of remaining use cases.
2080 */
2081 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08002082 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07002083 __func__);
2084 ret = false;
2085 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002086 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
2087 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07002088 "no change in HDMI channels", __func__);
2089 ret = false;
2090 break;
2091 }
2092 }
2093 }
2094 return ret;
2095}
2096
2097static int check_and_set_hdmi_channels(struct audio_device *adev,
2098 unsigned int channels)
2099{
2100 struct listnode *node;
2101 struct audio_usecase *usecase;
2102
2103 /* Check if change in HDMI channel config is allowed */
2104 if (!allow_hdmi_channel_config(adev))
2105 return 0;
2106
2107 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08002108 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002109 return 0;
2110 }
2111
2112 platform_set_hdmi_channels(adev->platform, channels);
2113 adev->cur_hdmi_channels = channels;
2114
2115 /*
2116 * Deroute all the playback streams routed to HDMI so that
2117 * the back end is deactivated. Note that backend will not
2118 * be deactivated if any one stream is connected to it.
2119 */
2120 list_for_each(node, &adev->usecase_list) {
2121 usecase = node_to_item(node, struct audio_usecase, list);
2122 if (usecase->type == PCM_PLAYBACK &&
2123 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002124 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002125 }
2126 }
2127
2128 /*
2129 * Enable all the streams disabled above. Now the HDMI backend
2130 * will be activated with new channel configuration
2131 */
2132 list_for_each(node, &adev->usecase_list) {
2133 usecase = node_to_item(node, struct audio_usecase, list);
2134 if (usecase->type == PCM_PLAYBACK &&
2135 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002136 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002137 }
2138 }
2139
2140 return 0;
2141}
2142
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002143static int check_and_set_usb_service_interval(struct audio_device *adev,
2144 struct audio_usecase *uc_info,
2145 bool min)
2146{
2147 struct listnode *node;
2148 struct audio_usecase *usecase;
2149 bool switch_usecases = false;
2150 bool reconfig = false;
2151
2152 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
2153 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
2154 return -1;
2155
2156 /* set if the valid usecase do not already exist */
2157 list_for_each(node, &adev->usecase_list) {
2158 usecase = node_to_item(node, struct audio_usecase, list);
2159 if (usecase->type == PCM_PLAYBACK &&
2160 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
2161 switch (usecase->id) {
2162 case USECASE_AUDIO_PLAYBACK_MMAP:
2163 case USECASE_AUDIO_PLAYBACK_ULL:
2164 // cannot reconfig while mmap/ull is present.
2165 return -1;
2166 default:
2167 switch_usecases = true;
2168 break;
2169 }
2170 }
2171 if (switch_usecases)
2172 break;
2173 }
2174 /*
2175 * client can try to set service interval in start_output_stream
2176 * to min or to 0 (i.e reset) in stop_output_stream .
2177 */
2178 unsigned long service_interval =
2179 audio_extn_usb_find_service_interval(min, true /*playback*/);
2180 int ret = platform_set_usb_service_interval(adev->platform,
2181 true /*playback*/,
2182 service_interval,
2183 &reconfig);
2184 /* no change or not supported or no active usecases */
2185 if (ret || !reconfig || !switch_usecases)
2186 return -1;
2187 return 0;
2188#undef VALID_USECASE
2189}
2190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002191static int stop_output_stream(struct stream_out *out)
2192{
2193 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194 struct audio_usecase *uc_info;
2195 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08002196 bool has_voip_usecase =
2197 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198
Eric Laurent994a6932013-07-17 11:51:42 -07002199 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002200 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002201 uc_info = get_usecase_from_list(adev, out->usecase);
2202 if (uc_info == NULL) {
2203 ALOGE("%s: Could not find the usecase (%d) in the list",
2204 __func__, out->usecase);
2205 return -EINVAL;
2206 }
2207
Haynes Mathew George41f86652014-06-17 14:22:15 -07002208 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2209 if (adev->visualizer_stop_output != NULL)
2210 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
2211 if (adev->offload_effects_stop_output != NULL)
2212 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002213 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2214 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2215 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07002216 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002217
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002218 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2219 voice_set_device_mute_flag(adev, false);
2220
Eric Laurent150dbfe2013-02-27 14:31:02 -08002221 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002222 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002223
2224 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002225 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002227 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228
Eric Laurent0499d4f2014-08-25 22:39:29 -05002229 audio_extn_extspk_update(adev->extspk);
2230
Eric Laurent07eeafd2013-10-06 12:52:49 -07002231 /* Must be called after removing the usecase from list */
2232 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2233 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002234 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002235 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2236 if (ret == 0) {
2237 /* default service interval was successfully updated,
2238 reopen USB backend with new service interval */
2239 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2240 }
2241 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002242 }
juyuchend194b432018-11-16 14:15:16 +08002243 /* 1) media + voip output routing to handset must route media back to
2244 speaker when voip stops.
2245 2) trigger voip input to reroute when voip output changes to
2246 hearing aid. */
HW Lee88512e92018-06-12 15:26:09 +08002247 if (has_voip_usecase ||
2248 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2249 struct listnode *node;
2250 struct audio_usecase *usecase;
2251 list_for_each(node, &adev->usecase_list) {
2252 usecase = node_to_item(node, struct audio_usecase, list);
juyuchend194b432018-11-16 14:15:16 +08002253 if ((usecase->type == PCM_CAPTURE &&
2254 usecase->id != USECASE_AUDIO_RECORD_VOIP)
2255 || usecase == uc_info)
HW Lee88512e92018-06-12 15:26:09 +08002256 continue;
2257
2258 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2259 __func__, usecase->id, use_case_table[usecase->id],
2260 out->usecase, use_case_table[out->usecase]);
2261 select_devices(adev, usecase->id);
2262 }
2263 }
2264
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002265 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002266 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002267 return ret;
2268}
2269
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002270struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
2271 unsigned int flags, unsigned int pcm_open_retry_count,
2272 struct pcm_config *config)
2273{
2274 struct pcm* pcm = NULL;
2275
2276 while (1) {
2277 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
2278 if (pcm == NULL || !pcm_is_ready(pcm)) {
2279 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
2280 if (pcm != NULL) {
2281 pcm_close(pcm);
2282 pcm = NULL;
2283 }
2284 if (pcm_open_retry_count-- == 0)
2285 return NULL;
2286
2287 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2288 continue;
2289 }
2290 break;
2291 }
2292
2293 if (pcm_is_ready(pcm)) {
2294 int ret = pcm_prepare(pcm);
2295 if (ret < 0) {
2296 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2297 pcm_close(pcm);
2298 pcm = NULL;
2299 }
2300 }
2301
2302 return pcm;
2303}
2304
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305int start_output_stream(struct stream_out *out)
2306{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002307 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002308 struct audio_usecase *uc_info;
2309 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002310 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002311
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002312 ALOGV("%s: enter: usecase(%d: %s) %s devices(%#x)",
2313 __func__, out->usecase, use_case_table[out->usecase],
2314 out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS ? "(with haptics)" : "",
2315 out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002316
2317 if (out->card_status == CARD_STATUS_OFFLINE ||
2318 adev->card_status == CARD_STATUS_OFFLINE) {
2319 ALOGW("out->card_status or adev->card_status offline, try again");
2320 ret = -EAGAIN;
2321 goto error_config;
2322 }
2323
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002324 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2325 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002326 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002327 a2dp_combo = true;
2328 } else {
2329 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2330 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2331 ret = -EAGAIN;
2332 goto error_config;
2333 }
2334 }
2335 }
2336 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002337 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002338 if (out->pcm_device_id < 0) {
2339 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2340 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002341 ret = -EINVAL;
2342 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343 }
2344
2345 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2346 uc_info->id = out->usecase;
2347 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002348 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002349 uc_info->devices = out->devices;
2350 uc_info->in_snd_device = SND_DEVICE_NONE;
2351 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352
Eric Laurent07eeafd2013-10-06 12:52:49 -07002353 /* This must be called before adding this usecase to the list */
2354 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2355 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002356 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2357 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2358 /* USB backend is not reopened immediately.
2359 This is eventually done as part of select_devices */
2360 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002361
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002362 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363
Wei Wangf4837d52017-11-21 14:51:20 -08002364 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002365 audio_extn_perf_lock_acquire();
2366
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002367 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2368 (!audio_extn_a2dp_is_ready())) {
2369 if (!a2dp_combo) {
2370 check_a2dp_restore_l(adev, out, false);
2371 } else {
2372 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002373 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2374 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2375 else
2376 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002377 select_devices(adev, out->usecase);
2378 out->devices = dev;
2379 }
2380 } else {
2381 select_devices(adev, out->usecase);
2382 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002383
Eric Laurent0499d4f2014-08-25 22:39:29 -05002384 audio_extn_extspk_update(adev->extspk);
2385
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002386 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2387 voice_set_device_mute_flag(adev, true);
2388
Andy Hung31aca912014-03-20 17:14:59 -07002389 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002390 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002391 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2392 out->pcm = NULL;
2393 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2394 COMPRESS_IN, &out->compr_config);
2395 if (out->compr && !is_compress_ready(out->compr)) {
2396 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2397 compress_close(out->compr);
2398 out->compr = NULL;
2399 ret = -EIO;
2400 goto error_open;
2401 }
2402 if (out->offload_callback)
2403 compress_nonblock(out->compr, out->non_blocking);
2404
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002405 if (adev->visualizer_start_output != NULL) {
2406 int capture_device_id =
2407 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2408 PCM_CAPTURE);
2409 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2410 adev->snd_card, capture_device_id);
2411 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002412 if (adev->offload_effects_start_output != NULL)
2413 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2414 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002415 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002416 ALOGE("%s: pcm stream not ready", __func__);
2417 goto error_open;
2418 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002419 ret = pcm_start(out->pcm);
2420 if (ret < 0) {
2421 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2422 goto error_open;
2423 }
2424 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002425 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002426 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002427
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002428 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2429 flags |= PCM_MMAP | PCM_NOIRQ;
2430 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002431 } else if (out->realtime) {
2432 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002433 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002434
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002435 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
2436 flags, pcm_open_retry_count,
2437 &(out->config));
2438 if (out->pcm == NULL) {
2439 ret = -EIO;
2440 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002441 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002442
2443 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2444 if (adev->haptic_pcm != NULL) {
2445 pcm_close(adev->haptic_pcm);
2446 adev->haptic_pcm = NULL;
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002447 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002448 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
2449 adev->haptic_pcm_device_id,
2450 flags, pcm_open_retry_count,
2451 &(adev->haptics_config));
2452 // failure to open haptics pcm shouldnt stop audio,
2453 // so do not close audio pcm in case of error
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002454 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002455
Eric Laurent0e46adf2016-12-16 12:49:24 -08002456 if (out->realtime) {
2457 ret = pcm_start(out->pcm);
2458 if (ret < 0) {
2459 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2460 pcm_close(out->pcm);
2461 out->pcm = NULL;
2462 goto error_open;
2463 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002464 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002465 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002466
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002467 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002468 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002469 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002470 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002471
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002472 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2473 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2474 audio_low_latency_hint_start();
2475 }
2476
vivek mehtae59cfb22017-06-16 15:57:11 -07002477 // consider a scenario where on pause lower layers are tear down.
2478 // so on resume, swap mixer control need to be sent only when
2479 // backend is active, hence rather than sending from enable device
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002480 // sending it from start of stream
vivek mehtae59cfb22017-06-16 15:57:11 -07002481
2482 platform_set_swap_channels(adev, true);
2483
Eric Laurent994a6932013-07-17 11:51:42 -07002484 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002485 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002486error_open:
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002487 if (adev->haptic_pcm) {
2488 pcm_close(adev->haptic_pcm);
2489 adev->haptic_pcm = NULL;
2490 }
Wei Wangf4837d52017-11-21 14:51:20 -08002491 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002492 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002494error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002495 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496}
2497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498static int check_input_parameters(uint32_t sample_rate,
2499 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002500 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002502 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2503 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002504 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2505 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002506 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2507 return -EINVAL;
2508 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509
Eric Laurent74b55762017-07-09 17:04:53 -07002510 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2511 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002512 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002513 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002514 return -EINVAL;
2515 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516
2517 switch (sample_rate) {
2518 case 8000:
2519 case 11025:
2520 case 12000:
2521 case 16000:
2522 case 22050:
2523 case 24000:
2524 case 32000:
2525 case 44100:
2526 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002527 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528 break;
2529 default:
vivek mehtadae44712015-07-27 14:13:18 -07002530 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002531 return -EINVAL;
2532 }
2533
2534 return 0;
2535}
2536
Kevin Rocarda325aa22018-04-03 09:15:52 -07002537/** Add a value in a list if not already present.
2538 * @return true if value was successfully inserted or already present,
2539 * false if the list is full and does not contain the value.
2540 */
2541static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2542 for (size_t i = 0; i < list_length; i++) {
2543 if (list[i] == value) return true; // value is already present
2544 if (list[i] == 0) { // no values in this slot
2545 list[i] = value;
2546 return true; // value inserted
2547 }
2548 }
2549 return false; // could not insert value
2550}
2551
2552/** Add channel_mask in supported_channel_masks if not already present.
2553 * @return true if channel_mask was successfully inserted or already present,
2554 * false if supported_channel_masks is full and does not contain channel_mask.
2555 */
2556static void register_channel_mask(audio_channel_mask_t channel_mask,
2557 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2558 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2559 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2560}
2561
2562/** Add format in supported_formats if not already present.
2563 * @return true if format was successfully inserted or already present,
2564 * false if supported_formats is full and does not contain format.
2565 */
2566static void register_format(audio_format_t format,
2567 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2568 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2569 "%s: stream can not declare supporting its format %x", __func__, format);
2570}
2571/** Add sample_rate in supported_sample_rates if not already present.
2572 * @return true if sample_rate was successfully inserted or already present,
2573 * false if supported_sample_rates is full and does not contain sample_rate.
2574 */
2575static void register_sample_rate(uint32_t sample_rate,
2576 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2577 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2578 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2579}
2580
vivek mehtaa68fea62017-06-08 19:04:02 -07002581static size_t get_stream_buffer_size(size_t duration_ms,
2582 uint32_t sample_rate,
2583 audio_format_t format,
2584 int channel_count,
2585 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586{
2587 size_t size = 0;
2588
vivek mehtaa68fea62017-06-08 19:04:02 -07002589 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002590 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002591 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002592
2593 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594
Glenn Kasten4f993392014-05-14 07:30:48 -07002595 /* make sure the size is multiple of 32 bytes
2596 * At 48 kHz mono 16-bit PCM:
2597 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2598 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2599 */
2600 size += 0x1f;
2601 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002602
2603 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604}
2605
2606static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2607{
2608 struct stream_out *out = (struct stream_out *)stream;
2609
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002610 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611}
2612
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002613static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614{
2615 return -ENOSYS;
2616}
2617
2618static size_t out_get_buffer_size(const struct audio_stream *stream)
2619{
2620 struct stream_out *out = (struct stream_out *)stream;
2621
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002622 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2623 return out->compr_config.fragment_size;
2624 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002625 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002626 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627}
2628
2629static uint32_t out_get_channels(const struct audio_stream *stream)
2630{
2631 struct stream_out *out = (struct stream_out *)stream;
2632
2633 return out->channel_mask;
2634}
2635
2636static audio_format_t out_get_format(const struct audio_stream *stream)
2637{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002638 struct stream_out *out = (struct stream_out *)stream;
2639
2640 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641}
2642
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002643static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644{
2645 return -ENOSYS;
2646}
2647
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002648/* must be called with out->lock locked */
2649static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650{
2651 struct stream_out *out = (struct stream_out *)stream;
2652 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002653 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002654
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002656 if (adev->adm_deregister_stream)
2657 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002658 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002660 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2661 if (out->pcm) {
2662 pcm_close(out->pcm);
2663 out->pcm = NULL;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002664
2665 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2666 if (adev->haptic_pcm) {
2667 pcm_close(adev->haptic_pcm);
2668 adev->haptic_pcm = NULL;
2669 }
2670
2671 if (adev->haptic_buffer != NULL) {
2672 free(adev->haptic_buffer);
2673 adev->haptic_buffer = NULL;
2674 adev->haptic_buffer_size = 0;
2675 }
2676 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002677 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002678 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002679 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002680 out->playback_started = false;
2681 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002682 } else {
2683 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002684 out->gapless_mdata.encoder_delay = 0;
2685 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002686 if (out->compr != NULL) {
2687 compress_close(out->compr);
2688 out->compr = NULL;
2689 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002690 }
Phil Burkbc991042017-02-24 08:06:44 -08002691 if (do_stop) {
2692 stop_output_stream(out);
2693 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002694 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002696 return 0;
2697}
2698
2699static int out_standby(struct audio_stream *stream)
2700{
2701 struct stream_out *out = (struct stream_out *)stream;
2702
2703 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2704 out->usecase, use_case_table[out->usecase]);
2705
2706 lock_output_stream(out);
2707 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002709 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710 return 0;
2711}
2712
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002713static int out_on_error(struct audio_stream *stream)
2714{
2715 struct stream_out *out = (struct stream_out *)stream;
2716 struct audio_device *adev = out->dev;
2717 bool do_standby = false;
2718
2719 lock_output_stream(out);
2720 if (!out->standby) {
2721 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2722 stop_compressed_output_l(out);
2723 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2724 } else
2725 do_standby = true;
2726 }
2727 pthread_mutex_unlock(&out->lock);
2728
2729 if (do_standby)
2730 return out_standby(&out->stream.common);
2731
2732 return 0;
2733}
2734
Andy Hung7401c7c2016-09-21 12:41:21 -07002735static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736{
Andy Hung7401c7c2016-09-21 12:41:21 -07002737 struct stream_out *out = (struct stream_out *)stream;
2738
2739 // We try to get the lock for consistency,
2740 // but it isn't necessary for these variables.
2741 // If we're not in standby, we may be blocked on a write.
2742 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2743 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2744 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2745
Andy Hung572633e2019-02-19 11:58:24 -08002746 char buffer[256]; // for statistics formatting
2747 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
2748 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
2749
Andy Hung241e36f2019-02-19 12:00:38 -08002750 if (out->start_latency_ms.n > 0) {
2751 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
2752 dprintf(fd, " Start latency ms: %s\n", buffer);
2753 }
2754
Andy Hung7401c7c2016-09-21 12:41:21 -07002755 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002756 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002757 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002758
2759 // dump error info
2760 (void)error_log_dump(
2761 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002762
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002763 return 0;
2764}
2765
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002766static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2767{
2768 int ret = 0;
2769 char value[32];
2770 struct compr_gapless_mdata tmp_mdata;
2771
2772 if (!out || !parms) {
2773 return -EINVAL;
2774 }
2775
2776 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2777 if (ret >= 0) {
2778 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2779 } else {
2780 return -EINVAL;
2781 }
2782
2783 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2784 if (ret >= 0) {
2785 tmp_mdata.encoder_padding = atoi(value);
2786 } else {
2787 return -EINVAL;
2788 }
2789
2790 out->gapless_mdata = tmp_mdata;
2791 out->send_new_metadata = 1;
2792 ALOGV("%s new encoder delay %u and padding %u", __func__,
2793 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2794
2795 return 0;
2796}
2797
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002798static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2799{
2800 return out == adev->primary_output || out == adev->voice_tx_output;
2801}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002802
Kevin Rocard1e02c882017-08-09 15:26:07 -07002803static int get_alive_usb_card(struct str_parms* parms) {
2804 int card;
2805 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2806 !audio_extn_usb_alive(card)) {
2807 return card;
2808 }
2809 return -ENODEV;
2810}
2811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2813{
2814 struct stream_out *out = (struct stream_out *)stream;
2815 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002816 struct audio_usecase *usecase;
2817 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002818 struct str_parms *parms;
2819 char value[32];
2820 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002821 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002822 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002823 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824
Eric Laurent2e140aa2016-06-30 17:14:46 -07002825 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002826 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827 parms = str_parms_create_str(kvpairs);
2828 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2829 if (ret >= 0) {
2830 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002831
Eric Laurenta1478072015-09-21 17:21:52 -07002832 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002833
2834 // The usb driver needs to be closed after usb device disconnection
2835 // otherwise audio is no longer played on the new usb devices.
2836 // By forcing the stream in standby, the usb stack refcount drops to 0
2837 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002838 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002839 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002840 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2841 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2842 out_standby_l(&out->stream.common);
2843 }
2844 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002845 }
2846
Eric Laurent150dbfe2013-02-27 14:31:02 -08002847 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002848
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002849 /*
2850 * When HDMI cable is unplugged the music playback is paused and
2851 * the policy manager sends routing=0. But the audioflinger
2852 * continues to write data until standby time (3sec).
2853 * As the HDMI core is turned off, the write gets blocked.
2854 * Avoid this by routing audio to speaker until standby.
2855 */
2856 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2857 val == AUDIO_DEVICE_NONE) {
2858 val = AUDIO_DEVICE_OUT_SPEAKER;
2859 }
2860
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002861 /*
2862 * When A2DP is disconnected the
2863 * music playback is paused and the policy manager sends routing=0
2864 * But the audioflingercontinues to write data until standby time
2865 * (3sec). As BT is turned off, the write gets blocked.
2866 * Avoid this by routing audio to speaker until standby.
2867 */
2868 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2869 (val == AUDIO_DEVICE_NONE) &&
2870 !audio_extn_a2dp_is_ready()) {
2871 val = AUDIO_DEVICE_OUT_SPEAKER;
2872 }
2873
2874 /* To avoid a2dp to sco overlapping / BT device improper state
2875 * check with BT lib about a2dp streaming support before routing
2876 */
2877 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2878 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002879 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002880 //combo usecase just by pass a2dp
2881 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2882 bypass_a2dp = true;
2883 } else {
2884 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2885 /* update device to a2dp and don't route as BT returned error
2886 * However it is still possible a2dp routing called because
2887 * of current active device disconnection (like wired headset)
2888 */
2889 out->devices = val;
2890 pthread_mutex_unlock(&out->lock);
2891 pthread_mutex_unlock(&adev->lock);
2892 status = -ENOSYS;
2893 goto routing_fail;
2894 }
2895 }
2896 }
2897
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002898 audio_devices_t new_dev = val;
2899
2900 // Workaround: If routing to an non existing usb device, fail gracefully
2901 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002902 int card;
2903 if (audio_is_usb_out_device(new_dev) &&
2904 (card = get_alive_usb_card(parms)) >= 0) {
2905
2906 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002907 pthread_mutex_unlock(&adev->lock);
2908 pthread_mutex_unlock(&out->lock);
2909 status = -ENOSYS;
2910 goto routing_fail;
2911 }
2912
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002913 /*
2914 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002915 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002916 * the select_devices(). But how do we undo this?
2917 *
2918 * For example, music playback is active on headset (deep-buffer usecase)
2919 * and if we go to ringtones and select a ringtone, low-latency usecase
2920 * will be started on headset+speaker. As we can't enable headset+speaker
2921 * and headset devices at the same time, select_devices() switches the music
2922 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2923 * So when the ringtone playback is completed, how do we undo the same?
2924 *
2925 * We are relying on the out_set_parameters() call on deep-buffer output,
2926 * once the ringtone playback is ended.
2927 * NOTE: We should not check if the current devices are same as new devices.
2928 * Because select_devices() must be called to switch back the music
2929 * playback to headset.
2930 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002931 if (new_dev != AUDIO_DEVICE_NONE) {
2932 bool same_dev = out->devices == new_dev;
2933 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002934
Eric Laurenta7657192014-10-09 21:09:33 -07002935 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002936 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002937 if (adev->mode == AUDIO_MODE_IN_CALL) {
2938 adev->current_call_output = out;
2939 ret = voice_start_call(adev);
2940 }
2941 } else {
2942 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002943 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002944 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002945 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002946
2947 if (!out->standby) {
2948 if (!same_dev) {
2949 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002950 // inform adm before actual routing to prevent glitches.
2951 if (adev->adm_on_routing_change) {
2952 adev->adm_on_routing_change(adev->adm_data,
2953 out->handle);
2954 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002955 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002956 if (!bypass_a2dp) {
2957 select_devices(adev, out->usecase);
2958 } else {
juyuchen9baad392018-06-05 19:02:10 +08002959 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2960 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2961 else
2962 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002963 select_devices(adev, out->usecase);
2964 out->devices = new_dev;
2965 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002966 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002967
2968 // on device switch force swap, lower functions will make sure
2969 // to check if swap is allowed or not.
2970
2971 if (!same_dev)
2972 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002973
2974 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2975 out->a2dp_compress_mute &&
2976 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2977 pthread_mutex_lock(&out->compr_mute_lock);
2978 out->a2dp_compress_mute = false;
2979 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2980 pthread_mutex_unlock(&out->compr_mute_lock);
2981 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002982 }
2983
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002984 }
2985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002987 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002988
2989 /*handles device and call state changes*/
2990 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002991 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002992 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002993
2994 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2995 parse_compress_metadata(out, parms);
2996 }
2997
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002999 ALOGV("%s: exit: code(%d)", __func__, status);
3000 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001}
3002
Haynes Mathew George569b7482017-05-08 14:44:27 -07003003static bool stream_get_parameter_channels(struct str_parms *query,
3004 struct str_parms *reply,
3005 audio_channel_mask_t *supported_channel_masks) {
3006 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07003007 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003009 size_t i, j;
3010
3011 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3012 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003013 value[0] = '\0';
3014 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003015 while (supported_channel_masks[i] != 0) {
3016 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3017 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018 if (!first) {
3019 strcat(value, "|");
3020 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003021 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003022 first = false;
3023 break;
3024 }
3025 }
3026 i++;
3027 }
3028 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003029 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003030 return ret >= 0;
3031}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003032
Haynes Mathew George569b7482017-05-08 14:44:27 -07003033static bool stream_get_parameter_formats(struct str_parms *query,
3034 struct str_parms *reply,
3035 audio_format_t *supported_formats) {
3036 int ret = -1;
3037 char value[256];
3038 int i;
3039
3040 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
3041 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003042 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07003043 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003044 case AUDIO_FORMAT_PCM_16_BIT:
3045 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
3046 break;
3047 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
3048 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
3049 break;
3050 case AUDIO_FORMAT_PCM_32_BIT:
3051 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
3052 break;
3053 default:
3054 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07003055 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003056 break;
3057 }
3058 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003059 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003060 return ret >= 0;
3061}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003062
Haynes Mathew George569b7482017-05-08 14:44:27 -07003063static bool stream_get_parameter_rates(struct str_parms *query,
3064 struct str_parms *reply,
3065 uint32_t *supported_sample_rates) {
3066
3067 int i;
3068 char value[256];
3069 int ret = -1;
3070 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
3071 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003072 value[0] = '\0';
3073 i=0;
3074 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003075 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003076 int avail = sizeof(value) - cursor;
3077 ret = snprintf(value + cursor, avail, "%s%d",
3078 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07003079 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003080 if (ret < 0 || ret >= avail) {
3081 // if cursor is at the last element of the array
3082 // overwrite with \0 is duplicate work as
3083 // snprintf already put a \0 in place.
3084 // else
3085 // we had space to write the '|' at value[cursor]
3086 // (which will be overwritten) or no space to fill
3087 // the first element (=> cursor == 0)
3088 value[cursor] = '\0';
3089 break;
3090 }
3091 cursor += ret;
3092 ++i;
3093 }
3094 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3095 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003096 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003097 return ret >= 0;
3098}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003099
Haynes Mathew George569b7482017-05-08 14:44:27 -07003100static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3101{
3102 struct stream_out *out = (struct stream_out *)stream;
3103 struct str_parms *query = str_parms_create_str(keys);
3104 char *str;
3105 struct str_parms *reply = str_parms_create();
3106 bool replied = false;
3107 ALOGV("%s: enter: keys - %s", __func__, keys);
3108
3109 replied |= stream_get_parameter_channels(query, reply,
3110 &out->supported_channel_masks[0]);
3111 replied |= stream_get_parameter_formats(query, reply,
3112 &out->supported_formats[0]);
3113 replied |= stream_get_parameter_rates(query, reply,
3114 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003115 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116 str = str_parms_to_str(reply);
3117 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07003118 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119 }
3120 str_parms_destroy(query);
3121 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003122 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123 return str;
3124}
3125
3126static uint32_t out_get_latency(const struct audio_stream_out *stream)
3127{
Haynes Mathew George03c40102016-01-29 17:57:48 -08003128 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003129 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003130 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003132 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3133 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003134 else if ((out->realtime) ||
3135 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003136 // since the buffer won't be filled up faster than realtime,
3137 // return a smaller number
3138 period_ms = (out->af_period_multiplier * out->config.period_size *
3139 1000) / (out->config.rate);
3140 hw_delay = platform_render_latency(out->usecase)/1000;
3141 return period_ms + hw_delay;
3142 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003143
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003144 latency = (out->config.period_count * out->config.period_size * 1000) /
3145 (out->config.rate);
3146
3147 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
3148 latency += audio_extn_a2dp_get_encoder_latency();
3149
3150 return latency;
3151}
3152
3153static int set_compr_volume(struct audio_stream_out *stream, float left,
3154 float right)
3155{
3156 struct stream_out *out = (struct stream_out *)stream;
3157 int volume[2];
3158 char mixer_ctl_name[128];
3159 struct audio_device *adev = out->dev;
3160 struct mixer_ctl *ctl;
3161 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3162 PCM_PLAYBACK);
3163
3164 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3165 "Compress Playback %d Volume", pcm_device_id);
3166 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3167 if (!ctl) {
3168 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3169 __func__, mixer_ctl_name);
3170 return -EINVAL;
3171 }
3172 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
3173 __func__, mixer_ctl_name, left, right);
3174 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3175 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3176 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
3177
3178 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179}
3180
3181static int out_set_volume(struct audio_stream_out *stream, float left,
3182 float right)
3183{
Eric Laurenta9024de2013-04-04 09:19:12 -07003184 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003185 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003186
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003187 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07003188 /* only take left channel into account: the API is for stereo anyway */
3189 out->muted = (left == 0.0f);
3190 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003191 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003192 pthread_mutex_lock(&out->compr_mute_lock);
3193 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3194 if (!out->a2dp_compress_mute)
3195 ret = set_compr_volume(stream, left, right);
3196 out->volume_l = left;
3197 out->volume_r = right;
3198 pthread_mutex_unlock(&out->compr_mute_lock);
3199 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07003200 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07003201 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3202 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3203 if (!out->standby) {
3204 // if in standby, cached volume will be sent after stream is opened
3205 audio_extn_utils_send_app_type_gain(out->dev,
3206 out->app_type_cfg.app_type,
3207 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07003208 }
vivek mehtaa68fea62017-06-08 19:04:02 -07003209 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003210 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003211
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212 return -ENOSYS;
3213}
3214
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003215// note: this call is safe only if the stream_cb is
3216// removed first in close_output_stream (as is done now).
3217static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3218{
3219 if (!stream || !parms)
3220 return;
3221
3222 struct stream_out *out = (struct stream_out *)stream;
3223 struct audio_device *adev = out->dev;
3224
3225 card_status_t status;
3226 int card;
3227 if (parse_snd_card_status(parms, &card, &status) < 0)
3228 return;
3229
3230 pthread_mutex_lock(&adev->lock);
3231 bool valid_cb = (card == adev->snd_card);
3232 pthread_mutex_unlock(&adev->lock);
3233
3234 if (!valid_cb)
3235 return;
3236
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003237 lock_output_stream(out);
3238 if (out->card_status != status)
3239 out->card_status = status;
3240 pthread_mutex_unlock(&out->lock);
3241
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07003242 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
3243 use_case_table[out->usecase],
3244 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3245
3246 if (status == CARD_STATUS_OFFLINE)
3247 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003248
3249 return;
3250}
3251
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003252#ifdef NO_AUDIO_OUT
3253static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003254 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003255{
3256 struct stream_out *out = (struct stream_out *)stream;
3257
3258 /* No Output device supported other than BT for playback.
3259 * Sleep for the amount of buffer duration
3260 */
Eric Laurenta1478072015-09-21 17:21:52 -07003261 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003262 usleep(bytes * 1000000 / audio_stream_out_frame_size(
3263 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003264 out_get_sample_rate(&out->stream.common));
3265 pthread_mutex_unlock(&out->lock);
3266 return bytes;
3267}
3268#endif
3269
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003270static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3271 size_t bytes)
3272{
3273 struct stream_out *out = (struct stream_out *)stream;
3274 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003275 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07003276 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003277
Eric Laurenta1478072015-09-21 17:21:52 -07003278 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07003279 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07003280 const size_t frame_size = audio_stream_out_frame_size(stream);
3281 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003282
Eric Laurent0e46adf2016-12-16 12:49:24 -08003283 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3284 error_code = ERROR_CODE_WRITE;
3285 goto exit;
3286 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003287
3288 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3289 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003290 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003291 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3292 ret = -EIO;
3293 goto exit;
3294 }
3295 }
3296 }
3297
Andy Hung572633e2019-02-19 11:58:24 -08003298 const bool was_in_standby = out->standby;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003299 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003300 out->standby = false;
Andy Hung241e36f2019-02-19 12:00:38 -08003301 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
3302
Eric Laurent150dbfe2013-02-27 14:31:02 -08003303 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003305
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003306 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003308 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003309 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310 goto exit;
3311 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003312
vivek mehta40125092017-08-21 18:48:51 -07003313 // after standby always force set last known cal step
3314 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3315 ALOGD("%s: retry previous failed cal level set", __func__);
3316 send_gain_dep_calibration_l();
3317 pthread_mutex_unlock(&adev->lock);
Andy Hung572633e2019-02-19 11:58:24 -08003318
Andy Hung241e36f2019-02-19 12:00:38 -08003319 // log startup time in ms.
3320 simple_stats_log(
3321 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Andy Hung572633e2019-02-19 11:58:24 -08003322 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003323 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003325 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003326 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003327 if (out->send_new_metadata) {
3328 ALOGVV("send new gapless metadata");
3329 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3330 out->send_new_metadata = 0;
3331 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003332 unsigned int avail;
3333 struct timespec tstamp;
3334 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3335 /* Do not limit write size if the available frames count is unknown */
3336 if (ret != 0) {
3337 avail = bytes;
3338 }
3339 if (avail == 0) {
3340 ret = 0;
3341 } else {
Andy Hung572633e2019-02-19 11:58:24 -08003342 // check for compressed format underrun, essentially an empty buffer check
3343 // for a lack of better measurement.
3344 if (!was_in_standby && avail == out->kernel_buffer_size) {
3345 ALOGW("%s: compressed buffer empty (underrun)", __func__);
3346 simple_stats_log(&out->fifo_underruns, 1.); // Note: log one frame for compressed.
3347 }
3348
Eric Laurentb49b3f62016-02-29 17:59:49 -08003349 if (avail > bytes) {
3350 avail = bytes;
3351 }
3352 ret = compress_write(out->compr, buffer, avail);
3353 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3354 __func__, avail, ret);
3355 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003356
Eric Laurent6e895242013-09-05 16:10:57 -07003357 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003358 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3359 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003360 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003361 compress_start(out->compr);
3362 out->playback_started = 1;
3363 out->offload_state = OFFLOAD_STATE_PLAYING;
3364 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003365 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003366 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003367 } else {
3368 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003369 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003370 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003371 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003372 return ret;
3373 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003374 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003375 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003376 size_t bytes_to_write = bytes;
3377
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003378 if (out->muted)
3379 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003380 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003381 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003382 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3383 int16_t *src = (int16_t *)buffer;
3384 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003385
Eric Laurentad2dde92017-09-20 18:27:31 -07003386 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3387 out->format != AUDIO_FORMAT_PCM_16_BIT,
3388 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003389
Eric Laurentad2dde92017-09-20 18:27:31 -07003390 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3391 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3392 }
3393 bytes_to_write /= 2;
3394 }
Andy Hung572633e2019-02-19 11:58:24 -08003395
3396 // Note: since out_get_presentation_position() is called alternating with out_write()
3397 // by AudioFlinger, we can check underruns using the prior timestamp read.
3398 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
3399 if (out->last_fifo_valid) {
3400 // compute drain to see if there is an underrun.
3401 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
3402 const int64_t frames_by_time =
3403 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
3404 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
3405
3406 if (underrun > 0) {
3407 simple_stats_log(&out->fifo_underruns, underrun);
3408
3409 ALOGW("%s: underrun(%lld) "
3410 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
3411 __func__,
3412 (long long)out->fifo_underruns.n,
3413 (long long)frames_by_time,
3414 (long long)out->last_fifo_frames_remaining);
3415 }
3416 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
3417 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003418
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003419 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003420 request_out_focus(out, ns);
3421
3422 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003423 if (use_mmap) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003424 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003425 } else {
3426 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3427 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3428 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
3429 size_t frame_size = channel_count * bytes_per_sample;
3430 size_t frame_count = bytes_to_write / frame_size;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003431
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003432 bool force_haptic_path =
3433 property_get_bool("vendor.audio.test_haptic", false);
3434
3435 // extract Haptics data from Audio buffer
3436 bool alloc_haptic_buffer = false;
3437 int haptic_channel_count = adev->haptics_config.channels;
3438 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
3439 size_t audio_frame_size = frame_size - haptic_frame_size;
3440 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
3441
3442 if (adev->haptic_buffer == NULL) {
3443 alloc_haptic_buffer = true;
3444 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
3445 free(adev->haptic_buffer);
3446 adev->haptic_buffer_size = 0;
3447 alloc_haptic_buffer = true;
3448 }
3449
3450 if (alloc_haptic_buffer) {
3451 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
3452 adev->haptic_buffer_size = total_haptic_buffer_size;
3453 }
3454
3455 size_t src_index = 0, aud_index = 0, hap_index = 0;
3456 uint8_t *audio_buffer = (uint8_t *)buffer;
3457 uint8_t *haptic_buffer = adev->haptic_buffer;
3458
3459 // This is required for testing only. This works for stereo data only.
3460 // One channel is fed to audio stream and other to haptic stream for testing.
3461 if (force_haptic_path) {
3462 audio_frame_size = haptic_frame_size = bytes_per_sample;
3463 }
3464
3465 for (size_t i = 0; i < frame_count; i++) {
3466 for (size_t j = 0; j < audio_frame_size; j++)
3467 audio_buffer[aud_index++] = audio_buffer[src_index++];
3468
3469 for (size_t j = 0; j < haptic_frame_size; j++)
3470 haptic_buffer[hap_index++] = audio_buffer[src_index++];
3471 }
3472
3473 // This is required for testing only.
3474 // Discard haptic channel data.
3475 if (force_haptic_path) {
3476 src_index += haptic_frame_size;
3477 }
3478
3479 // write to audio pipeline
3480 ret = pcm_write(out->pcm,
3481 (void *)audio_buffer,
3482 frame_count * audio_frame_size);
3483
3484 // write to haptics pipeline
3485 if (adev->haptic_pcm)
3486 ret = pcm_write(adev->haptic_pcm,
3487 (void *)adev->haptic_buffer,
3488 frame_count * haptic_frame_size);
3489
3490 } else {
3491 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
3492 }
3493 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003494 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003495 } else {
3496 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003497 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498 }
3499
3500exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003501 // For PCM we always consume the buffer and return #bytes regardless of ret.
3502 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003503 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003504 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003505 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003506
Andy Hung7401c7c2016-09-21 12:41:21 -07003507 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003508 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003509 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3510 ALOGE_IF(out->pcm != NULL,
3511 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003512 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003513 // usleep not guaranteed for values over 1 second but we don't limit here.
3514 }
3515 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517 pthread_mutex_unlock(&out->lock);
3518
3519 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003520 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003521 if (sleeptime_us != 0)
3522 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523 }
3524 return bytes;
3525}
3526
3527static int out_get_render_position(const struct audio_stream_out *stream,
3528 uint32_t *dsp_frames)
3529{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003530 struct stream_out *out = (struct stream_out *)stream;
3531 *dsp_frames = 0;
3532 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003533 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003534 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003535 unsigned long frames = 0;
3536 // TODO: check return value
3537 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3538 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003539 ALOGVV("%s rendered frames %d sample_rate %d",
3540 __func__, *dsp_frames, out->sample_rate);
3541 }
3542 pthread_mutex_unlock(&out->lock);
3543 return 0;
3544 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003545 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546}
3547
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003548static int out_add_audio_effect(const struct audio_stream *stream __unused,
3549 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550{
3551 return 0;
3552}
3553
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003554static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3555 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556{
3557 return 0;
3558}
3559
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003560static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3561 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003563 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564}
3565
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003566static int out_get_presentation_position(const struct audio_stream_out *stream,
3567 uint64_t *frames, struct timespec *timestamp)
3568{
3569 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003570 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003571 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003572
Eric Laurenta1478072015-09-21 17:21:52 -07003573 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003574
Eric Laurent949a0892013-09-20 09:20:13 -07003575 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3576 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003577 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003578 compress_get_tstamp(out->compr, &dsp_frames,
3579 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003580 // Adjustment accounts for A2DP encoder latency with offload usecases
3581 // Note: Encoder latency is returned in ms.
3582 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3583 unsigned long offset =
3584 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3585 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3586 }
Eric Laurent949a0892013-09-20 09:20:13 -07003587 ALOGVV("%s rendered frames %ld sample_rate %d",
3588 __func__, dsp_frames, out->sample_rate);
3589 *frames = dsp_frames;
3590 ret = 0;
3591 /* this is the best we can do */
3592 clock_gettime(CLOCK_MONOTONIC, timestamp);
3593 }
3594 } else {
3595 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003596 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003597 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
Andy Hung572633e2019-02-19 11:58:24 -08003598
3599 // pcm_get_htimestamp() computes the available frames by comparing
3600 // the alsa driver hw_ptr and the appl_ptr levels.
3601 // In underrun, the hw_ptr may keep running and report an excessively
3602 // large number available number.
3603 if (avail > out->kernel_buffer_size) {
3604 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
3605 __func__, avail, out->kernel_buffer_size);
3606 avail = out->kernel_buffer_size;
3607 out->last_fifo_frames_remaining = 0;
3608 } else {
3609 out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
3610 }
3611 out->last_fifo_valid = true;
3612 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
3613
3614 int64_t signed_frames = out->written - out->last_fifo_frames_remaining;
3615
3616 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
3617 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
3618
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003619 // This adjustment accounts for buffering after app processor.
3620 // It is based on estimated DSP latency per use case, rather than exact.
3621 signed_frames -=
3622 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3623
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003624 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3625 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3626 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3627 signed_frames -=
3628 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3629 }
3630
Eric Laurent949a0892013-09-20 09:20:13 -07003631 // It would be unusual for this value to be negative, but check just in case ...
3632 if (signed_frames >= 0) {
3633 *frames = signed_frames;
3634 ret = 0;
3635 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003636 }
3637 }
3638 }
3639
3640 pthread_mutex_unlock(&out->lock);
3641
3642 return ret;
3643}
3644
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003645static int out_set_callback(struct audio_stream_out *stream,
3646 stream_callback_t callback, void *cookie)
3647{
3648 struct stream_out *out = (struct stream_out *)stream;
3649
3650 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003651 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003652 out->offload_callback = callback;
3653 out->offload_cookie = cookie;
3654 pthread_mutex_unlock(&out->lock);
3655 return 0;
3656}
3657
3658static int out_pause(struct audio_stream_out* stream)
3659{
3660 struct stream_out *out = (struct stream_out *)stream;
3661 int status = -ENOSYS;
3662 ALOGV("%s", __func__);
3663 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003664 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003665 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3666 status = compress_pause(out->compr);
3667 out->offload_state = OFFLOAD_STATE_PAUSED;
3668 }
3669 pthread_mutex_unlock(&out->lock);
3670 }
3671 return status;
3672}
3673
3674static int out_resume(struct audio_stream_out* stream)
3675{
3676 struct stream_out *out = (struct stream_out *)stream;
3677 int status = -ENOSYS;
3678 ALOGV("%s", __func__);
3679 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3680 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003681 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003682 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3683 status = compress_resume(out->compr);
3684 out->offload_state = OFFLOAD_STATE_PLAYING;
3685 }
3686 pthread_mutex_unlock(&out->lock);
3687 }
3688 return status;
3689}
3690
3691static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3692{
3693 struct stream_out *out = (struct stream_out *)stream;
3694 int status = -ENOSYS;
3695 ALOGV("%s", __func__);
3696 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003697 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003698 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3699 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3700 else
3701 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3702 pthread_mutex_unlock(&out->lock);
3703 }
3704 return status;
3705}
3706
3707static int out_flush(struct audio_stream_out* stream)
3708{
3709 struct stream_out *out = (struct stream_out *)stream;
3710 ALOGV("%s", __func__);
3711 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003712 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003713 stop_compressed_output_l(out);
3714 pthread_mutex_unlock(&out->lock);
3715 return 0;
3716 }
3717 return -ENOSYS;
3718}
3719
Eric Laurent0e46adf2016-12-16 12:49:24 -08003720static int out_stop(const struct audio_stream_out* stream)
3721{
3722 struct stream_out *out = (struct stream_out *)stream;
3723 struct audio_device *adev = out->dev;
3724 int ret = -ENOSYS;
3725
3726 ALOGV("%s", __func__);
3727 pthread_mutex_lock(&adev->lock);
3728 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3729 out->playback_started && out->pcm != NULL) {
3730 pcm_stop(out->pcm);
3731 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003732 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003733 }
3734 pthread_mutex_unlock(&adev->lock);
3735 return ret;
3736}
3737
3738static int out_start(const struct audio_stream_out* stream)
3739{
3740 struct stream_out *out = (struct stream_out *)stream;
3741 struct audio_device *adev = out->dev;
3742 int ret = -ENOSYS;
3743
3744 ALOGV("%s", __func__);
3745 pthread_mutex_lock(&adev->lock);
3746 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3747 !out->playback_started && out->pcm != NULL) {
3748 ret = start_output_stream(out);
3749 if (ret == 0) {
3750 out->playback_started = true;
3751 }
3752 }
3753 pthread_mutex_unlock(&adev->lock);
3754 return ret;
3755}
3756
Phil Burkbc991042017-02-24 08:06:44 -08003757/*
3758 * Modify config->period_count based on min_size_frames
3759 */
3760static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3761{
3762 int periodCountRequested = (min_size_frames + config->period_size - 1)
3763 / config->period_size;
3764 int periodCount = MMAP_PERIOD_COUNT_MIN;
3765
3766 ALOGV("%s original config.period_size = %d config.period_count = %d",
3767 __func__, config->period_size, config->period_count);
3768
3769 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3770 periodCount *= 2;
3771 }
3772 config->period_count = periodCount;
3773
3774 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3775}
3776
Eric Laurent0e46adf2016-12-16 12:49:24 -08003777static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3778 int32_t min_size_frames,
3779 struct audio_mmap_buffer_info *info)
3780{
3781 struct stream_out *out = (struct stream_out *)stream;
3782 struct audio_device *adev = out->dev;
3783 int ret = 0;
3784 unsigned int offset1;
3785 unsigned int frames1;
3786 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003787 uint32_t mmap_size;
3788 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003789
3790 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003791 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003792 pthread_mutex_lock(&adev->lock);
3793
3794 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003795 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003796 ret = -EINVAL;
3797 goto exit;
3798 }
3799 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003800 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003801 ret = -ENOSYS;
3802 goto exit;
3803 }
3804 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3805 if (out->pcm_device_id < 0) {
3806 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3807 __func__, out->pcm_device_id, out->usecase);
3808 ret = -EINVAL;
3809 goto exit;
3810 }
Phil Burkbc991042017-02-24 08:06:44 -08003811
3812 adjust_mmap_period_count(&out->config, min_size_frames);
3813
Eric Laurent0e46adf2016-12-16 12:49:24 -08003814 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3815 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3816 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3817 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3818 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3819 step = "open";
3820 ret = -ENODEV;
3821 goto exit;
3822 }
3823 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3824 if (ret < 0) {
3825 step = "begin";
3826 goto exit;
3827 }
3828 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003829 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003830 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003831 ret = platform_get_mmap_data_fd(adev->platform,
3832 out->pcm_device_id, 0 /*playback*/,
3833 &info->shared_memory_fd,
3834 &mmap_size);
3835 if (ret < 0) {
3836 // Fall back to non exclusive mode
3837 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3838 } else {
3839 if (mmap_size < buffer_size) {
3840 step = "mmap";
3841 goto exit;
3842 }
3843 // FIXME: indicate exclusive mode support by returning a negative buffer size
3844 info->buffer_size_frames *= -1;
3845 }
3846 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003847
3848 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3849 if (ret < 0) {
3850 step = "commit";
3851 goto exit;
3852 }
Phil Burkbc991042017-02-24 08:06:44 -08003853
3854 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003855 ret = 0;
3856
3857 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3858 __func__, info->shared_memory_address, info->buffer_size_frames);
3859
3860exit:
3861 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003862 if (out->pcm == NULL) {
3863 ALOGE("%s: %s - %d", __func__, step, ret);
3864 } else {
3865 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003866 pcm_close(out->pcm);
3867 out->pcm = NULL;
3868 }
3869 }
3870 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003871 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003872 return ret;
3873}
3874
3875static int out_get_mmap_position(const struct audio_stream_out *stream,
3876 struct audio_mmap_position *position)
3877{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003878 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003879 struct stream_out *out = (struct stream_out *)stream;
3880 ALOGVV("%s", __func__);
3881 if (position == NULL) {
3882 return -EINVAL;
3883 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003884 lock_output_stream(out);
3885 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3886 out->pcm == NULL) {
3887 ret = -ENOSYS;
3888 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003889 }
3890
3891 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003892 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003893 if (ret < 0) {
3894 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003895 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003896 }
Andy Hungfc044e12017-03-20 09:24:22 -07003897 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003898exit:
3899 pthread_mutex_unlock(&out->lock);
3900 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003901}
3902
3903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003904/** audio_stream_in implementation **/
3905static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3906{
3907 struct stream_in *in = (struct stream_in *)stream;
3908
3909 return in->config.rate;
3910}
3911
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003912static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913{
3914 return -ENOSYS;
3915}
3916
3917static size_t in_get_buffer_size(const struct audio_stream *stream)
3918{
3919 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003920 return in->config.period_size * in->af_period_multiplier *
3921 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003922}
3923
3924static uint32_t in_get_channels(const struct audio_stream *stream)
3925{
3926 struct stream_in *in = (struct stream_in *)stream;
3927
3928 return in->channel_mask;
3929}
3930
vivek mehta4ed66e62016-04-15 23:33:34 -07003931static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003932{
vivek mehta4ed66e62016-04-15 23:33:34 -07003933 struct stream_in *in = (struct stream_in *)stream;
3934 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003935}
3936
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003937static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003938{
3939 return -ENOSYS;
3940}
3941
3942static int in_standby(struct audio_stream *stream)
3943{
3944 struct stream_in *in = (struct stream_in *)stream;
3945 struct audio_device *adev = in->dev;
3946 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003947 bool do_stop = true;
3948
Eric Laurent994a6932013-07-17 11:51:42 -07003949 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003950
3951 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003952
3953 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003954 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003955 audio_extn_sound_trigger_stop_lab(in);
3956 in->standby = true;
3957 }
3958
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003959 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003960 if (adev->adm_deregister_stream)
3961 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3962
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003963 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003965 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003966 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003967 in->capture_started = false;
3968 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003969 if (in->pcm) {
3970 pcm_close(in->pcm);
3971 in->pcm = NULL;
3972 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003973 adev->enable_voicerx = false;
3974 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003975 if (do_stop) {
3976 status = stop_input_stream(in);
3977 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003978 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003979 }
3980 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003981 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982 return status;
3983}
3984
Andy Hungd13f0d32017-06-12 13:58:37 -07003985static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986{
Andy Hungd13f0d32017-06-12 13:58:37 -07003987 struct stream_in *in = (struct stream_in *)stream;
3988
3989 // We try to get the lock for consistency,
3990 // but it isn't necessary for these variables.
3991 // If we're not in standby, we may be blocked on a read.
3992 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3993 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3994 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3995 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3996
Andy Hung241e36f2019-02-19 12:00:38 -08003997 char buffer[256]; // for statistics formatting
3998 if (in->start_latency_ms.n > 0) {
3999 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
4000 dprintf(fd, " Start latency ms: %s\n", buffer);
4001 }
4002
Andy Hungd13f0d32017-06-12 13:58:37 -07004003 if (locked) {
4004 pthread_mutex_unlock(&in->lock);
4005 }
4006
4007 // dump error info
4008 (void)error_log_dump(
4009 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004010 return 0;
4011}
4012
4013static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4014{
4015 struct stream_in *in = (struct stream_in *)stream;
4016 struct audio_device *adev = in->dev;
4017 struct str_parms *parms;
4018 char *str;
4019 char value[32];
4020 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07004021 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004022
Eric Laurent994a6932013-07-17 11:51:42 -07004023 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024 parms = str_parms_create_str(kvpairs);
4025
4026 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4027
Eric Laurenta1478072015-09-21 17:21:52 -07004028 lock_input_stream(in);
4029
Eric Laurent150dbfe2013-02-27 14:31:02 -08004030 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004031 if (ret >= 0) {
4032 val = atoi(value);
4033 /* no audio source uses val == 0 */
4034 if ((in->source != val) && (val != 0)) {
4035 in->source = val;
4036 }
4037 }
4038
4039 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07004040
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004041 if (ret >= 0) {
4042 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07004043 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004044
4045 // Workaround: If routing to an non existing usb device, fail gracefully
4046 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07004047 int card;
4048 if (audio_is_usb_in_device(val) &&
4049 (card = get_alive_usb_card(parms)) >= 0) {
4050
4051 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004052 status = -ENOSYS;
4053 } else {
4054
4055 in->device = val;
4056 /* If recording is in progress, change the tx device to new device */
4057 if (!in->standby) {
4058 ALOGV("update input routing change");
4059 // inform adm before actual routing to prevent glitches.
4060 if (adev->adm_on_routing_change) {
4061 adev->adm_on_routing_change(adev->adm_data,
4062 in->capture_handle);
4063 }
4064 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07004065 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004066 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004067 }
4068 }
4069
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004070 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004071 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004072
4073 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07004074 ALOGV("%s: exit: status(%d)", __func__, status);
4075 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004076}
4077
Haynes Mathew George569b7482017-05-08 14:44:27 -07004078static char* in_get_parameters(const struct audio_stream *stream,
4079 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004080{
Haynes Mathew George569b7482017-05-08 14:44:27 -07004081 struct stream_in *in = (struct stream_in *)stream;
4082 struct str_parms *query = str_parms_create_str(keys);
4083 char *str;
4084 struct str_parms *reply = str_parms_create();
4085 bool replied = false;
4086
4087 ALOGV("%s: enter: keys - %s", __func__, keys);
4088 replied |= stream_get_parameter_channels(query, reply,
4089 &in->supported_channel_masks[0]);
4090 replied |= stream_get_parameter_formats(query, reply,
4091 &in->supported_formats[0]);
4092 replied |= stream_get_parameter_rates(query, reply,
4093 &in->supported_sample_rates[0]);
4094 if (replied) {
4095 str = str_parms_to_str(reply);
4096 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07004097 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07004098 }
4099 str_parms_destroy(query);
4100 str_parms_destroy(reply);
4101 ALOGV("%s: exit: returns - %s", __func__, str);
4102 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004103}
4104
Eric Laurent51f3c662018-04-10 18:21:34 -07004105static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004106{
Eric Laurent51f3c662018-04-10 18:21:34 -07004107 struct stream_in *in = (struct stream_in *)stream;
4108 char mixer_ctl_name[128];
4109 struct mixer_ctl *ctl;
4110 int ctl_value;
4111
4112 ALOGV("%s: gain %f", __func__, gain);
4113
4114 if (stream == NULL)
4115 return -EINVAL;
4116
4117 /* in_set_gain() only used to silence MMAP capture for now */
4118 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
4119 return -ENOSYS;
4120
4121 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
4122
4123 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
4124 if (!ctl) {
4125 ALOGW("%s: Could not get ctl for mixer cmd - %s",
4126 __func__, mixer_ctl_name);
4127 return -ENOSYS;
4128 }
4129
4130 if (gain < RECORD_GAIN_MIN)
4131 gain = RECORD_GAIN_MIN;
4132 else if (gain > RECORD_GAIN_MAX)
4133 gain = RECORD_GAIN_MAX;
4134 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
4135
4136 mixer_ctl_set_value(ctl, 0, ctl_value);
4137 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004138}
4139
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004140static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4141{
4142 if (!stream || !parms)
4143 return;
4144
4145 struct stream_in *in = (struct stream_in *)stream;
4146 struct audio_device *adev = in->dev;
4147
4148 card_status_t status;
4149 int card;
4150 if (parse_snd_card_status(parms, &card, &status) < 0)
4151 return;
4152
4153 pthread_mutex_lock(&adev->lock);
4154 bool valid_cb = (card == adev->snd_card);
4155 pthread_mutex_unlock(&adev->lock);
4156
4157 if (!valid_cb)
4158 return;
4159
4160 lock_input_stream(in);
4161 if (in->card_status != status)
4162 in->card_status = status;
4163 pthread_mutex_unlock(&in->lock);
4164
4165 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4166 use_case_table[in->usecase],
4167 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4168
4169 // a better solution would be to report error back to AF and let
4170 // it put the stream to standby
4171 if (status == CARD_STATUS_OFFLINE)
4172 in_standby(&in->stream.common);
4173
4174 return;
4175}
4176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004177static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4178 size_t bytes)
4179{
4180 struct stream_in *in = (struct stream_in *)stream;
4181 struct audio_device *adev = in->dev;
4182 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07004183 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07004184 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004185
Eric Laurenta1478072015-09-21 17:21:52 -07004186 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004187 const size_t frame_size = audio_stream_in_frame_size(stream);
4188 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07004189
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004190 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004191 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004192 /* Read from sound trigger HAL */
4193 audio_extn_sound_trigger_read(in, buffer, bytes);
4194 pthread_mutex_unlock(&in->lock);
4195 return bytes;
4196 }
4197
Eric Laurent0e46adf2016-12-16 12:49:24 -08004198 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4199 ret = -ENOSYS;
4200 goto exit;
4201 }
4202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004203 if (in->standby) {
Andy Hung241e36f2019-02-19 12:00:38 -08004204 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
4205
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004206 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004207 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004208 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004209 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004210 goto exit;
4211 }
4212 in->standby = 0;
Andy Hung241e36f2019-02-19 12:00:38 -08004213
4214 // log startup time in ms.
4215 simple_stats_log(
4216 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004217 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004218
Andy Hungd13f0d32017-06-12 13:58:37 -07004219 // errors that occur here are read errors.
4220 error_code = ERROR_CODE_READ;
4221
Haynes Mathew George03c40102016-01-29 17:57:48 -08004222 //what's the duration requested by the client?
4223 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4224 in->config.rate;
4225 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004226
Haynes Mathew George03c40102016-01-29 17:57:48 -08004227 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004228 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08004229 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004230 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07004231 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004232 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004233 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004234 if (ret < 0) {
4235 ALOGE("Failed to read w/err %s", strerror(errno));
4236 ret = -errno;
4237 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004238 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4239 if (bytes % 4 == 0) {
4240 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4241 int_buf_stream = buffer;
4242 for (size_t itt=0; itt < bytes/4 ; itt++) {
4243 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07004244 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004245 } else {
4246 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
4247 ret = -EINVAL;
4248 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07004249 }
4250 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004251 }
4252
Haynes Mathew George03c40102016-01-29 17:57:48 -08004253 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004255 /*
4256 * Instead of writing zeroes here, we could trust the hardware
4257 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004258 * 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 -08004259 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08004260 if (ret == 0 && adev->mic_muted &&
4261 !voice_is_in_call_rec_stream(in) &&
4262 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004263 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07004264 in->frames_muted += frames;
4265 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004266
4267exit:
4268 pthread_mutex_unlock(&in->lock);
4269
4270 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07004271 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004272 in_standby(&in->stream.common);
4273 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004274 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08004275 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07004276 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08004277 }
4278 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07004279 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004280 }
4281 return bytes;
4282}
4283
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004284static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004285{
4286 return 0;
4287}
4288
Andy Hung6ebe5962016-01-15 17:46:57 -08004289static int in_get_capture_position(const struct audio_stream_in *stream,
4290 int64_t *frames, int64_t *time)
4291{
4292 if (stream == NULL || frames == NULL || time == NULL) {
4293 return -EINVAL;
4294 }
4295 struct stream_in *in = (struct stream_in *)stream;
4296 int ret = -ENOSYS;
4297
4298 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004299 // note: ST sessions do not close the alsa pcm driver synchronously
4300 // on standby. Therefore, we may return an error even though the
4301 // pcm stream is still opened.
4302 if (in->standby) {
4303 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
4304 "%s stream in standby but pcm not NULL for non ST session", __func__);
4305 goto exit;
4306 }
Andy Hung6ebe5962016-01-15 17:46:57 -08004307 if (in->pcm) {
4308 struct timespec timestamp;
4309 unsigned int avail;
4310 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
4311 *frames = in->frames_read + avail;
4312 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
4313 ret = 0;
4314 }
4315 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004316exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08004317 pthread_mutex_unlock(&in->lock);
4318 return ret;
4319}
4320
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004321static int add_remove_audio_effect(const struct audio_stream *stream,
4322 effect_handle_t effect,
4323 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004324{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004325 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004326 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004327 int status = 0;
4328 effect_descriptor_t desc;
4329
4330 status = (*effect)->get_descriptor(effect, &desc);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004331 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
4332
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004333 if (status != 0)
4334 return status;
4335
Eric Laurenta1478072015-09-21 17:21:52 -07004336 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004337 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07004338 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07004339 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07004340 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004341 in->enable_aec != enable &&
4342 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4343 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004344 if (!enable)
4345 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07004346 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
4347 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
4348 adev->enable_voicerx = enable;
4349 struct audio_usecase *usecase;
4350 struct listnode *node;
4351 list_for_each(node, &adev->usecase_list) {
4352 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07004353 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07004354 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05004355 }
4356 }
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004357 if (!in->standby
4358 && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004359 select_devices(in->dev, in->usecase);
4360 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004361 if (in->enable_ns != enable &&
4362 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4363 in->enable_ns = enable;
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004364 if (!in->standby) {
4365 if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
4366 || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
4367 select_devices(in->dev, in->usecase);
4368 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004369 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004370 pthread_mutex_unlock(&in->dev->lock);
4371 pthread_mutex_unlock(&in->lock);
4372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004373 return 0;
4374}
4375
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004376static int in_add_audio_effect(const struct audio_stream *stream,
4377 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004378{
Eric Laurent994a6932013-07-17 11:51:42 -07004379 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004380 return add_remove_audio_effect(stream, effect, true);
4381}
4382
4383static int in_remove_audio_effect(const struct audio_stream *stream,
4384 effect_handle_t effect)
4385{
Eric Laurent994a6932013-07-17 11:51:42 -07004386 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004387 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004388}
4389
Eric Laurent0e46adf2016-12-16 12:49:24 -08004390static int in_stop(const struct audio_stream_in* stream)
4391{
4392 struct stream_in *in = (struct stream_in *)stream;
4393 struct audio_device *adev = in->dev;
4394
4395 int ret = -ENOSYS;
4396 ALOGV("%s", __func__);
4397 pthread_mutex_lock(&adev->lock);
4398 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4399 in->capture_started && in->pcm != NULL) {
4400 pcm_stop(in->pcm);
4401 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08004402 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004403 }
4404 pthread_mutex_unlock(&adev->lock);
4405 return ret;
4406}
4407
4408static int in_start(const struct audio_stream_in* stream)
4409{
4410 struct stream_in *in = (struct stream_in *)stream;
4411 struct audio_device *adev = in->dev;
4412 int ret = -ENOSYS;
4413
4414 ALOGV("%s in %p", __func__, in);
4415 pthread_mutex_lock(&adev->lock);
4416 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4417 !in->capture_started && in->pcm != NULL) {
4418 if (!in->capture_started) {
4419 ret = start_input_stream(in);
4420 if (ret == 0) {
4421 in->capture_started = true;
4422 }
4423 }
4424 }
4425 pthread_mutex_unlock(&adev->lock);
4426 return ret;
4427}
4428
Phil Burk8a6a1652019-03-25 10:15:59 -07004429// Read offset for the positional timestamp from a persistent vendor property.
4430// This is to workaround apparent inaccuracies in the timing information that
4431// is used by the AAudio timing model. The inaccuracies can cause glitches.
Phil Burkc4714fc2019-02-16 22:28:11 -08004432static int64_t in_get_mmap_time_offset() {
Phil Burk8a6a1652019-03-25 10:15:59 -07004433 const int32_t kDefaultOffsetMicros = 0;
Phil Burkc4714fc2019-02-16 22:28:11 -08004434 int32_t mmap_time_offset_micros = property_get_int32(
Phil Burk8a6a1652019-03-25 10:15:59 -07004435 "persist.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkc4714fc2019-02-16 22:28:11 -08004436 ALOGI("in_get_mmap_time_offset set to %d micros", mmap_time_offset_micros);
4437 return mmap_time_offset_micros * (int64_t)1000;
4438}
4439
Eric Laurent0e46adf2016-12-16 12:49:24 -08004440static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4441 int32_t min_size_frames,
4442 struct audio_mmap_buffer_info *info)
4443{
4444 struct stream_in *in = (struct stream_in *)stream;
4445 struct audio_device *adev = in->dev;
4446 int ret = 0;
4447 unsigned int offset1;
4448 unsigned int frames1;
4449 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004450 uint32_t mmap_size;
4451 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004452
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004453 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004454 pthread_mutex_lock(&adev->lock);
4455 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004456
Eric Laurent0e46adf2016-12-16 12:49:24 -08004457 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004458 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004459 ret = -EINVAL;
4460 goto exit;
4461 }
4462 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004463 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004464 ALOGV("%s in %p", __func__, in);
4465 ret = -ENOSYS;
4466 goto exit;
4467 }
4468 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4469 if (in->pcm_device_id < 0) {
4470 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4471 __func__, in->pcm_device_id, in->usecase);
4472 ret = -EINVAL;
4473 goto exit;
4474 }
Phil Burkbc991042017-02-24 08:06:44 -08004475
4476 adjust_mmap_period_count(&in->config, min_size_frames);
4477
Eric Laurent0e46adf2016-12-16 12:49:24 -08004478 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4479 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4480 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4481 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4482 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4483 step = "open";
4484 ret = -ENODEV;
4485 goto exit;
4486 }
4487
4488 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4489 if (ret < 0) {
4490 step = "begin";
4491 goto exit;
4492 }
4493 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004494 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004495 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004496 ret = platform_get_mmap_data_fd(adev->platform,
4497 in->pcm_device_id, 1 /*capture*/,
4498 &info->shared_memory_fd,
4499 &mmap_size);
4500 if (ret < 0) {
4501 // Fall back to non exclusive mode
4502 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4503 } else {
4504 if (mmap_size < buffer_size) {
4505 step = "mmap";
4506 goto exit;
4507 }
4508 // FIXME: indicate exclusive mode support by returning a negative buffer size
4509 info->buffer_size_frames *= -1;
4510 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004511
Haynes Mathew George96483a22017-03-28 14:52:47 -07004512 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004513
4514 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4515 if (ret < 0) {
4516 step = "commit";
4517 goto exit;
4518 }
4519
Phil Burkc4714fc2019-02-16 22:28:11 -08004520 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
4521
Phil Burkbc991042017-02-24 08:06:44 -08004522 in->standby = false;
4523 ret = 0;
4524
Eric Laurent0e46adf2016-12-16 12:49:24 -08004525 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4526 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004527
4528exit:
4529 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004530 if (in->pcm == NULL) {
4531 ALOGE("%s: %s - %d", __func__, step, ret);
4532 } else {
4533 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004534 pcm_close(in->pcm);
4535 in->pcm = NULL;
4536 }
4537 }
4538 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004539 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004540 return ret;
4541}
4542
4543static int in_get_mmap_position(const struct audio_stream_in *stream,
4544 struct audio_mmap_position *position)
4545{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004546 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004547 struct stream_in *in = (struct stream_in *)stream;
4548 ALOGVV("%s", __func__);
4549 if (position == NULL) {
4550 return -EINVAL;
4551 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004552 lock_input_stream(in);
4553 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4554 in->pcm == NULL) {
4555 ret = -ENOSYS;
4556 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004557 }
4558 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004559 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004560 if (ret < 0) {
4561 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004562 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004563 }
Phil Burk8a6a1652019-03-25 10:15:59 -07004564 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts)
4565 + in->mmap_time_offset_nanos;
Phil Burkc4714fc2019-02-16 22:28:11 -08004566
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004567exit:
4568 pthread_mutex_unlock(&in->lock);
4569 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004570}
4571
jiabin8962a4d2018-03-19 18:21:24 -07004572static int in_get_active_microphones(const struct audio_stream_in *stream,
4573 struct audio_microphone_characteristic_t *mic_array,
4574 size_t *mic_count) {
4575 struct stream_in *in = (struct stream_in *)stream;
4576 struct audio_device *adev = in->dev;
4577 ALOGVV("%s", __func__);
4578
4579 lock_input_stream(in);
4580 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004581 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004582 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004583 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004584 pthread_mutex_unlock(&adev->lock);
4585 pthread_mutex_unlock(&in->lock);
4586
4587 return ret;
4588}
4589
4590static int adev_get_microphones(const struct audio_hw_device *dev,
4591 struct audio_microphone_characteristic_t *mic_array,
4592 size_t *mic_count) {
4593 struct audio_device *adev = (struct audio_device *)dev;
4594 ALOGVV("%s", __func__);
4595
4596 pthread_mutex_lock(&adev->lock);
4597 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4598 pthread_mutex_unlock(&adev->lock);
4599
4600 return ret;
4601}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004602
Paul McLean57530d52018-12-17 08:24:21 -07004603static int in_set_microphone_direction(const struct audio_stream_in *stream,
4604 audio_microphone_direction_t dir) {
4605 (void)stream;
4606 (void)dir;
4607 ALOGVV("%s", __func__);
4608 return -ENOSYS;
4609}
4610
4611static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
4612 (void)stream;
4613 (void)zoom;
4614 ALOGVV("%s", __func__);
4615 return -ENOSYS;
4616}
4617
juyuchenba338cd2019-01-21 11:57:17 +08004618static void in_update_sink_metadata(struct audio_stream_in *stream,
4619 const struct sink_metadata *sink_metadata) {
4620
4621 if (stream == NULL
4622 || sink_metadata == NULL
4623 || sink_metadata->tracks == NULL) {
4624 return;
4625 }
4626
4627 int error = 0;
4628 struct stream_in *in = (struct stream_in *)stream;
4629 struct audio_device *adev = in->dev;
4630 audio_devices_t device = AUDIO_DEVICE_NONE;
4631
4632 if (sink_metadata->track_count != 0)
4633 device = sink_metadata->tracks->dest_device;
4634
4635 lock_input_stream(in);
4636 pthread_mutex_lock(&adev->lock);
4637 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
4638
4639 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
4640 && device != AUDIO_DEVICE_NONE
4641 && adev->voice_tx_output != NULL) {
4642 /* Use the rx device from afe-proxy record to route voice call because
4643 there is no routing if tx device is on primary hal and rx device
4644 is on other hal during voice call. */
4645 adev->voice_tx_output->devices = device;
4646
4647 if (!voice_is_call_state_active(adev)) {
4648 if (adev->mode == AUDIO_MODE_IN_CALL) {
4649 adev->current_call_output = adev->voice_tx_output;
4650 error = voice_start_call(adev);
4651 if (error != 0)
4652 ALOGE("%s: start voice call failed %d", __func__, error);
4653 }
4654 } else {
4655 adev->current_call_output = adev->voice_tx_output;
4656 voice_update_devices_for_all_voice_usecases(adev);
4657 }
4658 }
4659
4660 pthread_mutex_unlock(&adev->lock);
4661 pthread_mutex_unlock(&in->lock);
4662}
4663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004664static int adev_open_output_stream(struct audio_hw_device *dev,
4665 audio_io_handle_t handle,
4666 audio_devices_t devices,
4667 audio_output_flags_t flags,
4668 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004669 struct audio_stream_out **stream_out,
4670 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004671{
4672 struct audio_device *adev = (struct audio_device *)dev;
4673 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004674 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004675 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4676 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4677 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004678 bool force_haptic_path =
4679 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004680
Andy Hungd9653bd2017-08-01 19:31:39 -07004681 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4682 return -ENOSYS;
4683 }
4684
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004685 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4686 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004688 *stream_out = NULL;
4689 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4690
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004691 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693 if (devices == AUDIO_DEVICE_NONE)
4694 devices = AUDIO_DEVICE_OUT_SPEAKER;
4695
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004696 out->flags = flags;
4697 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004698 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004699 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004700 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004701
4702 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004703 if ((is_hdmi || is_usb_dev) &&
4704 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4705 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4706 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004707 audio_format_t req_format = config->format;
4708 audio_channel_mask_t req_channel_mask = config->channel_mask;
4709 uint32_t req_sample_rate = config->sample_rate;
4710
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004711 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004712 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004713 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004714 if (config->sample_rate == 0)
4715 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004716 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004717 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4718 if (config->format == AUDIO_FORMAT_DEFAULT)
4719 config->format = AUDIO_FORMAT_PCM_16_BIT;
4720 } else if (is_usb_dev) {
4721 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4722 &config->format,
4723 &out->supported_formats[0],
4724 MAX_SUPPORTED_FORMATS,
4725 &config->channel_mask,
4726 &out->supported_channel_masks[0],
4727 MAX_SUPPORTED_CHANNEL_MASKS,
4728 &config->sample_rate,
4729 &out->supported_sample_rates[0],
4730 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004731 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004732 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004733 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004734 if (ret != 0) {
4735 // For MMAP NO IRQ, allow conversions in ADSP
4736 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4737 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004738
Eric Laurentab805ee2018-03-30 12:20:38 -07004739 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4740 config->sample_rate = req_sample_rate;
4741 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4742 config->channel_mask = req_channel_mask;
4743 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4744 config->format = req_format;
4745 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004746
Haynes Mathew George569b7482017-05-08 14:44:27 -07004747 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004748 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004749 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004750 if (is_hdmi) {
4751 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4752 out->config = pcm_config_hdmi_multi;
4753 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4754 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4755 out->config = pcm_config_mmap_playback;
4756 out->stream.start = out_start;
4757 out->stream.stop = out_stop;
4758 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4759 out->stream.get_mmap_position = out_get_mmap_position;
4760 } else {
4761 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4762 out->config = pcm_config_hifi;
4763 }
4764
4765 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004766 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004767 if (is_hdmi) {
4768 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4769 audio_bytes_per_sample(out->format));
4770 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004771 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004772 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004773 pthread_mutex_lock(&adev->lock);
4774 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4775 pthread_mutex_unlock(&adev->lock);
4776
4777 // reject offload during card offline to allow
4778 // fallback to s/w paths
4779 if (offline) {
4780 ret = -ENODEV;
4781 goto error_open;
4782 }
4783
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004784 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4785 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4786 ALOGE("%s: Unsupported Offload information", __func__);
4787 ret = -EINVAL;
4788 goto error_open;
4789 }
4790 if (!is_supported_format(config->offload_info.format)) {
4791 ALOGE("%s: Unsupported audio format", __func__);
4792 ret = -EINVAL;
4793 goto error_open;
4794 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004795 out->sample_rate = config->offload_info.sample_rate;
4796 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4797 out->channel_mask = config->offload_info.channel_mask;
4798 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4799 out->channel_mask = config->channel_mask;
4800 else
4801 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4802
4803 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004804
4805 out->compr_config.codec = (struct snd_codec *)
4806 calloc(1, sizeof(struct snd_codec));
4807
4808 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004809
4810 out->stream.set_callback = out_set_callback;
4811 out->stream.pause = out_pause;
4812 out->stream.resume = out_resume;
4813 out->stream.drain = out_drain;
4814 out->stream.flush = out_flush;
4815
4816 out->compr_config.codec->id =
4817 get_snd_codec_id(config->offload_info.format);
4818 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4819 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004820 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004821 out->compr_config.codec->bit_rate =
4822 config->offload_info.bit_rate;
4823 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004824 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004825 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4826
4827 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4828 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004829
4830 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004831 create_offload_callback_thread(out);
4832 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4833 __func__, config->offload_info.version,
4834 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004835 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4836 switch (config->sample_rate) {
4837 case 0:
4838 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4839 break;
4840 case 8000:
4841 case 16000:
4842 case 48000:
4843 out->sample_rate = config->sample_rate;
4844 break;
4845 default:
4846 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4847 config->sample_rate);
4848 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4849 ret = -EINVAL;
4850 goto error_open;
4851 }
4852 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4853 switch (config->channel_mask) {
4854 case AUDIO_CHANNEL_NONE:
4855 case AUDIO_CHANNEL_OUT_STEREO:
4856 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4857 break;
4858 default:
4859 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4860 config->channel_mask);
4861 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4862 ret = -EINVAL;
4863 goto error_open;
4864 }
4865 switch (config->format) {
4866 case AUDIO_FORMAT_DEFAULT:
4867 case AUDIO_FORMAT_PCM_16_BIT:
4868 out->format = AUDIO_FORMAT_PCM_16_BIT;
4869 break;
4870 default:
4871 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4872 config->format);
4873 config->format = AUDIO_FORMAT_PCM_16_BIT;
4874 ret = -EINVAL;
4875 goto error_open;
4876 }
4877
4878 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004879 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004880 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004881 case 0:
4882 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4883 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004884 case 8000:
4885 case 16000:
4886 case 48000:
4887 out->sample_rate = config->sample_rate;
4888 break;
4889 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004890 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4891 config->sample_rate);
4892 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4893 ret = -EINVAL;
4894 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004895 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004896 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4897 switch (config->channel_mask) {
4898 case AUDIO_CHANNEL_NONE:
4899 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4900 break;
4901 case AUDIO_CHANNEL_OUT_STEREO:
4902 out->channel_mask = config->channel_mask;
4903 break;
4904 default:
4905 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4906 config->channel_mask);
4907 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4908 ret = -EINVAL;
4909 break;
4910 }
4911 switch (config->format) {
4912 case AUDIO_FORMAT_DEFAULT:
4913 out->format = AUDIO_FORMAT_PCM_16_BIT;
4914 break;
4915 case AUDIO_FORMAT_PCM_16_BIT:
4916 out->format = config->format;
4917 break;
4918 default:
4919 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4920 config->format);
4921 config->format = AUDIO_FORMAT_PCM_16_BIT;
4922 ret = -EINVAL;
4923 break;
4924 }
4925 if (ret != 0)
4926 goto error_open;
4927
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004928 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4929 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004930 out->config.rate = out->sample_rate;
4931 out->config.channels =
4932 audio_channel_count_from_out_mask(out->channel_mask);
4933 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004934 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004935 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4936 switch (config->sample_rate) {
4937 case 0:
4938 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4939 break;
4940 case 8000:
4941 case 16000:
4942 case 32000:
4943 case 48000:
4944 out->sample_rate = config->sample_rate;
4945 break;
4946 default:
4947 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4948 config->sample_rate);
4949 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4950 ret = -EINVAL;
4951 break;
4952 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004953 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004954 switch (config->channel_mask) {
4955 case AUDIO_CHANNEL_NONE:
4956 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4957 break;
4958 case AUDIO_CHANNEL_OUT_STEREO:
4959 out->channel_mask = config->channel_mask;
4960 break;
4961 default:
4962 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4963 config->channel_mask);
4964 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4965 ret = -EINVAL;
4966 break;
4967 }
4968 switch (config->format) {
4969 case AUDIO_FORMAT_DEFAULT:
4970 out->format = AUDIO_FORMAT_PCM_16_BIT;
4971 break;
4972 case AUDIO_FORMAT_PCM_16_BIT:
4973 out->format = config->format;
4974 break;
4975 default:
4976 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4977 config->format);
4978 config->format = AUDIO_FORMAT_PCM_16_BIT;
4979 ret = -EINVAL;
4980 break;
4981 }
4982 if (ret != 0)
4983 goto error_open;
4984
vivek mehtaa68fea62017-06-08 19:04:02 -07004985 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004986 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4987 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004988 out->config.rate = out->sample_rate;
4989 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004990 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004991 out->sample_rate,
4992 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004993 out->config.channels,
4994 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004995 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004996 out->config.period_size = buffer_size / frame_size;
4997 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4998 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004999 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005000 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07005001 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5002 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005003 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07005004 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
5005 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005006 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07005007 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005008 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005009 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005010 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08005011 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5012 out->config = pcm_config_mmap_playback;
5013 out->stream.start = out_start;
5014 out->stream.stop = out_stop;
5015 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5016 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005017 } else {
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005018 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5019 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
5020 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
5021 if (adev->haptic_pcm_device_id < 0) {
5022 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
5023 __func__, adev->haptic_pcm_device_id, out->usecase);
5024 ret = -ENOSYS;
5025 goto error_open;
5026 }
5027 out->config = pcm_config_haptics_audio;
5028 if (force_haptic_path)
5029 adev->haptics_config = pcm_config_haptics_audio;
5030 else
5031 adev->haptics_config = pcm_config_haptics;
5032 } else {
5033 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
5034 out->config = pcm_config_low_latency;
5035 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07005036 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005037
5038 if (config->sample_rate == 0) {
5039 out->sample_rate = out->config.rate;
5040 } else {
5041 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005042 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005043
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005044 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
5045 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
5046 } else {
5047 out->channel_mask = config->channel_mask;
5048 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005049
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005050 if (config->format == AUDIO_FORMAT_DEFAULT)
5051 out->format = audio_format_from_pcm_format(out->config.format);
5052 else if (!audio_is_linear_pcm(config->format)) {
5053 config->format = AUDIO_FORMAT_PCM_16_BIT;
5054 ret = -EINVAL;
5055 goto error_open;
5056 } else {
5057 out->format = config->format;
5058 }
5059
5060 out->config.rate = out->sample_rate;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005061
5062 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5063 out->config.channels =
5064 audio_channel_count_from_out_mask(out->channel_mask &
5065 ~AUDIO_CHANNEL_HAPTIC_ALL);
5066
5067 if (force_haptic_path) {
5068 out->config.channels = 1;
5069 adev->haptics_config.channels = 1;
5070 } else {
5071 adev->haptics_config.channels =
5072 audio_channel_count_from_out_mask(out->channel_mask &
5073 AUDIO_CHANNEL_HAPTIC_ALL);
5074 }
5075 } else {
5076 out->config.channels =
5077 audio_channel_count_from_out_mask(out->channel_mask);
5078 }
5079
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005080 if (out->format != audio_format_from_pcm_format(out->config.format)) {
5081 out->config.format = pcm_format_from_audio_format(out->format);
5082 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005083 }
Kevin Rocard50eff892017-05-02 16:52:05 -07005084
5085 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
5086 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005087 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07005088 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
5089 __func__, config->sample_rate, config->format, config->channel_mask);
5090 config->sample_rate = out->sample_rate;
5091 config->format = out->format;
5092 config->channel_mask = out->channel_mask;
5093 ret = -EINVAL;
5094 goto error_open;
5095 }
5096
Andy Hung6fcba9c2014-03-18 11:53:32 -07005097 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
5098 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005099
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005100 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005101 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005102 adev->primary_output = out;
5103 else {
5104 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005105 ret = -EEXIST;
5106 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005107 }
5108 }
5109
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005110 /* Check if this usecase is already existing */
5111 pthread_mutex_lock(&adev->lock);
5112 if (get_usecase_from_list(adev, out->usecase) != NULL) {
5113 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005114 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005115 ret = -EEXIST;
5116 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005117 }
5118 pthread_mutex_unlock(&adev->lock);
5119
5120 out->stream.common.get_sample_rate = out_get_sample_rate;
5121 out->stream.common.set_sample_rate = out_set_sample_rate;
5122 out->stream.common.get_buffer_size = out_get_buffer_size;
5123 out->stream.common.get_channels = out_get_channels;
5124 out->stream.common.get_format = out_get_format;
5125 out->stream.common.set_format = out_set_format;
5126 out->stream.common.standby = out_standby;
5127 out->stream.common.dump = out_dump;
5128 out->stream.common.set_parameters = out_set_parameters;
5129 out->stream.common.get_parameters = out_get_parameters;
5130 out->stream.common.add_audio_effect = out_add_audio_effect;
5131 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5132 out->stream.get_latency = out_get_latency;
5133 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005134#ifdef NO_AUDIO_OUT
5135 out->stream.write = out_write_for_no_output;
5136#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005137 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005138#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005139 out->stream.get_render_position = out_get_render_position;
5140 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005141 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005142
Eric Laurent0e46adf2016-12-16 12:49:24 -08005143 if (out->realtime)
5144 out->af_period_multiplier = af_period_multiplier;
5145 else
5146 out->af_period_multiplier = 1;
5147
Andy Hung572633e2019-02-19 11:58:24 -08005148 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
5149
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005150 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005151 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005152 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005153
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005154 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005155 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005156 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5157
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005158 config->format = out->stream.common.get_format(&out->stream.common);
5159 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5160 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5161
Kevin Rocarda325aa22018-04-03 09:15:52 -07005162 register_format(out->format, out->supported_formats);
5163 register_channel_mask(out->channel_mask, out->supported_channel_masks);
5164 register_sample_rate(out->sample_rate, out->supported_sample_rates);
5165
Andy Hunga452b0a2017-03-15 14:51:15 -07005166 out->error_log = error_log_create(
5167 ERROR_LOG_ENTRIES,
5168 1000000000 /* aggregate consecutive identical errors within one second in ns */);
5169
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005170 /*
5171 By locking output stream before registering, we allow the callback
5172 to update stream's state only after stream's initial state is set to
5173 adev state.
5174 */
5175 lock_output_stream(out);
5176 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5177 pthread_mutex_lock(&adev->lock);
5178 out->card_status = adev->card_status;
5179 pthread_mutex_unlock(&adev->lock);
5180 pthread_mutex_unlock(&out->lock);
5181
vivek mehta4a824772017-06-08 19:05:49 -07005182 stream_app_type_cfg_init(&out->app_type_cfg);
5183
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005184 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005185
Eric Laurent994a6932013-07-17 11:51:42 -07005186 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005187 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005188
5189error_open:
5190 free(out);
5191 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07005192 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005193 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005194}
5195
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005196static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005197 struct audio_stream_out *stream)
5198{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005199 struct stream_out *out = (struct stream_out *)stream;
5200 struct audio_device *adev = out->dev;
5201
Eric Laurent994a6932013-07-17 11:51:42 -07005202 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005203
5204 // must deregister from sndmonitor first to prevent races
5205 // between the callback and close_stream
5206 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005207 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005208 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
5209 destroy_offload_callback_thread(out);
5210
5211 if (out->compr_config.codec != NULL)
5212 free(out->compr_config.codec);
5213 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005214
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005215 out->a2dp_compress_mute = false;
5216
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005217 if (adev->voice_tx_output == out)
5218 adev->voice_tx_output = NULL;
5219
Andy Hunga452b0a2017-03-15 14:51:15 -07005220 error_log_destroy(out->error_log);
5221 out->error_log = NULL;
5222
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005223 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005224 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005225 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005226 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005227 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005228}
5229
5230static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5231{
5232 struct audio_device *adev = (struct audio_device *)dev;
5233 struct str_parms *parms;
5234 char *str;
5235 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005236 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005237 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07005238 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005239 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005240
Joe Onorato188b6222016-03-01 11:02:27 -08005241 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005242
5243 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005244
5245 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005246 status = voice_set_parameters(adev, parms);
5247 if (status != 0) {
5248 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005249 }
5250
5251 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5252 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07005253 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005254 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5255 adev->bluetooth_nrec = true;
5256 else
5257 adev->bluetooth_nrec = false;
5258 }
5259
5260 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5261 if (ret >= 0) {
5262 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5263 adev->screen_off = false;
5264 else
5265 adev->screen_off = true;
5266 }
5267
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005268 ret = str_parms_get_int(parms, "rotation", &val);
5269 if (ret >= 0) {
5270 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005271 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005272 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005273 // FIXME: note that the code below assumes that the speakers are in the correct placement
5274 // relative to the user when the device is rotated 90deg from its default rotation. This
5275 // assumption is device-specific, not platform-specific like this code.
5276 case 270:
5277 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005278 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005279 break;
5280 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005281 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07005282 camera_rotation = CAMERA_ROTATION_PORTRAIT;
5283 break;
5284 case 90:
5285 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005286 break;
5287 default:
5288 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07005289 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005290 }
Eric Laurent03f09432014-03-25 18:09:11 -07005291 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07005292 // check and set swap
5293 // - check if orientation changed and speaker active
5294 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07005295 adev->camera_orientation =
5296 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
5297#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07005298 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07005299#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005300 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005301 }
5302
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005303 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5304 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005305 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005306 }
5307
David Linee3fe402017-03-13 10:00:42 -07005308 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5309 if (ret >= 0) {
5310 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005311 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005312 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5313 if (ret >= 0) {
5314 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005315 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005316 }
Eric Laurent99dab492017-06-17 15:19:08 -07005317 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005318 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5319 if (ret >= 0) {
5320 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005321 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005322 }
5323 }
5324 }
5325
5326 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5327 if (ret >= 0) {
5328 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005329 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005330 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5331 if (ret >= 0) {
5332 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005333 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005334 }
Eric Laurent99dab492017-06-17 15:19:08 -07005335 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005336 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5337 if (ret >= 0) {
5338 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005339 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005340 }
5341 }
5342 }
5343
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08005344 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08005345 audio_extn_ma_set_parameters(adev, parms);
5346
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005347 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
5348 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005349 struct audio_usecase *usecase;
5350 struct listnode *node;
5351 list_for_each(node, &adev->usecase_list) {
5352 usecase = node_to_item(node, struct audio_usecase, list);
5353 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005354 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005355 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
5356
5357 pthread_mutex_unlock(&adev->lock);
5358 lock_output_stream(usecase->stream.out);
5359 pthread_mutex_lock(&adev->lock);
5360 audio_extn_a2dp_set_handoff_mode(true);
5361 // force device switch to reconfigure encoder
5362 select_devices(adev, usecase->id);
5363 audio_extn_a2dp_set_handoff_mode(false);
5364 pthread_mutex_unlock(&usecase->stream.out->lock);
5365 break;
5366 }
5367 }
5368 }
5369
Eric Laurent5f4ca952018-10-19 17:33:43 -07005370 //FIXME: to be replaced by proper video capture properties API
5371 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
5372 if (ret >= 0) {
5373 int camera_facing = CAMERA_FACING_BACK;
5374 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
5375 camera_facing = CAMERA_FACING_FRONT;
5376 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
5377 camera_facing = CAMERA_FACING_BACK;
5378 else {
5379 ALOGW("%s: invalid camera facing value: %s", __func__, value);
5380 goto done;
5381 }
5382 adev->camera_orientation =
5383 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
5384 struct audio_usecase *usecase;
5385 struct listnode *node;
5386 list_for_each(node, &adev->usecase_list) {
5387 usecase = node_to_item(node, struct audio_usecase, list);
5388 struct stream_in *in = usecase->stream.in;
5389 if (usecase->type == PCM_CAPTURE && in != NULL &&
5390 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
5391 select_devices(adev, in->usecase);
5392 }
5393 }
5394 }
5395
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005396done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005397 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005398 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07005399 ALOGV("%s: exit with code(%d)", __func__, status);
5400 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005401}
5402
5403static char* adev_get_parameters(const struct audio_hw_device *dev,
5404 const char *keys)
5405{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005406 struct audio_device *adev = (struct audio_device *)dev;
5407 struct str_parms *reply = str_parms_create();
5408 struct str_parms *query = str_parms_create_str(keys);
5409 char *str;
5410
5411 pthread_mutex_lock(&adev->lock);
5412
5413 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005414 audio_extn_a2dp_get_parameters(query, reply);
5415
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005416 str = str_parms_to_str(reply);
5417 str_parms_destroy(query);
5418 str_parms_destroy(reply);
5419
5420 pthread_mutex_unlock(&adev->lock);
5421 ALOGV("%s: exit: returns - %s", __func__, str);
5422 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005423}
5424
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005425static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005426{
5427 return 0;
5428}
5429
Haynes Mathew George5191a852013-09-11 14:19:36 -07005430static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5431{
5432 int ret;
5433 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005434
Eric Laurent4cc4ce12014-09-10 13:21:01 -05005435 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
5436
Haynes Mathew George5191a852013-09-11 14:19:36 -07005437 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005438 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005439 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005440
Haynes Mathew George5191a852013-09-11 14:19:36 -07005441 return ret;
5442}
5443
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005444static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005445{
5446 return -ENOSYS;
5447}
5448
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005449static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5450 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005451{
5452 return -ENOSYS;
5453}
5454
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005455static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005456{
5457 return -ENOSYS;
5458}
5459
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005460static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005461{
5462 return -ENOSYS;
5463}
5464
5465static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5466{
5467 struct audio_device *adev = (struct audio_device *)dev;
5468
5469 pthread_mutex_lock(&adev->lock);
5470 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07005471 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005472 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005473 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
5474 voice_is_in_call(adev)) {
5475 voice_stop_call(adev);
5476 adev->current_call_output = NULL;
5477 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005478 }
5479 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05005480
5481 audio_extn_extspk_set_mode(adev->extspk, mode);
5482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005483 return 0;
5484}
5485
5486static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5487{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005488 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005489 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005490
Eric Laurent2bafff12016-03-17 12:17:23 -07005491 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005492 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005493 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
5494 ret = audio_extn_hfp_set_mic_mute(adev, state);
5495 } else {
5496 ret = voice_set_mic_mute(adev, state);
5497 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005498 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005499 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005500
5501 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005502}
5503
5504static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5505{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005506 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005507 return 0;
5508}
5509
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005510static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005511 const struct audio_config *config)
5512{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005513 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005514
Eric Laurent74b55762017-07-09 17:04:53 -07005515 /* Don't know if USB HIFI in this context so use true to be conservative */
5516 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5517 true /*is_usb_hifi */) != 0)
5518 return 0;
5519
vivek mehtaa68fea62017-06-08 19:04:02 -07005520 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5521 config->sample_rate, config->format,
5522 channel_count,
5523 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005524}
5525
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005526static bool adev_input_allow_hifi_record(struct audio_device *adev,
5527 audio_devices_t devices,
5528 audio_input_flags_t flags,
5529 audio_source_t source) {
5530 const bool allowed = true;
5531
5532 if (!audio_is_usb_in_device(devices))
5533 return !allowed;
5534
5535 switch (flags) {
5536 case AUDIO_INPUT_FLAG_NONE:
5537 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5538 break;
5539 default:
5540 return !allowed;
5541 }
5542
5543 switch (source) {
5544 case AUDIO_SOURCE_DEFAULT:
5545 case AUDIO_SOURCE_MIC:
5546 case AUDIO_SOURCE_UNPROCESSED:
5547 break;
5548 default:
5549 return !allowed;
5550 }
5551
5552 switch (adev->mode) {
5553 case 0:
5554 break;
5555 default:
5556 return !allowed;
5557 }
5558
5559 return allowed;
5560}
5561
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005562static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005563 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005564 audio_devices_t devices,
5565 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005566 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005567 audio_input_flags_t flags,
5568 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005569 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005570{
5571 struct audio_device *adev = (struct audio_device *)dev;
5572 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005573 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005574 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005575 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005576 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005577 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5578 devices,
5579 flags,
5580 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005581 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5582 " sample_rate %u, channel_mask %#x, format %#x",
5583 __func__, flags, is_usb_dev, may_use_hifi_record,
5584 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005585 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005586
Andy Hungd9653bd2017-08-01 19:31:39 -07005587 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5588 return -ENOSYS;
5589 }
5590
Eric Laurent74b55762017-07-09 17:04:53 -07005591 if (!(is_usb_dev && may_use_hifi_record)) {
5592 if (config->sample_rate == 0)
5593 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5594 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5595 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5596 if (config->format == AUDIO_FORMAT_DEFAULT)
5597 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005598
Eric Laurent74b55762017-07-09 17:04:53 -07005599 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5600
5601 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5602 return -EINVAL;
5603 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005604
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005605 if (audio_extn_tfa_98xx_is_supported() &&
5606 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005607 return -EINVAL;
5608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005609 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5610
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005611 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005612 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005614 in->stream.common.get_sample_rate = in_get_sample_rate;
5615 in->stream.common.set_sample_rate = in_set_sample_rate;
5616 in->stream.common.get_buffer_size = in_get_buffer_size;
5617 in->stream.common.get_channels = in_get_channels;
5618 in->stream.common.get_format = in_get_format;
5619 in->stream.common.set_format = in_set_format;
5620 in->stream.common.standby = in_standby;
5621 in->stream.common.dump = in_dump;
5622 in->stream.common.set_parameters = in_set_parameters;
5623 in->stream.common.get_parameters = in_get_parameters;
5624 in->stream.common.add_audio_effect = in_add_audio_effect;
5625 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5626 in->stream.set_gain = in_set_gain;
5627 in->stream.read = in_read;
5628 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005629 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005630 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLean57530d52018-12-17 08:24:21 -07005631 in->stream.set_microphone_direction = in_set_microphone_direction;
5632 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchenba338cd2019-01-21 11:57:17 +08005633 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005634
5635 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005636 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005637 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005638 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005639 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005640 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005641
Andy Hung88ce1d92018-10-29 18:31:12 -07005642 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005643 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5644 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5645 /* Force channel config requested to mono if incall
5646 record is being requested for only uplink/downlink */
5647 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5648 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5649 ret = -EINVAL;
5650 goto err_open;
5651 }
5652 }
5653
Haynes Mathew George569b7482017-05-08 14:44:27 -07005654 if (is_usb_dev && may_use_hifi_record) {
5655 /* HiFi record selects an appropriate format, channel, rate combo
5656 depending on sink capabilities*/
5657 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5658 &config->format,
5659 &in->supported_formats[0],
5660 MAX_SUPPORTED_FORMATS,
5661 &config->channel_mask,
5662 &in->supported_channel_masks[0],
5663 MAX_SUPPORTED_CHANNEL_MASKS,
5664 &config->sample_rate,
5665 &in->supported_sample_rates[0],
5666 MAX_SUPPORTED_SAMPLE_RATES);
5667 if (ret != 0) {
5668 ret = -EINVAL;
5669 goto err_open;
5670 }
Eric Laurent74b55762017-07-09 17:04:53 -07005671 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005672 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005673 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005674 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5675 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5676 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5677 bool ret_error = false;
5678 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5679 from HAL is 8_24
5680 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5681 8_24 return error indicating supported format is 8_24
5682 *> In case of any other source requesting 24 bit or float return error
5683 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005684
vivek mehta57ff9b52016-04-28 14:13:08 -07005685 on error flinger will retry with supported format passed
5686 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005687 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005688 config->format = AUDIO_FORMAT_PCM_16_BIT;
5689 ret_error = true;
5690 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5691 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5692 ret_error = true;
5693 }
5694
5695 if (ret_error) {
5696 ret = -EINVAL;
5697 goto err_open;
5698 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005699 }
5700
vivek mehta57ff9b52016-04-28 14:13:08 -07005701 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005702 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005704 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005705 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5706 if (config->sample_rate == 0)
5707 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5708 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5709 config->sample_rate != 8000) {
5710 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5711 ret = -EINVAL;
5712 goto err_open;
5713 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005714
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005715 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5716 config->format = AUDIO_FORMAT_PCM_16_BIT;
5717 ret = -EINVAL;
5718 goto err_open;
5719 }
5720
5721 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5722 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005723 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005724 } else if (is_usb_dev && may_use_hifi_record) {
5725 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5726 in->config = pcm_config_audio_capture;
5727 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005728 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5729 config->sample_rate,
5730 config->format,
5731 channel_count,
5732 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005733 in->config.period_size = buffer_size / frame_size;
5734 in->config.rate = config->sample_rate;
5735 in->af_period_multiplier = 1;
5736 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005737 } else {
5738 in->usecase = USECASE_AUDIO_RECORD;
5739 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005740 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005741 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005742#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005743 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005744#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005745 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005746 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005747 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005748 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005749 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5750 config->sample_rate,
5751 config->format,
5752 channel_count,
5753 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005754 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005755 in->config.rate = config->sample_rate;
5756 in->af_period_multiplier = 1;
5757 } else {
5758 // period size is left untouched for rt mode playback
5759 in->config = pcm_config_audio_capture_rt;
5760 in->af_period_multiplier = af_period_multiplier;
5761 }
5762 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5763 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005764 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005765 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5766 in->config = pcm_config_mmap_capture;
5767 in->stream.start = in_start;
5768 in->stream.stop = in_stop;
5769 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5770 in->stream.get_mmap_position = in_get_mmap_position;
5771 in->af_period_multiplier = 1;
5772 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005773 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005774 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005775 (config->sample_rate == 8000 ||
5776 config->sample_rate == 16000 ||
5777 config->sample_rate == 32000 ||
5778 config->sample_rate == 48000) &&
5779 channel_count == 1) {
5780 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5781 in->config = pcm_config_audio_capture;
5782 frame_size = audio_stream_in_frame_size(&in->stream);
5783 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5784 config->sample_rate,
5785 config->format,
5786 channel_count, false /*is_low_latency*/);
5787 in->config.period_size = buffer_size / frame_size;
5788 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5789 in->config.rate = config->sample_rate;
5790 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005791 } else {
5792 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005793 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005794 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5795 config->sample_rate,
5796 config->format,
5797 channel_count,
5798 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005799 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005800 in->config.rate = config->sample_rate;
5801 in->af_period_multiplier = 1;
5802 }
5803 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5804 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005805 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005806
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005807 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005808 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005809
Kevin Rocarda325aa22018-04-03 09:15:52 -07005810
5811 register_format(in->format, in->supported_formats);
5812 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5813 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5814
Andy Hungd13f0d32017-06-12 13:58:37 -07005815 in->error_log = error_log_create(
5816 ERROR_LOG_ENTRIES,
5817 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5818
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005819 /* This stream could be for sound trigger lab,
5820 get sound trigger pcm if present */
5821 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005822
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005823 lock_input_stream(in);
5824 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5825 pthread_mutex_lock(&adev->lock);
5826 in->card_status = adev->card_status;
5827 pthread_mutex_unlock(&adev->lock);
5828 pthread_mutex_unlock(&in->lock);
5829
vivek mehta4a824772017-06-08 19:05:49 -07005830 stream_app_type_cfg_init(&in->app_type_cfg);
5831
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005832 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005833 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005834 return 0;
5835
5836err_open:
5837 free(in);
5838 *stream_in = NULL;
5839 return ret;
5840}
5841
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005842static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005843 struct audio_stream_in *stream)
5844{
Andy Hungd13f0d32017-06-12 13:58:37 -07005845 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005846 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005847
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005848 // must deregister from sndmonitor first to prevent races
5849 // between the callback and close_stream
5850 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005851 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005852
5853 error_log_destroy(in->error_log);
5854 in->error_log = NULL;
5855
Andy Hung0dbb52b2017-08-09 13:51:38 -07005856 pthread_mutex_destroy(&in->pre_lock);
5857 pthread_mutex_destroy(&in->lock);
5858
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005859 free(stream);
5860
5861 return;
5862}
5863
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005864static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005865{
5866 return 0;
5867}
5868
Andy Hung31aca912014-03-20 17:14:59 -07005869/* verifies input and output devices and their capabilities.
5870 *
5871 * This verification is required when enabling extended bit-depth or
5872 * sampling rates, as not all qcom products support it.
5873 *
5874 * Suitable for calling only on initialization such as adev_open().
5875 * It fills the audio_device use_case_table[] array.
5876 *
5877 * Has a side-effect that it needs to configure audio routing / devices
5878 * in order to power up the devices and read the device parameters.
5879 * It does not acquire any hw device lock. Should restore the devices
5880 * back to "normal state" upon completion.
5881 */
5882static int adev_verify_devices(struct audio_device *adev)
5883{
5884 /* enumeration is a bit difficult because one really wants to pull
5885 * the use_case, device id, etc from the hidden pcm_device_table[].
5886 * In this case there are the following use cases and device ids.
5887 *
5888 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5889 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005890 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005891 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5892 * [USECASE_AUDIO_RECORD] = {0, 0},
5893 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5894 * [USECASE_VOICE_CALL] = {2, 2},
5895 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005896 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005897 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5898 */
5899
5900 /* should be the usecases enabled in adev_open_input_stream() */
5901 static const int test_in_usecases[] = {
5902 USECASE_AUDIO_RECORD,
5903 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5904 };
5905 /* should be the usecases enabled in adev_open_output_stream()*/
5906 static const int test_out_usecases[] = {
5907 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5908 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5909 };
5910 static const usecase_type_t usecase_type_by_dir[] = {
5911 PCM_PLAYBACK,
5912 PCM_CAPTURE,
5913 };
5914 static const unsigned flags_by_dir[] = {
5915 PCM_OUT,
5916 PCM_IN,
5917 };
5918
5919 size_t i;
5920 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005921 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005922 char info[512]; /* for possible debug info */
5923
5924 for (dir = 0; dir < 2; ++dir) {
5925 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5926 const unsigned flags_dir = flags_by_dir[dir];
5927 const size_t testsize =
5928 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5929 const int *testcases =
5930 dir ? test_in_usecases : test_out_usecases;
5931 const audio_devices_t audio_device =
5932 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5933
5934 for (i = 0; i < testsize; ++i) {
5935 const audio_usecase_t audio_usecase = testcases[i];
5936 int device_id;
5937 snd_device_t snd_device;
5938 struct pcm_params **pparams;
5939 struct stream_out out;
5940 struct stream_in in;
5941 struct audio_usecase uc_info;
5942 int retval;
5943
5944 pparams = &adev->use_case_table[audio_usecase];
5945 pcm_params_free(*pparams); /* can accept null input */
5946 *pparams = NULL;
5947
5948 /* find the device ID for the use case (signed, for error) */
5949 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5950 if (device_id < 0)
5951 continue;
5952
5953 /* prepare structures for device probing */
5954 memset(&uc_info, 0, sizeof(uc_info));
5955 uc_info.id = audio_usecase;
5956 uc_info.type = usecase_type;
5957 if (dir) {
Andy Hung31aca912014-03-20 17:14:59 -07005958 memset(&in, 0, sizeof(in));
5959 in.device = audio_device;
5960 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5961 uc_info.stream.in = &in;
Andy Hung31aca912014-03-20 17:14:59 -07005962 }
5963 memset(&out, 0, sizeof(out));
5964 out.devices = audio_device; /* only field needed in select_devices */
5965 uc_info.stream.out = &out;
5966 uc_info.devices = audio_device;
5967 uc_info.in_snd_device = SND_DEVICE_NONE;
5968 uc_info.out_snd_device = SND_DEVICE_NONE;
5969 list_add_tail(&adev->usecase_list, &uc_info.list);
5970
5971 /* select device - similar to start_(in/out)put_stream() */
5972 retval = select_devices(adev, audio_usecase);
5973 if (retval >= 0) {
5974 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5975#if LOG_NDEBUG == 0
5976 if (*pparams) {
5977 ALOGV("%s: (%s) card %d device %d", __func__,
5978 dir ? "input" : "output", card_id, device_id);
5979 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005980 } else {
5981 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5982 }
5983#endif
5984 }
5985
5986 /* deselect device - similar to stop_(in/out)put_stream() */
5987 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005988 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005989 /* 2. Disable the rx device */
5990 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005991 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005992 list_remove(&uc_info.list);
5993 }
5994 }
Andy Hung31aca912014-03-20 17:14:59 -07005995 return 0;
5996}
5997
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005998static int adev_close(hw_device_t *device)
5999{
Andy Hung31aca912014-03-20 17:14:59 -07006000 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006001 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006002
6003 if (!adev)
6004 return 0;
6005
6006 pthread_mutex_lock(&adev_init_lock);
6007
6008 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006009 audio_extn_snd_mon_unregister_listener(adev);
6010 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08006011 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006012 audio_route_free(adev->audio_route);
6013 free(adev->snd_dev_ref_cnt);
6014 platform_deinit(adev->platform);
6015 audio_extn_extspk_deinit(adev->extspk);
6016 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006017 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006018 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
6019 pcm_params_free(adev->use_case_table[i]);
6020 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006021 if (adev->adm_deinit)
6022 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07006023 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006024 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07006025 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07006026
6027 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006029 return 0;
6030}
6031
Glenn Kasten4f993392014-05-14 07:30:48 -07006032/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6033 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6034 * just that it _might_ work.
6035 */
6036static int period_size_is_plausible_for_low_latency(int period_size)
6037{
6038 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006039 case 48:
6040 case 96:
6041 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07006042 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006043 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07006044 case 240:
6045 case 320:
6046 case 480:
6047 return 1;
6048 default:
6049 return 0;
6050 }
6051}
6052
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006053static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
6054{
6055 int card;
6056 card_status_t status;
6057
6058 if (!parms)
6059 return;
6060
6061 if (parse_snd_card_status(parms, &card, &status) < 0)
6062 return;
6063
6064 pthread_mutex_lock(&adev->lock);
6065 bool valid_cb = (card == adev->snd_card);
6066 if (valid_cb) {
6067 if (adev->card_status != status) {
6068 adev->card_status = status;
6069 platform_snd_card_update(adev->platform, status);
6070 }
6071 }
6072 pthread_mutex_unlock(&adev->lock);
6073 return;
6074}
6075
Aniket Kumar Lata26483012018-01-31 20:21:42 -08006076/* out and adev lock held */
6077static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6078{
6079 struct audio_usecase *uc_info;
6080 float left_p;
6081 float right_p;
6082 audio_devices_t devices;
6083
6084 uc_info = get_usecase_from_list(adev, out->usecase);
6085 if (uc_info == NULL) {
6086 ALOGE("%s: Could not find the usecase (%d) in the list",
6087 __func__, out->usecase);
6088 return -EINVAL;
6089 }
6090
6091 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6092 out->usecase, use_case_table[out->usecase]);
6093
6094 if (restore) {
6095 // restore A2DP device for active usecases and unmute if required
6096 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6097 !is_a2dp_device(uc_info->out_snd_device)) {
6098 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
6099 select_devices(adev, uc_info->id);
6100 pthread_mutex_lock(&out->compr_mute_lock);
6101 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6102 (out->a2dp_compress_mute)) {
6103 out->a2dp_compress_mute = false;
6104 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6105 }
6106 pthread_mutex_unlock(&out->compr_mute_lock);
6107 }
6108 } else {
6109 // mute compress stream if suspended
6110 pthread_mutex_lock(&out->compr_mute_lock);
6111 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6112 (!out->a2dp_compress_mute)) {
6113 if (!out->standby) {
6114 ALOGD("%s: selecting speaker and muting stream", __func__);
6115 devices = out->devices;
6116 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6117 left_p = out->volume_l;
6118 right_p = out->volume_r;
6119 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6120 compress_pause(out->compr);
6121 set_compr_volume(&out->stream, 0.0f, 0.0f);
6122 out->a2dp_compress_mute = true;
6123 select_devices(adev, out->usecase);
6124 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6125 compress_resume(out->compr);
6126 out->devices = devices;
6127 out->volume_l = left_p;
6128 out->volume_r = right_p;
6129 }
6130 }
6131 pthread_mutex_unlock(&out->compr_mute_lock);
6132 }
6133 ALOGV("%s: exit", __func__);
6134 return 0;
6135}
6136
6137int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6138{
6139 int ret = 0;
6140
6141 lock_output_stream(out);
6142 pthread_mutex_lock(&adev->lock);
6143
6144 ret = check_a2dp_restore_l(adev, out, restore);
6145
6146 pthread_mutex_unlock(&adev->lock);
6147 pthread_mutex_unlock(&out->lock);
6148 return ret;
6149}
6150
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006151static int adev_open(const hw_module_t *module, const char *name,
6152 hw_device_t **device)
6153{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07006154 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006155
Eric Laurent2bafff12016-03-17 12:17:23 -07006156 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006157 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006158 pthread_mutex_lock(&adev_init_lock);
6159 if (audio_device_ref_count != 0) {
6160 *device = &adev->device.common;
6161 audio_device_ref_count++;
6162 ALOGV("%s: returning existing instance of adev", __func__);
6163 ALOGV("%s: exit", __func__);
6164 pthread_mutex_unlock(&adev_init_lock);
6165 return 0;
6166 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006167 adev = calloc(1, sizeof(struct audio_device));
6168
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006169 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6170
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006171 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6172 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6173 adev->device.common.module = (struct hw_module_t *)module;
6174 adev->device.common.close = adev_close;
6175
6176 adev->device.init_check = adev_init_check;
6177 adev->device.set_voice_volume = adev_set_voice_volume;
6178 adev->device.set_master_volume = adev_set_master_volume;
6179 adev->device.get_master_volume = adev_get_master_volume;
6180 adev->device.set_master_mute = adev_set_master_mute;
6181 adev->device.get_master_mute = adev_get_master_mute;
6182 adev->device.set_mode = adev_set_mode;
6183 adev->device.set_mic_mute = adev_set_mic_mute;
6184 adev->device.get_mic_mute = adev_get_mic_mute;
6185 adev->device.set_parameters = adev_set_parameters;
6186 adev->device.get_parameters = adev_get_parameters;
6187 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6188 adev->device.open_output_stream = adev_open_output_stream;
6189 adev->device.close_output_stream = adev_close_output_stream;
6190 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006192 adev->device.close_input_stream = adev_close_input_stream;
6193 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07006194 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006195
6196 /* Set the default route before the PCM stream is opened */
6197 pthread_mutex_lock(&adev->lock);
6198 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006199 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006200 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006201 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006202 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006203 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006204 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006205 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006206 pthread_mutex_unlock(&adev->lock);
6207
6208 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006209 adev->platform = platform_init(adev);
6210 if (!adev->platform) {
6211 free(adev->snd_dev_ref_cnt);
6212 free(adev);
6213 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6214 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006215 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006216 return -EINVAL;
6217 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05006218 adev->extspk = audio_extn_extspk_init(adev);
6219
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006220 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6221 if (adev->visualizer_lib == NULL) {
6222 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6223 } else {
6224 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6225 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07006226 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006227 "visualizer_hal_start_output");
6228 adev->visualizer_stop_output =
6229 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
6230 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07006231 }
6232
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006233 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6234 if (adev->offload_effects_lib == NULL) {
6235 ALOGW("%s: DLOPEN failed for %s", __func__,
6236 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6237 } else {
6238 ALOGV("%s: DLOPEN successful for %s", __func__,
6239 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6240 adev->offload_effects_start_output =
6241 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6242 "offload_effects_bundle_hal_start_output");
6243 adev->offload_effects_stop_output =
6244 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6245 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07006246 }
6247
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006248 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6249 if (adev->adm_lib == NULL) {
6250 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6251 } else {
6252 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6253 adev->adm_init = (adm_init_t)
6254 dlsym(adev->adm_lib, "adm_init");
6255 adev->adm_deinit = (adm_deinit_t)
6256 dlsym(adev->adm_lib, "adm_deinit");
6257 adev->adm_register_input_stream = (adm_register_input_stream_t)
6258 dlsym(adev->adm_lib, "adm_register_input_stream");
6259 adev->adm_register_output_stream = (adm_register_output_stream_t)
6260 dlsym(adev->adm_lib, "adm_register_output_stream");
6261 adev->adm_deregister_stream = (adm_deregister_stream_t)
6262 dlsym(adev->adm_lib, "adm_deregister_stream");
6263 adev->adm_request_focus = (adm_request_focus_t)
6264 dlsym(adev->adm_lib, "adm_request_focus");
6265 adev->adm_abandon_focus = (adm_abandon_focus_t)
6266 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08006267 adev->adm_set_config = (adm_set_config_t)
6268 dlsym(adev->adm_lib, "adm_set_config");
6269 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6270 dlsym(adev->adm_lib, "adm_request_focus_v2");
6271 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6272 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6273 adev->adm_on_routing_change = (adm_on_routing_change_t)
6274 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006275 }
6276
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006277 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05006278 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006279
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006280 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006281
Andy Hung31aca912014-03-20 17:14:59 -07006282 if (k_enable_extended_precision)
6283 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006284
Glenn Kasten4f993392014-05-14 07:30:48 -07006285 char value[PROPERTY_VALUE_MAX];
6286 int trial;
6287 if (property_get("audio_hal.period_size", value, NULL) > 0) {
6288 trial = atoi(value);
6289 if (period_size_is_plausible_for_low_latency(trial)) {
6290 pcm_config_low_latency.period_size = trial;
6291 pcm_config_low_latency.start_threshold = trial / 4;
6292 pcm_config_low_latency.avail_min = trial / 4;
6293 configured_low_latency_capture_period_size = trial;
6294 }
6295 }
6296 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
6297 trial = atoi(value);
6298 if (period_size_is_plausible_for_low_latency(trial)) {
6299 configured_low_latency_capture_period_size = trial;
6300 }
6301 }
6302
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07006303 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
6304
Eric Laurent5f4ca952018-10-19 17:33:43 -07006305 adev->camera_orientation = CAMERA_DEFAULT;
6306
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006307 // commented as full set of app type cfg is sent from platform
6308 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006309 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08006310
6311 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
6312 af_period_multiplier = atoi(value);
6313 if (af_period_multiplier < 0) {
6314 af_period_multiplier = 2;
6315 } else if (af_period_multiplier > 4) {
6316 af_period_multiplier = 4;
6317 }
6318 ALOGV("new period_multiplier = %d", af_period_multiplier);
6319 }
6320
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006321 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08006322 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006323
vivek mehta1a9b7c02015-06-25 11:49:38 -07006324 pthread_mutex_unlock(&adev_init_lock);
6325
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006326 if (adev->adm_init)
6327 adev->adm_data = adev->adm_init();
6328
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006329 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006330 audio_extn_snd_mon_init();
6331 pthread_mutex_lock(&adev->lock);
6332 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
6333 adev->card_status = CARD_STATUS_ONLINE;
6334 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006335 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006336
Eric Laurent2bafff12016-03-17 12:17:23 -07006337 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006338 return 0;
6339}
6340
6341static struct hw_module_methods_t hal_module_methods = {
6342 .open = adev_open,
6343};
6344
6345struct audio_module HAL_MODULE_INFO_SYM = {
6346 .common = {
6347 .tag = HARDWARE_MODULE_TAG,
6348 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6349 .hal_api_version = HARDWARE_HAL_API_VERSION,
6350 .id = AUDIO_HARDWARE_MODULE_ID,
6351 .name = "QCOM Audio HAL",
6352 .author = "Code Aurora Forum",
6353 .methods = &hal_module_methods,
6354 },
6355};