blob: 01ec9988f822e3d53b5669c98a673cbdec21cb2b [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
Phil Burkc4714fc2019-02-16 22:28:11 -08004430// Read offset for the input positional timestamp from a property.
4431// This is to workaround apparent inaccuracies in the timing info that
4432// are causing glitches.
4433static int64_t in_get_mmap_time_offset() {
4434 // Roughly 100 usec is needed on some devices to cover inaccuracy in DSP.
4435 // This should be set in a property. But I cannot read the property!
4436 // So I am setting the offset here to 101 as a test.
4437 const int32_t kDefaultOffsetMicros = 101; // should be zero if no bug
4438 // FIXME - why is the property not being read?! The default is used.
4439 int32_t mmap_time_offset_micros = property_get_int32(
4440 "persist.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
4441 ALOGI("in_get_mmap_time_offset set to %d micros", mmap_time_offset_micros);
4442 return mmap_time_offset_micros * (int64_t)1000;
4443}
4444
Eric Laurent0e46adf2016-12-16 12:49:24 -08004445static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4446 int32_t min_size_frames,
4447 struct audio_mmap_buffer_info *info)
4448{
4449 struct stream_in *in = (struct stream_in *)stream;
4450 struct audio_device *adev = in->dev;
4451 int ret = 0;
4452 unsigned int offset1;
4453 unsigned int frames1;
4454 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004455 uint32_t mmap_size;
4456 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004457
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004458 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004459 pthread_mutex_lock(&adev->lock);
4460 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004461
Eric Laurent0e46adf2016-12-16 12:49:24 -08004462 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004463 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004464 ret = -EINVAL;
4465 goto exit;
4466 }
4467 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004468 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004469 ALOGV("%s in %p", __func__, in);
4470 ret = -ENOSYS;
4471 goto exit;
4472 }
4473 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4474 if (in->pcm_device_id < 0) {
4475 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4476 __func__, in->pcm_device_id, in->usecase);
4477 ret = -EINVAL;
4478 goto exit;
4479 }
Phil Burkbc991042017-02-24 08:06:44 -08004480
4481 adjust_mmap_period_count(&in->config, min_size_frames);
4482
Eric Laurent0e46adf2016-12-16 12:49:24 -08004483 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4484 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4485 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4486 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4487 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4488 step = "open";
4489 ret = -ENODEV;
4490 goto exit;
4491 }
4492
4493 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4494 if (ret < 0) {
4495 step = "begin";
4496 goto exit;
4497 }
4498 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004499 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004500 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004501 ret = platform_get_mmap_data_fd(adev->platform,
4502 in->pcm_device_id, 1 /*capture*/,
4503 &info->shared_memory_fd,
4504 &mmap_size);
4505 if (ret < 0) {
4506 // Fall back to non exclusive mode
4507 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4508 } else {
4509 if (mmap_size < buffer_size) {
4510 step = "mmap";
4511 goto exit;
4512 }
4513 // FIXME: indicate exclusive mode support by returning a negative buffer size
4514 info->buffer_size_frames *= -1;
4515 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004516
Haynes Mathew George96483a22017-03-28 14:52:47 -07004517 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004518
4519 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4520 if (ret < 0) {
4521 step = "commit";
4522 goto exit;
4523 }
4524
Phil Burkc4714fc2019-02-16 22:28:11 -08004525 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
4526
Phil Burkbc991042017-02-24 08:06:44 -08004527 in->standby = false;
4528 ret = 0;
4529
Eric Laurent0e46adf2016-12-16 12:49:24 -08004530 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4531 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004532
4533exit:
4534 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004535 if (in->pcm == NULL) {
4536 ALOGE("%s: %s - %d", __func__, step, ret);
4537 } else {
4538 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004539 pcm_close(in->pcm);
4540 in->pcm = NULL;
4541 }
4542 }
4543 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004544 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004545 return ret;
4546}
4547
4548static int in_get_mmap_position(const struct audio_stream_in *stream,
4549 struct audio_mmap_position *position)
4550{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004551 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004552 struct stream_in *in = (struct stream_in *)stream;
4553 ALOGVV("%s", __func__);
4554 if (position == NULL) {
4555 return -EINVAL;
4556 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004557 lock_input_stream(in);
4558 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4559 in->pcm == NULL) {
4560 ret = -ENOSYS;
4561 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004562 }
4563 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004564 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004565 if (ret < 0) {
4566 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004567 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004568 }
Andy Hungfc044e12017-03-20 09:24:22 -07004569 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Phil Burkc4714fc2019-02-16 22:28:11 -08004570 position->time_nanoseconds += in->mmap_time_offset_nanos;
4571
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004572exit:
4573 pthread_mutex_unlock(&in->lock);
4574 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004575}
4576
jiabin8962a4d2018-03-19 18:21:24 -07004577static int in_get_active_microphones(const struct audio_stream_in *stream,
4578 struct audio_microphone_characteristic_t *mic_array,
4579 size_t *mic_count) {
4580 struct stream_in *in = (struct stream_in *)stream;
4581 struct audio_device *adev = in->dev;
4582 ALOGVV("%s", __func__);
4583
4584 lock_input_stream(in);
4585 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004586 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004587 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004588 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004589 pthread_mutex_unlock(&adev->lock);
4590 pthread_mutex_unlock(&in->lock);
4591
4592 return ret;
4593}
4594
4595static int adev_get_microphones(const struct audio_hw_device *dev,
4596 struct audio_microphone_characteristic_t *mic_array,
4597 size_t *mic_count) {
4598 struct audio_device *adev = (struct audio_device *)dev;
4599 ALOGVV("%s", __func__);
4600
4601 pthread_mutex_lock(&adev->lock);
4602 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4603 pthread_mutex_unlock(&adev->lock);
4604
4605 return ret;
4606}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004607
Paul McLean57530d52018-12-17 08:24:21 -07004608static int in_set_microphone_direction(const struct audio_stream_in *stream,
4609 audio_microphone_direction_t dir) {
4610 (void)stream;
4611 (void)dir;
4612 ALOGVV("%s", __func__);
4613 return -ENOSYS;
4614}
4615
4616static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
4617 (void)stream;
4618 (void)zoom;
4619 ALOGVV("%s", __func__);
4620 return -ENOSYS;
4621}
4622
juyuchenba338cd2019-01-21 11:57:17 +08004623static void in_update_sink_metadata(struct audio_stream_in *stream,
4624 const struct sink_metadata *sink_metadata) {
4625
4626 if (stream == NULL
4627 || sink_metadata == NULL
4628 || sink_metadata->tracks == NULL) {
4629 return;
4630 }
4631
4632 int error = 0;
4633 struct stream_in *in = (struct stream_in *)stream;
4634 struct audio_device *adev = in->dev;
4635 audio_devices_t device = AUDIO_DEVICE_NONE;
4636
4637 if (sink_metadata->track_count != 0)
4638 device = sink_metadata->tracks->dest_device;
4639
4640 lock_input_stream(in);
4641 pthread_mutex_lock(&adev->lock);
4642 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
4643
4644 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
4645 && device != AUDIO_DEVICE_NONE
4646 && adev->voice_tx_output != NULL) {
4647 /* Use the rx device from afe-proxy record to route voice call because
4648 there is no routing if tx device is on primary hal and rx device
4649 is on other hal during voice call. */
4650 adev->voice_tx_output->devices = device;
4651
4652 if (!voice_is_call_state_active(adev)) {
4653 if (adev->mode == AUDIO_MODE_IN_CALL) {
4654 adev->current_call_output = adev->voice_tx_output;
4655 error = voice_start_call(adev);
4656 if (error != 0)
4657 ALOGE("%s: start voice call failed %d", __func__, error);
4658 }
4659 } else {
4660 adev->current_call_output = adev->voice_tx_output;
4661 voice_update_devices_for_all_voice_usecases(adev);
4662 }
4663 }
4664
4665 pthread_mutex_unlock(&adev->lock);
4666 pthread_mutex_unlock(&in->lock);
4667}
4668
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004669static int adev_open_output_stream(struct audio_hw_device *dev,
4670 audio_io_handle_t handle,
4671 audio_devices_t devices,
4672 audio_output_flags_t flags,
4673 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004674 struct audio_stream_out **stream_out,
4675 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004676{
4677 struct audio_device *adev = (struct audio_device *)dev;
4678 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004679 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004680 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4681 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4682 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004683 bool force_haptic_path =
4684 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004685
Andy Hungd9653bd2017-08-01 19:31:39 -07004686 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4687 return -ENOSYS;
4688 }
4689
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004690 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4691 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693 *stream_out = NULL;
4694 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4695
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004696 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4697
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004698 if (devices == AUDIO_DEVICE_NONE)
4699 devices = AUDIO_DEVICE_OUT_SPEAKER;
4700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004701 out->flags = flags;
4702 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004703 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004704 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004705 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004706
4707 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004708 if ((is_hdmi || is_usb_dev) &&
4709 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4710 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4711 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004712 audio_format_t req_format = config->format;
4713 audio_channel_mask_t req_channel_mask = config->channel_mask;
4714 uint32_t req_sample_rate = config->sample_rate;
4715
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004716 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004717 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004718 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004719 if (config->sample_rate == 0)
4720 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004721 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004722 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4723 if (config->format == AUDIO_FORMAT_DEFAULT)
4724 config->format = AUDIO_FORMAT_PCM_16_BIT;
4725 } else if (is_usb_dev) {
4726 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4727 &config->format,
4728 &out->supported_formats[0],
4729 MAX_SUPPORTED_FORMATS,
4730 &config->channel_mask,
4731 &out->supported_channel_masks[0],
4732 MAX_SUPPORTED_CHANNEL_MASKS,
4733 &config->sample_rate,
4734 &out->supported_sample_rates[0],
4735 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004736 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004737 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004738 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004739 if (ret != 0) {
4740 // For MMAP NO IRQ, allow conversions in ADSP
4741 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4742 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004743
Eric Laurentab805ee2018-03-30 12:20:38 -07004744 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4745 config->sample_rate = req_sample_rate;
4746 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4747 config->channel_mask = req_channel_mask;
4748 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4749 config->format = req_format;
4750 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004751
Haynes Mathew George569b7482017-05-08 14:44:27 -07004752 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004753 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004754 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004755 if (is_hdmi) {
4756 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4757 out->config = pcm_config_hdmi_multi;
4758 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4759 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4760 out->config = pcm_config_mmap_playback;
4761 out->stream.start = out_start;
4762 out->stream.stop = out_stop;
4763 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4764 out->stream.get_mmap_position = out_get_mmap_position;
4765 } else {
4766 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4767 out->config = pcm_config_hifi;
4768 }
4769
4770 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004771 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004772 if (is_hdmi) {
4773 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4774 audio_bytes_per_sample(out->format));
4775 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004776 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004777 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004778 pthread_mutex_lock(&adev->lock);
4779 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4780 pthread_mutex_unlock(&adev->lock);
4781
4782 // reject offload during card offline to allow
4783 // fallback to s/w paths
4784 if (offline) {
4785 ret = -ENODEV;
4786 goto error_open;
4787 }
4788
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004789 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4790 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4791 ALOGE("%s: Unsupported Offload information", __func__);
4792 ret = -EINVAL;
4793 goto error_open;
4794 }
4795 if (!is_supported_format(config->offload_info.format)) {
4796 ALOGE("%s: Unsupported audio format", __func__);
4797 ret = -EINVAL;
4798 goto error_open;
4799 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004800 out->sample_rate = config->offload_info.sample_rate;
4801 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4802 out->channel_mask = config->offload_info.channel_mask;
4803 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4804 out->channel_mask = config->channel_mask;
4805 else
4806 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4807
4808 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004809
4810 out->compr_config.codec = (struct snd_codec *)
4811 calloc(1, sizeof(struct snd_codec));
4812
4813 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004814
4815 out->stream.set_callback = out_set_callback;
4816 out->stream.pause = out_pause;
4817 out->stream.resume = out_resume;
4818 out->stream.drain = out_drain;
4819 out->stream.flush = out_flush;
4820
4821 out->compr_config.codec->id =
4822 get_snd_codec_id(config->offload_info.format);
4823 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4824 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004825 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004826 out->compr_config.codec->bit_rate =
4827 config->offload_info.bit_rate;
4828 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004829 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004830 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4831
4832 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4833 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004834
4835 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004836 create_offload_callback_thread(out);
4837 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4838 __func__, config->offload_info.version,
4839 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004840 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4841 switch (config->sample_rate) {
4842 case 0:
4843 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4844 break;
4845 case 8000:
4846 case 16000:
4847 case 48000:
4848 out->sample_rate = config->sample_rate;
4849 break;
4850 default:
4851 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4852 config->sample_rate);
4853 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4854 ret = -EINVAL;
4855 goto error_open;
4856 }
4857 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4858 switch (config->channel_mask) {
4859 case AUDIO_CHANNEL_NONE:
4860 case AUDIO_CHANNEL_OUT_STEREO:
4861 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4862 break;
4863 default:
4864 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4865 config->channel_mask);
4866 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4867 ret = -EINVAL;
4868 goto error_open;
4869 }
4870 switch (config->format) {
4871 case AUDIO_FORMAT_DEFAULT:
4872 case AUDIO_FORMAT_PCM_16_BIT:
4873 out->format = AUDIO_FORMAT_PCM_16_BIT;
4874 break;
4875 default:
4876 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4877 config->format);
4878 config->format = AUDIO_FORMAT_PCM_16_BIT;
4879 ret = -EINVAL;
4880 goto error_open;
4881 }
4882
4883 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004884 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004885 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004886 case 0:
4887 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4888 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004889 case 8000:
4890 case 16000:
4891 case 48000:
4892 out->sample_rate = config->sample_rate;
4893 break;
4894 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004895 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4896 config->sample_rate);
4897 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4898 ret = -EINVAL;
4899 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004900 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004901 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4902 switch (config->channel_mask) {
4903 case AUDIO_CHANNEL_NONE:
4904 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4905 break;
4906 case AUDIO_CHANNEL_OUT_STEREO:
4907 out->channel_mask = config->channel_mask;
4908 break;
4909 default:
4910 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4911 config->channel_mask);
4912 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4913 ret = -EINVAL;
4914 break;
4915 }
4916 switch (config->format) {
4917 case AUDIO_FORMAT_DEFAULT:
4918 out->format = AUDIO_FORMAT_PCM_16_BIT;
4919 break;
4920 case AUDIO_FORMAT_PCM_16_BIT:
4921 out->format = config->format;
4922 break;
4923 default:
4924 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4925 config->format);
4926 config->format = AUDIO_FORMAT_PCM_16_BIT;
4927 ret = -EINVAL;
4928 break;
4929 }
4930 if (ret != 0)
4931 goto error_open;
4932
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004933 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4934 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004935 out->config.rate = out->sample_rate;
4936 out->config.channels =
4937 audio_channel_count_from_out_mask(out->channel_mask);
4938 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004939 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004940 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4941 switch (config->sample_rate) {
4942 case 0:
4943 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4944 break;
4945 case 8000:
4946 case 16000:
4947 case 32000:
4948 case 48000:
4949 out->sample_rate = config->sample_rate;
4950 break;
4951 default:
4952 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4953 config->sample_rate);
4954 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4955 ret = -EINVAL;
4956 break;
4957 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004958 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004959 switch (config->channel_mask) {
4960 case AUDIO_CHANNEL_NONE:
4961 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4962 break;
4963 case AUDIO_CHANNEL_OUT_STEREO:
4964 out->channel_mask = config->channel_mask;
4965 break;
4966 default:
4967 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4968 config->channel_mask);
4969 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4970 ret = -EINVAL;
4971 break;
4972 }
4973 switch (config->format) {
4974 case AUDIO_FORMAT_DEFAULT:
4975 out->format = AUDIO_FORMAT_PCM_16_BIT;
4976 break;
4977 case AUDIO_FORMAT_PCM_16_BIT:
4978 out->format = config->format;
4979 break;
4980 default:
4981 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4982 config->format);
4983 config->format = AUDIO_FORMAT_PCM_16_BIT;
4984 ret = -EINVAL;
4985 break;
4986 }
4987 if (ret != 0)
4988 goto error_open;
4989
vivek mehtaa68fea62017-06-08 19:04:02 -07004990 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004991 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4992 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004993 out->config.rate = out->sample_rate;
4994 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004995 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004996 out->sample_rate,
4997 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004998 out->config.channels,
4999 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005000 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07005001 out->config.period_size = buffer_size / frame_size;
5002 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
5003 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005004 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005005 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07005006 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5007 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005008 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07005009 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
5010 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005011 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07005012 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005013 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005014 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005015 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08005016 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5017 out->config = pcm_config_mmap_playback;
5018 out->stream.start = out_start;
5019 out->stream.stop = out_stop;
5020 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5021 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005022 } else {
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005023 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5024 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
5025 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
5026 if (adev->haptic_pcm_device_id < 0) {
5027 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
5028 __func__, adev->haptic_pcm_device_id, out->usecase);
5029 ret = -ENOSYS;
5030 goto error_open;
5031 }
5032 out->config = pcm_config_haptics_audio;
5033 if (force_haptic_path)
5034 adev->haptics_config = pcm_config_haptics_audio;
5035 else
5036 adev->haptics_config = pcm_config_haptics;
5037 } else {
5038 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
5039 out->config = pcm_config_low_latency;
5040 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07005041 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005042
5043 if (config->sample_rate == 0) {
5044 out->sample_rate = out->config.rate;
5045 } else {
5046 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005047 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005048
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005049 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
5050 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
5051 } else {
5052 out->channel_mask = config->channel_mask;
5053 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005054
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005055 if (config->format == AUDIO_FORMAT_DEFAULT)
5056 out->format = audio_format_from_pcm_format(out->config.format);
5057 else if (!audio_is_linear_pcm(config->format)) {
5058 config->format = AUDIO_FORMAT_PCM_16_BIT;
5059 ret = -EINVAL;
5060 goto error_open;
5061 } else {
5062 out->format = config->format;
5063 }
5064
5065 out->config.rate = out->sample_rate;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005066
5067 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5068 out->config.channels =
5069 audio_channel_count_from_out_mask(out->channel_mask &
5070 ~AUDIO_CHANNEL_HAPTIC_ALL);
5071
5072 if (force_haptic_path) {
5073 out->config.channels = 1;
5074 adev->haptics_config.channels = 1;
5075 } else {
5076 adev->haptics_config.channels =
5077 audio_channel_count_from_out_mask(out->channel_mask &
5078 AUDIO_CHANNEL_HAPTIC_ALL);
5079 }
5080 } else {
5081 out->config.channels =
5082 audio_channel_count_from_out_mask(out->channel_mask);
5083 }
5084
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005085 if (out->format != audio_format_from_pcm_format(out->config.format)) {
5086 out->config.format = pcm_format_from_audio_format(out->format);
5087 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005088 }
Kevin Rocard50eff892017-05-02 16:52:05 -07005089
5090 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
5091 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005092 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07005093 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
5094 __func__, config->sample_rate, config->format, config->channel_mask);
5095 config->sample_rate = out->sample_rate;
5096 config->format = out->format;
5097 config->channel_mask = out->channel_mask;
5098 ret = -EINVAL;
5099 goto error_open;
5100 }
5101
Andy Hung6fcba9c2014-03-18 11:53:32 -07005102 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
5103 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005104
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005105 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005106 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005107 adev->primary_output = out;
5108 else {
5109 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005110 ret = -EEXIST;
5111 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005112 }
5113 }
5114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005115 /* Check if this usecase is already existing */
5116 pthread_mutex_lock(&adev->lock);
5117 if (get_usecase_from_list(adev, out->usecase) != NULL) {
5118 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005119 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005120 ret = -EEXIST;
5121 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005122 }
5123 pthread_mutex_unlock(&adev->lock);
5124
5125 out->stream.common.get_sample_rate = out_get_sample_rate;
5126 out->stream.common.set_sample_rate = out_set_sample_rate;
5127 out->stream.common.get_buffer_size = out_get_buffer_size;
5128 out->stream.common.get_channels = out_get_channels;
5129 out->stream.common.get_format = out_get_format;
5130 out->stream.common.set_format = out_set_format;
5131 out->stream.common.standby = out_standby;
5132 out->stream.common.dump = out_dump;
5133 out->stream.common.set_parameters = out_set_parameters;
5134 out->stream.common.get_parameters = out_get_parameters;
5135 out->stream.common.add_audio_effect = out_add_audio_effect;
5136 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5137 out->stream.get_latency = out_get_latency;
5138 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005139#ifdef NO_AUDIO_OUT
5140 out->stream.write = out_write_for_no_output;
5141#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005142 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005143#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005144 out->stream.get_render_position = out_get_render_position;
5145 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005146 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005147
Eric Laurent0e46adf2016-12-16 12:49:24 -08005148 if (out->realtime)
5149 out->af_period_multiplier = af_period_multiplier;
5150 else
5151 out->af_period_multiplier = 1;
5152
Andy Hung572633e2019-02-19 11:58:24 -08005153 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
5154
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005155 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005156 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005157 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005158
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005159 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005160 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005161 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005163 config->format = out->stream.common.get_format(&out->stream.common);
5164 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5165 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5166
Kevin Rocarda325aa22018-04-03 09:15:52 -07005167 register_format(out->format, out->supported_formats);
5168 register_channel_mask(out->channel_mask, out->supported_channel_masks);
5169 register_sample_rate(out->sample_rate, out->supported_sample_rates);
5170
Andy Hunga452b0a2017-03-15 14:51:15 -07005171 out->error_log = error_log_create(
5172 ERROR_LOG_ENTRIES,
5173 1000000000 /* aggregate consecutive identical errors within one second in ns */);
5174
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005175 /*
5176 By locking output stream before registering, we allow the callback
5177 to update stream's state only after stream's initial state is set to
5178 adev state.
5179 */
5180 lock_output_stream(out);
5181 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5182 pthread_mutex_lock(&adev->lock);
5183 out->card_status = adev->card_status;
5184 pthread_mutex_unlock(&adev->lock);
5185 pthread_mutex_unlock(&out->lock);
5186
vivek mehta4a824772017-06-08 19:05:49 -07005187 stream_app_type_cfg_init(&out->app_type_cfg);
5188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005189 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005190
Eric Laurent994a6932013-07-17 11:51:42 -07005191 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005192 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005193
5194error_open:
5195 free(out);
5196 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07005197 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005198 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005199}
5200
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005201static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005202 struct audio_stream_out *stream)
5203{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005204 struct stream_out *out = (struct stream_out *)stream;
5205 struct audio_device *adev = out->dev;
5206
Eric Laurent994a6932013-07-17 11:51:42 -07005207 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005208
5209 // must deregister from sndmonitor first to prevent races
5210 // between the callback and close_stream
5211 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005212 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005213 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
5214 destroy_offload_callback_thread(out);
5215
5216 if (out->compr_config.codec != NULL)
5217 free(out->compr_config.codec);
5218 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005219
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005220 out->a2dp_compress_mute = false;
5221
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005222 if (adev->voice_tx_output == out)
5223 adev->voice_tx_output = NULL;
5224
Andy Hunga452b0a2017-03-15 14:51:15 -07005225 error_log_destroy(out->error_log);
5226 out->error_log = NULL;
5227
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005228 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005229 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005230 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005231 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005232 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005233}
5234
5235static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5236{
5237 struct audio_device *adev = (struct audio_device *)dev;
5238 struct str_parms *parms;
5239 char *str;
5240 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005241 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005242 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07005243 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005244 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005245
Joe Onorato188b6222016-03-01 11:02:27 -08005246 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005247
5248 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005249
5250 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005251 status = voice_set_parameters(adev, parms);
5252 if (status != 0) {
5253 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005254 }
5255
5256 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5257 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07005258 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005259 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5260 adev->bluetooth_nrec = true;
5261 else
5262 adev->bluetooth_nrec = false;
5263 }
5264
5265 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5266 if (ret >= 0) {
5267 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5268 adev->screen_off = false;
5269 else
5270 adev->screen_off = true;
5271 }
5272
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005273 ret = str_parms_get_int(parms, "rotation", &val);
5274 if (ret >= 0) {
5275 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005276 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005277 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005278 // FIXME: note that the code below assumes that the speakers are in the correct placement
5279 // relative to the user when the device is rotated 90deg from its default rotation. This
5280 // assumption is device-specific, not platform-specific like this code.
5281 case 270:
5282 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005283 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005284 break;
5285 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005286 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07005287 camera_rotation = CAMERA_ROTATION_PORTRAIT;
5288 break;
5289 case 90:
5290 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005291 break;
5292 default:
5293 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07005294 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005295 }
Eric Laurent03f09432014-03-25 18:09:11 -07005296 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07005297 // check and set swap
5298 // - check if orientation changed and speaker active
5299 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07005300 adev->camera_orientation =
5301 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
5302#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07005303 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07005304#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005305 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005306 }
5307
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005308 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5309 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005310 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005311 }
5312
David Linee3fe402017-03-13 10:00:42 -07005313 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5314 if (ret >= 0) {
5315 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005316 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005317 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5318 if (ret >= 0) {
5319 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005320 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005321 }
Eric Laurent99dab492017-06-17 15:19:08 -07005322 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005323 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5324 if (ret >= 0) {
5325 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005326 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005327 }
5328 }
5329 }
5330
5331 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5332 if (ret >= 0) {
5333 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005334 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005335 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5336 if (ret >= 0) {
5337 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005338 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005339 }
Eric Laurent99dab492017-06-17 15:19:08 -07005340 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005341 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5342 if (ret >= 0) {
5343 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005344 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005345 }
5346 }
5347 }
5348
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08005349 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08005350 audio_extn_ma_set_parameters(adev, parms);
5351
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005352 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
5353 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005354 struct audio_usecase *usecase;
5355 struct listnode *node;
5356 list_for_each(node, &adev->usecase_list) {
5357 usecase = node_to_item(node, struct audio_usecase, list);
5358 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005359 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005360 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
5361
5362 pthread_mutex_unlock(&adev->lock);
5363 lock_output_stream(usecase->stream.out);
5364 pthread_mutex_lock(&adev->lock);
5365 audio_extn_a2dp_set_handoff_mode(true);
5366 // force device switch to reconfigure encoder
5367 select_devices(adev, usecase->id);
5368 audio_extn_a2dp_set_handoff_mode(false);
5369 pthread_mutex_unlock(&usecase->stream.out->lock);
5370 break;
5371 }
5372 }
5373 }
5374
Eric Laurent5f4ca952018-10-19 17:33:43 -07005375 //FIXME: to be replaced by proper video capture properties API
5376 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
5377 if (ret >= 0) {
5378 int camera_facing = CAMERA_FACING_BACK;
5379 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
5380 camera_facing = CAMERA_FACING_FRONT;
5381 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
5382 camera_facing = CAMERA_FACING_BACK;
5383 else {
5384 ALOGW("%s: invalid camera facing value: %s", __func__, value);
5385 goto done;
5386 }
5387 adev->camera_orientation =
5388 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
5389 struct audio_usecase *usecase;
5390 struct listnode *node;
5391 list_for_each(node, &adev->usecase_list) {
5392 usecase = node_to_item(node, struct audio_usecase, list);
5393 struct stream_in *in = usecase->stream.in;
5394 if (usecase->type == PCM_CAPTURE && in != NULL &&
5395 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
5396 select_devices(adev, in->usecase);
5397 }
5398 }
5399 }
5400
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005401done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005402 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005403 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07005404 ALOGV("%s: exit with code(%d)", __func__, status);
5405 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005406}
5407
5408static char* adev_get_parameters(const struct audio_hw_device *dev,
5409 const char *keys)
5410{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005411 struct audio_device *adev = (struct audio_device *)dev;
5412 struct str_parms *reply = str_parms_create();
5413 struct str_parms *query = str_parms_create_str(keys);
5414 char *str;
5415
5416 pthread_mutex_lock(&adev->lock);
5417
5418 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005419 audio_extn_a2dp_get_parameters(query, reply);
5420
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005421 str = str_parms_to_str(reply);
5422 str_parms_destroy(query);
5423 str_parms_destroy(reply);
5424
5425 pthread_mutex_unlock(&adev->lock);
5426 ALOGV("%s: exit: returns - %s", __func__, str);
5427 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005428}
5429
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005430static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005431{
5432 return 0;
5433}
5434
Haynes Mathew George5191a852013-09-11 14:19:36 -07005435static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5436{
5437 int ret;
5438 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005439
Eric Laurent4cc4ce12014-09-10 13:21:01 -05005440 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
5441
Haynes Mathew George5191a852013-09-11 14:19:36 -07005442 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005443 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005444 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005445
Haynes Mathew George5191a852013-09-11 14:19:36 -07005446 return ret;
5447}
5448
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005449static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005450{
5451 return -ENOSYS;
5452}
5453
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005454static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5455 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005456{
5457 return -ENOSYS;
5458}
5459
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005460static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005461{
5462 return -ENOSYS;
5463}
5464
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005465static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005466{
5467 return -ENOSYS;
5468}
5469
5470static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5471{
5472 struct audio_device *adev = (struct audio_device *)dev;
5473
5474 pthread_mutex_lock(&adev->lock);
5475 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07005476 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005477 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005478 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
5479 voice_is_in_call(adev)) {
5480 voice_stop_call(adev);
5481 adev->current_call_output = NULL;
5482 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005483 }
5484 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05005485
5486 audio_extn_extspk_set_mode(adev->extspk, mode);
5487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005488 return 0;
5489}
5490
5491static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5492{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005493 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005494 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005495
Eric Laurent2bafff12016-03-17 12:17:23 -07005496 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005497 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005498 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
5499 ret = audio_extn_hfp_set_mic_mute(adev, state);
5500 } else {
5501 ret = voice_set_mic_mute(adev, state);
5502 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005503 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005504 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005505
5506 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005507}
5508
5509static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5510{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005511 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005512 return 0;
5513}
5514
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005515static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005516 const struct audio_config *config)
5517{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005518 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005519
Eric Laurent74b55762017-07-09 17:04:53 -07005520 /* Don't know if USB HIFI in this context so use true to be conservative */
5521 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5522 true /*is_usb_hifi */) != 0)
5523 return 0;
5524
vivek mehtaa68fea62017-06-08 19:04:02 -07005525 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5526 config->sample_rate, config->format,
5527 channel_count,
5528 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005529}
5530
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005531static bool adev_input_allow_hifi_record(struct audio_device *adev,
5532 audio_devices_t devices,
5533 audio_input_flags_t flags,
5534 audio_source_t source) {
5535 const bool allowed = true;
5536
5537 if (!audio_is_usb_in_device(devices))
5538 return !allowed;
5539
5540 switch (flags) {
5541 case AUDIO_INPUT_FLAG_NONE:
5542 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5543 break;
5544 default:
5545 return !allowed;
5546 }
5547
5548 switch (source) {
5549 case AUDIO_SOURCE_DEFAULT:
5550 case AUDIO_SOURCE_MIC:
5551 case AUDIO_SOURCE_UNPROCESSED:
5552 break;
5553 default:
5554 return !allowed;
5555 }
5556
5557 switch (adev->mode) {
5558 case 0:
5559 break;
5560 default:
5561 return !allowed;
5562 }
5563
5564 return allowed;
5565}
5566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005567static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005568 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005569 audio_devices_t devices,
5570 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005571 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005572 audio_input_flags_t flags,
5573 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005574 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005575{
5576 struct audio_device *adev = (struct audio_device *)dev;
5577 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005578 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005579 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005580 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005581 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005582 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5583 devices,
5584 flags,
5585 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005586 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5587 " sample_rate %u, channel_mask %#x, format %#x",
5588 __func__, flags, is_usb_dev, may_use_hifi_record,
5589 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005590 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005591
Andy Hungd9653bd2017-08-01 19:31:39 -07005592 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5593 return -ENOSYS;
5594 }
5595
Eric Laurent74b55762017-07-09 17:04:53 -07005596 if (!(is_usb_dev && may_use_hifi_record)) {
5597 if (config->sample_rate == 0)
5598 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5599 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5600 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5601 if (config->format == AUDIO_FORMAT_DEFAULT)
5602 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005603
Eric Laurent74b55762017-07-09 17:04:53 -07005604 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5605
5606 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5607 return -EINVAL;
5608 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005609
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005610 if (audio_extn_tfa_98xx_is_supported() &&
5611 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005612 return -EINVAL;
5613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005614 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5615
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005616 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005617 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005618
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005619 in->stream.common.get_sample_rate = in_get_sample_rate;
5620 in->stream.common.set_sample_rate = in_set_sample_rate;
5621 in->stream.common.get_buffer_size = in_get_buffer_size;
5622 in->stream.common.get_channels = in_get_channels;
5623 in->stream.common.get_format = in_get_format;
5624 in->stream.common.set_format = in_set_format;
5625 in->stream.common.standby = in_standby;
5626 in->stream.common.dump = in_dump;
5627 in->stream.common.set_parameters = in_set_parameters;
5628 in->stream.common.get_parameters = in_get_parameters;
5629 in->stream.common.add_audio_effect = in_add_audio_effect;
5630 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5631 in->stream.set_gain = in_set_gain;
5632 in->stream.read = in_read;
5633 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005634 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005635 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLean57530d52018-12-17 08:24:21 -07005636 in->stream.set_microphone_direction = in_set_microphone_direction;
5637 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchenba338cd2019-01-21 11:57:17 +08005638 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005639
5640 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005641 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005642 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005643 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005644 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005645 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005646
Andy Hung88ce1d92018-10-29 18:31:12 -07005647 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005648 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5649 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5650 /* Force channel config requested to mono if incall
5651 record is being requested for only uplink/downlink */
5652 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5653 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5654 ret = -EINVAL;
5655 goto err_open;
5656 }
5657 }
5658
Haynes Mathew George569b7482017-05-08 14:44:27 -07005659 if (is_usb_dev && may_use_hifi_record) {
5660 /* HiFi record selects an appropriate format, channel, rate combo
5661 depending on sink capabilities*/
5662 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5663 &config->format,
5664 &in->supported_formats[0],
5665 MAX_SUPPORTED_FORMATS,
5666 &config->channel_mask,
5667 &in->supported_channel_masks[0],
5668 MAX_SUPPORTED_CHANNEL_MASKS,
5669 &config->sample_rate,
5670 &in->supported_sample_rates[0],
5671 MAX_SUPPORTED_SAMPLE_RATES);
5672 if (ret != 0) {
5673 ret = -EINVAL;
5674 goto err_open;
5675 }
Eric Laurent74b55762017-07-09 17:04:53 -07005676 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005677 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005678 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005679 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5680 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5681 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5682 bool ret_error = false;
5683 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5684 from HAL is 8_24
5685 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5686 8_24 return error indicating supported format is 8_24
5687 *> In case of any other source requesting 24 bit or float return error
5688 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005689
vivek mehta57ff9b52016-04-28 14:13:08 -07005690 on error flinger will retry with supported format passed
5691 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005692 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005693 config->format = AUDIO_FORMAT_PCM_16_BIT;
5694 ret_error = true;
5695 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5696 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5697 ret_error = true;
5698 }
5699
5700 if (ret_error) {
5701 ret = -EINVAL;
5702 goto err_open;
5703 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005704 }
5705
vivek mehta57ff9b52016-04-28 14:13:08 -07005706 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005707 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005708
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005709 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005710 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5711 if (config->sample_rate == 0)
5712 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5713 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5714 config->sample_rate != 8000) {
5715 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5716 ret = -EINVAL;
5717 goto err_open;
5718 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005719
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005720 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5721 config->format = AUDIO_FORMAT_PCM_16_BIT;
5722 ret = -EINVAL;
5723 goto err_open;
5724 }
5725
5726 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5727 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005728 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005729 } else if (is_usb_dev && may_use_hifi_record) {
5730 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5731 in->config = pcm_config_audio_capture;
5732 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005733 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5734 config->sample_rate,
5735 config->format,
5736 channel_count,
5737 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005738 in->config.period_size = buffer_size / frame_size;
5739 in->config.rate = config->sample_rate;
5740 in->af_period_multiplier = 1;
5741 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005742 } else {
5743 in->usecase = USECASE_AUDIO_RECORD;
5744 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005745 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005746 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005747#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005748 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005749#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005750 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005751 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005752 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005753 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005754 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5755 config->sample_rate,
5756 config->format,
5757 channel_count,
5758 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005759 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005760 in->config.rate = config->sample_rate;
5761 in->af_period_multiplier = 1;
5762 } else {
5763 // period size is left untouched for rt mode playback
5764 in->config = pcm_config_audio_capture_rt;
5765 in->af_period_multiplier = af_period_multiplier;
5766 }
5767 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5768 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005769 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005770 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5771 in->config = pcm_config_mmap_capture;
5772 in->stream.start = in_start;
5773 in->stream.stop = in_stop;
5774 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5775 in->stream.get_mmap_position = in_get_mmap_position;
5776 in->af_period_multiplier = 1;
5777 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005778 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005779 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005780 (config->sample_rate == 8000 ||
5781 config->sample_rate == 16000 ||
5782 config->sample_rate == 32000 ||
5783 config->sample_rate == 48000) &&
5784 channel_count == 1) {
5785 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5786 in->config = pcm_config_audio_capture;
5787 frame_size = audio_stream_in_frame_size(&in->stream);
5788 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5789 config->sample_rate,
5790 config->format,
5791 channel_count, false /*is_low_latency*/);
5792 in->config.period_size = buffer_size / frame_size;
5793 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5794 in->config.rate = config->sample_rate;
5795 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005796 } else {
5797 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005798 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005799 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5800 config->sample_rate,
5801 config->format,
5802 channel_count,
5803 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005804 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005805 in->config.rate = config->sample_rate;
5806 in->af_period_multiplier = 1;
5807 }
5808 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5809 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005810 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005812 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005813 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005814
Kevin Rocarda325aa22018-04-03 09:15:52 -07005815
5816 register_format(in->format, in->supported_formats);
5817 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5818 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5819
Andy Hungd13f0d32017-06-12 13:58:37 -07005820 in->error_log = error_log_create(
5821 ERROR_LOG_ENTRIES,
5822 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5823
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005824 /* This stream could be for sound trigger lab,
5825 get sound trigger pcm if present */
5826 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005827
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005828 lock_input_stream(in);
5829 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5830 pthread_mutex_lock(&adev->lock);
5831 in->card_status = adev->card_status;
5832 pthread_mutex_unlock(&adev->lock);
5833 pthread_mutex_unlock(&in->lock);
5834
vivek mehta4a824772017-06-08 19:05:49 -07005835 stream_app_type_cfg_init(&in->app_type_cfg);
5836
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005837 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005838 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005839 return 0;
5840
5841err_open:
5842 free(in);
5843 *stream_in = NULL;
5844 return ret;
5845}
5846
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005847static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005848 struct audio_stream_in *stream)
5849{
Andy Hungd13f0d32017-06-12 13:58:37 -07005850 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005851 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005852
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005853 // must deregister from sndmonitor first to prevent races
5854 // between the callback and close_stream
5855 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005856 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005857
5858 error_log_destroy(in->error_log);
5859 in->error_log = NULL;
5860
Andy Hung0dbb52b2017-08-09 13:51:38 -07005861 pthread_mutex_destroy(&in->pre_lock);
5862 pthread_mutex_destroy(&in->lock);
5863
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005864 free(stream);
5865
5866 return;
5867}
5868
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005869static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005870{
5871 return 0;
5872}
5873
Andy Hung31aca912014-03-20 17:14:59 -07005874/* verifies input and output devices and their capabilities.
5875 *
5876 * This verification is required when enabling extended bit-depth or
5877 * sampling rates, as not all qcom products support it.
5878 *
5879 * Suitable for calling only on initialization such as adev_open().
5880 * It fills the audio_device use_case_table[] array.
5881 *
5882 * Has a side-effect that it needs to configure audio routing / devices
5883 * in order to power up the devices and read the device parameters.
5884 * It does not acquire any hw device lock. Should restore the devices
5885 * back to "normal state" upon completion.
5886 */
5887static int adev_verify_devices(struct audio_device *adev)
5888{
5889 /* enumeration is a bit difficult because one really wants to pull
5890 * the use_case, device id, etc from the hidden pcm_device_table[].
5891 * In this case there are the following use cases and device ids.
5892 *
5893 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5894 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005895 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005896 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5897 * [USECASE_AUDIO_RECORD] = {0, 0},
5898 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5899 * [USECASE_VOICE_CALL] = {2, 2},
5900 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005901 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005902 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5903 */
5904
5905 /* should be the usecases enabled in adev_open_input_stream() */
5906 static const int test_in_usecases[] = {
5907 USECASE_AUDIO_RECORD,
5908 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5909 };
5910 /* should be the usecases enabled in adev_open_output_stream()*/
5911 static const int test_out_usecases[] = {
5912 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5913 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5914 };
5915 static const usecase_type_t usecase_type_by_dir[] = {
5916 PCM_PLAYBACK,
5917 PCM_CAPTURE,
5918 };
5919 static const unsigned flags_by_dir[] = {
5920 PCM_OUT,
5921 PCM_IN,
5922 };
5923
5924 size_t i;
5925 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005926 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005927 char info[512]; /* for possible debug info */
5928
5929 for (dir = 0; dir < 2; ++dir) {
5930 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5931 const unsigned flags_dir = flags_by_dir[dir];
5932 const size_t testsize =
5933 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5934 const int *testcases =
5935 dir ? test_in_usecases : test_out_usecases;
5936 const audio_devices_t audio_device =
5937 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5938
5939 for (i = 0; i < testsize; ++i) {
5940 const audio_usecase_t audio_usecase = testcases[i];
5941 int device_id;
5942 snd_device_t snd_device;
5943 struct pcm_params **pparams;
5944 struct stream_out out;
5945 struct stream_in in;
5946 struct audio_usecase uc_info;
5947 int retval;
5948
5949 pparams = &adev->use_case_table[audio_usecase];
5950 pcm_params_free(*pparams); /* can accept null input */
5951 *pparams = NULL;
5952
5953 /* find the device ID for the use case (signed, for error) */
5954 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5955 if (device_id < 0)
5956 continue;
5957
5958 /* prepare structures for device probing */
5959 memset(&uc_info, 0, sizeof(uc_info));
5960 uc_info.id = audio_usecase;
5961 uc_info.type = usecase_type;
5962 if (dir) {
Andy Hung31aca912014-03-20 17:14:59 -07005963 memset(&in, 0, sizeof(in));
5964 in.device = audio_device;
5965 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5966 uc_info.stream.in = &in;
Andy Hung31aca912014-03-20 17:14:59 -07005967 }
5968 memset(&out, 0, sizeof(out));
5969 out.devices = audio_device; /* only field needed in select_devices */
5970 uc_info.stream.out = &out;
5971 uc_info.devices = audio_device;
5972 uc_info.in_snd_device = SND_DEVICE_NONE;
5973 uc_info.out_snd_device = SND_DEVICE_NONE;
5974 list_add_tail(&adev->usecase_list, &uc_info.list);
5975
5976 /* select device - similar to start_(in/out)put_stream() */
5977 retval = select_devices(adev, audio_usecase);
5978 if (retval >= 0) {
5979 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5980#if LOG_NDEBUG == 0
5981 if (*pparams) {
5982 ALOGV("%s: (%s) card %d device %d", __func__,
5983 dir ? "input" : "output", card_id, device_id);
5984 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005985 } else {
5986 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5987 }
5988#endif
5989 }
5990
5991 /* deselect device - similar to stop_(in/out)put_stream() */
5992 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005993 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005994 /* 2. Disable the rx device */
5995 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005996 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005997 list_remove(&uc_info.list);
5998 }
5999 }
Andy Hung31aca912014-03-20 17:14:59 -07006000 return 0;
6001}
6002
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006003static int adev_close(hw_device_t *device)
6004{
Andy Hung31aca912014-03-20 17:14:59 -07006005 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006006 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006007
6008 if (!adev)
6009 return 0;
6010
6011 pthread_mutex_lock(&adev_init_lock);
6012
6013 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006014 audio_extn_snd_mon_unregister_listener(adev);
6015 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08006016 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006017 audio_route_free(adev->audio_route);
6018 free(adev->snd_dev_ref_cnt);
6019 platform_deinit(adev->platform);
6020 audio_extn_extspk_deinit(adev->extspk);
6021 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006022 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006023 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
6024 pcm_params_free(adev->use_case_table[i]);
6025 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006026 if (adev->adm_deinit)
6027 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07006028 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006029 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07006030 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07006031
6032 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006033
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006034 return 0;
6035}
6036
Glenn Kasten4f993392014-05-14 07:30:48 -07006037/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6038 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6039 * just that it _might_ work.
6040 */
6041static int period_size_is_plausible_for_low_latency(int period_size)
6042{
6043 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006044 case 48:
6045 case 96:
6046 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07006047 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006048 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07006049 case 240:
6050 case 320:
6051 case 480:
6052 return 1;
6053 default:
6054 return 0;
6055 }
6056}
6057
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006058static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
6059{
6060 int card;
6061 card_status_t status;
6062
6063 if (!parms)
6064 return;
6065
6066 if (parse_snd_card_status(parms, &card, &status) < 0)
6067 return;
6068
6069 pthread_mutex_lock(&adev->lock);
6070 bool valid_cb = (card == adev->snd_card);
6071 if (valid_cb) {
6072 if (adev->card_status != status) {
6073 adev->card_status = status;
6074 platform_snd_card_update(adev->platform, status);
6075 }
6076 }
6077 pthread_mutex_unlock(&adev->lock);
6078 return;
6079}
6080
Aniket Kumar Lata26483012018-01-31 20:21:42 -08006081/* out and adev lock held */
6082static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6083{
6084 struct audio_usecase *uc_info;
6085 float left_p;
6086 float right_p;
6087 audio_devices_t devices;
6088
6089 uc_info = get_usecase_from_list(adev, out->usecase);
6090 if (uc_info == NULL) {
6091 ALOGE("%s: Could not find the usecase (%d) in the list",
6092 __func__, out->usecase);
6093 return -EINVAL;
6094 }
6095
6096 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6097 out->usecase, use_case_table[out->usecase]);
6098
6099 if (restore) {
6100 // restore A2DP device for active usecases and unmute if required
6101 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6102 !is_a2dp_device(uc_info->out_snd_device)) {
6103 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
6104 select_devices(adev, uc_info->id);
6105 pthread_mutex_lock(&out->compr_mute_lock);
6106 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6107 (out->a2dp_compress_mute)) {
6108 out->a2dp_compress_mute = false;
6109 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6110 }
6111 pthread_mutex_unlock(&out->compr_mute_lock);
6112 }
6113 } else {
6114 // mute compress stream if suspended
6115 pthread_mutex_lock(&out->compr_mute_lock);
6116 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6117 (!out->a2dp_compress_mute)) {
6118 if (!out->standby) {
6119 ALOGD("%s: selecting speaker and muting stream", __func__);
6120 devices = out->devices;
6121 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6122 left_p = out->volume_l;
6123 right_p = out->volume_r;
6124 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6125 compress_pause(out->compr);
6126 set_compr_volume(&out->stream, 0.0f, 0.0f);
6127 out->a2dp_compress_mute = true;
6128 select_devices(adev, out->usecase);
6129 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6130 compress_resume(out->compr);
6131 out->devices = devices;
6132 out->volume_l = left_p;
6133 out->volume_r = right_p;
6134 }
6135 }
6136 pthread_mutex_unlock(&out->compr_mute_lock);
6137 }
6138 ALOGV("%s: exit", __func__);
6139 return 0;
6140}
6141
6142int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6143{
6144 int ret = 0;
6145
6146 lock_output_stream(out);
6147 pthread_mutex_lock(&adev->lock);
6148
6149 ret = check_a2dp_restore_l(adev, out, restore);
6150
6151 pthread_mutex_unlock(&adev->lock);
6152 pthread_mutex_unlock(&out->lock);
6153 return ret;
6154}
6155
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006156static int adev_open(const hw_module_t *module, const char *name,
6157 hw_device_t **device)
6158{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07006159 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006160
Eric Laurent2bafff12016-03-17 12:17:23 -07006161 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006162 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006163 pthread_mutex_lock(&adev_init_lock);
6164 if (audio_device_ref_count != 0) {
6165 *device = &adev->device.common;
6166 audio_device_ref_count++;
6167 ALOGV("%s: returning existing instance of adev", __func__);
6168 ALOGV("%s: exit", __func__);
6169 pthread_mutex_unlock(&adev_init_lock);
6170 return 0;
6171 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006172 adev = calloc(1, sizeof(struct audio_device));
6173
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006174 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6175
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006176 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6177 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6178 adev->device.common.module = (struct hw_module_t *)module;
6179 adev->device.common.close = adev_close;
6180
6181 adev->device.init_check = adev_init_check;
6182 adev->device.set_voice_volume = adev_set_voice_volume;
6183 adev->device.set_master_volume = adev_set_master_volume;
6184 adev->device.get_master_volume = adev_get_master_volume;
6185 adev->device.set_master_mute = adev_set_master_mute;
6186 adev->device.get_master_mute = adev_get_master_mute;
6187 adev->device.set_mode = adev_set_mode;
6188 adev->device.set_mic_mute = adev_set_mic_mute;
6189 adev->device.get_mic_mute = adev_get_mic_mute;
6190 adev->device.set_parameters = adev_set_parameters;
6191 adev->device.get_parameters = adev_get_parameters;
6192 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6193 adev->device.open_output_stream = adev_open_output_stream;
6194 adev->device.close_output_stream = adev_close_output_stream;
6195 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006196
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006197 adev->device.close_input_stream = adev_close_input_stream;
6198 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07006199 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006200
6201 /* Set the default route before the PCM stream is opened */
6202 pthread_mutex_lock(&adev->lock);
6203 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006204 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006205 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006206 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006207 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006208 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006209 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006210 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006211 pthread_mutex_unlock(&adev->lock);
6212
6213 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006214 adev->platform = platform_init(adev);
6215 if (!adev->platform) {
6216 free(adev->snd_dev_ref_cnt);
6217 free(adev);
6218 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6219 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006220 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006221 return -EINVAL;
6222 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05006223 adev->extspk = audio_extn_extspk_init(adev);
6224
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006225 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6226 if (adev->visualizer_lib == NULL) {
6227 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6228 } else {
6229 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6230 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07006231 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006232 "visualizer_hal_start_output");
6233 adev->visualizer_stop_output =
6234 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
6235 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07006236 }
6237
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006238 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6239 if (adev->offload_effects_lib == NULL) {
6240 ALOGW("%s: DLOPEN failed for %s", __func__,
6241 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6242 } else {
6243 ALOGV("%s: DLOPEN successful for %s", __func__,
6244 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6245 adev->offload_effects_start_output =
6246 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6247 "offload_effects_bundle_hal_start_output");
6248 adev->offload_effects_stop_output =
6249 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6250 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07006251 }
6252
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006253 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6254 if (adev->adm_lib == NULL) {
6255 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6256 } else {
6257 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6258 adev->adm_init = (adm_init_t)
6259 dlsym(adev->adm_lib, "adm_init");
6260 adev->adm_deinit = (adm_deinit_t)
6261 dlsym(adev->adm_lib, "adm_deinit");
6262 adev->adm_register_input_stream = (adm_register_input_stream_t)
6263 dlsym(adev->adm_lib, "adm_register_input_stream");
6264 adev->adm_register_output_stream = (adm_register_output_stream_t)
6265 dlsym(adev->adm_lib, "adm_register_output_stream");
6266 adev->adm_deregister_stream = (adm_deregister_stream_t)
6267 dlsym(adev->adm_lib, "adm_deregister_stream");
6268 adev->adm_request_focus = (adm_request_focus_t)
6269 dlsym(adev->adm_lib, "adm_request_focus");
6270 adev->adm_abandon_focus = (adm_abandon_focus_t)
6271 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08006272 adev->adm_set_config = (adm_set_config_t)
6273 dlsym(adev->adm_lib, "adm_set_config");
6274 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6275 dlsym(adev->adm_lib, "adm_request_focus_v2");
6276 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6277 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6278 adev->adm_on_routing_change = (adm_on_routing_change_t)
6279 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006280 }
6281
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006282 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05006283 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006284
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006285 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006286
Andy Hung31aca912014-03-20 17:14:59 -07006287 if (k_enable_extended_precision)
6288 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006289
Glenn Kasten4f993392014-05-14 07:30:48 -07006290 char value[PROPERTY_VALUE_MAX];
6291 int trial;
6292 if (property_get("audio_hal.period_size", value, NULL) > 0) {
6293 trial = atoi(value);
6294 if (period_size_is_plausible_for_low_latency(trial)) {
6295 pcm_config_low_latency.period_size = trial;
6296 pcm_config_low_latency.start_threshold = trial / 4;
6297 pcm_config_low_latency.avail_min = trial / 4;
6298 configured_low_latency_capture_period_size = trial;
6299 }
6300 }
6301 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
6302 trial = atoi(value);
6303 if (period_size_is_plausible_for_low_latency(trial)) {
6304 configured_low_latency_capture_period_size = trial;
6305 }
6306 }
6307
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07006308 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
6309
Eric Laurent5f4ca952018-10-19 17:33:43 -07006310 adev->camera_orientation = CAMERA_DEFAULT;
6311
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006312 // commented as full set of app type cfg is sent from platform
6313 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006314 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08006315
6316 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
6317 af_period_multiplier = atoi(value);
6318 if (af_period_multiplier < 0) {
6319 af_period_multiplier = 2;
6320 } else if (af_period_multiplier > 4) {
6321 af_period_multiplier = 4;
6322 }
6323 ALOGV("new period_multiplier = %d", af_period_multiplier);
6324 }
6325
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006326 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08006327 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006328
vivek mehta1a9b7c02015-06-25 11:49:38 -07006329 pthread_mutex_unlock(&adev_init_lock);
6330
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006331 if (adev->adm_init)
6332 adev->adm_data = adev->adm_init();
6333
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006334 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006335 audio_extn_snd_mon_init();
6336 pthread_mutex_lock(&adev->lock);
6337 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
6338 adev->card_status = CARD_STATUS_ONLINE;
6339 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006340 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006341
Eric Laurent2bafff12016-03-17 12:17:23 -07006342 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006343 return 0;
6344}
6345
6346static struct hw_module_methods_t hal_module_methods = {
6347 .open = adev_open,
6348};
6349
6350struct audio_module HAL_MODULE_INFO_SYM = {
6351 .common = {
6352 .tag = HARDWARE_MODULE_TAG,
6353 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6354 .hal_api_version = HARDWARE_HAL_API_VERSION,
6355 .id = AUDIO_HARDWARE_MODULE_ID,
6356 .name = "QCOM Audio HAL",
6357 .author = "Code Aurora Forum",
6358 .methods = &hal_module_methods,
6359 },
6360};