blob: d3b4589692e89ee71eedd7aa3af0769b7bafaff7 [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"
justinwengc6347db2019-02-21 18:49:00 +080063#include "audio_extn/audiozoom.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064
Eric Laurent397db572016-05-11 11:31:47 -070065/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
66 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070067#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070068// 2 buffers causes problems with high bitrate files
69#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070070/* ToDo: Check and update a proper value in msec */
71#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070072/* treat as unsigned Q1.13 */
73#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070074#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070075
76/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070077#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070078
Eric Laurent51f3c662018-04-10 18:21:34 -070079#define RECORD_GAIN_MIN 0.0f
80#define RECORD_GAIN_MAX 1.0f
81#define RECORD_VOLUME_CTL_MAX 0x2000
82
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070083#define PROXY_OPEN_RETRY_COUNT 100
84#define PROXY_OPEN_WAIT_TIME 20
85
vivek mehtadae44712015-07-27 14:13:18 -070086#define MIN_CHANNEL_COUNT 1
87#define DEFAULT_CHANNEL_COUNT 2
88
Jean-Michel Trivic0750692015-10-12 12:12:32 -070089#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
90#define MAX_CHANNEL_COUNT 1
91#else
vivek mehtadae44712015-07-27 14:13:18 -070092#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
93#define XSTR(x) STR(x)
94#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070095#endif
Eric Laurent74b55762017-07-09 17:04:53 -070096#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070097
Haynes Mathew George03c40102016-01-29 17:57:48 -080098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Glenn Kasten4f993392014-05-14 07:30:48 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurent0e46adf2016-12-16 12:49:24 -0800103
104#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -0800105#define MMAP_PERIOD_COUNT_MIN 32
106#define MMAP_PERIOD_COUNT_MAX 512
107#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800108
Andy Hung31aca912014-03-20 17:14:59 -0700109/* This constant enables extended precision handling.
110 * TODO The flag is off until more testing is done.
111 */
112static const bool k_enable_extended_precision = false;
113
Eric Laurentb23d5282013-05-14 15:27:20 -0700114struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700115 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
118 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
123};
124
125struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700126 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700127 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
128 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
129 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
130 .format = PCM_FORMAT_S16_LE,
131 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
132 .stop_threshold = INT_MAX,
133 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
134};
135
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -0800136struct pcm_config pcm_config_haptics_audio = {
137 .channels = 1,
138 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
139 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
140 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
141 .format = PCM_FORMAT_S16_LE,
142 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
143 .stop_threshold = INT_MAX,
144 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
145};
146
147struct pcm_config pcm_config_haptics = {
148 .channels = 1,
149 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
150 .period_count = 2,
151 .format = PCM_FORMAT_S16_LE,
152 .stop_threshold = INT_MAX,
153 .avail_min = 0,
154};
155
Haynes Mathew George03c40102016-01-29 17:57:48 -0800156static int af_period_multiplier = 4;
157struct pcm_config pcm_config_rt = {
158 .channels = DEFAULT_CHANNEL_COUNT,
159 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
160 .period_size = ULL_PERIOD_SIZE, //1 ms
161 .period_count = 512, //=> buffer size is 512ms
162 .format = PCM_FORMAT_S16_LE,
163 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
164 .stop_threshold = INT_MAX,
165 .silence_threshold = 0,
166 .silence_size = 0,
167 .avail_min = ULL_PERIOD_SIZE, //1 ms
168};
169
Eric Laurentb23d5282013-05-14 15:27:20 -0700170struct pcm_config pcm_config_hdmi_multi = {
171 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
172 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
173 .period_size = HDMI_MULTI_PERIOD_SIZE,
174 .period_count = HDMI_MULTI_PERIOD_COUNT,
175 .format = PCM_FORMAT_S16_LE,
176 .start_threshold = 0,
177 .stop_threshold = INT_MAX,
178 .avail_min = 0,
179};
180
Eric Laurent0e46adf2016-12-16 12:49:24 -0800181struct pcm_config pcm_config_mmap_playback = {
182 .channels = DEFAULT_CHANNEL_COUNT,
183 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
184 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800185 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800186 .format = PCM_FORMAT_S16_LE,
187 .start_threshold = MMAP_PERIOD_SIZE*8,
188 .stop_threshold = INT32_MAX,
189 .silence_threshold = 0,
190 .silence_size = 0,
191 .avail_min = MMAP_PERIOD_SIZE, //1 ms
192};
193
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800194struct pcm_config pcm_config_hifi = {
195 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
196 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
197 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
198 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
199 .format = PCM_FORMAT_S24_3LE,
200 .start_threshold = 0,
201 .stop_threshold = INT_MAX,
202 .avail_min = 0,
203};
204
Eric Laurentb23d5282013-05-14 15:27:20 -0700205struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700206 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700207 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
208 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700209 .stop_threshold = INT_MAX,
210 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700211};
212
Haynes Mathew George03c40102016-01-29 17:57:48 -0800213struct pcm_config pcm_config_audio_capture_rt = {
214 .channels = DEFAULT_CHANNEL_COUNT,
215 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
216 .period_size = ULL_PERIOD_SIZE,
217 .period_count = 512,
218 .format = PCM_FORMAT_S16_LE,
219 .start_threshold = 0,
220 .stop_threshold = INT_MAX,
221 .silence_threshold = 0,
222 .silence_size = 0,
223 .avail_min = ULL_PERIOD_SIZE, //1 ms
224};
225
Eric Laurent0e46adf2016-12-16 12:49:24 -0800226struct pcm_config pcm_config_mmap_capture = {
227 .channels = DEFAULT_CHANNEL_COUNT,
228 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
229 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800230 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800231 .format = PCM_FORMAT_S16_LE,
232 .start_threshold = 0,
233 .stop_threshold = INT_MAX,
234 .silence_threshold = 0,
235 .silence_size = 0,
236 .avail_min = MMAP_PERIOD_SIZE, //1 ms
237};
238
vivek mehtaa68fea62017-06-08 19:04:02 -0700239struct pcm_config pcm_config_voip = {
240 .channels = 1,
241 .period_count = 2,
242 .format = PCM_FORMAT_S16_LE,
243 .stop_threshold = INT_MAX,
244 .avail_min = 0,
245};
246
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700247#define AFE_PROXY_CHANNEL_COUNT 2
248#define AFE_PROXY_SAMPLING_RATE 48000
249
jiabinad481a72018-07-23 12:03:17 -0700250#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700251#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
252
253struct pcm_config pcm_config_afe_proxy_playback = {
254 .channels = AFE_PROXY_CHANNEL_COUNT,
255 .rate = AFE_PROXY_SAMPLING_RATE,
256 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
257 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
258 .format = PCM_FORMAT_S16_LE,
259 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
260 .stop_threshold = INT_MAX,
261 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
262};
263
jiabinad481a72018-07-23 12:03:17 -0700264#define AFE_PROXY_RECORD_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700265#define AFE_PROXY_RECORD_PERIOD_COUNT 4
266
267struct pcm_config pcm_config_afe_proxy_record = {
268 .channels = AFE_PROXY_CHANNEL_COUNT,
269 .rate = AFE_PROXY_SAMPLING_RATE,
270 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
271 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
272 .format = PCM_FORMAT_S16_LE,
273 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
jiabin5d0261e2018-05-25 09:43:59 -0700274 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700275 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
276};
277
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700278const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700279 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
280 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -0800281 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800282 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700283 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700284 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700285 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800286 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700287
Eric Laurentb23d5282013-05-14 15:27:20 -0700288 [USECASE_AUDIO_RECORD] = "audio-record",
289 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800290 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700291 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700292
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800293 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
294 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700295
Eric Laurentb23d5282013-05-14 15:27:20 -0700296 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700297 [USECASE_VOICE2_CALL] = "voice2-call",
298 [USECASE_VOLTE_CALL] = "volte-call",
299 [USECASE_QCHAT_CALL] = "qchat-call",
300 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800301 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
302 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700303
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700304 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
305 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
306
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700307 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
308 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700309
310 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
311 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
312 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
313
vivek mehtaa68fea62017-06-08 19:04:02 -0700314 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
315 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200316
317 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700318
319 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700320};
321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800322
323#define STRING_TO_ENUM(string) { #string, string }
324
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800325struct string_to_enum {
326 const char *name;
327 uint32_t value;
328};
329
Haynes Mathew George569b7482017-05-08 14:44:27 -0700330static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800331 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
332 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
333 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700334 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700335 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700336 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
337 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
338 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
339 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
340 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
341 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
342 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
343 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
344 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800345};
346
Haynes Mathew George5191a852013-09-11 14:19:36 -0700347static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700348static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700349static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700350static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700351//cache last MBDRC cal step level
352static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700353
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800354static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
355static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
356
justinwengc6347db2019-02-21 18:49:00 +0800357static int in_set_microphone_direction(const struct audio_stream_in *stream,
358 audio_microphone_direction_t dir);
359static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
360
361
Haynes Mathew George03c40102016-01-29 17:57:48 -0800362static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
363 int flags __unused)
364{
365 int dir = 0;
366 switch (uc_id) {
367 case USECASE_AUDIO_RECORD_LOW_LATENCY:
368 dir = 1;
369 case USECASE_AUDIO_PLAYBACK_ULL:
370 break;
371 default:
372 return false;
373 }
374
375 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
376 PCM_PLAYBACK : PCM_CAPTURE);
377 if (adev->adm_is_noirq_avail)
378 return adev->adm_is_noirq_avail(adev->adm_data,
379 adev->snd_card, dev_id, dir);
380 return false;
381}
382
383static void register_out_stream(struct stream_out *out)
384{
385 struct audio_device *adev = out->dev;
386 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
387 return;
388
389 if (!adev->adm_register_output_stream)
390 return;
391
392 adev->adm_register_output_stream(adev->adm_data,
393 out->handle,
394 out->flags);
395
396 if (!adev->adm_set_config)
397 return;
398
399 if (out->realtime) {
400 adev->adm_set_config(adev->adm_data,
401 out->handle,
402 out->pcm, &out->config);
403 }
404}
405
406static void register_in_stream(struct stream_in *in)
407{
408 struct audio_device *adev = in->dev;
409 if (!adev->adm_register_input_stream)
410 return;
411
412 adev->adm_register_input_stream(adev->adm_data,
413 in->capture_handle,
414 in->flags);
415
416 if (!adev->adm_set_config)
417 return;
418
419 if (in->realtime) {
420 adev->adm_set_config(adev->adm_data,
421 in->capture_handle,
422 in->pcm,
423 &in->config);
424 }
425}
426
427static void request_out_focus(struct stream_out *out, long ns)
428{
429 struct audio_device *adev = out->dev;
430
Haynes Mathew George03c40102016-01-29 17:57:48 -0800431 if (adev->adm_request_focus_v2) {
432 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
433 } else if (adev->adm_request_focus) {
434 adev->adm_request_focus(adev->adm_data, out->handle);
435 }
436}
437
438static void request_in_focus(struct stream_in *in, long ns)
439{
440 struct audio_device *adev = in->dev;
441
Haynes Mathew George03c40102016-01-29 17:57:48 -0800442 if (adev->adm_request_focus_v2) {
443 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
444 } else if (adev->adm_request_focus) {
445 adev->adm_request_focus(adev->adm_data, in->capture_handle);
446 }
447}
448
449static void release_out_focus(struct stream_out *out, long ns __unused)
450{
451 struct audio_device *adev = out->dev;
452
453 if (adev->adm_abandon_focus)
454 adev->adm_abandon_focus(adev->adm_data, out->handle);
455}
456
457static void release_in_focus(struct stream_in *in, long ns __unused)
458{
459 struct audio_device *adev = in->dev;
460 if (adev->adm_abandon_focus)
461 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
462}
463
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700464static int parse_snd_card_status(struct str_parms * parms, int * card,
465 card_status_t * status)
466{
467 char value[32]={0};
468 char state[32]={0};
469
470 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
471
472 if (ret < 0)
473 return -1;
474
475 // sscanf should be okay as value is of max length 32.
476 // same as sizeof state.
477 if (sscanf(value, "%d,%s", card, state) < 2)
478 return -1;
479
480 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
481 CARD_STATUS_OFFLINE;
482 return 0;
483}
484
vivek mehta40125092017-08-21 18:48:51 -0700485// always call with adev lock held
486void send_gain_dep_calibration_l() {
487 if (last_known_cal_step >= 0)
488 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
489}
490
vivek mehta1a9b7c02015-06-25 11:49:38 -0700491__attribute__ ((visibility ("default")))
492bool audio_hw_send_gain_dep_calibration(int level) {
493 bool ret_val = false;
494 ALOGV("%s: enter ... ", __func__);
495
496 pthread_mutex_lock(&adev_init_lock);
497
498 if (adev != NULL && adev->platform != NULL) {
499 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700500 last_known_cal_step = level;
501 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700502 pthread_mutex_unlock(&adev->lock);
503 } else {
504 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
505 }
506
507 pthread_mutex_unlock(&adev_init_lock);
508
509 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
510 return ret_val;
511}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700512
jasmine cha270b7762018-03-30 15:41:33 +0800513#ifdef MAXXAUDIO_QDSP_ENABLED
514bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
515{
516 bool ret = false;
517 ALOGV("%s: enter ...", __func__);
518
519 pthread_mutex_lock(&adev_init_lock);
520
521 if (adev != NULL && adev->platform != NULL) {
522 pthread_mutex_lock(&adev->lock);
523 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
524 pthread_mutex_unlock(&adev->lock);
525 }
526
527 pthread_mutex_unlock(&adev_init_lock);
528
529 ALOGV("%s: exit with ret %d", __func__, ret);
530 return ret;
531}
532#else
533#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
534#endif
535
vivek mehtaa8d7c922016-05-25 14:40:44 -0700536__attribute__ ((visibility ("default")))
537int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
538 int table_size) {
539 int ret_val = 0;
540 ALOGV("%s: enter ... ", __func__);
541
542 pthread_mutex_lock(&adev_init_lock);
543 if (adev == NULL) {
544 ALOGW("%s: adev is NULL .... ", __func__);
545 goto done;
546 }
547
548 pthread_mutex_lock(&adev->lock);
549 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
550 pthread_mutex_unlock(&adev->lock);
551done:
552 pthread_mutex_unlock(&adev_init_lock);
553 ALOGV("%s: exit ... ", __func__);
554 return ret_val;
555}
556
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700557static bool is_supported_format(audio_format_t format)
558{
Eric Laurent8251ac82014-07-23 11:00:25 -0700559 switch (format) {
560 case AUDIO_FORMAT_MP3:
561 case AUDIO_FORMAT_AAC_LC:
562 case AUDIO_FORMAT_AAC_HE_V1:
563 case AUDIO_FORMAT_AAC_HE_V2:
564 return true;
565 default:
566 break;
567 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700568 return false;
569}
570
juyuchenbe5c67e2018-08-29 17:19:20 +0800571static bool is_supported_24bits_audiosource(audio_source_t source)
572{
573 switch (source) {
574 case AUDIO_SOURCE_UNPROCESSED:
575#ifdef ENABLED_24BITS_CAMCORDER
576 case AUDIO_SOURCE_CAMCORDER:
577#endif
578 return true;
579 default:
580 break;
581 }
582 return false;
583}
584
Haynes Mathew George03c40102016-01-29 17:57:48 -0800585static inline bool is_mmap_usecase(audio_usecase_t uc_id)
586{
587 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
588 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
589}
590
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700591static int get_snd_codec_id(audio_format_t format)
592{
593 int id = 0;
594
Eric Laurent8251ac82014-07-23 11:00:25 -0700595 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700596 case AUDIO_FORMAT_MP3:
597 id = SND_AUDIOCODEC_MP3;
598 break;
599 case AUDIO_FORMAT_AAC:
600 id = SND_AUDIOCODEC_AAC;
601 break;
602 default:
603 ALOGE("%s: Unsupported audio format", __func__);
604 }
605
606 return id;
607}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800608
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800609static int audio_ssr_status(struct audio_device *adev)
610{
611 int ret = 0;
612 struct mixer_ctl *ctl;
613 const char *mixer_ctl_name = "Audio SSR Status";
614
615 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
616 ret = mixer_ctl_get_value(ctl, 0);
617 ALOGD("%s: value: %d", __func__, ret);
618 return ret;
619}
620
vivek mehta4a824772017-06-08 19:05:49 -0700621static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
622{
623 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
624}
625
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800626static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
627{
628 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
629 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
630 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
631 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
632 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
633 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
634
635}
636
637static bool is_a2dp_device(snd_device_t out_snd_device)
638{
639 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
640}
641
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800642int enable_audio_route(struct audio_device *adev,
643 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800644{
yixuanjiang509f0a72018-09-06 18:37:23 +0800645 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700646 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800647
648 if (usecase == NULL)
649 return -EINVAL;
650
651 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
652
yixuanjiang509f0a72018-09-06 18:37:23 +0800653 if (usecase->type == PCM_CAPTURE)
654 snd_device = usecase->in_snd_device;
655 else
656 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530657 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Chafb2ea2c2019-03-04 18:12:47 +0800658 audio_extn_ma_set_device(usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800659 audio_extn_utils_send_audio_calibration(adev, usecase);
Andy Hung11f10e22018-10-19 17:47:12 -0700660
661 // we shouldn't truncate mixer_path
662 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
663 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
664 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800665 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Andy Hung11f10e22018-10-19 17:47:12 -0700666
yixuanjiang509f0a72018-09-06 18:37:23 +0800667 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700668 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700669 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800670
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800671 ALOGV("%s: exit", __func__);
672 return 0;
673}
674
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800675int disable_audio_route(struct audio_device *adev,
676 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800677{
yixuanjiang509f0a72018-09-06 18:37:23 +0800678 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700679 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800680
681 if (usecase == NULL)
682 return -EINVAL;
683
684 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800685 if (usecase->type == PCM_CAPTURE)
686 snd_device = usecase->in_snd_device;
687 else
688 snd_device = usecase->out_snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700689
690 // we shouldn't truncate mixer_path
691 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
692 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
693 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800694 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700695 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Andy Hung11f10e22018-10-19 17:47:12 -0700696
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700697 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000698 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800700 ALOGV("%s: exit", __func__);
701 return 0;
702}
703
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800704int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700705 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800706{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700707 int i, num_devices = 0;
708 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800709 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800710 if (snd_device < SND_DEVICE_MIN ||
711 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800712 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800713 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800714 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700715
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700716 platform_send_audio_calibration(adev->platform, snd_device);
717
vivek mehtade4849c2016-03-03 17:23:38 -0800718 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700719 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700720 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800721 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700722 }
723
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700724 /* due to the possibility of calibration overwrite between listen
725 and audio, notify sound trigger hal before audio calibration is sent */
726 audio_extn_sound_trigger_update_device_status(snd_device,
727 ST_EVENT_SND_DEVICE_BUSY);
728
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700729 if (audio_extn_spkr_prot_is_enabled())
730 audio_extn_spkr_prot_calib_cancel(adev);
731
zhaoyang yin4211fad2015-06-04 21:13:25 +0800732 audio_extn_dsm_feedback_enable(adev, snd_device, true);
733
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700734 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800735 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800736 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700737 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
738 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700739 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800740 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700741 }
742 if (audio_extn_spkr_prot_start_processing(snd_device)) {
743 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800744 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700745 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700746 } else if (platform_can_split_snd_device(snd_device,
747 &num_devices,
748 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700749 for (i = 0; i < num_devices; i++) {
750 enable_snd_device(adev, new_snd_devices[i]);
751 }
vivek mehtab6506412015-08-07 16:55:17 -0700752 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700753 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800754 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
755 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
756 ALOGE(" %s: Invalid sound device returned", __func__);
757 goto on_error;
758 }
Ed Tam70b5c142016-03-21 19:14:29 -0700759
Eric Laurent2e140aa2016-06-30 17:14:46 -0700760 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700761
762 if (is_a2dp_device(snd_device) &&
763 (audio_extn_a2dp_start_playback() < 0)) {
764 ALOGE("%s: failed to configure A2DP control path", __func__);
765 goto on_error;
766 }
767
vivek mehtade4849c2016-03-03 17:23:38 -0800768 audio_route_apply_and_update_path(adev->audio_route, device_name);
769 }
770on_success:
771 adev->snd_dev_ref_cnt[snd_device]++;
772 ret_val = 0;
773on_error:
774 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800775}
776
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800777int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700778 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800779{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700780 int i, num_devices = 0;
781 snd_device_t new_snd_devices[2];
782
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800783 if (snd_device < SND_DEVICE_MIN ||
784 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800785 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800786 return -EINVAL;
787 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700788 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
789 ALOGE("%s: device ref cnt is already 0", __func__);
790 return -EINVAL;
791 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800792 audio_extn_tfa_98xx_disable_speaker(snd_device);
793
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700794 adev->snd_dev_ref_cnt[snd_device]--;
795 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800796 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800797
798 if (is_a2dp_device(snd_device))
799 audio_extn_a2dp_stop_playback();
800
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700801 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800802 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700803 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700804 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
805 audio_extn_spkr_prot_is_enabled()) {
806 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700807
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700808 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
809 // and does not use speaker swap. As this code causes a problem with device enable ref
810 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700811 // when speaker device is disabled, reset swap.
812 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700813 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700814
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700815 } else if (platform_can_split_snd_device(snd_device,
816 &num_devices,
817 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700818 for (i = 0; i < num_devices; i++) {
819 disable_snd_device(adev, new_snd_devices[i]);
820 }
vivek mehtab6506412015-08-07 16:55:17 -0700821 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700822 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800823 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
824 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
825 ALOGE(" %s: Invalid sound device returned", __func__);
826 return -EINVAL;
827 }
828
Eric Laurent2e140aa2016-06-30 17:14:46 -0700829 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800830 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700831 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700832 audio_extn_sound_trigger_update_device_status(snd_device,
833 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700834 }
vivek mehtab6506412015-08-07 16:55:17 -0700835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800836 return 0;
837}
838
Vignesh Kulothungan64698822018-01-23 11:25:18 -0800839#ifdef DYNAMIC_ECNS_ENABLED
840static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
841 struct stream_in *in,
842 struct audio_effect_config effect_config,
843 unsigned int param_value)
844{
845 char mixer_ctl_name[] = "Audio Effect";
846 long set_values[6];
847
848 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
849 if (!ctl) {
850 ALOGE("%s: Could not get mixer ctl - %s",
851 __func__, mixer_ctl_name);
852 return -EINVAL;
853 }
854
855 set_values[0] = 1; //0:Rx 1:Tx
856 set_values[1] = in->app_type_cfg.app_type;
857 set_values[2] = (long)effect_config.module_id;
858 set_values[3] = (long)effect_config.instance_id;
859 set_values[4] = (long)effect_config.param_id;
860 set_values[5] = param_value;
861
862 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
863
864 return 0;
865
866}
867
868static int update_effect_param_ecns(struct audio_usecase *usecase,
869 unsigned int module_id, int effect_type,
870 unsigned int *param_value)
871{
872 int ret = 0;
873 struct audio_effect_config other_effect_config;
874 struct stream_in *in = NULL;
875
876 if (!usecase)
877 return -EINVAL;
878
879 in = usecase->stream.in;
880
881 /* Get the effect config data of the other effect */
882 ret = platform_get_effect_config_data(usecase->in_snd_device,
883 &other_effect_config,
884 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
885 if (ret < 0) {
886 ALOGE("%s Failed to get effect params %d", __func__, ret);
887 return ret;
888 }
889
890 if (module_id == other_effect_config.module_id) {
891 //Same module id for AEC/NS. Values need to be combined
892 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
893 ((effect_type == EFFECT_NS) && (in->enable_aec)))
894 *param_value |= other_effect_config.param_value;
895 }
896
897 return ret;
898}
899
900static int enable_disable_effect(struct audio_device *adev, struct stream_in *in,
901 int effect_type, bool enable)
902{
903 struct audio_effect_config effect_config;
904 struct audio_usecase *usecase = NULL;
905 int ret = 0;
906 unsigned int param_value = 0;
907
908 if (!in) {
909 ALOGE("%s: Invalid input stream", __func__);
910 return -EINVAL;
911 }
912
913 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
914
915 usecase = get_usecase_from_list(adev, in->usecase);
916
917 ret = platform_get_effect_config_data(usecase->in_snd_device,
918 &effect_config, effect_type);
919 if (ret < 0) {
920 ALOGE("%s Failed to get module id %d", __func__, ret);
921 return ret;
922 }
923 ALOGV("%s: module %d app_type %d usecase->id:%d usecase->in_snd_device:%d",
924 __func__, effect_config.module_id, in->app_type_cfg.app_type,
925 usecase->id, usecase->in_snd_device);
926
927 if (enable)
928 param_value = effect_config.param_value;
929
930 /*Special handling for AEC & NS effects Param values need to be
931 updated if module ids are same*/
932
933 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
934 ret = update_effect_param_ecns(usecase, effect_config.module_id,
935 effect_type, &param_value);
936 if (ret < 0)
937 return ret;
938 }
939
940 ret = send_effect_enable_disable_mixer_ctl(adev, in,
941 effect_config, param_value);
942
943 return ret;
944}
945
946static int check_and_enable_effect(struct audio_device *adev)
947{
948 int ret = 0;
949
950 struct listnode *node;
951 struct stream_in *in = NULL;
952
953 list_for_each(node, &adev->usecase_list)
954 {
955 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
956 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
957 in = usecase->stream.in;
958
959 if (in->standby)
960 continue;
961
962 if (in->enable_aec) {
963 ret = enable_disable_effect(adev, in, EFFECT_AEC, true);
964 }
965
966 if (in->enable_ns &&
967 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
968 ret = enable_disable_effect(adev, in, EFFECT_NS, true);
969 }
970 }
971 }
972
973 return ret;
974}
975#else
976#define enable_disable_effect(w, x, y, z) -ENOSYS
977#define check_and_enable_effect(x) -ENOSYS
978#endif
979
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700980/*
981 legend:
982 uc - existing usecase
983 new_uc - new usecase
984 d1, d11, d2 - SND_DEVICE enums
985 a1, a2 - corresponding ANDROID device enums
986 B, B1, B2 - backend strings
987
988case 1
989 uc->dev d1 (a1) B1
990 new_uc->dev d1 (a1), d2 (a2) B1, B2
991
992 resolution: disable and enable uc->dev on d1
993
994case 2
995 uc->dev d1 (a1) B1
996 new_uc->dev d11 (a1) B1
997
998 resolution: need to switch uc since d1 and d11 are related
999 (e.g. speaker and voice-speaker)
1000 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1001
1002case 3
1003 uc->dev d1 (a1) B1
1004 new_uc->dev d2 (a2) B2
1005
1006 resolution: no need to switch uc
1007
1008case 4
1009 uc->dev d1 (a1) B
1010 new_uc->dev d2 (a2) B
1011
1012 resolution: disable enable uc-dev on d2 since backends match
1013 we cannot enable two streams on two different devices if they
1014 share the same backend. e.g. if offload is on speaker device using
1015 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1016 using the same backend, offload must also be switched to voice-handset.
1017
1018case 5
1019 uc->dev d1 (a1) B
1020 new_uc->dev d1 (a1), d2 (a2) B
1021
1022 resolution: disable enable uc-dev on d2 since backends match
1023 we cannot enable two streams on two different devices if they
1024 share the same backend.
1025
1026case 6
1027 uc->dev d1 a1 B1
1028 new_uc->dev d2 a1 B2
1029
1030 resolution: no need to switch
1031
1032case 7
1033
1034 uc->dev d1 (a1), d2 (a2) B1, B2
1035 new_uc->dev d1 B1
1036
1037 resolution: no need to switch
1038
1039*/
1040static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
1041 struct audio_usecase *new_uc,
1042 snd_device_t new_snd_device)
1043{
1044 audio_devices_t a1 = uc->stream.out->devices;
1045 audio_devices_t a2 = new_uc->stream.out->devices;
1046
1047 snd_device_t d1 = uc->out_snd_device;
1048 snd_device_t d2 = new_snd_device;
1049
1050 // Treat as a special case when a1 and a2 are not disjoint
1051 if ((a1 != a2) && (a1 & a2)) {
1052 snd_device_t d3[2];
1053 int num_devices = 0;
1054 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
1055 &num_devices,
1056 d3);
1057 if (ret < 0) {
1058 if (ret != -ENOSYS) {
1059 ALOGW("%s failed to split snd_device %d",
1060 __func__,
1061 popcount(a1) > 1 ? d1 : d2);
1062 }
1063 goto end;
1064 }
1065
1066 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1067 // But if it does happen, we need to give priority to d2 if
1068 // the combo devices active on the existing usecase share a backend.
1069 // This is because we cannot have a usecase active on a combo device
1070 // and a new usecase requests one device in this combo pair.
1071 if (platform_check_backends_match(d3[0], d3[1])) {
1072 return d2; // case 5
1073 } else {
1074 return d1; // case 1
1075 }
1076 } else {
1077 if (platform_check_backends_match(d1, d2)) {
1078 return d2; // case 2, 4
1079 } else {
1080 return d1; // case 6, 3
1081 }
1082 }
1083
1084end:
1085 return d2; // return whatever was calculated before.
1086}
1087
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001088static void check_and_route_playback_usecases(struct audio_device *adev,
1089 struct audio_usecase *uc_info,
1090 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001091{
1092 struct listnode *node;
1093 struct audio_usecase *usecase;
1094 bool switch_device[AUDIO_USECASE_MAX];
1095 int i, num_uc_to_switch = 0;
1096
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001097 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
1098 uc_info,
1099 snd_device);
David Linee3fe402017-03-13 10:00:42 -07001100
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001101 /* For a2dp device reconfigure all active sessions
1102 * with new AFE encoder format based on a2dp state
1103 */
1104 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001105 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1106 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001107 audio_extn_a2dp_is_force_device_switch()) {
1108 force_routing = true;
1109 }
1110
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001111 /*
1112 * This function is to make sure that all the usecases that are active on
1113 * the hardware codec backend are always routed to any one device that is
1114 * handled by the hardware codec.
1115 * For example, if low-latency and deep-buffer usecases are currently active
1116 * on speaker and out_set_parameters(headset) is received on low-latency
1117 * output, then we have to make sure deep-buffer is also switched to headset,
1118 * because of the limitation that both the devices cannot be enabled
1119 * at the same time as they share the same backend.
1120 */
1121 /* Disable all the usecases on the shared backend other than the
1122 specified usecase */
1123 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1124 switch_device[i] = false;
1125
1126 list_for_each(node, &adev->usecase_list) {
1127 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001128 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
1129 continue;
1130
1131 if (force_routing ||
1132 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -07001133 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
1134 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001135 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001136 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1137 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -07001138 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001139 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001140 switch_device[usecase->id] = true;
1141 num_uc_to_switch++;
1142 }
1143 }
1144
1145 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001146 list_for_each(node, &adev->usecase_list) {
1147 usecase = node_to_item(node, struct audio_usecase, list);
1148 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001149 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001150 }
1151 }
1152
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001153 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001154 list_for_each(node, &adev->usecase_list) {
1155 usecase = node_to_item(node, struct audio_usecase, list);
1156 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001157 d_device = derive_playback_snd_device(usecase, uc_info,
1158 snd_device);
1159 enable_snd_device(adev, d_device);
1160 /* Update the out_snd_device before enabling the audio route */
1161 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001162 }
1163 }
1164
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001165 /* Re-route all the usecases on the shared backend other than the
1166 specified usecase to new snd devices */
1167 list_for_each(node, &adev->usecase_list) {
1168 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001169 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001170 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001171 }
1172 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001173 }
1174}
1175
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001176static void check_and_route_capture_usecases(struct audio_device *adev,
1177 struct audio_usecase *uc_info,
1178 snd_device_t snd_device)
1179{
1180 struct listnode *node;
1181 struct audio_usecase *usecase;
1182 bool switch_device[AUDIO_USECASE_MAX];
1183 int i, num_uc_to_switch = 0;
1184
vivek mehta4ed66e62016-04-15 23:33:34 -07001185 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1186
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001187 /*
1188 * This function is to make sure that all the active capture usecases
1189 * are always routed to the same input sound device.
1190 * For example, if audio-record and voice-call usecases are currently
1191 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1192 * is received for voice call then we have to make sure that audio-record
1193 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1194 * because of the limitation that two devices cannot be enabled
1195 * at the same time if they share the same backend.
1196 */
1197 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1198 switch_device[i] = false;
1199
1200 list_for_each(node, &adev->usecase_list) {
1201 usecase = node_to_item(node, struct audio_usecase, list);
1202 if (usecase->type != PCM_PLAYBACK &&
1203 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001204 usecase->in_snd_device != snd_device &&
Carter Hsu0a1160c2018-10-04 09:24:36 +08001205 ((uc_info->type == VOICE_CALL &&
1206 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1207 platform_check_backends_match(snd_device,\
1208 usecase->in_snd_device)) &&
Anish Kumarff864712015-06-03 13:35:11 -07001209 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001210 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1211 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001212 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001213 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001214 switch_device[usecase->id] = true;
1215 num_uc_to_switch++;
1216 }
1217 }
1218
1219 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001220 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 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001224 }
1225 }
1226
1227 list_for_each(node, &adev->usecase_list) {
1228 usecase = node_to_item(node, struct audio_usecase, list);
1229 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001230 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001231 }
1232 }
1233
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001234 /* Re-route all the usecases on the shared backend other than the
1235 specified usecase to new snd devices */
1236 list_for_each(node, &adev->usecase_list) {
1237 usecase = node_to_item(node, struct audio_usecase, list);
1238 /* Update the in_snd_device only before enabling the audio route */
1239 if (switch_device[usecase->id] ) {
1240 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001241 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001242 }
1243 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001244 }
1245}
1246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001247/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001248static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001249{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001250 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001251 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001252
1253 switch (channels) {
1254 /*
1255 * Do not handle stereo output in Multi-channel cases
1256 * Stereo case is handled in normal playback path
1257 */
1258 case 6:
1259 ALOGV("%s: HDMI supports 5.1", __func__);
1260 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1261 break;
1262 case 8:
1263 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1264 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1265 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1266 break;
1267 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001268 ALOGE("HDMI does not support multi channel playback");
1269 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001270 break;
1271 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001272 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001273}
1274
Andy Hung18859412017-08-09 11:47:21 -07001275static ssize_t read_usb_sup_sample_rates(bool is_playback,
1276 uint32_t *supported_sample_rates,
1277 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001278{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001279 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1280 supported_sample_rates,
1281 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001282#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001283 for (ssize_t i=0; i<count; i++) {
1284 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1285 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001286 }
1287#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001288 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001289}
1290
Haynes Mathew George569b7482017-05-08 14:44:27 -07001291static int read_usb_sup_channel_masks(bool is_playback,
1292 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001293 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001294{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001295 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001296 int channel_count;
1297 uint32_t num_masks = 0;
1298 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1299 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001300 }
Eric Laurent74b55762017-07-09 17:04:53 -07001301 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001302 // start from 2 channels as framework currently doesn't support mono.
1303 // TODO: consider only supporting channel index masks beyond stereo here.
1304 for (channel_count = FCC_2;
1305 channel_count <= channels && num_masks < max_masks;
1306 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001307 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1308 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001309 for (channel_count = FCC_2;
1310 channel_count <= channels && num_masks < max_masks;
1311 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001312 supported_channel_masks[num_masks++] =
1313 audio_channel_mask_for_index_assignment_from_count(channel_count);
1314 }
1315 } else {
1316 // For capture we report all supported channel masks from 1 channel up.
1317 channel_count = MIN_CHANNEL_COUNT;
1318 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1319 // indexed mask
1320 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
Andy Hung88ce1d92018-10-29 18:31:12 -07001321 const audio_channel_mask_t mask =
Eric Laurent74b55762017-07-09 17:04:53 -07001322 audio_channel_in_mask_from_count(channel_count);
Andy Hung88ce1d92018-10-29 18:31:12 -07001323 supported_channel_masks[num_masks++] = mask;
1324 const audio_channel_mask_t index_mask =
1325 audio_channel_mask_for_index_assignment_from_count(channel_count);
1326 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1327 supported_channel_masks[num_masks++] = index_mask;
1328 }
Eric Laurent74b55762017-07-09 17:04:53 -07001329 }
1330 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001331#ifdef NDEBUG
1332 for (size_t i = 0; i < num_masks; ++i) {
1333 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1334 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1335 }
1336#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001337 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001338}
1339
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001340static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001341 audio_format_t *supported_formats,
1342 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001343{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001344 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001345 switch (bitwidth) {
1346 case 24:
1347 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001348 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001349 break;
1350 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001351 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001352 break;
1353 case 16:
1354 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001355 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001356 break;
1357 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001358 ALOGV("%s: %s supported format %d", __func__,
1359 is_playback ? "P" : "C", bitwidth);
1360 return 1;
1361}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001362
Haynes Mathew George569b7482017-05-08 14:44:27 -07001363static int read_usb_sup_params_and_compare(bool is_playback,
1364 audio_format_t *format,
1365 audio_format_t *supported_formats,
1366 uint32_t max_formats,
1367 audio_channel_mask_t *mask,
1368 audio_channel_mask_t *supported_channel_masks,
1369 uint32_t max_masks,
1370 uint32_t *rate,
1371 uint32_t *supported_sample_rates,
1372 uint32_t max_rates) {
1373 int ret = 0;
1374 int num_formats;
1375 int num_masks;
1376 int num_rates;
1377 int i;
1378
1379 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1380 max_formats);
1381 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1382 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001383
Haynes Mathew George569b7482017-05-08 14:44:27 -07001384 num_rates = read_usb_sup_sample_rates(is_playback,
1385 supported_sample_rates, max_rates);
1386
1387#define LUT(table, len, what, dflt) \
1388 for (i=0; i<len && (table[i] != what); i++); \
1389 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1390
1391 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1392 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1393 LUT(supported_sample_rates, num_rates, *rate, 0);
1394
1395#undef LUT
1396 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001397}
1398
Andy Hungd9653bd2017-08-01 19:31:39 -07001399static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1400{
1401 // Check if usb is ready.
1402 // The usb device may have been removed quickly after insertion and hence
1403 // no longer available. This will show up as empty channel masks, or rates.
1404
1405 pthread_mutex_lock(&adev->lock);
1406 uint32_t supported_sample_rate;
1407
1408 // we consider usb ready if we can fetch at least one sample rate.
1409 const bool ready = read_usb_sup_sample_rates(
1410 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1411 pthread_mutex_unlock(&adev->lock);
1412 return ready;
1413}
1414
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001415static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1416{
1417 struct audio_usecase *usecase;
1418 struct listnode *node;
1419
1420 list_for_each(node, &adev->usecase_list) {
1421 usecase = node_to_item(node, struct audio_usecase, list);
1422 if (usecase->type == VOICE_CALL) {
1423 ALOGV("%s: usecase id %d", __func__, usecase->id);
1424 return usecase->id;
1425 }
1426 }
1427 return USECASE_INVALID;
1428}
1429
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001430struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1431 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001432{
1433 struct audio_usecase *usecase;
1434 struct listnode *node;
1435
1436 list_for_each(node, &adev->usecase_list) {
1437 usecase = node_to_item(node, struct audio_usecase, list);
1438 if (usecase->id == uc_id)
1439 return usecase;
1440 }
1441 return NULL;
1442}
1443
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001444static bool force_device_switch(struct audio_usecase *usecase)
1445{
1446 if (usecase->stream.out == NULL) {
1447 ALOGE("%s: stream.out is NULL", __func__);
1448 return false;
1449 }
1450
1451 // Force all A2DP output devices to reconfigure for proper AFE encode format
1452 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1453 // in suspended state, hence try to trigger a retry when we again get a routing request.
1454 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1455 audio_extn_a2dp_is_force_device_switch()) {
1456 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1457 return true;
1458 }
1459
1460 return false;
1461}
1462
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001463struct stream_in *adev_get_active_input(const struct audio_device *adev)
1464{
1465 struct listnode *node;
1466 struct stream_in *last_active_in = NULL;
1467
1468 /* Get last added active input.
1469 * TODO: We may use a priority mechanism to pick highest priority active source */
1470 list_for_each(node, &adev->usecase_list)
1471 {
1472 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1473 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
1474 last_active_in = usecase->stream.in;
1475 }
1476 }
1477
1478 return last_active_in;
1479}
1480
1481struct stream_in *get_voice_communication_input(const struct audio_device *adev)
1482{
1483 struct listnode *node;
1484
1485 /* First check active inputs with voice communication source and then
1486 * any input if audio mode is in communication */
1487 list_for_each(node, &adev->usecase_list)
1488 {
1489 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1490 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
1491 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1492 return usecase->stream.in;
1493 }
1494 }
1495 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
1496 return adev_get_active_input(adev);
1497 }
1498 return NULL;
1499}
1500
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001501int select_devices(struct audio_device *adev,
1502 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001503{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001504 snd_device_t out_snd_device = SND_DEVICE_NONE;
1505 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001506 struct audio_usecase *usecase = NULL;
1507 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001508 struct audio_usecase *hfp_usecase = NULL;
1509 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001510 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001511 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001512 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1513 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001514
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001515 usecase = get_usecase_from_list(adev, uc_id);
1516 if (usecase == NULL) {
1517 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1518 return -EINVAL;
1519 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001520
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001521 if ((usecase->type == VOICE_CALL) ||
1522 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001523 out_snd_device = platform_get_output_snd_device(adev->platform,
1524 usecase->stream.out->devices);
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001525 in_snd_device = platform_get_input_snd_device(adev->platform,
1526 NULL,
1527 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001528 usecase->devices = usecase->stream.out->devices;
1529 } else {
1530 /*
1531 * If the voice call is active, use the sound devices of voice call usecase
1532 * so that it would not result any device switch. All the usecases will
1533 * be switched to new device when select_devices() is called for voice call
1534 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001535 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001536 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001537 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001538 vc_usecase = get_usecase_from_list(adev,
1539 get_voice_usecase_id_from_list(adev));
1540 if ((vc_usecase != NULL) &&
1541 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
juyuchend194b432018-11-16 14:15:16 +08001542 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
1543 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001544 in_snd_device = vc_usecase->in_snd_device;
1545 out_snd_device = vc_usecase->out_snd_device;
1546 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001547 } else if (audio_extn_hfp_is_active(adev)) {
1548 hfp_ucid = audio_extn_hfp_get_usecase();
1549 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1550 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1551 in_snd_device = hfp_usecase->in_snd_device;
1552 out_snd_device = hfp_usecase->out_snd_device;
1553 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001554 }
1555 if (usecase->type == PCM_PLAYBACK) {
1556 usecase->devices = usecase->stream.out->devices;
1557 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001558 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001559 struct stream_out *voip_out = adev->primary_output;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001560 struct stream_in *voip_in = get_voice_communication_input(adev);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001561
Eric Laurentb23d5282013-05-14 15:27:20 -07001562 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001563 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001564
1565 if (voip_usecase)
1566 voip_out = voip_usecase->stream.out;
1567
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001568 if (usecase->stream.out == voip_out && voip_in != NULL) {
1569 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001570 }
1571 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001572 } else if (usecase->type == PCM_CAPTURE) {
1573 usecase->devices = usecase->stream.in->device;
1574 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001575 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001576 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001577 struct stream_in *voip_in = get_voice_communication_input(adev);
1578
1579 if (voip_in != NULL) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001580
1581 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1582 USECASE_AUDIO_PLAYBACK_VOIP);
1583
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001584 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001585 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1586 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001587 } else if (voip_usecase) {
1588 out_device = voip_usecase->stream.out->devices;
juyuchend194b432018-11-16 14:15:16 +08001589 } else if (adev->primary_output &&
1590 !adev->primary_output->standby) {
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001591 out_device = adev->primary_output->devices;
juyuchend194b432018-11-16 14:15:16 +08001592 } else {
1593 /* forcing speaker o/p device to get matching i/p pair
1594 in case o/p is not routed from same primary HAL */
1595 out_device = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001596 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001597 }
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001598 in_snd_device = platform_get_input_snd_device(adev->platform,
1599 usecase->stream.in,
1600 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001601 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001602 }
1603 }
1604
1605 if (out_snd_device == usecase->out_snd_device &&
1606 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001607 if (!force_device_switch(usecase))
1608 return 0;
1609 }
1610
1611 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1612 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1613 return 0;
1614 }
1615
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001616 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1617 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001618 (!audio_extn_a2dp_is_ready())) {
1619 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001620 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1621 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1622 else
1623 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624 }
1625
juyuchen66c4ecf2018-08-06 15:39:34 +08001626 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1627 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1628 }
1629
Eric Laurent2bafff12016-03-17 12:17:23 -07001630 if (out_snd_device != SND_DEVICE_NONE &&
1631 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1632 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1633 __func__,
1634 use_case_table[uc_id],
1635 adev->last_logged_snd_device[uc_id][0],
1636 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1637 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1638 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1639 -1,
1640 out_snd_device,
1641 platform_get_snd_device_name(out_snd_device),
1642 platform_get_snd_device_acdb_id(out_snd_device));
1643 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1644 }
1645 if (in_snd_device != SND_DEVICE_NONE &&
1646 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1647 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1648 __func__,
1649 use_case_table[uc_id],
1650 adev->last_logged_snd_device[uc_id][1],
1651 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1652 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1653 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1654 -1,
1655 in_snd_device,
1656 platform_get_snd_device_name(in_snd_device),
1657 platform_get_snd_device_acdb_id(in_snd_device));
1658 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1659 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001660
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661 /*
1662 * Limitation: While in call, to do a device switch we need to disable
1663 * and enable both RX and TX devices though one of them is same as current
1664 * device.
1665 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001666 if ((usecase->type == VOICE_CALL) &&
1667 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1668 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001669 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001670 /* Disable sidetone only if voice call already exists */
1671 if (voice_is_call_state_active(adev))
1672 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001673 }
1674
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001675 /* Disable current sound devices */
1676 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001677 disable_audio_route(adev, usecase);
1678 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679 }
1680
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001681 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001682 disable_audio_route(adev, usecase);
1683 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684 }
1685
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001686 /* Applicable only on the targets that has external modem.
1687 * New device information should be sent to modem before enabling
1688 * the devices to reduce in-call device switch time.
1689 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001690 if ((usecase->type == VOICE_CALL) &&
1691 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1692 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001693 status = platform_switch_voice_call_enable_device_config(adev->platform,
1694 out_snd_device,
1695 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001696 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001697
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001698 /* Enable new sound devices */
1699 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001700 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001701 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1702 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001703 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001704 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705 }
1706
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001707 if (in_snd_device != SND_DEVICE_NONE) {
1708 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001709 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001710 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001711
Eric Laurentb23d5282013-05-14 15:27:20 -07001712 if (usecase->type == VOICE_CALL)
1713 status = platform_switch_voice_call_device_post(adev->platform,
1714 out_snd_device,
1715 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001716
sangwoo170731f2013-06-08 15:36:36 +09001717 usecase->in_snd_device = in_snd_device;
1718 usecase->out_snd_device = out_snd_device;
1719
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001720 audio_extn_tfa_98xx_set_mode();
1721
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001722 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001723
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001724 /* If input stream is already running the effect needs to be
1725 applied on the new input device that's being enabled here. */
1726 if (in_snd_device != SND_DEVICE_NONE)
1727 check_and_enable_effect(adev);
1728
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001729 /* Applicable only on the targets that has external modem.
1730 * Enable device command should be sent to modem only after
1731 * enabling voice call mixer controls
1732 */
vivek mehta765eb642015-08-07 19:46:06 -07001733 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001734 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1735 out_snd_device,
1736 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001737 /* Enable sidetone only if voice call already exists */
1738 if (voice_is_call_state_active(adev))
1739 voice_set_sidetone(adev, out_snd_device, true);
1740 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001741
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001742 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001743 struct stream_out *voip_out = voip_usecase->stream.out;
1744 audio_extn_utils_send_app_type_gain(adev,
1745 voip_out->app_type_cfg.app_type,
1746 &voip_out->app_type_cfg.gain[0]);
1747 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748 return status;
1749}
1750
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001751static int stop_input_stream(struct stream_in *in)
1752{
1753 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754 struct audio_usecase *uc_info;
1755 struct audio_device *adev = in->dev;
1756
Eric Laurent994a6932013-07-17 11:51:42 -07001757 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001758 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760 uc_info = get_usecase_from_list(adev, in->usecase);
1761 if (uc_info == NULL) {
1762 ALOGE("%s: Could not find the usecase (%d) in the list",
1763 __func__, in->usecase);
1764 return -EINVAL;
1765 }
1766
vivek mehta781065c2017-04-04 12:55:01 -07001767 /* Close in-call recording streams */
1768 voice_check_and_stop_incall_rec_usecase(adev, in);
1769
Eric Laurent150dbfe2013-02-27 14:31:02 -08001770 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001771 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001772
1773 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001774 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001775
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001776 list_remove(&uc_info->list);
1777 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778
Eric Laurent994a6932013-07-17 11:51:42 -07001779 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780 return ret;
1781}
1782
1783int start_input_stream(struct stream_in *in)
1784{
1785 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001786 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787 struct audio_usecase *uc_info;
1788 struct audio_device *adev = in->dev;
1789
Eric Laurent994a6932013-07-17 11:51:42 -07001790 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001791
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001792 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1793 return -EIO;
1794
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001795 if (in->card_status == CARD_STATUS_OFFLINE ||
1796 adev->card_status == CARD_STATUS_OFFLINE) {
1797 ALOGW("in->card_status or adev->card_status offline, try again");
1798 ret = -EAGAIN;
1799 goto error_config;
1800 }
1801
vivek mehta781065c2017-04-04 12:55:01 -07001802 /* Check if source matches incall recording usecase criteria */
1803 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1804 if (ret)
1805 goto error_config;
1806 else
1807 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1808
Eric Laurentb23d5282013-05-14 15:27:20 -07001809 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001810 if (in->pcm_device_id < 0) {
1811 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1812 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001813 ret = -EINVAL;
1814 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001815 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001816
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001817 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1818 uc_info->id = in->usecase;
1819 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001820 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001821 uc_info->devices = in->device;
1822 uc_info->in_snd_device = SND_DEVICE_NONE;
1823 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001824
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001825 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001826
Wei Wangf4837d52017-11-21 14:51:20 -08001827 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001828 audio_extn_perf_lock_acquire();
1829
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001830 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001831
Eric Laurent0e46adf2016-12-16 12:49:24 -08001832 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001833 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001834 ALOGE("%s: pcm stream not ready", __func__);
1835 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001836 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001837 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001838 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001839 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1840 goto error_open;
1841 }
1842 } else {
1843 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1844 unsigned int pcm_open_retry_count = 0;
1845
1846 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1847 flags |= PCM_MMAP | PCM_NOIRQ;
1848 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1849 } else if (in->realtime) {
1850 flags |= PCM_MMAP | PCM_NOIRQ;
1851 }
1852
1853 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1854 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1855
1856 while (1) {
1857 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1858 flags, &in->config);
1859 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1860 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1861 if (in->pcm != NULL) {
1862 pcm_close(in->pcm);
1863 in->pcm = NULL;
1864 }
1865 if (pcm_open_retry_count-- == 0) {
1866 ret = -EIO;
1867 goto error_open;
1868 }
1869 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1870 continue;
1871 }
1872 break;
1873 }
1874
1875 ALOGV("%s: pcm_prepare", __func__);
1876 ret = pcm_prepare(in->pcm);
1877 if (ret < 0) {
1878 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001879 pcm_close(in->pcm);
1880 in->pcm = NULL;
1881 goto error_open;
1882 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001883 if (in->realtime) {
1884 ret = pcm_start(in->pcm);
1885 if (ret < 0) {
1886 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1887 pcm_close(in->pcm);
1888 in->pcm = NULL;
1889 goto error_open;
1890 }
1891 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001892 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001893 register_in_stream(in);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001894 check_and_enable_effect(adev);
justinwengc6347db2019-02-21 18:49:00 +08001895 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
1896 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Wei Wangf4837d52017-11-21 14:51:20 -08001897 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001898 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001899 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001900
Eric Laurent0e46adf2016-12-16 12:49:24 -08001901 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001902
1903error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001905 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001906 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001907
1908error_config:
Eric Laurent2bafff12016-03-17 12:17:23 -07001909 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001910 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001911}
1912
Eric Laurenta1478072015-09-21 17:21:52 -07001913void lock_input_stream(struct stream_in *in)
1914{
1915 pthread_mutex_lock(&in->pre_lock);
1916 pthread_mutex_lock(&in->lock);
1917 pthread_mutex_unlock(&in->pre_lock);
1918}
1919
1920void lock_output_stream(struct stream_out *out)
1921{
1922 pthread_mutex_lock(&out->pre_lock);
1923 pthread_mutex_lock(&out->lock);
1924 pthread_mutex_unlock(&out->pre_lock);
1925}
1926
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001927/* must be called with out->lock locked */
1928static int send_offload_cmd_l(struct stream_out* out, int command)
1929{
1930 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1931
1932 ALOGVV("%s %d", __func__, command);
1933
1934 cmd->cmd = command;
1935 list_add_tail(&out->offload_cmd_list, &cmd->node);
1936 pthread_cond_signal(&out->offload_cond);
1937 return 0;
1938}
1939
1940/* must be called iwth out->lock locked */
1941static void stop_compressed_output_l(struct stream_out *out)
1942{
1943 out->offload_state = OFFLOAD_STATE_IDLE;
1944 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001945 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001946 if (out->compr != NULL) {
1947 compress_stop(out->compr);
1948 while (out->offload_thread_blocked) {
1949 pthread_cond_wait(&out->cond, &out->lock);
1950 }
1951 }
1952}
1953
1954static void *offload_thread_loop(void *context)
1955{
1956 struct stream_out *out = (struct stream_out *) context;
1957 struct listnode *item;
1958
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001959 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1960 set_sched_policy(0, SP_FOREGROUND);
1961 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1962
1963 ALOGV("%s", __func__);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001964
Eric Laurenta1478072015-09-21 17:21:52 -07001965 lock_output_stream(out);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001966 out->offload_state = OFFLOAD_STATE_IDLE;
1967 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001968 for (;;) {
1969 struct offload_cmd *cmd = NULL;
1970 stream_callback_event_t event;
1971 bool send_callback = false;
1972
1973 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1974 __func__, list_empty(&out->offload_cmd_list),
1975 out->offload_state);
1976 if (list_empty(&out->offload_cmd_list)) {
1977 ALOGV("%s SLEEPING", __func__);
1978 pthread_cond_wait(&out->offload_cond, &out->lock);
1979 ALOGV("%s RUNNING", __func__);
1980 continue;
1981 }
1982
1983 item = list_head(&out->offload_cmd_list);
1984 cmd = node_to_item(item, struct offload_cmd, node);
1985 list_remove(item);
1986
1987 ALOGVV("%s STATE %d CMD %d out->compr %p",
1988 __func__, out->offload_state, cmd->cmd, out->compr);
1989
1990 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1991 free(cmd);
1992 break;
1993 }
1994
1995 if (out->compr == NULL) {
1996 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001997 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001998 pthread_cond_signal(&out->cond);
1999 continue;
2000 }
2001 out->offload_thread_blocked = true;
2002 pthread_mutex_unlock(&out->lock);
2003 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002004 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002005 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
2006 compress_wait(out->compr, -1);
2007 send_callback = true;
2008 event = STREAM_CBK_EVENT_WRITE_READY;
2009 break;
2010 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002011 compress_next_track(out->compr);
2012 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002013 send_callback = true;
2014 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002015 /* Resend the metadata for next iteration */
2016 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002017 break;
2018 case OFFLOAD_CMD_DRAIN:
2019 compress_drain(out->compr);
2020 send_callback = true;
2021 event = STREAM_CBK_EVENT_DRAIN_READY;
2022 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002023 case OFFLOAD_CMD_ERROR:
2024 send_callback = true;
2025 event = STREAM_CBK_EVENT_ERROR;
2026 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002027 default:
2028 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2029 break;
2030 }
Eric Laurenta1478072015-09-21 17:21:52 -07002031 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002032 out->offload_thread_blocked = false;
2033 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07002034 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002035 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002036 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002037 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002038 free(cmd);
2039 }
2040
2041 pthread_cond_signal(&out->cond);
2042 while (!list_empty(&out->offload_cmd_list)) {
2043 item = list_head(&out->offload_cmd_list);
2044 list_remove(item);
2045 free(node_to_item(item, struct offload_cmd, node));
2046 }
2047 pthread_mutex_unlock(&out->lock);
2048
2049 return NULL;
2050}
2051
2052static int create_offload_callback_thread(struct stream_out *out)
2053{
2054 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2055 list_init(&out->offload_cmd_list);
2056 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2057 offload_thread_loop, out);
2058 return 0;
2059}
2060
2061static int destroy_offload_callback_thread(struct stream_out *out)
2062{
Eric Laurenta1478072015-09-21 17:21:52 -07002063 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002064 stop_compressed_output_l(out);
2065 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2066
2067 pthread_mutex_unlock(&out->lock);
2068 pthread_join(out->offload_thread, (void **) NULL);
2069 pthread_cond_destroy(&out->offload_cond);
2070
2071 return 0;
2072}
2073
Eric Laurent07eeafd2013-10-06 12:52:49 -07002074static bool allow_hdmi_channel_config(struct audio_device *adev)
2075{
2076 struct listnode *node;
2077 struct audio_usecase *usecase;
2078 bool ret = true;
2079
2080 list_for_each(node, &adev->usecase_list) {
2081 usecase = node_to_item(node, struct audio_usecase, list);
2082 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2083 /*
2084 * If voice call is already existing, do not proceed further to avoid
2085 * disabling/enabling both RX and TX devices, CSD calls, etc.
2086 * Once the voice call done, the HDMI channels can be configured to
2087 * max channels of remaining use cases.
2088 */
2089 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08002090 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07002091 __func__);
2092 ret = false;
2093 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002094 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
2095 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07002096 "no change in HDMI channels", __func__);
2097 ret = false;
2098 break;
2099 }
2100 }
2101 }
2102 return ret;
2103}
2104
2105static int check_and_set_hdmi_channels(struct audio_device *adev,
2106 unsigned int channels)
2107{
2108 struct listnode *node;
2109 struct audio_usecase *usecase;
2110
2111 /* Check if change in HDMI channel config is allowed */
2112 if (!allow_hdmi_channel_config(adev))
2113 return 0;
2114
2115 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08002116 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002117 return 0;
2118 }
2119
2120 platform_set_hdmi_channels(adev->platform, channels);
2121 adev->cur_hdmi_channels = channels;
2122
2123 /*
2124 * Deroute all the playback streams routed to HDMI so that
2125 * the back end is deactivated. Note that backend will not
2126 * be deactivated if any one stream is connected to it.
2127 */
2128 list_for_each(node, &adev->usecase_list) {
2129 usecase = node_to_item(node, struct audio_usecase, list);
2130 if (usecase->type == PCM_PLAYBACK &&
2131 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002132 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002133 }
2134 }
2135
2136 /*
2137 * Enable all the streams disabled above. Now the HDMI backend
2138 * will be activated with new channel configuration
2139 */
2140 list_for_each(node, &adev->usecase_list) {
2141 usecase = node_to_item(node, struct audio_usecase, list);
2142 if (usecase->type == PCM_PLAYBACK &&
2143 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002144 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002145 }
2146 }
2147
2148 return 0;
2149}
2150
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002151static int check_and_set_usb_service_interval(struct audio_device *adev,
2152 struct audio_usecase *uc_info,
2153 bool min)
2154{
2155 struct listnode *node;
2156 struct audio_usecase *usecase;
2157 bool switch_usecases = false;
2158 bool reconfig = false;
2159
2160 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
2161 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
2162 return -1;
2163
2164 /* set if the valid usecase do not already exist */
2165 list_for_each(node, &adev->usecase_list) {
2166 usecase = node_to_item(node, struct audio_usecase, list);
2167 if (usecase->type == PCM_PLAYBACK &&
2168 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
2169 switch (usecase->id) {
2170 case USECASE_AUDIO_PLAYBACK_MMAP:
2171 case USECASE_AUDIO_PLAYBACK_ULL:
2172 // cannot reconfig while mmap/ull is present.
2173 return -1;
2174 default:
2175 switch_usecases = true;
2176 break;
2177 }
2178 }
2179 if (switch_usecases)
2180 break;
2181 }
2182 /*
2183 * client can try to set service interval in start_output_stream
2184 * to min or to 0 (i.e reset) in stop_output_stream .
2185 */
2186 unsigned long service_interval =
2187 audio_extn_usb_find_service_interval(min, true /*playback*/);
2188 int ret = platform_set_usb_service_interval(adev->platform,
2189 true /*playback*/,
2190 service_interval,
2191 &reconfig);
2192 /* no change or not supported or no active usecases */
2193 if (ret || !reconfig || !switch_usecases)
2194 return -1;
2195 return 0;
2196#undef VALID_USECASE
2197}
2198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002199static int stop_output_stream(struct stream_out *out)
2200{
2201 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002202 struct audio_usecase *uc_info;
2203 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08002204 bool has_voip_usecase =
2205 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002206
Eric Laurent994a6932013-07-17 11:51:42 -07002207 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002208 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209 uc_info = get_usecase_from_list(adev, out->usecase);
2210 if (uc_info == NULL) {
2211 ALOGE("%s: Could not find the usecase (%d) in the list",
2212 __func__, out->usecase);
2213 return -EINVAL;
2214 }
2215
Haynes Mathew George41f86652014-06-17 14:22:15 -07002216 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2217 if (adev->visualizer_stop_output != NULL)
2218 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
2219 if (adev->offload_effects_stop_output != NULL)
2220 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002221 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2222 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2223 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07002224 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002225
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002226 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2227 voice_set_device_mute_flag(adev, false);
2228
Eric Laurent150dbfe2013-02-27 14:31:02 -08002229 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002230 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002231
2232 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002233 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002235 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236
Eric Laurent0499d4f2014-08-25 22:39:29 -05002237 audio_extn_extspk_update(adev->extspk);
2238
Eric Laurent07eeafd2013-10-06 12:52:49 -07002239 /* Must be called after removing the usecase from list */
2240 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2241 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002242 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002243 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2244 if (ret == 0) {
2245 /* default service interval was successfully updated,
2246 reopen USB backend with new service interval */
2247 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2248 }
2249 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002250 }
juyuchend194b432018-11-16 14:15:16 +08002251 /* 1) media + voip output routing to handset must route media back to
2252 speaker when voip stops.
2253 2) trigger voip input to reroute when voip output changes to
2254 hearing aid. */
HW Lee88512e92018-06-12 15:26:09 +08002255 if (has_voip_usecase ||
2256 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2257 struct listnode *node;
2258 struct audio_usecase *usecase;
2259 list_for_each(node, &adev->usecase_list) {
2260 usecase = node_to_item(node, struct audio_usecase, list);
juyuchend194b432018-11-16 14:15:16 +08002261 if ((usecase->type == PCM_CAPTURE &&
2262 usecase->id != USECASE_AUDIO_RECORD_VOIP)
2263 || usecase == uc_info)
HW Lee88512e92018-06-12 15:26:09 +08002264 continue;
2265
2266 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2267 __func__, usecase->id, use_case_table[usecase->id],
2268 out->usecase, use_case_table[out->usecase]);
2269 select_devices(adev, usecase->id);
2270 }
2271 }
2272
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002273 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002274 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002275 return ret;
2276}
2277
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002278struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
2279 unsigned int flags, unsigned int pcm_open_retry_count,
2280 struct pcm_config *config)
2281{
2282 struct pcm* pcm = NULL;
2283
2284 while (1) {
2285 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
2286 if (pcm == NULL || !pcm_is_ready(pcm)) {
2287 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
2288 if (pcm != NULL) {
2289 pcm_close(pcm);
2290 pcm = NULL;
2291 }
2292 if (pcm_open_retry_count-- == 0)
2293 return NULL;
2294
2295 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2296 continue;
2297 }
2298 break;
2299 }
2300
2301 if (pcm_is_ready(pcm)) {
2302 int ret = pcm_prepare(pcm);
2303 if (ret < 0) {
2304 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2305 pcm_close(pcm);
2306 pcm = NULL;
2307 }
2308 }
2309
2310 return pcm;
2311}
2312
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313int start_output_stream(struct stream_out *out)
2314{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002315 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002316 struct audio_usecase *uc_info;
2317 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002318 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002320 ALOGV("%s: enter: usecase(%d: %s) %s devices(%#x)",
2321 __func__, out->usecase, use_case_table[out->usecase],
2322 out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS ? "(with haptics)" : "",
2323 out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002324
2325 if (out->card_status == CARD_STATUS_OFFLINE ||
2326 adev->card_status == CARD_STATUS_OFFLINE) {
2327 ALOGW("out->card_status or adev->card_status offline, try again");
2328 ret = -EAGAIN;
2329 goto error_config;
2330 }
2331
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002332 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2333 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002334 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002335 a2dp_combo = true;
2336 } else {
2337 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2338 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2339 ret = -EAGAIN;
2340 goto error_config;
2341 }
2342 }
2343 }
2344 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002345 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346 if (out->pcm_device_id < 0) {
2347 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2348 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002349 ret = -EINVAL;
2350 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351 }
2352
2353 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2354 uc_info->id = out->usecase;
2355 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002356 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002357 uc_info->devices = out->devices;
2358 uc_info->in_snd_device = SND_DEVICE_NONE;
2359 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360
Eric Laurent07eeafd2013-10-06 12:52:49 -07002361 /* This must be called before adding this usecase to the list */
2362 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2363 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002364 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2365 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2366 /* USB backend is not reopened immediately.
2367 This is eventually done as part of select_devices */
2368 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002369
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002370 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002371
Wei Wangf4837d52017-11-21 14:51:20 -08002372 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002373 audio_extn_perf_lock_acquire();
2374
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002375 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2376 (!audio_extn_a2dp_is_ready())) {
2377 if (!a2dp_combo) {
2378 check_a2dp_restore_l(adev, out, false);
2379 } else {
2380 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002381 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2382 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2383 else
2384 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002385 select_devices(adev, out->usecase);
2386 out->devices = dev;
2387 }
2388 } else {
2389 select_devices(adev, out->usecase);
2390 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002391
Eric Laurent0499d4f2014-08-25 22:39:29 -05002392 audio_extn_extspk_update(adev->extspk);
2393
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002394 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2395 voice_set_device_mute_flag(adev, true);
2396
Andy Hung31aca912014-03-20 17:14:59 -07002397 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002398 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002399 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2400 out->pcm = NULL;
2401 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2402 COMPRESS_IN, &out->compr_config);
2403 if (out->compr && !is_compress_ready(out->compr)) {
2404 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2405 compress_close(out->compr);
2406 out->compr = NULL;
2407 ret = -EIO;
2408 goto error_open;
2409 }
2410 if (out->offload_callback)
2411 compress_nonblock(out->compr, out->non_blocking);
2412
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002413 if (adev->visualizer_start_output != NULL) {
2414 int capture_device_id =
2415 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2416 PCM_CAPTURE);
2417 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2418 adev->snd_card, capture_device_id);
2419 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002420 if (adev->offload_effects_start_output != NULL)
2421 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2422 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002423 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002424 ALOGE("%s: pcm stream not ready", __func__);
2425 goto error_open;
2426 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002427 ret = pcm_start(out->pcm);
2428 if (ret < 0) {
2429 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2430 goto error_open;
2431 }
2432 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002433 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002434 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002435
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002436 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2437 flags |= PCM_MMAP | PCM_NOIRQ;
2438 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002439 } else if (out->realtime) {
2440 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002441 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002442
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002443 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
2444 flags, pcm_open_retry_count,
2445 &(out->config));
2446 if (out->pcm == NULL) {
2447 ret = -EIO;
2448 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002449 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002450
2451 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2452 if (adev->haptic_pcm != NULL) {
2453 pcm_close(adev->haptic_pcm);
2454 adev->haptic_pcm = NULL;
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002455 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002456 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
2457 adev->haptic_pcm_device_id,
2458 flags, pcm_open_retry_count,
2459 &(adev->haptics_config));
2460 // failure to open haptics pcm shouldnt stop audio,
2461 // so do not close audio pcm in case of error
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002462 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002463
Eric Laurent0e46adf2016-12-16 12:49:24 -08002464 if (out->realtime) {
2465 ret = pcm_start(out->pcm);
2466 if (ret < 0) {
2467 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2468 pcm_close(out->pcm);
2469 out->pcm = NULL;
2470 goto error_open;
2471 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002472 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002473 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002474
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002475 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002476 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002477 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002478 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002479
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002480 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2481 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2482 audio_low_latency_hint_start();
2483 }
2484
vivek mehtae59cfb22017-06-16 15:57:11 -07002485 // consider a scenario where on pause lower layers are tear down.
2486 // so on resume, swap mixer control need to be sent only when
2487 // backend is active, hence rather than sending from enable device
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002488 // sending it from start of stream
vivek mehtae59cfb22017-06-16 15:57:11 -07002489
2490 platform_set_swap_channels(adev, true);
2491
Eric Laurent994a6932013-07-17 11:51:42 -07002492 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002493 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002494error_open:
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002495 if (adev->haptic_pcm) {
2496 pcm_close(adev->haptic_pcm);
2497 adev->haptic_pcm = NULL;
2498 }
Wei Wangf4837d52017-11-21 14:51:20 -08002499 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002500 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002502error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002503 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504}
2505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506static int check_input_parameters(uint32_t sample_rate,
2507 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002508 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002510 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2511 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002512 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2513 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002514 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2515 return -EINVAL;
2516 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517
Eric Laurent74b55762017-07-09 17:04:53 -07002518 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2519 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002520 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002521 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002522 return -EINVAL;
2523 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524
2525 switch (sample_rate) {
2526 case 8000:
2527 case 11025:
2528 case 12000:
2529 case 16000:
2530 case 22050:
2531 case 24000:
2532 case 32000:
2533 case 44100:
2534 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002535 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536 break;
2537 default:
vivek mehtadae44712015-07-27 14:13:18 -07002538 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539 return -EINVAL;
2540 }
2541
2542 return 0;
2543}
2544
Kevin Rocarda325aa22018-04-03 09:15:52 -07002545/** Add a value in a list if not already present.
2546 * @return true if value was successfully inserted or already present,
2547 * false if the list is full and does not contain the value.
2548 */
2549static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2550 for (size_t i = 0; i < list_length; i++) {
2551 if (list[i] == value) return true; // value is already present
2552 if (list[i] == 0) { // no values in this slot
2553 list[i] = value;
2554 return true; // value inserted
2555 }
2556 }
2557 return false; // could not insert value
2558}
2559
2560/** Add channel_mask in supported_channel_masks if not already present.
2561 * @return true if channel_mask was successfully inserted or already present,
2562 * false if supported_channel_masks is full and does not contain channel_mask.
2563 */
2564static void register_channel_mask(audio_channel_mask_t channel_mask,
2565 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2566 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2567 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2568}
2569
2570/** Add format in supported_formats if not already present.
2571 * @return true if format was successfully inserted or already present,
2572 * false if supported_formats is full and does not contain format.
2573 */
2574static void register_format(audio_format_t format,
2575 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2576 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2577 "%s: stream can not declare supporting its format %x", __func__, format);
2578}
2579/** Add sample_rate in supported_sample_rates if not already present.
2580 * @return true if sample_rate was successfully inserted or already present,
2581 * false if supported_sample_rates is full and does not contain sample_rate.
2582 */
2583static void register_sample_rate(uint32_t sample_rate,
2584 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2585 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2586 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2587}
2588
vivek mehtaa68fea62017-06-08 19:04:02 -07002589static size_t get_stream_buffer_size(size_t duration_ms,
2590 uint32_t sample_rate,
2591 audio_format_t format,
2592 int channel_count,
2593 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594{
2595 size_t size = 0;
2596
vivek mehtaa68fea62017-06-08 19:04:02 -07002597 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002598 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002599 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002600
2601 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602
Glenn Kasten4f993392014-05-14 07:30:48 -07002603 /* make sure the size is multiple of 32 bytes
2604 * At 48 kHz mono 16-bit PCM:
2605 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2606 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2607 */
2608 size += 0x1f;
2609 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002610
2611 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612}
2613
2614static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2615{
2616 struct stream_out *out = (struct stream_out *)stream;
2617
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002618 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619}
2620
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002621static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622{
2623 return -ENOSYS;
2624}
2625
2626static size_t out_get_buffer_size(const struct audio_stream *stream)
2627{
2628 struct stream_out *out = (struct stream_out *)stream;
2629
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002630 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2631 return out->compr_config.fragment_size;
2632 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002633 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002634 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635}
2636
2637static uint32_t out_get_channels(const struct audio_stream *stream)
2638{
2639 struct stream_out *out = (struct stream_out *)stream;
2640
2641 return out->channel_mask;
2642}
2643
2644static audio_format_t out_get_format(const struct audio_stream *stream)
2645{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002646 struct stream_out *out = (struct stream_out *)stream;
2647
2648 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649}
2650
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002651static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652{
2653 return -ENOSYS;
2654}
2655
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002656/* must be called with out->lock locked */
2657static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658{
2659 struct stream_out *out = (struct stream_out *)stream;
2660 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002661 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002664 if (adev->adm_deregister_stream)
2665 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002666 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002668 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2669 if (out->pcm) {
2670 pcm_close(out->pcm);
2671 out->pcm = NULL;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002672
2673 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2674 if (adev->haptic_pcm) {
2675 pcm_close(adev->haptic_pcm);
2676 adev->haptic_pcm = NULL;
2677 }
2678
2679 if (adev->haptic_buffer != NULL) {
2680 free(adev->haptic_buffer);
2681 adev->haptic_buffer = NULL;
2682 adev->haptic_buffer_size = 0;
2683 }
2684 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002685 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002686 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002687 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002688 out->playback_started = false;
2689 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002690 } else {
2691 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002692 out->gapless_mdata.encoder_delay = 0;
2693 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002694 if (out->compr != NULL) {
2695 compress_close(out->compr);
2696 out->compr = NULL;
2697 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002698 }
Phil Burkbc991042017-02-24 08:06:44 -08002699 if (do_stop) {
2700 stop_output_stream(out);
2701 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002702 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002704 return 0;
2705}
2706
2707static int out_standby(struct audio_stream *stream)
2708{
2709 struct stream_out *out = (struct stream_out *)stream;
2710
2711 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2712 out->usecase, use_case_table[out->usecase]);
2713
2714 lock_output_stream(out);
2715 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002717 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718 return 0;
2719}
2720
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002721static int out_on_error(struct audio_stream *stream)
2722{
2723 struct stream_out *out = (struct stream_out *)stream;
2724 struct audio_device *adev = out->dev;
2725 bool do_standby = false;
2726
2727 lock_output_stream(out);
2728 if (!out->standby) {
2729 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2730 stop_compressed_output_l(out);
2731 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2732 } else
2733 do_standby = true;
2734 }
2735 pthread_mutex_unlock(&out->lock);
2736
2737 if (do_standby)
2738 return out_standby(&out->stream.common);
2739
2740 return 0;
2741}
2742
Andy Hung7401c7c2016-09-21 12:41:21 -07002743static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002744{
Andy Hung7401c7c2016-09-21 12:41:21 -07002745 struct stream_out *out = (struct stream_out *)stream;
2746
2747 // We try to get the lock for consistency,
2748 // but it isn't necessary for these variables.
2749 // If we're not in standby, we may be blocked on a write.
2750 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2751 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2752 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2753
Andy Hung572633e2019-02-19 11:58:24 -08002754 char buffer[256]; // for statistics formatting
2755 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
2756 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
2757
Andy Hung241e36f2019-02-19 12:00:38 -08002758 if (out->start_latency_ms.n > 0) {
2759 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
2760 dprintf(fd, " Start latency ms: %s\n", buffer);
2761 }
2762
Andy Hung7401c7c2016-09-21 12:41:21 -07002763 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002764 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002765 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002766
2767 // dump error info
2768 (void)error_log_dump(
2769 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002770
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771 return 0;
2772}
2773
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002774static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2775{
2776 int ret = 0;
2777 char value[32];
2778 struct compr_gapless_mdata tmp_mdata;
2779
2780 if (!out || !parms) {
2781 return -EINVAL;
2782 }
2783
2784 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2785 if (ret >= 0) {
2786 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2787 } else {
2788 return -EINVAL;
2789 }
2790
2791 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2792 if (ret >= 0) {
2793 tmp_mdata.encoder_padding = atoi(value);
2794 } else {
2795 return -EINVAL;
2796 }
2797
2798 out->gapless_mdata = tmp_mdata;
2799 out->send_new_metadata = 1;
2800 ALOGV("%s new encoder delay %u and padding %u", __func__,
2801 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2802
2803 return 0;
2804}
2805
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002806static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2807{
2808 return out == adev->primary_output || out == adev->voice_tx_output;
2809}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002810
Kevin Rocard1e02c882017-08-09 15:26:07 -07002811static int get_alive_usb_card(struct str_parms* parms) {
2812 int card;
2813 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2814 !audio_extn_usb_alive(card)) {
2815 return card;
2816 }
2817 return -ENODEV;
2818}
2819
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002820static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2821{
2822 struct stream_out *out = (struct stream_out *)stream;
2823 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002824 struct audio_usecase *usecase;
2825 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826 struct str_parms *parms;
2827 char value[32];
2828 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002829 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002830 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002831 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832
Eric Laurent2e140aa2016-06-30 17:14:46 -07002833 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002834 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002835 parms = str_parms_create_str(kvpairs);
2836 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2837 if (ret >= 0) {
2838 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002839
Eric Laurenta1478072015-09-21 17:21:52 -07002840 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002841
2842 // The usb driver needs to be closed after usb device disconnection
2843 // otherwise audio is no longer played on the new usb devices.
2844 // By forcing the stream in standby, the usb stack refcount drops to 0
2845 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002846 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002847 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002848 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2849 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2850 out_standby_l(&out->stream.common);
2851 }
2852 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002853 }
2854
Eric Laurent150dbfe2013-02-27 14:31:02 -08002855 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002856
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002857 /*
2858 * When HDMI cable is unplugged the music playback is paused and
2859 * the policy manager sends routing=0. But the audioflinger
2860 * continues to write data until standby time (3sec).
2861 * As the HDMI core is turned off, the write gets blocked.
2862 * Avoid this by routing audio to speaker until standby.
2863 */
2864 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2865 val == AUDIO_DEVICE_NONE) {
2866 val = AUDIO_DEVICE_OUT_SPEAKER;
2867 }
2868
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002869 /*
2870 * When A2DP is disconnected the
2871 * music playback is paused and the policy manager sends routing=0
2872 * But the audioflingercontinues to write data until standby time
2873 * (3sec). As BT is turned off, the write gets blocked.
2874 * Avoid this by routing audio to speaker until standby.
2875 */
2876 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2877 (val == AUDIO_DEVICE_NONE) &&
2878 !audio_extn_a2dp_is_ready()) {
2879 val = AUDIO_DEVICE_OUT_SPEAKER;
2880 }
2881
2882 /* To avoid a2dp to sco overlapping / BT device improper state
2883 * check with BT lib about a2dp streaming support before routing
2884 */
2885 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2886 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002887 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002888 //combo usecase just by pass a2dp
2889 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2890 bypass_a2dp = true;
2891 } else {
2892 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2893 /* update device to a2dp and don't route as BT returned error
2894 * However it is still possible a2dp routing called because
2895 * of current active device disconnection (like wired headset)
2896 */
2897 out->devices = val;
2898 pthread_mutex_unlock(&out->lock);
2899 pthread_mutex_unlock(&adev->lock);
2900 status = -ENOSYS;
2901 goto routing_fail;
2902 }
2903 }
2904 }
2905
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002906 audio_devices_t new_dev = val;
2907
2908 // Workaround: If routing to an non existing usb device, fail gracefully
2909 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002910 int card;
2911 if (audio_is_usb_out_device(new_dev) &&
2912 (card = get_alive_usb_card(parms)) >= 0) {
2913
2914 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002915 pthread_mutex_unlock(&adev->lock);
2916 pthread_mutex_unlock(&out->lock);
2917 status = -ENOSYS;
2918 goto routing_fail;
2919 }
2920
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002921 /*
2922 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002923 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002924 * the select_devices(). But how do we undo this?
2925 *
2926 * For example, music playback is active on headset (deep-buffer usecase)
2927 * and if we go to ringtones and select a ringtone, low-latency usecase
2928 * will be started on headset+speaker. As we can't enable headset+speaker
2929 * and headset devices at the same time, select_devices() switches the music
2930 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2931 * So when the ringtone playback is completed, how do we undo the same?
2932 *
2933 * We are relying on the out_set_parameters() call on deep-buffer output,
2934 * once the ringtone playback is ended.
2935 * NOTE: We should not check if the current devices are same as new devices.
2936 * Because select_devices() must be called to switch back the music
2937 * playback to headset.
2938 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002939 if (new_dev != AUDIO_DEVICE_NONE) {
2940 bool same_dev = out->devices == new_dev;
2941 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002942
Eric Laurenta7657192014-10-09 21:09:33 -07002943 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002944 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002945 if (adev->mode == AUDIO_MODE_IN_CALL) {
2946 adev->current_call_output = out;
2947 ret = voice_start_call(adev);
2948 }
2949 } else {
2950 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002951 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002952 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002953 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002954
2955 if (!out->standby) {
2956 if (!same_dev) {
2957 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002958 // inform adm before actual routing to prevent glitches.
2959 if (adev->adm_on_routing_change) {
2960 adev->adm_on_routing_change(adev->adm_data,
2961 out->handle);
2962 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002963 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002964 if (!bypass_a2dp) {
2965 select_devices(adev, out->usecase);
2966 } else {
juyuchen9baad392018-06-05 19:02:10 +08002967 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2968 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2969 else
2970 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002971 select_devices(adev, out->usecase);
2972 out->devices = new_dev;
2973 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002974 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002975
2976 // on device switch force swap, lower functions will make sure
2977 // to check if swap is allowed or not.
2978
2979 if (!same_dev)
2980 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002981
2982 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2983 out->a2dp_compress_mute &&
2984 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2985 pthread_mutex_lock(&out->compr_mute_lock);
2986 out->a2dp_compress_mute = false;
2987 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2988 pthread_mutex_unlock(&out->compr_mute_lock);
2989 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002990 }
2991
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002992 }
2993
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002995 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002996
2997 /*handles device and call state changes*/
2998 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003000 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003001
3002 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3003 parse_compress_metadata(out, parms);
3004 }
3005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003007 ALOGV("%s: exit: code(%d)", __func__, status);
3008 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009}
3010
Haynes Mathew George569b7482017-05-08 14:44:27 -07003011static bool stream_get_parameter_channels(struct str_parms *query,
3012 struct str_parms *reply,
3013 audio_channel_mask_t *supported_channel_masks) {
3014 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07003015 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003017 size_t i, j;
3018
3019 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3020 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021 value[0] = '\0';
3022 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003023 while (supported_channel_masks[i] != 0) {
3024 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3025 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026 if (!first) {
3027 strcat(value, "|");
3028 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003029 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030 first = false;
3031 break;
3032 }
3033 }
3034 i++;
3035 }
3036 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003037 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003038 return ret >= 0;
3039}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003040
Haynes Mathew George569b7482017-05-08 14:44:27 -07003041static bool stream_get_parameter_formats(struct str_parms *query,
3042 struct str_parms *reply,
3043 audio_format_t *supported_formats) {
3044 int ret = -1;
3045 char value[256];
3046 int i;
3047
3048 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
3049 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003050 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07003051 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003052 case AUDIO_FORMAT_PCM_16_BIT:
3053 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
3054 break;
3055 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
3056 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
3057 break;
3058 case AUDIO_FORMAT_PCM_32_BIT:
3059 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
3060 break;
3061 default:
3062 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07003063 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003064 break;
3065 }
3066 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003067 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003068 return ret >= 0;
3069}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003070
Haynes Mathew George569b7482017-05-08 14:44:27 -07003071static bool stream_get_parameter_rates(struct str_parms *query,
3072 struct str_parms *reply,
3073 uint32_t *supported_sample_rates) {
3074
3075 int i;
3076 char value[256];
3077 int ret = -1;
3078 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
3079 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003080 value[0] = '\0';
3081 i=0;
3082 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003083 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003084 int avail = sizeof(value) - cursor;
3085 ret = snprintf(value + cursor, avail, "%s%d",
3086 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07003087 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003088 if (ret < 0 || ret >= avail) {
3089 // if cursor is at the last element of the array
3090 // overwrite with \0 is duplicate work as
3091 // snprintf already put a \0 in place.
3092 // else
3093 // we had space to write the '|' at value[cursor]
3094 // (which will be overwritten) or no space to fill
3095 // the first element (=> cursor == 0)
3096 value[cursor] = '\0';
3097 break;
3098 }
3099 cursor += ret;
3100 ++i;
3101 }
3102 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3103 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003104 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003105 return ret >= 0;
3106}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003107
Haynes Mathew George569b7482017-05-08 14:44:27 -07003108static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3109{
3110 struct stream_out *out = (struct stream_out *)stream;
3111 struct str_parms *query = str_parms_create_str(keys);
3112 char *str;
3113 struct str_parms *reply = str_parms_create();
3114 bool replied = false;
3115 ALOGV("%s: enter: keys - %s", __func__, keys);
3116
3117 replied |= stream_get_parameter_channels(query, reply,
3118 &out->supported_channel_masks[0]);
3119 replied |= stream_get_parameter_formats(query, reply,
3120 &out->supported_formats[0]);
3121 replied |= stream_get_parameter_rates(query, reply,
3122 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003123 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003124 str = str_parms_to_str(reply);
3125 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07003126 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127 }
3128 str_parms_destroy(query);
3129 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003130 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131 return str;
3132}
3133
3134static uint32_t out_get_latency(const struct audio_stream_out *stream)
3135{
Haynes Mathew George03c40102016-01-29 17:57:48 -08003136 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003138 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003140 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3141 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003142 else if ((out->realtime) ||
3143 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003144 // since the buffer won't be filled up faster than realtime,
3145 // return a smaller number
3146 period_ms = (out->af_period_multiplier * out->config.period_size *
3147 1000) / (out->config.rate);
3148 hw_delay = platform_render_latency(out->usecase)/1000;
3149 return period_ms + hw_delay;
3150 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003151
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003152 latency = (out->config.period_count * out->config.period_size * 1000) /
3153 (out->config.rate);
3154
3155 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
3156 latency += audio_extn_a2dp_get_encoder_latency();
3157
3158 return latency;
3159}
3160
3161static int set_compr_volume(struct audio_stream_out *stream, float left,
3162 float right)
3163{
3164 struct stream_out *out = (struct stream_out *)stream;
3165 int volume[2];
3166 char mixer_ctl_name[128];
3167 struct audio_device *adev = out->dev;
3168 struct mixer_ctl *ctl;
3169 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3170 PCM_PLAYBACK);
3171
3172 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3173 "Compress Playback %d Volume", pcm_device_id);
3174 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3175 if (!ctl) {
3176 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3177 __func__, mixer_ctl_name);
3178 return -EINVAL;
3179 }
3180 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
3181 __func__, mixer_ctl_name, left, right);
3182 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3183 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3184 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
3185
3186 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187}
3188
3189static int out_set_volume(struct audio_stream_out *stream, float left,
3190 float right)
3191{
Eric Laurenta9024de2013-04-04 09:19:12 -07003192 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003193 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003194
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003195 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07003196 /* only take left channel into account: the API is for stereo anyway */
3197 out->muted = (left == 0.0f);
3198 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003199 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003200 pthread_mutex_lock(&out->compr_mute_lock);
3201 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3202 if (!out->a2dp_compress_mute)
3203 ret = set_compr_volume(stream, left, right);
3204 out->volume_l = left;
3205 out->volume_r = right;
3206 pthread_mutex_unlock(&out->compr_mute_lock);
3207 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07003208 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07003209 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3210 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3211 if (!out->standby) {
3212 // if in standby, cached volume will be sent after stream is opened
3213 audio_extn_utils_send_app_type_gain(out->dev,
3214 out->app_type_cfg.app_type,
3215 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07003216 }
vivek mehtaa68fea62017-06-08 19:04:02 -07003217 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003218 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003219
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003220 return -ENOSYS;
3221}
3222
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003223// note: this call is safe only if the stream_cb is
3224// removed first in close_output_stream (as is done now).
3225static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3226{
3227 if (!stream || !parms)
3228 return;
3229
3230 struct stream_out *out = (struct stream_out *)stream;
3231 struct audio_device *adev = out->dev;
3232
3233 card_status_t status;
3234 int card;
3235 if (parse_snd_card_status(parms, &card, &status) < 0)
3236 return;
3237
3238 pthread_mutex_lock(&adev->lock);
3239 bool valid_cb = (card == adev->snd_card);
3240 pthread_mutex_unlock(&adev->lock);
3241
3242 if (!valid_cb)
3243 return;
3244
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003245 lock_output_stream(out);
3246 if (out->card_status != status)
3247 out->card_status = status;
3248 pthread_mutex_unlock(&out->lock);
3249
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07003250 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
3251 use_case_table[out->usecase],
3252 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3253
3254 if (status == CARD_STATUS_OFFLINE)
3255 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003256
3257 return;
3258}
3259
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003260#ifdef NO_AUDIO_OUT
3261static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003262 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003263{
3264 struct stream_out *out = (struct stream_out *)stream;
3265
3266 /* No Output device supported other than BT for playback.
3267 * Sleep for the amount of buffer duration
3268 */
Eric Laurenta1478072015-09-21 17:21:52 -07003269 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003270 usleep(bytes * 1000000 / audio_stream_out_frame_size(
3271 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003272 out_get_sample_rate(&out->stream.common));
3273 pthread_mutex_unlock(&out->lock);
3274 return bytes;
3275}
3276#endif
3277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3279 size_t bytes)
3280{
3281 struct stream_out *out = (struct stream_out *)stream;
3282 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003283 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07003284 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285
Eric Laurenta1478072015-09-21 17:21:52 -07003286 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07003287 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07003288 const size_t frame_size = audio_stream_out_frame_size(stream);
3289 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003290
Eric Laurent0e46adf2016-12-16 12:49:24 -08003291 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3292 error_code = ERROR_CODE_WRITE;
3293 goto exit;
3294 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003295
3296 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3297 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003298 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003299 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3300 ret = -EIO;
3301 goto exit;
3302 }
3303 }
3304 }
3305
Andy Hung572633e2019-02-19 11:58:24 -08003306 const bool was_in_standby = out->standby;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003308 out->standby = false;
Andy Hung241e36f2019-02-19 12:00:38 -08003309 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
3310
Eric Laurent150dbfe2013-02-27 14:31:02 -08003311 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003313
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003314 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003315 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003316 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003317 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318 goto exit;
3319 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003320
vivek mehta40125092017-08-21 18:48:51 -07003321 // after standby always force set last known cal step
3322 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3323 ALOGD("%s: retry previous failed cal level set", __func__);
3324 send_gain_dep_calibration_l();
3325 pthread_mutex_unlock(&adev->lock);
Andy Hung572633e2019-02-19 11:58:24 -08003326
Andy Hung241e36f2019-02-19 12:00:38 -08003327 // log startup time in ms.
3328 simple_stats_log(
3329 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Andy Hung572633e2019-02-19 11:58:24 -08003330 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003332
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003333 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003334 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003335 if (out->send_new_metadata) {
3336 ALOGVV("send new gapless metadata");
3337 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3338 out->send_new_metadata = 0;
3339 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003340 unsigned int avail;
3341 struct timespec tstamp;
3342 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3343 /* Do not limit write size if the available frames count is unknown */
3344 if (ret != 0) {
3345 avail = bytes;
3346 }
3347 if (avail == 0) {
3348 ret = 0;
3349 } else {
Andy Hung572633e2019-02-19 11:58:24 -08003350 // check for compressed format underrun, essentially an empty buffer check
3351 // for a lack of better measurement.
3352 if (!was_in_standby && avail == out->kernel_buffer_size) {
3353 ALOGW("%s: compressed buffer empty (underrun)", __func__);
3354 simple_stats_log(&out->fifo_underruns, 1.); // Note: log one frame for compressed.
3355 }
3356
Eric Laurentb49b3f62016-02-29 17:59:49 -08003357 if (avail > bytes) {
3358 avail = bytes;
3359 }
3360 ret = compress_write(out->compr, buffer, avail);
3361 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3362 __func__, avail, ret);
3363 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003364
Eric Laurent6e895242013-09-05 16:10:57 -07003365 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003366 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3367 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003368 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003369 compress_start(out->compr);
3370 out->playback_started = 1;
3371 out->offload_state = OFFLOAD_STATE_PLAYING;
3372 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003373 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003374 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003375 } else {
3376 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003377 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003378 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003379 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003380 return ret;
3381 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003382 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003383 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003384 size_t bytes_to_write = bytes;
3385
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003386 if (out->muted)
3387 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003388 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003389 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003390 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3391 int16_t *src = (int16_t *)buffer;
3392 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003393
Eric Laurentad2dde92017-09-20 18:27:31 -07003394 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3395 out->format != AUDIO_FORMAT_PCM_16_BIT,
3396 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003397
Eric Laurentad2dde92017-09-20 18:27:31 -07003398 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3399 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3400 }
3401 bytes_to_write /= 2;
3402 }
Andy Hung572633e2019-02-19 11:58:24 -08003403
3404 // Note: since out_get_presentation_position() is called alternating with out_write()
3405 // by AudioFlinger, we can check underruns using the prior timestamp read.
3406 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
3407 if (out->last_fifo_valid) {
3408 // compute drain to see if there is an underrun.
3409 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
3410 const int64_t frames_by_time =
3411 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
3412 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
3413
3414 if (underrun > 0) {
3415 simple_stats_log(&out->fifo_underruns, underrun);
3416
3417 ALOGW("%s: underrun(%lld) "
3418 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
3419 __func__,
3420 (long long)out->fifo_underruns.n,
3421 (long long)frames_by_time,
3422 (long long)out->last_fifo_frames_remaining);
3423 }
3424 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
3425 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003426
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003427 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003428 request_out_focus(out, ns);
3429
3430 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003431 if (use_mmap) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003432 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003433 } else {
3434 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3435 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3436 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
3437 size_t frame_size = channel_count * bytes_per_sample;
3438 size_t frame_count = bytes_to_write / frame_size;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003439
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003440 bool force_haptic_path =
3441 property_get_bool("vendor.audio.test_haptic", false);
3442
3443 // extract Haptics data from Audio buffer
3444 bool alloc_haptic_buffer = false;
3445 int haptic_channel_count = adev->haptics_config.channels;
3446 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
3447 size_t audio_frame_size = frame_size - haptic_frame_size;
3448 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
3449
3450 if (adev->haptic_buffer == NULL) {
3451 alloc_haptic_buffer = true;
3452 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
3453 free(adev->haptic_buffer);
3454 adev->haptic_buffer_size = 0;
3455 alloc_haptic_buffer = true;
3456 }
3457
3458 if (alloc_haptic_buffer) {
3459 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
3460 adev->haptic_buffer_size = total_haptic_buffer_size;
3461 }
3462
3463 size_t src_index = 0, aud_index = 0, hap_index = 0;
3464 uint8_t *audio_buffer = (uint8_t *)buffer;
3465 uint8_t *haptic_buffer = adev->haptic_buffer;
3466
3467 // This is required for testing only. This works for stereo data only.
3468 // One channel is fed to audio stream and other to haptic stream for testing.
3469 if (force_haptic_path) {
3470 audio_frame_size = haptic_frame_size = bytes_per_sample;
3471 }
3472
3473 for (size_t i = 0; i < frame_count; i++) {
3474 for (size_t j = 0; j < audio_frame_size; j++)
3475 audio_buffer[aud_index++] = audio_buffer[src_index++];
3476
3477 for (size_t j = 0; j < haptic_frame_size; j++)
3478 haptic_buffer[hap_index++] = audio_buffer[src_index++];
3479 }
3480
3481 // This is required for testing only.
3482 // Discard haptic channel data.
3483 if (force_haptic_path) {
3484 src_index += haptic_frame_size;
3485 }
3486
3487 // write to audio pipeline
3488 ret = pcm_write(out->pcm,
3489 (void *)audio_buffer,
3490 frame_count * audio_frame_size);
3491
3492 // write to haptics pipeline
3493 if (adev->haptic_pcm)
3494 ret = pcm_write(adev->haptic_pcm,
3495 (void *)adev->haptic_buffer,
3496 frame_count * haptic_frame_size);
3497
3498 } else {
3499 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
3500 }
3501 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003502 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003503 } else {
3504 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003505 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506 }
3507
3508exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003509 // For PCM we always consume the buffer and return #bytes regardless of ret.
3510 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003511 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003512 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003513 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003514
Andy Hung7401c7c2016-09-21 12:41:21 -07003515 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003516 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003517 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3518 ALOGE_IF(out->pcm != NULL,
3519 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003520 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003521 // usleep not guaranteed for values over 1 second but we don't limit here.
3522 }
3523 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525 pthread_mutex_unlock(&out->lock);
3526
3527 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003528 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003529 if (sleeptime_us != 0)
3530 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 }
3532 return bytes;
3533}
3534
3535static int out_get_render_position(const struct audio_stream_out *stream,
3536 uint32_t *dsp_frames)
3537{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003538 struct stream_out *out = (struct stream_out *)stream;
3539 *dsp_frames = 0;
3540 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003541 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003542 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003543 unsigned long frames = 0;
3544 // TODO: check return value
3545 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3546 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003547 ALOGVV("%s rendered frames %d sample_rate %d",
3548 __func__, *dsp_frames, out->sample_rate);
3549 }
3550 pthread_mutex_unlock(&out->lock);
3551 return 0;
3552 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003553 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554}
3555
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003556static int out_add_audio_effect(const struct audio_stream *stream __unused,
3557 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003558{
3559 return 0;
3560}
3561
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003562static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3563 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564{
3565 return 0;
3566}
3567
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003568static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3569 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003571 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572}
3573
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003574static int out_get_presentation_position(const struct audio_stream_out *stream,
3575 uint64_t *frames, struct timespec *timestamp)
3576{
3577 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003578 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003579 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003580
Eric Laurenta1478072015-09-21 17:21:52 -07003581 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003582
Eric Laurent949a0892013-09-20 09:20:13 -07003583 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3584 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003585 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003586 compress_get_tstamp(out->compr, &dsp_frames,
3587 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003588 // Adjustment accounts for A2DP encoder latency with offload usecases
3589 // Note: Encoder latency is returned in ms.
3590 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3591 unsigned long offset =
3592 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3593 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3594 }
Eric Laurent949a0892013-09-20 09:20:13 -07003595 ALOGVV("%s rendered frames %ld sample_rate %d",
3596 __func__, dsp_frames, out->sample_rate);
3597 *frames = dsp_frames;
3598 ret = 0;
3599 /* this is the best we can do */
3600 clock_gettime(CLOCK_MONOTONIC, timestamp);
3601 }
3602 } else {
3603 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003604 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003605 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
Andy Hung572633e2019-02-19 11:58:24 -08003606
3607 // pcm_get_htimestamp() computes the available frames by comparing
3608 // the alsa driver hw_ptr and the appl_ptr levels.
3609 // In underrun, the hw_ptr may keep running and report an excessively
3610 // large number available number.
3611 if (avail > out->kernel_buffer_size) {
3612 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
3613 __func__, avail, out->kernel_buffer_size);
3614 avail = out->kernel_buffer_size;
3615 out->last_fifo_frames_remaining = 0;
3616 } else {
3617 out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
3618 }
3619 out->last_fifo_valid = true;
3620 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
3621
3622 int64_t signed_frames = out->written - out->last_fifo_frames_remaining;
3623
3624 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
3625 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
3626
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003627 // This adjustment accounts for buffering after app processor.
3628 // It is based on estimated DSP latency per use case, rather than exact.
3629 signed_frames -=
3630 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3631
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003632 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3633 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3634 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3635 signed_frames -=
3636 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3637 }
3638
Eric Laurent949a0892013-09-20 09:20:13 -07003639 // It would be unusual for this value to be negative, but check just in case ...
3640 if (signed_frames >= 0) {
3641 *frames = signed_frames;
3642 ret = 0;
3643 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003644 }
3645 }
3646 }
3647
3648 pthread_mutex_unlock(&out->lock);
3649
3650 return ret;
3651}
3652
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003653static int out_set_callback(struct audio_stream_out *stream,
3654 stream_callback_t callback, void *cookie)
3655{
3656 struct stream_out *out = (struct stream_out *)stream;
3657
3658 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003659 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003660 out->offload_callback = callback;
3661 out->offload_cookie = cookie;
3662 pthread_mutex_unlock(&out->lock);
3663 return 0;
3664}
3665
3666static int out_pause(struct audio_stream_out* stream)
3667{
3668 struct stream_out *out = (struct stream_out *)stream;
3669 int status = -ENOSYS;
3670 ALOGV("%s", __func__);
3671 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003672 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003673 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3674 status = compress_pause(out->compr);
3675 out->offload_state = OFFLOAD_STATE_PAUSED;
3676 }
3677 pthread_mutex_unlock(&out->lock);
3678 }
3679 return status;
3680}
3681
3682static int out_resume(struct audio_stream_out* stream)
3683{
3684 struct stream_out *out = (struct stream_out *)stream;
3685 int status = -ENOSYS;
3686 ALOGV("%s", __func__);
3687 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3688 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003689 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003690 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3691 status = compress_resume(out->compr);
3692 out->offload_state = OFFLOAD_STATE_PLAYING;
3693 }
3694 pthread_mutex_unlock(&out->lock);
3695 }
3696 return status;
3697}
3698
3699static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3700{
3701 struct stream_out *out = (struct stream_out *)stream;
3702 int status = -ENOSYS;
3703 ALOGV("%s", __func__);
3704 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003705 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003706 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3707 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3708 else
3709 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3710 pthread_mutex_unlock(&out->lock);
3711 }
3712 return status;
3713}
3714
3715static int out_flush(struct audio_stream_out* stream)
3716{
3717 struct stream_out *out = (struct stream_out *)stream;
3718 ALOGV("%s", __func__);
3719 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003720 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003721 stop_compressed_output_l(out);
3722 pthread_mutex_unlock(&out->lock);
3723 return 0;
3724 }
3725 return -ENOSYS;
3726}
3727
Eric Laurent0e46adf2016-12-16 12:49:24 -08003728static int out_stop(const struct audio_stream_out* stream)
3729{
3730 struct stream_out *out = (struct stream_out *)stream;
3731 struct audio_device *adev = out->dev;
3732 int ret = -ENOSYS;
3733
3734 ALOGV("%s", __func__);
3735 pthread_mutex_lock(&adev->lock);
3736 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3737 out->playback_started && out->pcm != NULL) {
3738 pcm_stop(out->pcm);
3739 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003740 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003741 }
3742 pthread_mutex_unlock(&adev->lock);
3743 return ret;
3744}
3745
3746static int out_start(const struct audio_stream_out* stream)
3747{
3748 struct stream_out *out = (struct stream_out *)stream;
3749 struct audio_device *adev = out->dev;
3750 int ret = -ENOSYS;
3751
3752 ALOGV("%s", __func__);
3753 pthread_mutex_lock(&adev->lock);
3754 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3755 !out->playback_started && out->pcm != NULL) {
3756 ret = start_output_stream(out);
3757 if (ret == 0) {
3758 out->playback_started = true;
3759 }
3760 }
3761 pthread_mutex_unlock(&adev->lock);
3762 return ret;
3763}
3764
Phil Burkbc991042017-02-24 08:06:44 -08003765/*
3766 * Modify config->period_count based on min_size_frames
3767 */
3768static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3769{
3770 int periodCountRequested = (min_size_frames + config->period_size - 1)
3771 / config->period_size;
3772 int periodCount = MMAP_PERIOD_COUNT_MIN;
3773
3774 ALOGV("%s original config.period_size = %d config.period_count = %d",
3775 __func__, config->period_size, config->period_count);
3776
3777 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3778 periodCount *= 2;
3779 }
3780 config->period_count = periodCount;
3781
3782 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3783}
3784
Eric Laurent0e46adf2016-12-16 12:49:24 -08003785static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3786 int32_t min_size_frames,
3787 struct audio_mmap_buffer_info *info)
3788{
3789 struct stream_out *out = (struct stream_out *)stream;
3790 struct audio_device *adev = out->dev;
3791 int ret = 0;
3792 unsigned int offset1;
3793 unsigned int frames1;
3794 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003795 uint32_t mmap_size;
3796 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003797
3798 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003799 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003800 pthread_mutex_lock(&adev->lock);
3801
3802 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003803 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003804 ret = -EINVAL;
3805 goto exit;
3806 }
3807 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003808 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003809 ret = -ENOSYS;
3810 goto exit;
3811 }
3812 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3813 if (out->pcm_device_id < 0) {
3814 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3815 __func__, out->pcm_device_id, out->usecase);
3816 ret = -EINVAL;
3817 goto exit;
3818 }
Phil Burkbc991042017-02-24 08:06:44 -08003819
3820 adjust_mmap_period_count(&out->config, min_size_frames);
3821
Eric Laurent0e46adf2016-12-16 12:49:24 -08003822 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3823 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3824 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3825 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3826 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3827 step = "open";
3828 ret = -ENODEV;
3829 goto exit;
3830 }
3831 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3832 if (ret < 0) {
3833 step = "begin";
3834 goto exit;
3835 }
3836 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003837 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003838 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003839 ret = platform_get_mmap_data_fd(adev->platform,
3840 out->pcm_device_id, 0 /*playback*/,
3841 &info->shared_memory_fd,
3842 &mmap_size);
3843 if (ret < 0) {
3844 // Fall back to non exclusive mode
3845 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3846 } else {
3847 if (mmap_size < buffer_size) {
3848 step = "mmap";
3849 goto exit;
3850 }
3851 // FIXME: indicate exclusive mode support by returning a negative buffer size
3852 info->buffer_size_frames *= -1;
3853 }
3854 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003855
3856 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3857 if (ret < 0) {
3858 step = "commit";
3859 goto exit;
3860 }
Phil Burkbc991042017-02-24 08:06:44 -08003861
3862 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003863 ret = 0;
3864
3865 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3866 __func__, info->shared_memory_address, info->buffer_size_frames);
3867
3868exit:
3869 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003870 if (out->pcm == NULL) {
3871 ALOGE("%s: %s - %d", __func__, step, ret);
3872 } else {
3873 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003874 pcm_close(out->pcm);
3875 out->pcm = NULL;
3876 }
3877 }
3878 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003879 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003880 return ret;
3881}
3882
3883static int out_get_mmap_position(const struct audio_stream_out *stream,
3884 struct audio_mmap_position *position)
3885{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003886 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003887 struct stream_out *out = (struct stream_out *)stream;
3888 ALOGVV("%s", __func__);
3889 if (position == NULL) {
3890 return -EINVAL;
3891 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003892 lock_output_stream(out);
3893 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3894 out->pcm == NULL) {
3895 ret = -ENOSYS;
3896 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003897 }
3898
3899 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003900 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003901 if (ret < 0) {
3902 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003903 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003904 }
Andy Hungfc044e12017-03-20 09:24:22 -07003905 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003906exit:
3907 pthread_mutex_unlock(&out->lock);
3908 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003909}
3910
3911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912/** audio_stream_in implementation **/
3913static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3914{
3915 struct stream_in *in = (struct stream_in *)stream;
3916
3917 return in->config.rate;
3918}
3919
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003920static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003921{
3922 return -ENOSYS;
3923}
3924
3925static size_t in_get_buffer_size(const struct audio_stream *stream)
3926{
3927 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003928 return in->config.period_size * in->af_period_multiplier *
3929 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930}
3931
3932static uint32_t in_get_channels(const struct audio_stream *stream)
3933{
3934 struct stream_in *in = (struct stream_in *)stream;
3935
3936 return in->channel_mask;
3937}
3938
vivek mehta4ed66e62016-04-15 23:33:34 -07003939static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003940{
vivek mehta4ed66e62016-04-15 23:33:34 -07003941 struct stream_in *in = (struct stream_in *)stream;
3942 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003943}
3944
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003945static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946{
3947 return -ENOSYS;
3948}
3949
3950static int in_standby(struct audio_stream *stream)
3951{
3952 struct stream_in *in = (struct stream_in *)stream;
3953 struct audio_device *adev = in->dev;
3954 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003955 bool do_stop = true;
3956
Eric Laurent994a6932013-07-17 11:51:42 -07003957 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003958
3959 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003960
3961 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003962 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003963 audio_extn_sound_trigger_stop_lab(in);
3964 in->standby = true;
3965 }
3966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003967 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003968 if (adev->adm_deregister_stream)
3969 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3970
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003971 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003972 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003973 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003974 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003975 in->capture_started = false;
3976 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003977 if (in->pcm) {
3978 pcm_close(in->pcm);
3979 in->pcm = NULL;
3980 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003981 adev->enable_voicerx = false;
3982 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003983 if (do_stop) {
3984 status = stop_input_stream(in);
3985 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003986 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003987 }
3988 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003989 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003990 return status;
3991}
3992
Andy Hungd13f0d32017-06-12 13:58:37 -07003993static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003994{
Andy Hungd13f0d32017-06-12 13:58:37 -07003995 struct stream_in *in = (struct stream_in *)stream;
3996
3997 // We try to get the lock for consistency,
3998 // but it isn't necessary for these variables.
3999 // If we're not in standby, we may be blocked on a read.
4000 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
4001 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
4002 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
4003 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
4004
Andy Hung241e36f2019-02-19 12:00:38 -08004005 char buffer[256]; // for statistics formatting
4006 if (in->start_latency_ms.n > 0) {
4007 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
4008 dprintf(fd, " Start latency ms: %s\n", buffer);
4009 }
4010
Andy Hungd13f0d32017-06-12 13:58:37 -07004011 if (locked) {
4012 pthread_mutex_unlock(&in->lock);
4013 }
4014
4015 // dump error info
4016 (void)error_log_dump(
4017 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004018 return 0;
4019}
4020
4021static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4022{
4023 struct stream_in *in = (struct stream_in *)stream;
4024 struct audio_device *adev = in->dev;
4025 struct str_parms *parms;
4026 char *str;
4027 char value[32];
4028 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07004029 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004030
Eric Laurent994a6932013-07-17 11:51:42 -07004031 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004032 parms = str_parms_create_str(kvpairs);
4033
4034 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4035
Eric Laurenta1478072015-09-21 17:21:52 -07004036 lock_input_stream(in);
4037
Eric Laurent150dbfe2013-02-27 14:31:02 -08004038 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004039 if (ret >= 0) {
4040 val = atoi(value);
4041 /* no audio source uses val == 0 */
4042 if ((in->source != val) && (val != 0)) {
4043 in->source = val;
4044 }
4045 }
4046
4047 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07004048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004049 if (ret >= 0) {
4050 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07004051 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004052
4053 // Workaround: If routing to an non existing usb device, fail gracefully
4054 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07004055 int card;
4056 if (audio_is_usb_in_device(val) &&
4057 (card = get_alive_usb_card(parms)) >= 0) {
4058
4059 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004060 status = -ENOSYS;
4061 } else {
4062
4063 in->device = val;
4064 /* If recording is in progress, change the tx device to new device */
4065 if (!in->standby) {
4066 ALOGV("update input routing change");
4067 // inform adm before actual routing to prevent glitches.
4068 if (adev->adm_on_routing_change) {
4069 adev->adm_on_routing_change(adev->adm_data,
4070 in->capture_handle);
4071 }
4072 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07004073 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004074 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004075 }
4076 }
4077
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004078 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004079 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004080
4081 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07004082 ALOGV("%s: exit: status(%d)", __func__, status);
4083 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004084}
4085
Haynes Mathew George569b7482017-05-08 14:44:27 -07004086static char* in_get_parameters(const struct audio_stream *stream,
4087 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004088{
Haynes Mathew George569b7482017-05-08 14:44:27 -07004089 struct stream_in *in = (struct stream_in *)stream;
4090 struct str_parms *query = str_parms_create_str(keys);
4091 char *str;
4092 struct str_parms *reply = str_parms_create();
4093 bool replied = false;
4094
4095 ALOGV("%s: enter: keys - %s", __func__, keys);
4096 replied |= stream_get_parameter_channels(query, reply,
4097 &in->supported_channel_masks[0]);
4098 replied |= stream_get_parameter_formats(query, reply,
4099 &in->supported_formats[0]);
4100 replied |= stream_get_parameter_rates(query, reply,
4101 &in->supported_sample_rates[0]);
4102 if (replied) {
4103 str = str_parms_to_str(reply);
4104 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07004105 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07004106 }
4107 str_parms_destroy(query);
4108 str_parms_destroy(reply);
4109 ALOGV("%s: exit: returns - %s", __func__, str);
4110 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004111}
4112
Eric Laurent51f3c662018-04-10 18:21:34 -07004113static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004114{
Eric Laurent51f3c662018-04-10 18:21:34 -07004115 struct stream_in *in = (struct stream_in *)stream;
4116 char mixer_ctl_name[128];
4117 struct mixer_ctl *ctl;
4118 int ctl_value;
4119
4120 ALOGV("%s: gain %f", __func__, gain);
4121
4122 if (stream == NULL)
4123 return -EINVAL;
4124
4125 /* in_set_gain() only used to silence MMAP capture for now */
4126 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
4127 return -ENOSYS;
4128
4129 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
4130
4131 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
4132 if (!ctl) {
4133 ALOGW("%s: Could not get ctl for mixer cmd - %s",
4134 __func__, mixer_ctl_name);
4135 return -ENOSYS;
4136 }
4137
4138 if (gain < RECORD_GAIN_MIN)
4139 gain = RECORD_GAIN_MIN;
4140 else if (gain > RECORD_GAIN_MAX)
4141 gain = RECORD_GAIN_MAX;
4142 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
4143
4144 mixer_ctl_set_value(ctl, 0, ctl_value);
4145 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004146}
4147
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004148static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4149{
4150 if (!stream || !parms)
4151 return;
4152
4153 struct stream_in *in = (struct stream_in *)stream;
4154 struct audio_device *adev = in->dev;
4155
4156 card_status_t status;
4157 int card;
4158 if (parse_snd_card_status(parms, &card, &status) < 0)
4159 return;
4160
4161 pthread_mutex_lock(&adev->lock);
4162 bool valid_cb = (card == adev->snd_card);
4163 pthread_mutex_unlock(&adev->lock);
4164
4165 if (!valid_cb)
4166 return;
4167
4168 lock_input_stream(in);
4169 if (in->card_status != status)
4170 in->card_status = status;
4171 pthread_mutex_unlock(&in->lock);
4172
4173 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4174 use_case_table[in->usecase],
4175 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4176
4177 // a better solution would be to report error back to AF and let
4178 // it put the stream to standby
4179 if (status == CARD_STATUS_OFFLINE)
4180 in_standby(&in->stream.common);
4181
4182 return;
4183}
4184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004185static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4186 size_t bytes)
4187{
4188 struct stream_in *in = (struct stream_in *)stream;
4189 struct audio_device *adev = in->dev;
4190 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07004191 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07004192 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004193
Eric Laurenta1478072015-09-21 17:21:52 -07004194 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004195 const size_t frame_size = audio_stream_in_frame_size(stream);
4196 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07004197
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004198 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004199 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004200 /* Read from sound trigger HAL */
4201 audio_extn_sound_trigger_read(in, buffer, bytes);
4202 pthread_mutex_unlock(&in->lock);
4203 return bytes;
4204 }
4205
Eric Laurent0e46adf2016-12-16 12:49:24 -08004206 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4207 ret = -ENOSYS;
4208 goto exit;
4209 }
4210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004211 if (in->standby) {
Andy Hung241e36f2019-02-19 12:00:38 -08004212 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
4213
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004214 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004215 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004216 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004217 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004218 goto exit;
4219 }
4220 in->standby = 0;
Andy Hung241e36f2019-02-19 12:00:38 -08004221
4222 // log startup time in ms.
4223 simple_stats_log(
4224 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004225 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004226
Andy Hungd13f0d32017-06-12 13:58:37 -07004227 // errors that occur here are read errors.
4228 error_code = ERROR_CODE_READ;
4229
Haynes Mathew George03c40102016-01-29 17:57:48 -08004230 //what's the duration requested by the client?
4231 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4232 in->config.rate;
4233 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004234
Haynes Mathew George03c40102016-01-29 17:57:48 -08004235 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004236 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08004237 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004238 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07004239 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004240 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004241 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004242 if (ret < 0) {
4243 ALOGE("Failed to read w/err %s", strerror(errno));
4244 ret = -errno;
4245 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004246 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4247 if (bytes % 4 == 0) {
4248 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4249 int_buf_stream = buffer;
4250 for (size_t itt=0; itt < bytes/4 ; itt++) {
4251 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07004252 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004253 } else {
4254 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
4255 ret = -EINVAL;
4256 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07004257 }
4258 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004259 }
4260
Haynes Mathew George03c40102016-01-29 17:57:48 -08004261 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004263 /*
4264 * Instead of writing zeroes here, we could trust the hardware
4265 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004266 * 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 -08004267 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08004268 if (ret == 0 && adev->mic_muted &&
4269 !voice_is_in_call_rec_stream(in) &&
4270 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004271 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07004272 in->frames_muted += frames;
4273 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004274
4275exit:
4276 pthread_mutex_unlock(&in->lock);
4277
4278 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07004279 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004280 in_standby(&in->stream.common);
4281 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004282 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08004283 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07004284 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08004285 }
4286 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07004287 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004288 }
4289 return bytes;
4290}
4291
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004292static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004293{
4294 return 0;
4295}
4296
Andy Hung6ebe5962016-01-15 17:46:57 -08004297static int in_get_capture_position(const struct audio_stream_in *stream,
4298 int64_t *frames, int64_t *time)
4299{
4300 if (stream == NULL || frames == NULL || time == NULL) {
4301 return -EINVAL;
4302 }
4303 struct stream_in *in = (struct stream_in *)stream;
4304 int ret = -ENOSYS;
4305
4306 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004307 // note: ST sessions do not close the alsa pcm driver synchronously
4308 // on standby. Therefore, we may return an error even though the
4309 // pcm stream is still opened.
4310 if (in->standby) {
4311 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
4312 "%s stream in standby but pcm not NULL for non ST session", __func__);
4313 goto exit;
4314 }
Andy Hung6ebe5962016-01-15 17:46:57 -08004315 if (in->pcm) {
4316 struct timespec timestamp;
4317 unsigned int avail;
4318 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
4319 *frames = in->frames_read + avail;
4320 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
4321 ret = 0;
4322 }
4323 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004324exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08004325 pthread_mutex_unlock(&in->lock);
4326 return ret;
4327}
4328
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004329static int add_remove_audio_effect(const struct audio_stream *stream,
4330 effect_handle_t effect,
4331 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004332{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004333 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004334 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004335 int status = 0;
4336 effect_descriptor_t desc;
4337
4338 status = (*effect)->get_descriptor(effect, &desc);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004339 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
4340
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004341 if (status != 0)
4342 return status;
4343
Eric Laurenta1478072015-09-21 17:21:52 -07004344 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004345 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07004346 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07004347 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07004348 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004349 in->enable_aec != enable &&
4350 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4351 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004352 if (!enable)
4353 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07004354 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
4355 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
4356 adev->enable_voicerx = enable;
4357 struct audio_usecase *usecase;
4358 struct listnode *node;
4359 list_for_each(node, &adev->usecase_list) {
4360 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07004361 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07004362 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05004363 }
4364 }
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004365 if (!in->standby
4366 && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004367 select_devices(in->dev, in->usecase);
4368 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004369 if (in->enable_ns != enable &&
4370 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4371 in->enable_ns = enable;
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004372 if (!in->standby) {
4373 if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
4374 || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
4375 select_devices(in->dev, in->usecase);
4376 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004377 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004378 pthread_mutex_unlock(&in->dev->lock);
4379 pthread_mutex_unlock(&in->lock);
4380
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381 return 0;
4382}
4383
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004384static int in_add_audio_effect(const struct audio_stream *stream,
4385 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004386{
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, true);
4389}
4390
4391static int in_remove_audio_effect(const struct audio_stream *stream,
4392 effect_handle_t effect)
4393{
Eric Laurent994a6932013-07-17 11:51:42 -07004394 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004395 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004396}
4397
Eric Laurent0e46adf2016-12-16 12:49:24 -08004398static int in_stop(const struct audio_stream_in* stream)
4399{
4400 struct stream_in *in = (struct stream_in *)stream;
4401 struct audio_device *adev = in->dev;
4402
4403 int ret = -ENOSYS;
4404 ALOGV("%s", __func__);
4405 pthread_mutex_lock(&adev->lock);
4406 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4407 in->capture_started && in->pcm != NULL) {
4408 pcm_stop(in->pcm);
4409 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08004410 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004411 }
4412 pthread_mutex_unlock(&adev->lock);
4413 return ret;
4414}
4415
4416static int in_start(const struct audio_stream_in* stream)
4417{
4418 struct stream_in *in = (struct stream_in *)stream;
4419 struct audio_device *adev = in->dev;
4420 int ret = -ENOSYS;
4421
4422 ALOGV("%s in %p", __func__, in);
4423 pthread_mutex_lock(&adev->lock);
4424 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4425 !in->capture_started && in->pcm != NULL) {
4426 if (!in->capture_started) {
4427 ret = start_input_stream(in);
4428 if (ret == 0) {
4429 in->capture_started = true;
4430 }
4431 }
4432 }
4433 pthread_mutex_unlock(&adev->lock);
4434 return ret;
4435}
4436
Phil Burkc4714fc2019-02-16 22:28:11 -08004437// Read offset for the input positional timestamp from a property.
4438// This is to workaround apparent inaccuracies in the timing info that
4439// are causing glitches.
4440static int64_t in_get_mmap_time_offset() {
4441 // Roughly 100 usec is needed on some devices to cover inaccuracy in DSP.
4442 // This should be set in a property. But I cannot read the property!
4443 // So I am setting the offset here to 101 as a test.
4444 const int32_t kDefaultOffsetMicros = 101; // should be zero if no bug
4445 // FIXME - why is the property not being read?! The default is used.
4446 int32_t mmap_time_offset_micros = property_get_int32(
4447 "persist.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
4448 ALOGI("in_get_mmap_time_offset set to %d micros", mmap_time_offset_micros);
4449 return mmap_time_offset_micros * (int64_t)1000;
4450}
4451
Eric Laurent0e46adf2016-12-16 12:49:24 -08004452static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4453 int32_t min_size_frames,
4454 struct audio_mmap_buffer_info *info)
4455{
4456 struct stream_in *in = (struct stream_in *)stream;
4457 struct audio_device *adev = in->dev;
4458 int ret = 0;
4459 unsigned int offset1;
4460 unsigned int frames1;
4461 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004462 uint32_t mmap_size;
4463 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004464
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004465 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004466 pthread_mutex_lock(&adev->lock);
4467 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004468
Eric Laurent0e46adf2016-12-16 12:49:24 -08004469 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004470 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004471 ret = -EINVAL;
4472 goto exit;
4473 }
4474 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004475 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004476 ALOGV("%s in %p", __func__, in);
4477 ret = -ENOSYS;
4478 goto exit;
4479 }
4480 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4481 if (in->pcm_device_id < 0) {
4482 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4483 __func__, in->pcm_device_id, in->usecase);
4484 ret = -EINVAL;
4485 goto exit;
4486 }
Phil Burkbc991042017-02-24 08:06:44 -08004487
4488 adjust_mmap_period_count(&in->config, min_size_frames);
4489
Eric Laurent0e46adf2016-12-16 12:49:24 -08004490 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4491 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4492 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4493 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4494 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4495 step = "open";
4496 ret = -ENODEV;
4497 goto exit;
4498 }
4499
4500 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4501 if (ret < 0) {
4502 step = "begin";
4503 goto exit;
4504 }
4505 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004506 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004507 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004508 ret = platform_get_mmap_data_fd(adev->platform,
4509 in->pcm_device_id, 1 /*capture*/,
4510 &info->shared_memory_fd,
4511 &mmap_size);
4512 if (ret < 0) {
4513 // Fall back to non exclusive mode
4514 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4515 } else {
4516 if (mmap_size < buffer_size) {
4517 step = "mmap";
4518 goto exit;
4519 }
4520 // FIXME: indicate exclusive mode support by returning a negative buffer size
4521 info->buffer_size_frames *= -1;
4522 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004523
Haynes Mathew George96483a22017-03-28 14:52:47 -07004524 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004525
4526 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4527 if (ret < 0) {
4528 step = "commit";
4529 goto exit;
4530 }
4531
Phil Burkc4714fc2019-02-16 22:28:11 -08004532 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
4533
Phil Burkbc991042017-02-24 08:06:44 -08004534 in->standby = false;
4535 ret = 0;
4536
Eric Laurent0e46adf2016-12-16 12:49:24 -08004537 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4538 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004539
4540exit:
4541 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004542 if (in->pcm == NULL) {
4543 ALOGE("%s: %s - %d", __func__, step, ret);
4544 } else {
4545 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004546 pcm_close(in->pcm);
4547 in->pcm = NULL;
4548 }
4549 }
4550 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004551 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004552 return ret;
4553}
4554
4555static int in_get_mmap_position(const struct audio_stream_in *stream,
4556 struct audio_mmap_position *position)
4557{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004558 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004559 struct stream_in *in = (struct stream_in *)stream;
4560 ALOGVV("%s", __func__);
4561 if (position == NULL) {
4562 return -EINVAL;
4563 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004564 lock_input_stream(in);
4565 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4566 in->pcm == NULL) {
4567 ret = -ENOSYS;
4568 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004569 }
4570 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004571 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004572 if (ret < 0) {
4573 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004574 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004575 }
Andy Hungfc044e12017-03-20 09:24:22 -07004576 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Phil Burkc4714fc2019-02-16 22:28:11 -08004577 position->time_nanoseconds += in->mmap_time_offset_nanos;
4578
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004579exit:
4580 pthread_mutex_unlock(&in->lock);
4581 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004582}
4583
jiabin8962a4d2018-03-19 18:21:24 -07004584static int in_get_active_microphones(const struct audio_stream_in *stream,
4585 struct audio_microphone_characteristic_t *mic_array,
4586 size_t *mic_count) {
4587 struct stream_in *in = (struct stream_in *)stream;
4588 struct audio_device *adev = in->dev;
4589 ALOGVV("%s", __func__);
4590
4591 lock_input_stream(in);
4592 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004593 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004594 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004595 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004596 pthread_mutex_unlock(&adev->lock);
4597 pthread_mutex_unlock(&in->lock);
4598
4599 return ret;
4600}
4601
4602static int adev_get_microphones(const struct audio_hw_device *dev,
4603 struct audio_microphone_characteristic_t *mic_array,
4604 size_t *mic_count) {
4605 struct audio_device *adev = (struct audio_device *)dev;
4606 ALOGVV("%s", __func__);
4607
4608 pthread_mutex_lock(&adev->lock);
4609 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4610 pthread_mutex_unlock(&adev->lock);
4611
4612 return ret;
4613}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004614
Paul McLean57530d52018-12-17 08:24:21 -07004615static int in_set_microphone_direction(const struct audio_stream_in *stream,
4616 audio_microphone_direction_t dir) {
justinwengc6347db2019-02-21 18:49:00 +08004617 struct stream_in *in = (struct stream_in *)stream;
4618
4619 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4620
4621 in->direction = dir;
4622
4623 if (in->standby)
4624 return 0;
4625
4626 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLean57530d52018-12-17 08:24:21 -07004627}
4628
4629static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinwengc6347db2019-02-21 18:49:00 +08004630 struct stream_in *in = (struct stream_in *)stream;
4631
4632 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4633
4634 if (zoom > 1.0 || zoom < -1.0)
4635 return -EINVAL;
4636
4637 in->zoom = zoom;
4638
4639 if (in->standby)
4640 return 0;
4641
4642 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLean57530d52018-12-17 08:24:21 -07004643}
4644
juyuchenba338cd2019-01-21 11:57:17 +08004645static void in_update_sink_metadata(struct audio_stream_in *stream,
4646 const struct sink_metadata *sink_metadata) {
4647
4648 if (stream == NULL
4649 || sink_metadata == NULL
4650 || sink_metadata->tracks == NULL) {
4651 return;
4652 }
4653
4654 int error = 0;
4655 struct stream_in *in = (struct stream_in *)stream;
4656 struct audio_device *adev = in->dev;
4657 audio_devices_t device = AUDIO_DEVICE_NONE;
4658
4659 if (sink_metadata->track_count != 0)
4660 device = sink_metadata->tracks->dest_device;
4661
4662 lock_input_stream(in);
4663 pthread_mutex_lock(&adev->lock);
4664 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
4665
4666 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
4667 && device != AUDIO_DEVICE_NONE
4668 && adev->voice_tx_output != NULL) {
4669 /* Use the rx device from afe-proxy record to route voice call because
4670 there is no routing if tx device is on primary hal and rx device
4671 is on other hal during voice call. */
4672 adev->voice_tx_output->devices = device;
4673
4674 if (!voice_is_call_state_active(adev)) {
4675 if (adev->mode == AUDIO_MODE_IN_CALL) {
4676 adev->current_call_output = adev->voice_tx_output;
4677 error = voice_start_call(adev);
4678 if (error != 0)
4679 ALOGE("%s: start voice call failed %d", __func__, error);
4680 }
4681 } else {
4682 adev->current_call_output = adev->voice_tx_output;
4683 voice_update_devices_for_all_voice_usecases(adev);
4684 }
4685 }
4686
4687 pthread_mutex_unlock(&adev->lock);
4688 pthread_mutex_unlock(&in->lock);
4689}
4690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004691static int adev_open_output_stream(struct audio_hw_device *dev,
4692 audio_io_handle_t handle,
4693 audio_devices_t devices,
4694 audio_output_flags_t flags,
4695 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004696 struct audio_stream_out **stream_out,
4697 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004698{
4699 struct audio_device *adev = (struct audio_device *)dev;
4700 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004701 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004702 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4703 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4704 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004705 bool force_haptic_path =
4706 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707
Andy Hungd9653bd2017-08-01 19:31:39 -07004708 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4709 return -ENOSYS;
4710 }
4711
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004712 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4713 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004715 *stream_out = NULL;
4716 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4717
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004718 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4719
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004720 if (devices == AUDIO_DEVICE_NONE)
4721 devices = AUDIO_DEVICE_OUT_SPEAKER;
4722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004723 out->flags = flags;
4724 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004725 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004726 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004727 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004728
4729 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004730 if ((is_hdmi || is_usb_dev) &&
4731 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4732 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4733 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004734 audio_format_t req_format = config->format;
4735 audio_channel_mask_t req_channel_mask = config->channel_mask;
4736 uint32_t req_sample_rate = config->sample_rate;
4737
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004738 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004739 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004740 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004741 if (config->sample_rate == 0)
4742 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004743 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004744 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4745 if (config->format == AUDIO_FORMAT_DEFAULT)
4746 config->format = AUDIO_FORMAT_PCM_16_BIT;
4747 } else if (is_usb_dev) {
4748 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4749 &config->format,
4750 &out->supported_formats[0],
4751 MAX_SUPPORTED_FORMATS,
4752 &config->channel_mask,
4753 &out->supported_channel_masks[0],
4754 MAX_SUPPORTED_CHANNEL_MASKS,
4755 &config->sample_rate,
4756 &out->supported_sample_rates[0],
4757 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004758 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004759 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004760 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004761 if (ret != 0) {
4762 // For MMAP NO IRQ, allow conversions in ADSP
4763 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4764 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004765
Eric Laurentab805ee2018-03-30 12:20:38 -07004766 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4767 config->sample_rate = req_sample_rate;
4768 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4769 config->channel_mask = req_channel_mask;
4770 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4771 config->format = req_format;
4772 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004773
Haynes Mathew George569b7482017-05-08 14:44:27 -07004774 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004775 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004776 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004777 if (is_hdmi) {
4778 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4779 out->config = pcm_config_hdmi_multi;
4780 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4781 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4782 out->config = pcm_config_mmap_playback;
4783 out->stream.start = out_start;
4784 out->stream.stop = out_stop;
4785 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4786 out->stream.get_mmap_position = out_get_mmap_position;
4787 } else {
4788 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4789 out->config = pcm_config_hifi;
4790 }
4791
4792 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004793 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004794 if (is_hdmi) {
4795 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4796 audio_bytes_per_sample(out->format));
4797 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004798 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004799 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004800 pthread_mutex_lock(&adev->lock);
4801 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4802 pthread_mutex_unlock(&adev->lock);
4803
4804 // reject offload during card offline to allow
4805 // fallback to s/w paths
4806 if (offline) {
4807 ret = -ENODEV;
4808 goto error_open;
4809 }
4810
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004811 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4812 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4813 ALOGE("%s: Unsupported Offload information", __func__);
4814 ret = -EINVAL;
4815 goto error_open;
4816 }
4817 if (!is_supported_format(config->offload_info.format)) {
4818 ALOGE("%s: Unsupported audio format", __func__);
4819 ret = -EINVAL;
4820 goto error_open;
4821 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004822 out->sample_rate = config->offload_info.sample_rate;
4823 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4824 out->channel_mask = config->offload_info.channel_mask;
4825 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4826 out->channel_mask = config->channel_mask;
4827 else
4828 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4829
4830 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004831
4832 out->compr_config.codec = (struct snd_codec *)
4833 calloc(1, sizeof(struct snd_codec));
4834
4835 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004836
4837 out->stream.set_callback = out_set_callback;
4838 out->stream.pause = out_pause;
4839 out->stream.resume = out_resume;
4840 out->stream.drain = out_drain;
4841 out->stream.flush = out_flush;
4842
4843 out->compr_config.codec->id =
4844 get_snd_codec_id(config->offload_info.format);
4845 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4846 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004847 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004848 out->compr_config.codec->bit_rate =
4849 config->offload_info.bit_rate;
4850 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004851 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004852 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4853
4854 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4855 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004856
4857 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004858 create_offload_callback_thread(out);
4859 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4860 __func__, config->offload_info.version,
4861 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004862 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4863 switch (config->sample_rate) {
4864 case 0:
4865 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4866 break;
4867 case 8000:
4868 case 16000:
4869 case 48000:
4870 out->sample_rate = config->sample_rate;
4871 break;
4872 default:
4873 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4874 config->sample_rate);
4875 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4876 ret = -EINVAL;
4877 goto error_open;
4878 }
4879 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4880 switch (config->channel_mask) {
4881 case AUDIO_CHANNEL_NONE:
4882 case AUDIO_CHANNEL_OUT_STEREO:
4883 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4884 break;
4885 default:
4886 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4887 config->channel_mask);
4888 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4889 ret = -EINVAL;
4890 goto error_open;
4891 }
4892 switch (config->format) {
4893 case AUDIO_FORMAT_DEFAULT:
4894 case AUDIO_FORMAT_PCM_16_BIT:
4895 out->format = AUDIO_FORMAT_PCM_16_BIT;
4896 break;
4897 default:
4898 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4899 config->format);
4900 config->format = AUDIO_FORMAT_PCM_16_BIT;
4901 ret = -EINVAL;
4902 goto error_open;
4903 }
4904
4905 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004906 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004907 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004908 case 0:
4909 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4910 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004911 case 8000:
4912 case 16000:
4913 case 48000:
4914 out->sample_rate = config->sample_rate;
4915 break;
4916 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004917 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4918 config->sample_rate);
4919 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4920 ret = -EINVAL;
4921 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004922 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004923 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4924 switch (config->channel_mask) {
4925 case AUDIO_CHANNEL_NONE:
4926 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4927 break;
4928 case AUDIO_CHANNEL_OUT_STEREO:
4929 out->channel_mask = config->channel_mask;
4930 break;
4931 default:
4932 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4933 config->channel_mask);
4934 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4935 ret = -EINVAL;
4936 break;
4937 }
4938 switch (config->format) {
4939 case AUDIO_FORMAT_DEFAULT:
4940 out->format = AUDIO_FORMAT_PCM_16_BIT;
4941 break;
4942 case AUDIO_FORMAT_PCM_16_BIT:
4943 out->format = config->format;
4944 break;
4945 default:
4946 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4947 config->format);
4948 config->format = AUDIO_FORMAT_PCM_16_BIT;
4949 ret = -EINVAL;
4950 break;
4951 }
4952 if (ret != 0)
4953 goto error_open;
4954
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004955 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4956 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004957 out->config.rate = out->sample_rate;
4958 out->config.channels =
4959 audio_channel_count_from_out_mask(out->channel_mask);
4960 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004961 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004962 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4963 switch (config->sample_rate) {
4964 case 0:
4965 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4966 break;
4967 case 8000:
4968 case 16000:
4969 case 32000:
4970 case 48000:
4971 out->sample_rate = config->sample_rate;
4972 break;
4973 default:
4974 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4975 config->sample_rate);
4976 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4977 ret = -EINVAL;
4978 break;
4979 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004980 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004981 switch (config->channel_mask) {
4982 case AUDIO_CHANNEL_NONE:
4983 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4984 break;
4985 case AUDIO_CHANNEL_OUT_STEREO:
4986 out->channel_mask = config->channel_mask;
4987 break;
4988 default:
4989 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4990 config->channel_mask);
4991 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4992 ret = -EINVAL;
4993 break;
4994 }
4995 switch (config->format) {
4996 case AUDIO_FORMAT_DEFAULT:
4997 out->format = AUDIO_FORMAT_PCM_16_BIT;
4998 break;
4999 case AUDIO_FORMAT_PCM_16_BIT:
5000 out->format = config->format;
5001 break;
5002 default:
5003 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
5004 config->format);
5005 config->format = AUDIO_FORMAT_PCM_16_BIT;
5006 ret = -EINVAL;
5007 break;
5008 }
5009 if (ret != 0)
5010 goto error_open;
5011
vivek mehtaa68fea62017-06-08 19:04:02 -07005012 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07005013 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5014 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005015 out->config.rate = out->sample_rate;
5016 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07005017 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005018 out->sample_rate,
5019 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07005020 out->config.channels,
5021 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005022 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07005023 out->config.period_size = buffer_size / frame_size;
5024 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
5025 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005026 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005027 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07005028 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5029 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005030 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07005031 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
5032 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005033 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07005034 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005035 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005036 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005037 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08005038 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5039 out->config = pcm_config_mmap_playback;
5040 out->stream.start = out_start;
5041 out->stream.stop = out_stop;
5042 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5043 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005044 } else {
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005045 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5046 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
5047 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
5048 if (adev->haptic_pcm_device_id < 0) {
5049 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
5050 __func__, adev->haptic_pcm_device_id, out->usecase);
5051 ret = -ENOSYS;
5052 goto error_open;
5053 }
5054 out->config = pcm_config_haptics_audio;
5055 if (force_haptic_path)
5056 adev->haptics_config = pcm_config_haptics_audio;
5057 else
5058 adev->haptics_config = pcm_config_haptics;
5059 } else {
5060 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
5061 out->config = pcm_config_low_latency;
5062 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07005063 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005064
5065 if (config->sample_rate == 0) {
5066 out->sample_rate = out->config.rate;
5067 } else {
5068 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005069 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005070
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005071 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
5072 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
5073 } else {
5074 out->channel_mask = config->channel_mask;
5075 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005076
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005077 if (config->format == AUDIO_FORMAT_DEFAULT)
5078 out->format = audio_format_from_pcm_format(out->config.format);
5079 else if (!audio_is_linear_pcm(config->format)) {
5080 config->format = AUDIO_FORMAT_PCM_16_BIT;
5081 ret = -EINVAL;
5082 goto error_open;
5083 } else {
5084 out->format = config->format;
5085 }
5086
5087 out->config.rate = out->sample_rate;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005088
5089 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5090 out->config.channels =
5091 audio_channel_count_from_out_mask(out->channel_mask &
5092 ~AUDIO_CHANNEL_HAPTIC_ALL);
5093
5094 if (force_haptic_path) {
5095 out->config.channels = 1;
5096 adev->haptics_config.channels = 1;
5097 } else {
5098 adev->haptics_config.channels =
5099 audio_channel_count_from_out_mask(out->channel_mask &
5100 AUDIO_CHANNEL_HAPTIC_ALL);
5101 }
5102 } else {
5103 out->config.channels =
5104 audio_channel_count_from_out_mask(out->channel_mask);
5105 }
5106
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005107 if (out->format != audio_format_from_pcm_format(out->config.format)) {
5108 out->config.format = pcm_format_from_audio_format(out->format);
5109 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005110 }
Kevin Rocard50eff892017-05-02 16:52:05 -07005111
5112 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
5113 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005114 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07005115 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
5116 __func__, config->sample_rate, config->format, config->channel_mask);
5117 config->sample_rate = out->sample_rate;
5118 config->format = out->format;
5119 config->channel_mask = out->channel_mask;
5120 ret = -EINVAL;
5121 goto error_open;
5122 }
5123
Andy Hung6fcba9c2014-03-18 11:53:32 -07005124 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
5125 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005126
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005127 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005128 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005129 adev->primary_output = out;
5130 else {
5131 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005132 ret = -EEXIST;
5133 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005134 }
5135 }
5136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005137 /* Check if this usecase is already existing */
5138 pthread_mutex_lock(&adev->lock);
5139 if (get_usecase_from_list(adev, out->usecase) != NULL) {
5140 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005141 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005142 ret = -EEXIST;
5143 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005144 }
5145 pthread_mutex_unlock(&adev->lock);
5146
5147 out->stream.common.get_sample_rate = out_get_sample_rate;
5148 out->stream.common.set_sample_rate = out_set_sample_rate;
5149 out->stream.common.get_buffer_size = out_get_buffer_size;
5150 out->stream.common.get_channels = out_get_channels;
5151 out->stream.common.get_format = out_get_format;
5152 out->stream.common.set_format = out_set_format;
5153 out->stream.common.standby = out_standby;
5154 out->stream.common.dump = out_dump;
5155 out->stream.common.set_parameters = out_set_parameters;
5156 out->stream.common.get_parameters = out_get_parameters;
5157 out->stream.common.add_audio_effect = out_add_audio_effect;
5158 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5159 out->stream.get_latency = out_get_latency;
5160 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005161#ifdef NO_AUDIO_OUT
5162 out->stream.write = out_write_for_no_output;
5163#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005164 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005165#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005166 out->stream.get_render_position = out_get_render_position;
5167 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005168 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005169
Eric Laurent0e46adf2016-12-16 12:49:24 -08005170 if (out->realtime)
5171 out->af_period_multiplier = af_period_multiplier;
5172 else
5173 out->af_period_multiplier = 1;
5174
Andy Hung572633e2019-02-19 11:58:24 -08005175 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
5176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005177 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005178 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005179 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005180
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005181 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005182 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005183 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005185 config->format = out->stream.common.get_format(&out->stream.common);
5186 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5187 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5188
Kevin Rocarda325aa22018-04-03 09:15:52 -07005189 register_format(out->format, out->supported_formats);
5190 register_channel_mask(out->channel_mask, out->supported_channel_masks);
5191 register_sample_rate(out->sample_rate, out->supported_sample_rates);
5192
Andy Hunga452b0a2017-03-15 14:51:15 -07005193 out->error_log = error_log_create(
5194 ERROR_LOG_ENTRIES,
5195 1000000000 /* aggregate consecutive identical errors within one second in ns */);
5196
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005197 /*
5198 By locking output stream before registering, we allow the callback
5199 to update stream's state only after stream's initial state is set to
5200 adev state.
5201 */
5202 lock_output_stream(out);
5203 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5204 pthread_mutex_lock(&adev->lock);
5205 out->card_status = adev->card_status;
5206 pthread_mutex_unlock(&adev->lock);
5207 pthread_mutex_unlock(&out->lock);
5208
vivek mehta4a824772017-06-08 19:05:49 -07005209 stream_app_type_cfg_init(&out->app_type_cfg);
5210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005211 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005212
Eric Laurent994a6932013-07-17 11:51:42 -07005213 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005214 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005215
5216error_open:
5217 free(out);
5218 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07005219 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005220 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005221}
5222
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005223static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005224 struct audio_stream_out *stream)
5225{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005226 struct stream_out *out = (struct stream_out *)stream;
5227 struct audio_device *adev = out->dev;
5228
Eric Laurent994a6932013-07-17 11:51:42 -07005229 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005230
5231 // must deregister from sndmonitor first to prevent races
5232 // between the callback and close_stream
5233 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005234 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005235 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
5236 destroy_offload_callback_thread(out);
5237
5238 if (out->compr_config.codec != NULL)
5239 free(out->compr_config.codec);
5240 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005241
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005242 out->a2dp_compress_mute = false;
5243
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005244 if (adev->voice_tx_output == out)
5245 adev->voice_tx_output = NULL;
5246
Andy Hunga452b0a2017-03-15 14:51:15 -07005247 error_log_destroy(out->error_log);
5248 out->error_log = NULL;
5249
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005250 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005251 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005252 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005253 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005254 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005255}
5256
5257static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5258{
5259 struct audio_device *adev = (struct audio_device *)dev;
5260 struct str_parms *parms;
5261 char *str;
5262 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005263 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005264 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07005265 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005266 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005267
Joe Onorato188b6222016-03-01 11:02:27 -08005268 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005269
5270 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005271
5272 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005273 status = voice_set_parameters(adev, parms);
5274 if (status != 0) {
5275 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005276 }
5277
5278 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5279 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07005280 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005281 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5282 adev->bluetooth_nrec = true;
5283 else
5284 adev->bluetooth_nrec = false;
5285 }
5286
5287 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5288 if (ret >= 0) {
5289 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5290 adev->screen_off = false;
5291 else
5292 adev->screen_off = true;
5293 }
5294
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005295 ret = str_parms_get_int(parms, "rotation", &val);
5296 if (ret >= 0) {
5297 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005298 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005299 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005300 // FIXME: note that the code below assumes that the speakers are in the correct placement
5301 // relative to the user when the device is rotated 90deg from its default rotation. This
5302 // assumption is device-specific, not platform-specific like this code.
5303 case 270:
5304 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005305 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005306 break;
5307 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005308 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07005309 camera_rotation = CAMERA_ROTATION_PORTRAIT;
5310 break;
5311 case 90:
5312 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005313 break;
5314 default:
5315 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07005316 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005317 }
Eric Laurent03f09432014-03-25 18:09:11 -07005318 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07005319 // check and set swap
5320 // - check if orientation changed and speaker active
5321 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07005322 adev->camera_orientation =
5323 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
5324#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07005325 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07005326#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005327 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005328 }
5329
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005330 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5331 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005332 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005333 }
5334
David Linee3fe402017-03-13 10:00:42 -07005335 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5336 if (ret >= 0) {
5337 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005338 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005339 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5340 if (ret >= 0) {
5341 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005342 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005343 }
Eric Laurent99dab492017-06-17 15:19:08 -07005344 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005345 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5346 if (ret >= 0) {
5347 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005348 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005349 }
5350 }
5351 }
5352
5353 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5354 if (ret >= 0) {
5355 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005356 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005357 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5358 if (ret >= 0) {
5359 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005360 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005361 }
Eric Laurent99dab492017-06-17 15:19:08 -07005362 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005363 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5364 if (ret >= 0) {
5365 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005366 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005367 }
5368 }
5369 }
5370
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08005371 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08005372 audio_extn_ma_set_parameters(adev, parms);
5373
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005374 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
5375 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005376 struct audio_usecase *usecase;
5377 struct listnode *node;
5378 list_for_each(node, &adev->usecase_list) {
5379 usecase = node_to_item(node, struct audio_usecase, list);
5380 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005381 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005382 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
5383
5384 pthread_mutex_unlock(&adev->lock);
5385 lock_output_stream(usecase->stream.out);
5386 pthread_mutex_lock(&adev->lock);
5387 audio_extn_a2dp_set_handoff_mode(true);
5388 // force device switch to reconfigure encoder
5389 select_devices(adev, usecase->id);
5390 audio_extn_a2dp_set_handoff_mode(false);
5391 pthread_mutex_unlock(&usecase->stream.out->lock);
5392 break;
5393 }
5394 }
5395 }
5396
Eric Laurent5f4ca952018-10-19 17:33:43 -07005397 //FIXME: to be replaced by proper video capture properties API
5398 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
5399 if (ret >= 0) {
5400 int camera_facing = CAMERA_FACING_BACK;
5401 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
5402 camera_facing = CAMERA_FACING_FRONT;
5403 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
5404 camera_facing = CAMERA_FACING_BACK;
5405 else {
5406 ALOGW("%s: invalid camera facing value: %s", __func__, value);
5407 goto done;
5408 }
5409 adev->camera_orientation =
5410 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
5411 struct audio_usecase *usecase;
5412 struct listnode *node;
5413 list_for_each(node, &adev->usecase_list) {
5414 usecase = node_to_item(node, struct audio_usecase, list);
5415 struct stream_in *in = usecase->stream.in;
5416 if (usecase->type == PCM_CAPTURE && in != NULL &&
5417 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
5418 select_devices(adev, in->usecase);
5419 }
5420 }
5421 }
5422
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005423done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005424 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005425 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07005426 ALOGV("%s: exit with code(%d)", __func__, status);
5427 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005428}
5429
5430static char* adev_get_parameters(const struct audio_hw_device *dev,
5431 const char *keys)
5432{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005433 struct audio_device *adev = (struct audio_device *)dev;
5434 struct str_parms *reply = str_parms_create();
5435 struct str_parms *query = str_parms_create_str(keys);
5436 char *str;
5437
5438 pthread_mutex_lock(&adev->lock);
5439
5440 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005441 audio_extn_a2dp_get_parameters(query, reply);
5442
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005443 str = str_parms_to_str(reply);
5444 str_parms_destroy(query);
5445 str_parms_destroy(reply);
5446
5447 pthread_mutex_unlock(&adev->lock);
5448 ALOGV("%s: exit: returns - %s", __func__, str);
5449 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005450}
5451
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005452static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005453{
5454 return 0;
5455}
5456
Haynes Mathew George5191a852013-09-11 14:19:36 -07005457static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5458{
5459 int ret;
5460 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005461
Eric Laurent4cc4ce12014-09-10 13:21:01 -05005462 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
5463
Haynes Mathew George5191a852013-09-11 14:19:36 -07005464 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005465 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005466 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005467
Haynes Mathew George5191a852013-09-11 14:19:36 -07005468 return ret;
5469}
5470
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005471static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005472{
5473 return -ENOSYS;
5474}
5475
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005476static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5477 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005478{
5479 return -ENOSYS;
5480}
5481
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005482static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005483{
5484 return -ENOSYS;
5485}
5486
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005487static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005488{
5489 return -ENOSYS;
5490}
5491
5492static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5493{
5494 struct audio_device *adev = (struct audio_device *)dev;
5495
5496 pthread_mutex_lock(&adev->lock);
5497 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07005498 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005499 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005500 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
5501 voice_is_in_call(adev)) {
5502 voice_stop_call(adev);
5503 adev->current_call_output = NULL;
5504 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005505 }
5506 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05005507
5508 audio_extn_extspk_set_mode(adev->extspk, mode);
5509
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005510 return 0;
5511}
5512
5513static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5514{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005515 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005516 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005517
Eric Laurent2bafff12016-03-17 12:17:23 -07005518 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005519 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005520 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
5521 ret = audio_extn_hfp_set_mic_mute(adev, state);
5522 } else {
5523 ret = voice_set_mic_mute(adev, state);
5524 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005525 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005526 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005527
5528 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005529}
5530
5531static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5532{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005533 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005534 return 0;
5535}
5536
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005537static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005538 const struct audio_config *config)
5539{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005540 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005541
Eric Laurent74b55762017-07-09 17:04:53 -07005542 /* Don't know if USB HIFI in this context so use true to be conservative */
5543 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5544 true /*is_usb_hifi */) != 0)
5545 return 0;
5546
vivek mehtaa68fea62017-06-08 19:04:02 -07005547 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5548 config->sample_rate, config->format,
5549 channel_count,
5550 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005551}
5552
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005553static bool adev_input_allow_hifi_record(struct audio_device *adev,
5554 audio_devices_t devices,
5555 audio_input_flags_t flags,
5556 audio_source_t source) {
5557 const bool allowed = true;
5558
5559 if (!audio_is_usb_in_device(devices))
5560 return !allowed;
5561
5562 switch (flags) {
5563 case AUDIO_INPUT_FLAG_NONE:
5564 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5565 break;
5566 default:
5567 return !allowed;
5568 }
5569
5570 switch (source) {
5571 case AUDIO_SOURCE_DEFAULT:
5572 case AUDIO_SOURCE_MIC:
5573 case AUDIO_SOURCE_UNPROCESSED:
5574 break;
5575 default:
5576 return !allowed;
5577 }
5578
5579 switch (adev->mode) {
5580 case 0:
5581 break;
5582 default:
5583 return !allowed;
5584 }
5585
5586 return allowed;
5587}
5588
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005589static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005590 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005591 audio_devices_t devices,
5592 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005593 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005594 audio_input_flags_t flags,
5595 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005596 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005597{
5598 struct audio_device *adev = (struct audio_device *)dev;
5599 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005600 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005601 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005602 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005603 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005604 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5605 devices,
5606 flags,
5607 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005608 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5609 " sample_rate %u, channel_mask %#x, format %#x",
5610 __func__, flags, is_usb_dev, may_use_hifi_record,
5611 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005612 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005613
Andy Hungd9653bd2017-08-01 19:31:39 -07005614 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5615 return -ENOSYS;
5616 }
5617
Eric Laurent74b55762017-07-09 17:04:53 -07005618 if (!(is_usb_dev && may_use_hifi_record)) {
5619 if (config->sample_rate == 0)
5620 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5621 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5622 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5623 if (config->format == AUDIO_FORMAT_DEFAULT)
5624 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005625
Eric Laurent74b55762017-07-09 17:04:53 -07005626 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5627
5628 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5629 return -EINVAL;
5630 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005631
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005632 if (audio_extn_tfa_98xx_is_supported() &&
5633 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005634 return -EINVAL;
5635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005636 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5637
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005638 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005639 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005640
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005641 in->stream.common.get_sample_rate = in_get_sample_rate;
5642 in->stream.common.set_sample_rate = in_set_sample_rate;
5643 in->stream.common.get_buffer_size = in_get_buffer_size;
5644 in->stream.common.get_channels = in_get_channels;
5645 in->stream.common.get_format = in_get_format;
5646 in->stream.common.set_format = in_set_format;
5647 in->stream.common.standby = in_standby;
5648 in->stream.common.dump = in_dump;
5649 in->stream.common.set_parameters = in_set_parameters;
5650 in->stream.common.get_parameters = in_get_parameters;
5651 in->stream.common.add_audio_effect = in_add_audio_effect;
5652 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5653 in->stream.set_gain = in_set_gain;
5654 in->stream.read = in_read;
5655 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005656 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005657 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLean57530d52018-12-17 08:24:21 -07005658 in->stream.set_microphone_direction = in_set_microphone_direction;
5659 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchenba338cd2019-01-21 11:57:17 +08005660 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005661
5662 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005663 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005664 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005665 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005666 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005667 in->flags = flags;
justinwengc6347db2019-02-21 18:49:00 +08005668 in->direction = MIC_DIRECTION_UNSPECIFIED;
5669 in->zoom = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005670
Andy Hung88ce1d92018-10-29 18:31:12 -07005671 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005672 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5673 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5674 /* Force channel config requested to mono if incall
5675 record is being requested for only uplink/downlink */
5676 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5677 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5678 ret = -EINVAL;
5679 goto err_open;
5680 }
5681 }
5682
Haynes Mathew George569b7482017-05-08 14:44:27 -07005683 if (is_usb_dev && may_use_hifi_record) {
5684 /* HiFi record selects an appropriate format, channel, rate combo
5685 depending on sink capabilities*/
5686 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5687 &config->format,
5688 &in->supported_formats[0],
5689 MAX_SUPPORTED_FORMATS,
5690 &config->channel_mask,
5691 &in->supported_channel_masks[0],
5692 MAX_SUPPORTED_CHANNEL_MASKS,
5693 &config->sample_rate,
5694 &in->supported_sample_rates[0],
5695 MAX_SUPPORTED_SAMPLE_RATES);
5696 if (ret != 0) {
5697 ret = -EINVAL;
5698 goto err_open;
5699 }
Eric Laurent74b55762017-07-09 17:04:53 -07005700 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005701 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005702 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005703 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5704 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5705 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5706 bool ret_error = false;
5707 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5708 from HAL is 8_24
5709 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5710 8_24 return error indicating supported format is 8_24
5711 *> In case of any other source requesting 24 bit or float return error
5712 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005713
vivek mehta57ff9b52016-04-28 14:13:08 -07005714 on error flinger will retry with supported format passed
5715 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005716 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005717 config->format = AUDIO_FORMAT_PCM_16_BIT;
5718 ret_error = true;
5719 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5720 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5721 ret_error = true;
5722 }
5723
5724 if (ret_error) {
5725 ret = -EINVAL;
5726 goto err_open;
5727 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005728 }
5729
vivek mehta57ff9b52016-04-28 14:13:08 -07005730 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005731 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005732
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005733 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005734 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5735 if (config->sample_rate == 0)
5736 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5737 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5738 config->sample_rate != 8000) {
5739 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5740 ret = -EINVAL;
5741 goto err_open;
5742 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005743
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005744 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5745 config->format = AUDIO_FORMAT_PCM_16_BIT;
5746 ret = -EINVAL;
5747 goto err_open;
5748 }
5749
5750 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5751 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005752 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005753 } else if (is_usb_dev && may_use_hifi_record) {
5754 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5755 in->config = pcm_config_audio_capture;
5756 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005757 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5758 config->sample_rate,
5759 config->format,
5760 channel_count,
5761 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005762 in->config.period_size = buffer_size / frame_size;
5763 in->config.rate = config->sample_rate;
5764 in->af_period_multiplier = 1;
5765 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005766 } else {
5767 in->usecase = USECASE_AUDIO_RECORD;
5768 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005769 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005770 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005771#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005772 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005773#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005774 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005775 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005776 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005777 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005778 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5779 config->sample_rate,
5780 config->format,
5781 channel_count,
5782 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005783 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005784 in->config.rate = config->sample_rate;
5785 in->af_period_multiplier = 1;
5786 } else {
5787 // period size is left untouched for rt mode playback
5788 in->config = pcm_config_audio_capture_rt;
5789 in->af_period_multiplier = af_period_multiplier;
5790 }
5791 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5792 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005793 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005794 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5795 in->config = pcm_config_mmap_capture;
5796 in->stream.start = in_start;
5797 in->stream.stop = in_stop;
5798 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5799 in->stream.get_mmap_position = in_get_mmap_position;
5800 in->af_period_multiplier = 1;
5801 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005802 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005803 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005804 (config->sample_rate == 8000 ||
5805 config->sample_rate == 16000 ||
5806 config->sample_rate == 32000 ||
5807 config->sample_rate == 48000) &&
5808 channel_count == 1) {
5809 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5810 in->config = pcm_config_audio_capture;
5811 frame_size = audio_stream_in_frame_size(&in->stream);
5812 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5813 config->sample_rate,
5814 config->format,
5815 channel_count, false /*is_low_latency*/);
5816 in->config.period_size = buffer_size / frame_size;
5817 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5818 in->config.rate = config->sample_rate;
5819 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005820 } else {
5821 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005822 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005823 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5824 config->sample_rate,
5825 config->format,
5826 channel_count,
5827 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005828 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005829 in->config.rate = config->sample_rate;
5830 in->af_period_multiplier = 1;
5831 }
5832 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5833 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005834 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005836 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005837 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005838
Kevin Rocarda325aa22018-04-03 09:15:52 -07005839
5840 register_format(in->format, in->supported_formats);
5841 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5842 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5843
Andy Hungd13f0d32017-06-12 13:58:37 -07005844 in->error_log = error_log_create(
5845 ERROR_LOG_ENTRIES,
5846 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5847
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005848 /* This stream could be for sound trigger lab,
5849 get sound trigger pcm if present */
5850 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005851
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005852 lock_input_stream(in);
5853 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5854 pthread_mutex_lock(&adev->lock);
5855 in->card_status = adev->card_status;
5856 pthread_mutex_unlock(&adev->lock);
5857 pthread_mutex_unlock(&in->lock);
5858
vivek mehta4a824772017-06-08 19:05:49 -07005859 stream_app_type_cfg_init(&in->app_type_cfg);
5860
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005861 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005862 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005863 return 0;
5864
5865err_open:
5866 free(in);
5867 *stream_in = NULL;
5868 return ret;
5869}
5870
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005871static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005872 struct audio_stream_in *stream)
5873{
Andy Hungd13f0d32017-06-12 13:58:37 -07005874 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005875 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005876
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005877 // must deregister from sndmonitor first to prevent races
5878 // between the callback and close_stream
5879 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005880 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005881
5882 error_log_destroy(in->error_log);
5883 in->error_log = NULL;
5884
Andy Hung0dbb52b2017-08-09 13:51:38 -07005885 pthread_mutex_destroy(&in->pre_lock);
5886 pthread_mutex_destroy(&in->lock);
5887
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005888 free(stream);
5889
5890 return;
5891}
5892
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005893static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005894{
5895 return 0;
5896}
5897
Andy Hung31aca912014-03-20 17:14:59 -07005898/* verifies input and output devices and their capabilities.
5899 *
5900 * This verification is required when enabling extended bit-depth or
5901 * sampling rates, as not all qcom products support it.
5902 *
5903 * Suitable for calling only on initialization such as adev_open().
5904 * It fills the audio_device use_case_table[] array.
5905 *
5906 * Has a side-effect that it needs to configure audio routing / devices
5907 * in order to power up the devices and read the device parameters.
5908 * It does not acquire any hw device lock. Should restore the devices
5909 * back to "normal state" upon completion.
5910 */
5911static int adev_verify_devices(struct audio_device *adev)
5912{
5913 /* enumeration is a bit difficult because one really wants to pull
5914 * the use_case, device id, etc from the hidden pcm_device_table[].
5915 * In this case there are the following use cases and device ids.
5916 *
5917 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5918 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005919 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005920 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5921 * [USECASE_AUDIO_RECORD] = {0, 0},
5922 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5923 * [USECASE_VOICE_CALL] = {2, 2},
5924 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005925 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005926 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5927 */
5928
5929 /* should be the usecases enabled in adev_open_input_stream() */
5930 static const int test_in_usecases[] = {
5931 USECASE_AUDIO_RECORD,
5932 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5933 };
5934 /* should be the usecases enabled in adev_open_output_stream()*/
5935 static const int test_out_usecases[] = {
5936 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5937 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5938 };
5939 static const usecase_type_t usecase_type_by_dir[] = {
5940 PCM_PLAYBACK,
5941 PCM_CAPTURE,
5942 };
5943 static const unsigned flags_by_dir[] = {
5944 PCM_OUT,
5945 PCM_IN,
5946 };
5947
5948 size_t i;
5949 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005950 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005951 char info[512]; /* for possible debug info */
5952
5953 for (dir = 0; dir < 2; ++dir) {
5954 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5955 const unsigned flags_dir = flags_by_dir[dir];
5956 const size_t testsize =
5957 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5958 const int *testcases =
5959 dir ? test_in_usecases : test_out_usecases;
5960 const audio_devices_t audio_device =
5961 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5962
5963 for (i = 0; i < testsize; ++i) {
5964 const audio_usecase_t audio_usecase = testcases[i];
5965 int device_id;
5966 snd_device_t snd_device;
5967 struct pcm_params **pparams;
5968 struct stream_out out;
5969 struct stream_in in;
5970 struct audio_usecase uc_info;
5971 int retval;
5972
5973 pparams = &adev->use_case_table[audio_usecase];
5974 pcm_params_free(*pparams); /* can accept null input */
5975 *pparams = NULL;
5976
5977 /* find the device ID for the use case (signed, for error) */
5978 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5979 if (device_id < 0)
5980 continue;
5981
5982 /* prepare structures for device probing */
5983 memset(&uc_info, 0, sizeof(uc_info));
5984 uc_info.id = audio_usecase;
5985 uc_info.type = usecase_type;
5986 if (dir) {
Andy Hung31aca912014-03-20 17:14:59 -07005987 memset(&in, 0, sizeof(in));
5988 in.device = audio_device;
5989 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5990 uc_info.stream.in = &in;
Andy Hung31aca912014-03-20 17:14:59 -07005991 }
5992 memset(&out, 0, sizeof(out));
5993 out.devices = audio_device; /* only field needed in select_devices */
5994 uc_info.stream.out = &out;
5995 uc_info.devices = audio_device;
5996 uc_info.in_snd_device = SND_DEVICE_NONE;
5997 uc_info.out_snd_device = SND_DEVICE_NONE;
5998 list_add_tail(&adev->usecase_list, &uc_info.list);
5999
6000 /* select device - similar to start_(in/out)put_stream() */
6001 retval = select_devices(adev, audio_usecase);
6002 if (retval >= 0) {
6003 *pparams = pcm_params_get(card_id, device_id, flags_dir);
6004#if LOG_NDEBUG == 0
6005 if (*pparams) {
6006 ALOGV("%s: (%s) card %d device %d", __func__,
6007 dir ? "input" : "output", card_id, device_id);
6008 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07006009 } else {
6010 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
6011 }
6012#endif
6013 }
6014
6015 /* deselect device - similar to stop_(in/out)put_stream() */
6016 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07006017 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07006018 /* 2. Disable the rx device */
6019 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07006020 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07006021 list_remove(&uc_info.list);
6022 }
6023 }
Andy Hung31aca912014-03-20 17:14:59 -07006024 return 0;
6025}
6026
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006027static int adev_close(hw_device_t *device)
6028{
Andy Hung31aca912014-03-20 17:14:59 -07006029 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006030 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006031
6032 if (!adev)
6033 return 0;
6034
6035 pthread_mutex_lock(&adev_init_lock);
6036
6037 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006038 audio_extn_snd_mon_unregister_listener(adev);
6039 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08006040 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006041 audio_route_free(adev->audio_route);
6042 free(adev->snd_dev_ref_cnt);
6043 platform_deinit(adev->platform);
6044 audio_extn_extspk_deinit(adev->extspk);
6045 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006046 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006047 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
6048 pcm_params_free(adev->use_case_table[i]);
6049 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006050 if (adev->adm_deinit)
6051 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07006052 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006053 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07006054 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07006055
6056 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006057
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006058 return 0;
6059}
6060
Glenn Kasten4f993392014-05-14 07:30:48 -07006061/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6062 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6063 * just that it _might_ work.
6064 */
6065static int period_size_is_plausible_for_low_latency(int period_size)
6066{
6067 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006068 case 48:
6069 case 96:
6070 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07006071 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006072 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07006073 case 240:
6074 case 320:
6075 case 480:
6076 return 1;
6077 default:
6078 return 0;
6079 }
6080}
6081
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006082static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
6083{
6084 int card;
6085 card_status_t status;
6086
6087 if (!parms)
6088 return;
6089
6090 if (parse_snd_card_status(parms, &card, &status) < 0)
6091 return;
6092
6093 pthread_mutex_lock(&adev->lock);
6094 bool valid_cb = (card == adev->snd_card);
6095 if (valid_cb) {
6096 if (adev->card_status != status) {
6097 adev->card_status = status;
6098 platform_snd_card_update(adev->platform, status);
6099 }
6100 }
6101 pthread_mutex_unlock(&adev->lock);
6102 return;
6103}
6104
Aniket Kumar Lata26483012018-01-31 20:21:42 -08006105/* out and adev lock held */
6106static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6107{
6108 struct audio_usecase *uc_info;
6109 float left_p;
6110 float right_p;
6111 audio_devices_t devices;
6112
6113 uc_info = get_usecase_from_list(adev, out->usecase);
6114 if (uc_info == NULL) {
6115 ALOGE("%s: Could not find the usecase (%d) in the list",
6116 __func__, out->usecase);
6117 return -EINVAL;
6118 }
6119
6120 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6121 out->usecase, use_case_table[out->usecase]);
6122
6123 if (restore) {
6124 // restore A2DP device for active usecases and unmute if required
6125 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6126 !is_a2dp_device(uc_info->out_snd_device)) {
6127 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
6128 select_devices(adev, uc_info->id);
6129 pthread_mutex_lock(&out->compr_mute_lock);
6130 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6131 (out->a2dp_compress_mute)) {
6132 out->a2dp_compress_mute = false;
6133 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6134 }
6135 pthread_mutex_unlock(&out->compr_mute_lock);
6136 }
6137 } else {
6138 // mute compress stream if suspended
6139 pthread_mutex_lock(&out->compr_mute_lock);
6140 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6141 (!out->a2dp_compress_mute)) {
6142 if (!out->standby) {
6143 ALOGD("%s: selecting speaker and muting stream", __func__);
6144 devices = out->devices;
6145 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6146 left_p = out->volume_l;
6147 right_p = out->volume_r;
6148 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6149 compress_pause(out->compr);
6150 set_compr_volume(&out->stream, 0.0f, 0.0f);
6151 out->a2dp_compress_mute = true;
6152 select_devices(adev, out->usecase);
6153 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6154 compress_resume(out->compr);
6155 out->devices = devices;
6156 out->volume_l = left_p;
6157 out->volume_r = right_p;
6158 }
6159 }
6160 pthread_mutex_unlock(&out->compr_mute_lock);
6161 }
6162 ALOGV("%s: exit", __func__);
6163 return 0;
6164}
6165
6166int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6167{
6168 int ret = 0;
6169
6170 lock_output_stream(out);
6171 pthread_mutex_lock(&adev->lock);
6172
6173 ret = check_a2dp_restore_l(adev, out, restore);
6174
6175 pthread_mutex_unlock(&adev->lock);
6176 pthread_mutex_unlock(&out->lock);
6177 return ret;
6178}
6179
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006180static int adev_open(const hw_module_t *module, const char *name,
6181 hw_device_t **device)
6182{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07006183 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006184
Eric Laurent2bafff12016-03-17 12:17:23 -07006185 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006186 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006187 pthread_mutex_lock(&adev_init_lock);
6188 if (audio_device_ref_count != 0) {
6189 *device = &adev->device.common;
6190 audio_device_ref_count++;
6191 ALOGV("%s: returning existing instance of adev", __func__);
6192 ALOGV("%s: exit", __func__);
6193 pthread_mutex_unlock(&adev_init_lock);
6194 return 0;
6195 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006196 adev = calloc(1, sizeof(struct audio_device));
6197
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006198 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006200 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6201 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6202 adev->device.common.module = (struct hw_module_t *)module;
6203 adev->device.common.close = adev_close;
6204
6205 adev->device.init_check = adev_init_check;
6206 adev->device.set_voice_volume = adev_set_voice_volume;
6207 adev->device.set_master_volume = adev_set_master_volume;
6208 adev->device.get_master_volume = adev_get_master_volume;
6209 adev->device.set_master_mute = adev_set_master_mute;
6210 adev->device.get_master_mute = adev_get_master_mute;
6211 adev->device.set_mode = adev_set_mode;
6212 adev->device.set_mic_mute = adev_set_mic_mute;
6213 adev->device.get_mic_mute = adev_get_mic_mute;
6214 adev->device.set_parameters = adev_set_parameters;
6215 adev->device.get_parameters = adev_get_parameters;
6216 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6217 adev->device.open_output_stream = adev_open_output_stream;
6218 adev->device.close_output_stream = adev_close_output_stream;
6219 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006220
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006221 adev->device.close_input_stream = adev_close_input_stream;
6222 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07006223 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006224
6225 /* Set the default route before the PCM stream is opened */
6226 pthread_mutex_lock(&adev->lock);
6227 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006228 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006229 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006230 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006231 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006232 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006233 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006234 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006235 pthread_mutex_unlock(&adev->lock);
6236
6237 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006238 adev->platform = platform_init(adev);
6239 if (!adev->platform) {
6240 free(adev->snd_dev_ref_cnt);
6241 free(adev);
6242 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6243 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006244 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006245 return -EINVAL;
6246 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05006247 adev->extspk = audio_extn_extspk_init(adev);
6248
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006249 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6250 if (adev->visualizer_lib == NULL) {
6251 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6252 } else {
6253 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6254 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07006255 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006256 "visualizer_hal_start_output");
6257 adev->visualizer_stop_output =
6258 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
6259 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07006260 }
6261
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006262 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6263 if (adev->offload_effects_lib == NULL) {
6264 ALOGW("%s: DLOPEN failed for %s", __func__,
6265 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6266 } else {
6267 ALOGV("%s: DLOPEN successful for %s", __func__,
6268 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6269 adev->offload_effects_start_output =
6270 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6271 "offload_effects_bundle_hal_start_output");
6272 adev->offload_effects_stop_output =
6273 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6274 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07006275 }
6276
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006277 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6278 if (adev->adm_lib == NULL) {
6279 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6280 } else {
6281 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6282 adev->adm_init = (adm_init_t)
6283 dlsym(adev->adm_lib, "adm_init");
6284 adev->adm_deinit = (adm_deinit_t)
6285 dlsym(adev->adm_lib, "adm_deinit");
6286 adev->adm_register_input_stream = (adm_register_input_stream_t)
6287 dlsym(adev->adm_lib, "adm_register_input_stream");
6288 adev->adm_register_output_stream = (adm_register_output_stream_t)
6289 dlsym(adev->adm_lib, "adm_register_output_stream");
6290 adev->adm_deregister_stream = (adm_deregister_stream_t)
6291 dlsym(adev->adm_lib, "adm_deregister_stream");
6292 adev->adm_request_focus = (adm_request_focus_t)
6293 dlsym(adev->adm_lib, "adm_request_focus");
6294 adev->adm_abandon_focus = (adm_abandon_focus_t)
6295 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08006296 adev->adm_set_config = (adm_set_config_t)
6297 dlsym(adev->adm_lib, "adm_set_config");
6298 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6299 dlsym(adev->adm_lib, "adm_request_focus_v2");
6300 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6301 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6302 adev->adm_on_routing_change = (adm_on_routing_change_t)
6303 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006304 }
6305
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006306 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05006307 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006308
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006309 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006310
Andy Hung31aca912014-03-20 17:14:59 -07006311 if (k_enable_extended_precision)
6312 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006313
Glenn Kasten4f993392014-05-14 07:30:48 -07006314 char value[PROPERTY_VALUE_MAX];
6315 int trial;
6316 if (property_get("audio_hal.period_size", value, NULL) > 0) {
6317 trial = atoi(value);
6318 if (period_size_is_plausible_for_low_latency(trial)) {
6319 pcm_config_low_latency.period_size = trial;
6320 pcm_config_low_latency.start_threshold = trial / 4;
6321 pcm_config_low_latency.avail_min = trial / 4;
6322 configured_low_latency_capture_period_size = trial;
6323 }
6324 }
6325 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
6326 trial = atoi(value);
6327 if (period_size_is_plausible_for_low_latency(trial)) {
6328 configured_low_latency_capture_period_size = trial;
6329 }
6330 }
6331
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07006332 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
6333
Eric Laurent5f4ca952018-10-19 17:33:43 -07006334 adev->camera_orientation = CAMERA_DEFAULT;
6335
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006336 // commented as full set of app type cfg is sent from platform
6337 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006338 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08006339
6340 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
6341 af_period_multiplier = atoi(value);
6342 if (af_period_multiplier < 0) {
6343 af_period_multiplier = 2;
6344 } else if (af_period_multiplier > 4) {
6345 af_period_multiplier = 4;
6346 }
6347 ALOGV("new period_multiplier = %d", af_period_multiplier);
6348 }
6349
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006350 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08006351 audio_extn_ma_init(adev->platform);
justinwengc6347db2019-02-21 18:49:00 +08006352 audio_extn_audiozoom_init();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006353
vivek mehta1a9b7c02015-06-25 11:49:38 -07006354 pthread_mutex_unlock(&adev_init_lock);
6355
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006356 if (adev->adm_init)
6357 adev->adm_data = adev->adm_init();
6358
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006359 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006360 audio_extn_snd_mon_init();
6361 pthread_mutex_lock(&adev->lock);
6362 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
6363 adev->card_status = CARD_STATUS_ONLINE;
6364 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006365 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006366
Eric Laurent2bafff12016-03-17 12:17:23 -07006367 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006368 return 0;
6369}
6370
6371static struct hw_module_methods_t hal_module_methods = {
6372 .open = adev_open,
6373};
6374
6375struct audio_module HAL_MODULE_INFO_SYM = {
6376 .common = {
6377 .tag = HARDWARE_MODULE_TAG,
6378 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6379 .hal_api_version = HARDWARE_HAL_API_VERSION,
6380 .id = AUDIO_HARDWARE_MODULE_ID,
6381 .name = "QCOM Audio HAL",
6382 .author = "Code Aurora Forum",
6383 .methods = &hal_module_methods,
6384 },
6385};