blob: 417d7cdb2b6dc03078d8cc5fe7869abefc276ae6 [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
Carter Hsuaaa94962019-05-14 14:26:24 +0800653 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
654
yixuanjiang509f0a72018-09-06 18:37:23 +0800655 if (usecase->type == PCM_CAPTURE)
656 snd_device = usecase->in_snd_device;
657 else
658 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530659 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Chafb2ea2c2019-03-04 18:12:47 +0800660 audio_extn_ma_set_device(usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800661 audio_extn_utils_send_audio_calibration(adev, usecase);
Andy Hung11f10e22018-10-19 17:47:12 -0700662
663 // we shouldn't truncate mixer_path
664 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
665 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
666 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800667 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Andy Hung11f10e22018-10-19 17:47:12 -0700668
Eric Laurent2e140aa2016-06-30 17:14:46 -0700669 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700670 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800672 ALOGV("%s: exit", __func__);
673 return 0;
674}
675
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800676int disable_audio_route(struct audio_device *adev,
677 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800678{
yixuanjiang509f0a72018-09-06 18:37:23 +0800679 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700680 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800681
682 if (usecase == NULL)
683 return -EINVAL;
684
685 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800686 if (usecase->type == PCM_CAPTURE)
687 snd_device = usecase->in_snd_device;
688 else
689 snd_device = usecase->out_snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700690
691 // we shouldn't truncate mixer_path
692 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
693 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
694 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800695 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700696 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Andy Hung11f10e22018-10-19 17:47:12 -0700697
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700698 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000699 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800701 ALOGV("%s: exit", __func__);
702 return 0;
703}
704
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800705int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700706 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800707{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700708 int i, num_devices = 0;
709 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800710 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800711 if (snd_device < SND_DEVICE_MIN ||
712 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800713 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800714 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800715 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700716
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700717 platform_send_audio_calibration(adev->platform, snd_device);
718
vivek mehtade4849c2016-03-03 17:23:38 -0800719 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700720 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700721 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800722 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700723 }
724
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700725 /* due to the possibility of calibration overwrite between listen
726 and audio, notify sound trigger hal before audio calibration is sent */
727 audio_extn_sound_trigger_update_device_status(snd_device,
728 ST_EVENT_SND_DEVICE_BUSY);
729
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700730 if (audio_extn_spkr_prot_is_enabled())
731 audio_extn_spkr_prot_calib_cancel(adev);
732
zhaoyang yin4211fad2015-06-04 21:13:25 +0800733 audio_extn_dsm_feedback_enable(adev, snd_device, true);
734
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700735 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800736 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800737 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700738 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
739 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700740 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800741 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700742 }
743 if (audio_extn_spkr_prot_start_processing(snd_device)) {
744 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800745 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700746 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700747 } else if (platform_can_split_snd_device(snd_device,
748 &num_devices,
749 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700750 for (i = 0; i < num_devices; i++) {
751 enable_snd_device(adev, new_snd_devices[i]);
752 }
vivek mehtab6506412015-08-07 16:55:17 -0700753 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700754 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800755 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
756 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
757 ALOGE(" %s: Invalid sound device returned", __func__);
758 goto on_error;
759 }
Ed Tam70b5c142016-03-21 19:14:29 -0700760
Eric Laurent2e140aa2016-06-30 17:14:46 -0700761 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700762
763 if (is_a2dp_device(snd_device) &&
764 (audio_extn_a2dp_start_playback() < 0)) {
765 ALOGE("%s: failed to configure A2DP control path", __func__);
766 goto on_error;
767 }
768
vivek mehtade4849c2016-03-03 17:23:38 -0800769 audio_route_apply_and_update_path(adev->audio_route, device_name);
770 }
771on_success:
772 adev->snd_dev_ref_cnt[snd_device]++;
773 ret_val = 0;
774on_error:
775 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776}
777
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800778int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700779 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800780{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700781 int i, num_devices = 0;
782 snd_device_t new_snd_devices[2];
783
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800784 if (snd_device < SND_DEVICE_MIN ||
785 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800786 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800787 return -EINVAL;
788 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700789 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
790 ALOGE("%s: device ref cnt is already 0", __func__);
791 return -EINVAL;
792 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800793 audio_extn_tfa_98xx_disable_speaker(snd_device);
794
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700795 adev->snd_dev_ref_cnt[snd_device]--;
796 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800797 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800798
799 if (is_a2dp_device(snd_device))
800 audio_extn_a2dp_stop_playback();
801
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700802 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800803 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700804 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700805 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
806 audio_extn_spkr_prot_is_enabled()) {
807 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700808
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700809 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
810 // and does not use speaker swap. As this code causes a problem with device enable ref
811 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700812 // when speaker device is disabled, reset swap.
813 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700814 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700815
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700816 } else if (platform_can_split_snd_device(snd_device,
817 &num_devices,
818 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700819 for (i = 0; i < num_devices; i++) {
820 disable_snd_device(adev, new_snd_devices[i]);
821 }
vivek mehtab6506412015-08-07 16:55:17 -0700822 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700823 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800824 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
825 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
826 ALOGE(" %s: Invalid sound device returned", __func__);
827 return -EINVAL;
828 }
829
Eric Laurent2e140aa2016-06-30 17:14:46 -0700830 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800831 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700832 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700833 audio_extn_sound_trigger_update_device_status(snd_device,
834 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835 }
vivek mehtab6506412015-08-07 16:55:17 -0700836
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800837 return 0;
838}
839
Vignesh Kulothungan64698822018-01-23 11:25:18 -0800840#ifdef DYNAMIC_ECNS_ENABLED
841static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
842 struct stream_in *in,
843 struct audio_effect_config effect_config,
844 unsigned int param_value)
845{
846 char mixer_ctl_name[] = "Audio Effect";
847 long set_values[6];
848
849 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
850 if (!ctl) {
851 ALOGE("%s: Could not get mixer ctl - %s",
852 __func__, mixer_ctl_name);
853 return -EINVAL;
854 }
855
856 set_values[0] = 1; //0:Rx 1:Tx
857 set_values[1] = in->app_type_cfg.app_type;
858 set_values[2] = (long)effect_config.module_id;
859 set_values[3] = (long)effect_config.instance_id;
860 set_values[4] = (long)effect_config.param_id;
861 set_values[5] = param_value;
862
863 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
864
865 return 0;
866
867}
868
869static int update_effect_param_ecns(struct audio_usecase *usecase,
870 unsigned int module_id, int effect_type,
871 unsigned int *param_value)
872{
873 int ret = 0;
874 struct audio_effect_config other_effect_config;
875 struct stream_in *in = NULL;
876
877 if (!usecase)
878 return -EINVAL;
879
880 in = usecase->stream.in;
881
882 /* Get the effect config data of the other effect */
883 ret = platform_get_effect_config_data(usecase->in_snd_device,
884 &other_effect_config,
885 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
886 if (ret < 0) {
887 ALOGE("%s Failed to get effect params %d", __func__, ret);
888 return ret;
889 }
890
891 if (module_id == other_effect_config.module_id) {
892 //Same module id for AEC/NS. Values need to be combined
893 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
894 ((effect_type == EFFECT_NS) && (in->enable_aec)))
895 *param_value |= other_effect_config.param_value;
896 }
897
898 return ret;
899}
900
901static int enable_disable_effect(struct audio_device *adev, struct stream_in *in,
902 int effect_type, bool enable)
903{
904 struct audio_effect_config effect_config;
905 struct audio_usecase *usecase = NULL;
906 int ret = 0;
907 unsigned int param_value = 0;
908
909 if (!in) {
910 ALOGE("%s: Invalid input stream", __func__);
911 return -EINVAL;
912 }
913
914 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
915
916 usecase = get_usecase_from_list(adev, in->usecase);
917
918 ret = platform_get_effect_config_data(usecase->in_snd_device,
919 &effect_config, effect_type);
920 if (ret < 0) {
921 ALOGE("%s Failed to get module id %d", __func__, ret);
922 return ret;
923 }
924 ALOGV("%s: module %d app_type %d usecase->id:%d usecase->in_snd_device:%d",
925 __func__, effect_config.module_id, in->app_type_cfg.app_type,
926 usecase->id, usecase->in_snd_device);
927
928 if (enable)
929 param_value = effect_config.param_value;
930
931 /*Special handling for AEC & NS effects Param values need to be
932 updated if module ids are same*/
933
934 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
935 ret = update_effect_param_ecns(usecase, effect_config.module_id,
936 effect_type, &param_value);
937 if (ret < 0)
938 return ret;
939 }
940
941 ret = send_effect_enable_disable_mixer_ctl(adev, in,
942 effect_config, param_value);
943
944 return ret;
945}
946
947static int check_and_enable_effect(struct audio_device *adev)
948{
949 int ret = 0;
950
951 struct listnode *node;
952 struct stream_in *in = NULL;
953
954 list_for_each(node, &adev->usecase_list)
955 {
956 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
957 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
958 in = usecase->stream.in;
959
960 if (in->standby)
961 continue;
962
963 if (in->enable_aec) {
964 ret = enable_disable_effect(adev, in, EFFECT_AEC, true);
965 }
966
967 if (in->enable_ns &&
968 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
969 ret = enable_disable_effect(adev, in, EFFECT_NS, true);
970 }
971 }
972 }
973
974 return ret;
975}
976#else
977#define enable_disable_effect(w, x, y, z) -ENOSYS
978#define check_and_enable_effect(x) -ENOSYS
979#endif
980
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700981/*
982 legend:
983 uc - existing usecase
984 new_uc - new usecase
985 d1, d11, d2 - SND_DEVICE enums
986 a1, a2 - corresponding ANDROID device enums
987 B, B1, B2 - backend strings
988
989case 1
990 uc->dev d1 (a1) B1
991 new_uc->dev d1 (a1), d2 (a2) B1, B2
992
993 resolution: disable and enable uc->dev on d1
994
995case 2
996 uc->dev d1 (a1) B1
997 new_uc->dev d11 (a1) B1
998
999 resolution: need to switch uc since d1 and d11 are related
1000 (e.g. speaker and voice-speaker)
1001 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1002
1003case 3
1004 uc->dev d1 (a1) B1
1005 new_uc->dev d2 (a2) B2
1006
1007 resolution: no need to switch uc
1008
1009case 4
1010 uc->dev d1 (a1) B
1011 new_uc->dev d2 (a2) B
1012
1013 resolution: disable enable uc-dev on d2 since backends match
1014 we cannot enable two streams on two different devices if they
1015 share the same backend. e.g. if offload is on speaker device using
1016 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1017 using the same backend, offload must also be switched to voice-handset.
1018
1019case 5
1020 uc->dev d1 (a1) B
1021 new_uc->dev d1 (a1), d2 (a2) B
1022
1023 resolution: disable enable uc-dev on d2 since backends match
1024 we cannot enable two streams on two different devices if they
1025 share the same backend.
1026
1027case 6
1028 uc->dev d1 a1 B1
1029 new_uc->dev d2 a1 B2
1030
1031 resolution: no need to switch
1032
1033case 7
1034
1035 uc->dev d1 (a1), d2 (a2) B1, B2
1036 new_uc->dev d1 B1
1037
1038 resolution: no need to switch
1039
1040*/
1041static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
1042 struct audio_usecase *new_uc,
1043 snd_device_t new_snd_device)
1044{
1045 audio_devices_t a1 = uc->stream.out->devices;
1046 audio_devices_t a2 = new_uc->stream.out->devices;
1047
1048 snd_device_t d1 = uc->out_snd_device;
1049 snd_device_t d2 = new_snd_device;
1050
1051 // Treat as a special case when a1 and a2 are not disjoint
1052 if ((a1 != a2) && (a1 & a2)) {
1053 snd_device_t d3[2];
1054 int num_devices = 0;
1055 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
1056 &num_devices,
1057 d3);
1058 if (ret < 0) {
1059 if (ret != -ENOSYS) {
1060 ALOGW("%s failed to split snd_device %d",
1061 __func__,
1062 popcount(a1) > 1 ? d1 : d2);
1063 }
1064 goto end;
1065 }
1066
1067 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1068 // But if it does happen, we need to give priority to d2 if
1069 // the combo devices active on the existing usecase share a backend.
1070 // This is because we cannot have a usecase active on a combo device
1071 // and a new usecase requests one device in this combo pair.
1072 if (platform_check_backends_match(d3[0], d3[1])) {
1073 return d2; // case 5
1074 } else {
1075 return d1; // case 1
1076 }
1077 } else {
1078 if (platform_check_backends_match(d1, d2)) {
1079 return d2; // case 2, 4
1080 } else {
1081 return d1; // case 6, 3
1082 }
1083 }
1084
1085end:
1086 return d2; // return whatever was calculated before.
1087}
1088
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001089static void check_and_route_playback_usecases(struct audio_device *adev,
1090 struct audio_usecase *uc_info,
1091 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001092{
1093 struct listnode *node;
1094 struct audio_usecase *usecase;
1095 bool switch_device[AUDIO_USECASE_MAX];
1096 int i, num_uc_to_switch = 0;
1097
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001098 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
1099 uc_info,
1100 snd_device);
David Linee3fe402017-03-13 10:00:42 -07001101
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001102 /* For a2dp device reconfigure all active sessions
1103 * with new AFE encoder format based on a2dp state
1104 */
1105 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001106 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1107 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001108 audio_extn_a2dp_is_force_device_switch()) {
1109 force_routing = true;
1110 }
1111
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001112 /*
1113 * This function is to make sure that all the usecases that are active on
1114 * the hardware codec backend are always routed to any one device that is
1115 * handled by the hardware codec.
1116 * For example, if low-latency and deep-buffer usecases are currently active
1117 * on speaker and out_set_parameters(headset) is received on low-latency
1118 * output, then we have to make sure deep-buffer is also switched to headset,
1119 * because of the limitation that both the devices cannot be enabled
1120 * at the same time as they share the same backend.
1121 */
1122 /* Disable all the usecases on the shared backend other than the
1123 specified usecase */
1124 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1125 switch_device[i] = false;
1126
1127 list_for_each(node, &adev->usecase_list) {
1128 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001129 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
1130 continue;
1131
1132 if (force_routing ||
1133 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -07001134 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
1135 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001136 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1138 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -07001139 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001140 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001141 switch_device[usecase->id] = true;
1142 num_uc_to_switch++;
1143 }
1144 }
1145
1146 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001147 list_for_each(node, &adev->usecase_list) {
1148 usecase = node_to_item(node, struct audio_usecase, list);
1149 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001150 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001151 }
1152 }
1153
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001154 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001155 list_for_each(node, &adev->usecase_list) {
1156 usecase = node_to_item(node, struct audio_usecase, list);
1157 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001158 d_device = derive_playback_snd_device(usecase, uc_info,
1159 snd_device);
1160 enable_snd_device(adev, d_device);
1161 /* Update the out_snd_device before enabling the audio route */
1162 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001163 }
1164 }
1165
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001166 /* Re-route all the usecases on the shared backend other than the
1167 specified usecase to new snd devices */
1168 list_for_each(node, &adev->usecase_list) {
1169 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001170 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001171 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001172 }
1173 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001174 }
1175}
1176
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001177static void check_and_route_capture_usecases(struct audio_device *adev,
1178 struct audio_usecase *uc_info,
1179 snd_device_t snd_device)
1180{
1181 struct listnode *node;
1182 struct audio_usecase *usecase;
1183 bool switch_device[AUDIO_USECASE_MAX];
1184 int i, num_uc_to_switch = 0;
1185
vivek mehta4ed66e62016-04-15 23:33:34 -07001186 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1187
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001188 /*
1189 * This function is to make sure that all the active capture usecases
1190 * are always routed to the same input sound device.
1191 * For example, if audio-record and voice-call usecases are currently
1192 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1193 * is received for voice call then we have to make sure that audio-record
1194 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1195 * because of the limitation that two devices cannot be enabled
1196 * at the same time if they share the same backend.
1197 */
1198 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1199 switch_device[i] = false;
1200
1201 list_for_each(node, &adev->usecase_list) {
1202 usecase = node_to_item(node, struct audio_usecase, list);
1203 if (usecase->type != PCM_PLAYBACK &&
1204 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001205 usecase->in_snd_device != snd_device &&
Carter Hsu0a1160c2018-10-04 09:24:36 +08001206 ((uc_info->type == VOICE_CALL &&
1207 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1208 platform_check_backends_match(snd_device,\
1209 usecase->in_snd_device)) &&
Anish Kumarff864712015-06-03 13:35:11 -07001210 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001211 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1212 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001213 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001214 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001215 switch_device[usecase->id] = true;
1216 num_uc_to_switch++;
1217 }
1218 }
1219
1220 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001221 list_for_each(node, &adev->usecase_list) {
1222 usecase = node_to_item(node, struct audio_usecase, list);
1223 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001224 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001225 }
1226 }
1227
1228 list_for_each(node, &adev->usecase_list) {
1229 usecase = node_to_item(node, struct audio_usecase, list);
1230 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001231 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001232 }
1233 }
1234
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001235 /* Re-route all the usecases on the shared backend other than the
1236 specified usecase to new snd devices */
1237 list_for_each(node, &adev->usecase_list) {
1238 usecase = node_to_item(node, struct audio_usecase, list);
1239 /* Update the in_snd_device only before enabling the audio route */
1240 if (switch_device[usecase->id] ) {
1241 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001242 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001243 }
1244 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001245 }
1246}
1247
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001248/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001249static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001250{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001251 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001252 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001253
1254 switch (channels) {
1255 /*
1256 * Do not handle stereo output in Multi-channel cases
1257 * Stereo case is handled in normal playback path
1258 */
1259 case 6:
1260 ALOGV("%s: HDMI supports 5.1", __func__);
1261 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1262 break;
1263 case 8:
1264 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1265 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1266 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1267 break;
1268 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001269 ALOGE("HDMI does not support multi channel playback");
1270 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001271 break;
1272 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001273 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001274}
1275
Andy Hung18859412017-08-09 11:47:21 -07001276static ssize_t read_usb_sup_sample_rates(bool is_playback,
1277 uint32_t *supported_sample_rates,
1278 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001279{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001280 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1281 supported_sample_rates,
1282 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001283#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001284 for (ssize_t i=0; i<count; i++) {
1285 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1286 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001287 }
1288#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001289 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001290}
1291
Haynes Mathew George569b7482017-05-08 14:44:27 -07001292static int read_usb_sup_channel_masks(bool is_playback,
1293 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001294 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001295{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001296 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001297 int channel_count;
1298 uint32_t num_masks = 0;
1299 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1300 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001301 }
Eric Laurent74b55762017-07-09 17:04:53 -07001302 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001303 // start from 2 channels as framework currently doesn't support mono.
Eric Laurent154055d2019-05-01 18:07:29 -07001304 if (channels >= FCC_2) {
1305 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
Eric Laurent74b55762017-07-09 17:04:53 -07001306 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001307 for (channel_count = FCC_2;
1308 channel_count <= channels && num_masks < max_masks;
1309 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001310 supported_channel_masks[num_masks++] =
1311 audio_channel_mask_for_index_assignment_from_count(channel_count);
1312 }
1313 } else {
1314 // For capture we report all supported channel masks from 1 channel up.
1315 channel_count = MIN_CHANNEL_COUNT;
1316 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1317 // indexed mask
1318 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
Eric Laurent154055d2019-05-01 18:07:29 -07001319 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
1320 if (channel_count <= FCC_2) {
1321 mask = audio_channel_in_mask_from_count(channel_count);
1322 supported_channel_masks[num_masks++] = mask;
1323 }
Andy Hung88ce1d92018-10-29 18:31:12 -07001324 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{
Carter Hsuaaa94962019-05-14 14:26:24 +08001446 if (usecase->type == PCM_CAPTURE || usecase->stream.out == NULL) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001447 return false;
1448 }
1449
1450 // Force all A2DP output devices to reconfigure for proper AFE encode format
1451 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1452 // in suspended state, hence try to trigger a retry when we again get a routing request.
1453 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1454 audio_extn_a2dp_is_force_device_switch()) {
1455 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1456 return true;
1457 }
1458
1459 return false;
1460}
1461
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001462struct stream_in *adev_get_active_input(const struct audio_device *adev)
1463{
1464 struct listnode *node;
1465 struct stream_in *last_active_in = NULL;
1466
1467 /* Get last added active input.
1468 * TODO: We may use a priority mechanism to pick highest priority active source */
1469 list_for_each(node, &adev->usecase_list)
1470 {
1471 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1472 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
1473 last_active_in = usecase->stream.in;
1474 }
1475 }
1476
1477 return last_active_in;
1478}
1479
1480struct stream_in *get_voice_communication_input(const struct audio_device *adev)
1481{
1482 struct listnode *node;
1483
1484 /* First check active inputs with voice communication source and then
1485 * any input if audio mode is in communication */
1486 list_for_each(node, &adev->usecase_list)
1487 {
1488 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1489 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
1490 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1491 return usecase->stream.in;
1492 }
1493 }
1494 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
1495 return adev_get_active_input(adev);
1496 }
1497 return NULL;
1498}
1499
HW Leef88584d2019-03-18 17:27:18 +08001500int select_devices_with_force_switch(struct audio_device *adev,
1501 audio_usecase_t uc_id,
1502 bool force_switch)
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) {
HW Leef88584d2019-03-18 17:27:18 +08001607 if (!force_device_switch(usecase) && !force_switch)
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001608 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
HW Leef88584d2019-03-18 17:27:18 +08001751int select_devices(struct audio_device *adev,
1752 audio_usecase_t uc_id)
1753{
1754 return select_devices_with_force_switch(adev, uc_id, false);
1755}
1756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001757static int stop_input_stream(struct stream_in *in)
1758{
1759 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760 struct audio_usecase *uc_info;
1761 struct audio_device *adev = in->dev;
1762
Eric Laurent994a6932013-07-17 11:51:42 -07001763 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001764 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001765
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001766 uc_info = get_usecase_from_list(adev, in->usecase);
1767 if (uc_info == NULL) {
1768 ALOGE("%s: Could not find the usecase (%d) in the list",
1769 __func__, in->usecase);
1770 return -EINVAL;
1771 }
1772
vivek mehta781065c2017-04-04 12:55:01 -07001773 /* Close in-call recording streams */
1774 voice_check_and_stop_incall_rec_usecase(adev, in);
1775
Eric Laurent150dbfe2013-02-27 14:31:02 -08001776 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001777 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001778
1779 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001780 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001782 list_remove(&uc_info->list);
1783 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784
Eric Laurent994a6932013-07-17 11:51:42 -07001785 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001786 return ret;
1787}
1788
1789int start_input_stream(struct stream_in *in)
1790{
1791 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001792 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001793 struct audio_usecase *uc_info;
1794 struct audio_device *adev = in->dev;
1795
Eric Laurent994a6932013-07-17 11:51:42 -07001796 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001797
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001798 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1799 return -EIO;
1800
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001801 if (in->card_status == CARD_STATUS_OFFLINE ||
1802 adev->card_status == CARD_STATUS_OFFLINE) {
1803 ALOGW("in->card_status or adev->card_status offline, try again");
1804 ret = -EAGAIN;
1805 goto error_config;
1806 }
1807
vivek mehta781065c2017-04-04 12:55:01 -07001808 /* Check if source matches incall recording usecase criteria */
1809 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1810 if (ret)
1811 goto error_config;
1812 else
1813 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1814
Eric Laurentb23d5282013-05-14 15:27:20 -07001815 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001816 if (in->pcm_device_id < 0) {
1817 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1818 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001819 ret = -EINVAL;
1820 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001821 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1824 uc_info->id = in->usecase;
1825 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001826 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001827 uc_info->devices = in->device;
1828 uc_info->in_snd_device = SND_DEVICE_NONE;
1829 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001831 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001832
Wei Wangf4837d52017-11-21 14:51:20 -08001833 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001834 audio_extn_perf_lock_acquire();
1835
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001836 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837
Eric Laurent0e46adf2016-12-16 12:49:24 -08001838 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001839 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001840 ALOGE("%s: pcm stream not ready", __func__);
1841 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001842 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001843 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001844 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001845 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1846 goto error_open;
1847 }
1848 } else {
1849 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1850 unsigned int pcm_open_retry_count = 0;
1851
1852 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1853 flags |= PCM_MMAP | PCM_NOIRQ;
1854 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1855 } else if (in->realtime) {
1856 flags |= PCM_MMAP | PCM_NOIRQ;
1857 }
1858
1859 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1860 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1861
1862 while (1) {
1863 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1864 flags, &in->config);
1865 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1866 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1867 if (in->pcm != NULL) {
1868 pcm_close(in->pcm);
1869 in->pcm = NULL;
1870 }
1871 if (pcm_open_retry_count-- == 0) {
1872 ret = -EIO;
1873 goto error_open;
1874 }
1875 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1876 continue;
1877 }
1878 break;
1879 }
1880
1881 ALOGV("%s: pcm_prepare", __func__);
1882 ret = pcm_prepare(in->pcm);
1883 if (ret < 0) {
1884 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001885 pcm_close(in->pcm);
1886 in->pcm = NULL;
1887 goto error_open;
1888 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001889 if (in->realtime) {
1890 ret = pcm_start(in->pcm);
1891 if (ret < 0) {
1892 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1893 pcm_close(in->pcm);
1894 in->pcm = NULL;
1895 goto error_open;
1896 }
1897 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001898 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001899 register_in_stream(in);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001900 check_and_enable_effect(adev);
justinwengc6347db2019-02-21 18:49:00 +08001901 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
1902 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Wei Wangf4837d52017-11-21 14:51:20 -08001903 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001904 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001905 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001906
Eric Laurent0e46adf2016-12-16 12:49:24 -08001907 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001908
1909error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001911 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001912 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001913
1914error_config:
Eric Laurent2bafff12016-03-17 12:17:23 -07001915 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001916 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001917}
1918
Eric Laurenta1478072015-09-21 17:21:52 -07001919void lock_input_stream(struct stream_in *in)
1920{
1921 pthread_mutex_lock(&in->pre_lock);
1922 pthread_mutex_lock(&in->lock);
1923 pthread_mutex_unlock(&in->pre_lock);
1924}
1925
1926void lock_output_stream(struct stream_out *out)
1927{
1928 pthread_mutex_lock(&out->pre_lock);
1929 pthread_mutex_lock(&out->lock);
1930 pthread_mutex_unlock(&out->pre_lock);
1931}
1932
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001933/* must be called with out->lock locked */
1934static int send_offload_cmd_l(struct stream_out* out, int command)
1935{
1936 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1937
1938 ALOGVV("%s %d", __func__, command);
1939
1940 cmd->cmd = command;
1941 list_add_tail(&out->offload_cmd_list, &cmd->node);
1942 pthread_cond_signal(&out->offload_cond);
1943 return 0;
1944}
1945
1946/* must be called iwth out->lock locked */
1947static void stop_compressed_output_l(struct stream_out *out)
1948{
1949 out->offload_state = OFFLOAD_STATE_IDLE;
1950 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001951 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001952 if (out->compr != NULL) {
1953 compress_stop(out->compr);
1954 while (out->offload_thread_blocked) {
1955 pthread_cond_wait(&out->cond, &out->lock);
1956 }
1957 }
1958}
1959
1960static void *offload_thread_loop(void *context)
1961{
1962 struct stream_out *out = (struct stream_out *) context;
1963 struct listnode *item;
1964
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001965 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1966 set_sched_policy(0, SP_FOREGROUND);
1967 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1968
1969 ALOGV("%s", __func__);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001970
Eric Laurenta1478072015-09-21 17:21:52 -07001971 lock_output_stream(out);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001972 out->offload_state = OFFLOAD_STATE_IDLE;
1973 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001974 for (;;) {
1975 struct offload_cmd *cmd = NULL;
1976 stream_callback_event_t event;
1977 bool send_callback = false;
1978
1979 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1980 __func__, list_empty(&out->offload_cmd_list),
1981 out->offload_state);
1982 if (list_empty(&out->offload_cmd_list)) {
1983 ALOGV("%s SLEEPING", __func__);
1984 pthread_cond_wait(&out->offload_cond, &out->lock);
1985 ALOGV("%s RUNNING", __func__);
1986 continue;
1987 }
1988
1989 item = list_head(&out->offload_cmd_list);
1990 cmd = node_to_item(item, struct offload_cmd, node);
1991 list_remove(item);
1992
1993 ALOGVV("%s STATE %d CMD %d out->compr %p",
1994 __func__, out->offload_state, cmd->cmd, out->compr);
1995
1996 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1997 free(cmd);
1998 break;
1999 }
2000
2001 if (out->compr == NULL) {
2002 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07002003 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002004 pthread_cond_signal(&out->cond);
2005 continue;
2006 }
2007 out->offload_thread_blocked = true;
2008 pthread_mutex_unlock(&out->lock);
2009 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002010 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002011 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
2012 compress_wait(out->compr, -1);
2013 send_callback = true;
2014 event = STREAM_CBK_EVENT_WRITE_READY;
2015 break;
2016 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002017 compress_next_track(out->compr);
2018 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002019 send_callback = true;
2020 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002021 /* Resend the metadata for next iteration */
2022 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002023 break;
2024 case OFFLOAD_CMD_DRAIN:
2025 compress_drain(out->compr);
2026 send_callback = true;
2027 event = STREAM_CBK_EVENT_DRAIN_READY;
2028 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002029 case OFFLOAD_CMD_ERROR:
2030 send_callback = true;
2031 event = STREAM_CBK_EVENT_ERROR;
2032 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002033 default:
2034 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2035 break;
2036 }
Eric Laurenta1478072015-09-21 17:21:52 -07002037 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002038 out->offload_thread_blocked = false;
2039 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07002040 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002041 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002042 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002043 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002044 free(cmd);
2045 }
2046
2047 pthread_cond_signal(&out->cond);
2048 while (!list_empty(&out->offload_cmd_list)) {
2049 item = list_head(&out->offload_cmd_list);
2050 list_remove(item);
2051 free(node_to_item(item, struct offload_cmd, node));
2052 }
2053 pthread_mutex_unlock(&out->lock);
2054
2055 return NULL;
2056}
2057
2058static int create_offload_callback_thread(struct stream_out *out)
2059{
2060 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2061 list_init(&out->offload_cmd_list);
2062 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2063 offload_thread_loop, out);
2064 return 0;
2065}
2066
2067static int destroy_offload_callback_thread(struct stream_out *out)
2068{
Eric Laurenta1478072015-09-21 17:21:52 -07002069 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002070 stop_compressed_output_l(out);
2071 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2072
2073 pthread_mutex_unlock(&out->lock);
2074 pthread_join(out->offload_thread, (void **) NULL);
2075 pthread_cond_destroy(&out->offload_cond);
2076
2077 return 0;
2078}
2079
Eric Laurent07eeafd2013-10-06 12:52:49 -07002080static bool allow_hdmi_channel_config(struct audio_device *adev)
2081{
2082 struct listnode *node;
2083 struct audio_usecase *usecase;
2084 bool ret = true;
2085
2086 list_for_each(node, &adev->usecase_list) {
2087 usecase = node_to_item(node, struct audio_usecase, list);
2088 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2089 /*
2090 * If voice call is already existing, do not proceed further to avoid
2091 * disabling/enabling both RX and TX devices, CSD calls, etc.
2092 * Once the voice call done, the HDMI channels can be configured to
2093 * max channels of remaining use cases.
2094 */
2095 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08002096 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07002097 __func__);
2098 ret = false;
2099 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002100 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
2101 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07002102 "no change in HDMI channels", __func__);
2103 ret = false;
2104 break;
2105 }
2106 }
2107 }
2108 return ret;
2109}
2110
2111static int check_and_set_hdmi_channels(struct audio_device *adev,
2112 unsigned int channels)
2113{
2114 struct listnode *node;
2115 struct audio_usecase *usecase;
2116
2117 /* Check if change in HDMI channel config is allowed */
2118 if (!allow_hdmi_channel_config(adev))
2119 return 0;
2120
2121 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08002122 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002123 return 0;
2124 }
2125
2126 platform_set_hdmi_channels(adev->platform, channels);
2127 adev->cur_hdmi_channels = channels;
2128
2129 /*
2130 * Deroute all the playback streams routed to HDMI so that
2131 * the back end is deactivated. Note that backend will not
2132 * be deactivated if any one stream is connected to it.
2133 */
2134 list_for_each(node, &adev->usecase_list) {
2135 usecase = node_to_item(node, struct audio_usecase, list);
2136 if (usecase->type == PCM_PLAYBACK &&
2137 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002138 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002139 }
2140 }
2141
2142 /*
2143 * Enable all the streams disabled above. Now the HDMI backend
2144 * will be activated with new channel configuration
2145 */
2146 list_for_each(node, &adev->usecase_list) {
2147 usecase = node_to_item(node, struct audio_usecase, list);
2148 if (usecase->type == PCM_PLAYBACK &&
2149 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002150 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002151 }
2152 }
2153
2154 return 0;
2155}
2156
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002157static int check_and_set_usb_service_interval(struct audio_device *adev,
2158 struct audio_usecase *uc_info,
2159 bool min)
2160{
2161 struct listnode *node;
2162 struct audio_usecase *usecase;
2163 bool switch_usecases = false;
2164 bool reconfig = false;
2165
2166 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
2167 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
2168 return -1;
2169
2170 /* set if the valid usecase do not already exist */
2171 list_for_each(node, &adev->usecase_list) {
2172 usecase = node_to_item(node, struct audio_usecase, list);
2173 if (usecase->type == PCM_PLAYBACK &&
2174 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
2175 switch (usecase->id) {
2176 case USECASE_AUDIO_PLAYBACK_MMAP:
2177 case USECASE_AUDIO_PLAYBACK_ULL:
2178 // cannot reconfig while mmap/ull is present.
2179 return -1;
2180 default:
2181 switch_usecases = true;
2182 break;
2183 }
2184 }
2185 if (switch_usecases)
2186 break;
2187 }
2188 /*
2189 * client can try to set service interval in start_output_stream
2190 * to min or to 0 (i.e reset) in stop_output_stream .
2191 */
2192 unsigned long service_interval =
2193 audio_extn_usb_find_service_interval(min, true /*playback*/);
2194 int ret = platform_set_usb_service_interval(adev->platform,
2195 true /*playback*/,
2196 service_interval,
2197 &reconfig);
2198 /* no change or not supported or no active usecases */
2199 if (ret || !reconfig || !switch_usecases)
2200 return -1;
2201 return 0;
2202#undef VALID_USECASE
2203}
2204
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002205static int stop_output_stream(struct stream_out *out)
2206{
2207 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208 struct audio_usecase *uc_info;
2209 struct audio_device *adev = out->dev;
2210
Eric Laurent994a6932013-07-17 11:51:42 -07002211 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002212 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002213 uc_info = get_usecase_from_list(adev, out->usecase);
2214 if (uc_info == NULL) {
2215 ALOGE("%s: Could not find the usecase (%d) in the list",
2216 __func__, out->usecase);
2217 return -EINVAL;
2218 }
2219
Haynes Mathew George41f86652014-06-17 14:22:15 -07002220 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2221 if (adev->visualizer_stop_output != NULL)
2222 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
2223 if (adev->offload_effects_stop_output != NULL)
2224 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002225 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2226 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2227 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07002228 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002229
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002230 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2231 voice_set_device_mute_flag(adev, false);
2232
Eric Laurent150dbfe2013-02-27 14:31:02 -08002233 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002234 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002235
2236 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002237 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002239 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240
Eric Laurent0499d4f2014-08-25 22:39:29 -05002241 audio_extn_extspk_update(adev->extspk);
2242
Eric Laurent07eeafd2013-10-06 12:52:49 -07002243 /* Must be called after removing the usecase from list */
2244 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2245 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002246 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002247 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2248 if (ret == 0) {
2249 /* default service interval was successfully updated,
2250 reopen USB backend with new service interval */
2251 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2252 }
2253 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002254 }
juyuchend194b432018-11-16 14:15:16 +08002255 /* 1) media + voip output routing to handset must route media back to
2256 speaker when voip stops.
2257 2) trigger voip input to reroute when voip output changes to
2258 hearing aid. */
Robert Leec5271f72019-04-16 18:46:02 +08002259 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP ||
2260 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
HW Lee88512e92018-06-12 15:26:09 +08002261 struct listnode *node;
2262 struct audio_usecase *usecase;
2263 list_for_each(node, &adev->usecase_list) {
2264 usecase = node_to_item(node, struct audio_usecase, list);
juyuchend194b432018-11-16 14:15:16 +08002265 if ((usecase->type == PCM_CAPTURE &&
2266 usecase->id != USECASE_AUDIO_RECORD_VOIP)
2267 || usecase == uc_info)
HW Lee88512e92018-06-12 15:26:09 +08002268 continue;
2269
2270 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2271 __func__, usecase->id, use_case_table[usecase->id],
2272 out->usecase, use_case_table[out->usecase]);
2273 select_devices(adev, usecase->id);
2274 }
2275 }
2276
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002277 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002278 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279 return ret;
2280}
2281
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002282struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
2283 unsigned int flags, unsigned int pcm_open_retry_count,
2284 struct pcm_config *config)
2285{
2286 struct pcm* pcm = NULL;
2287
2288 while (1) {
2289 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
2290 if (pcm == NULL || !pcm_is_ready(pcm)) {
2291 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
2292 if (pcm != NULL) {
2293 pcm_close(pcm);
2294 pcm = NULL;
2295 }
2296 if (pcm_open_retry_count-- == 0)
2297 return NULL;
2298
2299 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2300 continue;
2301 }
2302 break;
2303 }
2304
2305 if (pcm_is_ready(pcm)) {
2306 int ret = pcm_prepare(pcm);
2307 if (ret < 0) {
2308 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2309 pcm_close(pcm);
2310 pcm = NULL;
2311 }
2312 }
2313
2314 return pcm;
2315}
2316
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002317int start_output_stream(struct stream_out *out)
2318{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320 struct audio_usecase *uc_info;
2321 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002322 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002323
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002324 ALOGV("%s: enter: usecase(%d: %s) %s devices(%#x)",
2325 __func__, out->usecase, use_case_table[out->usecase],
2326 out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS ? "(with haptics)" : "",
2327 out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002328
2329 if (out->card_status == CARD_STATUS_OFFLINE ||
2330 adev->card_status == CARD_STATUS_OFFLINE) {
2331 ALOGW("out->card_status or adev->card_status offline, try again");
2332 ret = -EAGAIN;
2333 goto error_config;
2334 }
2335
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002336 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2337 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002338 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002339 a2dp_combo = true;
2340 } else {
2341 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2342 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2343 ret = -EAGAIN;
2344 goto error_config;
2345 }
2346 }
2347 }
2348 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002349 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350 if (out->pcm_device_id < 0) {
2351 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2352 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002353 ret = -EINVAL;
2354 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002355 }
2356
2357 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2358 uc_info->id = out->usecase;
2359 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002360 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002361 uc_info->devices = out->devices;
2362 uc_info->in_snd_device = SND_DEVICE_NONE;
2363 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364
Eric Laurent07eeafd2013-10-06 12:52:49 -07002365 /* This must be called before adding this usecase to the list */
2366 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2367 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002368 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2369 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2370 /* USB backend is not reopened immediately.
2371 This is eventually done as part of select_devices */
2372 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002373
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002374 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002375
Wei Wangf4837d52017-11-21 14:51:20 -08002376 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002377 audio_extn_perf_lock_acquire();
2378
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002379 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2380 (!audio_extn_a2dp_is_ready())) {
2381 if (!a2dp_combo) {
2382 check_a2dp_restore_l(adev, out, false);
2383 } else {
2384 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002385 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2386 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2387 else
2388 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002389 select_devices(adev, out->usecase);
2390 out->devices = dev;
2391 }
2392 } else {
2393 select_devices(adev, out->usecase);
2394 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002395
Eric Laurent0499d4f2014-08-25 22:39:29 -05002396 audio_extn_extspk_update(adev->extspk);
2397
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002398 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2399 voice_set_device_mute_flag(adev, true);
2400
Andy Hung31aca912014-03-20 17:14:59 -07002401 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002402 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002403 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2404 out->pcm = NULL;
2405 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2406 COMPRESS_IN, &out->compr_config);
2407 if (out->compr && !is_compress_ready(out->compr)) {
2408 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2409 compress_close(out->compr);
2410 out->compr = NULL;
2411 ret = -EIO;
2412 goto error_open;
2413 }
2414 if (out->offload_callback)
2415 compress_nonblock(out->compr, out->non_blocking);
2416
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002417 if (adev->visualizer_start_output != NULL) {
2418 int capture_device_id =
2419 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2420 PCM_CAPTURE);
2421 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2422 adev->snd_card, capture_device_id);
2423 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002424 if (adev->offload_effects_start_output != NULL)
2425 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2426 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002427 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002428 ALOGE("%s: pcm stream not ready", __func__);
2429 goto error_open;
2430 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002431 ret = pcm_start(out->pcm);
2432 if (ret < 0) {
2433 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2434 goto error_open;
2435 }
2436 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002437 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002438 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002439
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002440 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2441 flags |= PCM_MMAP | PCM_NOIRQ;
2442 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002443 } else if (out->realtime) {
2444 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002445 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002446
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002447 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
2448 flags, pcm_open_retry_count,
2449 &(out->config));
2450 if (out->pcm == NULL) {
2451 ret = -EIO;
2452 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002453 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002454
2455 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2456 if (adev->haptic_pcm != NULL) {
2457 pcm_close(adev->haptic_pcm);
2458 adev->haptic_pcm = NULL;
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002459 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002460 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
2461 adev->haptic_pcm_device_id,
2462 flags, pcm_open_retry_count,
2463 &(adev->haptics_config));
2464 // failure to open haptics pcm shouldnt stop audio,
2465 // so do not close audio pcm in case of error
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002466 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002467
Eric Laurent0e46adf2016-12-16 12:49:24 -08002468 if (out->realtime) {
2469 ret = pcm_start(out->pcm);
2470 if (ret < 0) {
2471 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2472 pcm_close(out->pcm);
2473 out->pcm = NULL;
2474 goto error_open;
2475 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002476 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002477 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002478
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002479 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002480 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002481 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002482 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002483
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002484 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2485 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2486 audio_low_latency_hint_start();
2487 }
2488
vivek mehtae59cfb22017-06-16 15:57:11 -07002489 // consider a scenario where on pause lower layers are tear down.
2490 // so on resume, swap mixer control need to be sent only when
2491 // backend is active, hence rather than sending from enable device
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002492 // sending it from start of stream
vivek mehtae59cfb22017-06-16 15:57:11 -07002493
2494 platform_set_swap_channels(adev, true);
2495
Eric Laurent994a6932013-07-17 11:51:42 -07002496 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002497 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002498error_open:
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002499 if (adev->haptic_pcm) {
2500 pcm_close(adev->haptic_pcm);
2501 adev->haptic_pcm = NULL;
2502 }
Wei Wangf4837d52017-11-21 14:51:20 -08002503 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002504 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002506error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002507 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508}
2509
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510static int check_input_parameters(uint32_t sample_rate,
2511 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002512 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002514 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2515 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002516 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2517 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002518 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2519 return -EINVAL;
2520 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521
Eric Laurent74b55762017-07-09 17:04:53 -07002522 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2523 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002524 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002525 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002526 return -EINVAL;
2527 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528
2529 switch (sample_rate) {
2530 case 8000:
2531 case 11025:
2532 case 12000:
2533 case 16000:
2534 case 22050:
2535 case 24000:
2536 case 32000:
2537 case 44100:
2538 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002539 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540 break;
2541 default:
vivek mehtadae44712015-07-27 14:13:18 -07002542 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543 return -EINVAL;
2544 }
2545
2546 return 0;
2547}
2548
Kevin Rocarda325aa22018-04-03 09:15:52 -07002549/** Add a value in a list if not already present.
2550 * @return true if value was successfully inserted or already present,
2551 * false if the list is full and does not contain the value.
2552 */
2553static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2554 for (size_t i = 0; i < list_length; i++) {
2555 if (list[i] == value) return true; // value is already present
2556 if (list[i] == 0) { // no values in this slot
2557 list[i] = value;
2558 return true; // value inserted
2559 }
2560 }
2561 return false; // could not insert value
2562}
2563
2564/** Add channel_mask in supported_channel_masks if not already present.
2565 * @return true if channel_mask was successfully inserted or already present,
2566 * false if supported_channel_masks is full and does not contain channel_mask.
2567 */
2568static void register_channel_mask(audio_channel_mask_t channel_mask,
2569 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2570 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2571 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2572}
2573
2574/** Add format in supported_formats if not already present.
2575 * @return true if format was successfully inserted or already present,
2576 * false if supported_formats is full and does not contain format.
2577 */
2578static void register_format(audio_format_t format,
2579 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2580 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2581 "%s: stream can not declare supporting its format %x", __func__, format);
2582}
2583/** Add sample_rate in supported_sample_rates if not already present.
2584 * @return true if sample_rate was successfully inserted or already present,
2585 * false if supported_sample_rates is full and does not contain sample_rate.
2586 */
2587static void register_sample_rate(uint32_t sample_rate,
2588 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2589 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2590 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2591}
2592
vivek mehtaa68fea62017-06-08 19:04:02 -07002593static size_t get_stream_buffer_size(size_t duration_ms,
2594 uint32_t sample_rate,
2595 audio_format_t format,
2596 int channel_count,
2597 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598{
2599 size_t size = 0;
2600
vivek mehtaa68fea62017-06-08 19:04:02 -07002601 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002602 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002603 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002604
2605 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002606
Glenn Kasten4f993392014-05-14 07:30:48 -07002607 /* make sure the size is multiple of 32 bytes
2608 * At 48 kHz mono 16-bit PCM:
2609 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2610 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2611 */
2612 size += 0x1f;
2613 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002614
2615 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616}
2617
2618static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2619{
2620 struct stream_out *out = (struct stream_out *)stream;
2621
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002622 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002623}
2624
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002625static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626{
2627 return -ENOSYS;
2628}
2629
2630static size_t out_get_buffer_size(const struct audio_stream *stream)
2631{
2632 struct stream_out *out = (struct stream_out *)stream;
2633
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002634 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2635 return out->compr_config.fragment_size;
2636 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002637 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002638 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639}
2640
2641static uint32_t out_get_channels(const struct audio_stream *stream)
2642{
2643 struct stream_out *out = (struct stream_out *)stream;
2644
2645 return out->channel_mask;
2646}
2647
2648static audio_format_t out_get_format(const struct audio_stream *stream)
2649{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002650 struct stream_out *out = (struct stream_out *)stream;
2651
2652 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653}
2654
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002655static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656{
2657 return -ENOSYS;
2658}
2659
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002660/* must be called with out->lock locked */
2661static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662{
2663 struct stream_out *out = (struct stream_out *)stream;
2664 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002665 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002668 if (adev->adm_deregister_stream)
2669 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002670 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002672 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2673 if (out->pcm) {
2674 pcm_close(out->pcm);
2675 out->pcm = NULL;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002676
2677 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2678 if (adev->haptic_pcm) {
2679 pcm_close(adev->haptic_pcm);
2680 adev->haptic_pcm = NULL;
2681 }
2682
2683 if (adev->haptic_buffer != NULL) {
2684 free(adev->haptic_buffer);
2685 adev->haptic_buffer = NULL;
2686 adev->haptic_buffer_size = 0;
2687 }
2688 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002689 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002690 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002691 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002692 out->playback_started = false;
2693 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002694 } else {
2695 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002696 out->gapless_mdata.encoder_delay = 0;
2697 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002698 if (out->compr != NULL) {
2699 compress_close(out->compr);
2700 out->compr = NULL;
2701 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002702 }
Phil Burkbc991042017-02-24 08:06:44 -08002703 if (do_stop) {
2704 stop_output_stream(out);
2705 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002706 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002708 return 0;
2709}
2710
2711static int out_standby(struct audio_stream *stream)
2712{
2713 struct stream_out *out = (struct stream_out *)stream;
2714
2715 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2716 out->usecase, use_case_table[out->usecase]);
2717
2718 lock_output_stream(out);
2719 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002721 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722 return 0;
2723}
2724
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002725static int out_on_error(struct audio_stream *stream)
2726{
2727 struct stream_out *out = (struct stream_out *)stream;
2728 struct audio_device *adev = out->dev;
2729 bool do_standby = false;
2730
2731 lock_output_stream(out);
2732 if (!out->standby) {
2733 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2734 stop_compressed_output_l(out);
2735 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2736 } else
2737 do_standby = true;
2738 }
2739 pthread_mutex_unlock(&out->lock);
2740
2741 if (do_standby)
2742 return out_standby(&out->stream.common);
2743
2744 return 0;
2745}
2746
Andy Hung7401c7c2016-09-21 12:41:21 -07002747static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748{
Andy Hung7401c7c2016-09-21 12:41:21 -07002749 struct stream_out *out = (struct stream_out *)stream;
2750
2751 // We try to get the lock for consistency,
2752 // but it isn't necessary for these variables.
2753 // If we're not in standby, we may be blocked on a write.
2754 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2755 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2756 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2757
Andy Hung572633e2019-02-19 11:58:24 -08002758 char buffer[256]; // for statistics formatting
2759 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
2760 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
2761
Andy Hung241e36f2019-02-19 12:00:38 -08002762 if (out->start_latency_ms.n > 0) {
2763 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
2764 dprintf(fd, " Start latency ms: %s\n", buffer);
2765 }
2766
Andy Hung7401c7c2016-09-21 12:41:21 -07002767 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002768 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002769 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002770
2771 // dump error info
2772 (void)error_log_dump(
2773 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002774
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002775 return 0;
2776}
2777
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002778static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2779{
2780 int ret = 0;
2781 char value[32];
2782 struct compr_gapless_mdata tmp_mdata;
2783
2784 if (!out || !parms) {
2785 return -EINVAL;
2786 }
2787
2788 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2789 if (ret >= 0) {
2790 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2791 } else {
2792 return -EINVAL;
2793 }
2794
2795 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2796 if (ret >= 0) {
2797 tmp_mdata.encoder_padding = atoi(value);
2798 } else {
2799 return -EINVAL;
2800 }
2801
2802 out->gapless_mdata = tmp_mdata;
2803 out->send_new_metadata = 1;
2804 ALOGV("%s new encoder delay %u and padding %u", __func__,
2805 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2806
2807 return 0;
2808}
2809
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002810static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2811{
2812 return out == adev->primary_output || out == adev->voice_tx_output;
2813}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002814
Kevin Rocard1e02c882017-08-09 15:26:07 -07002815static int get_alive_usb_card(struct str_parms* parms) {
2816 int card;
2817 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2818 !audio_extn_usb_alive(card)) {
2819 return card;
2820 }
2821 return -ENODEV;
2822}
2823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2825{
2826 struct stream_out *out = (struct stream_out *)stream;
2827 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002828 struct audio_usecase *usecase;
2829 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002830 struct str_parms *parms;
2831 char value[32];
2832 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002833 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002834 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002835 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002836
Eric Laurent2e140aa2016-06-30 17:14:46 -07002837 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002838 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839 parms = str_parms_create_str(kvpairs);
2840 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2841 if (ret >= 0) {
2842 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002843
Eric Laurenta1478072015-09-21 17:21:52 -07002844 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002845
2846 // The usb driver needs to be closed after usb device disconnection
2847 // otherwise audio is no longer played on the new usb devices.
2848 // By forcing the stream in standby, the usb stack refcount drops to 0
2849 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002850 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002851 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002852 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2853 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2854 out_standby_l(&out->stream.common);
2855 }
2856 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002857 }
2858
Eric Laurent150dbfe2013-02-27 14:31:02 -08002859 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002861 /*
2862 * When HDMI cable is unplugged the music playback is paused and
2863 * the policy manager sends routing=0. But the audioflinger
2864 * continues to write data until standby time (3sec).
2865 * As the HDMI core is turned off, the write gets blocked.
2866 * Avoid this by routing audio to speaker until standby.
2867 */
2868 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2869 val == AUDIO_DEVICE_NONE) {
2870 val = AUDIO_DEVICE_OUT_SPEAKER;
2871 }
2872
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002873 /*
2874 * When A2DP is disconnected the
2875 * music playback is paused and the policy manager sends routing=0
2876 * But the audioflingercontinues to write data until standby time
2877 * (3sec). As BT is turned off, the write gets blocked.
2878 * Avoid this by routing audio to speaker until standby.
2879 */
2880 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2881 (val == AUDIO_DEVICE_NONE) &&
Aniket Kumar Lata8f270262019-05-08 15:56:56 -07002882 !audio_extn_a2dp_is_ready() &&
2883 !adev->bt_sco_on) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002884 val = AUDIO_DEVICE_OUT_SPEAKER;
2885 }
2886
2887 /* To avoid a2dp to sco overlapping / BT device improper state
2888 * check with BT lib about a2dp streaming support before routing
2889 */
2890 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2891 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002892 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002893 //combo usecase just by pass a2dp
2894 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2895 bypass_a2dp = true;
2896 } else {
2897 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2898 /* update device to a2dp and don't route as BT returned error
2899 * However it is still possible a2dp routing called because
2900 * of current active device disconnection (like wired headset)
2901 */
2902 out->devices = val;
2903 pthread_mutex_unlock(&out->lock);
2904 pthread_mutex_unlock(&adev->lock);
2905 status = -ENOSYS;
2906 goto routing_fail;
2907 }
2908 }
2909 }
2910
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002911 audio_devices_t new_dev = val;
2912
2913 // Workaround: If routing to an non existing usb device, fail gracefully
2914 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002915 int card;
2916 if (audio_is_usb_out_device(new_dev) &&
2917 (card = get_alive_usb_card(parms)) >= 0) {
2918
2919 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002920 pthread_mutex_unlock(&adev->lock);
2921 pthread_mutex_unlock(&out->lock);
2922 status = -ENOSYS;
2923 goto routing_fail;
2924 }
2925
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002926 /*
2927 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002928 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002929 * the select_devices(). But how do we undo this?
2930 *
2931 * For example, music playback is active on headset (deep-buffer usecase)
2932 * and if we go to ringtones and select a ringtone, low-latency usecase
2933 * will be started on headset+speaker. As we can't enable headset+speaker
2934 * and headset devices at the same time, select_devices() switches the music
2935 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2936 * So when the ringtone playback is completed, how do we undo the same?
2937 *
2938 * We are relying on the out_set_parameters() call on deep-buffer output,
2939 * once the ringtone playback is ended.
2940 * NOTE: We should not check if the current devices are same as new devices.
2941 * Because select_devices() must be called to switch back the music
2942 * playback to headset.
2943 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002944 if (new_dev != AUDIO_DEVICE_NONE) {
2945 bool same_dev = out->devices == new_dev;
2946 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002947
Eric Laurenta7657192014-10-09 21:09:33 -07002948 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002949 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002950 if (adev->mode == AUDIO_MODE_IN_CALL) {
2951 adev->current_call_output = out;
2952 ret = voice_start_call(adev);
2953 }
2954 } else {
2955 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002956 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002957 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002958 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002959
2960 if (!out->standby) {
2961 if (!same_dev) {
2962 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002963 // inform adm before actual routing to prevent glitches.
2964 if (adev->adm_on_routing_change) {
2965 adev->adm_on_routing_change(adev->adm_data,
2966 out->handle);
2967 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002968 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002969 if (!bypass_a2dp) {
2970 select_devices(adev, out->usecase);
2971 } else {
juyuchen9baad392018-06-05 19:02:10 +08002972 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2973 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2974 else
2975 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002976 select_devices(adev, out->usecase);
2977 out->devices = new_dev;
2978 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002979 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002980
2981 // on device switch force swap, lower functions will make sure
2982 // to check if swap is allowed or not.
2983
2984 if (!same_dev)
2985 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002986
2987 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2988 out->a2dp_compress_mute &&
2989 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2990 pthread_mutex_lock(&out->compr_mute_lock);
2991 out->a2dp_compress_mute = false;
2992 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2993 pthread_mutex_unlock(&out->compr_mute_lock);
2994 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002995 }
2996
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002997 }
2998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003000 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003001
3002 /*handles device and call state changes*/
3003 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003004 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003005 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003006
3007 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3008 parse_compress_metadata(out, parms);
3009 }
3010
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003011 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003012 ALOGV("%s: exit: code(%d)", __func__, status);
3013 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014}
3015
Haynes Mathew George569b7482017-05-08 14:44:27 -07003016static bool stream_get_parameter_channels(struct str_parms *query,
3017 struct str_parms *reply,
3018 audio_channel_mask_t *supported_channel_masks) {
3019 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07003020 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003022 size_t i, j;
3023
3024 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3025 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026 value[0] = '\0';
3027 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003028 while (supported_channel_masks[i] != 0) {
3029 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3030 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031 if (!first) {
3032 strcat(value, "|");
3033 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003034 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035 first = false;
3036 break;
3037 }
3038 }
3039 i++;
3040 }
3041 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003042 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003043 return ret >= 0;
3044}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003045
Haynes Mathew George569b7482017-05-08 14:44:27 -07003046static bool stream_get_parameter_formats(struct str_parms *query,
3047 struct str_parms *reply,
3048 audio_format_t *supported_formats) {
3049 int ret = -1;
3050 char value[256];
3051 int i;
3052
3053 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
3054 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003055 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07003056 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003057 case AUDIO_FORMAT_PCM_16_BIT:
3058 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
3059 break;
3060 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
3061 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
3062 break;
3063 case AUDIO_FORMAT_PCM_32_BIT:
3064 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
3065 break;
3066 default:
3067 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07003068 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003069 break;
3070 }
3071 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003072 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003073 return ret >= 0;
3074}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003075
Haynes Mathew George569b7482017-05-08 14:44:27 -07003076static bool stream_get_parameter_rates(struct str_parms *query,
3077 struct str_parms *reply,
3078 uint32_t *supported_sample_rates) {
3079
3080 int i;
3081 char value[256];
3082 int ret = -1;
3083 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
3084 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003085 value[0] = '\0';
3086 i=0;
3087 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003088 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003089 int avail = sizeof(value) - cursor;
3090 ret = snprintf(value + cursor, avail, "%s%d",
3091 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07003092 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003093 if (ret < 0 || ret >= avail) {
3094 // if cursor is at the last element of the array
3095 // overwrite with \0 is duplicate work as
3096 // snprintf already put a \0 in place.
3097 // else
3098 // we had space to write the '|' at value[cursor]
3099 // (which will be overwritten) or no space to fill
3100 // the first element (=> cursor == 0)
3101 value[cursor] = '\0';
3102 break;
3103 }
3104 cursor += ret;
3105 ++i;
3106 }
3107 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3108 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003109 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003110 return ret >= 0;
3111}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003112
Haynes Mathew George569b7482017-05-08 14:44:27 -07003113static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3114{
3115 struct stream_out *out = (struct stream_out *)stream;
3116 struct str_parms *query = str_parms_create_str(keys);
3117 char *str;
3118 struct str_parms *reply = str_parms_create();
3119 bool replied = false;
3120 ALOGV("%s: enter: keys - %s", __func__, keys);
3121
3122 replied |= stream_get_parameter_channels(query, reply,
3123 &out->supported_channel_masks[0]);
3124 replied |= stream_get_parameter_formats(query, reply,
3125 &out->supported_formats[0]);
3126 replied |= stream_get_parameter_rates(query, reply,
3127 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003128 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003129 str = str_parms_to_str(reply);
3130 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07003131 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132 }
3133 str_parms_destroy(query);
3134 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003135 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136 return str;
3137}
3138
3139static uint32_t out_get_latency(const struct audio_stream_out *stream)
3140{
Haynes Mathew George03c40102016-01-29 17:57:48 -08003141 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003143 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003145 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3146 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003147 else if ((out->realtime) ||
3148 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003149 // since the buffer won't be filled up faster than realtime,
3150 // return a smaller number
3151 period_ms = (out->af_period_multiplier * out->config.period_size *
3152 1000) / (out->config.rate);
3153 hw_delay = platform_render_latency(out->usecase)/1000;
3154 return period_ms + hw_delay;
3155 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003156
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003157 latency = (out->config.period_count * out->config.period_size * 1000) /
3158 (out->config.rate);
3159
3160 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
3161 latency += audio_extn_a2dp_get_encoder_latency();
3162
3163 return latency;
3164}
3165
3166static int set_compr_volume(struct audio_stream_out *stream, float left,
3167 float right)
3168{
3169 struct stream_out *out = (struct stream_out *)stream;
3170 int volume[2];
3171 char mixer_ctl_name[128];
3172 struct audio_device *adev = out->dev;
3173 struct mixer_ctl *ctl;
3174 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3175 PCM_PLAYBACK);
3176
3177 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3178 "Compress Playback %d Volume", pcm_device_id);
3179 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3180 if (!ctl) {
3181 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3182 __func__, mixer_ctl_name);
3183 return -EINVAL;
3184 }
3185 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
3186 __func__, mixer_ctl_name, left, right);
3187 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3188 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3189 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
3190
3191 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192}
3193
3194static int out_set_volume(struct audio_stream_out *stream, float left,
3195 float right)
3196{
Eric Laurenta9024de2013-04-04 09:19:12 -07003197 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003198 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003199
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003200 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07003201 /* only take left channel into account: the API is for stereo anyway */
3202 out->muted = (left == 0.0f);
3203 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003204 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003205 pthread_mutex_lock(&out->compr_mute_lock);
3206 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3207 if (!out->a2dp_compress_mute)
3208 ret = set_compr_volume(stream, left, right);
3209 out->volume_l = left;
3210 out->volume_r = right;
3211 pthread_mutex_unlock(&out->compr_mute_lock);
3212 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07003213 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07003214 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3215 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3216 if (!out->standby) {
3217 // if in standby, cached volume will be sent after stream is opened
3218 audio_extn_utils_send_app_type_gain(out->dev,
3219 out->app_type_cfg.app_type,
3220 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07003221 }
vivek mehtaa68fea62017-06-08 19:04:02 -07003222 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003223 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003224
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003225 return -ENOSYS;
3226}
3227
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003228// note: this call is safe only if the stream_cb is
3229// removed first in close_output_stream (as is done now).
3230static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3231{
3232 if (!stream || !parms)
3233 return;
3234
3235 struct stream_out *out = (struct stream_out *)stream;
3236 struct audio_device *adev = out->dev;
3237
3238 card_status_t status;
3239 int card;
3240 if (parse_snd_card_status(parms, &card, &status) < 0)
3241 return;
3242
3243 pthread_mutex_lock(&adev->lock);
3244 bool valid_cb = (card == adev->snd_card);
3245 pthread_mutex_unlock(&adev->lock);
3246
3247 if (!valid_cb)
3248 return;
3249
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003250 lock_output_stream(out);
3251 if (out->card_status != status)
3252 out->card_status = status;
3253 pthread_mutex_unlock(&out->lock);
3254
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07003255 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
3256 use_case_table[out->usecase],
3257 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3258
3259 if (status == CARD_STATUS_OFFLINE)
3260 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003261
3262 return;
3263}
3264
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003265#ifdef NO_AUDIO_OUT
3266static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003267 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003268{
3269 struct stream_out *out = (struct stream_out *)stream;
3270
3271 /* No Output device supported other than BT for playback.
3272 * Sleep for the amount of buffer duration
3273 */
Eric Laurenta1478072015-09-21 17:21:52 -07003274 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003275 usleep(bytes * 1000000 / audio_stream_out_frame_size(
3276 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003277 out_get_sample_rate(&out->stream.common));
3278 pthread_mutex_unlock(&out->lock);
3279 return bytes;
3280}
3281#endif
3282
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3284 size_t bytes)
3285{
3286 struct stream_out *out = (struct stream_out *)stream;
3287 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003288 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07003289 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003290
Eric Laurenta1478072015-09-21 17:21:52 -07003291 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07003292 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07003293 const size_t frame_size = audio_stream_out_frame_size(stream);
3294 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003295
Eric Laurent0e46adf2016-12-16 12:49:24 -08003296 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3297 error_code = ERROR_CODE_WRITE;
3298 goto exit;
3299 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003300
3301 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3302 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003303 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003304 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3305 ret = -EIO;
3306 goto exit;
3307 }
3308 }
3309 }
3310
Andy Hung572633e2019-02-19 11:58:24 -08003311 const bool was_in_standby = out->standby;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003313 out->standby = false;
Andy Hung241e36f2019-02-19 12:00:38 -08003314 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
3315
Eric Laurent150dbfe2013-02-27 14:31:02 -08003316 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003318
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003319 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003320 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003321 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003322 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003323 goto exit;
3324 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003325
vivek mehta40125092017-08-21 18:48:51 -07003326 // after standby always force set last known cal step
3327 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3328 ALOGD("%s: retry previous failed cal level set", __func__);
3329 send_gain_dep_calibration_l();
3330 pthread_mutex_unlock(&adev->lock);
Andy Hung572633e2019-02-19 11:58:24 -08003331
Andy Hung241e36f2019-02-19 12:00:38 -08003332 // log startup time in ms.
3333 simple_stats_log(
3334 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Andy Hung572633e2019-02-19 11:58:24 -08003335 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003338 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003339 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003340 if (out->send_new_metadata) {
3341 ALOGVV("send new gapless metadata");
3342 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3343 out->send_new_metadata = 0;
3344 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003345 unsigned int avail;
3346 struct timespec tstamp;
3347 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3348 /* Do not limit write size if the available frames count is unknown */
3349 if (ret != 0) {
3350 avail = bytes;
3351 }
3352 if (avail == 0) {
3353 ret = 0;
3354 } else {
Andy Hung572633e2019-02-19 11:58:24 -08003355 // check for compressed format underrun, essentially an empty buffer check
3356 // for a lack of better measurement.
3357 if (!was_in_standby && avail == out->kernel_buffer_size) {
3358 ALOGW("%s: compressed buffer empty (underrun)", __func__);
3359 simple_stats_log(&out->fifo_underruns, 1.); // Note: log one frame for compressed.
3360 }
3361
Eric Laurentb49b3f62016-02-29 17:59:49 -08003362 if (avail > bytes) {
3363 avail = bytes;
3364 }
3365 ret = compress_write(out->compr, buffer, avail);
3366 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3367 __func__, avail, ret);
3368 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003369
Eric Laurent6e895242013-09-05 16:10:57 -07003370 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003371 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3372 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003373 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003374 compress_start(out->compr);
3375 out->playback_started = 1;
3376 out->offload_state = OFFLOAD_STATE_PLAYING;
3377 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003378 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003379 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003380 } else {
3381 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003382 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003383 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003384 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003385 return ret;
3386 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003387 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003388 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003389 size_t bytes_to_write = bytes;
3390
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003391 if (out->muted)
3392 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003393 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003394 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003395 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3396 int16_t *src = (int16_t *)buffer;
3397 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003398
Eric Laurentad2dde92017-09-20 18:27:31 -07003399 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3400 out->format != AUDIO_FORMAT_PCM_16_BIT,
3401 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003402
Eric Laurentad2dde92017-09-20 18:27:31 -07003403 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3404 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3405 }
3406 bytes_to_write /= 2;
3407 }
Andy Hung572633e2019-02-19 11:58:24 -08003408
3409 // Note: since out_get_presentation_position() is called alternating with out_write()
3410 // by AudioFlinger, we can check underruns using the prior timestamp read.
3411 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
3412 if (out->last_fifo_valid) {
3413 // compute drain to see if there is an underrun.
3414 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
3415 const int64_t frames_by_time =
3416 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
3417 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
3418
3419 if (underrun > 0) {
3420 simple_stats_log(&out->fifo_underruns, underrun);
3421
3422 ALOGW("%s: underrun(%lld) "
3423 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
3424 __func__,
3425 (long long)out->fifo_underruns.n,
3426 (long long)frames_by_time,
3427 (long long)out->last_fifo_frames_remaining);
3428 }
3429 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
3430 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003431
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003432 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003433 request_out_focus(out, ns);
3434
3435 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003436 if (use_mmap) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003437 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003438 } else {
3439 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3440 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3441 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
3442 size_t frame_size = channel_count * bytes_per_sample;
3443 size_t frame_count = bytes_to_write / frame_size;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003444
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003445 bool force_haptic_path =
3446 property_get_bool("vendor.audio.test_haptic", false);
3447
3448 // extract Haptics data from Audio buffer
3449 bool alloc_haptic_buffer = false;
3450 int haptic_channel_count = adev->haptics_config.channels;
3451 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
3452 size_t audio_frame_size = frame_size - haptic_frame_size;
3453 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
3454
3455 if (adev->haptic_buffer == NULL) {
3456 alloc_haptic_buffer = true;
3457 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
3458 free(adev->haptic_buffer);
3459 adev->haptic_buffer_size = 0;
3460 alloc_haptic_buffer = true;
3461 }
3462
3463 if (alloc_haptic_buffer) {
3464 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
3465 adev->haptic_buffer_size = total_haptic_buffer_size;
3466 }
3467
3468 size_t src_index = 0, aud_index = 0, hap_index = 0;
3469 uint8_t *audio_buffer = (uint8_t *)buffer;
3470 uint8_t *haptic_buffer = adev->haptic_buffer;
3471
3472 // This is required for testing only. This works for stereo data only.
3473 // One channel is fed to audio stream and other to haptic stream for testing.
3474 if (force_haptic_path) {
3475 audio_frame_size = haptic_frame_size = bytes_per_sample;
3476 }
3477
3478 for (size_t i = 0; i < frame_count; i++) {
3479 for (size_t j = 0; j < audio_frame_size; j++)
3480 audio_buffer[aud_index++] = audio_buffer[src_index++];
3481
3482 for (size_t j = 0; j < haptic_frame_size; j++)
3483 haptic_buffer[hap_index++] = audio_buffer[src_index++];
3484 }
3485
3486 // This is required for testing only.
3487 // Discard haptic channel data.
3488 if (force_haptic_path) {
3489 src_index += haptic_frame_size;
3490 }
3491
3492 // write to audio pipeline
3493 ret = pcm_write(out->pcm,
3494 (void *)audio_buffer,
3495 frame_count * audio_frame_size);
3496
3497 // write to haptics pipeline
3498 if (adev->haptic_pcm)
3499 ret = pcm_write(adev->haptic_pcm,
3500 (void *)adev->haptic_buffer,
3501 frame_count * haptic_frame_size);
3502
3503 } else {
3504 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
3505 }
3506 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003507 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003508 } else {
3509 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003510 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511 }
3512
3513exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003514 // For PCM we always consume the buffer and return #bytes regardless of ret.
3515 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003516 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003517 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003518 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003519
Andy Hung7401c7c2016-09-21 12:41:21 -07003520 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003521 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003522 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3523 ALOGE_IF(out->pcm != NULL,
3524 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003525 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003526 // usleep not guaranteed for values over 1 second but we don't limit here.
3527 }
3528 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003529
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530 pthread_mutex_unlock(&out->lock);
3531
3532 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003533 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003534 if (sleeptime_us != 0)
3535 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536 }
3537 return bytes;
3538}
3539
3540static int out_get_render_position(const struct audio_stream_out *stream,
3541 uint32_t *dsp_frames)
3542{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003543 struct stream_out *out = (struct stream_out *)stream;
3544 *dsp_frames = 0;
3545 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003546 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003547 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003548 unsigned long frames = 0;
3549 // TODO: check return value
3550 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3551 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003552 ALOGVV("%s rendered frames %d sample_rate %d",
3553 __func__, *dsp_frames, out->sample_rate);
3554 }
3555 pthread_mutex_unlock(&out->lock);
3556 return 0;
3557 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003558 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559}
3560
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003561static int out_add_audio_effect(const struct audio_stream *stream __unused,
3562 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563{
3564 return 0;
3565}
3566
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003567static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3568 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569{
3570 return 0;
3571}
3572
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003573static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3574 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003575{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003576 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577}
3578
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003579static int out_get_presentation_position(const struct audio_stream_out *stream,
3580 uint64_t *frames, struct timespec *timestamp)
3581{
3582 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003583 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003584 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003585
Eric Laurenta1478072015-09-21 17:21:52 -07003586 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003587
Eric Laurent949a0892013-09-20 09:20:13 -07003588 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3589 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003590 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003591 compress_get_tstamp(out->compr, &dsp_frames,
3592 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003593 // Adjustment accounts for A2DP encoder latency with offload usecases
3594 // Note: Encoder latency is returned in ms.
3595 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3596 unsigned long offset =
3597 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3598 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3599 }
Eric Laurent949a0892013-09-20 09:20:13 -07003600 ALOGVV("%s rendered frames %ld sample_rate %d",
3601 __func__, dsp_frames, out->sample_rate);
3602 *frames = dsp_frames;
3603 ret = 0;
3604 /* this is the best we can do */
3605 clock_gettime(CLOCK_MONOTONIC, timestamp);
3606 }
3607 } else {
3608 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003609 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003610 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
Andy Hung572633e2019-02-19 11:58:24 -08003611
3612 // pcm_get_htimestamp() computes the available frames by comparing
3613 // the alsa driver hw_ptr and the appl_ptr levels.
3614 // In underrun, the hw_ptr may keep running and report an excessively
3615 // large number available number.
3616 if (avail > out->kernel_buffer_size) {
3617 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
3618 __func__, avail, out->kernel_buffer_size);
3619 avail = out->kernel_buffer_size;
3620 out->last_fifo_frames_remaining = 0;
3621 } else {
3622 out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
3623 }
3624 out->last_fifo_valid = true;
3625 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
3626
3627 int64_t signed_frames = out->written - out->last_fifo_frames_remaining;
3628
3629 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
3630 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
3631
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003632 // This adjustment accounts for buffering after app processor.
3633 // It is based on estimated DSP latency per use case, rather than exact.
3634 signed_frames -=
3635 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3636
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003637 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3638 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3639 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3640 signed_frames -=
3641 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3642 }
3643
Eric Laurent949a0892013-09-20 09:20:13 -07003644 // It would be unusual for this value to be negative, but check just in case ...
3645 if (signed_frames >= 0) {
3646 *frames = signed_frames;
3647 ret = 0;
3648 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003649 }
3650 }
3651 }
3652
3653 pthread_mutex_unlock(&out->lock);
3654
3655 return ret;
3656}
3657
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003658static int out_set_callback(struct audio_stream_out *stream,
3659 stream_callback_t callback, void *cookie)
3660{
3661 struct stream_out *out = (struct stream_out *)stream;
3662
3663 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003664 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003665 out->offload_callback = callback;
3666 out->offload_cookie = cookie;
3667 pthread_mutex_unlock(&out->lock);
3668 return 0;
3669}
3670
3671static int out_pause(struct audio_stream_out* stream)
3672{
3673 struct stream_out *out = (struct stream_out *)stream;
3674 int status = -ENOSYS;
3675 ALOGV("%s", __func__);
3676 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003677 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003678 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3679 status = compress_pause(out->compr);
3680 out->offload_state = OFFLOAD_STATE_PAUSED;
3681 }
3682 pthread_mutex_unlock(&out->lock);
3683 }
3684 return status;
3685}
3686
3687static int out_resume(struct audio_stream_out* stream)
3688{
3689 struct stream_out *out = (struct stream_out *)stream;
3690 int status = -ENOSYS;
3691 ALOGV("%s", __func__);
3692 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3693 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003694 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003695 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3696 status = compress_resume(out->compr);
3697 out->offload_state = OFFLOAD_STATE_PLAYING;
3698 }
3699 pthread_mutex_unlock(&out->lock);
3700 }
3701 return status;
3702}
3703
3704static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3705{
3706 struct stream_out *out = (struct stream_out *)stream;
3707 int status = -ENOSYS;
3708 ALOGV("%s", __func__);
3709 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003710 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003711 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3712 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3713 else
3714 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3715 pthread_mutex_unlock(&out->lock);
3716 }
3717 return status;
3718}
3719
3720static int out_flush(struct audio_stream_out* stream)
3721{
3722 struct stream_out *out = (struct stream_out *)stream;
3723 ALOGV("%s", __func__);
3724 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003725 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003726 stop_compressed_output_l(out);
3727 pthread_mutex_unlock(&out->lock);
3728 return 0;
3729 }
3730 return -ENOSYS;
3731}
3732
Eric Laurent0e46adf2016-12-16 12:49:24 -08003733static int out_stop(const struct audio_stream_out* stream)
3734{
3735 struct stream_out *out = (struct stream_out *)stream;
3736 struct audio_device *adev = out->dev;
3737 int ret = -ENOSYS;
3738
3739 ALOGV("%s", __func__);
3740 pthread_mutex_lock(&adev->lock);
3741 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3742 out->playback_started && out->pcm != NULL) {
3743 pcm_stop(out->pcm);
3744 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003745 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003746 }
3747 pthread_mutex_unlock(&adev->lock);
3748 return ret;
3749}
3750
3751static int out_start(const struct audio_stream_out* stream)
3752{
3753 struct stream_out *out = (struct stream_out *)stream;
3754 struct audio_device *adev = out->dev;
3755 int ret = -ENOSYS;
3756
3757 ALOGV("%s", __func__);
3758 pthread_mutex_lock(&adev->lock);
3759 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3760 !out->playback_started && out->pcm != NULL) {
3761 ret = start_output_stream(out);
3762 if (ret == 0) {
3763 out->playback_started = true;
3764 }
3765 }
3766 pthread_mutex_unlock(&adev->lock);
3767 return ret;
3768}
3769
Phil Burkbc991042017-02-24 08:06:44 -08003770/*
3771 * Modify config->period_count based on min_size_frames
3772 */
3773static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3774{
3775 int periodCountRequested = (min_size_frames + config->period_size - 1)
3776 / config->period_size;
3777 int periodCount = MMAP_PERIOD_COUNT_MIN;
3778
3779 ALOGV("%s original config.period_size = %d config.period_count = %d",
3780 __func__, config->period_size, config->period_count);
3781
3782 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3783 periodCount *= 2;
3784 }
3785 config->period_count = periodCount;
3786
3787 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3788}
3789
Phil Burk51e6bc42019-03-25 10:23:35 -07003790// Read offset for the positional timestamp from a persistent vendor property.
3791// This is to workaround apparent inaccuracies in the timing information that
3792// is used by the AAudio timing model. The inaccuracies can cause glitches.
3793static int64_t get_mmap_out_time_offset() {
3794 const int32_t kDefaultOffsetMicros = 0;
3795 int32_t mmap_time_offset_micros = property_get_int32(
3796 "persist.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
3797 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
3798 return mmap_time_offset_micros * (int64_t)1000;
3799}
3800
Eric Laurent0e46adf2016-12-16 12:49:24 -08003801static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3802 int32_t min_size_frames,
3803 struct audio_mmap_buffer_info *info)
3804{
3805 struct stream_out *out = (struct stream_out *)stream;
3806 struct audio_device *adev = out->dev;
3807 int ret = 0;
3808 unsigned int offset1;
3809 unsigned int frames1;
3810 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003811 uint32_t mmap_size;
3812 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003813
3814 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003815 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003816 pthread_mutex_lock(&adev->lock);
3817
3818 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003819 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003820 ret = -EINVAL;
3821 goto exit;
3822 }
3823 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003824 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003825 ret = -ENOSYS;
3826 goto exit;
3827 }
3828 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3829 if (out->pcm_device_id < 0) {
3830 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3831 __func__, out->pcm_device_id, out->usecase);
3832 ret = -EINVAL;
3833 goto exit;
3834 }
Phil Burkbc991042017-02-24 08:06:44 -08003835
3836 adjust_mmap_period_count(&out->config, min_size_frames);
3837
Eric Laurent0e46adf2016-12-16 12:49:24 -08003838 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3839 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3840 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3841 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3842 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3843 step = "open";
3844 ret = -ENODEV;
3845 goto exit;
3846 }
3847 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3848 if (ret < 0) {
3849 step = "begin";
3850 goto exit;
3851 }
3852 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003853 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003854 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003855 ret = platform_get_mmap_data_fd(adev->platform,
3856 out->pcm_device_id, 0 /*playback*/,
3857 &info->shared_memory_fd,
3858 &mmap_size);
3859 if (ret < 0) {
3860 // Fall back to non exclusive mode
3861 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3862 } else {
3863 if (mmap_size < buffer_size) {
3864 step = "mmap";
3865 goto exit;
3866 }
3867 // FIXME: indicate exclusive mode support by returning a negative buffer size
3868 info->buffer_size_frames *= -1;
3869 }
3870 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003871
3872 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3873 if (ret < 0) {
3874 step = "commit";
3875 goto exit;
3876 }
Phil Burkbc991042017-02-24 08:06:44 -08003877
Phil Burk51e6bc42019-03-25 10:23:35 -07003878 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
3879
Phil Burkbc991042017-02-24 08:06:44 -08003880 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003881 ret = 0;
3882
3883 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3884 __func__, info->shared_memory_address, info->buffer_size_frames);
3885
3886exit:
3887 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003888 if (out->pcm == NULL) {
3889 ALOGE("%s: %s - %d", __func__, step, ret);
3890 } else {
3891 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003892 pcm_close(out->pcm);
3893 out->pcm = NULL;
3894 }
3895 }
3896 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003897 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003898 return ret;
3899}
3900
3901static int out_get_mmap_position(const struct audio_stream_out *stream,
3902 struct audio_mmap_position *position)
3903{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003904 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003905 struct stream_out *out = (struct stream_out *)stream;
3906 ALOGVV("%s", __func__);
3907 if (position == NULL) {
3908 return -EINVAL;
3909 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003910 lock_output_stream(out);
3911 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3912 out->pcm == NULL) {
3913 ret = -ENOSYS;
3914 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003915 }
3916
3917 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003918 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003919 if (ret < 0) {
3920 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003921 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003922 }
Phil Burk51e6bc42019-03-25 10:23:35 -07003923 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts)
3924 + out->mmap_time_offset_nanos;
3925
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003926exit:
3927 pthread_mutex_unlock(&out->lock);
3928 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003929}
3930
3931
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003932/** audio_stream_in implementation **/
3933static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3934{
3935 struct stream_in *in = (struct stream_in *)stream;
3936
3937 return in->config.rate;
3938}
3939
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003940static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003941{
3942 return -ENOSYS;
3943}
3944
3945static size_t in_get_buffer_size(const struct audio_stream *stream)
3946{
3947 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003948 return in->config.period_size * in->af_period_multiplier *
3949 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003950}
3951
3952static uint32_t in_get_channels(const struct audio_stream *stream)
3953{
3954 struct stream_in *in = (struct stream_in *)stream;
3955
3956 return in->channel_mask;
3957}
3958
vivek mehta4ed66e62016-04-15 23:33:34 -07003959static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003960{
vivek mehta4ed66e62016-04-15 23:33:34 -07003961 struct stream_in *in = (struct stream_in *)stream;
3962 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003963}
3964
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003965static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003966{
3967 return -ENOSYS;
3968}
3969
3970static int in_standby(struct audio_stream *stream)
3971{
3972 struct stream_in *in = (struct stream_in *)stream;
3973 struct audio_device *adev = in->dev;
3974 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003975 bool do_stop = true;
3976
Eric Laurent994a6932013-07-17 11:51:42 -07003977 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003978
3979 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003980
3981 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003982 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003983 audio_extn_sound_trigger_stop_lab(in);
3984 in->standby = true;
3985 }
3986
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003987 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003988 if (adev->adm_deregister_stream)
3989 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3990
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003991 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003992 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003993 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003994 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003995 in->capture_started = false;
3996 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003997 if (in->pcm) {
3998 pcm_close(in->pcm);
3999 in->pcm = NULL;
4000 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05004001 adev->enable_voicerx = false;
4002 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08004003 if (do_stop) {
4004 status = stop_input_stream(in);
4005 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004006 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004007 }
4008 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07004009 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004010 return status;
4011}
4012
Andy Hungd13f0d32017-06-12 13:58:37 -07004013static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004014{
Andy Hungd13f0d32017-06-12 13:58:37 -07004015 struct stream_in *in = (struct stream_in *)stream;
4016
4017 // We try to get the lock for consistency,
4018 // but it isn't necessary for these variables.
4019 // If we're not in standby, we may be blocked on a read.
4020 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
4021 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
4022 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
4023 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
4024
Andy Hung241e36f2019-02-19 12:00:38 -08004025 char buffer[256]; // for statistics formatting
4026 if (in->start_latency_ms.n > 0) {
4027 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
4028 dprintf(fd, " Start latency ms: %s\n", buffer);
4029 }
4030
Andy Hungd13f0d32017-06-12 13:58:37 -07004031 if (locked) {
4032 pthread_mutex_unlock(&in->lock);
4033 }
4034
4035 // dump error info
4036 (void)error_log_dump(
4037 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004038 return 0;
4039}
4040
4041static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4042{
4043 struct stream_in *in = (struct stream_in *)stream;
4044 struct audio_device *adev = in->dev;
4045 struct str_parms *parms;
4046 char *str;
4047 char value[32];
4048 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07004049 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050
Eric Laurent994a6932013-07-17 11:51:42 -07004051 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004052 parms = str_parms_create_str(kvpairs);
4053
4054 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4055
Eric Laurenta1478072015-09-21 17:21:52 -07004056 lock_input_stream(in);
4057
Eric Laurent150dbfe2013-02-27 14:31:02 -08004058 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004059 if (ret >= 0) {
4060 val = atoi(value);
4061 /* no audio source uses val == 0 */
4062 if ((in->source != val) && (val != 0)) {
4063 in->source = val;
4064 }
4065 }
4066
4067 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07004068
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004069 if (ret >= 0) {
4070 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07004071 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004072
4073 // Workaround: If routing to an non existing usb device, fail gracefully
4074 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07004075 int card;
4076 if (audio_is_usb_in_device(val) &&
4077 (card = get_alive_usb_card(parms)) >= 0) {
4078
4079 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004080 status = -ENOSYS;
4081 } else {
4082
4083 in->device = val;
4084 /* If recording is in progress, change the tx device to new device */
4085 if (!in->standby) {
4086 ALOGV("update input routing change");
4087 // inform adm before actual routing to prevent glitches.
4088 if (adev->adm_on_routing_change) {
4089 adev->adm_on_routing_change(adev->adm_data,
4090 in->capture_handle);
4091 }
4092 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07004093 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004094 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004095 }
4096 }
4097
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004098 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004099 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004100
4101 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07004102 ALOGV("%s: exit: status(%d)", __func__, status);
4103 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004104}
4105
Haynes Mathew George569b7482017-05-08 14:44:27 -07004106static char* in_get_parameters(const struct audio_stream *stream,
4107 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004108{
Haynes Mathew George569b7482017-05-08 14:44:27 -07004109 struct stream_in *in = (struct stream_in *)stream;
4110 struct str_parms *query = str_parms_create_str(keys);
4111 char *str;
4112 struct str_parms *reply = str_parms_create();
4113 bool replied = false;
4114
4115 ALOGV("%s: enter: keys - %s", __func__, keys);
4116 replied |= stream_get_parameter_channels(query, reply,
4117 &in->supported_channel_masks[0]);
4118 replied |= stream_get_parameter_formats(query, reply,
4119 &in->supported_formats[0]);
4120 replied |= stream_get_parameter_rates(query, reply,
4121 &in->supported_sample_rates[0]);
4122 if (replied) {
4123 str = str_parms_to_str(reply);
4124 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07004125 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07004126 }
4127 str_parms_destroy(query);
4128 str_parms_destroy(reply);
4129 ALOGV("%s: exit: returns - %s", __func__, str);
4130 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004131}
4132
Eric Laurent51f3c662018-04-10 18:21:34 -07004133static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004134{
Eric Laurent51f3c662018-04-10 18:21:34 -07004135 struct stream_in *in = (struct stream_in *)stream;
4136 char mixer_ctl_name[128];
4137 struct mixer_ctl *ctl;
4138 int ctl_value;
4139
4140 ALOGV("%s: gain %f", __func__, gain);
4141
4142 if (stream == NULL)
4143 return -EINVAL;
4144
4145 /* in_set_gain() only used to silence MMAP capture for now */
4146 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
4147 return -ENOSYS;
4148
4149 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
4150
4151 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
4152 if (!ctl) {
4153 ALOGW("%s: Could not get ctl for mixer cmd - %s",
4154 __func__, mixer_ctl_name);
4155 return -ENOSYS;
4156 }
4157
4158 if (gain < RECORD_GAIN_MIN)
4159 gain = RECORD_GAIN_MIN;
4160 else if (gain > RECORD_GAIN_MAX)
4161 gain = RECORD_GAIN_MAX;
4162 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
4163
4164 mixer_ctl_set_value(ctl, 0, ctl_value);
4165 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004166}
4167
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004168static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4169{
4170 if (!stream || !parms)
4171 return;
4172
4173 struct stream_in *in = (struct stream_in *)stream;
4174 struct audio_device *adev = in->dev;
4175
4176 card_status_t status;
4177 int card;
4178 if (parse_snd_card_status(parms, &card, &status) < 0)
4179 return;
4180
4181 pthread_mutex_lock(&adev->lock);
4182 bool valid_cb = (card == adev->snd_card);
4183 pthread_mutex_unlock(&adev->lock);
4184
4185 if (!valid_cb)
4186 return;
4187
4188 lock_input_stream(in);
4189 if (in->card_status != status)
4190 in->card_status = status;
4191 pthread_mutex_unlock(&in->lock);
4192
4193 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4194 use_case_table[in->usecase],
4195 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4196
4197 // a better solution would be to report error back to AF and let
4198 // it put the stream to standby
4199 if (status == CARD_STATUS_OFFLINE)
4200 in_standby(&in->stream.common);
4201
4202 return;
4203}
4204
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004205static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4206 size_t bytes)
4207{
4208 struct stream_in *in = (struct stream_in *)stream;
4209 struct audio_device *adev = in->dev;
4210 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07004211 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07004212 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004213
Eric Laurenta1478072015-09-21 17:21:52 -07004214 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004215 const size_t frame_size = audio_stream_in_frame_size(stream);
4216 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07004217
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004218 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004219 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004220 /* Read from sound trigger HAL */
4221 audio_extn_sound_trigger_read(in, buffer, bytes);
4222 pthread_mutex_unlock(&in->lock);
4223 return bytes;
4224 }
4225
Eric Laurent0e46adf2016-12-16 12:49:24 -08004226 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4227 ret = -ENOSYS;
4228 goto exit;
4229 }
4230
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004231 if (in->standby) {
Andy Hung241e36f2019-02-19 12:00:38 -08004232 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
4233
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004234 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004235 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004236 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004237 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004238 goto exit;
4239 }
4240 in->standby = 0;
Andy Hung241e36f2019-02-19 12:00:38 -08004241
4242 // log startup time in ms.
4243 simple_stats_log(
4244 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004246
Andy Hungd13f0d32017-06-12 13:58:37 -07004247 // errors that occur here are read errors.
4248 error_code = ERROR_CODE_READ;
4249
Haynes Mathew George03c40102016-01-29 17:57:48 -08004250 //what's the duration requested by the client?
4251 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4252 in->config.rate;
4253 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004254
Haynes Mathew George03c40102016-01-29 17:57:48 -08004255 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004256 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08004257 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004258 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07004259 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004260 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004261 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004262 if (ret < 0) {
4263 ALOGE("Failed to read w/err %s", strerror(errno));
4264 ret = -errno;
4265 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004266 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4267 if (bytes % 4 == 0) {
4268 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4269 int_buf_stream = buffer;
4270 for (size_t itt=0; itt < bytes/4 ; itt++) {
4271 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07004272 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004273 } else {
4274 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
4275 ret = -EINVAL;
4276 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07004277 }
4278 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004279 }
4280
Haynes Mathew George03c40102016-01-29 17:57:48 -08004281 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004282
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004283 /*
4284 * Instead of writing zeroes here, we could trust the hardware
4285 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004286 * 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 -08004287 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08004288 if (ret == 0 && adev->mic_muted &&
4289 !voice_is_in_call_rec_stream(in) &&
4290 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004291 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07004292 in->frames_muted += frames;
4293 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004294
4295exit:
4296 pthread_mutex_unlock(&in->lock);
4297
4298 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07004299 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004300 in_standby(&in->stream.common);
4301 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004302 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08004303 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07004304 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08004305 }
4306 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07004307 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004308 }
4309 return bytes;
4310}
4311
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004312static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313{
4314 return 0;
4315}
4316
Andy Hung6ebe5962016-01-15 17:46:57 -08004317static int in_get_capture_position(const struct audio_stream_in *stream,
4318 int64_t *frames, int64_t *time)
4319{
4320 if (stream == NULL || frames == NULL || time == NULL) {
4321 return -EINVAL;
4322 }
4323 struct stream_in *in = (struct stream_in *)stream;
4324 int ret = -ENOSYS;
4325
4326 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004327 // note: ST sessions do not close the alsa pcm driver synchronously
4328 // on standby. Therefore, we may return an error even though the
4329 // pcm stream is still opened.
4330 if (in->standby) {
4331 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
4332 "%s stream in standby but pcm not NULL for non ST session", __func__);
4333 goto exit;
4334 }
Andy Hung6ebe5962016-01-15 17:46:57 -08004335 if (in->pcm) {
4336 struct timespec timestamp;
4337 unsigned int avail;
4338 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
4339 *frames = in->frames_read + avail;
4340 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
4341 ret = 0;
4342 }
4343 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004344exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08004345 pthread_mutex_unlock(&in->lock);
4346 return ret;
4347}
4348
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004349static int add_remove_audio_effect(const struct audio_stream *stream,
4350 effect_handle_t effect,
4351 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004352{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004353 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004354 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004355 int status = 0;
4356 effect_descriptor_t desc;
4357
4358 status = (*effect)->get_descriptor(effect, &desc);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004359 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
4360
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004361 if (status != 0)
4362 return status;
4363
Eric Laurenta1478072015-09-21 17:21:52 -07004364 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004365 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07004366 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07004367 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07004368 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004369 in->enable_aec != enable &&
4370 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4371 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004372 if (!enable)
4373 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07004374 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
4375 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
4376 adev->enable_voicerx = enable;
4377 struct audio_usecase *usecase;
4378 struct listnode *node;
4379 list_for_each(node, &adev->usecase_list) {
4380 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07004381 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07004382 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05004383 }
4384 }
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004385 if (!in->standby
4386 && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004387 select_devices(in->dev, in->usecase);
4388 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004389 if (in->enable_ns != enable &&
4390 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4391 in->enable_ns = enable;
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004392 if (!in->standby) {
4393 if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
4394 || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
4395 select_devices(in->dev, in->usecase);
4396 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004397 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004398 pthread_mutex_unlock(&in->dev->lock);
4399 pthread_mutex_unlock(&in->lock);
4400
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004401 return 0;
4402}
4403
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004404static int in_add_audio_effect(const struct audio_stream *stream,
4405 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004406{
Eric Laurent994a6932013-07-17 11:51:42 -07004407 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004408 return add_remove_audio_effect(stream, effect, true);
4409}
4410
4411static int in_remove_audio_effect(const struct audio_stream *stream,
4412 effect_handle_t effect)
4413{
Eric Laurent994a6932013-07-17 11:51:42 -07004414 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004415 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004416}
4417
Eric Laurent0e46adf2016-12-16 12:49:24 -08004418static int in_stop(const struct audio_stream_in* stream)
4419{
4420 struct stream_in *in = (struct stream_in *)stream;
4421 struct audio_device *adev = in->dev;
4422
4423 int ret = -ENOSYS;
4424 ALOGV("%s", __func__);
4425 pthread_mutex_lock(&adev->lock);
4426 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4427 in->capture_started && in->pcm != NULL) {
4428 pcm_stop(in->pcm);
4429 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08004430 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004431 }
4432 pthread_mutex_unlock(&adev->lock);
4433 return ret;
4434}
4435
4436static int in_start(const struct audio_stream_in* stream)
4437{
4438 struct stream_in *in = (struct stream_in *)stream;
4439 struct audio_device *adev = in->dev;
4440 int ret = -ENOSYS;
4441
4442 ALOGV("%s in %p", __func__, in);
4443 pthread_mutex_lock(&adev->lock);
4444 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4445 !in->capture_started && in->pcm != NULL) {
4446 if (!in->capture_started) {
4447 ret = start_input_stream(in);
4448 if (ret == 0) {
4449 in->capture_started = true;
4450 }
4451 }
4452 }
4453 pthread_mutex_unlock(&adev->lock);
4454 return ret;
4455}
4456
Phil Burk8a6a1652019-03-25 10:15:59 -07004457// Read offset for the positional timestamp from a persistent vendor property.
4458// This is to workaround apparent inaccuracies in the timing information that
4459// is used by the AAudio timing model. The inaccuracies can cause glitches.
Phil Burkc4714fc2019-02-16 22:28:11 -08004460static int64_t in_get_mmap_time_offset() {
Phil Burk8a6a1652019-03-25 10:15:59 -07004461 const int32_t kDefaultOffsetMicros = 0;
Phil Burkc4714fc2019-02-16 22:28:11 -08004462 int32_t mmap_time_offset_micros = property_get_int32(
Phil Burk8a6a1652019-03-25 10:15:59 -07004463 "persist.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkc4714fc2019-02-16 22:28:11 -08004464 ALOGI("in_get_mmap_time_offset set to %d micros", mmap_time_offset_micros);
4465 return mmap_time_offset_micros * (int64_t)1000;
4466}
4467
Eric Laurent0e46adf2016-12-16 12:49:24 -08004468static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4469 int32_t min_size_frames,
4470 struct audio_mmap_buffer_info *info)
4471{
4472 struct stream_in *in = (struct stream_in *)stream;
4473 struct audio_device *adev = in->dev;
4474 int ret = 0;
4475 unsigned int offset1;
4476 unsigned int frames1;
4477 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004478 uint32_t mmap_size;
4479 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004480
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004481 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004482 pthread_mutex_lock(&adev->lock);
4483 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004484
Eric Laurent0e46adf2016-12-16 12:49:24 -08004485 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004486 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004487 ret = -EINVAL;
4488 goto exit;
4489 }
4490 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004491 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004492 ALOGV("%s in %p", __func__, in);
4493 ret = -ENOSYS;
4494 goto exit;
4495 }
4496 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4497 if (in->pcm_device_id < 0) {
4498 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4499 __func__, in->pcm_device_id, in->usecase);
4500 ret = -EINVAL;
4501 goto exit;
4502 }
Phil Burkbc991042017-02-24 08:06:44 -08004503
4504 adjust_mmap_period_count(&in->config, min_size_frames);
4505
Eric Laurent0e46adf2016-12-16 12:49:24 -08004506 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4507 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4508 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4509 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4510 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4511 step = "open";
4512 ret = -ENODEV;
4513 goto exit;
4514 }
4515
4516 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4517 if (ret < 0) {
4518 step = "begin";
4519 goto exit;
4520 }
4521 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004522 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004523 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004524 ret = platform_get_mmap_data_fd(adev->platform,
4525 in->pcm_device_id, 1 /*capture*/,
4526 &info->shared_memory_fd,
4527 &mmap_size);
4528 if (ret < 0) {
4529 // Fall back to non exclusive mode
4530 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4531 } else {
4532 if (mmap_size < buffer_size) {
4533 step = "mmap";
4534 goto exit;
4535 }
4536 // FIXME: indicate exclusive mode support by returning a negative buffer size
4537 info->buffer_size_frames *= -1;
4538 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004539
Haynes Mathew George96483a22017-03-28 14:52:47 -07004540 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004541
4542 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4543 if (ret < 0) {
4544 step = "commit";
4545 goto exit;
4546 }
4547
Phil Burkc4714fc2019-02-16 22:28:11 -08004548 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
4549
Phil Burkbc991042017-02-24 08:06:44 -08004550 in->standby = false;
4551 ret = 0;
4552
Eric Laurent0e46adf2016-12-16 12:49:24 -08004553 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4554 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004555
4556exit:
4557 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004558 if (in->pcm == NULL) {
4559 ALOGE("%s: %s - %d", __func__, step, ret);
4560 } else {
4561 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004562 pcm_close(in->pcm);
4563 in->pcm = NULL;
4564 }
4565 }
4566 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004567 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004568 return ret;
4569}
4570
4571static int in_get_mmap_position(const struct audio_stream_in *stream,
4572 struct audio_mmap_position *position)
4573{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004574 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004575 struct stream_in *in = (struct stream_in *)stream;
4576 ALOGVV("%s", __func__);
4577 if (position == NULL) {
4578 return -EINVAL;
4579 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004580 lock_input_stream(in);
4581 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4582 in->pcm == NULL) {
4583 ret = -ENOSYS;
4584 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004585 }
4586 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004587 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004588 if (ret < 0) {
4589 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004590 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004591 }
Phil Burk8a6a1652019-03-25 10:15:59 -07004592 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts)
4593 + in->mmap_time_offset_nanos;
Phil Burkc4714fc2019-02-16 22:28:11 -08004594
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004595exit:
4596 pthread_mutex_unlock(&in->lock);
4597 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004598}
4599
jiabin8962a4d2018-03-19 18:21:24 -07004600static int in_get_active_microphones(const struct audio_stream_in *stream,
4601 struct audio_microphone_characteristic_t *mic_array,
4602 size_t *mic_count) {
4603 struct stream_in *in = (struct stream_in *)stream;
4604 struct audio_device *adev = in->dev;
4605 ALOGVV("%s", __func__);
4606
4607 lock_input_stream(in);
4608 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004609 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004610 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004611 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004612 pthread_mutex_unlock(&adev->lock);
4613 pthread_mutex_unlock(&in->lock);
4614
4615 return ret;
4616}
4617
4618static int adev_get_microphones(const struct audio_hw_device *dev,
4619 struct audio_microphone_characteristic_t *mic_array,
4620 size_t *mic_count) {
4621 struct audio_device *adev = (struct audio_device *)dev;
4622 ALOGVV("%s", __func__);
4623
4624 pthread_mutex_lock(&adev->lock);
4625 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4626 pthread_mutex_unlock(&adev->lock);
4627
4628 return ret;
4629}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004630
Paul McLean57530d52018-12-17 08:24:21 -07004631static int in_set_microphone_direction(const struct audio_stream_in *stream,
4632 audio_microphone_direction_t dir) {
justinwengc6347db2019-02-21 18:49:00 +08004633 struct stream_in *in = (struct stream_in *)stream;
4634
4635 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4636
4637 in->direction = dir;
4638
4639 if (in->standby)
4640 return 0;
4641
4642 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLean57530d52018-12-17 08:24:21 -07004643}
4644
4645static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinwengc6347db2019-02-21 18:49:00 +08004646 struct stream_in *in = (struct stream_in *)stream;
4647
4648 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4649
4650 if (zoom > 1.0 || zoom < -1.0)
4651 return -EINVAL;
4652
4653 in->zoom = zoom;
4654
4655 if (in->standby)
4656 return 0;
4657
4658 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLean57530d52018-12-17 08:24:21 -07004659}
4660
juyuchenba338cd2019-01-21 11:57:17 +08004661static void in_update_sink_metadata(struct audio_stream_in *stream,
4662 const struct sink_metadata *sink_metadata) {
4663
4664 if (stream == NULL
4665 || sink_metadata == NULL
4666 || sink_metadata->tracks == NULL) {
4667 return;
4668 }
4669
4670 int error = 0;
4671 struct stream_in *in = (struct stream_in *)stream;
4672 struct audio_device *adev = in->dev;
4673 audio_devices_t device = AUDIO_DEVICE_NONE;
4674
4675 if (sink_metadata->track_count != 0)
4676 device = sink_metadata->tracks->dest_device;
4677
4678 lock_input_stream(in);
4679 pthread_mutex_lock(&adev->lock);
4680 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
4681
4682 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
4683 && device != AUDIO_DEVICE_NONE
4684 && adev->voice_tx_output != NULL) {
4685 /* Use the rx device from afe-proxy record to route voice call because
4686 there is no routing if tx device is on primary hal and rx device
4687 is on other hal during voice call. */
4688 adev->voice_tx_output->devices = device;
4689
4690 if (!voice_is_call_state_active(adev)) {
4691 if (adev->mode == AUDIO_MODE_IN_CALL) {
4692 adev->current_call_output = adev->voice_tx_output;
4693 error = voice_start_call(adev);
4694 if (error != 0)
4695 ALOGE("%s: start voice call failed %d", __func__, error);
4696 }
4697 } else {
4698 adev->current_call_output = adev->voice_tx_output;
4699 voice_update_devices_for_all_voice_usecases(adev);
4700 }
4701 }
4702
4703 pthread_mutex_unlock(&adev->lock);
4704 pthread_mutex_unlock(&in->lock);
4705}
4706
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707static int adev_open_output_stream(struct audio_hw_device *dev,
4708 audio_io_handle_t handle,
4709 audio_devices_t devices,
4710 audio_output_flags_t flags,
4711 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004712 struct audio_stream_out **stream_out,
4713 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004714{
4715 struct audio_device *adev = (struct audio_device *)dev;
4716 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004717 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004718 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4719 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4720 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004721 bool force_haptic_path =
4722 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004723
Andy Hungd9653bd2017-08-01 19:31:39 -07004724 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4725 return -ENOSYS;
4726 }
4727
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004728 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4729 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004731 *stream_out = NULL;
4732 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4733
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004734 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4735
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004736 if (devices == AUDIO_DEVICE_NONE)
4737 devices = AUDIO_DEVICE_OUT_SPEAKER;
4738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004739 out->flags = flags;
4740 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004741 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004742 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004743 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004744
4745 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004746 if ((is_hdmi || is_usb_dev) &&
4747 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4748 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4749 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004750 audio_format_t req_format = config->format;
4751 audio_channel_mask_t req_channel_mask = config->channel_mask;
4752 uint32_t req_sample_rate = config->sample_rate;
4753
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004754 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004755 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004756 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004757 if (config->sample_rate == 0)
4758 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004759 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004760 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4761 if (config->format == AUDIO_FORMAT_DEFAULT)
4762 config->format = AUDIO_FORMAT_PCM_16_BIT;
4763 } else if (is_usb_dev) {
4764 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4765 &config->format,
4766 &out->supported_formats[0],
4767 MAX_SUPPORTED_FORMATS,
4768 &config->channel_mask,
4769 &out->supported_channel_masks[0],
4770 MAX_SUPPORTED_CHANNEL_MASKS,
4771 &config->sample_rate,
4772 &out->supported_sample_rates[0],
4773 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004774 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004775 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004776 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004777 if (ret != 0) {
4778 // For MMAP NO IRQ, allow conversions in ADSP
4779 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4780 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004781
Eric Laurentab805ee2018-03-30 12:20:38 -07004782 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4783 config->sample_rate = req_sample_rate;
4784 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4785 config->channel_mask = req_channel_mask;
4786 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4787 config->format = req_format;
4788 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004789
Haynes Mathew George569b7482017-05-08 14:44:27 -07004790 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004791 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004792 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004793 if (is_hdmi) {
4794 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4795 out->config = pcm_config_hdmi_multi;
4796 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4797 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4798 out->config = pcm_config_mmap_playback;
4799 out->stream.start = out_start;
4800 out->stream.stop = out_stop;
4801 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4802 out->stream.get_mmap_position = out_get_mmap_position;
4803 } else {
4804 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4805 out->config = pcm_config_hifi;
4806 }
4807
4808 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004809 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004810 if (is_hdmi) {
4811 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4812 audio_bytes_per_sample(out->format));
4813 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004814 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004815 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004816 pthread_mutex_lock(&adev->lock);
4817 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4818 pthread_mutex_unlock(&adev->lock);
4819
4820 // reject offload during card offline to allow
4821 // fallback to s/w paths
4822 if (offline) {
4823 ret = -ENODEV;
4824 goto error_open;
4825 }
4826
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004827 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4828 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4829 ALOGE("%s: Unsupported Offload information", __func__);
4830 ret = -EINVAL;
4831 goto error_open;
4832 }
4833 if (!is_supported_format(config->offload_info.format)) {
4834 ALOGE("%s: Unsupported audio format", __func__);
4835 ret = -EINVAL;
4836 goto error_open;
4837 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004838 out->sample_rate = config->offload_info.sample_rate;
4839 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4840 out->channel_mask = config->offload_info.channel_mask;
4841 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4842 out->channel_mask = config->channel_mask;
4843 else
4844 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4845
4846 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004847
4848 out->compr_config.codec = (struct snd_codec *)
4849 calloc(1, sizeof(struct snd_codec));
4850
4851 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004852
4853 out->stream.set_callback = out_set_callback;
4854 out->stream.pause = out_pause;
4855 out->stream.resume = out_resume;
4856 out->stream.drain = out_drain;
4857 out->stream.flush = out_flush;
4858
4859 out->compr_config.codec->id =
4860 get_snd_codec_id(config->offload_info.format);
4861 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4862 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004863 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004864 out->compr_config.codec->bit_rate =
4865 config->offload_info.bit_rate;
4866 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004867 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004868 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4869
4870 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4871 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004872
4873 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004874 create_offload_callback_thread(out);
4875 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4876 __func__, config->offload_info.version,
4877 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004878 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4879 switch (config->sample_rate) {
4880 case 0:
4881 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4882 break;
4883 case 8000:
4884 case 16000:
4885 case 48000:
4886 out->sample_rate = config->sample_rate;
4887 break;
4888 default:
4889 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4890 config->sample_rate);
4891 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4892 ret = -EINVAL;
4893 goto error_open;
4894 }
4895 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4896 switch (config->channel_mask) {
4897 case AUDIO_CHANNEL_NONE:
4898 case AUDIO_CHANNEL_OUT_STEREO:
4899 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4900 break;
4901 default:
4902 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4903 config->channel_mask);
4904 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4905 ret = -EINVAL;
4906 goto error_open;
4907 }
4908 switch (config->format) {
4909 case AUDIO_FORMAT_DEFAULT:
4910 case AUDIO_FORMAT_PCM_16_BIT:
4911 out->format = AUDIO_FORMAT_PCM_16_BIT;
4912 break;
4913 default:
4914 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4915 config->format);
4916 config->format = AUDIO_FORMAT_PCM_16_BIT;
4917 ret = -EINVAL;
4918 goto error_open;
4919 }
4920
4921 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004922 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004923 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004924 case 0:
4925 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4926 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004927 case 8000:
4928 case 16000:
4929 case 48000:
4930 out->sample_rate = config->sample_rate;
4931 break;
4932 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004933 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4934 config->sample_rate);
4935 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4936 ret = -EINVAL;
4937 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004938 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004939 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4940 switch (config->channel_mask) {
4941 case AUDIO_CHANNEL_NONE:
4942 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4943 break;
4944 case AUDIO_CHANNEL_OUT_STEREO:
4945 out->channel_mask = config->channel_mask;
4946 break;
4947 default:
4948 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4949 config->channel_mask);
4950 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4951 ret = -EINVAL;
4952 break;
4953 }
4954 switch (config->format) {
4955 case AUDIO_FORMAT_DEFAULT:
4956 out->format = AUDIO_FORMAT_PCM_16_BIT;
4957 break;
4958 case AUDIO_FORMAT_PCM_16_BIT:
4959 out->format = config->format;
4960 break;
4961 default:
4962 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4963 config->format);
4964 config->format = AUDIO_FORMAT_PCM_16_BIT;
4965 ret = -EINVAL;
4966 break;
4967 }
4968 if (ret != 0)
4969 goto error_open;
4970
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004971 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4972 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004973 out->config.rate = out->sample_rate;
4974 out->config.channels =
4975 audio_channel_count_from_out_mask(out->channel_mask);
4976 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004977 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004978 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4979 switch (config->sample_rate) {
4980 case 0:
4981 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4982 break;
4983 case 8000:
4984 case 16000:
4985 case 32000:
4986 case 48000:
4987 out->sample_rate = config->sample_rate;
4988 break;
4989 default:
4990 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4991 config->sample_rate);
4992 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4993 ret = -EINVAL;
4994 break;
4995 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004996 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004997 switch (config->channel_mask) {
4998 case AUDIO_CHANNEL_NONE:
4999 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5000 break;
5001 case AUDIO_CHANNEL_OUT_STEREO:
5002 out->channel_mask = config->channel_mask;
5003 break;
5004 default:
5005 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
5006 config->channel_mask);
5007 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5008 ret = -EINVAL;
5009 break;
5010 }
5011 switch (config->format) {
5012 case AUDIO_FORMAT_DEFAULT:
5013 out->format = AUDIO_FORMAT_PCM_16_BIT;
5014 break;
5015 case AUDIO_FORMAT_PCM_16_BIT:
5016 out->format = config->format;
5017 break;
5018 default:
5019 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
5020 config->format);
5021 config->format = AUDIO_FORMAT_PCM_16_BIT;
5022 ret = -EINVAL;
5023 break;
5024 }
5025 if (ret != 0)
5026 goto error_open;
5027
vivek mehtaa68fea62017-06-08 19:04:02 -07005028 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07005029 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5030 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005031 out->config.rate = out->sample_rate;
5032 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07005033 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005034 out->sample_rate,
5035 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07005036 out->config.channels,
5037 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005038 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07005039 out->config.period_size = buffer_size / frame_size;
5040 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
5041 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005042 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005043 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07005044 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5045 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005046 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07005047 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
5048 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005049 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07005050 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005051 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005052 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005053 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08005054 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5055 out->config = pcm_config_mmap_playback;
5056 out->stream.start = out_start;
5057 out->stream.stop = out_stop;
5058 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5059 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005060 } else {
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005061 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5062 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
5063 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
5064 if (adev->haptic_pcm_device_id < 0) {
5065 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
5066 __func__, adev->haptic_pcm_device_id, out->usecase);
5067 ret = -ENOSYS;
5068 goto error_open;
5069 }
5070 out->config = pcm_config_haptics_audio;
5071 if (force_haptic_path)
5072 adev->haptics_config = pcm_config_haptics_audio;
5073 else
5074 adev->haptics_config = pcm_config_haptics;
5075 } else {
5076 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
5077 out->config = pcm_config_low_latency;
5078 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07005079 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005080
5081 if (config->sample_rate == 0) {
5082 out->sample_rate = out->config.rate;
5083 } else {
5084 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005085 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005086
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005087 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
5088 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
5089 } else {
5090 out->channel_mask = config->channel_mask;
5091 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005092
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005093 if (config->format == AUDIO_FORMAT_DEFAULT)
5094 out->format = audio_format_from_pcm_format(out->config.format);
5095 else if (!audio_is_linear_pcm(config->format)) {
5096 config->format = AUDIO_FORMAT_PCM_16_BIT;
5097 ret = -EINVAL;
5098 goto error_open;
5099 } else {
5100 out->format = config->format;
5101 }
5102
5103 out->config.rate = out->sample_rate;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005104
5105 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5106 out->config.channels =
5107 audio_channel_count_from_out_mask(out->channel_mask &
5108 ~AUDIO_CHANNEL_HAPTIC_ALL);
5109
5110 if (force_haptic_path) {
5111 out->config.channels = 1;
5112 adev->haptics_config.channels = 1;
5113 } else {
5114 adev->haptics_config.channels =
5115 audio_channel_count_from_out_mask(out->channel_mask &
5116 AUDIO_CHANNEL_HAPTIC_ALL);
5117 }
5118 } else {
5119 out->config.channels =
5120 audio_channel_count_from_out_mask(out->channel_mask);
5121 }
5122
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005123 if (out->format != audio_format_from_pcm_format(out->config.format)) {
5124 out->config.format = pcm_format_from_audio_format(out->format);
5125 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005126 }
Kevin Rocard50eff892017-05-02 16:52:05 -07005127
5128 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
5129 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005130 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07005131 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
5132 __func__, config->sample_rate, config->format, config->channel_mask);
5133 config->sample_rate = out->sample_rate;
5134 config->format = out->format;
5135 config->channel_mask = out->channel_mask;
5136 ret = -EINVAL;
5137 goto error_open;
5138 }
5139
Andy Hung6fcba9c2014-03-18 11:53:32 -07005140 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
5141 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005142
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005143 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005144 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005145 adev->primary_output = out;
5146 else {
5147 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005148 ret = -EEXIST;
5149 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005150 }
5151 }
5152
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005153 /* Check if this usecase is already existing */
5154 pthread_mutex_lock(&adev->lock);
5155 if (get_usecase_from_list(adev, out->usecase) != NULL) {
5156 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005157 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005158 ret = -EEXIST;
5159 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005160 }
5161 pthread_mutex_unlock(&adev->lock);
5162
5163 out->stream.common.get_sample_rate = out_get_sample_rate;
5164 out->stream.common.set_sample_rate = out_set_sample_rate;
5165 out->stream.common.get_buffer_size = out_get_buffer_size;
5166 out->stream.common.get_channels = out_get_channels;
5167 out->stream.common.get_format = out_get_format;
5168 out->stream.common.set_format = out_set_format;
5169 out->stream.common.standby = out_standby;
5170 out->stream.common.dump = out_dump;
5171 out->stream.common.set_parameters = out_set_parameters;
5172 out->stream.common.get_parameters = out_get_parameters;
5173 out->stream.common.add_audio_effect = out_add_audio_effect;
5174 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5175 out->stream.get_latency = out_get_latency;
5176 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005177#ifdef NO_AUDIO_OUT
5178 out->stream.write = out_write_for_no_output;
5179#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005180 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005181#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005182 out->stream.get_render_position = out_get_render_position;
5183 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005184 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005185
Eric Laurent0e46adf2016-12-16 12:49:24 -08005186 if (out->realtime)
5187 out->af_period_multiplier = af_period_multiplier;
5188 else
5189 out->af_period_multiplier = 1;
5190
Andy Hung572633e2019-02-19 11:58:24 -08005191 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
5192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005193 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005194 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005195 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005196
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005197 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005198 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005199 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005201 config->format = out->stream.common.get_format(&out->stream.common);
5202 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5203 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5204
Kevin Rocarda325aa22018-04-03 09:15:52 -07005205 register_format(out->format, out->supported_formats);
5206 register_channel_mask(out->channel_mask, out->supported_channel_masks);
5207 register_sample_rate(out->sample_rate, out->supported_sample_rates);
5208
Andy Hunga452b0a2017-03-15 14:51:15 -07005209 out->error_log = error_log_create(
5210 ERROR_LOG_ENTRIES,
5211 1000000000 /* aggregate consecutive identical errors within one second in ns */);
5212
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005213 /*
5214 By locking output stream before registering, we allow the callback
5215 to update stream's state only after stream's initial state is set to
5216 adev state.
5217 */
5218 lock_output_stream(out);
5219 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5220 pthread_mutex_lock(&adev->lock);
5221 out->card_status = adev->card_status;
5222 pthread_mutex_unlock(&adev->lock);
5223 pthread_mutex_unlock(&out->lock);
5224
vivek mehta4a824772017-06-08 19:05:49 -07005225 stream_app_type_cfg_init(&out->app_type_cfg);
5226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005227 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005228
Eric Laurent994a6932013-07-17 11:51:42 -07005229 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005230 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005231
5232error_open:
5233 free(out);
5234 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07005235 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005236 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005237}
5238
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005239static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005240 struct audio_stream_out *stream)
5241{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005242 struct stream_out *out = (struct stream_out *)stream;
5243 struct audio_device *adev = out->dev;
5244
Eric Laurent994a6932013-07-17 11:51:42 -07005245 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005246
5247 // must deregister from sndmonitor first to prevent races
5248 // between the callback and close_stream
5249 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005250 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005251 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
5252 destroy_offload_callback_thread(out);
5253
5254 if (out->compr_config.codec != NULL)
5255 free(out->compr_config.codec);
5256 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005257
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005258 out->a2dp_compress_mute = false;
5259
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005260 if (adev->voice_tx_output == out)
5261 adev->voice_tx_output = NULL;
5262
Andy Hunga452b0a2017-03-15 14:51:15 -07005263 error_log_destroy(out->error_log);
5264 out->error_log = NULL;
5265
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005266 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005267 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005268 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005269 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005270 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005271}
5272
5273static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5274{
5275 struct audio_device *adev = (struct audio_device *)dev;
5276 struct str_parms *parms;
5277 char *str;
5278 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005279 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005280 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07005281 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005282 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005283
Joe Onorato188b6222016-03-01 11:02:27 -08005284 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005285
5286 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005287
5288 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005289 status = voice_set_parameters(adev, parms);
5290 if (status != 0) {
5291 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005292 }
5293
5294 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5295 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07005296 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005297 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5298 adev->bluetooth_nrec = true;
5299 else
5300 adev->bluetooth_nrec = false;
5301 }
5302
5303 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5304 if (ret >= 0) {
5305 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5306 adev->screen_off = false;
5307 else
5308 adev->screen_off = true;
5309 }
5310
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005311 ret = str_parms_get_int(parms, "rotation", &val);
5312 if (ret >= 0) {
5313 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005314 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005315 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005316 // FIXME: note that the code below assumes that the speakers are in the correct placement
5317 // relative to the user when the device is rotated 90deg from its default rotation. This
5318 // assumption is device-specific, not platform-specific like this code.
5319 case 270:
5320 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005321 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005322 break;
5323 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005324 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07005325 camera_rotation = CAMERA_ROTATION_PORTRAIT;
5326 break;
5327 case 90:
5328 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005329 break;
5330 default:
5331 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07005332 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005333 }
Eric Laurent03f09432014-03-25 18:09:11 -07005334 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07005335 // check and set swap
5336 // - check if orientation changed and speaker active
5337 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07005338 adev->camera_orientation =
5339 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
5340#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07005341 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07005342#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005343 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005344 }
5345
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005346 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5347 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005348 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005349 }
5350
Aniket Kumar Lata8f270262019-05-08 15:56:56 -07005351 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
5352 if (ret >= 0) {
5353 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5354 adev->bt_sco_on = true;
5355 else
5356 adev->bt_sco_on = false;
5357 }
5358
David Linee3fe402017-03-13 10:00:42 -07005359 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5360 if (ret >= 0) {
5361 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005362 if (audio_is_usb_out_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_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005367 }
Eric Laurent99dab492017-06-17 15:19:08 -07005368 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005369 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5370 if (ret >= 0) {
5371 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005372 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005373 }
5374 }
5375 }
5376
5377 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5378 if (ret >= 0) {
5379 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005380 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005381 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5382 if (ret >= 0) {
5383 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005384 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005385 }
Eric Laurent99dab492017-06-17 15:19:08 -07005386 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005387 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5388 if (ret >= 0) {
5389 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005390 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005391 }
5392 }
5393 }
5394
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08005395 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08005396 audio_extn_ma_set_parameters(adev, parms);
5397
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005398 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
5399 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005400 struct audio_usecase *usecase;
5401 struct listnode *node;
5402 list_for_each(node, &adev->usecase_list) {
5403 usecase = node_to_item(node, struct audio_usecase, list);
5404 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005405 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005406 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
5407
5408 pthread_mutex_unlock(&adev->lock);
5409 lock_output_stream(usecase->stream.out);
5410 pthread_mutex_lock(&adev->lock);
5411 audio_extn_a2dp_set_handoff_mode(true);
5412 // force device switch to reconfigure encoder
5413 select_devices(adev, usecase->id);
5414 audio_extn_a2dp_set_handoff_mode(false);
5415 pthread_mutex_unlock(&usecase->stream.out->lock);
5416 break;
5417 }
5418 }
5419 }
5420
Eric Laurent5f4ca952018-10-19 17:33:43 -07005421 //FIXME: to be replaced by proper video capture properties API
5422 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
5423 if (ret >= 0) {
5424 int camera_facing = CAMERA_FACING_BACK;
5425 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
5426 camera_facing = CAMERA_FACING_FRONT;
5427 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
5428 camera_facing = CAMERA_FACING_BACK;
5429 else {
5430 ALOGW("%s: invalid camera facing value: %s", __func__, value);
5431 goto done;
5432 }
5433 adev->camera_orientation =
5434 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
5435 struct audio_usecase *usecase;
5436 struct listnode *node;
5437 list_for_each(node, &adev->usecase_list) {
5438 usecase = node_to_item(node, struct audio_usecase, list);
5439 struct stream_in *in = usecase->stream.in;
5440 if (usecase->type == PCM_CAPTURE && in != NULL &&
5441 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
5442 select_devices(adev, in->usecase);
5443 }
5444 }
5445 }
5446
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005447done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005448 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005449 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07005450 ALOGV("%s: exit with code(%d)", __func__, status);
5451 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005452}
5453
5454static char* adev_get_parameters(const struct audio_hw_device *dev,
5455 const char *keys)
5456{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005457 struct audio_device *adev = (struct audio_device *)dev;
5458 struct str_parms *reply = str_parms_create();
5459 struct str_parms *query = str_parms_create_str(keys);
5460 char *str;
5461
5462 pthread_mutex_lock(&adev->lock);
5463
5464 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005465 audio_extn_a2dp_get_parameters(query, reply);
5466
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005467 str = str_parms_to_str(reply);
5468 str_parms_destroy(query);
5469 str_parms_destroy(reply);
5470
5471 pthread_mutex_unlock(&adev->lock);
5472 ALOGV("%s: exit: returns - %s", __func__, str);
5473 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005474}
5475
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005476static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005477{
5478 return 0;
5479}
5480
Haynes Mathew George5191a852013-09-11 14:19:36 -07005481static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5482{
5483 int ret;
5484 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005485
Eric Laurent4cc4ce12014-09-10 13:21:01 -05005486 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
5487
Haynes Mathew George5191a852013-09-11 14:19:36 -07005488 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005489 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005490 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005491
Haynes Mathew George5191a852013-09-11 14:19:36 -07005492 return ret;
5493}
5494
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005495static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005496{
5497 return -ENOSYS;
5498}
5499
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005500static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5501 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005502{
5503 return -ENOSYS;
5504}
5505
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005506static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005507{
5508 return -ENOSYS;
5509}
5510
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005511static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005512{
5513 return -ENOSYS;
5514}
5515
5516static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5517{
5518 struct audio_device *adev = (struct audio_device *)dev;
5519
5520 pthread_mutex_lock(&adev->lock);
5521 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07005522 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005523 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005524 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
5525 voice_is_in_call(adev)) {
5526 voice_stop_call(adev);
5527 adev->current_call_output = NULL;
HW Leef88584d2019-03-18 17:27:18 +08005528
5529 /*
5530 * After stopping the call, it must check if any active capture
5531 * activity device needs to be re-selected.
5532 */
5533 struct audio_usecase *usecase;
5534 struct listnode *node;
5535 list_for_each(node, &adev->usecase_list) {
5536 usecase = node_to_item(node, struct audio_usecase, list);
5537 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
5538 select_devices_with_force_switch(adev, usecase->id, true);
5539 }
5540 }
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005541 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005542 }
5543 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05005544
5545 audio_extn_extspk_set_mode(adev->extspk, mode);
5546
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005547 return 0;
5548}
5549
5550static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5551{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005552 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005553 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005554
Eric Laurent2bafff12016-03-17 12:17:23 -07005555 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005556 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005557 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
5558 ret = audio_extn_hfp_set_mic_mute(adev, state);
5559 } else {
5560 ret = voice_set_mic_mute(adev, state);
5561 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005562 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005563 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005564
5565 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005566}
5567
5568static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5569{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005570 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005571 return 0;
5572}
5573
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005574static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005575 const struct audio_config *config)
5576{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005577 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005578
Eric Laurent74b55762017-07-09 17:04:53 -07005579 /* Don't know if USB HIFI in this context so use true to be conservative */
5580 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5581 true /*is_usb_hifi */) != 0)
5582 return 0;
5583
vivek mehtaa68fea62017-06-08 19:04:02 -07005584 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5585 config->sample_rate, config->format,
5586 channel_count,
5587 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005588}
5589
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005590static bool adev_input_allow_hifi_record(struct audio_device *adev,
5591 audio_devices_t devices,
5592 audio_input_flags_t flags,
5593 audio_source_t source) {
5594 const bool allowed = true;
5595
5596 if (!audio_is_usb_in_device(devices))
5597 return !allowed;
5598
5599 switch (flags) {
5600 case AUDIO_INPUT_FLAG_NONE:
5601 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5602 break;
5603 default:
5604 return !allowed;
5605 }
5606
5607 switch (source) {
5608 case AUDIO_SOURCE_DEFAULT:
5609 case AUDIO_SOURCE_MIC:
5610 case AUDIO_SOURCE_UNPROCESSED:
5611 break;
5612 default:
5613 return !allowed;
5614 }
5615
5616 switch (adev->mode) {
5617 case 0:
5618 break;
5619 default:
5620 return !allowed;
5621 }
5622
5623 return allowed;
5624}
5625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005626static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005627 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005628 audio_devices_t devices,
5629 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005630 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005631 audio_input_flags_t flags,
5632 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005633 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005634{
5635 struct audio_device *adev = (struct audio_device *)dev;
5636 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005637 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005638 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005639 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005640 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005641 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5642 devices,
5643 flags,
5644 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005645 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5646 " sample_rate %u, channel_mask %#x, format %#x",
5647 __func__, flags, is_usb_dev, may_use_hifi_record,
5648 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005649 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005650
Andy Hungd9653bd2017-08-01 19:31:39 -07005651 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5652 return -ENOSYS;
5653 }
5654
Eric Laurent74b55762017-07-09 17:04:53 -07005655 if (!(is_usb_dev && may_use_hifi_record)) {
5656 if (config->sample_rate == 0)
5657 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5658 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5659 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5660 if (config->format == AUDIO_FORMAT_DEFAULT)
5661 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005662
Eric Laurent74b55762017-07-09 17:04:53 -07005663 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5664
5665 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5666 return -EINVAL;
5667 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005668
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005669 if (audio_extn_tfa_98xx_is_supported() &&
5670 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005671 return -EINVAL;
5672
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005673 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5674
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005675 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005676 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005677
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005678 in->stream.common.get_sample_rate = in_get_sample_rate;
5679 in->stream.common.set_sample_rate = in_set_sample_rate;
5680 in->stream.common.get_buffer_size = in_get_buffer_size;
5681 in->stream.common.get_channels = in_get_channels;
5682 in->stream.common.get_format = in_get_format;
5683 in->stream.common.set_format = in_set_format;
5684 in->stream.common.standby = in_standby;
5685 in->stream.common.dump = in_dump;
5686 in->stream.common.set_parameters = in_set_parameters;
5687 in->stream.common.get_parameters = in_get_parameters;
5688 in->stream.common.add_audio_effect = in_add_audio_effect;
5689 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5690 in->stream.set_gain = in_set_gain;
5691 in->stream.read = in_read;
5692 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005693 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005694 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLean57530d52018-12-17 08:24:21 -07005695 in->stream.set_microphone_direction = in_set_microphone_direction;
5696 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchenba338cd2019-01-21 11:57:17 +08005697 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005698
5699 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005700 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005701 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005702 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005703 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005704 in->flags = flags;
justinwengc6347db2019-02-21 18:49:00 +08005705 in->direction = MIC_DIRECTION_UNSPECIFIED;
5706 in->zoom = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005707
Andy Hung88ce1d92018-10-29 18:31:12 -07005708 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005709 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5710 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5711 /* Force channel config requested to mono if incall
5712 record is being requested for only uplink/downlink */
5713 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5714 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5715 ret = -EINVAL;
5716 goto err_open;
5717 }
5718 }
5719
Haynes Mathew George569b7482017-05-08 14:44:27 -07005720 if (is_usb_dev && may_use_hifi_record) {
5721 /* HiFi record selects an appropriate format, channel, rate combo
5722 depending on sink capabilities*/
5723 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5724 &config->format,
5725 &in->supported_formats[0],
5726 MAX_SUPPORTED_FORMATS,
5727 &config->channel_mask,
5728 &in->supported_channel_masks[0],
5729 MAX_SUPPORTED_CHANNEL_MASKS,
5730 &config->sample_rate,
5731 &in->supported_sample_rates[0],
5732 MAX_SUPPORTED_SAMPLE_RATES);
5733 if (ret != 0) {
5734 ret = -EINVAL;
5735 goto err_open;
5736 }
Eric Laurent74b55762017-07-09 17:04:53 -07005737 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005738 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005739 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005740 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5741 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5742 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5743 bool ret_error = false;
5744 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5745 from HAL is 8_24
5746 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5747 8_24 return error indicating supported format is 8_24
5748 *> In case of any other source requesting 24 bit or float return error
5749 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005750
vivek mehta57ff9b52016-04-28 14:13:08 -07005751 on error flinger will retry with supported format passed
5752 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005753 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005754 config->format = AUDIO_FORMAT_PCM_16_BIT;
5755 ret_error = true;
5756 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5757 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5758 ret_error = true;
5759 }
5760
5761 if (ret_error) {
5762 ret = -EINVAL;
5763 goto err_open;
5764 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005765 }
5766
vivek mehta57ff9b52016-04-28 14:13:08 -07005767 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005768 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005770 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005771 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5772 if (config->sample_rate == 0)
5773 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5774 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5775 config->sample_rate != 8000) {
5776 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5777 ret = -EINVAL;
5778 goto err_open;
5779 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005780
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005781 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5782 config->format = AUDIO_FORMAT_PCM_16_BIT;
5783 ret = -EINVAL;
5784 goto err_open;
5785 }
5786
5787 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5788 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005789 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005790 } else if (is_usb_dev && may_use_hifi_record) {
5791 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5792 in->config = pcm_config_audio_capture;
5793 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005794 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5795 config->sample_rate,
5796 config->format,
5797 channel_count,
5798 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005799 in->config.period_size = buffer_size / frame_size;
5800 in->config.rate = config->sample_rate;
5801 in->af_period_multiplier = 1;
5802 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005803 } else {
5804 in->usecase = USECASE_AUDIO_RECORD;
5805 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005806 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005807 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005808#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005809 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005810#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005811 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005812 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005813 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005814 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005815 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5816 config->sample_rate,
5817 config->format,
5818 channel_count,
5819 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005820 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005821 in->config.rate = config->sample_rate;
5822 in->af_period_multiplier = 1;
5823 } else {
5824 // period size is left untouched for rt mode playback
5825 in->config = pcm_config_audio_capture_rt;
5826 in->af_period_multiplier = af_period_multiplier;
5827 }
5828 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5829 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005830 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005831 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5832 in->config = pcm_config_mmap_capture;
5833 in->stream.start = in_start;
5834 in->stream.stop = in_stop;
5835 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5836 in->stream.get_mmap_position = in_get_mmap_position;
5837 in->af_period_multiplier = 1;
5838 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005839 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005840 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005841 (config->sample_rate == 8000 ||
5842 config->sample_rate == 16000 ||
5843 config->sample_rate == 32000 ||
5844 config->sample_rate == 48000) &&
5845 channel_count == 1) {
5846 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5847 in->config = pcm_config_audio_capture;
5848 frame_size = audio_stream_in_frame_size(&in->stream);
5849 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5850 config->sample_rate,
5851 config->format,
5852 channel_count, false /*is_low_latency*/);
5853 in->config.period_size = buffer_size / frame_size;
5854 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5855 in->config.rate = config->sample_rate;
5856 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005857 } else {
5858 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005859 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005860 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5861 config->sample_rate,
5862 config->format,
5863 channel_count,
5864 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005865 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005866 in->config.rate = config->sample_rate;
5867 in->af_period_multiplier = 1;
5868 }
5869 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5870 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005871 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005872
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005873 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005874 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005875
Kevin Rocarda325aa22018-04-03 09:15:52 -07005876
5877 register_format(in->format, in->supported_formats);
5878 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5879 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5880
Andy Hungd13f0d32017-06-12 13:58:37 -07005881 in->error_log = error_log_create(
5882 ERROR_LOG_ENTRIES,
5883 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5884
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005885 /* This stream could be for sound trigger lab,
5886 get sound trigger pcm if present */
5887 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005888
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005889 lock_input_stream(in);
5890 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5891 pthread_mutex_lock(&adev->lock);
5892 in->card_status = adev->card_status;
5893 pthread_mutex_unlock(&adev->lock);
5894 pthread_mutex_unlock(&in->lock);
5895
vivek mehta4a824772017-06-08 19:05:49 -07005896 stream_app_type_cfg_init(&in->app_type_cfg);
5897
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005898 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005899 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005900 return 0;
5901
5902err_open:
5903 free(in);
5904 *stream_in = NULL;
5905 return ret;
5906}
5907
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005908static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005909 struct audio_stream_in *stream)
5910{
Andy Hungd13f0d32017-06-12 13:58:37 -07005911 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005912 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005913
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005914 // must deregister from sndmonitor first to prevent races
5915 // between the callback and close_stream
5916 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005917 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005918
5919 error_log_destroy(in->error_log);
5920 in->error_log = NULL;
5921
Andy Hung0dbb52b2017-08-09 13:51:38 -07005922 pthread_mutex_destroy(&in->pre_lock);
5923 pthread_mutex_destroy(&in->lock);
5924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005925 free(stream);
5926
5927 return;
5928}
5929
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005930static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005931{
5932 return 0;
5933}
5934
Andy Hung31aca912014-03-20 17:14:59 -07005935/* verifies input and output devices and their capabilities.
5936 *
5937 * This verification is required when enabling extended bit-depth or
5938 * sampling rates, as not all qcom products support it.
5939 *
5940 * Suitable for calling only on initialization such as adev_open().
5941 * It fills the audio_device use_case_table[] array.
5942 *
5943 * Has a side-effect that it needs to configure audio routing / devices
5944 * in order to power up the devices and read the device parameters.
5945 * It does not acquire any hw device lock. Should restore the devices
5946 * back to "normal state" upon completion.
5947 */
5948static int adev_verify_devices(struct audio_device *adev)
5949{
5950 /* enumeration is a bit difficult because one really wants to pull
5951 * the use_case, device id, etc from the hidden pcm_device_table[].
5952 * In this case there are the following use cases and device ids.
5953 *
5954 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5955 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005956 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005957 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5958 * [USECASE_AUDIO_RECORD] = {0, 0},
5959 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5960 * [USECASE_VOICE_CALL] = {2, 2},
5961 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005962 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005963 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5964 */
5965
5966 /* should be the usecases enabled in adev_open_input_stream() */
5967 static const int test_in_usecases[] = {
5968 USECASE_AUDIO_RECORD,
5969 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5970 };
5971 /* should be the usecases enabled in adev_open_output_stream()*/
5972 static const int test_out_usecases[] = {
5973 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5974 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5975 };
5976 static const usecase_type_t usecase_type_by_dir[] = {
5977 PCM_PLAYBACK,
5978 PCM_CAPTURE,
5979 };
5980 static const unsigned flags_by_dir[] = {
5981 PCM_OUT,
5982 PCM_IN,
5983 };
5984
5985 size_t i;
5986 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005987 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005988 char info[512]; /* for possible debug info */
5989
5990 for (dir = 0; dir < 2; ++dir) {
5991 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5992 const unsigned flags_dir = flags_by_dir[dir];
5993 const size_t testsize =
5994 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5995 const int *testcases =
5996 dir ? test_in_usecases : test_out_usecases;
5997 const audio_devices_t audio_device =
5998 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5999
6000 for (i = 0; i < testsize; ++i) {
6001 const audio_usecase_t audio_usecase = testcases[i];
6002 int device_id;
6003 snd_device_t snd_device;
6004 struct pcm_params **pparams;
6005 struct stream_out out;
6006 struct stream_in in;
6007 struct audio_usecase uc_info;
6008 int retval;
6009
6010 pparams = &adev->use_case_table[audio_usecase];
6011 pcm_params_free(*pparams); /* can accept null input */
6012 *pparams = NULL;
6013
6014 /* find the device ID for the use case (signed, for error) */
6015 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
6016 if (device_id < 0)
6017 continue;
6018
6019 /* prepare structures for device probing */
6020 memset(&uc_info, 0, sizeof(uc_info));
6021 uc_info.id = audio_usecase;
6022 uc_info.type = usecase_type;
6023 if (dir) {
Andy Hung31aca912014-03-20 17:14:59 -07006024 memset(&in, 0, sizeof(in));
6025 in.device = audio_device;
6026 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
6027 uc_info.stream.in = &in;
Andy Hung31aca912014-03-20 17:14:59 -07006028 }
6029 memset(&out, 0, sizeof(out));
6030 out.devices = audio_device; /* only field needed in select_devices */
6031 uc_info.stream.out = &out;
6032 uc_info.devices = audio_device;
6033 uc_info.in_snd_device = SND_DEVICE_NONE;
6034 uc_info.out_snd_device = SND_DEVICE_NONE;
6035 list_add_tail(&adev->usecase_list, &uc_info.list);
6036
6037 /* select device - similar to start_(in/out)put_stream() */
6038 retval = select_devices(adev, audio_usecase);
6039 if (retval >= 0) {
6040 *pparams = pcm_params_get(card_id, device_id, flags_dir);
6041#if LOG_NDEBUG == 0
6042 if (*pparams) {
6043 ALOGV("%s: (%s) card %d device %d", __func__,
6044 dir ? "input" : "output", card_id, device_id);
6045 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07006046 } else {
6047 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
6048 }
6049#endif
6050 }
6051
6052 /* deselect device - similar to stop_(in/out)put_stream() */
6053 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07006054 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07006055 /* 2. Disable the rx device */
6056 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07006057 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07006058 list_remove(&uc_info.list);
6059 }
6060 }
Andy Hung31aca912014-03-20 17:14:59 -07006061 return 0;
6062}
6063
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006064static int adev_close(hw_device_t *device)
6065{
Andy Hung31aca912014-03-20 17:14:59 -07006066 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006067 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006068
6069 if (!adev)
6070 return 0;
6071
6072 pthread_mutex_lock(&adev_init_lock);
6073
6074 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006075 audio_extn_snd_mon_unregister_listener(adev);
6076 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08006077 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006078 audio_route_free(adev->audio_route);
6079 free(adev->snd_dev_ref_cnt);
6080 platform_deinit(adev->platform);
6081 audio_extn_extspk_deinit(adev->extspk);
6082 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006083 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006084 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
6085 pcm_params_free(adev->use_case_table[i]);
6086 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006087 if (adev->adm_deinit)
6088 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07006089 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006090 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07006091 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07006092
6093 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006095 return 0;
6096}
6097
Glenn Kasten4f993392014-05-14 07:30:48 -07006098/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6099 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6100 * just that it _might_ work.
6101 */
6102static int period_size_is_plausible_for_low_latency(int period_size)
6103{
6104 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006105 case 48:
6106 case 96:
6107 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07006108 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006109 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07006110 case 240:
6111 case 320:
6112 case 480:
6113 return 1;
6114 default:
6115 return 0;
6116 }
6117}
6118
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006119static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
6120{
6121 int card;
6122 card_status_t status;
6123
6124 if (!parms)
6125 return;
6126
6127 if (parse_snd_card_status(parms, &card, &status) < 0)
6128 return;
6129
6130 pthread_mutex_lock(&adev->lock);
6131 bool valid_cb = (card == adev->snd_card);
6132 if (valid_cb) {
6133 if (adev->card_status != status) {
6134 adev->card_status = status;
6135 platform_snd_card_update(adev->platform, status);
6136 }
6137 }
6138 pthread_mutex_unlock(&adev->lock);
6139 return;
6140}
6141
Aniket Kumar Lata26483012018-01-31 20:21:42 -08006142/* out and adev lock held */
6143static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6144{
6145 struct audio_usecase *uc_info;
6146 float left_p;
6147 float right_p;
6148 audio_devices_t devices;
6149
6150 uc_info = get_usecase_from_list(adev, out->usecase);
6151 if (uc_info == NULL) {
6152 ALOGE("%s: Could not find the usecase (%d) in the list",
6153 __func__, out->usecase);
6154 return -EINVAL;
6155 }
6156
6157 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6158 out->usecase, use_case_table[out->usecase]);
6159
6160 if (restore) {
6161 // restore A2DP device for active usecases and unmute if required
6162 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6163 !is_a2dp_device(uc_info->out_snd_device)) {
6164 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
6165 select_devices(adev, uc_info->id);
6166 pthread_mutex_lock(&out->compr_mute_lock);
6167 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6168 (out->a2dp_compress_mute)) {
6169 out->a2dp_compress_mute = false;
6170 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6171 }
6172 pthread_mutex_unlock(&out->compr_mute_lock);
6173 }
6174 } else {
6175 // mute compress stream if suspended
6176 pthread_mutex_lock(&out->compr_mute_lock);
6177 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6178 (!out->a2dp_compress_mute)) {
6179 if (!out->standby) {
6180 ALOGD("%s: selecting speaker and muting stream", __func__);
6181 devices = out->devices;
6182 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6183 left_p = out->volume_l;
6184 right_p = out->volume_r;
6185 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6186 compress_pause(out->compr);
6187 set_compr_volume(&out->stream, 0.0f, 0.0f);
6188 out->a2dp_compress_mute = true;
6189 select_devices(adev, out->usecase);
6190 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6191 compress_resume(out->compr);
6192 out->devices = devices;
6193 out->volume_l = left_p;
6194 out->volume_r = right_p;
6195 }
6196 }
6197 pthread_mutex_unlock(&out->compr_mute_lock);
6198 }
6199 ALOGV("%s: exit", __func__);
6200 return 0;
6201}
6202
6203int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6204{
6205 int ret = 0;
6206
6207 lock_output_stream(out);
6208 pthread_mutex_lock(&adev->lock);
6209
6210 ret = check_a2dp_restore_l(adev, out, restore);
6211
6212 pthread_mutex_unlock(&adev->lock);
6213 pthread_mutex_unlock(&out->lock);
6214 return ret;
6215}
6216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006217static int adev_open(const hw_module_t *module, const char *name,
6218 hw_device_t **device)
6219{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07006220 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006221
Eric Laurent2bafff12016-03-17 12:17:23 -07006222 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006223 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006224 pthread_mutex_lock(&adev_init_lock);
6225 if (audio_device_ref_count != 0) {
6226 *device = &adev->device.common;
6227 audio_device_ref_count++;
6228 ALOGV("%s: returning existing instance of adev", __func__);
6229 ALOGV("%s: exit", __func__);
6230 pthread_mutex_unlock(&adev_init_lock);
6231 return 0;
6232 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006233 adev = calloc(1, sizeof(struct audio_device));
6234
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006235 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6236
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006237 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6238 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6239 adev->device.common.module = (struct hw_module_t *)module;
6240 adev->device.common.close = adev_close;
6241
6242 adev->device.init_check = adev_init_check;
6243 adev->device.set_voice_volume = adev_set_voice_volume;
6244 adev->device.set_master_volume = adev_set_master_volume;
6245 adev->device.get_master_volume = adev_get_master_volume;
6246 adev->device.set_master_mute = adev_set_master_mute;
6247 adev->device.get_master_mute = adev_get_master_mute;
6248 adev->device.set_mode = adev_set_mode;
6249 adev->device.set_mic_mute = adev_set_mic_mute;
6250 adev->device.get_mic_mute = adev_get_mic_mute;
6251 adev->device.set_parameters = adev_set_parameters;
6252 adev->device.get_parameters = adev_get_parameters;
6253 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6254 adev->device.open_output_stream = adev_open_output_stream;
6255 adev->device.close_output_stream = adev_close_output_stream;
6256 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006258 adev->device.close_input_stream = adev_close_input_stream;
6259 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07006260 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006261
6262 /* Set the default route before the PCM stream is opened */
6263 pthread_mutex_lock(&adev->lock);
6264 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006265 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006266 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006267 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006268 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006269 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006270 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006271 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006272 pthread_mutex_unlock(&adev->lock);
6273
6274 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006275 adev->platform = platform_init(adev);
6276 if (!adev->platform) {
6277 free(adev->snd_dev_ref_cnt);
6278 free(adev);
6279 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6280 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006281 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006282 return -EINVAL;
6283 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05006284 adev->extspk = audio_extn_extspk_init(adev);
6285
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006286 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6287 if (adev->visualizer_lib == NULL) {
6288 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6289 } else {
6290 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6291 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07006292 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006293 "visualizer_hal_start_output");
6294 adev->visualizer_stop_output =
6295 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
6296 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07006297 }
6298
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006299 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6300 if (adev->offload_effects_lib == NULL) {
6301 ALOGW("%s: DLOPEN failed for %s", __func__,
6302 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6303 } else {
6304 ALOGV("%s: DLOPEN successful for %s", __func__,
6305 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6306 adev->offload_effects_start_output =
6307 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6308 "offload_effects_bundle_hal_start_output");
6309 adev->offload_effects_stop_output =
6310 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6311 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07006312 }
6313
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006314 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6315 if (adev->adm_lib == NULL) {
6316 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6317 } else {
6318 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6319 adev->adm_init = (adm_init_t)
6320 dlsym(adev->adm_lib, "adm_init");
6321 adev->adm_deinit = (adm_deinit_t)
6322 dlsym(adev->adm_lib, "adm_deinit");
6323 adev->adm_register_input_stream = (adm_register_input_stream_t)
6324 dlsym(adev->adm_lib, "adm_register_input_stream");
6325 adev->adm_register_output_stream = (adm_register_output_stream_t)
6326 dlsym(adev->adm_lib, "adm_register_output_stream");
6327 adev->adm_deregister_stream = (adm_deregister_stream_t)
6328 dlsym(adev->adm_lib, "adm_deregister_stream");
6329 adev->adm_request_focus = (adm_request_focus_t)
6330 dlsym(adev->adm_lib, "adm_request_focus");
6331 adev->adm_abandon_focus = (adm_abandon_focus_t)
6332 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08006333 adev->adm_set_config = (adm_set_config_t)
6334 dlsym(adev->adm_lib, "adm_set_config");
6335 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6336 dlsym(adev->adm_lib, "adm_request_focus_v2");
6337 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6338 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6339 adev->adm_on_routing_change = (adm_on_routing_change_t)
6340 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006341 }
6342
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006343 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05006344 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006345
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006346 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006347
Andy Hung31aca912014-03-20 17:14:59 -07006348 if (k_enable_extended_precision)
6349 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006350
Glenn Kasten4f993392014-05-14 07:30:48 -07006351 char value[PROPERTY_VALUE_MAX];
6352 int trial;
6353 if (property_get("audio_hal.period_size", value, NULL) > 0) {
6354 trial = atoi(value);
6355 if (period_size_is_plausible_for_low_latency(trial)) {
6356 pcm_config_low_latency.period_size = trial;
6357 pcm_config_low_latency.start_threshold = trial / 4;
6358 pcm_config_low_latency.avail_min = trial / 4;
6359 configured_low_latency_capture_period_size = trial;
6360 }
6361 }
6362 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
6363 trial = atoi(value);
6364 if (period_size_is_plausible_for_low_latency(trial)) {
6365 configured_low_latency_capture_period_size = trial;
6366 }
6367 }
6368
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07006369 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
6370
Eric Laurent5f4ca952018-10-19 17:33:43 -07006371 adev->camera_orientation = CAMERA_DEFAULT;
6372
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006373 // commented as full set of app type cfg is sent from platform
6374 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006375 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08006376
6377 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
6378 af_period_multiplier = atoi(value);
6379 if (af_period_multiplier < 0) {
6380 af_period_multiplier = 2;
6381 } else if (af_period_multiplier > 4) {
6382 af_period_multiplier = 4;
6383 }
6384 ALOGV("new period_multiplier = %d", af_period_multiplier);
6385 }
6386
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006387 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08006388 audio_extn_ma_init(adev->platform);
justinwengc6347db2019-02-21 18:49:00 +08006389 audio_extn_audiozoom_init();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006390
vivek mehta1a9b7c02015-06-25 11:49:38 -07006391 pthread_mutex_unlock(&adev_init_lock);
6392
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006393 if (adev->adm_init)
6394 adev->adm_data = adev->adm_init();
6395
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006396 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006397 audio_extn_snd_mon_init();
6398 pthread_mutex_lock(&adev->lock);
6399 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
6400 adev->card_status = CARD_STATUS_ONLINE;
6401 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006402 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006403
Eric Laurent2bafff12016-03-17 12:17:23 -07006404 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006405 return 0;
6406}
6407
6408static struct hw_module_methods_t hal_module_methods = {
6409 .open = adev_open,
6410};
6411
6412struct audio_module HAL_MODULE_INFO_SYM = {
6413 .common = {
6414 .tag = HARDWARE_MODULE_TAG,
6415 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6416 .hal_api_version = HARDWARE_HAL_API_VERSION,
6417 .id = AUDIO_HARDWARE_MODULE_ID,
6418 .name = "QCOM Audio HAL",
6419 .author = "Code Aurora Forum",
6420 .methods = &hal_module_methods,
6421 },
6422};