blob: 4b85b21341197f1c3d2c5ce60088aaa401e6c6f1 [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 Burkc4714fc2019-02-16 22:28:11 -08004429// Read offset for the input positional timestamp from a property.
4430// This is to workaround apparent inaccuracies in the timing info that
4431// are causing glitches.
4432static int64_t in_get_mmap_time_offset() {
4433 // Roughly 100 usec is needed on some devices to cover inaccuracy in DSP.
4434 // This should be set in a property. But I cannot read the property!
4435 // So I am setting the offset here to 101 as a test.
4436 const int32_t kDefaultOffsetMicros = 101; // should be zero if no bug
4437 // FIXME - why is the property not being read?! The default is used.
4438 int32_t mmap_time_offset_micros = property_get_int32(
4439 "persist.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
4440 ALOGI("in_get_mmap_time_offset set to %d micros", mmap_time_offset_micros);
4441 return mmap_time_offset_micros * (int64_t)1000;
4442}
4443
Eric Laurent0e46adf2016-12-16 12:49:24 -08004444static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4445 int32_t min_size_frames,
4446 struct audio_mmap_buffer_info *info)
4447{
4448 struct stream_in *in = (struct stream_in *)stream;
4449 struct audio_device *adev = in->dev;
4450 int ret = 0;
4451 unsigned int offset1;
4452 unsigned int frames1;
4453 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004454 uint32_t mmap_size;
4455 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004456
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004457 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004458 pthread_mutex_lock(&adev->lock);
4459 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004460
Eric Laurent0e46adf2016-12-16 12:49:24 -08004461 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004462 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004463 ret = -EINVAL;
4464 goto exit;
4465 }
4466 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004467 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004468 ALOGV("%s in %p", __func__, in);
4469 ret = -ENOSYS;
4470 goto exit;
4471 }
4472 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4473 if (in->pcm_device_id < 0) {
4474 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4475 __func__, in->pcm_device_id, in->usecase);
4476 ret = -EINVAL;
4477 goto exit;
4478 }
Phil Burkbc991042017-02-24 08:06:44 -08004479
4480 adjust_mmap_period_count(&in->config, min_size_frames);
4481
Eric Laurent0e46adf2016-12-16 12:49:24 -08004482 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4483 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4484 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4485 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4486 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4487 step = "open";
4488 ret = -ENODEV;
4489 goto exit;
4490 }
4491
4492 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4493 if (ret < 0) {
4494 step = "begin";
4495 goto exit;
4496 }
4497 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004498 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004499 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004500 ret = platform_get_mmap_data_fd(adev->platform,
4501 in->pcm_device_id, 1 /*capture*/,
4502 &info->shared_memory_fd,
4503 &mmap_size);
4504 if (ret < 0) {
4505 // Fall back to non exclusive mode
4506 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4507 } else {
4508 if (mmap_size < buffer_size) {
4509 step = "mmap";
4510 goto exit;
4511 }
4512 // FIXME: indicate exclusive mode support by returning a negative buffer size
4513 info->buffer_size_frames *= -1;
4514 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004515
Haynes Mathew George96483a22017-03-28 14:52:47 -07004516 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004517
4518 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4519 if (ret < 0) {
4520 step = "commit";
4521 goto exit;
4522 }
4523
Phil Burkc4714fc2019-02-16 22:28:11 -08004524 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
4525
Phil Burkbc991042017-02-24 08:06:44 -08004526 in->standby = false;
4527 ret = 0;
4528
Eric Laurent0e46adf2016-12-16 12:49:24 -08004529 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4530 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004531
4532exit:
4533 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004534 if (in->pcm == NULL) {
4535 ALOGE("%s: %s - %d", __func__, step, ret);
4536 } else {
4537 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004538 pcm_close(in->pcm);
4539 in->pcm = NULL;
4540 }
4541 }
4542 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004543 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004544 return ret;
4545}
4546
4547static int in_get_mmap_position(const struct audio_stream_in *stream,
4548 struct audio_mmap_position *position)
4549{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004550 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004551 struct stream_in *in = (struct stream_in *)stream;
4552 ALOGVV("%s", __func__);
4553 if (position == NULL) {
4554 return -EINVAL;
4555 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004556 lock_input_stream(in);
4557 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4558 in->pcm == NULL) {
4559 ret = -ENOSYS;
4560 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004561 }
4562 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004563 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004564 if (ret < 0) {
4565 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004566 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004567 }
Andy Hungfc044e12017-03-20 09:24:22 -07004568 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Phil Burkc4714fc2019-02-16 22:28:11 -08004569 position->time_nanoseconds += in->mmap_time_offset_nanos;
4570
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004571exit:
4572 pthread_mutex_unlock(&in->lock);
4573 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004574}
4575
jiabin8962a4d2018-03-19 18:21:24 -07004576static int in_get_active_microphones(const struct audio_stream_in *stream,
4577 struct audio_microphone_characteristic_t *mic_array,
4578 size_t *mic_count) {
4579 struct stream_in *in = (struct stream_in *)stream;
4580 struct audio_device *adev = in->dev;
4581 ALOGVV("%s", __func__);
4582
4583 lock_input_stream(in);
4584 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004585 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004586 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004587 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004588 pthread_mutex_unlock(&adev->lock);
4589 pthread_mutex_unlock(&in->lock);
4590
4591 return ret;
4592}
4593
4594static int adev_get_microphones(const struct audio_hw_device *dev,
4595 struct audio_microphone_characteristic_t *mic_array,
4596 size_t *mic_count) {
4597 struct audio_device *adev = (struct audio_device *)dev;
4598 ALOGVV("%s", __func__);
4599
4600 pthread_mutex_lock(&adev->lock);
4601 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4602 pthread_mutex_unlock(&adev->lock);
4603
4604 return ret;
4605}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004606
Paul McLean57530d52018-12-17 08:24:21 -07004607static int in_set_microphone_direction(const struct audio_stream_in *stream,
4608 audio_microphone_direction_t dir) {
4609 (void)stream;
4610 (void)dir;
4611 ALOGVV("%s", __func__);
4612 return -ENOSYS;
4613}
4614
4615static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
4616 (void)stream;
4617 (void)zoom;
4618 ALOGVV("%s", __func__);
4619 return -ENOSYS;
4620}
4621
juyuchenba338cd2019-01-21 11:57:17 +08004622static void in_update_sink_metadata(struct audio_stream_in *stream,
4623 const struct sink_metadata *sink_metadata) {
4624
4625 if (stream == NULL
4626 || sink_metadata == NULL
4627 || sink_metadata->tracks == NULL) {
4628 return;
4629 }
4630
4631 int error = 0;
4632 struct stream_in *in = (struct stream_in *)stream;
4633 struct audio_device *adev = in->dev;
4634 audio_devices_t device = AUDIO_DEVICE_NONE;
4635
4636 if (sink_metadata->track_count != 0)
4637 device = sink_metadata->tracks->dest_device;
4638
4639 lock_input_stream(in);
4640 pthread_mutex_lock(&adev->lock);
4641 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
4642
4643 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
4644 && device != AUDIO_DEVICE_NONE
4645 && adev->voice_tx_output != NULL) {
4646 /* Use the rx device from afe-proxy record to route voice call because
4647 there is no routing if tx device is on primary hal and rx device
4648 is on other hal during voice call. */
4649 adev->voice_tx_output->devices = device;
4650
4651 if (!voice_is_call_state_active(adev)) {
4652 if (adev->mode == AUDIO_MODE_IN_CALL) {
4653 adev->current_call_output = adev->voice_tx_output;
4654 error = voice_start_call(adev);
4655 if (error != 0)
4656 ALOGE("%s: start voice call failed %d", __func__, error);
4657 }
4658 } else {
4659 adev->current_call_output = adev->voice_tx_output;
4660 voice_update_devices_for_all_voice_usecases(adev);
4661 }
4662 }
4663
4664 pthread_mutex_unlock(&adev->lock);
4665 pthread_mutex_unlock(&in->lock);
4666}
4667
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004668static int adev_open_output_stream(struct audio_hw_device *dev,
4669 audio_io_handle_t handle,
4670 audio_devices_t devices,
4671 audio_output_flags_t flags,
4672 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004673 struct audio_stream_out **stream_out,
4674 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004675{
4676 struct audio_device *adev = (struct audio_device *)dev;
4677 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004678 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004679 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4680 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4681 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004682 bool force_haptic_path =
4683 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004684
Andy Hungd9653bd2017-08-01 19:31:39 -07004685 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4686 return -ENOSYS;
4687 }
4688
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004689 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4690 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004691
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004692 *stream_out = NULL;
4693 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4694
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004695 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4696
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004697 if (devices == AUDIO_DEVICE_NONE)
4698 devices = AUDIO_DEVICE_OUT_SPEAKER;
4699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004700 out->flags = flags;
4701 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004702 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004703 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004704 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004705
4706 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004707 if ((is_hdmi || is_usb_dev) &&
4708 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4709 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4710 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004711 audio_format_t req_format = config->format;
4712 audio_channel_mask_t req_channel_mask = config->channel_mask;
4713 uint32_t req_sample_rate = config->sample_rate;
4714
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004715 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004716 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004717 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004718 if (config->sample_rate == 0)
4719 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004720 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004721 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4722 if (config->format == AUDIO_FORMAT_DEFAULT)
4723 config->format = AUDIO_FORMAT_PCM_16_BIT;
4724 } else if (is_usb_dev) {
4725 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4726 &config->format,
4727 &out->supported_formats[0],
4728 MAX_SUPPORTED_FORMATS,
4729 &config->channel_mask,
4730 &out->supported_channel_masks[0],
4731 MAX_SUPPORTED_CHANNEL_MASKS,
4732 &config->sample_rate,
4733 &out->supported_sample_rates[0],
4734 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004735 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004736 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004737 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004738 if (ret != 0) {
4739 // For MMAP NO IRQ, allow conversions in ADSP
4740 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4741 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004742
Eric Laurentab805ee2018-03-30 12:20:38 -07004743 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4744 config->sample_rate = req_sample_rate;
4745 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4746 config->channel_mask = req_channel_mask;
4747 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4748 config->format = req_format;
4749 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004750
Haynes Mathew George569b7482017-05-08 14:44:27 -07004751 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004752 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004753 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004754 if (is_hdmi) {
4755 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4756 out->config = pcm_config_hdmi_multi;
4757 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4758 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4759 out->config = pcm_config_mmap_playback;
4760 out->stream.start = out_start;
4761 out->stream.stop = out_stop;
4762 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4763 out->stream.get_mmap_position = out_get_mmap_position;
4764 } else {
4765 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4766 out->config = pcm_config_hifi;
4767 }
4768
4769 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004770 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004771 if (is_hdmi) {
4772 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4773 audio_bytes_per_sample(out->format));
4774 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004775 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004776 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004777 pthread_mutex_lock(&adev->lock);
4778 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4779 pthread_mutex_unlock(&adev->lock);
4780
4781 // reject offload during card offline to allow
4782 // fallback to s/w paths
4783 if (offline) {
4784 ret = -ENODEV;
4785 goto error_open;
4786 }
4787
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004788 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4789 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4790 ALOGE("%s: Unsupported Offload information", __func__);
4791 ret = -EINVAL;
4792 goto error_open;
4793 }
4794 if (!is_supported_format(config->offload_info.format)) {
4795 ALOGE("%s: Unsupported audio format", __func__);
4796 ret = -EINVAL;
4797 goto error_open;
4798 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004799 out->sample_rate = config->offload_info.sample_rate;
4800 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4801 out->channel_mask = config->offload_info.channel_mask;
4802 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4803 out->channel_mask = config->channel_mask;
4804 else
4805 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4806
4807 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004808
4809 out->compr_config.codec = (struct snd_codec *)
4810 calloc(1, sizeof(struct snd_codec));
4811
4812 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004813
4814 out->stream.set_callback = out_set_callback;
4815 out->stream.pause = out_pause;
4816 out->stream.resume = out_resume;
4817 out->stream.drain = out_drain;
4818 out->stream.flush = out_flush;
4819
4820 out->compr_config.codec->id =
4821 get_snd_codec_id(config->offload_info.format);
4822 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4823 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004824 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004825 out->compr_config.codec->bit_rate =
4826 config->offload_info.bit_rate;
4827 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004828 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004829 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4830
4831 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4832 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004833
4834 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004835 create_offload_callback_thread(out);
4836 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4837 __func__, config->offload_info.version,
4838 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004839 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4840 switch (config->sample_rate) {
4841 case 0:
4842 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4843 break;
4844 case 8000:
4845 case 16000:
4846 case 48000:
4847 out->sample_rate = config->sample_rate;
4848 break;
4849 default:
4850 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4851 config->sample_rate);
4852 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4853 ret = -EINVAL;
4854 goto error_open;
4855 }
4856 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4857 switch (config->channel_mask) {
4858 case AUDIO_CHANNEL_NONE:
4859 case AUDIO_CHANNEL_OUT_STEREO:
4860 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4861 break;
4862 default:
4863 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4864 config->channel_mask);
4865 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4866 ret = -EINVAL;
4867 goto error_open;
4868 }
4869 switch (config->format) {
4870 case AUDIO_FORMAT_DEFAULT:
4871 case AUDIO_FORMAT_PCM_16_BIT:
4872 out->format = AUDIO_FORMAT_PCM_16_BIT;
4873 break;
4874 default:
4875 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4876 config->format);
4877 config->format = AUDIO_FORMAT_PCM_16_BIT;
4878 ret = -EINVAL;
4879 goto error_open;
4880 }
4881
4882 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004883 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004884 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004885 case 0:
4886 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4887 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004888 case 8000:
4889 case 16000:
4890 case 48000:
4891 out->sample_rate = config->sample_rate;
4892 break;
4893 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004894 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4895 config->sample_rate);
4896 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4897 ret = -EINVAL;
4898 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004899 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004900 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4901 switch (config->channel_mask) {
4902 case AUDIO_CHANNEL_NONE:
4903 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4904 break;
4905 case AUDIO_CHANNEL_OUT_STEREO:
4906 out->channel_mask = config->channel_mask;
4907 break;
4908 default:
4909 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4910 config->channel_mask);
4911 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4912 ret = -EINVAL;
4913 break;
4914 }
4915 switch (config->format) {
4916 case AUDIO_FORMAT_DEFAULT:
4917 out->format = AUDIO_FORMAT_PCM_16_BIT;
4918 break;
4919 case AUDIO_FORMAT_PCM_16_BIT:
4920 out->format = config->format;
4921 break;
4922 default:
4923 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4924 config->format);
4925 config->format = AUDIO_FORMAT_PCM_16_BIT;
4926 ret = -EINVAL;
4927 break;
4928 }
4929 if (ret != 0)
4930 goto error_open;
4931
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004932 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4933 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004934 out->config.rate = out->sample_rate;
4935 out->config.channels =
4936 audio_channel_count_from_out_mask(out->channel_mask);
4937 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004938 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004939 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4940 switch (config->sample_rate) {
4941 case 0:
4942 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4943 break;
4944 case 8000:
4945 case 16000:
4946 case 32000:
4947 case 48000:
4948 out->sample_rate = config->sample_rate;
4949 break;
4950 default:
4951 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4952 config->sample_rate);
4953 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4954 ret = -EINVAL;
4955 break;
4956 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004957 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004958 switch (config->channel_mask) {
4959 case AUDIO_CHANNEL_NONE:
4960 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4961 break;
4962 case AUDIO_CHANNEL_OUT_STEREO:
4963 out->channel_mask = config->channel_mask;
4964 break;
4965 default:
4966 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4967 config->channel_mask);
4968 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4969 ret = -EINVAL;
4970 break;
4971 }
4972 switch (config->format) {
4973 case AUDIO_FORMAT_DEFAULT:
4974 out->format = AUDIO_FORMAT_PCM_16_BIT;
4975 break;
4976 case AUDIO_FORMAT_PCM_16_BIT:
4977 out->format = config->format;
4978 break;
4979 default:
4980 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4981 config->format);
4982 config->format = AUDIO_FORMAT_PCM_16_BIT;
4983 ret = -EINVAL;
4984 break;
4985 }
4986 if (ret != 0)
4987 goto error_open;
4988
vivek mehtaa68fea62017-06-08 19:04:02 -07004989 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004990 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4991 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004992 out->config.rate = out->sample_rate;
4993 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004994 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004995 out->sample_rate,
4996 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004997 out->config.channels,
4998 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004999 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07005000 out->config.period_size = buffer_size / frame_size;
5001 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
5002 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005003 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005004 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07005005 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5006 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005007 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07005008 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
5009 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005010 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07005011 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005012 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005013 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005014 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08005015 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5016 out->config = pcm_config_mmap_playback;
5017 out->stream.start = out_start;
5018 out->stream.stop = out_stop;
5019 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5020 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005021 } else {
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005022 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5023 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
5024 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
5025 if (adev->haptic_pcm_device_id < 0) {
5026 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
5027 __func__, adev->haptic_pcm_device_id, out->usecase);
5028 ret = -ENOSYS;
5029 goto error_open;
5030 }
5031 out->config = pcm_config_haptics_audio;
5032 if (force_haptic_path)
5033 adev->haptics_config = pcm_config_haptics_audio;
5034 else
5035 adev->haptics_config = pcm_config_haptics;
5036 } else {
5037 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
5038 out->config = pcm_config_low_latency;
5039 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07005040 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005041
5042 if (config->sample_rate == 0) {
5043 out->sample_rate = out->config.rate;
5044 } else {
5045 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005046 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005047
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005048 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
5049 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
5050 } else {
5051 out->channel_mask = config->channel_mask;
5052 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005053
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005054 if (config->format == AUDIO_FORMAT_DEFAULT)
5055 out->format = audio_format_from_pcm_format(out->config.format);
5056 else if (!audio_is_linear_pcm(config->format)) {
5057 config->format = AUDIO_FORMAT_PCM_16_BIT;
5058 ret = -EINVAL;
5059 goto error_open;
5060 } else {
5061 out->format = config->format;
5062 }
5063
5064 out->config.rate = out->sample_rate;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005065
5066 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5067 out->config.channels =
5068 audio_channel_count_from_out_mask(out->channel_mask &
5069 ~AUDIO_CHANNEL_HAPTIC_ALL);
5070
5071 if (force_haptic_path) {
5072 out->config.channels = 1;
5073 adev->haptics_config.channels = 1;
5074 } else {
5075 adev->haptics_config.channels =
5076 audio_channel_count_from_out_mask(out->channel_mask &
5077 AUDIO_CHANNEL_HAPTIC_ALL);
5078 }
5079 } else {
5080 out->config.channels =
5081 audio_channel_count_from_out_mask(out->channel_mask);
5082 }
5083
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005084 if (out->format != audio_format_from_pcm_format(out->config.format)) {
5085 out->config.format = pcm_format_from_audio_format(out->format);
5086 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005087 }
Kevin Rocard50eff892017-05-02 16:52:05 -07005088
5089 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
5090 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005091 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07005092 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
5093 __func__, config->sample_rate, config->format, config->channel_mask);
5094 config->sample_rate = out->sample_rate;
5095 config->format = out->format;
5096 config->channel_mask = out->channel_mask;
5097 ret = -EINVAL;
5098 goto error_open;
5099 }
5100
Andy Hung6fcba9c2014-03-18 11:53:32 -07005101 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
5102 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005103
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005104 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005105 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005106 adev->primary_output = out;
5107 else {
5108 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005109 ret = -EEXIST;
5110 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005111 }
5112 }
5113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005114 /* Check if this usecase is already existing */
5115 pthread_mutex_lock(&adev->lock);
5116 if (get_usecase_from_list(adev, out->usecase) != NULL) {
5117 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005118 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005119 ret = -EEXIST;
5120 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005121 }
5122 pthread_mutex_unlock(&adev->lock);
5123
5124 out->stream.common.get_sample_rate = out_get_sample_rate;
5125 out->stream.common.set_sample_rate = out_set_sample_rate;
5126 out->stream.common.get_buffer_size = out_get_buffer_size;
5127 out->stream.common.get_channels = out_get_channels;
5128 out->stream.common.get_format = out_get_format;
5129 out->stream.common.set_format = out_set_format;
5130 out->stream.common.standby = out_standby;
5131 out->stream.common.dump = out_dump;
5132 out->stream.common.set_parameters = out_set_parameters;
5133 out->stream.common.get_parameters = out_get_parameters;
5134 out->stream.common.add_audio_effect = out_add_audio_effect;
5135 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5136 out->stream.get_latency = out_get_latency;
5137 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005138#ifdef NO_AUDIO_OUT
5139 out->stream.write = out_write_for_no_output;
5140#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005141 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005142#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005143 out->stream.get_render_position = out_get_render_position;
5144 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005145 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005146
Eric Laurent0e46adf2016-12-16 12:49:24 -08005147 if (out->realtime)
5148 out->af_period_multiplier = af_period_multiplier;
5149 else
5150 out->af_period_multiplier = 1;
5151
Andy Hung572633e2019-02-19 11:58:24 -08005152 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
5153
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005154 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005155 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005156 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005157
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005158 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005159 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005160 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5161
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005162 config->format = out->stream.common.get_format(&out->stream.common);
5163 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5164 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5165
Kevin Rocarda325aa22018-04-03 09:15:52 -07005166 register_format(out->format, out->supported_formats);
5167 register_channel_mask(out->channel_mask, out->supported_channel_masks);
5168 register_sample_rate(out->sample_rate, out->supported_sample_rates);
5169
Andy Hunga452b0a2017-03-15 14:51:15 -07005170 out->error_log = error_log_create(
5171 ERROR_LOG_ENTRIES,
5172 1000000000 /* aggregate consecutive identical errors within one second in ns */);
5173
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005174 /*
5175 By locking output stream before registering, we allow the callback
5176 to update stream's state only after stream's initial state is set to
5177 adev state.
5178 */
5179 lock_output_stream(out);
5180 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5181 pthread_mutex_lock(&adev->lock);
5182 out->card_status = adev->card_status;
5183 pthread_mutex_unlock(&adev->lock);
5184 pthread_mutex_unlock(&out->lock);
5185
vivek mehta4a824772017-06-08 19:05:49 -07005186 stream_app_type_cfg_init(&out->app_type_cfg);
5187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005188 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005189
Eric Laurent994a6932013-07-17 11:51:42 -07005190 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005191 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005192
5193error_open:
5194 free(out);
5195 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07005196 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005197 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005198}
5199
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005200static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005201 struct audio_stream_out *stream)
5202{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005203 struct stream_out *out = (struct stream_out *)stream;
5204 struct audio_device *adev = out->dev;
5205
Eric Laurent994a6932013-07-17 11:51:42 -07005206 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005207
5208 // must deregister from sndmonitor first to prevent races
5209 // between the callback and close_stream
5210 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005211 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005212 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
5213 destroy_offload_callback_thread(out);
5214
5215 if (out->compr_config.codec != NULL)
5216 free(out->compr_config.codec);
5217 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005218
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005219 out->a2dp_compress_mute = false;
5220
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005221 if (adev->voice_tx_output == out)
5222 adev->voice_tx_output = NULL;
5223
Andy Hunga452b0a2017-03-15 14:51:15 -07005224 error_log_destroy(out->error_log);
5225 out->error_log = NULL;
5226
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005227 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005228 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005229 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005230 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005231 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005232}
5233
5234static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5235{
5236 struct audio_device *adev = (struct audio_device *)dev;
5237 struct str_parms *parms;
5238 char *str;
5239 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005240 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005241 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07005242 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005243 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005244
Joe Onorato188b6222016-03-01 11:02:27 -08005245 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005246
5247 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005248
5249 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005250 status = voice_set_parameters(adev, parms);
5251 if (status != 0) {
5252 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005253 }
5254
5255 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5256 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07005257 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005258 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5259 adev->bluetooth_nrec = true;
5260 else
5261 adev->bluetooth_nrec = false;
5262 }
5263
5264 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5265 if (ret >= 0) {
5266 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5267 adev->screen_off = false;
5268 else
5269 adev->screen_off = true;
5270 }
5271
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005272 ret = str_parms_get_int(parms, "rotation", &val);
5273 if (ret >= 0) {
5274 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005275 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005276 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005277 // FIXME: note that the code below assumes that the speakers are in the correct placement
5278 // relative to the user when the device is rotated 90deg from its default rotation. This
5279 // assumption is device-specific, not platform-specific like this code.
5280 case 270:
5281 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005282 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005283 break;
5284 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005285 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07005286 camera_rotation = CAMERA_ROTATION_PORTRAIT;
5287 break;
5288 case 90:
5289 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005290 break;
5291 default:
5292 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07005293 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005294 }
Eric Laurent03f09432014-03-25 18:09:11 -07005295 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07005296 // check and set swap
5297 // - check if orientation changed and speaker active
5298 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07005299 adev->camera_orientation =
5300 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
5301#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07005302 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07005303#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005304 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005305 }
5306
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005307 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5308 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005309 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005310 }
5311
David Linee3fe402017-03-13 10:00:42 -07005312 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5313 if (ret >= 0) {
5314 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005315 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005316 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5317 if (ret >= 0) {
5318 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005319 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005320 }
Eric Laurent99dab492017-06-17 15:19:08 -07005321 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005322 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5323 if (ret >= 0) {
5324 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005325 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005326 }
5327 }
5328 }
5329
5330 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5331 if (ret >= 0) {
5332 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005333 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005334 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5335 if (ret >= 0) {
5336 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005337 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005338 }
Eric Laurent99dab492017-06-17 15:19:08 -07005339 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005340 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5341 if (ret >= 0) {
5342 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005343 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005344 }
5345 }
5346 }
5347
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08005348 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08005349 audio_extn_ma_set_parameters(adev, parms);
5350
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005351 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
5352 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005353 struct audio_usecase *usecase;
5354 struct listnode *node;
5355 list_for_each(node, &adev->usecase_list) {
5356 usecase = node_to_item(node, struct audio_usecase, list);
5357 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005358 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005359 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
5360
5361 pthread_mutex_unlock(&adev->lock);
5362 lock_output_stream(usecase->stream.out);
5363 pthread_mutex_lock(&adev->lock);
5364 audio_extn_a2dp_set_handoff_mode(true);
5365 // force device switch to reconfigure encoder
5366 select_devices(adev, usecase->id);
5367 audio_extn_a2dp_set_handoff_mode(false);
5368 pthread_mutex_unlock(&usecase->stream.out->lock);
5369 break;
5370 }
5371 }
5372 }
5373
Eric Laurent5f4ca952018-10-19 17:33:43 -07005374 //FIXME: to be replaced by proper video capture properties API
5375 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
5376 if (ret >= 0) {
5377 int camera_facing = CAMERA_FACING_BACK;
5378 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
5379 camera_facing = CAMERA_FACING_FRONT;
5380 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
5381 camera_facing = CAMERA_FACING_BACK;
5382 else {
5383 ALOGW("%s: invalid camera facing value: %s", __func__, value);
5384 goto done;
5385 }
5386 adev->camera_orientation =
5387 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
5388 struct audio_usecase *usecase;
5389 struct listnode *node;
5390 list_for_each(node, &adev->usecase_list) {
5391 usecase = node_to_item(node, struct audio_usecase, list);
5392 struct stream_in *in = usecase->stream.in;
5393 if (usecase->type == PCM_CAPTURE && in != NULL &&
5394 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
5395 select_devices(adev, in->usecase);
5396 }
5397 }
5398 }
5399
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005400done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005401 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005402 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07005403 ALOGV("%s: exit with code(%d)", __func__, status);
5404 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005405}
5406
5407static char* adev_get_parameters(const struct audio_hw_device *dev,
5408 const char *keys)
5409{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005410 struct audio_device *adev = (struct audio_device *)dev;
5411 struct str_parms *reply = str_parms_create();
5412 struct str_parms *query = str_parms_create_str(keys);
5413 char *str;
5414
5415 pthread_mutex_lock(&adev->lock);
5416
5417 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005418 audio_extn_a2dp_get_parameters(query, reply);
5419
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005420 str = str_parms_to_str(reply);
5421 str_parms_destroy(query);
5422 str_parms_destroy(reply);
5423
5424 pthread_mutex_unlock(&adev->lock);
5425 ALOGV("%s: exit: returns - %s", __func__, str);
5426 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005427}
5428
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005429static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005430{
5431 return 0;
5432}
5433
Haynes Mathew George5191a852013-09-11 14:19:36 -07005434static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5435{
5436 int ret;
5437 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005438
Eric Laurent4cc4ce12014-09-10 13:21:01 -05005439 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
5440
Haynes Mathew George5191a852013-09-11 14:19:36 -07005441 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005442 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005443 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005444
Haynes Mathew George5191a852013-09-11 14:19:36 -07005445 return ret;
5446}
5447
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005448static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005449{
5450 return -ENOSYS;
5451}
5452
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005453static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5454 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005455{
5456 return -ENOSYS;
5457}
5458
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005459static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005460{
5461 return -ENOSYS;
5462}
5463
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005464static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005465{
5466 return -ENOSYS;
5467}
5468
5469static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5470{
5471 struct audio_device *adev = (struct audio_device *)dev;
5472
5473 pthread_mutex_lock(&adev->lock);
5474 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07005475 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005476 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005477 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
5478 voice_is_in_call(adev)) {
5479 voice_stop_call(adev);
5480 adev->current_call_output = NULL;
5481 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005482 }
5483 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05005484
5485 audio_extn_extspk_set_mode(adev->extspk, mode);
5486
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005487 return 0;
5488}
5489
5490static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5491{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005492 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005493 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005494
Eric Laurent2bafff12016-03-17 12:17:23 -07005495 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005496 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005497 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
5498 ret = audio_extn_hfp_set_mic_mute(adev, state);
5499 } else {
5500 ret = voice_set_mic_mute(adev, state);
5501 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005502 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005503 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005504
5505 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005506}
5507
5508static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5509{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005510 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005511 return 0;
5512}
5513
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005514static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005515 const struct audio_config *config)
5516{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005517 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005518
Eric Laurent74b55762017-07-09 17:04:53 -07005519 /* Don't know if USB HIFI in this context so use true to be conservative */
5520 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5521 true /*is_usb_hifi */) != 0)
5522 return 0;
5523
vivek mehtaa68fea62017-06-08 19:04:02 -07005524 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5525 config->sample_rate, config->format,
5526 channel_count,
5527 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005528}
5529
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005530static bool adev_input_allow_hifi_record(struct audio_device *adev,
5531 audio_devices_t devices,
5532 audio_input_flags_t flags,
5533 audio_source_t source) {
5534 const bool allowed = true;
5535
5536 if (!audio_is_usb_in_device(devices))
5537 return !allowed;
5538
5539 switch (flags) {
5540 case AUDIO_INPUT_FLAG_NONE:
5541 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5542 break;
5543 default:
5544 return !allowed;
5545 }
5546
5547 switch (source) {
5548 case AUDIO_SOURCE_DEFAULT:
5549 case AUDIO_SOURCE_MIC:
5550 case AUDIO_SOURCE_UNPROCESSED:
5551 break;
5552 default:
5553 return !allowed;
5554 }
5555
5556 switch (adev->mode) {
5557 case 0:
5558 break;
5559 default:
5560 return !allowed;
5561 }
5562
5563 return allowed;
5564}
5565
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005566static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005567 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005568 audio_devices_t devices,
5569 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005570 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005571 audio_input_flags_t flags,
5572 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005573 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005574{
5575 struct audio_device *adev = (struct audio_device *)dev;
5576 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005577 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005578 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005579 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005580 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005581 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5582 devices,
5583 flags,
5584 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005585 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5586 " sample_rate %u, channel_mask %#x, format %#x",
5587 __func__, flags, is_usb_dev, may_use_hifi_record,
5588 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005589 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005590
Andy Hungd9653bd2017-08-01 19:31:39 -07005591 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5592 return -ENOSYS;
5593 }
5594
Eric Laurent74b55762017-07-09 17:04:53 -07005595 if (!(is_usb_dev && may_use_hifi_record)) {
5596 if (config->sample_rate == 0)
5597 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5598 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5599 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5600 if (config->format == AUDIO_FORMAT_DEFAULT)
5601 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005602
Eric Laurent74b55762017-07-09 17:04:53 -07005603 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5604
5605 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5606 return -EINVAL;
5607 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005608
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005609 if (audio_extn_tfa_98xx_is_supported() &&
5610 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005611 return -EINVAL;
5612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005613 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5614
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005615 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005616 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005618 in->stream.common.get_sample_rate = in_get_sample_rate;
5619 in->stream.common.set_sample_rate = in_set_sample_rate;
5620 in->stream.common.get_buffer_size = in_get_buffer_size;
5621 in->stream.common.get_channels = in_get_channels;
5622 in->stream.common.get_format = in_get_format;
5623 in->stream.common.set_format = in_set_format;
5624 in->stream.common.standby = in_standby;
5625 in->stream.common.dump = in_dump;
5626 in->stream.common.set_parameters = in_set_parameters;
5627 in->stream.common.get_parameters = in_get_parameters;
5628 in->stream.common.add_audio_effect = in_add_audio_effect;
5629 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5630 in->stream.set_gain = in_set_gain;
5631 in->stream.read = in_read;
5632 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005633 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005634 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLean57530d52018-12-17 08:24:21 -07005635 in->stream.set_microphone_direction = in_set_microphone_direction;
5636 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchenba338cd2019-01-21 11:57:17 +08005637 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005638
5639 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005640 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005641 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005642 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005643 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005644 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005645
Andy Hung88ce1d92018-10-29 18:31:12 -07005646 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005647 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5648 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5649 /* Force channel config requested to mono if incall
5650 record is being requested for only uplink/downlink */
5651 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5652 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5653 ret = -EINVAL;
5654 goto err_open;
5655 }
5656 }
5657
Haynes Mathew George569b7482017-05-08 14:44:27 -07005658 if (is_usb_dev && may_use_hifi_record) {
5659 /* HiFi record selects an appropriate format, channel, rate combo
5660 depending on sink capabilities*/
5661 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5662 &config->format,
5663 &in->supported_formats[0],
5664 MAX_SUPPORTED_FORMATS,
5665 &config->channel_mask,
5666 &in->supported_channel_masks[0],
5667 MAX_SUPPORTED_CHANNEL_MASKS,
5668 &config->sample_rate,
5669 &in->supported_sample_rates[0],
5670 MAX_SUPPORTED_SAMPLE_RATES);
5671 if (ret != 0) {
5672 ret = -EINVAL;
5673 goto err_open;
5674 }
Eric Laurent74b55762017-07-09 17:04:53 -07005675 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005676 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005677 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005678 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5679 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5680 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5681 bool ret_error = false;
5682 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5683 from HAL is 8_24
5684 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5685 8_24 return error indicating supported format is 8_24
5686 *> In case of any other source requesting 24 bit or float return error
5687 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005688
vivek mehta57ff9b52016-04-28 14:13:08 -07005689 on error flinger will retry with supported format passed
5690 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005691 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005692 config->format = AUDIO_FORMAT_PCM_16_BIT;
5693 ret_error = true;
5694 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5695 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5696 ret_error = true;
5697 }
5698
5699 if (ret_error) {
5700 ret = -EINVAL;
5701 goto err_open;
5702 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005703 }
5704
vivek mehta57ff9b52016-04-28 14:13:08 -07005705 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005706 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005707
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005708 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005709 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5710 if (config->sample_rate == 0)
5711 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5712 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5713 config->sample_rate != 8000) {
5714 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5715 ret = -EINVAL;
5716 goto err_open;
5717 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005718
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005719 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5720 config->format = AUDIO_FORMAT_PCM_16_BIT;
5721 ret = -EINVAL;
5722 goto err_open;
5723 }
5724
5725 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5726 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005727 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005728 } else if (is_usb_dev && may_use_hifi_record) {
5729 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5730 in->config = pcm_config_audio_capture;
5731 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005732 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5733 config->sample_rate,
5734 config->format,
5735 channel_count,
5736 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005737 in->config.period_size = buffer_size / frame_size;
5738 in->config.rate = config->sample_rate;
5739 in->af_period_multiplier = 1;
5740 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005741 } else {
5742 in->usecase = USECASE_AUDIO_RECORD;
5743 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005744 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005745 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005746#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005747 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005748#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005749 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005750 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005751 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005752 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005753 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5754 config->sample_rate,
5755 config->format,
5756 channel_count,
5757 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005758 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005759 in->config.rate = config->sample_rate;
5760 in->af_period_multiplier = 1;
5761 } else {
5762 // period size is left untouched for rt mode playback
5763 in->config = pcm_config_audio_capture_rt;
5764 in->af_period_multiplier = af_period_multiplier;
5765 }
5766 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5767 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005768 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005769 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5770 in->config = pcm_config_mmap_capture;
5771 in->stream.start = in_start;
5772 in->stream.stop = in_stop;
5773 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5774 in->stream.get_mmap_position = in_get_mmap_position;
5775 in->af_period_multiplier = 1;
5776 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005777 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005778 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005779 (config->sample_rate == 8000 ||
5780 config->sample_rate == 16000 ||
5781 config->sample_rate == 32000 ||
5782 config->sample_rate == 48000) &&
5783 channel_count == 1) {
5784 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5785 in->config = pcm_config_audio_capture;
5786 frame_size = audio_stream_in_frame_size(&in->stream);
5787 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5788 config->sample_rate,
5789 config->format,
5790 channel_count, false /*is_low_latency*/);
5791 in->config.period_size = buffer_size / frame_size;
5792 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5793 in->config.rate = config->sample_rate;
5794 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005795 } else {
5796 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005797 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005798 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5799 config->sample_rate,
5800 config->format,
5801 channel_count,
5802 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005803 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005804 in->config.rate = config->sample_rate;
5805 in->af_period_multiplier = 1;
5806 }
5807 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5808 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005809 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005810
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005811 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005812 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005813
Kevin Rocarda325aa22018-04-03 09:15:52 -07005814
5815 register_format(in->format, in->supported_formats);
5816 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5817 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5818
Andy Hungd13f0d32017-06-12 13:58:37 -07005819 in->error_log = error_log_create(
5820 ERROR_LOG_ENTRIES,
5821 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5822
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005823 /* This stream could be for sound trigger lab,
5824 get sound trigger pcm if present */
5825 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005826
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005827 lock_input_stream(in);
5828 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5829 pthread_mutex_lock(&adev->lock);
5830 in->card_status = adev->card_status;
5831 pthread_mutex_unlock(&adev->lock);
5832 pthread_mutex_unlock(&in->lock);
5833
vivek mehta4a824772017-06-08 19:05:49 -07005834 stream_app_type_cfg_init(&in->app_type_cfg);
5835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005836 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005837 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005838 return 0;
5839
5840err_open:
5841 free(in);
5842 *stream_in = NULL;
5843 return ret;
5844}
5845
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005846static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005847 struct audio_stream_in *stream)
5848{
Andy Hungd13f0d32017-06-12 13:58:37 -07005849 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005850 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005851
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005852 // must deregister from sndmonitor first to prevent races
5853 // between the callback and close_stream
5854 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005855 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005856
5857 error_log_destroy(in->error_log);
5858 in->error_log = NULL;
5859
Andy Hung0dbb52b2017-08-09 13:51:38 -07005860 pthread_mutex_destroy(&in->pre_lock);
5861 pthread_mutex_destroy(&in->lock);
5862
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005863 free(stream);
5864
5865 return;
5866}
5867
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005868static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005869{
5870 return 0;
5871}
5872
Andy Hung31aca912014-03-20 17:14:59 -07005873/* verifies input and output devices and their capabilities.
5874 *
5875 * This verification is required when enabling extended bit-depth or
5876 * sampling rates, as not all qcom products support it.
5877 *
5878 * Suitable for calling only on initialization such as adev_open().
5879 * It fills the audio_device use_case_table[] array.
5880 *
5881 * Has a side-effect that it needs to configure audio routing / devices
5882 * in order to power up the devices and read the device parameters.
5883 * It does not acquire any hw device lock. Should restore the devices
5884 * back to "normal state" upon completion.
5885 */
5886static int adev_verify_devices(struct audio_device *adev)
5887{
5888 /* enumeration is a bit difficult because one really wants to pull
5889 * the use_case, device id, etc from the hidden pcm_device_table[].
5890 * In this case there are the following use cases and device ids.
5891 *
5892 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5893 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005894 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005895 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5896 * [USECASE_AUDIO_RECORD] = {0, 0},
5897 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5898 * [USECASE_VOICE_CALL] = {2, 2},
5899 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005900 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005901 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5902 */
5903
5904 /* should be the usecases enabled in adev_open_input_stream() */
5905 static const int test_in_usecases[] = {
5906 USECASE_AUDIO_RECORD,
5907 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5908 };
5909 /* should be the usecases enabled in adev_open_output_stream()*/
5910 static const int test_out_usecases[] = {
5911 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5912 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5913 };
5914 static const usecase_type_t usecase_type_by_dir[] = {
5915 PCM_PLAYBACK,
5916 PCM_CAPTURE,
5917 };
5918 static const unsigned flags_by_dir[] = {
5919 PCM_OUT,
5920 PCM_IN,
5921 };
5922
5923 size_t i;
5924 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005925 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005926 char info[512]; /* for possible debug info */
5927
5928 for (dir = 0; dir < 2; ++dir) {
5929 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5930 const unsigned flags_dir = flags_by_dir[dir];
5931 const size_t testsize =
5932 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5933 const int *testcases =
5934 dir ? test_in_usecases : test_out_usecases;
5935 const audio_devices_t audio_device =
5936 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5937
5938 for (i = 0; i < testsize; ++i) {
5939 const audio_usecase_t audio_usecase = testcases[i];
5940 int device_id;
5941 snd_device_t snd_device;
5942 struct pcm_params **pparams;
5943 struct stream_out out;
5944 struct stream_in in;
5945 struct audio_usecase uc_info;
5946 int retval;
5947
5948 pparams = &adev->use_case_table[audio_usecase];
5949 pcm_params_free(*pparams); /* can accept null input */
5950 *pparams = NULL;
5951
5952 /* find the device ID for the use case (signed, for error) */
5953 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5954 if (device_id < 0)
5955 continue;
5956
5957 /* prepare structures for device probing */
5958 memset(&uc_info, 0, sizeof(uc_info));
5959 uc_info.id = audio_usecase;
5960 uc_info.type = usecase_type;
5961 if (dir) {
Andy Hung31aca912014-03-20 17:14:59 -07005962 memset(&in, 0, sizeof(in));
5963 in.device = audio_device;
5964 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5965 uc_info.stream.in = &in;
Andy Hung31aca912014-03-20 17:14:59 -07005966 }
5967 memset(&out, 0, sizeof(out));
5968 out.devices = audio_device; /* only field needed in select_devices */
5969 uc_info.stream.out = &out;
5970 uc_info.devices = audio_device;
5971 uc_info.in_snd_device = SND_DEVICE_NONE;
5972 uc_info.out_snd_device = SND_DEVICE_NONE;
5973 list_add_tail(&adev->usecase_list, &uc_info.list);
5974
5975 /* select device - similar to start_(in/out)put_stream() */
5976 retval = select_devices(adev, audio_usecase);
5977 if (retval >= 0) {
5978 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5979#if LOG_NDEBUG == 0
5980 if (*pparams) {
5981 ALOGV("%s: (%s) card %d device %d", __func__,
5982 dir ? "input" : "output", card_id, device_id);
5983 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005984 } else {
5985 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5986 }
5987#endif
5988 }
5989
5990 /* deselect device - similar to stop_(in/out)put_stream() */
5991 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005992 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005993 /* 2. Disable the rx device */
5994 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005995 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005996 list_remove(&uc_info.list);
5997 }
5998 }
Andy Hung31aca912014-03-20 17:14:59 -07005999 return 0;
6000}
6001
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006002static int adev_close(hw_device_t *device)
6003{
Andy Hung31aca912014-03-20 17:14:59 -07006004 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006005 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006006
6007 if (!adev)
6008 return 0;
6009
6010 pthread_mutex_lock(&adev_init_lock);
6011
6012 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006013 audio_extn_snd_mon_unregister_listener(adev);
6014 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08006015 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006016 audio_route_free(adev->audio_route);
6017 free(adev->snd_dev_ref_cnt);
6018 platform_deinit(adev->platform);
6019 audio_extn_extspk_deinit(adev->extspk);
6020 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006021 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006022 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
6023 pcm_params_free(adev->use_case_table[i]);
6024 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006025 if (adev->adm_deinit)
6026 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07006027 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006028 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07006029 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07006030
6031 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006032
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006033 return 0;
6034}
6035
Glenn Kasten4f993392014-05-14 07:30:48 -07006036/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6037 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6038 * just that it _might_ work.
6039 */
6040static int period_size_is_plausible_for_low_latency(int period_size)
6041{
6042 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006043 case 48:
6044 case 96:
6045 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07006046 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006047 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07006048 case 240:
6049 case 320:
6050 case 480:
6051 return 1;
6052 default:
6053 return 0;
6054 }
6055}
6056
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006057static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
6058{
6059 int card;
6060 card_status_t status;
6061
6062 if (!parms)
6063 return;
6064
6065 if (parse_snd_card_status(parms, &card, &status) < 0)
6066 return;
6067
6068 pthread_mutex_lock(&adev->lock);
6069 bool valid_cb = (card == adev->snd_card);
6070 if (valid_cb) {
6071 if (adev->card_status != status) {
6072 adev->card_status = status;
6073 platform_snd_card_update(adev->platform, status);
6074 }
6075 }
6076 pthread_mutex_unlock(&adev->lock);
6077 return;
6078}
6079
Aniket Kumar Lata26483012018-01-31 20:21:42 -08006080/* out and adev lock held */
6081static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6082{
6083 struct audio_usecase *uc_info;
6084 float left_p;
6085 float right_p;
6086 audio_devices_t devices;
6087
6088 uc_info = get_usecase_from_list(adev, out->usecase);
6089 if (uc_info == NULL) {
6090 ALOGE("%s: Could not find the usecase (%d) in the list",
6091 __func__, out->usecase);
6092 return -EINVAL;
6093 }
6094
6095 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6096 out->usecase, use_case_table[out->usecase]);
6097
6098 if (restore) {
6099 // restore A2DP device for active usecases and unmute if required
6100 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6101 !is_a2dp_device(uc_info->out_snd_device)) {
6102 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
6103 select_devices(adev, uc_info->id);
6104 pthread_mutex_lock(&out->compr_mute_lock);
6105 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6106 (out->a2dp_compress_mute)) {
6107 out->a2dp_compress_mute = false;
6108 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6109 }
6110 pthread_mutex_unlock(&out->compr_mute_lock);
6111 }
6112 } else {
6113 // mute compress stream if suspended
6114 pthread_mutex_lock(&out->compr_mute_lock);
6115 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6116 (!out->a2dp_compress_mute)) {
6117 if (!out->standby) {
6118 ALOGD("%s: selecting speaker and muting stream", __func__);
6119 devices = out->devices;
6120 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6121 left_p = out->volume_l;
6122 right_p = out->volume_r;
6123 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6124 compress_pause(out->compr);
6125 set_compr_volume(&out->stream, 0.0f, 0.0f);
6126 out->a2dp_compress_mute = true;
6127 select_devices(adev, out->usecase);
6128 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6129 compress_resume(out->compr);
6130 out->devices = devices;
6131 out->volume_l = left_p;
6132 out->volume_r = right_p;
6133 }
6134 }
6135 pthread_mutex_unlock(&out->compr_mute_lock);
6136 }
6137 ALOGV("%s: exit", __func__);
6138 return 0;
6139}
6140
6141int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6142{
6143 int ret = 0;
6144
6145 lock_output_stream(out);
6146 pthread_mutex_lock(&adev->lock);
6147
6148 ret = check_a2dp_restore_l(adev, out, restore);
6149
6150 pthread_mutex_unlock(&adev->lock);
6151 pthread_mutex_unlock(&out->lock);
6152 return ret;
6153}
6154
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006155static int adev_open(const hw_module_t *module, const char *name,
6156 hw_device_t **device)
6157{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07006158 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006159
Eric Laurent2bafff12016-03-17 12:17:23 -07006160 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006161 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006162 pthread_mutex_lock(&adev_init_lock);
6163 if (audio_device_ref_count != 0) {
6164 *device = &adev->device.common;
6165 audio_device_ref_count++;
6166 ALOGV("%s: returning existing instance of adev", __func__);
6167 ALOGV("%s: exit", __func__);
6168 pthread_mutex_unlock(&adev_init_lock);
6169 return 0;
6170 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006171 adev = calloc(1, sizeof(struct audio_device));
6172
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006173 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6174
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006175 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6176 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6177 adev->device.common.module = (struct hw_module_t *)module;
6178 adev->device.common.close = adev_close;
6179
6180 adev->device.init_check = adev_init_check;
6181 adev->device.set_voice_volume = adev_set_voice_volume;
6182 adev->device.set_master_volume = adev_set_master_volume;
6183 adev->device.get_master_volume = adev_get_master_volume;
6184 adev->device.set_master_mute = adev_set_master_mute;
6185 adev->device.get_master_mute = adev_get_master_mute;
6186 adev->device.set_mode = adev_set_mode;
6187 adev->device.set_mic_mute = adev_set_mic_mute;
6188 adev->device.get_mic_mute = adev_get_mic_mute;
6189 adev->device.set_parameters = adev_set_parameters;
6190 adev->device.get_parameters = adev_get_parameters;
6191 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6192 adev->device.open_output_stream = adev_open_output_stream;
6193 adev->device.close_output_stream = adev_close_output_stream;
6194 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006196 adev->device.close_input_stream = adev_close_input_stream;
6197 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07006198 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006199
6200 /* Set the default route before the PCM stream is opened */
6201 pthread_mutex_lock(&adev->lock);
6202 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006203 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006204 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006205 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006206 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006207 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006208 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006209 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006210 pthread_mutex_unlock(&adev->lock);
6211
6212 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006213 adev->platform = platform_init(adev);
6214 if (!adev->platform) {
6215 free(adev->snd_dev_ref_cnt);
6216 free(adev);
6217 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6218 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006219 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006220 return -EINVAL;
6221 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05006222 adev->extspk = audio_extn_extspk_init(adev);
6223
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006224 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6225 if (adev->visualizer_lib == NULL) {
6226 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6227 } else {
6228 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6229 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07006230 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006231 "visualizer_hal_start_output");
6232 adev->visualizer_stop_output =
6233 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
6234 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07006235 }
6236
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006237 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6238 if (adev->offload_effects_lib == NULL) {
6239 ALOGW("%s: DLOPEN failed for %s", __func__,
6240 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6241 } else {
6242 ALOGV("%s: DLOPEN successful for %s", __func__,
6243 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6244 adev->offload_effects_start_output =
6245 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6246 "offload_effects_bundle_hal_start_output");
6247 adev->offload_effects_stop_output =
6248 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6249 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07006250 }
6251
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006252 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6253 if (adev->adm_lib == NULL) {
6254 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6255 } else {
6256 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6257 adev->adm_init = (adm_init_t)
6258 dlsym(adev->adm_lib, "adm_init");
6259 adev->adm_deinit = (adm_deinit_t)
6260 dlsym(adev->adm_lib, "adm_deinit");
6261 adev->adm_register_input_stream = (adm_register_input_stream_t)
6262 dlsym(adev->adm_lib, "adm_register_input_stream");
6263 adev->adm_register_output_stream = (adm_register_output_stream_t)
6264 dlsym(adev->adm_lib, "adm_register_output_stream");
6265 adev->adm_deregister_stream = (adm_deregister_stream_t)
6266 dlsym(adev->adm_lib, "adm_deregister_stream");
6267 adev->adm_request_focus = (adm_request_focus_t)
6268 dlsym(adev->adm_lib, "adm_request_focus");
6269 adev->adm_abandon_focus = (adm_abandon_focus_t)
6270 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08006271 adev->adm_set_config = (adm_set_config_t)
6272 dlsym(adev->adm_lib, "adm_set_config");
6273 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6274 dlsym(adev->adm_lib, "adm_request_focus_v2");
6275 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6276 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6277 adev->adm_on_routing_change = (adm_on_routing_change_t)
6278 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006279 }
6280
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006281 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05006282 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006284 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006285
Andy Hung31aca912014-03-20 17:14:59 -07006286 if (k_enable_extended_precision)
6287 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006288
Glenn Kasten4f993392014-05-14 07:30:48 -07006289 char value[PROPERTY_VALUE_MAX];
6290 int trial;
6291 if (property_get("audio_hal.period_size", value, NULL) > 0) {
6292 trial = atoi(value);
6293 if (period_size_is_plausible_for_low_latency(trial)) {
6294 pcm_config_low_latency.period_size = trial;
6295 pcm_config_low_latency.start_threshold = trial / 4;
6296 pcm_config_low_latency.avail_min = trial / 4;
6297 configured_low_latency_capture_period_size = trial;
6298 }
6299 }
6300 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
6301 trial = atoi(value);
6302 if (period_size_is_plausible_for_low_latency(trial)) {
6303 configured_low_latency_capture_period_size = trial;
6304 }
6305 }
6306
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07006307 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
6308
Eric Laurent5f4ca952018-10-19 17:33:43 -07006309 adev->camera_orientation = CAMERA_DEFAULT;
6310
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006311 // commented as full set of app type cfg is sent from platform
6312 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006313 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08006314
6315 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
6316 af_period_multiplier = atoi(value);
6317 if (af_period_multiplier < 0) {
6318 af_period_multiplier = 2;
6319 } else if (af_period_multiplier > 4) {
6320 af_period_multiplier = 4;
6321 }
6322 ALOGV("new period_multiplier = %d", af_period_multiplier);
6323 }
6324
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006325 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08006326 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006327
vivek mehta1a9b7c02015-06-25 11:49:38 -07006328 pthread_mutex_unlock(&adev_init_lock);
6329
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006330 if (adev->adm_init)
6331 adev->adm_data = adev->adm_init();
6332
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006333 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006334 audio_extn_snd_mon_init();
6335 pthread_mutex_lock(&adev->lock);
6336 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
6337 adev->card_status = CARD_STATUS_ONLINE;
6338 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006339 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006340
Eric Laurent2bafff12016-03-17 12:17:23 -07006341 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006342 return 0;
6343}
6344
6345static struct hw_module_methods_t hal_module_methods = {
6346 .open = adev_open,
6347};
6348
6349struct audio_module HAL_MODULE_INFO_SYM = {
6350 .common = {
6351 .tag = HARDWARE_MODULE_TAG,
6352 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6353 .hal_api_version = HARDWARE_HAL_API_VERSION,
6354 .id = AUDIO_HARDWARE_MODULE_ID,
6355 .name = "QCOM Audio HAL",
6356 .author = "Code Aurora Forum",
6357 .methods = &hal_module_methods,
6358 },
6359};