blob: 4d693624f74dc8c69fac5145dc0be29a81cda9a5 [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);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800652 audio_extn_utils_send_audio_calibration(adev, usecase);
Andy Hung11f10e22018-10-19 17:47:12 -0700653
654 // we shouldn't truncate mixer_path
655 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
656 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
657 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800658 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Andy Hung11f10e22018-10-19 17:47:12 -0700659
yixuanjiang509f0a72018-09-06 18:37:23 +0800660 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700661 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700662 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800664 ALOGV("%s: exit", __func__);
665 return 0;
666}
667
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800668int disable_audio_route(struct audio_device *adev,
669 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800670{
yixuanjiang509f0a72018-09-06 18:37:23 +0800671 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700672 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800673
674 if (usecase == NULL)
675 return -EINVAL;
676
677 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800678 if (usecase->type == PCM_CAPTURE)
679 snd_device = usecase->in_snd_device;
680 else
681 snd_device = usecase->out_snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700682
683 // we shouldn't truncate mixer_path
684 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
685 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
686 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800687 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700688 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Andy Hung11f10e22018-10-19 17:47:12 -0700689
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700690 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000691 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800693 ALOGV("%s: exit", __func__);
694 return 0;
695}
696
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800697int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700698 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800699{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700700 int i, num_devices = 0;
701 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800702 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800703 if (snd_device < SND_DEVICE_MIN ||
704 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800705 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800706 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800707 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700708
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700709 platform_send_audio_calibration(adev->platform, snd_device);
710
vivek mehtade4849c2016-03-03 17:23:38 -0800711 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700712 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700713 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800714 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700715 }
716
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700717 /* due to the possibility of calibration overwrite between listen
718 and audio, notify sound trigger hal before audio calibration is sent */
719 audio_extn_sound_trigger_update_device_status(snd_device,
720 ST_EVENT_SND_DEVICE_BUSY);
721
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700722 if (audio_extn_spkr_prot_is_enabled())
723 audio_extn_spkr_prot_calib_cancel(adev);
724
zhaoyang yin4211fad2015-06-04 21:13:25 +0800725 audio_extn_dsm_feedback_enable(adev, snd_device, true);
726
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700727 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800728 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800729 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700730 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
731 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700732 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800733 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700734 }
735 if (audio_extn_spkr_prot_start_processing(snd_device)) {
736 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800737 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700738 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700739 } else if (platform_can_split_snd_device(snd_device,
740 &num_devices,
741 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700742 for (i = 0; i < num_devices; i++) {
743 enable_snd_device(adev, new_snd_devices[i]);
744 }
vivek mehtab6506412015-08-07 16:55:17 -0700745 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700746 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800747 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
748 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
749 ALOGE(" %s: Invalid sound device returned", __func__);
750 goto on_error;
751 }
Ed Tam70b5c142016-03-21 19:14:29 -0700752
Eric Laurent2e140aa2016-06-30 17:14:46 -0700753 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700754
755 if (is_a2dp_device(snd_device) &&
756 (audio_extn_a2dp_start_playback() < 0)) {
757 ALOGE("%s: failed to configure A2DP control path", __func__);
758 goto on_error;
759 }
760
vivek mehtade4849c2016-03-03 17:23:38 -0800761 audio_route_apply_and_update_path(adev->audio_route, device_name);
762 }
763on_success:
764 adev->snd_dev_ref_cnt[snd_device]++;
765 ret_val = 0;
766on_error:
767 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800768}
769
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800770int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700771 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800772{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700773 int i, num_devices = 0;
774 snd_device_t new_snd_devices[2];
775
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800776 if (snd_device < SND_DEVICE_MIN ||
777 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800778 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800779 return -EINVAL;
780 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700781 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
782 ALOGE("%s: device ref cnt is already 0", __func__);
783 return -EINVAL;
784 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800785 audio_extn_tfa_98xx_disable_speaker(snd_device);
786
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700787 adev->snd_dev_ref_cnt[snd_device]--;
788 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800789 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800790
791 if (is_a2dp_device(snd_device))
792 audio_extn_a2dp_stop_playback();
793
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700794 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800795 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700796 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700797 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
798 audio_extn_spkr_prot_is_enabled()) {
799 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700800
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700801 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
802 // and does not use speaker swap. As this code causes a problem with device enable ref
803 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700804 // when speaker device is disabled, reset swap.
805 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700806 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700807
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700808 } else if (platform_can_split_snd_device(snd_device,
809 &num_devices,
810 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700811 for (i = 0; i < num_devices; i++) {
812 disable_snd_device(adev, new_snd_devices[i]);
813 }
vivek mehtab6506412015-08-07 16:55:17 -0700814 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700815 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800816 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
817 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
818 ALOGE(" %s: Invalid sound device returned", __func__);
819 return -EINVAL;
820 }
821
Eric Laurent2e140aa2016-06-30 17:14:46 -0700822 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800823 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700824 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700825 audio_extn_sound_trigger_update_device_status(snd_device,
826 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700827 }
vivek mehtab6506412015-08-07 16:55:17 -0700828
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800829 return 0;
830}
831
Vignesh Kulothungan64698822018-01-23 11:25:18 -0800832#ifdef DYNAMIC_ECNS_ENABLED
833static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
834 struct stream_in *in,
835 struct audio_effect_config effect_config,
836 unsigned int param_value)
837{
838 char mixer_ctl_name[] = "Audio Effect";
839 long set_values[6];
840
841 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
842 if (!ctl) {
843 ALOGE("%s: Could not get mixer ctl - %s",
844 __func__, mixer_ctl_name);
845 return -EINVAL;
846 }
847
848 set_values[0] = 1; //0:Rx 1:Tx
849 set_values[1] = in->app_type_cfg.app_type;
850 set_values[2] = (long)effect_config.module_id;
851 set_values[3] = (long)effect_config.instance_id;
852 set_values[4] = (long)effect_config.param_id;
853 set_values[5] = param_value;
854
855 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
856
857 return 0;
858
859}
860
861static int update_effect_param_ecns(struct audio_usecase *usecase,
862 unsigned int module_id, int effect_type,
863 unsigned int *param_value)
864{
865 int ret = 0;
866 struct audio_effect_config other_effect_config;
867 struct stream_in *in = NULL;
868
869 if (!usecase)
870 return -EINVAL;
871
872 in = usecase->stream.in;
873
874 /* Get the effect config data of the other effect */
875 ret = platform_get_effect_config_data(usecase->in_snd_device,
876 &other_effect_config,
877 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
878 if (ret < 0) {
879 ALOGE("%s Failed to get effect params %d", __func__, ret);
880 return ret;
881 }
882
883 if (module_id == other_effect_config.module_id) {
884 //Same module id for AEC/NS. Values need to be combined
885 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
886 ((effect_type == EFFECT_NS) && (in->enable_aec)))
887 *param_value |= other_effect_config.param_value;
888 }
889
890 return ret;
891}
892
893static int enable_disable_effect(struct audio_device *adev, struct stream_in *in,
894 int effect_type, bool enable)
895{
896 struct audio_effect_config effect_config;
897 struct audio_usecase *usecase = NULL;
898 int ret = 0;
899 unsigned int param_value = 0;
900
901 if (!in) {
902 ALOGE("%s: Invalid input stream", __func__);
903 return -EINVAL;
904 }
905
906 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
907
908 usecase = get_usecase_from_list(adev, in->usecase);
909
910 ret = platform_get_effect_config_data(usecase->in_snd_device,
911 &effect_config, effect_type);
912 if (ret < 0) {
913 ALOGE("%s Failed to get module id %d", __func__, ret);
914 return ret;
915 }
916 ALOGV("%s: module %d app_type %d usecase->id:%d usecase->in_snd_device:%d",
917 __func__, effect_config.module_id, in->app_type_cfg.app_type,
918 usecase->id, usecase->in_snd_device);
919
920 if (enable)
921 param_value = effect_config.param_value;
922
923 /*Special handling for AEC & NS effects Param values need to be
924 updated if module ids are same*/
925
926 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
927 ret = update_effect_param_ecns(usecase, effect_config.module_id,
928 effect_type, &param_value);
929 if (ret < 0)
930 return ret;
931 }
932
933 ret = send_effect_enable_disable_mixer_ctl(adev, in,
934 effect_config, param_value);
935
936 return ret;
937}
938
939static int check_and_enable_effect(struct audio_device *adev)
940{
941 int ret = 0;
942
943 struct listnode *node;
944 struct stream_in *in = NULL;
945
946 list_for_each(node, &adev->usecase_list)
947 {
948 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
949 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
950 in = usecase->stream.in;
951
952 if (in->standby)
953 continue;
954
955 if (in->enable_aec) {
956 ret = enable_disable_effect(adev, in, EFFECT_AEC, true);
957 }
958
959 if (in->enable_ns &&
960 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
961 ret = enable_disable_effect(adev, in, EFFECT_NS, true);
962 }
963 }
964 }
965
966 return ret;
967}
968#else
969#define enable_disable_effect(w, x, y, z) -ENOSYS
970#define check_and_enable_effect(x) -ENOSYS
971#endif
972
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700973/*
974 legend:
975 uc - existing usecase
976 new_uc - new usecase
977 d1, d11, d2 - SND_DEVICE enums
978 a1, a2 - corresponding ANDROID device enums
979 B, B1, B2 - backend strings
980
981case 1
982 uc->dev d1 (a1) B1
983 new_uc->dev d1 (a1), d2 (a2) B1, B2
984
985 resolution: disable and enable uc->dev on d1
986
987case 2
988 uc->dev d1 (a1) B1
989 new_uc->dev d11 (a1) B1
990
991 resolution: need to switch uc since d1 and d11 are related
992 (e.g. speaker and voice-speaker)
993 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
994
995case 3
996 uc->dev d1 (a1) B1
997 new_uc->dev d2 (a2) B2
998
999 resolution: no need to switch uc
1000
1001case 4
1002 uc->dev d1 (a1) B
1003 new_uc->dev d2 (a2) B
1004
1005 resolution: disable enable uc-dev on d2 since backends match
1006 we cannot enable two streams on two different devices if they
1007 share the same backend. e.g. if offload is on speaker device using
1008 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1009 using the same backend, offload must also be switched to voice-handset.
1010
1011case 5
1012 uc->dev d1 (a1) B
1013 new_uc->dev d1 (a1), d2 (a2) B
1014
1015 resolution: disable enable uc-dev on d2 since backends match
1016 we cannot enable two streams on two different devices if they
1017 share the same backend.
1018
1019case 6
1020 uc->dev d1 a1 B1
1021 new_uc->dev d2 a1 B2
1022
1023 resolution: no need to switch
1024
1025case 7
1026
1027 uc->dev d1 (a1), d2 (a2) B1, B2
1028 new_uc->dev d1 B1
1029
1030 resolution: no need to switch
1031
1032*/
1033static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
1034 struct audio_usecase *new_uc,
1035 snd_device_t new_snd_device)
1036{
1037 audio_devices_t a1 = uc->stream.out->devices;
1038 audio_devices_t a2 = new_uc->stream.out->devices;
1039
1040 snd_device_t d1 = uc->out_snd_device;
1041 snd_device_t d2 = new_snd_device;
1042
1043 // Treat as a special case when a1 and a2 are not disjoint
1044 if ((a1 != a2) && (a1 & a2)) {
1045 snd_device_t d3[2];
1046 int num_devices = 0;
1047 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
1048 &num_devices,
1049 d3);
1050 if (ret < 0) {
1051 if (ret != -ENOSYS) {
1052 ALOGW("%s failed to split snd_device %d",
1053 __func__,
1054 popcount(a1) > 1 ? d1 : d2);
1055 }
1056 goto end;
1057 }
1058
1059 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1060 // But if it does happen, we need to give priority to d2 if
1061 // the combo devices active on the existing usecase share a backend.
1062 // This is because we cannot have a usecase active on a combo device
1063 // and a new usecase requests one device in this combo pair.
1064 if (platform_check_backends_match(d3[0], d3[1])) {
1065 return d2; // case 5
1066 } else {
1067 return d1; // case 1
1068 }
1069 } else {
1070 if (platform_check_backends_match(d1, d2)) {
1071 return d2; // case 2, 4
1072 } else {
1073 return d1; // case 6, 3
1074 }
1075 }
1076
1077end:
1078 return d2; // return whatever was calculated before.
1079}
1080
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001081static void check_and_route_playback_usecases(struct audio_device *adev,
1082 struct audio_usecase *uc_info,
1083 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001084{
1085 struct listnode *node;
1086 struct audio_usecase *usecase;
1087 bool switch_device[AUDIO_USECASE_MAX];
1088 int i, num_uc_to_switch = 0;
1089
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001090 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
1091 uc_info,
1092 snd_device);
David Linee3fe402017-03-13 10:00:42 -07001093
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001094 /* For a2dp device reconfigure all active sessions
1095 * with new AFE encoder format based on a2dp state
1096 */
1097 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001098 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1099 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001100 audio_extn_a2dp_is_force_device_switch()) {
1101 force_routing = true;
1102 }
1103
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001104 /*
1105 * This function is to make sure that all the usecases that are active on
1106 * the hardware codec backend are always routed to any one device that is
1107 * handled by the hardware codec.
1108 * For example, if low-latency and deep-buffer usecases are currently active
1109 * on speaker and out_set_parameters(headset) is received on low-latency
1110 * output, then we have to make sure deep-buffer is also switched to headset,
1111 * because of the limitation that both the devices cannot be enabled
1112 * at the same time as they share the same backend.
1113 */
1114 /* Disable all the usecases on the shared backend other than the
1115 specified usecase */
1116 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1117 switch_device[i] = false;
1118
1119 list_for_each(node, &adev->usecase_list) {
1120 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001121 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
1122 continue;
1123
1124 if (force_routing ||
1125 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -07001126 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
1127 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001128 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001129 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1130 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -07001131 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001132 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001133 switch_device[usecase->id] = true;
1134 num_uc_to_switch++;
1135 }
1136 }
1137
1138 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001139 list_for_each(node, &adev->usecase_list) {
1140 usecase = node_to_item(node, struct audio_usecase, list);
1141 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001142 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001143 }
1144 }
1145
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001146 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001147 list_for_each(node, &adev->usecase_list) {
1148 usecase = node_to_item(node, struct audio_usecase, list);
1149 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001150 d_device = derive_playback_snd_device(usecase, uc_info,
1151 snd_device);
1152 enable_snd_device(adev, d_device);
1153 /* Update the out_snd_device before enabling the audio route */
1154 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001155 }
1156 }
1157
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001158 /* Re-route all the usecases on the shared backend other than the
1159 specified usecase to new snd devices */
1160 list_for_each(node, &adev->usecase_list) {
1161 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001162 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001163 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001164 }
1165 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001166 }
1167}
1168
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001169static void check_and_route_capture_usecases(struct audio_device *adev,
1170 struct audio_usecase *uc_info,
1171 snd_device_t snd_device)
1172{
1173 struct listnode *node;
1174 struct audio_usecase *usecase;
1175 bool switch_device[AUDIO_USECASE_MAX];
1176 int i, num_uc_to_switch = 0;
1177
vivek mehta4ed66e62016-04-15 23:33:34 -07001178 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1179
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001180 /*
1181 * This function is to make sure that all the active capture usecases
1182 * are always routed to the same input sound device.
1183 * For example, if audio-record and voice-call usecases are currently
1184 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1185 * is received for voice call then we have to make sure that audio-record
1186 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1187 * because of the limitation that two devices cannot be enabled
1188 * at the same time if they share the same backend.
1189 */
1190 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1191 switch_device[i] = false;
1192
1193 list_for_each(node, &adev->usecase_list) {
1194 usecase = node_to_item(node, struct audio_usecase, list);
1195 if (usecase->type != PCM_PLAYBACK &&
1196 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001197 usecase->in_snd_device != snd_device &&
Carter Hsu0a1160c2018-10-04 09:24:36 +08001198 ((uc_info->type == VOICE_CALL &&
1199 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1200 platform_check_backends_match(snd_device,\
1201 usecase->in_snd_device)) &&
Anish Kumarff864712015-06-03 13:35:11 -07001202 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001203 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1204 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001205 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001206 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001207 switch_device[usecase->id] = true;
1208 num_uc_to_switch++;
1209 }
1210 }
1211
1212 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001213 list_for_each(node, &adev->usecase_list) {
1214 usecase = node_to_item(node, struct audio_usecase, list);
1215 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001216 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001217 }
1218 }
1219
1220 list_for_each(node, &adev->usecase_list) {
1221 usecase = node_to_item(node, struct audio_usecase, list);
1222 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001223 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001224 }
1225 }
1226
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001227 /* Re-route all the usecases on the shared backend other than the
1228 specified usecase to new snd devices */
1229 list_for_each(node, &adev->usecase_list) {
1230 usecase = node_to_item(node, struct audio_usecase, list);
1231 /* Update the in_snd_device only before enabling the audio route */
1232 if (switch_device[usecase->id] ) {
1233 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001234 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001235 }
1236 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001237 }
1238}
1239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001240/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001241static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001242{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001243 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001244 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001245
1246 switch (channels) {
1247 /*
1248 * Do not handle stereo output in Multi-channel cases
1249 * Stereo case is handled in normal playback path
1250 */
1251 case 6:
1252 ALOGV("%s: HDMI supports 5.1", __func__);
1253 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1254 break;
1255 case 8:
1256 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1257 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1258 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1259 break;
1260 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001261 ALOGE("HDMI does not support multi channel playback");
1262 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001263 break;
1264 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001265 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001266}
1267
Andy Hung18859412017-08-09 11:47:21 -07001268static ssize_t read_usb_sup_sample_rates(bool is_playback,
1269 uint32_t *supported_sample_rates,
1270 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001271{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001272 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1273 supported_sample_rates,
1274 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001275#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001276 for (ssize_t i=0; i<count; i++) {
1277 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1278 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001279 }
1280#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001281 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001282}
1283
Haynes Mathew George569b7482017-05-08 14:44:27 -07001284static int read_usb_sup_channel_masks(bool is_playback,
1285 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001286 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001287{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001288 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001289 int channel_count;
1290 uint32_t num_masks = 0;
1291 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1292 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001293 }
Eric Laurent74b55762017-07-09 17:04:53 -07001294 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001295 // start from 2 channels as framework currently doesn't support mono.
1296 // TODO: consider only supporting channel index masks beyond stereo here.
1297 for (channel_count = FCC_2;
1298 channel_count <= channels && num_masks < max_masks;
1299 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001300 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1301 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001302 for (channel_count = FCC_2;
1303 channel_count <= channels && num_masks < max_masks;
1304 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001305 supported_channel_masks[num_masks++] =
1306 audio_channel_mask_for_index_assignment_from_count(channel_count);
1307 }
1308 } else {
1309 // For capture we report all supported channel masks from 1 channel up.
1310 channel_count = MIN_CHANNEL_COUNT;
1311 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1312 // indexed mask
1313 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
Andy Hung88ce1d92018-10-29 18:31:12 -07001314 const audio_channel_mask_t mask =
Eric Laurent74b55762017-07-09 17:04:53 -07001315 audio_channel_in_mask_from_count(channel_count);
Andy Hung88ce1d92018-10-29 18:31:12 -07001316 supported_channel_masks[num_masks++] = mask;
1317 const audio_channel_mask_t index_mask =
1318 audio_channel_mask_for_index_assignment_from_count(channel_count);
1319 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1320 supported_channel_masks[num_masks++] = index_mask;
1321 }
Eric Laurent74b55762017-07-09 17:04:53 -07001322 }
1323 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001324#ifdef NDEBUG
1325 for (size_t i = 0; i < num_masks; ++i) {
1326 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1327 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1328 }
1329#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001330 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001331}
1332
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001333static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001334 audio_format_t *supported_formats,
1335 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001336{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001337 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001338 switch (bitwidth) {
1339 case 24:
1340 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001341 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001342 break;
1343 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001344 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001345 break;
1346 case 16:
1347 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001348 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001349 break;
1350 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001351 ALOGV("%s: %s supported format %d", __func__,
1352 is_playback ? "P" : "C", bitwidth);
1353 return 1;
1354}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001355
Haynes Mathew George569b7482017-05-08 14:44:27 -07001356static int read_usb_sup_params_and_compare(bool is_playback,
1357 audio_format_t *format,
1358 audio_format_t *supported_formats,
1359 uint32_t max_formats,
1360 audio_channel_mask_t *mask,
1361 audio_channel_mask_t *supported_channel_masks,
1362 uint32_t max_masks,
1363 uint32_t *rate,
1364 uint32_t *supported_sample_rates,
1365 uint32_t max_rates) {
1366 int ret = 0;
1367 int num_formats;
1368 int num_masks;
1369 int num_rates;
1370 int i;
1371
1372 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1373 max_formats);
1374 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1375 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001376
Haynes Mathew George569b7482017-05-08 14:44:27 -07001377 num_rates = read_usb_sup_sample_rates(is_playback,
1378 supported_sample_rates, max_rates);
1379
1380#define LUT(table, len, what, dflt) \
1381 for (i=0; i<len && (table[i] != what); i++); \
1382 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1383
1384 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1385 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1386 LUT(supported_sample_rates, num_rates, *rate, 0);
1387
1388#undef LUT
1389 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001390}
1391
Andy Hungd9653bd2017-08-01 19:31:39 -07001392static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1393{
1394 // Check if usb is ready.
1395 // The usb device may have been removed quickly after insertion and hence
1396 // no longer available. This will show up as empty channel masks, or rates.
1397
1398 pthread_mutex_lock(&adev->lock);
1399 uint32_t supported_sample_rate;
1400
1401 // we consider usb ready if we can fetch at least one sample rate.
1402 const bool ready = read_usb_sup_sample_rates(
1403 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1404 pthread_mutex_unlock(&adev->lock);
1405 return ready;
1406}
1407
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001408static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1409{
1410 struct audio_usecase *usecase;
1411 struct listnode *node;
1412
1413 list_for_each(node, &adev->usecase_list) {
1414 usecase = node_to_item(node, struct audio_usecase, list);
1415 if (usecase->type == VOICE_CALL) {
1416 ALOGV("%s: usecase id %d", __func__, usecase->id);
1417 return usecase->id;
1418 }
1419 }
1420 return USECASE_INVALID;
1421}
1422
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001423struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1424 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001425{
1426 struct audio_usecase *usecase;
1427 struct listnode *node;
1428
1429 list_for_each(node, &adev->usecase_list) {
1430 usecase = node_to_item(node, struct audio_usecase, list);
1431 if (usecase->id == uc_id)
1432 return usecase;
1433 }
1434 return NULL;
1435}
1436
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001437static bool force_device_switch(struct audio_usecase *usecase)
1438{
1439 if (usecase->stream.out == NULL) {
1440 ALOGE("%s: stream.out is NULL", __func__);
1441 return false;
1442 }
1443
1444 // Force all A2DP output devices to reconfigure for proper AFE encode format
1445 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1446 // in suspended state, hence try to trigger a retry when we again get a routing request.
1447 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1448 audio_extn_a2dp_is_force_device_switch()) {
1449 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1450 return true;
1451 }
1452
1453 return false;
1454}
1455
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001456struct stream_in *adev_get_active_input(const struct audio_device *adev)
1457{
1458 struct listnode *node;
1459 struct stream_in *last_active_in = NULL;
1460
1461 /* Get last added active input.
1462 * TODO: We may use a priority mechanism to pick highest priority active source */
1463 list_for_each(node, &adev->usecase_list)
1464 {
1465 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1466 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
1467 last_active_in = usecase->stream.in;
1468 }
1469 }
1470
1471 return last_active_in;
1472}
1473
1474struct stream_in *get_voice_communication_input(const struct audio_device *adev)
1475{
1476 struct listnode *node;
1477
1478 /* First check active inputs with voice communication source and then
1479 * any input if audio mode is in communication */
1480 list_for_each(node, &adev->usecase_list)
1481 {
1482 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1483 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
1484 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1485 return usecase->stream.in;
1486 }
1487 }
1488 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
1489 return adev_get_active_input(adev);
1490 }
1491 return NULL;
1492}
1493
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001494int select_devices(struct audio_device *adev,
1495 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001497 snd_device_t out_snd_device = SND_DEVICE_NONE;
1498 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001499 struct audio_usecase *usecase = NULL;
1500 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001501 struct audio_usecase *hfp_usecase = NULL;
1502 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001503 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001504 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001505 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1506 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001507
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001508 usecase = get_usecase_from_list(adev, uc_id);
1509 if (usecase == NULL) {
1510 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1511 return -EINVAL;
1512 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001513
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001514 if ((usecase->type == VOICE_CALL) ||
1515 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001516 out_snd_device = platform_get_output_snd_device(adev->platform,
1517 usecase->stream.out->devices);
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001518 in_snd_device = platform_get_input_snd_device(adev->platform,
1519 NULL,
1520 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001521 usecase->devices = usecase->stream.out->devices;
1522 } else {
1523 /*
1524 * If the voice call is active, use the sound devices of voice call usecase
1525 * so that it would not result any device switch. All the usecases will
1526 * be switched to new device when select_devices() is called for voice call
1527 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001528 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001529 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001530 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001531 vc_usecase = get_usecase_from_list(adev,
1532 get_voice_usecase_id_from_list(adev));
1533 if ((vc_usecase != NULL) &&
1534 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
juyuchend194b432018-11-16 14:15:16 +08001535 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
1536 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001537 in_snd_device = vc_usecase->in_snd_device;
1538 out_snd_device = vc_usecase->out_snd_device;
1539 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001540 } else if (audio_extn_hfp_is_active(adev)) {
1541 hfp_ucid = audio_extn_hfp_get_usecase();
1542 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1543 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1544 in_snd_device = hfp_usecase->in_snd_device;
1545 out_snd_device = hfp_usecase->out_snd_device;
1546 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001547 }
1548 if (usecase->type == PCM_PLAYBACK) {
1549 usecase->devices = usecase->stream.out->devices;
1550 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001551 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001552 struct stream_out *voip_out = adev->primary_output;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001553 struct stream_in *voip_in = get_voice_communication_input(adev);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001554
Eric Laurentb23d5282013-05-14 15:27:20 -07001555 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001556 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001557
1558 if (voip_usecase)
1559 voip_out = voip_usecase->stream.out;
1560
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001561 if (usecase->stream.out == voip_out && voip_in != NULL) {
1562 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001563 }
1564 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001565 } else if (usecase->type == PCM_CAPTURE) {
1566 usecase->devices = usecase->stream.in->device;
1567 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001568 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001569 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001570 struct stream_in *voip_in = get_voice_communication_input(adev);
1571
1572 if (voip_in != NULL) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001573
1574 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1575 USECASE_AUDIO_PLAYBACK_VOIP);
1576
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001577 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001578 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1579 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001580 } else if (voip_usecase) {
1581 out_device = voip_usecase->stream.out->devices;
juyuchend194b432018-11-16 14:15:16 +08001582 } else if (adev->primary_output &&
1583 !adev->primary_output->standby) {
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001584 out_device = adev->primary_output->devices;
juyuchend194b432018-11-16 14:15:16 +08001585 } else {
1586 /* forcing speaker o/p device to get matching i/p pair
1587 in case o/p is not routed from same primary HAL */
1588 out_device = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001589 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001590 }
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001591 in_snd_device = platform_get_input_snd_device(adev->platform,
1592 usecase->stream.in,
1593 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001594 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001595 }
1596 }
1597
1598 if (out_snd_device == usecase->out_snd_device &&
1599 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001600 if (!force_device_switch(usecase))
1601 return 0;
1602 }
1603
1604 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1605 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1606 return 0;
1607 }
1608
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001609 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1610 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001611 (!audio_extn_a2dp_is_ready())) {
1612 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001613 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1614 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1615 else
1616 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001617 }
1618
juyuchen66c4ecf2018-08-06 15:39:34 +08001619 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1620 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1621 }
1622
Eric Laurent2bafff12016-03-17 12:17:23 -07001623 if (out_snd_device != SND_DEVICE_NONE &&
1624 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1625 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1626 __func__,
1627 use_case_table[uc_id],
1628 adev->last_logged_snd_device[uc_id][0],
1629 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1630 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1631 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1632 -1,
1633 out_snd_device,
1634 platform_get_snd_device_name(out_snd_device),
1635 platform_get_snd_device_acdb_id(out_snd_device));
1636 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1637 }
1638 if (in_snd_device != SND_DEVICE_NONE &&
1639 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1640 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1641 __func__,
1642 use_case_table[uc_id],
1643 adev->last_logged_snd_device[uc_id][1],
1644 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1645 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1646 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1647 -1,
1648 in_snd_device,
1649 platform_get_snd_device_name(in_snd_device),
1650 platform_get_snd_device_acdb_id(in_snd_device));
1651 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1652 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001653
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001654 /*
1655 * Limitation: While in call, to do a device switch we need to disable
1656 * and enable both RX and TX devices though one of them is same as current
1657 * device.
1658 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001659 if ((usecase->type == VOICE_CALL) &&
1660 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1661 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001662 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001663 /* Disable sidetone only if voice call already exists */
1664 if (voice_is_call_state_active(adev))
1665 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001666 }
1667
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001668 /* Disable current sound devices */
1669 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001670 disable_audio_route(adev, usecase);
1671 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672 }
1673
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001674 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001675 disable_audio_route(adev, usecase);
1676 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001677 }
1678
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001679 /* Applicable only on the targets that has external modem.
1680 * New device information should be sent to modem before enabling
1681 * the devices to reduce in-call device switch time.
1682 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001683 if ((usecase->type == VOICE_CALL) &&
1684 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1685 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001686 status = platform_switch_voice_call_enable_device_config(adev->platform,
1687 out_snd_device,
1688 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001689 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001690
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001691 /* Enable new sound devices */
1692 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001693 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001694 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1695 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001696 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001697 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698 }
1699
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001700 if (in_snd_device != SND_DEVICE_NONE) {
1701 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001702 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001703 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001704
Eric Laurentb23d5282013-05-14 15:27:20 -07001705 if (usecase->type == VOICE_CALL)
1706 status = platform_switch_voice_call_device_post(adev->platform,
1707 out_snd_device,
1708 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001709
sangwoo170731f2013-06-08 15:36:36 +09001710 usecase->in_snd_device = in_snd_device;
1711 usecase->out_snd_device = out_snd_device;
1712
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001713 audio_extn_tfa_98xx_set_mode();
1714
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001715 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001716
Jasmine Cha70771b62018-05-15 15:02:43 +08001717 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001718
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001719 /* If input stream is already running the effect needs to be
1720 applied on the new input device that's being enabled here. */
1721 if (in_snd_device != SND_DEVICE_NONE)
1722 check_and_enable_effect(adev);
1723
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001724 /* Applicable only on the targets that has external modem.
1725 * Enable device command should be sent to modem only after
1726 * enabling voice call mixer controls
1727 */
vivek mehta765eb642015-08-07 19:46:06 -07001728 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001729 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1730 out_snd_device,
1731 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001732 /* Enable sidetone only if voice call already exists */
1733 if (voice_is_call_state_active(adev))
1734 voice_set_sidetone(adev, out_snd_device, true);
1735 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001736
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001737 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001738 struct stream_out *voip_out = voip_usecase->stream.out;
1739 audio_extn_utils_send_app_type_gain(adev,
1740 voip_out->app_type_cfg.app_type,
1741 &voip_out->app_type_cfg.gain[0]);
1742 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743 return status;
1744}
1745
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001746static int stop_input_stream(struct stream_in *in)
1747{
1748 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749 struct audio_usecase *uc_info;
1750 struct audio_device *adev = in->dev;
1751
Eric Laurent994a6932013-07-17 11:51:42 -07001752 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001753 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001754
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001755 uc_info = get_usecase_from_list(adev, in->usecase);
1756 if (uc_info == NULL) {
1757 ALOGE("%s: Could not find the usecase (%d) in the list",
1758 __func__, in->usecase);
1759 return -EINVAL;
1760 }
1761
vivek mehta781065c2017-04-04 12:55:01 -07001762 /* Close in-call recording streams */
1763 voice_check_and_stop_incall_rec_usecase(adev, in);
1764
Eric Laurent150dbfe2013-02-27 14:31:02 -08001765 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001766 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001767
1768 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001769 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001771 list_remove(&uc_info->list);
1772 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773
Eric Laurent994a6932013-07-17 11:51:42 -07001774 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001775 return ret;
1776}
1777
1778int start_input_stream(struct stream_in *in)
1779{
1780 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001781 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782 struct audio_usecase *uc_info;
1783 struct audio_device *adev = in->dev;
1784
Eric Laurent994a6932013-07-17 11:51:42 -07001785 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001786
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001787 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1788 return -EIO;
1789
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001790 if (in->card_status == CARD_STATUS_OFFLINE ||
1791 adev->card_status == CARD_STATUS_OFFLINE) {
1792 ALOGW("in->card_status or adev->card_status offline, try again");
1793 ret = -EAGAIN;
1794 goto error_config;
1795 }
1796
vivek mehta781065c2017-04-04 12:55:01 -07001797 /* Check if source matches incall recording usecase criteria */
1798 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1799 if (ret)
1800 goto error_config;
1801 else
1802 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1803
Eric Laurentb23d5282013-05-14 15:27:20 -07001804 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001805 if (in->pcm_device_id < 0) {
1806 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1807 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001808 ret = -EINVAL;
1809 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001810 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1813 uc_info->id = in->usecase;
1814 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001815 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001816 uc_info->devices = in->device;
1817 uc_info->in_snd_device = SND_DEVICE_NONE;
1818 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001819
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001820 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001821
Wei Wangf4837d52017-11-21 14:51:20 -08001822 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001823 audio_extn_perf_lock_acquire();
1824
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001825 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826
Eric Laurent0e46adf2016-12-16 12:49:24 -08001827 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001828 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001829 ALOGE("%s: pcm stream not ready", __func__);
1830 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001831 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001832 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001833 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001834 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1835 goto error_open;
1836 }
1837 } else {
1838 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1839 unsigned int pcm_open_retry_count = 0;
1840
1841 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1842 flags |= PCM_MMAP | PCM_NOIRQ;
1843 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1844 } else if (in->realtime) {
1845 flags |= PCM_MMAP | PCM_NOIRQ;
1846 }
1847
1848 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1849 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1850
1851 while (1) {
1852 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1853 flags, &in->config);
1854 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1855 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1856 if (in->pcm != NULL) {
1857 pcm_close(in->pcm);
1858 in->pcm = NULL;
1859 }
1860 if (pcm_open_retry_count-- == 0) {
1861 ret = -EIO;
1862 goto error_open;
1863 }
1864 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1865 continue;
1866 }
1867 break;
1868 }
1869
1870 ALOGV("%s: pcm_prepare", __func__);
1871 ret = pcm_prepare(in->pcm);
1872 if (ret < 0) {
1873 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001874 pcm_close(in->pcm);
1875 in->pcm = NULL;
1876 goto error_open;
1877 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001878 if (in->realtime) {
1879 ret = pcm_start(in->pcm);
1880 if (ret < 0) {
1881 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1882 pcm_close(in->pcm);
1883 in->pcm = NULL;
1884 goto error_open;
1885 }
1886 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001887 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001888 register_in_stream(in);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001889 check_and_enable_effect(adev);
Wei Wangf4837d52017-11-21 14:51:20 -08001890 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001891 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001892 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001893
Eric Laurent0e46adf2016-12-16 12:49:24 -08001894 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001895
1896error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001898 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001899 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001900
1901error_config:
Eric Laurent2bafff12016-03-17 12:17:23 -07001902 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001903 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904}
1905
Eric Laurenta1478072015-09-21 17:21:52 -07001906void lock_input_stream(struct stream_in *in)
1907{
1908 pthread_mutex_lock(&in->pre_lock);
1909 pthread_mutex_lock(&in->lock);
1910 pthread_mutex_unlock(&in->pre_lock);
1911}
1912
1913void lock_output_stream(struct stream_out *out)
1914{
1915 pthread_mutex_lock(&out->pre_lock);
1916 pthread_mutex_lock(&out->lock);
1917 pthread_mutex_unlock(&out->pre_lock);
1918}
1919
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001920/* must be called with out->lock locked */
1921static int send_offload_cmd_l(struct stream_out* out, int command)
1922{
1923 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1924
1925 ALOGVV("%s %d", __func__, command);
1926
1927 cmd->cmd = command;
1928 list_add_tail(&out->offload_cmd_list, &cmd->node);
1929 pthread_cond_signal(&out->offload_cond);
1930 return 0;
1931}
1932
1933/* must be called iwth out->lock locked */
1934static void stop_compressed_output_l(struct stream_out *out)
1935{
1936 out->offload_state = OFFLOAD_STATE_IDLE;
1937 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001938 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001939 if (out->compr != NULL) {
1940 compress_stop(out->compr);
1941 while (out->offload_thread_blocked) {
1942 pthread_cond_wait(&out->cond, &out->lock);
1943 }
1944 }
1945}
1946
1947static void *offload_thread_loop(void *context)
1948{
1949 struct stream_out *out = (struct stream_out *) context;
1950 struct listnode *item;
1951
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001952 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1953 set_sched_policy(0, SP_FOREGROUND);
1954 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1955
1956 ALOGV("%s", __func__);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001957
Eric Laurenta1478072015-09-21 17:21:52 -07001958 lock_output_stream(out);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001959 out->offload_state = OFFLOAD_STATE_IDLE;
1960 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001961 for (;;) {
1962 struct offload_cmd *cmd = NULL;
1963 stream_callback_event_t event;
1964 bool send_callback = false;
1965
1966 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1967 __func__, list_empty(&out->offload_cmd_list),
1968 out->offload_state);
1969 if (list_empty(&out->offload_cmd_list)) {
1970 ALOGV("%s SLEEPING", __func__);
1971 pthread_cond_wait(&out->offload_cond, &out->lock);
1972 ALOGV("%s RUNNING", __func__);
1973 continue;
1974 }
1975
1976 item = list_head(&out->offload_cmd_list);
1977 cmd = node_to_item(item, struct offload_cmd, node);
1978 list_remove(item);
1979
1980 ALOGVV("%s STATE %d CMD %d out->compr %p",
1981 __func__, out->offload_state, cmd->cmd, out->compr);
1982
1983 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1984 free(cmd);
1985 break;
1986 }
1987
1988 if (out->compr == NULL) {
1989 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001990 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001991 pthread_cond_signal(&out->cond);
1992 continue;
1993 }
1994 out->offload_thread_blocked = true;
1995 pthread_mutex_unlock(&out->lock);
1996 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001997 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001998 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1999 compress_wait(out->compr, -1);
2000 send_callback = true;
2001 event = STREAM_CBK_EVENT_WRITE_READY;
2002 break;
2003 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002004 compress_next_track(out->compr);
2005 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002006 send_callback = true;
2007 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002008 /* Resend the metadata for next iteration */
2009 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002010 break;
2011 case OFFLOAD_CMD_DRAIN:
2012 compress_drain(out->compr);
2013 send_callback = true;
2014 event = STREAM_CBK_EVENT_DRAIN_READY;
2015 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002016 case OFFLOAD_CMD_ERROR:
2017 send_callback = true;
2018 event = STREAM_CBK_EVENT_ERROR;
2019 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002020 default:
2021 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2022 break;
2023 }
Eric Laurenta1478072015-09-21 17:21:52 -07002024 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002025 out->offload_thread_blocked = false;
2026 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07002027 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002028 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002029 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002030 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002031 free(cmd);
2032 }
2033
2034 pthread_cond_signal(&out->cond);
2035 while (!list_empty(&out->offload_cmd_list)) {
2036 item = list_head(&out->offload_cmd_list);
2037 list_remove(item);
2038 free(node_to_item(item, struct offload_cmd, node));
2039 }
2040 pthread_mutex_unlock(&out->lock);
2041
2042 return NULL;
2043}
2044
2045static int create_offload_callback_thread(struct stream_out *out)
2046{
2047 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2048 list_init(&out->offload_cmd_list);
2049 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2050 offload_thread_loop, out);
2051 return 0;
2052}
2053
2054static int destroy_offload_callback_thread(struct stream_out *out)
2055{
Eric Laurenta1478072015-09-21 17:21:52 -07002056 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002057 stop_compressed_output_l(out);
2058 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2059
2060 pthread_mutex_unlock(&out->lock);
2061 pthread_join(out->offload_thread, (void **) NULL);
2062 pthread_cond_destroy(&out->offload_cond);
2063
2064 return 0;
2065}
2066
Eric Laurent07eeafd2013-10-06 12:52:49 -07002067static bool allow_hdmi_channel_config(struct audio_device *adev)
2068{
2069 struct listnode *node;
2070 struct audio_usecase *usecase;
2071 bool ret = true;
2072
2073 list_for_each(node, &adev->usecase_list) {
2074 usecase = node_to_item(node, struct audio_usecase, list);
2075 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2076 /*
2077 * If voice call is already existing, do not proceed further to avoid
2078 * disabling/enabling both RX and TX devices, CSD calls, etc.
2079 * Once the voice call done, the HDMI channels can be configured to
2080 * max channels of remaining use cases.
2081 */
2082 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08002083 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07002084 __func__);
2085 ret = false;
2086 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002087 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
2088 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07002089 "no change in HDMI channels", __func__);
2090 ret = false;
2091 break;
2092 }
2093 }
2094 }
2095 return ret;
2096}
2097
2098static int check_and_set_hdmi_channels(struct audio_device *adev,
2099 unsigned int channels)
2100{
2101 struct listnode *node;
2102 struct audio_usecase *usecase;
2103
2104 /* Check if change in HDMI channel config is allowed */
2105 if (!allow_hdmi_channel_config(adev))
2106 return 0;
2107
2108 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08002109 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002110 return 0;
2111 }
2112
2113 platform_set_hdmi_channels(adev->platform, channels);
2114 adev->cur_hdmi_channels = channels;
2115
2116 /*
2117 * Deroute all the playback streams routed to HDMI so that
2118 * the back end is deactivated. Note that backend will not
2119 * be deactivated if any one stream is connected to it.
2120 */
2121 list_for_each(node, &adev->usecase_list) {
2122 usecase = node_to_item(node, struct audio_usecase, list);
2123 if (usecase->type == PCM_PLAYBACK &&
2124 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002125 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002126 }
2127 }
2128
2129 /*
2130 * Enable all the streams disabled above. Now the HDMI backend
2131 * will be activated with new channel configuration
2132 */
2133 list_for_each(node, &adev->usecase_list) {
2134 usecase = node_to_item(node, struct audio_usecase, list);
2135 if (usecase->type == PCM_PLAYBACK &&
2136 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002137 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002138 }
2139 }
2140
2141 return 0;
2142}
2143
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002144static int check_and_set_usb_service_interval(struct audio_device *adev,
2145 struct audio_usecase *uc_info,
2146 bool min)
2147{
2148 struct listnode *node;
2149 struct audio_usecase *usecase;
2150 bool switch_usecases = false;
2151 bool reconfig = false;
2152
2153 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
2154 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
2155 return -1;
2156
2157 /* set if the valid usecase do not already exist */
2158 list_for_each(node, &adev->usecase_list) {
2159 usecase = node_to_item(node, struct audio_usecase, list);
2160 if (usecase->type == PCM_PLAYBACK &&
2161 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
2162 switch (usecase->id) {
2163 case USECASE_AUDIO_PLAYBACK_MMAP:
2164 case USECASE_AUDIO_PLAYBACK_ULL:
2165 // cannot reconfig while mmap/ull is present.
2166 return -1;
2167 default:
2168 switch_usecases = true;
2169 break;
2170 }
2171 }
2172 if (switch_usecases)
2173 break;
2174 }
2175 /*
2176 * client can try to set service interval in start_output_stream
2177 * to min or to 0 (i.e reset) in stop_output_stream .
2178 */
2179 unsigned long service_interval =
2180 audio_extn_usb_find_service_interval(min, true /*playback*/);
2181 int ret = platform_set_usb_service_interval(adev->platform,
2182 true /*playback*/,
2183 service_interval,
2184 &reconfig);
2185 /* no change or not supported or no active usecases */
2186 if (ret || !reconfig || !switch_usecases)
2187 return -1;
2188 return 0;
2189#undef VALID_USECASE
2190}
2191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192static int stop_output_stream(struct stream_out *out)
2193{
2194 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195 struct audio_usecase *uc_info;
2196 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08002197 bool has_voip_usecase =
2198 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002199
Eric Laurent994a6932013-07-17 11:51:42 -07002200 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002201 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002202 uc_info = get_usecase_from_list(adev, out->usecase);
2203 if (uc_info == NULL) {
2204 ALOGE("%s: Could not find the usecase (%d) in the list",
2205 __func__, out->usecase);
2206 return -EINVAL;
2207 }
2208
Haynes Mathew George41f86652014-06-17 14:22:15 -07002209 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2210 if (adev->visualizer_stop_output != NULL)
2211 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
2212 if (adev->offload_effects_stop_output != NULL)
2213 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002214 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2215 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2216 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07002217 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002218
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002219 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2220 voice_set_device_mute_flag(adev, false);
2221
Eric Laurent150dbfe2013-02-27 14:31:02 -08002222 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002223 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002224
2225 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002226 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002228 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229
Eric Laurent0499d4f2014-08-25 22:39:29 -05002230 audio_extn_extspk_update(adev->extspk);
2231
Eric Laurent07eeafd2013-10-06 12:52:49 -07002232 /* Must be called after removing the usecase from list */
2233 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2234 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002235 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002236 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2237 if (ret == 0) {
2238 /* default service interval was successfully updated,
2239 reopen USB backend with new service interval */
2240 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2241 }
2242 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002243 }
juyuchend194b432018-11-16 14:15:16 +08002244 /* 1) media + voip output routing to handset must route media back to
2245 speaker when voip stops.
2246 2) trigger voip input to reroute when voip output changes to
2247 hearing aid. */
HW Lee88512e92018-06-12 15:26:09 +08002248 if (has_voip_usecase ||
2249 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2250 struct listnode *node;
2251 struct audio_usecase *usecase;
2252 list_for_each(node, &adev->usecase_list) {
2253 usecase = node_to_item(node, struct audio_usecase, list);
juyuchend194b432018-11-16 14:15:16 +08002254 if ((usecase->type == PCM_CAPTURE &&
2255 usecase->id != USECASE_AUDIO_RECORD_VOIP)
2256 || usecase == uc_info)
HW Lee88512e92018-06-12 15:26:09 +08002257 continue;
2258
2259 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2260 __func__, usecase->id, use_case_table[usecase->id],
2261 out->usecase, use_case_table[out->usecase]);
2262 select_devices(adev, usecase->id);
2263 }
2264 }
2265
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002266 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002267 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002268 return ret;
2269}
2270
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002271struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
2272 unsigned int flags, unsigned int pcm_open_retry_count,
2273 struct pcm_config *config)
2274{
2275 struct pcm* pcm = NULL;
2276
2277 while (1) {
2278 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
2279 if (pcm == NULL || !pcm_is_ready(pcm)) {
2280 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
2281 if (pcm != NULL) {
2282 pcm_close(pcm);
2283 pcm = NULL;
2284 }
2285 if (pcm_open_retry_count-- == 0)
2286 return NULL;
2287
2288 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2289 continue;
2290 }
2291 break;
2292 }
2293
2294 if (pcm_is_ready(pcm)) {
2295 int ret = pcm_prepare(pcm);
2296 if (ret < 0) {
2297 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2298 pcm_close(pcm);
2299 pcm = NULL;
2300 }
2301 }
2302
2303 return pcm;
2304}
2305
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002306int start_output_stream(struct stream_out *out)
2307{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002308 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002309 struct audio_usecase *uc_info;
2310 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002311 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002312
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002313 ALOGV("%s: enter: usecase(%d: %s) %s devices(%#x)",
2314 __func__, out->usecase, use_case_table[out->usecase],
2315 out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS ? "(with haptics)" : "",
2316 out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002317
2318 if (out->card_status == CARD_STATUS_OFFLINE ||
2319 adev->card_status == CARD_STATUS_OFFLINE) {
2320 ALOGW("out->card_status or adev->card_status offline, try again");
2321 ret = -EAGAIN;
2322 goto error_config;
2323 }
2324
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002325 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2326 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002327 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002328 a2dp_combo = true;
2329 } else {
2330 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2331 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2332 ret = -EAGAIN;
2333 goto error_config;
2334 }
2335 }
2336 }
2337 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002338 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002339 if (out->pcm_device_id < 0) {
2340 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2341 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002342 ret = -EINVAL;
2343 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344 }
2345
2346 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2347 uc_info->id = out->usecase;
2348 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002349 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002350 uc_info->devices = out->devices;
2351 uc_info->in_snd_device = SND_DEVICE_NONE;
2352 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353
Eric Laurent07eeafd2013-10-06 12:52:49 -07002354 /* This must be called before adding this usecase to the list */
2355 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2356 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002357 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2358 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2359 /* USB backend is not reopened immediately.
2360 This is eventually done as part of select_devices */
2361 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002362
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002363 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364
Wei Wangf4837d52017-11-21 14:51:20 -08002365 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002366 audio_extn_perf_lock_acquire();
2367
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002368 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2369 (!audio_extn_a2dp_is_ready())) {
2370 if (!a2dp_combo) {
2371 check_a2dp_restore_l(adev, out, false);
2372 } else {
2373 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002374 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2375 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2376 else
2377 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002378 select_devices(adev, out->usecase);
2379 out->devices = dev;
2380 }
2381 } else {
2382 select_devices(adev, out->usecase);
2383 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002384
Eric Laurent0499d4f2014-08-25 22:39:29 -05002385 audio_extn_extspk_update(adev->extspk);
2386
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002387 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2388 voice_set_device_mute_flag(adev, true);
2389
Andy Hung31aca912014-03-20 17:14:59 -07002390 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002391 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002392 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2393 out->pcm = NULL;
2394 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2395 COMPRESS_IN, &out->compr_config);
2396 if (out->compr && !is_compress_ready(out->compr)) {
2397 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2398 compress_close(out->compr);
2399 out->compr = NULL;
2400 ret = -EIO;
2401 goto error_open;
2402 }
2403 if (out->offload_callback)
2404 compress_nonblock(out->compr, out->non_blocking);
2405
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002406 if (adev->visualizer_start_output != NULL) {
2407 int capture_device_id =
2408 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2409 PCM_CAPTURE);
2410 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2411 adev->snd_card, capture_device_id);
2412 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002413 if (adev->offload_effects_start_output != NULL)
2414 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2415 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002416 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002417 ALOGE("%s: pcm stream not ready", __func__);
2418 goto error_open;
2419 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002420 ret = pcm_start(out->pcm);
2421 if (ret < 0) {
2422 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2423 goto error_open;
2424 }
2425 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002426 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002427 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002428
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002429 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2430 flags |= PCM_MMAP | PCM_NOIRQ;
2431 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002432 } else if (out->realtime) {
2433 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002434 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002435
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002436 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
2437 flags, pcm_open_retry_count,
2438 &(out->config));
2439 if (out->pcm == NULL) {
2440 ret = -EIO;
2441 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002442 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002443
2444 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2445 if (adev->haptic_pcm != NULL) {
2446 pcm_close(adev->haptic_pcm);
2447 adev->haptic_pcm = NULL;
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002448 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002449 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
2450 adev->haptic_pcm_device_id,
2451 flags, pcm_open_retry_count,
2452 &(adev->haptics_config));
2453 // failure to open haptics pcm shouldnt stop audio,
2454 // so do not close audio pcm in case of error
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002455 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002456
Eric Laurent0e46adf2016-12-16 12:49:24 -08002457 if (out->realtime) {
2458 ret = pcm_start(out->pcm);
2459 if (ret < 0) {
2460 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2461 pcm_close(out->pcm);
2462 out->pcm = NULL;
2463 goto error_open;
2464 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002465 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002466 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002467
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002468 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002469 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002470 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002471 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002472
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002473 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2474 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2475 audio_low_latency_hint_start();
2476 }
2477
vivek mehtae59cfb22017-06-16 15:57:11 -07002478 // consider a scenario where on pause lower layers are tear down.
2479 // so on resume, swap mixer control need to be sent only when
2480 // backend is active, hence rather than sending from enable device
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002481 // sending it from start of stream
vivek mehtae59cfb22017-06-16 15:57:11 -07002482
2483 platform_set_swap_channels(adev, true);
2484
Eric Laurent994a6932013-07-17 11:51:42 -07002485 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002486 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002487error_open:
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002488 if (adev->haptic_pcm) {
2489 pcm_close(adev->haptic_pcm);
2490 adev->haptic_pcm = NULL;
2491 }
Wei Wangf4837d52017-11-21 14:51:20 -08002492 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002493 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002495error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002496 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497}
2498
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499static int check_input_parameters(uint32_t sample_rate,
2500 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002501 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002503 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2504 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002505 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2506 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002507 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2508 return -EINVAL;
2509 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510
Eric Laurent74b55762017-07-09 17:04:53 -07002511 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2512 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002513 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002514 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002515 return -EINVAL;
2516 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517
2518 switch (sample_rate) {
2519 case 8000:
2520 case 11025:
2521 case 12000:
2522 case 16000:
2523 case 22050:
2524 case 24000:
2525 case 32000:
2526 case 44100:
2527 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002528 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 break;
2530 default:
vivek mehtadae44712015-07-27 14:13:18 -07002531 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532 return -EINVAL;
2533 }
2534
2535 return 0;
2536}
2537
Kevin Rocarda325aa22018-04-03 09:15:52 -07002538/** Add a value in a list if not already present.
2539 * @return true if value was successfully inserted or already present,
2540 * false if the list is full and does not contain the value.
2541 */
2542static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2543 for (size_t i = 0; i < list_length; i++) {
2544 if (list[i] == value) return true; // value is already present
2545 if (list[i] == 0) { // no values in this slot
2546 list[i] = value;
2547 return true; // value inserted
2548 }
2549 }
2550 return false; // could not insert value
2551}
2552
2553/** Add channel_mask in supported_channel_masks if not already present.
2554 * @return true if channel_mask was successfully inserted or already present,
2555 * false if supported_channel_masks is full and does not contain channel_mask.
2556 */
2557static void register_channel_mask(audio_channel_mask_t channel_mask,
2558 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2559 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2560 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2561}
2562
2563/** Add format in supported_formats if not already present.
2564 * @return true if format was successfully inserted or already present,
2565 * false if supported_formats is full and does not contain format.
2566 */
2567static void register_format(audio_format_t format,
2568 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2569 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2570 "%s: stream can not declare supporting its format %x", __func__, format);
2571}
2572/** Add sample_rate in supported_sample_rates if not already present.
2573 * @return true if sample_rate was successfully inserted or already present,
2574 * false if supported_sample_rates is full and does not contain sample_rate.
2575 */
2576static void register_sample_rate(uint32_t sample_rate,
2577 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2578 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2579 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2580}
2581
vivek mehtaa68fea62017-06-08 19:04:02 -07002582static size_t get_stream_buffer_size(size_t duration_ms,
2583 uint32_t sample_rate,
2584 audio_format_t format,
2585 int channel_count,
2586 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587{
2588 size_t size = 0;
2589
vivek mehtaa68fea62017-06-08 19:04:02 -07002590 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002591 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002592 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002593
2594 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595
Glenn Kasten4f993392014-05-14 07:30:48 -07002596 /* make sure the size is multiple of 32 bytes
2597 * At 48 kHz mono 16-bit PCM:
2598 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2599 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2600 */
2601 size += 0x1f;
2602 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002603
2604 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002605}
2606
2607static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2608{
2609 struct stream_out *out = (struct stream_out *)stream;
2610
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002611 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612}
2613
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002614static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615{
2616 return -ENOSYS;
2617}
2618
2619static size_t out_get_buffer_size(const struct audio_stream *stream)
2620{
2621 struct stream_out *out = (struct stream_out *)stream;
2622
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002623 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2624 return out->compr_config.fragment_size;
2625 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002626 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002627 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628}
2629
2630static uint32_t out_get_channels(const struct audio_stream *stream)
2631{
2632 struct stream_out *out = (struct stream_out *)stream;
2633
2634 return out->channel_mask;
2635}
2636
2637static audio_format_t out_get_format(const struct audio_stream *stream)
2638{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002639 struct stream_out *out = (struct stream_out *)stream;
2640
2641 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642}
2643
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002644static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645{
2646 return -ENOSYS;
2647}
2648
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002649/* must be called with out->lock locked */
2650static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651{
2652 struct stream_out *out = (struct stream_out *)stream;
2653 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002654 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002657 if (adev->adm_deregister_stream)
2658 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002659 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002661 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2662 if (out->pcm) {
2663 pcm_close(out->pcm);
2664 out->pcm = NULL;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002665
2666 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2667 if (adev->haptic_pcm) {
2668 pcm_close(adev->haptic_pcm);
2669 adev->haptic_pcm = NULL;
2670 }
2671
2672 if (adev->haptic_buffer != NULL) {
2673 free(adev->haptic_buffer);
2674 adev->haptic_buffer = NULL;
2675 adev->haptic_buffer_size = 0;
2676 }
2677 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002678 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002679 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002680 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002681 out->playback_started = false;
2682 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002683 } else {
2684 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002685 out->gapless_mdata.encoder_delay = 0;
2686 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002687 if (out->compr != NULL) {
2688 compress_close(out->compr);
2689 out->compr = NULL;
2690 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002691 }
Phil Burkbc991042017-02-24 08:06:44 -08002692 if (do_stop) {
2693 stop_output_stream(out);
2694 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002695 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002697 return 0;
2698}
2699
2700static int out_standby(struct audio_stream *stream)
2701{
2702 struct stream_out *out = (struct stream_out *)stream;
2703
2704 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2705 out->usecase, use_case_table[out->usecase]);
2706
2707 lock_output_stream(out);
2708 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002710 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711 return 0;
2712}
2713
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002714static int out_on_error(struct audio_stream *stream)
2715{
2716 struct stream_out *out = (struct stream_out *)stream;
2717 struct audio_device *adev = out->dev;
2718 bool do_standby = false;
2719
2720 lock_output_stream(out);
2721 if (!out->standby) {
2722 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2723 stop_compressed_output_l(out);
2724 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2725 } else
2726 do_standby = true;
2727 }
2728 pthread_mutex_unlock(&out->lock);
2729
2730 if (do_standby)
2731 return out_standby(&out->stream.common);
2732
2733 return 0;
2734}
2735
Andy Hung7401c7c2016-09-21 12:41:21 -07002736static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737{
Andy Hung7401c7c2016-09-21 12:41:21 -07002738 struct stream_out *out = (struct stream_out *)stream;
2739
2740 // We try to get the lock for consistency,
2741 // but it isn't necessary for these variables.
2742 // If we're not in standby, we may be blocked on a write.
2743 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2744 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2745 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2746
Andy Hung572633e2019-02-19 11:58:24 -08002747 char buffer[256]; // for statistics formatting
2748 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
2749 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
2750
Andy Hung241e36f2019-02-19 12:00:38 -08002751 if (out->start_latency_ms.n > 0) {
2752 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
2753 dprintf(fd, " Start latency ms: %s\n", buffer);
2754 }
2755
Andy Hung7401c7c2016-09-21 12:41:21 -07002756 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002757 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002758 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002759
2760 // dump error info
2761 (void)error_log_dump(
2762 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002763
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764 return 0;
2765}
2766
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002767static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2768{
2769 int ret = 0;
2770 char value[32];
2771 struct compr_gapless_mdata tmp_mdata;
2772
2773 if (!out || !parms) {
2774 return -EINVAL;
2775 }
2776
2777 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2778 if (ret >= 0) {
2779 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2780 } else {
2781 return -EINVAL;
2782 }
2783
2784 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2785 if (ret >= 0) {
2786 tmp_mdata.encoder_padding = atoi(value);
2787 } else {
2788 return -EINVAL;
2789 }
2790
2791 out->gapless_mdata = tmp_mdata;
2792 out->send_new_metadata = 1;
2793 ALOGV("%s new encoder delay %u and padding %u", __func__,
2794 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2795
2796 return 0;
2797}
2798
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002799static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2800{
2801 return out == adev->primary_output || out == adev->voice_tx_output;
2802}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002803
Kevin Rocard1e02c882017-08-09 15:26:07 -07002804static int get_alive_usb_card(struct str_parms* parms) {
2805 int card;
2806 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2807 !audio_extn_usb_alive(card)) {
2808 return card;
2809 }
2810 return -ENODEV;
2811}
2812
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2814{
2815 struct stream_out *out = (struct stream_out *)stream;
2816 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002817 struct audio_usecase *usecase;
2818 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819 struct str_parms *parms;
2820 char value[32];
2821 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002822 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002823 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002824 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825
Eric Laurent2e140aa2016-06-30 17:14:46 -07002826 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002827 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002828 parms = str_parms_create_str(kvpairs);
2829 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2830 if (ret >= 0) {
2831 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002832
Eric Laurenta1478072015-09-21 17:21:52 -07002833 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002834
2835 // The usb driver needs to be closed after usb device disconnection
2836 // otherwise audio is no longer played on the new usb devices.
2837 // By forcing the stream in standby, the usb stack refcount drops to 0
2838 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002839 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002840 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002841 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2842 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2843 out_standby_l(&out->stream.common);
2844 }
2845 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002846 }
2847
Eric Laurent150dbfe2013-02-27 14:31:02 -08002848 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002850 /*
2851 * When HDMI cable is unplugged the music playback is paused and
2852 * the policy manager sends routing=0. But the audioflinger
2853 * continues to write data until standby time (3sec).
2854 * As the HDMI core is turned off, the write gets blocked.
2855 * Avoid this by routing audio to speaker until standby.
2856 */
2857 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2858 val == AUDIO_DEVICE_NONE) {
2859 val = AUDIO_DEVICE_OUT_SPEAKER;
2860 }
2861
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002862 /*
2863 * When A2DP is disconnected the
2864 * music playback is paused and the policy manager sends routing=0
2865 * But the audioflingercontinues to write data until standby time
2866 * (3sec). As BT is turned off, the write gets blocked.
2867 * Avoid this by routing audio to speaker until standby.
2868 */
2869 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2870 (val == AUDIO_DEVICE_NONE) &&
2871 !audio_extn_a2dp_is_ready()) {
2872 val = AUDIO_DEVICE_OUT_SPEAKER;
2873 }
2874
2875 /* To avoid a2dp to sco overlapping / BT device improper state
2876 * check with BT lib about a2dp streaming support before routing
2877 */
2878 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2879 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002880 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002881 //combo usecase just by pass a2dp
2882 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2883 bypass_a2dp = true;
2884 } else {
2885 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2886 /* update device to a2dp and don't route as BT returned error
2887 * However it is still possible a2dp routing called because
2888 * of current active device disconnection (like wired headset)
2889 */
2890 out->devices = val;
2891 pthread_mutex_unlock(&out->lock);
2892 pthread_mutex_unlock(&adev->lock);
2893 status = -ENOSYS;
2894 goto routing_fail;
2895 }
2896 }
2897 }
2898
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002899 audio_devices_t new_dev = val;
2900
2901 // Workaround: If routing to an non existing usb device, fail gracefully
2902 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002903 int card;
2904 if (audio_is_usb_out_device(new_dev) &&
2905 (card = get_alive_usb_card(parms)) >= 0) {
2906
2907 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002908 pthread_mutex_unlock(&adev->lock);
2909 pthread_mutex_unlock(&out->lock);
2910 status = -ENOSYS;
2911 goto routing_fail;
2912 }
2913
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002914 /*
2915 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002916 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002917 * the select_devices(). But how do we undo this?
2918 *
2919 * For example, music playback is active on headset (deep-buffer usecase)
2920 * and if we go to ringtones and select a ringtone, low-latency usecase
2921 * will be started on headset+speaker. As we can't enable headset+speaker
2922 * and headset devices at the same time, select_devices() switches the music
2923 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2924 * So when the ringtone playback is completed, how do we undo the same?
2925 *
2926 * We are relying on the out_set_parameters() call on deep-buffer output,
2927 * once the ringtone playback is ended.
2928 * NOTE: We should not check if the current devices are same as new devices.
2929 * Because select_devices() must be called to switch back the music
2930 * playback to headset.
2931 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002932 if (new_dev != AUDIO_DEVICE_NONE) {
2933 bool same_dev = out->devices == new_dev;
2934 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002935
Eric Laurenta7657192014-10-09 21:09:33 -07002936 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002937 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002938 if (adev->mode == AUDIO_MODE_IN_CALL) {
2939 adev->current_call_output = out;
2940 ret = voice_start_call(adev);
2941 }
2942 } else {
2943 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002944 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002945 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002946 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002947
2948 if (!out->standby) {
2949 if (!same_dev) {
2950 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002951 // inform adm before actual routing to prevent glitches.
2952 if (adev->adm_on_routing_change) {
2953 adev->adm_on_routing_change(adev->adm_data,
2954 out->handle);
2955 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002956 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002957 if (!bypass_a2dp) {
2958 select_devices(adev, out->usecase);
2959 } else {
juyuchen9baad392018-06-05 19:02:10 +08002960 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2961 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2962 else
2963 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002964 select_devices(adev, out->usecase);
2965 out->devices = new_dev;
2966 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002967 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002968
2969 // on device switch force swap, lower functions will make sure
2970 // to check if swap is allowed or not.
2971
2972 if (!same_dev)
2973 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002974
2975 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2976 out->a2dp_compress_mute &&
2977 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2978 pthread_mutex_lock(&out->compr_mute_lock);
2979 out->a2dp_compress_mute = false;
2980 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2981 pthread_mutex_unlock(&out->compr_mute_lock);
2982 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002983 }
2984
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002985 }
2986
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002988 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002989
2990 /*handles device and call state changes*/
2991 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002993 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002994
2995 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2996 parse_compress_metadata(out, parms);
2997 }
2998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003000 ALOGV("%s: exit: code(%d)", __func__, status);
3001 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002}
3003
Haynes Mathew George569b7482017-05-08 14:44:27 -07003004static bool stream_get_parameter_channels(struct str_parms *query,
3005 struct str_parms *reply,
3006 audio_channel_mask_t *supported_channel_masks) {
3007 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07003008 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003010 size_t i, j;
3011
3012 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3013 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014 value[0] = '\0';
3015 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003016 while (supported_channel_masks[i] != 0) {
3017 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3018 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 if (!first) {
3020 strcat(value, "|");
3021 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003022 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 first = false;
3024 break;
3025 }
3026 }
3027 i++;
3028 }
3029 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003030 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003031 return ret >= 0;
3032}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003033
Haynes Mathew George569b7482017-05-08 14:44:27 -07003034static bool stream_get_parameter_formats(struct str_parms *query,
3035 struct str_parms *reply,
3036 audio_format_t *supported_formats) {
3037 int ret = -1;
3038 char value[256];
3039 int i;
3040
3041 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
3042 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003043 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07003044 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003045 case AUDIO_FORMAT_PCM_16_BIT:
3046 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
3047 break;
3048 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
3049 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
3050 break;
3051 case AUDIO_FORMAT_PCM_32_BIT:
3052 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
3053 break;
3054 default:
3055 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07003056 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003057 break;
3058 }
3059 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003060 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003061 return ret >= 0;
3062}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003063
Haynes Mathew George569b7482017-05-08 14:44:27 -07003064static bool stream_get_parameter_rates(struct str_parms *query,
3065 struct str_parms *reply,
3066 uint32_t *supported_sample_rates) {
3067
3068 int i;
3069 char value[256];
3070 int ret = -1;
3071 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
3072 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003073 value[0] = '\0';
3074 i=0;
3075 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003076 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003077 int avail = sizeof(value) - cursor;
3078 ret = snprintf(value + cursor, avail, "%s%d",
3079 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07003080 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003081 if (ret < 0 || ret >= avail) {
3082 // if cursor is at the last element of the array
3083 // overwrite with \0 is duplicate work as
3084 // snprintf already put a \0 in place.
3085 // else
3086 // we had space to write the '|' at value[cursor]
3087 // (which will be overwritten) or no space to fill
3088 // the first element (=> cursor == 0)
3089 value[cursor] = '\0';
3090 break;
3091 }
3092 cursor += ret;
3093 ++i;
3094 }
3095 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3096 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003097 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003098 return ret >= 0;
3099}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003100
Haynes Mathew George569b7482017-05-08 14:44:27 -07003101static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3102{
3103 struct stream_out *out = (struct stream_out *)stream;
3104 struct str_parms *query = str_parms_create_str(keys);
3105 char *str;
3106 struct str_parms *reply = str_parms_create();
3107 bool replied = false;
3108 ALOGV("%s: enter: keys - %s", __func__, keys);
3109
3110 replied |= stream_get_parameter_channels(query, reply,
3111 &out->supported_channel_masks[0]);
3112 replied |= stream_get_parameter_formats(query, reply,
3113 &out->supported_formats[0]);
3114 replied |= stream_get_parameter_rates(query, reply,
3115 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003116 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117 str = str_parms_to_str(reply);
3118 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07003119 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120 }
3121 str_parms_destroy(query);
3122 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003123 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003124 return str;
3125}
3126
3127static uint32_t out_get_latency(const struct audio_stream_out *stream)
3128{
Haynes Mathew George03c40102016-01-29 17:57:48 -08003129 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003131 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003133 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3134 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003135 else if ((out->realtime) ||
3136 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003137 // since the buffer won't be filled up faster than realtime,
3138 // return a smaller number
3139 period_ms = (out->af_period_multiplier * out->config.period_size *
3140 1000) / (out->config.rate);
3141 hw_delay = platform_render_latency(out->usecase)/1000;
3142 return period_ms + hw_delay;
3143 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003144
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003145 latency = (out->config.period_count * out->config.period_size * 1000) /
3146 (out->config.rate);
3147
3148 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
3149 latency += audio_extn_a2dp_get_encoder_latency();
3150
3151 return latency;
3152}
3153
3154static int set_compr_volume(struct audio_stream_out *stream, float left,
3155 float right)
3156{
3157 struct stream_out *out = (struct stream_out *)stream;
3158 int volume[2];
3159 char mixer_ctl_name[128];
3160 struct audio_device *adev = out->dev;
3161 struct mixer_ctl *ctl;
3162 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3163 PCM_PLAYBACK);
3164
3165 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3166 "Compress Playback %d Volume", pcm_device_id);
3167 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3168 if (!ctl) {
3169 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3170 __func__, mixer_ctl_name);
3171 return -EINVAL;
3172 }
3173 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
3174 __func__, mixer_ctl_name, left, right);
3175 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3176 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3177 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
3178
3179 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180}
3181
3182static int out_set_volume(struct audio_stream_out *stream, float left,
3183 float right)
3184{
Eric Laurenta9024de2013-04-04 09:19:12 -07003185 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003186 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003187
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003188 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07003189 /* only take left channel into account: the API is for stereo anyway */
3190 out->muted = (left == 0.0f);
3191 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003192 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003193 pthread_mutex_lock(&out->compr_mute_lock);
3194 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3195 if (!out->a2dp_compress_mute)
3196 ret = set_compr_volume(stream, left, right);
3197 out->volume_l = left;
3198 out->volume_r = right;
3199 pthread_mutex_unlock(&out->compr_mute_lock);
3200 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07003201 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07003202 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3203 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3204 if (!out->standby) {
3205 // if in standby, cached volume will be sent after stream is opened
3206 audio_extn_utils_send_app_type_gain(out->dev,
3207 out->app_type_cfg.app_type,
3208 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07003209 }
vivek mehtaa68fea62017-06-08 19:04:02 -07003210 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003211 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003212
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213 return -ENOSYS;
3214}
3215
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003216// note: this call is safe only if the stream_cb is
3217// removed first in close_output_stream (as is done now).
3218static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3219{
3220 if (!stream || !parms)
3221 return;
3222
3223 struct stream_out *out = (struct stream_out *)stream;
3224 struct audio_device *adev = out->dev;
3225
3226 card_status_t status;
3227 int card;
3228 if (parse_snd_card_status(parms, &card, &status) < 0)
3229 return;
3230
3231 pthread_mutex_lock(&adev->lock);
3232 bool valid_cb = (card == adev->snd_card);
3233 pthread_mutex_unlock(&adev->lock);
3234
3235 if (!valid_cb)
3236 return;
3237
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003238 lock_output_stream(out);
3239 if (out->card_status != status)
3240 out->card_status = status;
3241 pthread_mutex_unlock(&out->lock);
3242
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07003243 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
3244 use_case_table[out->usecase],
3245 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3246
3247 if (status == CARD_STATUS_OFFLINE)
3248 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003249
3250 return;
3251}
3252
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003253#ifdef NO_AUDIO_OUT
3254static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003255 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003256{
3257 struct stream_out *out = (struct stream_out *)stream;
3258
3259 /* No Output device supported other than BT for playback.
3260 * Sleep for the amount of buffer duration
3261 */
Eric Laurenta1478072015-09-21 17:21:52 -07003262 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003263 usleep(bytes * 1000000 / audio_stream_out_frame_size(
3264 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003265 out_get_sample_rate(&out->stream.common));
3266 pthread_mutex_unlock(&out->lock);
3267 return bytes;
3268}
3269#endif
3270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3272 size_t bytes)
3273{
3274 struct stream_out *out = (struct stream_out *)stream;
3275 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003276 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07003277 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278
Eric Laurenta1478072015-09-21 17:21:52 -07003279 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07003280 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07003281 const size_t frame_size = audio_stream_out_frame_size(stream);
3282 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003283
Eric Laurent0e46adf2016-12-16 12:49:24 -08003284 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3285 error_code = ERROR_CODE_WRITE;
3286 goto exit;
3287 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003288
3289 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3290 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003291 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003292 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3293 ret = -EIO;
3294 goto exit;
3295 }
3296 }
3297 }
3298
Andy Hung572633e2019-02-19 11:58:24 -08003299 const bool was_in_standby = out->standby;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003301 out->standby = false;
Andy Hung241e36f2019-02-19 12:00:38 -08003302 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
3303
Eric Laurent150dbfe2013-02-27 14:31:02 -08003304 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003305 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003306
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003307 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003308 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003309 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003310 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311 goto exit;
3312 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003313
vivek mehta40125092017-08-21 18:48:51 -07003314 // after standby always force set last known cal step
3315 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3316 ALOGD("%s: retry previous failed cal level set", __func__);
3317 send_gain_dep_calibration_l();
3318 pthread_mutex_unlock(&adev->lock);
Andy Hung572633e2019-02-19 11:58:24 -08003319
Andy Hung241e36f2019-02-19 12:00:38 -08003320 // log startup time in ms.
3321 simple_stats_log(
3322 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Andy Hung572633e2019-02-19 11:58:24 -08003323 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003326 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003327 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003328 if (out->send_new_metadata) {
3329 ALOGVV("send new gapless metadata");
3330 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3331 out->send_new_metadata = 0;
3332 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003333 unsigned int avail;
3334 struct timespec tstamp;
3335 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3336 /* Do not limit write size if the available frames count is unknown */
3337 if (ret != 0) {
3338 avail = bytes;
3339 }
3340 if (avail == 0) {
3341 ret = 0;
3342 } else {
Andy Hung572633e2019-02-19 11:58:24 -08003343 // check for compressed format underrun, essentially an empty buffer check
3344 // for a lack of better measurement.
3345 if (!was_in_standby && avail == out->kernel_buffer_size) {
3346 ALOGW("%s: compressed buffer empty (underrun)", __func__);
3347 simple_stats_log(&out->fifo_underruns, 1.); // Note: log one frame for compressed.
3348 }
3349
Eric Laurentb49b3f62016-02-29 17:59:49 -08003350 if (avail > bytes) {
3351 avail = bytes;
3352 }
3353 ret = compress_write(out->compr, buffer, avail);
3354 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3355 __func__, avail, ret);
3356 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003357
Eric Laurent6e895242013-09-05 16:10:57 -07003358 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003359 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3360 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003361 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003362 compress_start(out->compr);
3363 out->playback_started = 1;
3364 out->offload_state = OFFLOAD_STATE_PLAYING;
3365 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003366 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003367 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003368 } else {
3369 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003370 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003371 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003372 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003373 return ret;
3374 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003375 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003376 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003377 size_t bytes_to_write = bytes;
3378
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003379 if (out->muted)
3380 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003381 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003382 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003383 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3384 int16_t *src = (int16_t *)buffer;
3385 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003386
Eric Laurentad2dde92017-09-20 18:27:31 -07003387 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3388 out->format != AUDIO_FORMAT_PCM_16_BIT,
3389 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003390
Eric Laurentad2dde92017-09-20 18:27:31 -07003391 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3392 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3393 }
3394 bytes_to_write /= 2;
3395 }
Andy Hung572633e2019-02-19 11:58:24 -08003396
3397 // Note: since out_get_presentation_position() is called alternating with out_write()
3398 // by AudioFlinger, we can check underruns using the prior timestamp read.
3399 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
3400 if (out->last_fifo_valid) {
3401 // compute drain to see if there is an underrun.
3402 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
3403 const int64_t frames_by_time =
3404 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
3405 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
3406
3407 if (underrun > 0) {
3408 simple_stats_log(&out->fifo_underruns, underrun);
3409
3410 ALOGW("%s: underrun(%lld) "
3411 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
3412 __func__,
3413 (long long)out->fifo_underruns.n,
3414 (long long)frames_by_time,
3415 (long long)out->last_fifo_frames_remaining);
3416 }
3417 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
3418 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003419
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003420 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003421 request_out_focus(out, ns);
3422
3423 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003424 if (use_mmap) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003425 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003426 } else {
3427 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3428 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3429 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
3430 size_t frame_size = channel_count * bytes_per_sample;
3431 size_t frame_count = bytes_to_write / frame_size;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003432
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003433 bool force_haptic_path =
3434 property_get_bool("vendor.audio.test_haptic", false);
3435
3436 // extract Haptics data from Audio buffer
3437 bool alloc_haptic_buffer = false;
3438 int haptic_channel_count = adev->haptics_config.channels;
3439 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
3440 size_t audio_frame_size = frame_size - haptic_frame_size;
3441 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
3442
3443 if (adev->haptic_buffer == NULL) {
3444 alloc_haptic_buffer = true;
3445 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
3446 free(adev->haptic_buffer);
3447 adev->haptic_buffer_size = 0;
3448 alloc_haptic_buffer = true;
3449 }
3450
3451 if (alloc_haptic_buffer) {
3452 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
3453 adev->haptic_buffer_size = total_haptic_buffer_size;
3454 }
3455
3456 size_t src_index = 0, aud_index = 0, hap_index = 0;
3457 uint8_t *audio_buffer = (uint8_t *)buffer;
3458 uint8_t *haptic_buffer = adev->haptic_buffer;
3459
3460 // This is required for testing only. This works for stereo data only.
3461 // One channel is fed to audio stream and other to haptic stream for testing.
3462 if (force_haptic_path) {
3463 audio_frame_size = haptic_frame_size = bytes_per_sample;
3464 }
3465
3466 for (size_t i = 0; i < frame_count; i++) {
3467 for (size_t j = 0; j < audio_frame_size; j++)
3468 audio_buffer[aud_index++] = audio_buffer[src_index++];
3469
3470 for (size_t j = 0; j < haptic_frame_size; j++)
3471 haptic_buffer[hap_index++] = audio_buffer[src_index++];
3472 }
3473
3474 // This is required for testing only.
3475 // Discard haptic channel data.
3476 if (force_haptic_path) {
3477 src_index += haptic_frame_size;
3478 }
3479
3480 // write to audio pipeline
3481 ret = pcm_write(out->pcm,
3482 (void *)audio_buffer,
3483 frame_count * audio_frame_size);
3484
3485 // write to haptics pipeline
3486 if (adev->haptic_pcm)
3487 ret = pcm_write(adev->haptic_pcm,
3488 (void *)adev->haptic_buffer,
3489 frame_count * haptic_frame_size);
3490
3491 } else {
3492 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
3493 }
3494 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003495 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003496 } else {
3497 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003498 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499 }
3500
3501exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003502 // For PCM we always consume the buffer and return #bytes regardless of ret.
3503 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003504 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003505 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003506 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003507
Andy Hung7401c7c2016-09-21 12:41:21 -07003508 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003509 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003510 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3511 ALOGE_IF(out->pcm != NULL,
3512 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003513 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003514 // usleep not guaranteed for values over 1 second but we don't limit here.
3515 }
3516 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518 pthread_mutex_unlock(&out->lock);
3519
3520 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003521 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003522 if (sleeptime_us != 0)
3523 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524 }
3525 return bytes;
3526}
3527
3528static int out_get_render_position(const struct audio_stream_out *stream,
3529 uint32_t *dsp_frames)
3530{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003531 struct stream_out *out = (struct stream_out *)stream;
3532 *dsp_frames = 0;
3533 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003534 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003535 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003536 unsigned long frames = 0;
3537 // TODO: check return value
3538 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3539 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003540 ALOGVV("%s rendered frames %d sample_rate %d",
3541 __func__, *dsp_frames, out->sample_rate);
3542 }
3543 pthread_mutex_unlock(&out->lock);
3544 return 0;
3545 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003546 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547}
3548
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003549static int out_add_audio_effect(const struct audio_stream *stream __unused,
3550 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551{
3552 return 0;
3553}
3554
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003555static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3556 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557{
3558 return 0;
3559}
3560
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003561static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3562 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003564 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565}
3566
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003567static int out_get_presentation_position(const struct audio_stream_out *stream,
3568 uint64_t *frames, struct timespec *timestamp)
3569{
3570 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003571 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003572 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003573
Eric Laurenta1478072015-09-21 17:21:52 -07003574 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003575
Eric Laurent949a0892013-09-20 09:20:13 -07003576 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3577 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003578 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003579 compress_get_tstamp(out->compr, &dsp_frames,
3580 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003581 // Adjustment accounts for A2DP encoder latency with offload usecases
3582 // Note: Encoder latency is returned in ms.
3583 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3584 unsigned long offset =
3585 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3586 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3587 }
Eric Laurent949a0892013-09-20 09:20:13 -07003588 ALOGVV("%s rendered frames %ld sample_rate %d",
3589 __func__, dsp_frames, out->sample_rate);
3590 *frames = dsp_frames;
3591 ret = 0;
3592 /* this is the best we can do */
3593 clock_gettime(CLOCK_MONOTONIC, timestamp);
3594 }
3595 } else {
3596 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003597 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003598 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
Andy Hung572633e2019-02-19 11:58:24 -08003599
3600 // pcm_get_htimestamp() computes the available frames by comparing
3601 // the alsa driver hw_ptr and the appl_ptr levels.
3602 // In underrun, the hw_ptr may keep running and report an excessively
3603 // large number available number.
3604 if (avail > out->kernel_buffer_size) {
3605 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
3606 __func__, avail, out->kernel_buffer_size);
3607 avail = out->kernel_buffer_size;
3608 out->last_fifo_frames_remaining = 0;
3609 } else {
3610 out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
3611 }
3612 out->last_fifo_valid = true;
3613 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
3614
3615 int64_t signed_frames = out->written - out->last_fifo_frames_remaining;
3616
3617 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
3618 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
3619
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003620 // This adjustment accounts for buffering after app processor.
3621 // It is based on estimated DSP latency per use case, rather than exact.
3622 signed_frames -=
3623 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3624
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003625 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3626 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3627 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3628 signed_frames -=
3629 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3630 }
3631
Eric Laurent949a0892013-09-20 09:20:13 -07003632 // It would be unusual for this value to be negative, but check just in case ...
3633 if (signed_frames >= 0) {
3634 *frames = signed_frames;
3635 ret = 0;
3636 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003637 }
3638 }
3639 }
3640
3641 pthread_mutex_unlock(&out->lock);
3642
3643 return ret;
3644}
3645
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003646static int out_set_callback(struct audio_stream_out *stream,
3647 stream_callback_t callback, void *cookie)
3648{
3649 struct stream_out *out = (struct stream_out *)stream;
3650
3651 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003652 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003653 out->offload_callback = callback;
3654 out->offload_cookie = cookie;
3655 pthread_mutex_unlock(&out->lock);
3656 return 0;
3657}
3658
3659static int out_pause(struct audio_stream_out* stream)
3660{
3661 struct stream_out *out = (struct stream_out *)stream;
3662 int status = -ENOSYS;
3663 ALOGV("%s", __func__);
3664 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003665 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003666 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3667 status = compress_pause(out->compr);
3668 out->offload_state = OFFLOAD_STATE_PAUSED;
3669 }
3670 pthread_mutex_unlock(&out->lock);
3671 }
3672 return status;
3673}
3674
3675static int out_resume(struct audio_stream_out* stream)
3676{
3677 struct stream_out *out = (struct stream_out *)stream;
3678 int status = -ENOSYS;
3679 ALOGV("%s", __func__);
3680 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3681 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003682 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003683 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3684 status = compress_resume(out->compr);
3685 out->offload_state = OFFLOAD_STATE_PLAYING;
3686 }
3687 pthread_mutex_unlock(&out->lock);
3688 }
3689 return status;
3690}
3691
3692static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3693{
3694 struct stream_out *out = (struct stream_out *)stream;
3695 int status = -ENOSYS;
3696 ALOGV("%s", __func__);
3697 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003698 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003699 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3700 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3701 else
3702 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3703 pthread_mutex_unlock(&out->lock);
3704 }
3705 return status;
3706}
3707
3708static int out_flush(struct audio_stream_out* stream)
3709{
3710 struct stream_out *out = (struct stream_out *)stream;
3711 ALOGV("%s", __func__);
3712 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003713 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003714 stop_compressed_output_l(out);
3715 pthread_mutex_unlock(&out->lock);
3716 return 0;
3717 }
3718 return -ENOSYS;
3719}
3720
Eric Laurent0e46adf2016-12-16 12:49:24 -08003721static int out_stop(const struct audio_stream_out* stream)
3722{
3723 struct stream_out *out = (struct stream_out *)stream;
3724 struct audio_device *adev = out->dev;
3725 int ret = -ENOSYS;
3726
3727 ALOGV("%s", __func__);
3728 pthread_mutex_lock(&adev->lock);
3729 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3730 out->playback_started && out->pcm != NULL) {
3731 pcm_stop(out->pcm);
3732 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003733 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003734 }
3735 pthread_mutex_unlock(&adev->lock);
3736 return ret;
3737}
3738
3739static int out_start(const struct audio_stream_out* stream)
3740{
3741 struct stream_out *out = (struct stream_out *)stream;
3742 struct audio_device *adev = out->dev;
3743 int ret = -ENOSYS;
3744
3745 ALOGV("%s", __func__);
3746 pthread_mutex_lock(&adev->lock);
3747 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3748 !out->playback_started && out->pcm != NULL) {
3749 ret = start_output_stream(out);
3750 if (ret == 0) {
3751 out->playback_started = true;
3752 }
3753 }
3754 pthread_mutex_unlock(&adev->lock);
3755 return ret;
3756}
3757
Phil Burkbc991042017-02-24 08:06:44 -08003758/*
3759 * Modify config->period_count based on min_size_frames
3760 */
3761static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3762{
3763 int periodCountRequested = (min_size_frames + config->period_size - 1)
3764 / config->period_size;
3765 int periodCount = MMAP_PERIOD_COUNT_MIN;
3766
3767 ALOGV("%s original config.period_size = %d config.period_count = %d",
3768 __func__, config->period_size, config->period_count);
3769
3770 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3771 periodCount *= 2;
3772 }
3773 config->period_count = periodCount;
3774
3775 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3776}
3777
Eric Laurent0e46adf2016-12-16 12:49:24 -08003778static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3779 int32_t min_size_frames,
3780 struct audio_mmap_buffer_info *info)
3781{
3782 struct stream_out *out = (struct stream_out *)stream;
3783 struct audio_device *adev = out->dev;
3784 int ret = 0;
3785 unsigned int offset1;
3786 unsigned int frames1;
3787 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003788 uint32_t mmap_size;
3789 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003790
3791 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003792 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003793 pthread_mutex_lock(&adev->lock);
3794
3795 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003796 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003797 ret = -EINVAL;
3798 goto exit;
3799 }
3800 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003801 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003802 ret = -ENOSYS;
3803 goto exit;
3804 }
3805 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3806 if (out->pcm_device_id < 0) {
3807 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3808 __func__, out->pcm_device_id, out->usecase);
3809 ret = -EINVAL;
3810 goto exit;
3811 }
Phil Burkbc991042017-02-24 08:06:44 -08003812
3813 adjust_mmap_period_count(&out->config, min_size_frames);
3814
Eric Laurent0e46adf2016-12-16 12:49:24 -08003815 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3816 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3817 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3818 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3819 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3820 step = "open";
3821 ret = -ENODEV;
3822 goto exit;
3823 }
3824 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3825 if (ret < 0) {
3826 step = "begin";
3827 goto exit;
3828 }
3829 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003830 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003831 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003832 ret = platform_get_mmap_data_fd(adev->platform,
3833 out->pcm_device_id, 0 /*playback*/,
3834 &info->shared_memory_fd,
3835 &mmap_size);
3836 if (ret < 0) {
3837 // Fall back to non exclusive mode
3838 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3839 } else {
3840 if (mmap_size < buffer_size) {
3841 step = "mmap";
3842 goto exit;
3843 }
3844 // FIXME: indicate exclusive mode support by returning a negative buffer size
3845 info->buffer_size_frames *= -1;
3846 }
3847 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003848
3849 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3850 if (ret < 0) {
3851 step = "commit";
3852 goto exit;
3853 }
Phil Burkbc991042017-02-24 08:06:44 -08003854
3855 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003856 ret = 0;
3857
3858 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3859 __func__, info->shared_memory_address, info->buffer_size_frames);
3860
3861exit:
3862 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003863 if (out->pcm == NULL) {
3864 ALOGE("%s: %s - %d", __func__, step, ret);
3865 } else {
3866 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003867 pcm_close(out->pcm);
3868 out->pcm = NULL;
3869 }
3870 }
3871 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003872 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003873 return ret;
3874}
3875
3876static int out_get_mmap_position(const struct audio_stream_out *stream,
3877 struct audio_mmap_position *position)
3878{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003879 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003880 struct stream_out *out = (struct stream_out *)stream;
3881 ALOGVV("%s", __func__);
3882 if (position == NULL) {
3883 return -EINVAL;
3884 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003885 lock_output_stream(out);
3886 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3887 out->pcm == NULL) {
3888 ret = -ENOSYS;
3889 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003890 }
3891
3892 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003893 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003894 if (ret < 0) {
3895 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003896 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003897 }
Andy Hungfc044e12017-03-20 09:24:22 -07003898 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003899exit:
3900 pthread_mutex_unlock(&out->lock);
3901 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003902}
3903
3904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003905/** audio_stream_in implementation **/
3906static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3907{
3908 struct stream_in *in = (struct stream_in *)stream;
3909
3910 return in->config.rate;
3911}
3912
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003913static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914{
3915 return -ENOSYS;
3916}
3917
3918static size_t in_get_buffer_size(const struct audio_stream *stream)
3919{
3920 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003921 return in->config.period_size * in->af_period_multiplier *
3922 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923}
3924
3925static uint32_t in_get_channels(const struct audio_stream *stream)
3926{
3927 struct stream_in *in = (struct stream_in *)stream;
3928
3929 return in->channel_mask;
3930}
3931
vivek mehta4ed66e62016-04-15 23:33:34 -07003932static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003933{
vivek mehta4ed66e62016-04-15 23:33:34 -07003934 struct stream_in *in = (struct stream_in *)stream;
3935 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936}
3937
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003938static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003939{
3940 return -ENOSYS;
3941}
3942
3943static int in_standby(struct audio_stream *stream)
3944{
3945 struct stream_in *in = (struct stream_in *)stream;
3946 struct audio_device *adev = in->dev;
3947 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003948 bool do_stop = true;
3949
Eric Laurent994a6932013-07-17 11:51:42 -07003950 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003951
3952 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003953
3954 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003955 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003956 audio_extn_sound_trigger_stop_lab(in);
3957 in->standby = true;
3958 }
3959
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003960 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003961 if (adev->adm_deregister_stream)
3962 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3963
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003964 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003965 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003966 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003967 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003968 in->capture_started = false;
3969 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003970 if (in->pcm) {
3971 pcm_close(in->pcm);
3972 in->pcm = NULL;
3973 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003974 adev->enable_voicerx = false;
3975 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003976 if (do_stop) {
3977 status = stop_input_stream(in);
3978 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003979 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003980 }
3981 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003982 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003983 return status;
3984}
3985
Andy Hungd13f0d32017-06-12 13:58:37 -07003986static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003987{
Andy Hungd13f0d32017-06-12 13:58:37 -07003988 struct stream_in *in = (struct stream_in *)stream;
3989
3990 // We try to get the lock for consistency,
3991 // but it isn't necessary for these variables.
3992 // If we're not in standby, we may be blocked on a read.
3993 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3994 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3995 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3996 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3997
Andy Hung241e36f2019-02-19 12:00:38 -08003998 char buffer[256]; // for statistics formatting
3999 if (in->start_latency_ms.n > 0) {
4000 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
4001 dprintf(fd, " Start latency ms: %s\n", buffer);
4002 }
4003
Andy Hungd13f0d32017-06-12 13:58:37 -07004004 if (locked) {
4005 pthread_mutex_unlock(&in->lock);
4006 }
4007
4008 // dump error info
4009 (void)error_log_dump(
4010 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004011 return 0;
4012}
4013
4014static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4015{
4016 struct stream_in *in = (struct stream_in *)stream;
4017 struct audio_device *adev = in->dev;
4018 struct str_parms *parms;
4019 char *str;
4020 char value[32];
4021 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07004022 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004023
Eric Laurent994a6932013-07-17 11:51:42 -07004024 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004025 parms = str_parms_create_str(kvpairs);
4026
4027 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4028
Eric Laurenta1478072015-09-21 17:21:52 -07004029 lock_input_stream(in);
4030
Eric Laurent150dbfe2013-02-27 14:31:02 -08004031 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004032 if (ret >= 0) {
4033 val = atoi(value);
4034 /* no audio source uses val == 0 */
4035 if ((in->source != val) && (val != 0)) {
4036 in->source = val;
4037 }
4038 }
4039
4040 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07004041
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004042 if (ret >= 0) {
4043 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07004044 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004045
4046 // Workaround: If routing to an non existing usb device, fail gracefully
4047 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07004048 int card;
4049 if (audio_is_usb_in_device(val) &&
4050 (card = get_alive_usb_card(parms)) >= 0) {
4051
4052 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004053 status = -ENOSYS;
4054 } else {
4055
4056 in->device = val;
4057 /* If recording is in progress, change the tx device to new device */
4058 if (!in->standby) {
4059 ALOGV("update input routing change");
4060 // inform adm before actual routing to prevent glitches.
4061 if (adev->adm_on_routing_change) {
4062 adev->adm_on_routing_change(adev->adm_data,
4063 in->capture_handle);
4064 }
4065 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07004066 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004067 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004068 }
4069 }
4070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004071 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004072 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004073
4074 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07004075 ALOGV("%s: exit: status(%d)", __func__, status);
4076 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004077}
4078
Haynes Mathew George569b7482017-05-08 14:44:27 -07004079static char* in_get_parameters(const struct audio_stream *stream,
4080 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004081{
Haynes Mathew George569b7482017-05-08 14:44:27 -07004082 struct stream_in *in = (struct stream_in *)stream;
4083 struct str_parms *query = str_parms_create_str(keys);
4084 char *str;
4085 struct str_parms *reply = str_parms_create();
4086 bool replied = false;
4087
4088 ALOGV("%s: enter: keys - %s", __func__, keys);
4089 replied |= stream_get_parameter_channels(query, reply,
4090 &in->supported_channel_masks[0]);
4091 replied |= stream_get_parameter_formats(query, reply,
4092 &in->supported_formats[0]);
4093 replied |= stream_get_parameter_rates(query, reply,
4094 &in->supported_sample_rates[0]);
4095 if (replied) {
4096 str = str_parms_to_str(reply);
4097 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07004098 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07004099 }
4100 str_parms_destroy(query);
4101 str_parms_destroy(reply);
4102 ALOGV("%s: exit: returns - %s", __func__, str);
4103 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004104}
4105
Eric Laurent51f3c662018-04-10 18:21:34 -07004106static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004107{
Eric Laurent51f3c662018-04-10 18:21:34 -07004108 struct stream_in *in = (struct stream_in *)stream;
4109 char mixer_ctl_name[128];
4110 struct mixer_ctl *ctl;
4111 int ctl_value;
4112
4113 ALOGV("%s: gain %f", __func__, gain);
4114
4115 if (stream == NULL)
4116 return -EINVAL;
4117
4118 /* in_set_gain() only used to silence MMAP capture for now */
4119 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
4120 return -ENOSYS;
4121
4122 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
4123
4124 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
4125 if (!ctl) {
4126 ALOGW("%s: Could not get ctl for mixer cmd - %s",
4127 __func__, mixer_ctl_name);
4128 return -ENOSYS;
4129 }
4130
4131 if (gain < RECORD_GAIN_MIN)
4132 gain = RECORD_GAIN_MIN;
4133 else if (gain > RECORD_GAIN_MAX)
4134 gain = RECORD_GAIN_MAX;
4135 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
4136
4137 mixer_ctl_set_value(ctl, 0, ctl_value);
4138 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004139}
4140
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004141static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4142{
4143 if (!stream || !parms)
4144 return;
4145
4146 struct stream_in *in = (struct stream_in *)stream;
4147 struct audio_device *adev = in->dev;
4148
4149 card_status_t status;
4150 int card;
4151 if (parse_snd_card_status(parms, &card, &status) < 0)
4152 return;
4153
4154 pthread_mutex_lock(&adev->lock);
4155 bool valid_cb = (card == adev->snd_card);
4156 pthread_mutex_unlock(&adev->lock);
4157
4158 if (!valid_cb)
4159 return;
4160
4161 lock_input_stream(in);
4162 if (in->card_status != status)
4163 in->card_status = status;
4164 pthread_mutex_unlock(&in->lock);
4165
4166 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4167 use_case_table[in->usecase],
4168 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4169
4170 // a better solution would be to report error back to AF and let
4171 // it put the stream to standby
4172 if (status == CARD_STATUS_OFFLINE)
4173 in_standby(&in->stream.common);
4174
4175 return;
4176}
4177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004178static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4179 size_t bytes)
4180{
4181 struct stream_in *in = (struct stream_in *)stream;
4182 struct audio_device *adev = in->dev;
4183 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07004184 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07004185 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004186
Eric Laurenta1478072015-09-21 17:21:52 -07004187 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004188 const size_t frame_size = audio_stream_in_frame_size(stream);
4189 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07004190
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004191 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004192 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004193 /* Read from sound trigger HAL */
4194 audio_extn_sound_trigger_read(in, buffer, bytes);
4195 pthread_mutex_unlock(&in->lock);
4196 return bytes;
4197 }
4198
Eric Laurent0e46adf2016-12-16 12:49:24 -08004199 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4200 ret = -ENOSYS;
4201 goto exit;
4202 }
4203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004204 if (in->standby) {
Andy Hung241e36f2019-02-19 12:00:38 -08004205 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
4206
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004207 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004208 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004209 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004210 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004211 goto exit;
4212 }
4213 in->standby = 0;
Andy Hung241e36f2019-02-19 12:00:38 -08004214
4215 // log startup time in ms.
4216 simple_stats_log(
4217 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004218 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004219
Andy Hungd13f0d32017-06-12 13:58:37 -07004220 // errors that occur here are read errors.
4221 error_code = ERROR_CODE_READ;
4222
Haynes Mathew George03c40102016-01-29 17:57:48 -08004223 //what's the duration requested by the client?
4224 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4225 in->config.rate;
4226 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004227
Haynes Mathew George03c40102016-01-29 17:57:48 -08004228 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004229 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08004230 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004231 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07004232 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004233 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004234 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004235 if (ret < 0) {
4236 ALOGE("Failed to read w/err %s", strerror(errno));
4237 ret = -errno;
4238 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004239 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4240 if (bytes % 4 == 0) {
4241 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4242 int_buf_stream = buffer;
4243 for (size_t itt=0; itt < bytes/4 ; itt++) {
4244 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07004245 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004246 } else {
4247 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
4248 ret = -EINVAL;
4249 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07004250 }
4251 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004252 }
4253
Haynes Mathew George03c40102016-01-29 17:57:48 -08004254 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004255
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004256 /*
4257 * Instead of writing zeroes here, we could trust the hardware
4258 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004259 * 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 -08004260 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08004261 if (ret == 0 && adev->mic_muted &&
4262 !voice_is_in_call_rec_stream(in) &&
4263 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004264 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07004265 in->frames_muted += frames;
4266 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004267
4268exit:
4269 pthread_mutex_unlock(&in->lock);
4270
4271 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07004272 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004273 in_standby(&in->stream.common);
4274 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004275 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08004276 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07004277 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08004278 }
4279 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07004280 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004281 }
4282 return bytes;
4283}
4284
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004285static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004286{
4287 return 0;
4288}
4289
Andy Hung6ebe5962016-01-15 17:46:57 -08004290static int in_get_capture_position(const struct audio_stream_in *stream,
4291 int64_t *frames, int64_t *time)
4292{
4293 if (stream == NULL || frames == NULL || time == NULL) {
4294 return -EINVAL;
4295 }
4296 struct stream_in *in = (struct stream_in *)stream;
4297 int ret = -ENOSYS;
4298
4299 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004300 // note: ST sessions do not close the alsa pcm driver synchronously
4301 // on standby. Therefore, we may return an error even though the
4302 // pcm stream is still opened.
4303 if (in->standby) {
4304 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
4305 "%s stream in standby but pcm not NULL for non ST session", __func__);
4306 goto exit;
4307 }
Andy Hung6ebe5962016-01-15 17:46:57 -08004308 if (in->pcm) {
4309 struct timespec timestamp;
4310 unsigned int avail;
4311 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
4312 *frames = in->frames_read + avail;
4313 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
4314 ret = 0;
4315 }
4316 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004317exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08004318 pthread_mutex_unlock(&in->lock);
4319 return ret;
4320}
4321
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004322static int add_remove_audio_effect(const struct audio_stream *stream,
4323 effect_handle_t effect,
4324 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004325{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004326 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004327 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004328 int status = 0;
4329 effect_descriptor_t desc;
4330
4331 status = (*effect)->get_descriptor(effect, &desc);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004332 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
4333
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004334 if (status != 0)
4335 return status;
4336
Eric Laurenta1478072015-09-21 17:21:52 -07004337 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004338 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07004339 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07004340 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07004341 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004342 in->enable_aec != enable &&
4343 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4344 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004345 if (!enable)
4346 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07004347 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
4348 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
4349 adev->enable_voicerx = enable;
4350 struct audio_usecase *usecase;
4351 struct listnode *node;
4352 list_for_each(node, &adev->usecase_list) {
4353 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07004354 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07004355 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05004356 }
4357 }
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004358 if (!in->standby
4359 && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004360 select_devices(in->dev, in->usecase);
4361 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004362 if (in->enable_ns != enable &&
4363 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4364 in->enable_ns = enable;
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004365 if (!in->standby) {
4366 if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
4367 || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
4368 select_devices(in->dev, in->usecase);
4369 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004370 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004371 pthread_mutex_unlock(&in->dev->lock);
4372 pthread_mutex_unlock(&in->lock);
4373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004374 return 0;
4375}
4376
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004377static int in_add_audio_effect(const struct audio_stream *stream,
4378 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004379{
Eric Laurent994a6932013-07-17 11:51:42 -07004380 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004381 return add_remove_audio_effect(stream, effect, true);
4382}
4383
4384static int in_remove_audio_effect(const struct audio_stream *stream,
4385 effect_handle_t effect)
4386{
Eric Laurent994a6932013-07-17 11:51:42 -07004387 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004388 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004389}
4390
Eric Laurent0e46adf2016-12-16 12:49:24 -08004391static int in_stop(const struct audio_stream_in* stream)
4392{
4393 struct stream_in *in = (struct stream_in *)stream;
4394 struct audio_device *adev = in->dev;
4395
4396 int ret = -ENOSYS;
4397 ALOGV("%s", __func__);
4398 pthread_mutex_lock(&adev->lock);
4399 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4400 in->capture_started && in->pcm != NULL) {
4401 pcm_stop(in->pcm);
4402 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08004403 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004404 }
4405 pthread_mutex_unlock(&adev->lock);
4406 return ret;
4407}
4408
4409static int in_start(const struct audio_stream_in* stream)
4410{
4411 struct stream_in *in = (struct stream_in *)stream;
4412 struct audio_device *adev = in->dev;
4413 int ret = -ENOSYS;
4414
4415 ALOGV("%s in %p", __func__, in);
4416 pthread_mutex_lock(&adev->lock);
4417 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4418 !in->capture_started && in->pcm != NULL) {
4419 if (!in->capture_started) {
4420 ret = start_input_stream(in);
4421 if (ret == 0) {
4422 in->capture_started = true;
4423 }
4424 }
4425 }
4426 pthread_mutex_unlock(&adev->lock);
4427 return ret;
4428}
4429
4430static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4431 int32_t min_size_frames,
4432 struct audio_mmap_buffer_info *info)
4433{
4434 struct stream_in *in = (struct stream_in *)stream;
4435 struct audio_device *adev = in->dev;
4436 int ret = 0;
4437 unsigned int offset1;
4438 unsigned int frames1;
4439 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004440 uint32_t mmap_size;
4441 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004442
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004443 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004444 pthread_mutex_lock(&adev->lock);
4445 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004446
Eric Laurent0e46adf2016-12-16 12:49:24 -08004447 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004448 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004449 ret = -EINVAL;
4450 goto exit;
4451 }
4452 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004453 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004454 ALOGV("%s in %p", __func__, in);
4455 ret = -ENOSYS;
4456 goto exit;
4457 }
4458 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4459 if (in->pcm_device_id < 0) {
4460 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4461 __func__, in->pcm_device_id, in->usecase);
4462 ret = -EINVAL;
4463 goto exit;
4464 }
Phil Burkbc991042017-02-24 08:06:44 -08004465
4466 adjust_mmap_period_count(&in->config, min_size_frames);
4467
Eric Laurent0e46adf2016-12-16 12:49:24 -08004468 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4469 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4470 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4471 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4472 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4473 step = "open";
4474 ret = -ENODEV;
4475 goto exit;
4476 }
4477
4478 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4479 if (ret < 0) {
4480 step = "begin";
4481 goto exit;
4482 }
4483 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004484 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004485 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004486 ret = platform_get_mmap_data_fd(adev->platform,
4487 in->pcm_device_id, 1 /*capture*/,
4488 &info->shared_memory_fd,
4489 &mmap_size);
4490 if (ret < 0) {
4491 // Fall back to non exclusive mode
4492 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4493 } else {
4494 if (mmap_size < buffer_size) {
4495 step = "mmap";
4496 goto exit;
4497 }
4498 // FIXME: indicate exclusive mode support by returning a negative buffer size
4499 info->buffer_size_frames *= -1;
4500 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004501
Haynes Mathew George96483a22017-03-28 14:52:47 -07004502 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004503
4504 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4505 if (ret < 0) {
4506 step = "commit";
4507 goto exit;
4508 }
4509
Phil Burkbc991042017-02-24 08:06:44 -08004510 in->standby = false;
4511 ret = 0;
4512
Eric Laurent0e46adf2016-12-16 12:49:24 -08004513 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4514 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004515
4516exit:
4517 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004518 if (in->pcm == NULL) {
4519 ALOGE("%s: %s - %d", __func__, step, ret);
4520 } else {
4521 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004522 pcm_close(in->pcm);
4523 in->pcm = NULL;
4524 }
4525 }
4526 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004527 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004528 return ret;
4529}
4530
4531static int in_get_mmap_position(const struct audio_stream_in *stream,
4532 struct audio_mmap_position *position)
4533{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004534 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004535 struct stream_in *in = (struct stream_in *)stream;
4536 ALOGVV("%s", __func__);
4537 if (position == NULL) {
4538 return -EINVAL;
4539 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004540 lock_input_stream(in);
4541 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4542 in->pcm == NULL) {
4543 ret = -ENOSYS;
4544 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004545 }
4546 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004547 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004548 if (ret < 0) {
4549 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004550 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004551 }
Andy Hungfc044e12017-03-20 09:24:22 -07004552 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004553exit:
4554 pthread_mutex_unlock(&in->lock);
4555 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004556}
4557
jiabin8962a4d2018-03-19 18:21:24 -07004558static int in_get_active_microphones(const struct audio_stream_in *stream,
4559 struct audio_microphone_characteristic_t *mic_array,
4560 size_t *mic_count) {
4561 struct stream_in *in = (struct stream_in *)stream;
4562 struct audio_device *adev = in->dev;
4563 ALOGVV("%s", __func__);
4564
4565 lock_input_stream(in);
4566 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004567 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004568 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004569 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004570 pthread_mutex_unlock(&adev->lock);
4571 pthread_mutex_unlock(&in->lock);
4572
4573 return ret;
4574}
4575
4576static int adev_get_microphones(const struct audio_hw_device *dev,
4577 struct audio_microphone_characteristic_t *mic_array,
4578 size_t *mic_count) {
4579 struct audio_device *adev = (struct audio_device *)dev;
4580 ALOGVV("%s", __func__);
4581
4582 pthread_mutex_lock(&adev->lock);
4583 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4584 pthread_mutex_unlock(&adev->lock);
4585
4586 return ret;
4587}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004588
Paul McLean57530d52018-12-17 08:24:21 -07004589static int in_set_microphone_direction(const struct audio_stream_in *stream,
4590 audio_microphone_direction_t dir) {
4591 (void)stream;
4592 (void)dir;
4593 ALOGVV("%s", __func__);
4594 return -ENOSYS;
4595}
4596
4597static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
4598 (void)stream;
4599 (void)zoom;
4600 ALOGVV("%s", __func__);
4601 return -ENOSYS;
4602}
4603
juyuchenba338cd2019-01-21 11:57:17 +08004604static void in_update_sink_metadata(struct audio_stream_in *stream,
4605 const struct sink_metadata *sink_metadata) {
4606
4607 if (stream == NULL
4608 || sink_metadata == NULL
4609 || sink_metadata->tracks == NULL) {
4610 return;
4611 }
4612
4613 int error = 0;
4614 struct stream_in *in = (struct stream_in *)stream;
4615 struct audio_device *adev = in->dev;
4616 audio_devices_t device = AUDIO_DEVICE_NONE;
4617
4618 if (sink_metadata->track_count != 0)
4619 device = sink_metadata->tracks->dest_device;
4620
4621 lock_input_stream(in);
4622 pthread_mutex_lock(&adev->lock);
4623 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
4624
4625 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
4626 && device != AUDIO_DEVICE_NONE
4627 && adev->voice_tx_output != NULL) {
4628 /* Use the rx device from afe-proxy record to route voice call because
4629 there is no routing if tx device is on primary hal and rx device
4630 is on other hal during voice call. */
4631 adev->voice_tx_output->devices = device;
4632
4633 if (!voice_is_call_state_active(adev)) {
4634 if (adev->mode == AUDIO_MODE_IN_CALL) {
4635 adev->current_call_output = adev->voice_tx_output;
4636 error = voice_start_call(adev);
4637 if (error != 0)
4638 ALOGE("%s: start voice call failed %d", __func__, error);
4639 }
4640 } else {
4641 adev->current_call_output = adev->voice_tx_output;
4642 voice_update_devices_for_all_voice_usecases(adev);
4643 }
4644 }
4645
4646 pthread_mutex_unlock(&adev->lock);
4647 pthread_mutex_unlock(&in->lock);
4648}
4649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650static int adev_open_output_stream(struct audio_hw_device *dev,
4651 audio_io_handle_t handle,
4652 audio_devices_t devices,
4653 audio_output_flags_t flags,
4654 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004655 struct audio_stream_out **stream_out,
4656 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657{
4658 struct audio_device *adev = (struct audio_device *)dev;
4659 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004660 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004661 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4662 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4663 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004664 bool force_haptic_path =
4665 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004666
Andy Hungd9653bd2017-08-01 19:31:39 -07004667 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4668 return -ENOSYS;
4669 }
4670
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004671 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4672 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004673
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004674 *stream_out = NULL;
4675 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4676
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004677 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4678
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004679 if (devices == AUDIO_DEVICE_NONE)
4680 devices = AUDIO_DEVICE_OUT_SPEAKER;
4681
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004682 out->flags = flags;
4683 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004684 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004685 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004686 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004687
4688 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004689 if ((is_hdmi || is_usb_dev) &&
4690 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4691 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4692 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004693 audio_format_t req_format = config->format;
4694 audio_channel_mask_t req_channel_mask = config->channel_mask;
4695 uint32_t req_sample_rate = config->sample_rate;
4696
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004697 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004698 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004699 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004700 if (config->sample_rate == 0)
4701 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004702 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004703 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4704 if (config->format == AUDIO_FORMAT_DEFAULT)
4705 config->format = AUDIO_FORMAT_PCM_16_BIT;
4706 } else if (is_usb_dev) {
4707 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4708 &config->format,
4709 &out->supported_formats[0],
4710 MAX_SUPPORTED_FORMATS,
4711 &config->channel_mask,
4712 &out->supported_channel_masks[0],
4713 MAX_SUPPORTED_CHANNEL_MASKS,
4714 &config->sample_rate,
4715 &out->supported_sample_rates[0],
4716 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004717 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004718 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004719 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004720 if (ret != 0) {
4721 // For MMAP NO IRQ, allow conversions in ADSP
4722 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4723 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004724
Eric Laurentab805ee2018-03-30 12:20:38 -07004725 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4726 config->sample_rate = req_sample_rate;
4727 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4728 config->channel_mask = req_channel_mask;
4729 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4730 config->format = req_format;
4731 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004732
Haynes Mathew George569b7482017-05-08 14:44:27 -07004733 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004734 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004735 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004736 if (is_hdmi) {
4737 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4738 out->config = pcm_config_hdmi_multi;
4739 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4740 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4741 out->config = pcm_config_mmap_playback;
4742 out->stream.start = out_start;
4743 out->stream.stop = out_stop;
4744 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4745 out->stream.get_mmap_position = out_get_mmap_position;
4746 } else {
4747 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4748 out->config = pcm_config_hifi;
4749 }
4750
4751 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004752 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004753 if (is_hdmi) {
4754 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4755 audio_bytes_per_sample(out->format));
4756 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004757 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004758 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004759 pthread_mutex_lock(&adev->lock);
4760 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4761 pthread_mutex_unlock(&adev->lock);
4762
4763 // reject offload during card offline to allow
4764 // fallback to s/w paths
4765 if (offline) {
4766 ret = -ENODEV;
4767 goto error_open;
4768 }
4769
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004770 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4771 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4772 ALOGE("%s: Unsupported Offload information", __func__);
4773 ret = -EINVAL;
4774 goto error_open;
4775 }
4776 if (!is_supported_format(config->offload_info.format)) {
4777 ALOGE("%s: Unsupported audio format", __func__);
4778 ret = -EINVAL;
4779 goto error_open;
4780 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004781 out->sample_rate = config->offload_info.sample_rate;
4782 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4783 out->channel_mask = config->offload_info.channel_mask;
4784 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4785 out->channel_mask = config->channel_mask;
4786 else
4787 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4788
4789 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004790
4791 out->compr_config.codec = (struct snd_codec *)
4792 calloc(1, sizeof(struct snd_codec));
4793
4794 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004795
4796 out->stream.set_callback = out_set_callback;
4797 out->stream.pause = out_pause;
4798 out->stream.resume = out_resume;
4799 out->stream.drain = out_drain;
4800 out->stream.flush = out_flush;
4801
4802 out->compr_config.codec->id =
4803 get_snd_codec_id(config->offload_info.format);
4804 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4805 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004806 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004807 out->compr_config.codec->bit_rate =
4808 config->offload_info.bit_rate;
4809 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004810 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004811 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4812
4813 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4814 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004815
4816 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004817 create_offload_callback_thread(out);
4818 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4819 __func__, config->offload_info.version,
4820 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004821 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4822 switch (config->sample_rate) {
4823 case 0:
4824 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4825 break;
4826 case 8000:
4827 case 16000:
4828 case 48000:
4829 out->sample_rate = config->sample_rate;
4830 break;
4831 default:
4832 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4833 config->sample_rate);
4834 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4835 ret = -EINVAL;
4836 goto error_open;
4837 }
4838 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4839 switch (config->channel_mask) {
4840 case AUDIO_CHANNEL_NONE:
4841 case AUDIO_CHANNEL_OUT_STEREO:
4842 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4843 break;
4844 default:
4845 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4846 config->channel_mask);
4847 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4848 ret = -EINVAL;
4849 goto error_open;
4850 }
4851 switch (config->format) {
4852 case AUDIO_FORMAT_DEFAULT:
4853 case AUDIO_FORMAT_PCM_16_BIT:
4854 out->format = AUDIO_FORMAT_PCM_16_BIT;
4855 break;
4856 default:
4857 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4858 config->format);
4859 config->format = AUDIO_FORMAT_PCM_16_BIT;
4860 ret = -EINVAL;
4861 goto error_open;
4862 }
4863
4864 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004865 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004866 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004867 case 0:
4868 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4869 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004870 case 8000:
4871 case 16000:
4872 case 48000:
4873 out->sample_rate = config->sample_rate;
4874 break;
4875 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004876 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4877 config->sample_rate);
4878 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4879 ret = -EINVAL;
4880 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004881 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004882 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4883 switch (config->channel_mask) {
4884 case AUDIO_CHANNEL_NONE:
4885 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4886 break;
4887 case AUDIO_CHANNEL_OUT_STEREO:
4888 out->channel_mask = config->channel_mask;
4889 break;
4890 default:
4891 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4892 config->channel_mask);
4893 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4894 ret = -EINVAL;
4895 break;
4896 }
4897 switch (config->format) {
4898 case AUDIO_FORMAT_DEFAULT:
4899 out->format = AUDIO_FORMAT_PCM_16_BIT;
4900 break;
4901 case AUDIO_FORMAT_PCM_16_BIT:
4902 out->format = config->format;
4903 break;
4904 default:
4905 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4906 config->format);
4907 config->format = AUDIO_FORMAT_PCM_16_BIT;
4908 ret = -EINVAL;
4909 break;
4910 }
4911 if (ret != 0)
4912 goto error_open;
4913
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004914 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4915 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004916 out->config.rate = out->sample_rate;
4917 out->config.channels =
4918 audio_channel_count_from_out_mask(out->channel_mask);
4919 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004920 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004921 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4922 switch (config->sample_rate) {
4923 case 0:
4924 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4925 break;
4926 case 8000:
4927 case 16000:
4928 case 32000:
4929 case 48000:
4930 out->sample_rate = config->sample_rate;
4931 break;
4932 default:
4933 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4934 config->sample_rate);
4935 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4936 ret = -EINVAL;
4937 break;
4938 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004939 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004940 switch (config->channel_mask) {
4941 case AUDIO_CHANNEL_NONE:
4942 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4943 break;
4944 case AUDIO_CHANNEL_OUT_STEREO:
4945 out->channel_mask = config->channel_mask;
4946 break;
4947 default:
4948 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4949 config->channel_mask);
4950 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4951 ret = -EINVAL;
4952 break;
4953 }
4954 switch (config->format) {
4955 case AUDIO_FORMAT_DEFAULT:
4956 out->format = AUDIO_FORMAT_PCM_16_BIT;
4957 break;
4958 case AUDIO_FORMAT_PCM_16_BIT:
4959 out->format = config->format;
4960 break;
4961 default:
4962 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4963 config->format);
4964 config->format = AUDIO_FORMAT_PCM_16_BIT;
4965 ret = -EINVAL;
4966 break;
4967 }
4968 if (ret != 0)
4969 goto error_open;
4970
vivek mehtaa68fea62017-06-08 19:04:02 -07004971 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004972 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4973 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004974 out->config.rate = out->sample_rate;
4975 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004976 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004977 out->sample_rate,
4978 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004979 out->config.channels,
4980 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004981 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004982 out->config.period_size = buffer_size / frame_size;
4983 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4984 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004985 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004986 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004987 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4988 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004989 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004990 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4991 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004992 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004993 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004994 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004995 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004996 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004997 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4998 out->config = pcm_config_mmap_playback;
4999 out->stream.start = out_start;
5000 out->stream.stop = out_stop;
5001 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5002 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005003 } else {
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005004 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5005 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
5006 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
5007 if (adev->haptic_pcm_device_id < 0) {
5008 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
5009 __func__, adev->haptic_pcm_device_id, out->usecase);
5010 ret = -ENOSYS;
5011 goto error_open;
5012 }
5013 out->config = pcm_config_haptics_audio;
5014 if (force_haptic_path)
5015 adev->haptics_config = pcm_config_haptics_audio;
5016 else
5017 adev->haptics_config = pcm_config_haptics;
5018 } else {
5019 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
5020 out->config = pcm_config_low_latency;
5021 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07005022 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005023
5024 if (config->sample_rate == 0) {
5025 out->sample_rate = out->config.rate;
5026 } else {
5027 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005028 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005029
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005030 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
5031 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
5032 } else {
5033 out->channel_mask = config->channel_mask;
5034 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005035
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005036 if (config->format == AUDIO_FORMAT_DEFAULT)
5037 out->format = audio_format_from_pcm_format(out->config.format);
5038 else if (!audio_is_linear_pcm(config->format)) {
5039 config->format = AUDIO_FORMAT_PCM_16_BIT;
5040 ret = -EINVAL;
5041 goto error_open;
5042 } else {
5043 out->format = config->format;
5044 }
5045
5046 out->config.rate = out->sample_rate;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005047
5048 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5049 out->config.channels =
5050 audio_channel_count_from_out_mask(out->channel_mask &
5051 ~AUDIO_CHANNEL_HAPTIC_ALL);
5052
5053 if (force_haptic_path) {
5054 out->config.channels = 1;
5055 adev->haptics_config.channels = 1;
5056 } else {
5057 adev->haptics_config.channels =
5058 audio_channel_count_from_out_mask(out->channel_mask &
5059 AUDIO_CHANNEL_HAPTIC_ALL);
5060 }
5061 } else {
5062 out->config.channels =
5063 audio_channel_count_from_out_mask(out->channel_mask);
5064 }
5065
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005066 if (out->format != audio_format_from_pcm_format(out->config.format)) {
5067 out->config.format = pcm_format_from_audio_format(out->format);
5068 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005069 }
Kevin Rocard50eff892017-05-02 16:52:05 -07005070
5071 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
5072 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005073 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07005074 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
5075 __func__, config->sample_rate, config->format, config->channel_mask);
5076 config->sample_rate = out->sample_rate;
5077 config->format = out->format;
5078 config->channel_mask = out->channel_mask;
5079 ret = -EINVAL;
5080 goto error_open;
5081 }
5082
Andy Hung6fcba9c2014-03-18 11:53:32 -07005083 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
5084 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005085
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005086 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005087 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005088 adev->primary_output = out;
5089 else {
5090 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005091 ret = -EEXIST;
5092 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005093 }
5094 }
5095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005096 /* Check if this usecase is already existing */
5097 pthread_mutex_lock(&adev->lock);
5098 if (get_usecase_from_list(adev, out->usecase) != NULL) {
5099 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005100 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005101 ret = -EEXIST;
5102 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005103 }
5104 pthread_mutex_unlock(&adev->lock);
5105
5106 out->stream.common.get_sample_rate = out_get_sample_rate;
5107 out->stream.common.set_sample_rate = out_set_sample_rate;
5108 out->stream.common.get_buffer_size = out_get_buffer_size;
5109 out->stream.common.get_channels = out_get_channels;
5110 out->stream.common.get_format = out_get_format;
5111 out->stream.common.set_format = out_set_format;
5112 out->stream.common.standby = out_standby;
5113 out->stream.common.dump = out_dump;
5114 out->stream.common.set_parameters = out_set_parameters;
5115 out->stream.common.get_parameters = out_get_parameters;
5116 out->stream.common.add_audio_effect = out_add_audio_effect;
5117 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5118 out->stream.get_latency = out_get_latency;
5119 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005120#ifdef NO_AUDIO_OUT
5121 out->stream.write = out_write_for_no_output;
5122#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005123 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005124#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005125 out->stream.get_render_position = out_get_render_position;
5126 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005127 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005128
Eric Laurent0e46adf2016-12-16 12:49:24 -08005129 if (out->realtime)
5130 out->af_period_multiplier = af_period_multiplier;
5131 else
5132 out->af_period_multiplier = 1;
5133
Andy Hung572633e2019-02-19 11:58:24 -08005134 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
5135
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005136 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005137 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005138 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005139
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005140 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005141 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005142 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5143
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005144 config->format = out->stream.common.get_format(&out->stream.common);
5145 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5146 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5147
Kevin Rocarda325aa22018-04-03 09:15:52 -07005148 register_format(out->format, out->supported_formats);
5149 register_channel_mask(out->channel_mask, out->supported_channel_masks);
5150 register_sample_rate(out->sample_rate, out->supported_sample_rates);
5151
Andy Hunga452b0a2017-03-15 14:51:15 -07005152 out->error_log = error_log_create(
5153 ERROR_LOG_ENTRIES,
5154 1000000000 /* aggregate consecutive identical errors within one second in ns */);
5155
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005156 /*
5157 By locking output stream before registering, we allow the callback
5158 to update stream's state only after stream's initial state is set to
5159 adev state.
5160 */
5161 lock_output_stream(out);
5162 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5163 pthread_mutex_lock(&adev->lock);
5164 out->card_status = adev->card_status;
5165 pthread_mutex_unlock(&adev->lock);
5166 pthread_mutex_unlock(&out->lock);
5167
vivek mehta4a824772017-06-08 19:05:49 -07005168 stream_app_type_cfg_init(&out->app_type_cfg);
5169
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005170 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005171
Eric Laurent994a6932013-07-17 11:51:42 -07005172 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005173 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005174
5175error_open:
5176 free(out);
5177 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07005178 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005179 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005180}
5181
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005182static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005183 struct audio_stream_out *stream)
5184{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005185 struct stream_out *out = (struct stream_out *)stream;
5186 struct audio_device *adev = out->dev;
5187
Eric Laurent994a6932013-07-17 11:51:42 -07005188 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005189
5190 // must deregister from sndmonitor first to prevent races
5191 // between the callback and close_stream
5192 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005193 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005194 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
5195 destroy_offload_callback_thread(out);
5196
5197 if (out->compr_config.codec != NULL)
5198 free(out->compr_config.codec);
5199 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005200
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005201 out->a2dp_compress_mute = false;
5202
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005203 if (adev->voice_tx_output == out)
5204 adev->voice_tx_output = NULL;
5205
Andy Hunga452b0a2017-03-15 14:51:15 -07005206 error_log_destroy(out->error_log);
5207 out->error_log = NULL;
5208
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005209 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005210 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005211 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005212 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005213 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005214}
5215
5216static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5217{
5218 struct audio_device *adev = (struct audio_device *)dev;
5219 struct str_parms *parms;
5220 char *str;
5221 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005222 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005223 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07005224 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005225 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005226
Joe Onorato188b6222016-03-01 11:02:27 -08005227 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005228
5229 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005230
5231 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005232 status = voice_set_parameters(adev, parms);
5233 if (status != 0) {
5234 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005235 }
5236
5237 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5238 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07005239 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005240 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5241 adev->bluetooth_nrec = true;
5242 else
5243 adev->bluetooth_nrec = false;
5244 }
5245
5246 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5247 if (ret >= 0) {
5248 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5249 adev->screen_off = false;
5250 else
5251 adev->screen_off = true;
5252 }
5253
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005254 ret = str_parms_get_int(parms, "rotation", &val);
5255 if (ret >= 0) {
5256 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005257 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005258 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005259 // FIXME: note that the code below assumes that the speakers are in the correct placement
5260 // relative to the user when the device is rotated 90deg from its default rotation. This
5261 // assumption is device-specific, not platform-specific like this code.
5262 case 270:
5263 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005264 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005265 break;
5266 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005267 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07005268 camera_rotation = CAMERA_ROTATION_PORTRAIT;
5269 break;
5270 case 90:
5271 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005272 break;
5273 default:
5274 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07005275 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005276 }
Eric Laurent03f09432014-03-25 18:09:11 -07005277 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07005278 // check and set swap
5279 // - check if orientation changed and speaker active
5280 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07005281 adev->camera_orientation =
5282 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
5283#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07005284 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07005285#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005286 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005287 }
5288
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005289 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5290 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005291 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005292 }
5293
David Linee3fe402017-03-13 10:00:42 -07005294 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5295 if (ret >= 0) {
5296 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005297 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005298 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5299 if (ret >= 0) {
5300 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005301 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005302 }
Eric Laurent99dab492017-06-17 15:19:08 -07005303 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005304 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5305 if (ret >= 0) {
5306 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005307 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005308 }
5309 }
5310 }
5311
5312 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, 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_remove_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_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005326 }
5327 }
5328 }
5329
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08005330 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08005331 audio_extn_ma_set_parameters(adev, parms);
5332
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005333 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
5334 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005335 struct audio_usecase *usecase;
5336 struct listnode *node;
5337 list_for_each(node, &adev->usecase_list) {
5338 usecase = node_to_item(node, struct audio_usecase, list);
5339 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005340 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005341 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
5342
5343 pthread_mutex_unlock(&adev->lock);
5344 lock_output_stream(usecase->stream.out);
5345 pthread_mutex_lock(&adev->lock);
5346 audio_extn_a2dp_set_handoff_mode(true);
5347 // force device switch to reconfigure encoder
5348 select_devices(adev, usecase->id);
5349 audio_extn_a2dp_set_handoff_mode(false);
5350 pthread_mutex_unlock(&usecase->stream.out->lock);
5351 break;
5352 }
5353 }
5354 }
5355
Eric Laurent5f4ca952018-10-19 17:33:43 -07005356 //FIXME: to be replaced by proper video capture properties API
5357 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
5358 if (ret >= 0) {
5359 int camera_facing = CAMERA_FACING_BACK;
5360 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
5361 camera_facing = CAMERA_FACING_FRONT;
5362 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
5363 camera_facing = CAMERA_FACING_BACK;
5364 else {
5365 ALOGW("%s: invalid camera facing value: %s", __func__, value);
5366 goto done;
5367 }
5368 adev->camera_orientation =
5369 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
5370 struct audio_usecase *usecase;
5371 struct listnode *node;
5372 list_for_each(node, &adev->usecase_list) {
5373 usecase = node_to_item(node, struct audio_usecase, list);
5374 struct stream_in *in = usecase->stream.in;
5375 if (usecase->type == PCM_CAPTURE && in != NULL &&
5376 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
5377 select_devices(adev, in->usecase);
5378 }
5379 }
5380 }
5381
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005382done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005383 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005384 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07005385 ALOGV("%s: exit with code(%d)", __func__, status);
5386 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005387}
5388
5389static char* adev_get_parameters(const struct audio_hw_device *dev,
5390 const char *keys)
5391{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005392 struct audio_device *adev = (struct audio_device *)dev;
5393 struct str_parms *reply = str_parms_create();
5394 struct str_parms *query = str_parms_create_str(keys);
5395 char *str;
5396
5397 pthread_mutex_lock(&adev->lock);
5398
5399 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005400 audio_extn_a2dp_get_parameters(query, reply);
5401
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005402 str = str_parms_to_str(reply);
5403 str_parms_destroy(query);
5404 str_parms_destroy(reply);
5405
5406 pthread_mutex_unlock(&adev->lock);
5407 ALOGV("%s: exit: returns - %s", __func__, str);
5408 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005409}
5410
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005411static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005412{
5413 return 0;
5414}
5415
Haynes Mathew George5191a852013-09-11 14:19:36 -07005416static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5417{
5418 int ret;
5419 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005420
Eric Laurent4cc4ce12014-09-10 13:21:01 -05005421 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
5422
Haynes Mathew George5191a852013-09-11 14:19:36 -07005423 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005424 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005425 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005426
Haynes Mathew George5191a852013-09-11 14:19:36 -07005427 return ret;
5428}
5429
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005430static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005431{
5432 return -ENOSYS;
5433}
5434
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005435static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5436 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005437{
5438 return -ENOSYS;
5439}
5440
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005441static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005442{
5443 return -ENOSYS;
5444}
5445
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005446static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005447{
5448 return -ENOSYS;
5449}
5450
5451static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5452{
5453 struct audio_device *adev = (struct audio_device *)dev;
5454
5455 pthread_mutex_lock(&adev->lock);
5456 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07005457 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005458 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005459 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
5460 voice_is_in_call(adev)) {
5461 voice_stop_call(adev);
5462 adev->current_call_output = NULL;
5463 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005464 }
5465 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05005466
5467 audio_extn_extspk_set_mode(adev->extspk, mode);
5468
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005469 return 0;
5470}
5471
5472static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5473{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005474 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005475 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005476
Eric Laurent2bafff12016-03-17 12:17:23 -07005477 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005478 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005479 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
5480 ret = audio_extn_hfp_set_mic_mute(adev, state);
5481 } else {
5482 ret = voice_set_mic_mute(adev, state);
5483 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005484 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005485 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005486
5487 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005488}
5489
5490static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5491{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005492 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005493 return 0;
5494}
5495
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005496static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005497 const struct audio_config *config)
5498{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005499 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005500
Eric Laurent74b55762017-07-09 17:04:53 -07005501 /* Don't know if USB HIFI in this context so use true to be conservative */
5502 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5503 true /*is_usb_hifi */) != 0)
5504 return 0;
5505
vivek mehtaa68fea62017-06-08 19:04:02 -07005506 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5507 config->sample_rate, config->format,
5508 channel_count,
5509 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005510}
5511
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005512static bool adev_input_allow_hifi_record(struct audio_device *adev,
5513 audio_devices_t devices,
5514 audio_input_flags_t flags,
5515 audio_source_t source) {
5516 const bool allowed = true;
5517
5518 if (!audio_is_usb_in_device(devices))
5519 return !allowed;
5520
5521 switch (flags) {
5522 case AUDIO_INPUT_FLAG_NONE:
5523 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5524 break;
5525 default:
5526 return !allowed;
5527 }
5528
5529 switch (source) {
5530 case AUDIO_SOURCE_DEFAULT:
5531 case AUDIO_SOURCE_MIC:
5532 case AUDIO_SOURCE_UNPROCESSED:
5533 break;
5534 default:
5535 return !allowed;
5536 }
5537
5538 switch (adev->mode) {
5539 case 0:
5540 break;
5541 default:
5542 return !allowed;
5543 }
5544
5545 return allowed;
5546}
5547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005548static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005549 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005550 audio_devices_t devices,
5551 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005552 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005553 audio_input_flags_t flags,
5554 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005555 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005556{
5557 struct audio_device *adev = (struct audio_device *)dev;
5558 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005559 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005560 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005561 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005562 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005563 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5564 devices,
5565 flags,
5566 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005567 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5568 " sample_rate %u, channel_mask %#x, format %#x",
5569 __func__, flags, is_usb_dev, may_use_hifi_record,
5570 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005571 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005572
Andy Hungd9653bd2017-08-01 19:31:39 -07005573 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5574 return -ENOSYS;
5575 }
5576
Eric Laurent74b55762017-07-09 17:04:53 -07005577 if (!(is_usb_dev && may_use_hifi_record)) {
5578 if (config->sample_rate == 0)
5579 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5580 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5581 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5582 if (config->format == AUDIO_FORMAT_DEFAULT)
5583 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005584
Eric Laurent74b55762017-07-09 17:04:53 -07005585 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5586
5587 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5588 return -EINVAL;
5589 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005590
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005591 if (audio_extn_tfa_98xx_is_supported() &&
5592 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005593 return -EINVAL;
5594
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005595 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5596
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005597 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005598 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005600 in->stream.common.get_sample_rate = in_get_sample_rate;
5601 in->stream.common.set_sample_rate = in_set_sample_rate;
5602 in->stream.common.get_buffer_size = in_get_buffer_size;
5603 in->stream.common.get_channels = in_get_channels;
5604 in->stream.common.get_format = in_get_format;
5605 in->stream.common.set_format = in_set_format;
5606 in->stream.common.standby = in_standby;
5607 in->stream.common.dump = in_dump;
5608 in->stream.common.set_parameters = in_set_parameters;
5609 in->stream.common.get_parameters = in_get_parameters;
5610 in->stream.common.add_audio_effect = in_add_audio_effect;
5611 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5612 in->stream.set_gain = in_set_gain;
5613 in->stream.read = in_read;
5614 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005615 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005616 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLean57530d52018-12-17 08:24:21 -07005617 in->stream.set_microphone_direction = in_set_microphone_direction;
5618 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchenba338cd2019-01-21 11:57:17 +08005619 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005620
5621 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005622 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005623 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005624 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005625 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005626 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005627
Andy Hung88ce1d92018-10-29 18:31:12 -07005628 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005629 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5630 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5631 /* Force channel config requested to mono if incall
5632 record is being requested for only uplink/downlink */
5633 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5634 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5635 ret = -EINVAL;
5636 goto err_open;
5637 }
5638 }
5639
Haynes Mathew George569b7482017-05-08 14:44:27 -07005640 if (is_usb_dev && may_use_hifi_record) {
5641 /* HiFi record selects an appropriate format, channel, rate combo
5642 depending on sink capabilities*/
5643 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5644 &config->format,
5645 &in->supported_formats[0],
5646 MAX_SUPPORTED_FORMATS,
5647 &config->channel_mask,
5648 &in->supported_channel_masks[0],
5649 MAX_SUPPORTED_CHANNEL_MASKS,
5650 &config->sample_rate,
5651 &in->supported_sample_rates[0],
5652 MAX_SUPPORTED_SAMPLE_RATES);
5653 if (ret != 0) {
5654 ret = -EINVAL;
5655 goto err_open;
5656 }
Eric Laurent74b55762017-07-09 17:04:53 -07005657 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005658 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005659 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005660 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5661 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5662 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5663 bool ret_error = false;
5664 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5665 from HAL is 8_24
5666 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5667 8_24 return error indicating supported format is 8_24
5668 *> In case of any other source requesting 24 bit or float return error
5669 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005670
vivek mehta57ff9b52016-04-28 14:13:08 -07005671 on error flinger will retry with supported format passed
5672 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005673 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005674 config->format = AUDIO_FORMAT_PCM_16_BIT;
5675 ret_error = true;
5676 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5677 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5678 ret_error = true;
5679 }
5680
5681 if (ret_error) {
5682 ret = -EINVAL;
5683 goto err_open;
5684 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005685 }
5686
vivek mehta57ff9b52016-04-28 14:13:08 -07005687 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005688 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005689
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005690 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005691 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5692 if (config->sample_rate == 0)
5693 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5694 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5695 config->sample_rate != 8000) {
5696 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5697 ret = -EINVAL;
5698 goto err_open;
5699 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005700
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005701 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5702 config->format = AUDIO_FORMAT_PCM_16_BIT;
5703 ret = -EINVAL;
5704 goto err_open;
5705 }
5706
5707 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5708 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005709 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005710 } else if (is_usb_dev && may_use_hifi_record) {
5711 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5712 in->config = pcm_config_audio_capture;
5713 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005714 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5715 config->sample_rate,
5716 config->format,
5717 channel_count,
5718 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005719 in->config.period_size = buffer_size / frame_size;
5720 in->config.rate = config->sample_rate;
5721 in->af_period_multiplier = 1;
5722 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005723 } else {
5724 in->usecase = USECASE_AUDIO_RECORD;
5725 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005726 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005727 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005728#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005729 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005730#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005731 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005732 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005733 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005734 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005735 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5736 config->sample_rate,
5737 config->format,
5738 channel_count,
5739 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005740 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005741 in->config.rate = config->sample_rate;
5742 in->af_period_multiplier = 1;
5743 } else {
5744 // period size is left untouched for rt mode playback
5745 in->config = pcm_config_audio_capture_rt;
5746 in->af_period_multiplier = af_period_multiplier;
5747 }
5748 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5749 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005750 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005751 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5752 in->config = pcm_config_mmap_capture;
5753 in->stream.start = in_start;
5754 in->stream.stop = in_stop;
5755 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5756 in->stream.get_mmap_position = in_get_mmap_position;
5757 in->af_period_multiplier = 1;
5758 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005759 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005760 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005761 (config->sample_rate == 8000 ||
5762 config->sample_rate == 16000 ||
5763 config->sample_rate == 32000 ||
5764 config->sample_rate == 48000) &&
5765 channel_count == 1) {
5766 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5767 in->config = pcm_config_audio_capture;
5768 frame_size = audio_stream_in_frame_size(&in->stream);
5769 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5770 config->sample_rate,
5771 config->format,
5772 channel_count, false /*is_low_latency*/);
5773 in->config.period_size = buffer_size / frame_size;
5774 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5775 in->config.rate = config->sample_rate;
5776 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005777 } else {
5778 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005779 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005780 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5781 config->sample_rate,
5782 config->format,
5783 channel_count,
5784 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005785 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005786 in->config.rate = config->sample_rate;
5787 in->af_period_multiplier = 1;
5788 }
5789 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5790 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005791 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005793 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005794 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005795
Kevin Rocarda325aa22018-04-03 09:15:52 -07005796
5797 register_format(in->format, in->supported_formats);
5798 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5799 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5800
Andy Hungd13f0d32017-06-12 13:58:37 -07005801 in->error_log = error_log_create(
5802 ERROR_LOG_ENTRIES,
5803 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5804
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005805 /* This stream could be for sound trigger lab,
5806 get sound trigger pcm if present */
5807 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005808
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005809 lock_input_stream(in);
5810 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5811 pthread_mutex_lock(&adev->lock);
5812 in->card_status = adev->card_status;
5813 pthread_mutex_unlock(&adev->lock);
5814 pthread_mutex_unlock(&in->lock);
5815
vivek mehta4a824772017-06-08 19:05:49 -07005816 stream_app_type_cfg_init(&in->app_type_cfg);
5817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005818 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005819 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005820 return 0;
5821
5822err_open:
5823 free(in);
5824 *stream_in = NULL;
5825 return ret;
5826}
5827
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005828static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005829 struct audio_stream_in *stream)
5830{
Andy Hungd13f0d32017-06-12 13:58:37 -07005831 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005832 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005833
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005834 // must deregister from sndmonitor first to prevent races
5835 // between the callback and close_stream
5836 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005837 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005838
5839 error_log_destroy(in->error_log);
5840 in->error_log = NULL;
5841
Andy Hung0dbb52b2017-08-09 13:51:38 -07005842 pthread_mutex_destroy(&in->pre_lock);
5843 pthread_mutex_destroy(&in->lock);
5844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005845 free(stream);
5846
5847 return;
5848}
5849
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005850static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005851{
5852 return 0;
5853}
5854
Andy Hung31aca912014-03-20 17:14:59 -07005855/* verifies input and output devices and their capabilities.
5856 *
5857 * This verification is required when enabling extended bit-depth or
5858 * sampling rates, as not all qcom products support it.
5859 *
5860 * Suitable for calling only on initialization such as adev_open().
5861 * It fills the audio_device use_case_table[] array.
5862 *
5863 * Has a side-effect that it needs to configure audio routing / devices
5864 * in order to power up the devices and read the device parameters.
5865 * It does not acquire any hw device lock. Should restore the devices
5866 * back to "normal state" upon completion.
5867 */
5868static int adev_verify_devices(struct audio_device *adev)
5869{
5870 /* enumeration is a bit difficult because one really wants to pull
5871 * the use_case, device id, etc from the hidden pcm_device_table[].
5872 * In this case there are the following use cases and device ids.
5873 *
5874 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5875 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005876 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005877 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5878 * [USECASE_AUDIO_RECORD] = {0, 0},
5879 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5880 * [USECASE_VOICE_CALL] = {2, 2},
5881 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005882 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005883 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5884 */
5885
5886 /* should be the usecases enabled in adev_open_input_stream() */
5887 static const int test_in_usecases[] = {
5888 USECASE_AUDIO_RECORD,
5889 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5890 };
5891 /* should be the usecases enabled in adev_open_output_stream()*/
5892 static const int test_out_usecases[] = {
5893 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5894 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5895 };
5896 static const usecase_type_t usecase_type_by_dir[] = {
5897 PCM_PLAYBACK,
5898 PCM_CAPTURE,
5899 };
5900 static const unsigned flags_by_dir[] = {
5901 PCM_OUT,
5902 PCM_IN,
5903 };
5904
5905 size_t i;
5906 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005907 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005908 char info[512]; /* for possible debug info */
5909
5910 for (dir = 0; dir < 2; ++dir) {
5911 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5912 const unsigned flags_dir = flags_by_dir[dir];
5913 const size_t testsize =
5914 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5915 const int *testcases =
5916 dir ? test_in_usecases : test_out_usecases;
5917 const audio_devices_t audio_device =
5918 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5919
5920 for (i = 0; i < testsize; ++i) {
5921 const audio_usecase_t audio_usecase = testcases[i];
5922 int device_id;
5923 snd_device_t snd_device;
5924 struct pcm_params **pparams;
5925 struct stream_out out;
5926 struct stream_in in;
5927 struct audio_usecase uc_info;
5928 int retval;
5929
5930 pparams = &adev->use_case_table[audio_usecase];
5931 pcm_params_free(*pparams); /* can accept null input */
5932 *pparams = NULL;
5933
5934 /* find the device ID for the use case (signed, for error) */
5935 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5936 if (device_id < 0)
5937 continue;
5938
5939 /* prepare structures for device probing */
5940 memset(&uc_info, 0, sizeof(uc_info));
5941 uc_info.id = audio_usecase;
5942 uc_info.type = usecase_type;
5943 if (dir) {
Andy Hung31aca912014-03-20 17:14:59 -07005944 memset(&in, 0, sizeof(in));
5945 in.device = audio_device;
5946 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5947 uc_info.stream.in = &in;
Andy Hung31aca912014-03-20 17:14:59 -07005948 }
5949 memset(&out, 0, sizeof(out));
5950 out.devices = audio_device; /* only field needed in select_devices */
5951 uc_info.stream.out = &out;
5952 uc_info.devices = audio_device;
5953 uc_info.in_snd_device = SND_DEVICE_NONE;
5954 uc_info.out_snd_device = SND_DEVICE_NONE;
5955 list_add_tail(&adev->usecase_list, &uc_info.list);
5956
5957 /* select device - similar to start_(in/out)put_stream() */
5958 retval = select_devices(adev, audio_usecase);
5959 if (retval >= 0) {
5960 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5961#if LOG_NDEBUG == 0
5962 if (*pparams) {
5963 ALOGV("%s: (%s) card %d device %d", __func__,
5964 dir ? "input" : "output", card_id, device_id);
5965 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005966 } else {
5967 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5968 }
5969#endif
5970 }
5971
5972 /* deselect device - similar to stop_(in/out)put_stream() */
5973 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005974 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005975 /* 2. Disable the rx device */
5976 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005977 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005978 list_remove(&uc_info.list);
5979 }
5980 }
Andy Hung31aca912014-03-20 17:14:59 -07005981 return 0;
5982}
5983
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005984static int adev_close(hw_device_t *device)
5985{
Andy Hung31aca912014-03-20 17:14:59 -07005986 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005987 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005988
5989 if (!adev)
5990 return 0;
5991
5992 pthread_mutex_lock(&adev_init_lock);
5993
5994 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005995 audio_extn_snd_mon_unregister_listener(adev);
5996 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005997 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005998 audio_route_free(adev->audio_route);
5999 free(adev->snd_dev_ref_cnt);
6000 platform_deinit(adev->platform);
6001 audio_extn_extspk_deinit(adev->extspk);
6002 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006003 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006004 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
6005 pcm_params_free(adev->use_case_table[i]);
6006 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006007 if (adev->adm_deinit)
6008 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07006009 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006010 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07006011 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07006012
6013 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006014
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006015 return 0;
6016}
6017
Glenn Kasten4f993392014-05-14 07:30:48 -07006018/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6019 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6020 * just that it _might_ work.
6021 */
6022static int period_size_is_plausible_for_low_latency(int period_size)
6023{
6024 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006025 case 48:
6026 case 96:
6027 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07006028 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006029 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07006030 case 240:
6031 case 320:
6032 case 480:
6033 return 1;
6034 default:
6035 return 0;
6036 }
6037}
6038
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006039static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
6040{
6041 int card;
6042 card_status_t status;
6043
6044 if (!parms)
6045 return;
6046
6047 if (parse_snd_card_status(parms, &card, &status) < 0)
6048 return;
6049
6050 pthread_mutex_lock(&adev->lock);
6051 bool valid_cb = (card == adev->snd_card);
6052 if (valid_cb) {
6053 if (adev->card_status != status) {
6054 adev->card_status = status;
6055 platform_snd_card_update(adev->platform, status);
6056 }
6057 }
6058 pthread_mutex_unlock(&adev->lock);
6059 return;
6060}
6061
Aniket Kumar Lata26483012018-01-31 20:21:42 -08006062/* out and adev lock held */
6063static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6064{
6065 struct audio_usecase *uc_info;
6066 float left_p;
6067 float right_p;
6068 audio_devices_t devices;
6069
6070 uc_info = get_usecase_from_list(adev, out->usecase);
6071 if (uc_info == NULL) {
6072 ALOGE("%s: Could not find the usecase (%d) in the list",
6073 __func__, out->usecase);
6074 return -EINVAL;
6075 }
6076
6077 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6078 out->usecase, use_case_table[out->usecase]);
6079
6080 if (restore) {
6081 // restore A2DP device for active usecases and unmute if required
6082 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6083 !is_a2dp_device(uc_info->out_snd_device)) {
6084 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
6085 select_devices(adev, uc_info->id);
6086 pthread_mutex_lock(&out->compr_mute_lock);
6087 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6088 (out->a2dp_compress_mute)) {
6089 out->a2dp_compress_mute = false;
6090 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6091 }
6092 pthread_mutex_unlock(&out->compr_mute_lock);
6093 }
6094 } else {
6095 // mute compress stream if suspended
6096 pthread_mutex_lock(&out->compr_mute_lock);
6097 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6098 (!out->a2dp_compress_mute)) {
6099 if (!out->standby) {
6100 ALOGD("%s: selecting speaker and muting stream", __func__);
6101 devices = out->devices;
6102 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6103 left_p = out->volume_l;
6104 right_p = out->volume_r;
6105 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6106 compress_pause(out->compr);
6107 set_compr_volume(&out->stream, 0.0f, 0.0f);
6108 out->a2dp_compress_mute = true;
6109 select_devices(adev, out->usecase);
6110 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6111 compress_resume(out->compr);
6112 out->devices = devices;
6113 out->volume_l = left_p;
6114 out->volume_r = right_p;
6115 }
6116 }
6117 pthread_mutex_unlock(&out->compr_mute_lock);
6118 }
6119 ALOGV("%s: exit", __func__);
6120 return 0;
6121}
6122
6123int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6124{
6125 int ret = 0;
6126
6127 lock_output_stream(out);
6128 pthread_mutex_lock(&adev->lock);
6129
6130 ret = check_a2dp_restore_l(adev, out, restore);
6131
6132 pthread_mutex_unlock(&adev->lock);
6133 pthread_mutex_unlock(&out->lock);
6134 return ret;
6135}
6136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006137static int adev_open(const hw_module_t *module, const char *name,
6138 hw_device_t **device)
6139{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07006140 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006141
Eric Laurent2bafff12016-03-17 12:17:23 -07006142 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006143 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006144 pthread_mutex_lock(&adev_init_lock);
6145 if (audio_device_ref_count != 0) {
6146 *device = &adev->device.common;
6147 audio_device_ref_count++;
6148 ALOGV("%s: returning existing instance of adev", __func__);
6149 ALOGV("%s: exit", __func__);
6150 pthread_mutex_unlock(&adev_init_lock);
6151 return 0;
6152 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006153 adev = calloc(1, sizeof(struct audio_device));
6154
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006155 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6156
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006157 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6158 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6159 adev->device.common.module = (struct hw_module_t *)module;
6160 adev->device.common.close = adev_close;
6161
6162 adev->device.init_check = adev_init_check;
6163 adev->device.set_voice_volume = adev_set_voice_volume;
6164 adev->device.set_master_volume = adev_set_master_volume;
6165 adev->device.get_master_volume = adev_get_master_volume;
6166 adev->device.set_master_mute = adev_set_master_mute;
6167 adev->device.get_master_mute = adev_get_master_mute;
6168 adev->device.set_mode = adev_set_mode;
6169 adev->device.set_mic_mute = adev_set_mic_mute;
6170 adev->device.get_mic_mute = adev_get_mic_mute;
6171 adev->device.set_parameters = adev_set_parameters;
6172 adev->device.get_parameters = adev_get_parameters;
6173 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6174 adev->device.open_output_stream = adev_open_output_stream;
6175 adev->device.close_output_stream = adev_close_output_stream;
6176 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006178 adev->device.close_input_stream = adev_close_input_stream;
6179 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07006180 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006181
6182 /* Set the default route before the PCM stream is opened */
6183 pthread_mutex_lock(&adev->lock);
6184 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006185 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006186 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006187 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006188 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006189 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006190 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006191 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006192 pthread_mutex_unlock(&adev->lock);
6193
6194 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006195 adev->platform = platform_init(adev);
6196 if (!adev->platform) {
6197 free(adev->snd_dev_ref_cnt);
6198 free(adev);
6199 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6200 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006201 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006202 return -EINVAL;
6203 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05006204 adev->extspk = audio_extn_extspk_init(adev);
6205
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006206 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6207 if (adev->visualizer_lib == NULL) {
6208 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6209 } else {
6210 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6211 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07006212 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006213 "visualizer_hal_start_output");
6214 adev->visualizer_stop_output =
6215 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
6216 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07006217 }
6218
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006219 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6220 if (adev->offload_effects_lib == NULL) {
6221 ALOGW("%s: DLOPEN failed for %s", __func__,
6222 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6223 } else {
6224 ALOGV("%s: DLOPEN successful for %s", __func__,
6225 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6226 adev->offload_effects_start_output =
6227 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6228 "offload_effects_bundle_hal_start_output");
6229 adev->offload_effects_stop_output =
6230 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6231 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07006232 }
6233
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006234 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6235 if (adev->adm_lib == NULL) {
6236 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6237 } else {
6238 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6239 adev->adm_init = (adm_init_t)
6240 dlsym(adev->adm_lib, "adm_init");
6241 adev->adm_deinit = (adm_deinit_t)
6242 dlsym(adev->adm_lib, "adm_deinit");
6243 adev->adm_register_input_stream = (adm_register_input_stream_t)
6244 dlsym(adev->adm_lib, "adm_register_input_stream");
6245 adev->adm_register_output_stream = (adm_register_output_stream_t)
6246 dlsym(adev->adm_lib, "adm_register_output_stream");
6247 adev->adm_deregister_stream = (adm_deregister_stream_t)
6248 dlsym(adev->adm_lib, "adm_deregister_stream");
6249 adev->adm_request_focus = (adm_request_focus_t)
6250 dlsym(adev->adm_lib, "adm_request_focus");
6251 adev->adm_abandon_focus = (adm_abandon_focus_t)
6252 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08006253 adev->adm_set_config = (adm_set_config_t)
6254 dlsym(adev->adm_lib, "adm_set_config");
6255 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6256 dlsym(adev->adm_lib, "adm_request_focus_v2");
6257 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6258 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6259 adev->adm_on_routing_change = (adm_on_routing_change_t)
6260 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006261 }
6262
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006263 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05006264 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006265
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006266 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006267
Andy Hung31aca912014-03-20 17:14:59 -07006268 if (k_enable_extended_precision)
6269 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006270
Glenn Kasten4f993392014-05-14 07:30:48 -07006271 char value[PROPERTY_VALUE_MAX];
6272 int trial;
6273 if (property_get("audio_hal.period_size", value, NULL) > 0) {
6274 trial = atoi(value);
6275 if (period_size_is_plausible_for_low_latency(trial)) {
6276 pcm_config_low_latency.period_size = trial;
6277 pcm_config_low_latency.start_threshold = trial / 4;
6278 pcm_config_low_latency.avail_min = trial / 4;
6279 configured_low_latency_capture_period_size = trial;
6280 }
6281 }
6282 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
6283 trial = atoi(value);
6284 if (period_size_is_plausible_for_low_latency(trial)) {
6285 configured_low_latency_capture_period_size = trial;
6286 }
6287 }
6288
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07006289 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
6290
Eric Laurent5f4ca952018-10-19 17:33:43 -07006291 adev->camera_orientation = CAMERA_DEFAULT;
6292
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006293 // commented as full set of app type cfg is sent from platform
6294 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006295 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08006296
6297 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
6298 af_period_multiplier = atoi(value);
6299 if (af_period_multiplier < 0) {
6300 af_period_multiplier = 2;
6301 } else if (af_period_multiplier > 4) {
6302 af_period_multiplier = 4;
6303 }
6304 ALOGV("new period_multiplier = %d", af_period_multiplier);
6305 }
6306
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006307 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08006308 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006309
vivek mehta1a9b7c02015-06-25 11:49:38 -07006310 pthread_mutex_unlock(&adev_init_lock);
6311
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006312 if (adev->adm_init)
6313 adev->adm_data = adev->adm_init();
6314
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006315 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006316 audio_extn_snd_mon_init();
6317 pthread_mutex_lock(&adev->lock);
6318 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
6319 adev->card_status = CARD_STATUS_ONLINE;
6320 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006321 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006322
Eric Laurent2bafff12016-03-17 12:17:23 -07006323 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006324 return 0;
6325}
6326
6327static struct hw_module_methods_t hal_module_methods = {
6328 .open = adev_open,
6329};
6330
6331struct audio_module HAL_MODULE_INFO_SYM = {
6332 .common = {
6333 .tag = HARDWARE_MODULE_TAG,
6334 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6335 .hal_api_version = HARDWARE_HAL_API_VERSION,
6336 .id = AUDIO_HARDWARE_MODULE_ID,
6337 .name = "QCOM Audio HAL",
6338 .author = "Code Aurora Forum",
6339 .methods = &hal_module_methods,
6340 },
6341};